add jigsaw-rpc-order

This commit is contained in:
李雄峰
2017-08-15 17:57:38 +08:00
parent 07a246cd13
commit 611f10a6cc
18 changed files with 766 additions and 0 deletions
+29
View File
@@ -0,0 +1,29 @@
## 1.0.6 2017-07-19
### Added
- 增加关闭订单服务
### Updated
- 修正同步到ES的过期时间转换
## 1.0.5 2017-06-29
### Updated
- 如果时账户消费 创建订单就进行账户消费
- 支持奇豆消费时同步旧库中奇豆数据
- 账户消费不再记录交易流水
## 1.0.3 2017-05-08
### Updated
- supported consuming qidian
- supported CreateTrade/PreparePay/FinishPay
## 1.0.3 2017-05-08
### Updated
- switch branch kepler
## 1.0.3 2017-04-26
### Added
- support sync extra_params to elastic
## 1.0.1 2017-03-10
### Added
- initial release
+1
View File
@@ -0,0 +1 @@
基于分库分表的支付流水基础服务
+97
View File
@@ -0,0 +1,97 @@
/*
Navicat MySQL Data Transfer
Source Server : jigsaw-payment
Source Server Version : 50719
Source Host : localhost:3306
Source Database : jigsaw-payment
Target Server Type : MYSQL
Target Server Version : 50719
File Encoding : 65001
Date: 2017-08-10 19:19:42
*/
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for pay_order_0
-- ----------------------------
DROP TABLE IF EXISTS `pay_order_0`;
CREATE TABLE `pay_order_0` (
`id` bigint(20) NOT NULL COMMENT '自增ID,兼容遗留数据',
`code` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '交易流水号',
`version` bigint(20) NOT NULL DEFAULT '0',
`app_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '发起交易的app id',
`pay_scenarios` int(4) NOT NULL COMMENT '发起交易的场景,包括api, 通用收银台,充值收银台,扫码支付等',
`notify_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '异步通知url',
`return_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '同步通知url',
`status` int(9) NOT NULL COMMENT '订单状态 1:已支付;2:未支付;3:等待中;4:退单;5:短信支付扣费成功;6:冻结;7:关闭',
`create_time` datetime NOT NULL,
`update_time` datetime NOT NULL,
`expire_time` datetime NOT NULL COMMENT '过期时间',
`pay_time` datetime NOT NULL COMMENT '支付时间',
`error_code` varchar(32) NOT NULL COMMENT '如果支付失败,这里需记录错误码',
`error_detail` varchar(128) NOT NULL COMMENT '详细错误信息,如果支付失败,需要在这里记录错误信息',
`partner_order_no` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '接入方订单号',
`pay_mode` tinyint(10) NOT NULL COMMENT '0.正常订单,1.代表测试订单',
`order_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '订单ID,记录用户购买的产品信息(需使用产品查询接口)',
`order_title` varchar(62) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '订单名称',
`order_detail` varchar(128) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '订单描述',
`order_show_url` varchar(256) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '订单显示的url地址',
`fee` int(9) NOT NULL COMMENT '预期金额',
`fee_real` int(9) NOT NULL COMMENT '实际支付总金额',
`fee_unit` tinyint(2) NOT NULL DEFAULT '1' COMMENT '货币类型 ',
`sub_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '交易主体不仅仅是用户,也可以是商户',
`sub_type` int(9) NOT NULL COMMENT '交易主体类型',
`sub_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '交易主体名称',
`sub_account_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '交易主体账号',
`sub_account_type` int(10) NOT NULL COMMENT '交易主体使用的账号类型;银行卡、钱包、奇点、奇豆等',
`sub_ip` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '交易主体ip地址',
`sub_mobile` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '交易主体使用的手机号',
`sub_client_code` varchar(16) NOT NULL COMMENT '交易主体的客户端代码,发起交易的平台代码,参考公司标准代码规范',
`sub_device_id` varchar(32) NOT NULL COMMENT '交易主体使用的设备',
`sub_email` varchar(128) NOT NULL COMMENT '交易主体的邮箱【预留】',
`sub_location` varchar(128) NOT NULL COMMENT '交易主体在交易发生时所在的位置【预留】',
`sub_country_code` varchar(128) NOT NULL COMMENT '交易主体所在的国家代码,默认为中国【预留】',
`partner_id` int(9) NOT NULL COMMENT '交易对手的Id,接入方ID',
`partner_type` int(9) NOT NULL COMMENT '交易对手的类型',
`partner_account_id` int(9) NOT NULL COMMENT '交易对手的账号,商户号pay_service_account的ID',
`partner_name` varchar(32) NOT NULL COMMENT '交易对手的名称',
`source_pay_type` int(9) NOT NULL COMMENT '用户选择的交易渠道实体编码',
`dest_pay_type` int(9) NOT NULL COMMENT '实际执行的交易渠道虚拟账户编码',
`third_create_time` datetime NOT NULL COMMENT '第三方创建时间',
`third_pay_time` datetime NOT NULL COMMENT '第三方创建时间',
`third_trade_code` varchar(256) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '第三方交易订单号',
`current_key` int(9) NOT NULL,
PRIMARY KEY (`code`),
KEY `idx_pay_uid_time` (`sub_id`,`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `pay_order_1`;
CREATE TABLE `pay_order_1` like `pay_order_0` ;
DROP TABLE IF EXISTS `pay_order_2`;
CREATE TABLE `pay_order_2` like `pay_order_0` ;
DROP TABLE IF EXISTS `pay_order_3`;
CREATE TABLE `pay_order_3` like `pay_order_0` ;
DROP TABLE IF EXISTS `pay_order_4`;
CREATE TABLE `pay_order_4` like `pay_order_0` ;
DROP TABLE IF EXISTS `pay_order_5`;
CREATE TABLE `pay_order_5` like `pay_order_0` ;
DROP TABLE IF EXISTS `pay_order_6`;
CREATE TABLE `pay_order_6` like `pay_order_0` ;
DROP TABLE IF EXISTS `pay_order_7`;
CREATE TABLE `pay_order_7` like `pay_order_0` ;
DROP TABLE IF EXISTS `pay_order_8`;
CREATE TABLE `pay_order_8` like `pay_order_0` ;
DROP TABLE IF EXISTS `pay_order_9`;
CREATE TABLE `pay_order_9` like `pay_order_0` ;
@@ -0,0 +1,35 @@
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">
<id>package</id>
<formats>
<format>tar.gz</format>
</formats>
<baseDirectory>${project.artifactId}</baseDirectory>
<fileSets>
<fileSet>
<directory>src/conf</directory>
<includes>
<include>*.*</include>
</includes>
<outputDirectory>conf</outputDirectory>
<fileMode>0644</fileMode>
<directoryMode>0755</directoryMode>
</fileSet>
<fileSet>
<directory>target/lib</directory>
<outputDirectory>lib</outputDirectory>
<fileMode>0644</fileMode>
<directoryMode>0755</directoryMode>
</fileSet>
</fileSets>
<files>
<file>
<source>target/${project.artifactId}-${project.version}.${project.packaging}</source>
<outputDirectory>lib</outputDirectory>
<fileMode>0644</fileMode>
</file>
</files>
</assembly>
@@ -0,0 +1,26 @@
package org.jigsaw.payment.order;
import org.jigsaw.payment.model.PayOrder;
import org.jigsaw.payment.mysql.JdbcProtobufTemplate;
/**
* @author shamphone@gmail.com
* @version 1.0.0
* @date 2017年8月10日
*/
public interface JdbcSharder {
/**
* 根据Uid获取JdbcTemplate
* @param uid
* @return
*/
public JdbcProtobufTemplate<Long, PayOrder> getTemplateByUserId(long uid);
/**
* 获取对应的表名
* @param uid
* @return
*/
public String getTableByUserId(long uid);
}
@@ -0,0 +1,27 @@
/**
*
*/
package org.jigsaw.payment.order;
import org.jigsaw.payment.model.PayOrder;
/**
* @author shamphone@gmail.com
* @version 1.0.0
* @date 2017年8月9日
*/
public interface PayOrderRepository {
/**
* 根据交易主体和订单号获取给定的订单
* @param subId 交易主体的ID
* @param code 订单号
* @return 符合条件的订单,如果没有找到,返回空。
*/
public PayOrder get(long subId, String code);
/**
* 创建订单
* @param order 带插入的订单
* @return 订单ID。
*/
public long create(PayOrder order) ;
}
@@ -0,0 +1,73 @@
package org.jigsaw.payment.order.mysql;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.sql.DataSource;
import org.jigsaw.payment.model.PayOrder;
import org.jigsaw.payment.mysql.JdbcProtobufTemplate;
import org.jigsaw.payment.order.JdbcSharder;
import org.springframework.jdbc.core.JdbcTemplate;
/**
* 增加表可以减少锁的争用,增加库可以增加并发性能。
* 按照这个原则,分表分库按照用户id(长整形)来进行,uid最后一位用来做分表。分库按照2、4、8的级数来扩展: 表号是: uid对10取模,即最后一位;
* 库号是: uid/10 后, 按照库的数量来取模。 加库时,先将表数据同步到1个从库,同步完成后,从库升级为主库即可。 表里有冗余数据,但是不会丢数据。
*
* @author shamphone@gmail.com
* @version 1.0.0
* @date 2017年8月10日
*/
public class MySQLJdbcSharder implements JdbcSharder {
private List<JdbcProtobufTemplate<Long, PayOrder>> templates;
private int tableCount = 10;
private int databaseCount = 2;
private String tableNamePattern = "pay_order_%01d";
/**
* 初始化template列表;
*
* @param dataSourceList
*/
public void setDataSourceList(List<DataSource> dataSourceList) {
this.templates = Collections
.synchronizedList(new ArrayList<JdbcProtobufTemplate<Long, PayOrder>>(
dataSourceList.size()));
for (DataSource dataSource : dataSourceList) {
JdbcTemplate template = new JdbcTemplate(dataSource);
JdbcProtobufTemplate<Long, PayOrder> wrapper = new JdbcProtobufTemplate<Long, PayOrder>(
template, PayOrder.class);
this.templates.add(wrapper);
}
if (this.templates.size() != this.databaseCount)
throw new IllegalArgumentException(
"please check your database configuration, it should have "
+ databaseCount + " count.");
}
public void setTableCount(int tableCount) {
this.tableCount = tableCount;
}
public void setDatabaseCount(int databaseCount) {
this.databaseCount = databaseCount;
}
public void setTableNamePattern(String tableNamePattern) {
this.tableNamePattern = tableNamePattern;
}
@Override
public JdbcProtobufTemplate<Long, PayOrder> getTemplateByUserId(long uid) {
return this.templates.get((int) (uid / tableCount % databaseCount));
}
@Override
public String getTableByUserId(long uid) {
return String.format(tableNamePattern, uid % this.tableCount);
}
}
@@ -0,0 +1,65 @@
package org.jigsaw.payment.order.mysql;
import java.text.MessageFormat;
import org.jigsaw.payment.metric.Timer;
import org.jigsaw.payment.model.IllegalParameterException;
import org.jigsaw.payment.model.PayOrder;
import org.jigsaw.payment.model.StatusCode;
import org.jigsaw.payment.mysql.JdbcProtobufTemplate;
import org.jigsaw.payment.order.JdbcSharder;
import org.jigsaw.payment.order.PayOrderRepository;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 支持分表分库的MySQL订单管理
*
* @author shamphone@gmail.com
* @version 1.0.0
* @date 2017年8月9日
*/
public class MySQLShardingPayOrderRepository implements PayOrderRepository {
private JdbcSharder sharder;
@Autowired
public MySQLShardingPayOrderRepository(JdbcSharder sharder) {
this.sharder = sharder;
}
private static final String SQL_GET_PAY_ORDER = "select * from {0} where sub_id=? AND code = ?";
@Override
@Timer("get-order")
public PayOrder get(long subId, String code) {
JdbcProtobufTemplate<Long, PayOrder> template = this.sharder.getTemplateByUserId(subId);
String tableName = this.sharder.getTableByUserId(subId);
String sql = MessageFormat.format(SQL_GET_PAY_ORDER, tableName);
return template.get(sql, subId, code);
}
/**
*验证数据有效性
* @param order
*/
private void validate(PayOrder order){
if(!order.hasSubId())
throw new IllegalParameterException(StatusCode.DATA_REQUIRED_VALUE, "error.pay.order.require.sub_id");
if(!order.hasCode())
throw new IllegalParameterException(StatusCode.DATA_REQUIRED_VALUE, "error.pay.order.require.code");
if(!order.hasCreateTime())
throw new IllegalParameterException(StatusCode.DATA_REQUIRED_VALUE, "error.pay.order.require.create_time");
}
@Override
@Timer("create-order")
public long create(PayOrder order) {
this.validate(order);
String tableName = this.sharder.getTableByUserId(order.getSubId());
this.sharder.getTemplateByUserId(order.getSubId()).insert(order, tableName);
return order.getId();
}
}
@@ -0,0 +1,25 @@
package org.jigsaw.payment.order.rpc;
import org.jigsaw.payment.rpc.PayOrderService.GetPayOrderRequest;
import org.jigsaw.payment.rpc.PayOrderService.GetPayOrderResponse;
import org.jigsaw.payment.rpc.server.BaseController;
import org.springframework.stereotype.Service;
/**
*
* @author shamphone@gmail.com
* @version 1.0.0
* @date 2017年8月9日
*/
@Service("getPayOrder")
public class GetTradeController extends
BaseController<GetPayOrderRequest, GetPayOrderResponse> {
@Override
protected GetPayOrderResponse doProcess(GetPayOrderRequest request)
throws Exception {
return null;
}
}
@@ -0,0 +1,23 @@
package org.jigsaw.payment.order.rpc;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* shard server
*/
@SpringBootApplication
public class Server{
/**
* main function
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
SpringApplication.run(Server.class, args);
}
}
@@ -0,0 +1,11 @@
#rpc settings
#min worker thread count;
rpc.server.min.worker.threads=50
#max worker threads count;
rpc.server.max.worker.threads=500
rpc.server.zookeeper.connect.string=localhost:2181
rpc.server.zookeeper.username= payment
rpc.server.zookeeper.password= 123456
rpc.server.service.path=/payment/rpc
@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<beans profile="dev">
<bean id="dataSourceParent" abstract="true"
class="org.apache.tomcat.jdbc.pool.DataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />
<property name="testWhileIdle" value="true" />
<property name="testOnBorrow" value="true" />
<property name="testOnReturn" value="false" />
<property name="validationQuery" value="SELECT 1" />
<property name="validationInterval" value="30000" />
<property name="timeBetweenEvictionRunsMillis" value="30000" />
<property name="maxActive" value="100" />
<property name="minIdle" value="2" />
<property name="maxWait" value="10000" />
<property name="initialSize" value="4" />
<property name="removeAbandonedTimeout" value="60" />
<property name="removeAbandoned" value="true" />
<property name="logAbandoned" value="true" />
<property name="minEvictableIdleTimeMillis" value="30000" />
<property name="jmxEnabled" value="true" />
</bean>
<bean id="jdbcSharder" class="org.jigsaw.payment.order.mysql.MySQLJdbcSharder">
<property name="tableCount" value="10"/>
<property name="databaseCount" value="2"/>
<property name="tableNamePattern" value="pay_order_%01d"/>
<property name="dataSourceList">
<list>
<bean parent="dataSourceParent" primary="true">
<property name="url"
value="jdbc:mysql://localhost:3306/jigsaw_payment_0?useUnicode=true&amp;autoReconnect=true&amp;zeroDateTimeBehavior=convertToNull&amp;serverTimezone=UTC&amp;useSSL=false" />
<property name="username" value="payment" />
<property name="password" value="123456" />
</bean>
<bean parent="dataSourceParent">
<property name="url"
value="jdbc:mysql://localhost:3306/jigsaw_payment_1?useUnicode=true&amp;autoReconnect=true&amp;zeroDateTimeBehavior=convertToNull&amp;serverTimezone=UTC&amp;useSSL=false" />
<property name="username" value="payment" />
<property name="password" value="123456" />
</bean>
</list>
</property>
</bean>
</beans>
<!-- 如果需要支持多机房(profile),可以参考上述格式定义不同的profile
<beans profile="test">
</beans>
-->
</beans>
@@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="log_path" value="d:/temp/logs/pay-service-trade-sharding"/>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%-5p] [%d{yyyy-MM-dd HH:mm:ss.SSS}] [%C{1}:%M:%L] %m%n</pattern>
</encoder>
</appender>
<appender name="ROLLING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log_path}/app.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log_path}/app.log.%d{yyyy-MM-dd_HH}</fileNamePattern>
<maxHistory>3</maxHistory>
<totalSizeCap>50GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>[%-5p] [%d{yyyy-MM-dd HH:mm:ss.SSS}] %m%n</pattern>
</encoder>
</appender>
<!--错误日志-->
<appender name="ERROR_DAILY_ROLLING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<pattern>[%-5p] [%d{yyyy-MM-dd HH:mm:ss.SSS}] [%C{1}:%M:%L] %m%n</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<file>${log_path}/error.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log_path}/error.log.%d{yyyy-MM-dd_HH}</fileNamePattern>
<maxHistory>30</maxHistory>
<totalSizeCap>50GB</totalSizeCap>
</rollingPolicy>
</appender>
<!-- 异步输出 -->
<appender name="ASYNC_ROLLING_FILE" class="ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>512</queueSize>
<!--耗费性能 默认不开启-->
<includeCallerData>false</includeCallerData>
<!-- 添加附加的appender,最多只能添加一个 -->
<appender-ref ref="ROLLING_FILE"/>
</appender>
<!-- 异步输出 -->
<appender name="ASYNC_ERROR_DAILY_ROLLING_FILE" class="ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>512</queueSize>
<!--耗费性能 默认不开启-->
<includeCallerData>false</includeCallerData>
<!-- 添加附加的appender,最多只能添加一个 -->
<appender-ref ref="ERROR_DAILY_ROLLING_FILE"/>
</appender>
<!-- project default level -->
<logger name="org.jigsaw.payment" level="DEBUG"/>
<root level="INFO">
${log.console}
<appender-ref ref="ASYNC_ROLLING_FILE"/>
<appender-ref ref="ASYNC_ERROR_DAILY_ROLLING_FILE"/>
</root>
</configuration>
@@ -0,0 +1,41 @@
/*
* Copyright 2012-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jigsaw.payment.order;
import org.jigsaw.payment.order.mysql.MySQLShardingPayOrderRepository;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
/**
* @author shamphone@gmail.com
* @version 1.0.0
* @date 2017年8月14日
*/
@Configuration()
@ImportResource("classpath:datasource.xml")
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
public class TestConfiguration {
@Bean("payOrderRepository")
public PayOrderRepository getPayOrderRepository(JdbcSharder jdbcSharder){
return new MySQLShardingPayOrderRepository(jdbcSharder);
}
}
@@ -0,0 +1,43 @@
package org.jigsaw.payment.order;
import javax.annotation.Resource;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
/**
* @author shamphone@gmail.com
* @version 1.0.0
* @date 2017年8月11日
*/
@RunWith(SpringRunner.class)
@ActiveProfiles("dev")
@SpringBootTest(classes= TestConfiguration.class, webEnvironment=WebEnvironment.NONE)
public class TestJdbcSharder {
@Resource(name = "jdbcSharder")
private JdbcSharder sharder;
/**
* 验证按照算法计算出来的ID属于同一个数据库;
*/
@Test
public void TestGetTemplateByUserIdEquals() {
Assert.assertEquals(sharder.getTemplateByUserId(1081l),sharder.getTemplateByUserId(1063l));
Assert.assertEquals(sharder.getTemplateByUserId(1081l),sharder.getTemplateByUserId(1049l));
Assert.assertNotEquals(sharder.getTemplateByUserId(1081l),sharder.getTemplateByUserId(1079l));
}
/**
* 验证按照算法计算出来的ID属于同一个表;
*/
@Test
public void TestGetTableByUserIdEquals() {
Assert.assertEquals(sharder.getTableByUserId(1081l),sharder.getTableByUserId(1061l));
Assert.assertEquals(sharder.getTableByUserId(1081l),sharder.getTableByUserId(1041l));
Assert.assertNotEquals(sharder.getTableByUserId(1081l),sharder.getTableByUserId(1079l));
}
}
@@ -0,0 +1,66 @@
/**
*
*/
package org.jigsaw.payment.order;
import java.util.Calendar;
import java.util.Date;
import java.util.UUID;
import javax.annotation.Resource;
import org.apache.commons.lang3.RandomUtils;
import org.jigsaw.payment.model.FeeUnit;
import org.jigsaw.payment.model.PayOrder;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
/**
* @author shamphone@gmail.com
* @version 1.0.0
* @date 2017年8月11日
*/
@RunWith(SpringRunner.class)
@ActiveProfiles("dev")
@SpringBootTest(classes= TestConfiguration.class, webEnvironment=WebEnvironment.NONE)
public class TestPayOrderRepository {
@Resource(name = "payOrderRepository")
private PayOrderRepository repository;
@Test
public void testCreateAndGet(){
PayOrder.Builder builder = PayOrder.newBuilder();
long uid = System.nanoTime();
String code = UUID.randomUUID().toString();
builder.setId(System.currentTimeMillis());
builder.setAppId("myapp");
builder.setCode(code);
builder.setCreateTime(new Date().getTime());
builder.setCurrentKey(19283745);
builder.setDestPayType(1982);
builder.setSubId(uid);
Calendar expireTime = Calendar.getInstance();
expireTime.add(Calendar.HOUR, 1);
builder.setExpireTime(expireTime.getTime().getTime());
int fee = RandomUtils.nextInt(1, 1000000);
builder.setFee(fee);
builder.setFeeReal(RandomUtils.nextInt(1, fee));
builder.setFeeUnit(FeeUnit.CNY_VALUE);
builder.setNotifyUrl("http://localhost/notify");
builder.setReturnUrl("http://localhost/returnUrl");
builder.setOrderDetail("OrderDetail");
builder.setOrderId(UUID.randomUUID().toString());
repository.create(builder.build());
PayOrder order = repository.get(uid, code);
Assert.assertEquals(order.getCode(), code);
}
}
@@ -0,0 +1,9 @@
#rpc settings
#min worker thread count;
rpc.server.min.worker.threads=50
#max worker threads count;
rpc.server.max.worker.threads=500
rpc.server.zookeeper.connect.string=localhost:2181
rpc.server.zookeeper.username= payment
rpc.server.zookeeper.password= 123456
rpc.server.service.path=/payment/rpc
@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--<include resource="org/springframework/boot/logging/logback/base.xml"/> -->
<!-- logger name="org.springside.samples.quickservice" level="DEBUG"/-->
<property name="log_path" value="d:/temp/logs/pay-service-trade-sharding"/>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%-5p] [%d{yyyy-MM-dd HH:mm:ss.SSS}] [%C{1}:%M:%L] %m%n</pattern>
</encoder>
</appender>
<appender name="ROLLING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log_path}/app.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log_path}/app.log.%d{yyyy-MM-dd_HH}</fileNamePattern>
</rollingPolicy>
<encoder>
<pattern>[%-5p] [%d{yyyy-MM-dd HH:mm:ss}] [%C{1}:%M:%L] %m%n</pattern>
</encoder>
</appender>
<!--错误日志-->
<appender name="ERROR_DAILY_ROLLING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<pattern>[%-5p] [%d{yyyy-MM-dd HH:mm:ss}] [%C{1}:%M:%L] %m%n</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<file>${log_path}/error.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log_path}/error.log.%d{yyyy-MM-dd_HH}</fileNamePattern>
<maxHistory>30</maxHistory>
<totalSizeCap>80GB</totalSizeCap>
</rollingPolicy>
</appender>
<!-- 异步输出 -->
<appender name="ASYNC_ROLLING_FILE" class="ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>512</queueSize>
<!--耗费性能 默认不开启-->
<includeCallerData>true</includeCallerData>
<!-- 添加附加的appender,最多只能添加一个 -->
<appender-ref ref="ROLLING_FILE"/>
</appender>
<!-- 异步输出 -->
<appender name="ASYNC_ERROR_DAILY_ROLLING_FILE" class="ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>512</queueSize>
<!--耗费性能 默认不开启-->
<includeCallerData>true</includeCallerData>
<!-- 添加附加的appender,最多只能添加一个 -->
<appender-ref ref="ERROR_DAILY_ROLLING_FILE"/>
</appender>
<!-- project default level -->
<logger name="org.jigsaw.payment" level="DEBUG"/>
<!--这些包中继承spring里面某些类,不需要输出debug日志-->
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="ASYNC_ROLLING_FILE"/>
<appender-ref ref="ASYNC_ERROR_DAILY_ROLLING_FILE"/>
</root>
</configuration>