add jigsaw-rpc-order
This commit is contained in:
@@ -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
|
||||
@@ -0,0 +1 @@
|
||||
基于分库分表的支付流水基础服务
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
+65
@@ -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&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&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&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&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>
|
||||
Reference in New Issue
Block a user