记得上下班打卡 | git大法好,push需谨慎

Commit f6769c31 authored by 胡佳晨's avatar 胡佳晨

Merge branch 'dev-dragon&order' into dev_bd_rm_consumer_od

parents 87b94f77 cf943826
......@@ -27,6 +27,11 @@
<artifactId>easyexcel</artifactId>
<version>3.0.5</version>
</dependency>
<dependency>
<groupId>com.liquidnet</groupId>
<artifactId>liquidnet-service-dragon-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package com.liquidnet.service.goblin.param;
import com.liquidnet.service.dragon.dto.DragonPayOrderQueryRespDto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
......@@ -46,4 +47,18 @@ public class GoblinNftOrderPayCallbackParam implements Cloneable {
return new GoblinNftOrderPayCallbackParam();
}
}
public GoblinNftOrderPayCallbackParam copy(DragonPayOrderQueryRespDto source) {
if (null == source) return this;
this.setStatus(source.getStatus());
// this.setOrderId(source.getOrderCodeId());
this.setOrderCode(source.getOrderCode());
this.setCode(source.getCode());
this.setPrice(source.getPrice());
this.setType(source.getType());
this.setPaymentId(source.getPaymentId());
this.setPaymentType(source.getPaymentType());
this.setPaymentAt(source.getPaymentAt());
return this;
}
}
......@@ -86,8 +86,8 @@ liquidnet:
service:
adam:
url-pay:
pay: http://devdragon.zhengzai.tv/dragon/pay/dragonPay
check: http://devdragon.zhengzai.tv/dragon/pay/checkOrder
pay: http://devorder.zhengzai.tv/order/pay/dragonPay
check: http://devorder.zhengzai.tv/order/pay/checkOrder
callback: http://devadam.zhengzai.tv/adam/member/order/callback
url: http://devadam.zhengzai.tv
kylin:
......@@ -108,18 +108,18 @@ liquidnet:
url: http://devorder.zhengzai.tv
url-pay:
pay: http://devdragon.zhengzai.tv/dragon/pay/dragonPay
applePay: http://devdragon.zhengzai.tv/dragon/notify/apple/purchase
# applePay: http://devorder.zhengzai.tv/order/notify/apple/purchase
check: http://devdragon.zhengzai.tv/dragon/pay/checkOrder
localUrl: http://devorder.zhengzai.tv/order/order/syncOrder
goblinUrl: http://devgoblin.zhengzai.tv/goblin/order/pay/syncOrder
goblinRefundUrl: http://devgoblin.zhengzai.tv/goblin/order/pay/refundSyncOrder
goblinUrl: http://devorder.zhengzai.tv/goblin/order/pay/syncOrder
goblinRefundUrl: http://devorder.zhengzai.tv/goblin/order/pay/refundSyncOrder
nftPayNotify: https://devorder.zhengzai.tv/order/goblin/nft/syncOrder
nftRefundNotify: https://devorder.zhengzai.tv/order/goblin/nft/refundSyncOrder
dragon:
notifyUrl: https://devdragon.zhengzai.tv/dragon
notifyUrl: https://devorder.zhengzai.tv/order
urls:
refundApply: https://devdragon.zhengzai.tv/dragon/refund/refundSingle
refundResult: https://devdragon.zhengzai.tv/dragon/refund/refund/alipay/result
refundApply: https://devorder.zhengzai.tv/order/refund/refundSingle
refundResult: https://devorder.zhengzai.tv/order/refund/refund/alipay/result
platform:
urls:
ticketRefundNotify: https://devplatform.zhengzai.tv/platform/refund/callback
......
......@@ -86,14 +86,14 @@ liquidnet:
service:
adam:
url-pay:
pay: http://testdragon.zhengzai.tv/dragon/pay/dragonPay
check: http://testdragon.zhengzai.tv/dragon/pay/checkOrder
pay: http://testorder.zhengzai.tv/order/pay/dragonPay
check: http://testorder.zhengzai.tv/order/pay/checkOrder
callback: http://testadam.zhengzai.tv/adam/member/order/callback
url: http://testadam.zhengzai.tv
kylin:
url-pay:
pay: http://testdragon.zhengzai.tv/dragon/pay/dragonPay
check: http://testdragon.zhengzai.tv/dragon/pay/checkOrder
pay: http://testorder.zhengzai.tv/order/pay/dragonPay
check: http://testorder.zhengzai.tv/order/pay/checkOrder
localUrl: http://testkylin.zhengzai.tv/kylin/order/syncOrder
url: http://testkylin.zhengzai.tv/kylin
candy:
......@@ -107,19 +107,19 @@ liquidnet:
order:
url: http://testorder.zhengzai.tv
url-pay:
pay: http://testdragon.zhengzai.tv/dragon/pay/dragonPay
applePay: http://testdragon.zhengzai.tv/dragon/notify/apple/purchase
check: http://testdragon.zhengzai.tv/dragon/pay/checkOrder
pay: http://testorder.zhengzai.tv/order/pay/dragonPay
# applePay: http://testorder.zhengzai.tv/order/notify/apple/purchase
check: http://testorder.zhengzai.tv/order/pay/checkOrder
localUrl: http://testorder.zhengzai.tv/order/order/syncOrder
goblinUrl: http://testorder.zhengzai.tv/order/goblin/syncOrder
goblinRefundUrl: http://testorder.zhengzai.tv/order/goblin/refundSyncOrder
nftPayNotify: https://testorder.zhengzai.tv/order/goblin/nft/syncOrder
nftRefundNotify: https://testorder.zhengzai.tv/order/goblin/nft/refundSyncOrder
dragon:
notifyUrl: https://testdragon.zhengzai.tv/dragon
notifyUrl: https://testorder.zhengzai.tv/order
urls:
refundApply: https://testdragon.zhengzai.tv/dragon/refund/refundSingle
refundResult: https://testdragon.zhengzai.tv/dragon/refund/refund/alipay/result
refundApply: https://testorder.zhengzai.tv/order/refund/refundSingle
refundResult: https://testorder.zhengzai.tv/order/refund/refund/alipay/result
platform:
urls:
ticketRefundNotify: https://testplatform.zhengzai.tv/platform/refund/callback
......
......@@ -24,3 +24,26 @@ liquidnet:
url: ${liquidnet.service.adam.url}
candy:
url: ${liquidnet.service.candy.url}
dragon:
url: ${liquidnet.service.dragon.notifyUrl}
alipay:
gataway-url: https://openapi.alipay.com/gateway.do
appId: 2019082866535131
merchantPubKey: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmePaETscydypY3rV4mXa8MtcQIL5zjP1KxdusNkHpePeU61hAZxKn0Z8pDB1wNaTK72wgEWaORXeRp4YTbf4usHlW562Pe5wdiSutb3iT6EMJ5eBD4HLI9wWDgYBtwfHwS5JJFhf0eptP4R1XluLiMhmMynLwJvHepgkVrS3mN+jmoPRmKFhZHGIYDoWypBMbUKiFHWiToHK1n0NYHHIi4WgK2wt4Wj7nexQGD69W7ofRCirYmz35c/cNFUA1lqzOEKu2z7PpjA6jQV2GJolnJ4xXPJ8Dpgp4g/dgsGqRydlmFqZD71i/pDDpF0RfRKHL+WhWVhI1hqe6jLtvJE+zQIDAQAB
merchantPrivateKey: MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCArhnBTpcAww8wSYBTwGp6oBvenzCCYFrugERgxJDZ7YnBZ3ZdiAaHjJ9PI0WymkpDr27FSg9czVbiH7G91zPq+8s9onrZi/l6cBZ2VjrwQ9BQPN2a8zHy8D6BfoKEV+PIicGz6hNPA7lgf04NgsXeWjeXnYD/IBTLZmnCxB2sPYo/0EN32mlSG9snO63HlPkoqn8ycw71a1cBrlQ+Y22fFnJAk/vrGoou8E0UHfL5zVE/up+ToOYW/eOKMFL/DSceCy32t9Za0RmpV3i2E9s8gBDewzT10Yf4+4mPUiTR6AhcLjqafAy2IaKPK57WZ6cGF9cGs9yq8bSTRpeNC4alAgMBAAECggEAH0Ms+qvPP94j6IVS6gYLWHNhkfp23JXwQZVkB2Z6EpgFKbmrJhoQDAp8Acv9+OBHPp52ePP/O3qfqxwsIIUSFfrKa9T3p7a8C6UDsAhPFWRETdobtLN05SK87NUBfImly2i8aKtruXycIveKzPmCfPzKGMmpN1Jh+vCMrUbcNqX8OUcxmhGvJwnQuBW4QEiepzl89Nl91iSwFmxaZoqLaB9lYUKke/z7FDHTpTWpZvtvxlZ0gvMVNLVp9NBNazolQ8eEjBG2PsQGD2cLUbM33mLTz+/VQjzZR3KXu5kQR9MloURILDsdxE1AyA4AkIXd4eMszEjA4Dv6CQK/jjrsgQKBgQDIiCt1OGmV2sqDBSn4nZNH7BzY3Hdnf+qsYUi+TXKhnQaT8XPKWZpKE/AcqsIKnANmO4sX0NL7ACBe7Rl1RcU9Mq5XuHhnkveFBVRRIHindzUfEN0WgdLy23qmJ2N+1i4FigelY0E5T2lojVb7wycAgAc6vflwE+eYf8W3968q0QKBgQCkRgsVCWWNMSLZeB0V9LV3Om2/UPWY/ovadTxAQtxg0Z75V6Wdu8u0hrYaPSeUK2ryaoE6HKgp7U8NiJGzgm2wpj7D2ysrPmhX5+CjiWkDMCuvWytVT7hLqhhLp7frZT39u8VhyfC8lE0xA67gAPsGSl1sBoZPwvvsmNAQ/h6rlQKBgQCtCtw9be2m88M3JnieYhOax8Po2u5qsLZoBBcKqLhXf7ISbhPWNFXwwJ29jxicoR5J1O3lIj09fVFxuLX0Pb3DXn2VksjLz8Wp0vx8eUHEeRis8xdleaf4C68du/WemOHjw8VvUWQSOVWjc/vwiumYA+K5LQAXWAXM0c1jP+e3UQKBgEWY/1z8TDATn0Yvo3MH6FIJSTIDJOqa/bmibdJ0AVZruUS+o4Y+aEGlyUU4n6og8wCdqv5p4b1Rs2pyb/hzy/FJndHw60s495A2x2/B6eHV6Mw0fhl42wYDnKOA/WUX0bnMcgXKPtpGoqWff9mb0L6LhyUbZpAodf95hr2MTIY5AoGBAIyPtYP6jRyR980h/Ud1MS0fBxymjQrR+kg3GWjnw0ZJJ8yFEXxDqLV8uLyXQKc89HGbI0cClWgZBTjfIPJ5U4Gl19Xlwx1SFrdgg5mGUqnMARTg7w1TG5QLSqNhZo2jgBM5FCJRbDUCO/MzLcFhTeGNva9yP7E7gW5/Dott9D7d
signtType: 2019082866535131
charset: 2019082866535131
wepay:
gataway-url: https://openapi.alipay.com/gateway.do
merchantId: 1551961491
appId: wx3498304dda39c5a1
partnerKey: itIuO65O9yKmemOu3S8g1S4orqvCGwXK
unionpay:
merchantId: 821690048160PQY
gateway-url: https://gateway.95516.com
refund-url: https://gateway.95516.com/
certs-path: /data/certs/dragon/unionpay/test
certs-prefix: acp_test
pfx-pwd: '520360'
apple:
urlVerify: https://sandbox.itunes.apple.com/verifyReceipt
\ No newline at end of file
......@@ -24,3 +24,26 @@ liquidnet:
url: ${liquidnet.service.adam.url}
candy:
url: ${liquidnet.service.candy.url}
dragon:
url: ${liquidnet.service.dragon.notifyUrl}
alipay:
gataway-url: https://openapi.alipay.com/gateway.do
appId: 2019082866535131
merchantPubKey: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmePaETscydypY3rV4mXa8MtcQIL5zjP1KxdusNkHpePeU61hAZxKn0Z8pDB1wNaTK72wgEWaORXeRp4YTbf4usHlW562Pe5wdiSutb3iT6EMJ5eBD4HLI9wWDgYBtwfHwS5JJFhf0eptP4R1XluLiMhmMynLwJvHepgkVrS3mN+jmoPRmKFhZHGIYDoWypBMbUKiFHWiToHK1n0NYHHIi4WgK2wt4Wj7nexQGD69W7ofRCirYmz35c/cNFUA1lqzOEKu2z7PpjA6jQV2GJolnJ4xXPJ8Dpgp4g/dgsGqRydlmFqZD71i/pDDpF0RfRKHL+WhWVhI1hqe6jLtvJE+zQIDAQAB
merchantPrivateKey: MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCArhnBTpcAww8wSYBTwGp6oBvenzCCYFrugERgxJDZ7YnBZ3ZdiAaHjJ9PI0WymkpDr27FSg9czVbiH7G91zPq+8s9onrZi/l6cBZ2VjrwQ9BQPN2a8zHy8D6BfoKEV+PIicGz6hNPA7lgf04NgsXeWjeXnYD/IBTLZmnCxB2sPYo/0EN32mlSG9snO63HlPkoqn8ycw71a1cBrlQ+Y22fFnJAk/vrGoou8E0UHfL5zVE/up+ToOYW/eOKMFL/DSceCy32t9Za0RmpV3i2E9s8gBDewzT10Yf4+4mPUiTR6AhcLjqafAy2IaKPK57WZ6cGF9cGs9yq8bSTRpeNC4alAgMBAAECggEAH0Ms+qvPP94j6IVS6gYLWHNhkfp23JXwQZVkB2Z6EpgFKbmrJhoQDAp8Acv9+OBHPp52ePP/O3qfqxwsIIUSFfrKa9T3p7a8C6UDsAhPFWRETdobtLN05SK87NUBfImly2i8aKtruXycIveKzPmCfPzKGMmpN1Jh+vCMrUbcNqX8OUcxmhGvJwnQuBW4QEiepzl89Nl91iSwFmxaZoqLaB9lYUKke/z7FDHTpTWpZvtvxlZ0gvMVNLVp9NBNazolQ8eEjBG2PsQGD2cLUbM33mLTz+/VQjzZR3KXu5kQR9MloURILDsdxE1AyA4AkIXd4eMszEjA4Dv6CQK/jjrsgQKBgQDIiCt1OGmV2sqDBSn4nZNH7BzY3Hdnf+qsYUi+TXKhnQaT8XPKWZpKE/AcqsIKnANmO4sX0NL7ACBe7Rl1RcU9Mq5XuHhnkveFBVRRIHindzUfEN0WgdLy23qmJ2N+1i4FigelY0E5T2lojVb7wycAgAc6vflwE+eYf8W3968q0QKBgQCkRgsVCWWNMSLZeB0V9LV3Om2/UPWY/ovadTxAQtxg0Z75V6Wdu8u0hrYaPSeUK2ryaoE6HKgp7U8NiJGzgm2wpj7D2ysrPmhX5+CjiWkDMCuvWytVT7hLqhhLp7frZT39u8VhyfC8lE0xA67gAPsGSl1sBoZPwvvsmNAQ/h6rlQKBgQCtCtw9be2m88M3JnieYhOax8Po2u5qsLZoBBcKqLhXf7ISbhPWNFXwwJ29jxicoR5J1O3lIj09fVFxuLX0Pb3DXn2VksjLz8Wp0vx8eUHEeRis8xdleaf4C68du/WemOHjw8VvUWQSOVWjc/vwiumYA+K5LQAXWAXM0c1jP+e3UQKBgEWY/1z8TDATn0Yvo3MH6FIJSTIDJOqa/bmibdJ0AVZruUS+o4Y+aEGlyUU4n6og8wCdqv5p4b1Rs2pyb/hzy/FJndHw60s495A2x2/B6eHV6Mw0fhl42wYDnKOA/WUX0bnMcgXKPtpGoqWff9mb0L6LhyUbZpAodf95hr2MTIY5AoGBAIyPtYP6jRyR980h/Ud1MS0fBxymjQrR+kg3GWjnw0ZJJ8yFEXxDqLV8uLyXQKc89HGbI0cClWgZBTjfIPJ5U4Gl19Xlwx1SFrdgg5mGUqnMARTg7w1TG5QLSqNhZo2jgBM5FCJRbDUCO/MzLcFhTeGNva9yP7E7gW5/Dott9D7d
signtType: 2019082866535131
charset: 2019082866535131
wepay:
gataway-url: https://openapi.alipay.com/gateway.do
merchantId: 1551961491
appId: wx3498304dda39c5a1
partnerKey: itIuO65O9yKmemOu3S8g1S4orqvCGwXK
unionpay:
merchantId: 821690048160PQY
gateway-url: https://gateway.95516.com
refund-url: https://gateway.95516.com/
certs-path: /data/certs/dragon/unionpay/test
certs-prefix: acp_test
pfx-pwd: '520360'
apple:
urlVerify: https://sandbox.itunes.apple.com/verifyReceipt
\ No newline at end of file
......@@ -120,8 +120,58 @@ global-auth:
- ${liquidnet.info.context}/goblin/nft/airdrop
- ${liquidnet.info.context}/mix/syncOrder
- ${liquidnet.info.context}/goblin/nft/airdropInner
- ${liquidnet.info.context}/notify/**
- ${liquidnet.info.context}/refund/**
- ${liquidnet.info.context}/pay/**
# -----------------------------------------------------------
# -----------------------------------------------------------
# -----------------------------------------------------------
# ---------------------以下为银联支付--------------------------------------
##交易请求地址
acpsdk:
## 消费接口
frontTransUrl: ${liquidnet.dragon.unionpay.gateway-url}/gateway/api/frontTransReq.do
## app 消费接口
appTransUrl: ${liquidnet.dragon.unionpay.gateway-url}/gateway/api/appTransReq.do
## 交易状态查询
backTransUrl: ${liquidnet.dragon.unionpay.gateway-url}/gateway/api/backTransReq.do
## 交易状态查询:app用的路径
singleQueryUrl: ${liquidnet.dragon.unionpay.gateway-url}/gateway/api/queryTrans.do
## 退款路径 (https://gateway.95516.com/gateway/api/backTransReq.do)
refundUrl: ${liquidnet.dragon.unionpay.refund-url}/gateway/api/backTransReq.do
########################################################################
########################################################################
# 报文版本号,固定5.1.0,请勿改动
version: 5.1.0
# 签名方式,证书方式固定01,请勿改动
signMethod: '01'
# 是否验证验签证书的CN,测试环境请设置false,生产环境请设置true。非false的值默认都当true处理。
ifValidateCNName: false
# 是否验证https证书,测试环境请设置false,生产环境建议优先尝试true,不行再false。非true的值默认都当false处理。
ifValidateRemoteCert: false
#后台通知地址,填写接收银联后台通知的地址,必须外网能访问
#backUrl: http://222.222.222.222:8080/ACPSample_AppServer/backRcvResponse
#前台通知地址,填写处理银联前台通知的地址,必须外网能访问
#frontUrl: http://localhost:8080/ACPSample_AppServer/frontRcvResponse
#########################入网测试环境签名证书配置 ################################
# 多证书的情况证书路径为代码指定,可不对此块做配置。
# 签名证书路径,必须使用绝对路径,如果不想使用绝对路径,可以自行实现相对路径获取证书的方法;测试证书所有商户共用开发包中的测试签名证书,生产环境请从cfca下载得到。
# windows样例:
signCertPath: ${liquidnet.dragon.unionpay.certs-path}/${liquidnet.dragon.unionpay.certs-prefix}_sign.pfx
# 签名证书密码,测试环境固定000000,生产环境请修改为从cfca下载的正式证书的密码,正式环境证书密码位数需小于等于6位,否则上传到商户服务网站会失败
signCertPwd: ${liquidnet.dragon.unionpay.pfx-pwd}
# 签名证书类型,固定不需要修改
signCertType: PKCS12
##########################加密证书配置################################
# 敏感信息加密证书路径(商户号开通了商户对敏感信息加密的权限,需要对 卡号accNo,pin和phoneNo,cvn2,expired加密(如果这些上送的话),对敏感信息加密使用)
encryptCertPath: ${liquidnet.dragon.unionpay.certs-path}/${liquidnet.dragon.unionpay.certs-prefix}_enc.cer
##########################验签证书配置################################
# 验签中级证书路径(银联提供)
middleCertPath: ${liquidnet.dragon.unionpay.certs-path}/${liquidnet.dragon.unionpay.certs-prefix}_middle.cer
# 验签根证书路径(银联提供)
rootCertPath: ${liquidnet.dragon.unionpay.certs-path}/${liquidnet.dragon.unionpay.certs-prefix}_root.cer
apple:
urlVerify: ${liquidnet.dragon.apple.urlVerify}
\ No newline at end of file
# create database if not exists ln_scene character set utf8mb4 collate utf8mb4_unicode_ci;
# -- >>------------------------------------------------------------------------------------
# use ln_scene;
-- 支付订单表
drop TABLE if exists `dragon_orders`;
CREATE TABLE `dragon_orders`
(
`mid` bigint unsigned NOT NULL AUTO_INCREMENT,
`order_id` varchar(200) NOT NULL DEFAULT '0' COMMENT 'order_id',
`status` tinyint NOT NULL DEFAULT '0' COMMENT '订单状态',
`code` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '订单支付编号',
`type` varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '订单类型',
`price` decimal(10, 2) NOT NULL COMMENT '总价格',
`name` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '类别或名称',
`detail` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '详情或描述',
`order_code` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '调用端订单编号',
`client_ip` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '用户客户端ip地址',
`notify_url` varchar(150) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '支付完成通知回调地址',
`payment_type` varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '支付类型',
`payment_id` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '支付的订单号',
`payment_at` timestamp NULL DEFAULT NULL COMMENT '支付时间',
`finished_at` timestamp NULL DEFAULT NULL COMMENT '结束时间',
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted_at` timestamp NULL DEFAULT NULL COMMENT '删除时间',
PRIMARY KEY (`mid`),
UNIQUE KEY `orders_code_unique` (`code`),
UNIQUE KEY `orders_payment_id_unique` (`payment_id`),
KEY `orders_payment_type_index` (`payment_type`),
KEY `orders_status_index` (`status`),
KEY `orders_type_index` (`type`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8
COLLATE = utf8_unicode_ci
ROW_FORMAT = DYNAMIC COMMENT '支付订单表';
-- 支付订单日志表
drop TABLE if exists `dragon_order_logs`;
CREATE TABLE `dragon_order_logs`
(
`mid` bigint unsigned NOT NULL AUTO_INCREMENT,
`code` varchar(200) NOT NULL COMMENT 'pay编码',
`payment_type` varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '支付类型',
`content` text CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '支付通知内容',
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted_at` timestamp NULL DEFAULT NULL COMMENT '删除时间',
PRIMARY KEY (`mid`),
KEY `order_logs_order_id_index` (`order_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8
COLLATE = utf8_unicode_ci
ROW_FORMAT = DYNAMIC COMMENT '支付订单日志表';
-- 退款订单表
drop TABLE if exists `dragon_order_refunds`;
CREATE TABLE `dragon_order_refunds`
(
`mid` bigint unsigned NOT NULL AUTO_INCREMENT,
`order_refund_id` varchar(200) NOT NULL DEFAULT '0' COMMENT 'order_refund_id',
`order_id` varchar(200) NULL COMMENT '订单id',
`status` tinyint NOT NULL DEFAULT '0' COMMENT '订单退款状态',
`code` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '订单退款编号',
`order_refund_code` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '调用端订单退款编号',
`price` decimal(10, 2) NOT NULL COMMENT '退款价格',
`reason` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '退款原因',
`notify_url` varchar(150) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '退款完成通知回调地址',
`refund_type` varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '退款类型',
`refund_id` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '退款的订单号',
`refund_error` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '退款失败原因',
`refund_at` timestamp NULL DEFAULT NULL COMMENT '退款时间',
`finished_at` timestamp NULL DEFAULT NULL COMMENT '退款结束时间',
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted_at` timestamp NULL DEFAULT NULL COMMENT '删除时间',
PRIMARY KEY (`mid`),
UNIQUE KEY `order_refunds_code_unique` (`code`),
UNIQUE KEY `order_refunds_order_id_order_refund_code_unique` (`order_id`, `order_refund_code`),
KEY `order_refunds_order_id_index` (`order_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8
COLLATE = utf8_unicode_ci
ROW_FORMAT = DYNAMIC COMMENT '退款订单表';
-- 退款订单信息表
drop TABLE if exists `dragon_order_refund_logs`;
CREATE TABLE `dragon_order_refund_logs`
(
`mid` bigint unsigned NOT NULL AUTO_INCREMENT,
`order_id` varchar(200) NULL COMMENT '订单id',
`order_refund_id` varchar(200) NULL COMMENT '退款订单id',
`refund_type` varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL COMMENT '退款类型',
`content` text CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '退款通知内容',
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted_at` timestamp NULL DEFAULT NULL COMMENT '删除时间',
PRIMARY KEY (`mid`),
KEY `order_refund_logs_order_id_index` (`order_id`),
KEY `order_refund_logs_order_refund_id_index` (`order_refund_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8
COLLATE = utf8_unicode_ci
ROW_FORMAT = DYNAMIC COMMENT '退款订单信息表';
alter table dragon_orders add receipt_data text comment '苹果支付回调的code';
-- pay
XADD dragon:stream:dragon-pay * 0 0
XADD dragon:stream:dragon-pay-notify-key * 0 0
XADD dragon:stream:pay-mch-notify-key * 0 0
XADD dragon:stream:pay-mch-notify-error-key * 0 0
XGROUP CREATE dragon:stream:dragon-pay dragon-pay-group 0
XGROUP CREATE dragon:stream:dragon-pay-notify-key dragon-pay-notify-group 0
XGROUP CREATE dragon:stream:pay-mch-notify-key pay-mch-notify-group 0
XGROUP CREATE dragon:stream:pay-mch-notify-error-key pay-mch-notify-error-group 0
-- refund
XADD dragon:stream:dragon-refund * 0 0
XGROUP CREATE dragon:stream:dragon-refund dragon-refund-group 0
-- delete
XGROUP DESTROY dragon:stream:dragon-pay dragon-pay-group 0
XGROUP DESTROY dragon-pay-notify-key dragon-pay-notify-group 0
XGROUP DESTROY pay-mch-notify-key pay-mch-notify-group 0
XGROUP DESTROY pay-mch-notify-error-key pay-mch-notify-error-group 0
-- delete refund
XGROUP DESTROY dragon:stream:dragon-refund dragon-refund-group 0
-----BEGIN CERTIFICATE-----
MIIEPzCCAyegAwIBAgIFEDl2NhIwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UEBhMC
Q04xMDAuBgNVBAoTJ0NoaW5hIEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhv
cml0eTEXMBUGA1UEAxMOQ0ZDQSBURVNUIE9DQTEwHhcNMjAwOTExMDI0MzI2WhcN
MjUwOTExMDI0MzI2WjBzMQswCQYDVQQGEwJDTjESMBAGA1UEChMJQ0ZDQSBPQ0Ex
MQ0wCwYDVQQLEwRZQ0NBMRUwEwYDVQQLEwxJbmRpdmlkdWFsLTExKjAoBgNVBAMM
IVlDQ0FA5rWL6K+V5L2/55SoQDAwMDQwMDAwOlNJR05AMTCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBALUwYYpqUXZyDAu0gX5d8XkiUfFxdCan/VyLa6Cz
KH38cjX0QZIShn/O6Cw2hn2WurP/r3LdopLRzTHI0vIDJpQY/0Y135QHRFZHkAH0
omRTfAZ/atePnRF7VW766LGhR5n05h1nITDHlzCZYPSumpDPpVcJj4y30+G3A5Ou
1VVAsuLi48XtGIKwRX6gMXI+P75RwHSmPt5/pHlEPT6wUbmF0HBoF2gRBpYZwiSK
51Z52XUVEk96reolFFLu/9qyL767/v2izd5YuN9i7oSXNw1gDYcLnAuww6V6BUnK
Kq4KUG6H3Lz3WyXbEay72f12A5pnHWDjLEOwJ2SG1VVMLN8CAwEAAaOB9DCB8TAf
BgNVHSMEGDAWgBTPcJ1h6518Lrj3ywJA9wmd/jN0gDBIBgNVHSAEQTA/MD0GCGCB
HIbvKgEBMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuY2ZjYS5jb20uY24vdXMv
dXMtMTQuaHRtMDkGA1UdHwQyMDAwLqAsoCqGKGh0dHA6Ly91Y3JsLmNmY2EuY29t
LmNuL1JTQS9jcmw3NTM3Ni5jcmwwCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBSwaOVL
eW+I7Pm7C8lXu94+MTXAzjAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQw
DQYJKoZIhvcNAQEFBQADggEBADhYan/FCZWzD0BS+KvZivpp498eWRqzXjH2QkBv
IDYv2+Ntue66WxECMW7i9+RZVjyMeYbFkoxVEcg0cE/mcHOnqd1mTBpeb62NRbWR
OuquWHxcdIHJ/TjGX8+NwtpAKsn/IvTdEBz+EOOzmXuxNqNxV3Gg7Ay3YavWZzci
h9GEAQ11WKAjaNqq+XO6dDwBSVEQEkvHqf1DeqCZ9wl58I4MvUmAI7wKfnoonquu
1wCNMxnkHYS5EAk1Zb0nsprjz771+YZI6ai/I2ehn8hyUR46TYmPMn0WyaXkmEO7
ig055dazyfvMinsHmKyLa/yJvQMlZIWtsKzaNG4ikdA+ELQ=
-----END CERTIFICATE-----
\ No newline at end of file
-----BEGIN CERTIFICATE-----
MIIDzjCCAragAwIBAgIKGNDz/H99Hd/CxjANBgkqhkiG9w0BAQUFADBZMQswCQYD
VQQGEwJDTjEwMC4GA1UEChMnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24g
QXV0aG9yaXR5MRgwFgYDVQQDEw9DRkNBIFRFU1QgQ1MgQ0EwHhcNMTIwODMwMDMx
NDMzWhcNMzEwNTExMDMxNDMzWjBYMQswCQYDVQQGEwJDTjEwMC4GA1UEChMnQ2hp
bmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRcwFQYDVQQDEw5D
RkNBIFRFU1QgT0NBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALiL
J/BrdvHSbXNfLIMTwUg9tDtVjMRGXOl6aZnu9IpxjI5SMUJ4hVwgJnmbTokxs6GF
IXKsCLSm5H1jHLI22ysc/ltByEybLWj5jjJuC9+Uknbl3/Ls1RBG6MogUCqZckuo
hKrf5DmlV3C/jVLxGn3pUeanvmqVUi4TKpXxgm5QqKSPF8VtQY4qCpNcQwwZqbMr
D+IfJtfpGAeVrP+Kg6i1t65seeEnVSaLhqpRUDU0PTblOuUv3OhiKJWA3cYWxUrg
7U7SIHNJLSEUWmjy4mKty+g7Cnjzt29F9qXFb6oB2mR8yt4GHCilw1Rc5RBXY63H
eTuOwdtGE3M2p7Q++OECAwEAAaOBmDCBlTAfBgNVHSMEGDAWgBR03sWNCn0QGqpp
g1tNIc6Gm8xxODAMBgNVHRMEBTADAQH/MDgGA1UdHwQxMC8wLaAroCmGJ2h0dHA6
Ly8yMTAuNzQuNDIuMy90ZXN0cmNhL1JTQS9jcmwxLmNybDALBgNVHQ8EBAMCAQYw
HQYDVR0OBBYEFM9wnWHrnXwuuPfLAkD3CZ3+M3SAMA0GCSqGSIb3DQEBBQUAA4IB
AQC0JOazrbkk0XMxMMeBCc3lgBId1RjQLgWUZ7zaUISpPstGIrE5A9aB6Ppq0Sxl
pt2gkFhPEKUqgOFN1CzCDEbP3n4H0chqK1DOMrgTCD8ID5UW+ECTYNe35rZ+1JiF
lOPEhFL3pv6XSkiKTfDnjum8+wFwUBGlfoWK1Hcx0P2Hk1jcZZKwGTx1IAkesF83
pufhxHE2Ur7W4d4tfp+eC7XXcA91pdd+VUrAfkj9eKHcDEYZz66HvHzmt6rtJVBa
pwrtCi9pW3rcm8c/1jSnEETZIaokai0fD7260h/LkD/GrNCibSWxFj1CqyP9Y5Yv
cj6aA5LnUcJYeNkrQ3V4XvVc
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDkzCCAnugAwIBAgIKUhN+zB19hbc65jANBgkqhkiG9w0BAQUFADBZMQswCQYD
VQQGEwJDTjEwMC4GA1UEChMnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24g
QXV0aG9yaXR5MRgwFgYDVQQDEw9DRkNBIFRFU1QgQ1MgQ0EwHhcNMTIwODI5MDUw
MTI5WhcNMzIwODI5MDUwMTI5WjBZMQswCQYDVQQGEwJDTjEwMC4GA1UEChMnQ2hp
bmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRgwFgYDVQQDEw9D
RkNBIFRFU1QgQ1MgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa
rMJGruH6rOBPFxUI7T1ybydSRRtOM1xvkVjQNX0qmYir8feE6Tb0ctgtKR7a20DI
YCj9kZ5ANBQqjRcj3Soq9XH3cirqhYHJ723OKyTpS0RPQ0N6vtVt3P5JQ+ztjWHd
qIbbTOQ6O024TGTiqi6uHgMuz9/OVur81X3a5YVkK7jFeZ9o8cTcvQxD853/1sgZ
QcmR9aUSw0RXH4XFLTrn7n4QSfWKiNotlD8Ag5gS1pH9ONUb6nGkMn3gh1xfJqjm
ONMSknPXTGiNpXtqvYi8oIvByVCbUDO59IwPP1r1SYyE3P8Nr7DdQRu0KQSdXLoG
iugSR3fn+toObVAQmplDAgMBAAGjXTBbMB8GA1UdIwQYMBaAFHTexY0KfRAaqmmD
W00hzoabzHE4MAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBR0
3sWNCn0QGqppg1tNIc6Gm8xxODANBgkqhkiG9w0BAQUFAAOCAQEAM0eTkM35D4hj
RlGC63wY0h++wVPUvOrObqAVBbzEEQ7ScBienmeY8Q6lWMUTXM9ALibZklpJPcJv
3ntht7LL6ztd4wdX7E9RzZCQnRvbL9A/BU3NxWdeSpCg/OyPod5oCKP+6Uc7kApi
F9OtYNWnt3l2Zp/NiedzEQD8H4qEWQLAq+0dFo5BkfVhb/jPcktndpfPOuH1IMhP
tVcvo6jpFHw4U/nP2Jv59osIE97KJz/SPt2JAYnZOlIDqWwp9/Afvt0/MDr8y0PK
Q9c6eqIzBx7a9LpUTUl5u1jS+xSDZ/KF2lXnjwaFp7jICLWEMlBstCoogi7KwH9A
LpJP7/dj9g==
-----END CERTIFICATE-----
##############SDK配置文件(证书方式签名)################
# 说明:
# 1. 使用时请将此文件复制到src文件夹下替换原来的acp_sdk.properties。
# 2. 具体配置项请根据注释修改。
#
################################################
##########################入网测试环境交易发送地址(线上测试需要使用生产环境交易请求地址)#############################
##交易请求地址
acpsdk.frontTransUrl=https://gateway.test.95516.com/gateway/api/frontTransReq.do
acpsdk.backTransUrl=https://gateway.test.95516.com/gateway/api/backTransReq.do
acpsdk.singleQueryUrl=https://gateway.test.95516.com/gateway/api/queryTrans.do
acpsdk.batchTransUrl=https://gateway.test.95516.com/gateway/api/batchTrans.do
acpsdk.fileTransUrl=https://filedownload.test.95516.com/
acpsdk.appTransUrl=https://gateway.test.95516.com/gateway/api/appTransReq.do
acpsdk.cardTransUrl=https://gateway.test.95516.com/gateway/api/cardTransReq.do
#以下缴费产品使用,其余产品用不到
acpsdk.jfFrontTransUrl=https://gateway.test.95516.com/jiaofei/api/frontTransReq.do
acpsdk.jfBackTransUrl=https://gateway.test.95516.com/jiaofei/api/backTransReq.do
acpsdk.jfSingleQueryUrl=https://gateway.test.95516.com/jiaofei/api/queryTrans.do
acpsdk.jfCardTransUrl=https://gateway.test.95516.com/jiaofei/api/cardTransReq.do
acpsdk.jfAppTransUrl=https://gateway.test.95516.com/jiaofei/api/appTransReq.do
########################################################################
# 报文版本号,固定5.1.0,请勿改动
acpsdk.version=5.1.0
# 签名方式,证书方式固定01,请勿改动
acpsdk.signMethod=01
# 是否验证验签证书的CN,测试环境请设置false,生产环境请设置true。非false的值默认都当true处理。
acpsdk.ifValidateCNName=false
# 是否验证https证书,测试环境请设置false,生产环境建议优先尝试true,不行再false。非true的值默认都当false处理。
acpsdk.ifValidateRemoteCert=false
#后台通知地址,填写接收银联后台通知的地址,必须外网能访问
acpsdk.backUrl=http://222.222.222.222:8080/ACPSample_AppServer/backRcvResponse
#前台通知地址,填写处理银联前台通知的地址,必须外网能访问
acpsdk.frontUrl=http://localhost:8080/ACPSample_AppServer/frontRcvResponse
#########################入网测试环境签名证书配置 ################################
# 多证书的情况证书路径为代码指定,可不对此块做配置。
# 签名证书路径,必须使用绝对路径,如果不想使用绝对路径,可以自行实现相对路径获取证书的方法;测试证书所有商户共用开发包中的测试签名证书,生产环境请从cfca下载得到。
# windows样例:
acpsdk.signCert.path=D:/certs/acp_test_sign.pfx
# linux样例(注意:在linux下读取证书需要保证证书有被应用读的权限)(后续其他路径配置也同此条说明)
#acpsdk.signCert.path=/SERVICE01/usr/ac_frnas/conf/ACPtest/acp_test_sign.pfx
# 签名证书密码,测试环境固定000000,生产环境请修改为从cfca下载的正式证书的密码,正式环境证书密码位数需小于等于6位,否则上传到商户服务网站会失败
acpsdk.signCert.pwd=000000
# 签名证书类型,固定不需要修改
acpsdk.signCert.type=PKCS12
##########################加密证书配置################################
# 敏感信息加密证书路径(商户号开通了商户对敏感信息加密的权限,需要对 卡号accNo,pin和phoneNo,cvn2,expired加密(如果这些上送的话),对敏感信息加密使用)
acpsdk.encryptCert.path=d:/certs/acp_test_enc.cer
##########################验签证书配置################################
# 验签中级证书路径(银联提供)
acpsdk.middleCert.path=D:/certs/acp_test_middle.cer
# 验签根证书路径(银联提供)
acpsdk.rootCert.path=D:/certs/acp_test_root.cer
-----BEGIN CERTIFICATE-----
MIIEGjCCAwKgAwIBAgIFEgg4VmIwDQYJKoZIhvcNAQEFBQAwITELMAkGA1UEBhMC
Q04xEjAQBgNVBAoTCUNGQ0EgT0NBMTAeFw0xODExMzAwNzUxNDBaFw0yNDAxMDIw
OTA3MThaMIGFMQswCQYDVQQGEwJjbjESMBAGA1UEChMJQ0ZDQSBPQ0ExMRYwFAYD
VQQLEw1Mb2NhbCBSQSBPQ0ExMRQwEgYDVQQLEwtFbnRlcnByaXNlczE0MDIGA1UE
AxQrMDQxQFoxMjAwMDQwMDAwOlNJR05AMDAwNDAwMDA6U0lHTkAwMDAwMDAwMjCC
ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN3BsX/kyJ2BRh2IW4GyYfFs
4g5RcIEPhzGfo0IztDeqM8cfwRGqklavYHuZfFG6XPb1N/p1rXQlwyBJ6UQwgnVu
ACyWa9+Cqf664XNp+vIVx9grqor9lzrJK6jTPrd57AJNuhpFGAW0dRAjfF5ZAdpZ
56gYiWFgp2zTIXGjXoA0MHqYKBGMMYdFSZ3EkRhsJ0jyJeaBep2VmsFDtODliW0X
5T+cSgPn1+zzlHwu1svmBYxh3ZpEY3hEwR8KQwja5d5b0kUZ5eCepg9OyB8y+K6P
5VxCN8YHwVsXFYz1rpEmjGp2qObO2A+vyJaaCdtB3AeppsGLwGCIXQ/t5wyjOqEC
AwEAAaOB8zCB8DAfBgNVHSMEGDAWgBTR2+mIguXdGo9MqgCMvnzyqxv22TBIBgNV
HSAEQTA/MD0GCGCBHIbvKgEBMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuY2Zj
YS5jb20uY24vdXMvdXMtMTQuaHRtMDgGA1UdHwQxMC8wLaAroCmGJ2h0dHA6Ly9j
cmwuY2ZjYS5jb20uY24vUlNBL2NybDE3ODgwLmNybDALBgNVHQ8EBAMCA+gwHQYD
VR0OBBYEFAIndZ83GnekyNLXDbnxhC6+p4aCMB0GA1UdJQQWMBQGCCsGAQUFBwMC
BggrBgEFBQcDBDANBgkqhkiG9w0BAQUFAAOCAQEASJTBgXZUnzJ7PVv9Ro4LvVtY
G/8UOyB7d6TPnWkOGsPghVJujwiSpGmzI3wCCqWbQI23sOBuwkRFCZdK11bc01Wb
bsapui647RfG0zCAd86ggn5eoe41lZRgIVc1PN/te9JtKcdHkAS9n1PUkD64lPVn
WEMOcUXukW1emQG9WXauQ8+MVWUtQPW3mmNz2pWsrLk4jk9bppCwkY0lT6KRUXWp
1xfxXF57wOoNR11wx7WQv1zHJok4oJTrM9lQuVLCwFNr7Pmg0JeEZMF7M7fGaBDi
ecJB+qLudeVOIpFijW6AQfZaLawlT6eco5/UclK95gnCSct1/BgMOe9UMYPG+w==
-----END CERTIFICATE-----
\ No newline at end of file
-----BEGIN CERTIFICATE-----
MIIDgzCCAmugAwIBAgIFEAAAABkwDQYJKoZIhvcNAQEFBQAwIjELMAkGA1UEBhMC
Q04xEzARBgNVBAoTCkNGQ0EgQ1MgQ0EwHhcNMTEwNTIwMTc0MTI0WhcNMzEwNTE1
MTc0MTI0WjAhMQswCQYDVQQGEwJDTjESMBAGA1UEChMJQ0ZDQSBPQ0ExMIIBIjAN
BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApR8eQ7of5iMfk2hlgGC9Z0jcpiFs
f6ligck4WoLNgEiYg7jWL0jKkcxxlTt79maSEHRWHbdYCIQ0gq/xdIY6EUbIJ4Wd
J46dTHBOL+OVE93P3Qd422WiDMTkYsH3Mb2BcTKK/1B4jPNCL0eqCDmJrYgBiAo8
FZqm9zHmDNZHwRF/5NsyoqwuZBbTiU+JVZqrxZRtQY2k74H+umQXBNoxxHlsi0QQ
itqrhuLczY21Q0IsAAYkAuok1amDdTvNBNeP2c0lKs6N8tOfCDzi6Xz+VxMs7nJj
6sz5GCR1d1rRQDh59DfmxKlWVzAiSDIdAfBAbICLE0NQNAhYulwUSJS1wQIDAQAB
o4HAMIG9MB8GA1UdIwQYMBaAFFhpydXdFLMToHE8fAONA+Y9D44BMAwGA1UdEwQF
MAMBAf8wYAYDVR0fBFkwVzBVoFOgUaRPME0xCzAJBgNVBAYTAkNOMRMwEQYDVQQK
EwpDRkNBIENTIENBMQwwCgYDVQQLEwNDUkwxDDAKBgNVBAsTA1JTQTENMAsGA1UE
AxMEY3JsMTALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFNHb6YiC5d0aj0yqAIy+fPKr
G/bZMA0GCSqGSIb3DQEBBQUAA4IBAQAhsQGgMpueLi4lVn+TmU8MN7sO+T9/fg1S
KPKedwPZ4arpRC2etLtQ1YC4xK8LdZcQVC3cCJ3MXeBLPJS0fVOtMI10LIhasYyy
U1Zj3OSwPSBbHXwMiaTdphDMG3ZowZ7x/4OL/QS90+Zp8zfCxt9uPWPKS6QR81oa
nkrXhPJ13zBMhbP8ZpakhSfMqYG8z9l41ujmI92NahrFivl/qQrIVP6A+8KsS45d
0MVnkM2ggqDDi42KZ05zkpwpLdGOSfZ+V54GqfhjgtYxkd5I3vAGNad0hWPuIQ59
H2HILbGHI45vG7803rh5CsyqvaW1KUD4i2sLkgs9vI432PyPJVBi
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDHzCCAgegAwIBAgIEGCVShDANBgkqhkiG9w0BAQUFADAiMQswCQYDVQQGEwJD
TjETMBEGA1UEChMKQ0ZDQSBDUyBDQTAeFw0xMTA1MjAxNTI3MDVaFw00MTA1MTIx
NTI3MDVaMCIxCzAJBgNVBAYTAkNOMRMwEQYDVQQKEwpDRkNBIENTIENBMIIBIjAN
BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAshVScIOG1yHCTl2FSU1XHONBWXcS
tlJr79ZeOZ8GkH+YFG0U60iaveoYBb4B7gAcc/pprxHEhgVr8uRBjlOAfp9vLrRX
1dJH00j93T7DXVRchGVjD/4x3zyjKLuNekeiBcA+7ry0m3FCHGSj31Kocw4kfrUc
+BsDz4gIXJtsu617/AO4bvA+a+nBfxhwnIRNItsCLkO6qJfGIzeGMO+IYJ1s4XzL
XCsrXM4ofUj6jblh5Cqo7ZwFRa0dV5lmgOz8xBYzvn/t+8HoIlwRq7zAbw1I8IpC
VYcaE4+aPBK47hY9o9q9+JAqKbYQQwjLW4MSv4GNCKCVHQCeHD0QLoxtQwIDAQAB
o10wWzAfBgNVHSMEGDAWgBRYacnV3RSzE6BxPHwDjQPmPQ+OATAMBgNVHRMEBTAD
AQH/MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUWGnJ1d0UsxOgcTx8A40D5j0PjgEw
DQYJKoZIhvcNAQEFBQADggEBAGXTChXGscLtYcWtYF8v9OLdvzEWXclSAbyPI15S
PYVrTleGMfUWraszz9CUrypuoYiWTnhr8ldOZ5HmR1IYIcs/XFQztTruAyCbAnMQ
s2il3WqEZ1N5N5AG9PeAg/EYoLxJ9+lHpNa9fLjMK9x9IzDu6/qtkdDN6NuJgqTX
6gk8RpSl8PSaxxhmyum6t1adm5S7fj2IlbWdjHcRUQEBn5l7/MNaleGh1q7+5fc3
sLIC+udfA42SLYrDCAQGJ8UK5ec37hKSKQxT1WXJnSgP5hcYd+Jmb3AeXz7PoR7t
8TsDYnMum7OHLlLlxm+wmZ1ew+SCTlz1nwhPaDqWOIZmSXc=
-----END CERTIFICATE-----
##############SDK配置文件(证书方式签名)################
# 说明:
# 1. 使用时请将此文件复制到src文件夹下替换原来的acp_sdk.properties。
# 2. 具体配置项请根据注释修改。
#
################################################
##########################入网测试环境交易发送地址(线上测试需要使用生产环境交易请求地址)#############################
##交易请求地址
acpsdk.frontTransUrl=https://gateway.95516.com/gateway/api/frontTransReq.do
acpsdk.backTransUrl=https://gateway.95516.com/gateway/api/backTransReq.do
acpsdk.singleQueryUrl=https://gateway.95516.com/gateway/api/queryTrans.do
acpsdk.batchTransUrl=https://gateway.95516.com/gateway/api/batchTrans.do
acpsdk.fileTransUrl=https://filedownload.95516.com/
acpsdk.appTransUrl=https://gateway.95516.com/gateway/api/appTransReq.do
acpsdk.cardTransUrl=https://gateway.95516.com/gateway/api/cardTransReq.do
#以下缴费产品使用,其余产品用不到
acpsdk.jfFrontTransUrl=https://gateway.95516.com/jiaofei/api/frontTransReq.do
acpsdk.jfBackTransUrl=https://gateway.95516.com/jiaofei/api/backTransReq.do
acpsdk.jfSingleQueryUrl=https://gateway.95516.com/jiaofei/api/queryTrans.do
acpsdk.jfCardTransUrl=https://gateway.95516.com/jiaofei/api/cardTransReq.do
acpsdk.jfAppTransUrl=https://gateway.95516.com/jiaofei/api/appTransReq.do
########################################################################
# 报文版本号,固定5.1.0,请勿改动
acpsdk.version=5.1.0
# 签名方式,证书方式固定01,请勿改动
acpsdk.signMethod=01
# 是否验证https证书,测试环境请设置false,生产环境建议优先尝试true,不行再false。非true的值默认都当false处理。
acpsdk.ifValidateRemoteCert=true
#后台通知地址,填写接收银联后台通知的地址,必须外网能访问
acpsdk.backUrl=http://222.222.222.222:8080/ACPSample_AppServer/backRcvResponse
#前台通知地址,填写处理银联前台通知的地址,必须外网能访问
acpsdk.frontUrl=http://localhost:8080/ACPSample_AppServer/frontRcvResponse
#########################入网测试环境签名证书配置 ################################
# 多证书的情况证书路径为代码指定,可不对此块做配置。
# 签名证书路径,必须使用绝对路径,如果不想使用绝对路径,可以自行实现相对路径获取证书的方法;测试证书所有商户共用开发包中的测试签名证书,生产环境请从cfca下载得到。
# windows样例:
acpsdk.signCert.path=D:/certs/从cfca获取到的私钥证书.pfx
# linux样例(注意:在linux下读取证书需要保证证书有被应用读的权限)(后续其他路径配置也同此条说明)
#acpsdk.signCert.path=/SERVICE01/usr/ac_frnas/conf/ACPtest/从cfca获取到的私钥证书.pfx
# 签名证书密码,测试环境固定000000,生产环境请修改为从cfca下载的正式证书的密码,正式环境证书密码位数需小于等于6位,否则上传到商户服务网站会失败
acpsdk.signCert.pwd=000000
# 签名证书类型,固定不需要修改
acpsdk.signCert.type=PKCS12
##########################加密证书配置################################
# 敏感信息加密证书路径(商户号开通了商户对敏感信息加密的权限,需要对 卡号accNo,pin和phoneNo,cvn2,expired加密(如果这些上送的话),对敏感信息加密使用)
acpsdk.encryptCert.path=d:/certs/acp_prod_enc.cer
##########################验签证书配置################################
# 验签中级证书路径(银联提供)
acpsdk.middleCert.path=D:/certs/acp_prod_middle.cer
# 验签根证书路径(银联提供)
acpsdk.rootCert.path=D:/certs/acp_prod_root.cer
......@@ -36,6 +36,16 @@
<artifactId>liquidnet-service-goblin-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.liquidnet</groupId>
<artifactId>liquidnet-service-dragon-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.15.6.ALL</version>
</dependency>
<dependency>
<groupId>com.liquidnet</groupId>
<artifactId>liquidnet-service-smile-api</artifactId>
......
package com.liquidnet.service.dragon.biz;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.service.base.SqlMapping;
import com.liquidnet.service.dragon.bo.PayNotifyReqBo;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.dto.DragonOrdersDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import com.liquidnet.service.dragon.dto.PayNotifyDto;
import com.liquidnet.service.dragon.utils.DataUtilsDragon;
import com.liquidnet.service.dragon.utils.MqHandleUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: DragonServiceCommonBiz
* @Package com.liquidnet.service.dragon.biz
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/19 18:06
*/
@Slf4j
@Component
public class DragonServiceCommonBiz {
@Autowired
private MqHandleUtil mqHandleUtil;
@Autowired
private DataUtilsDragon dataUtilsDragon;
public DragonOrdersDto buildPayOrders(DragonPayBaseReqDto dragonPayBaseReqDto, DragonPayBaseRespDto respDto){
//构造订单
DragonOrdersDto orders = DragonOrdersDto.getNew();
// orders.setMid();
orders.setOrderId(IDGenerator.nextTimeId());
orders.setStatus(Integer.valueOf(DragonConstant.PayStatusEnum.STATUS_UNPAID.getCode()));
orders.setCode(dragonPayBaseReqDto.getCode());
orders.setType(dragonPayBaseReqDto.getType());
orders.setPrice(dragonPayBaseReqDto.getPrice());
orders.setName(dragonPayBaseReqDto.getName());
orders.setDetail(dragonPayBaseReqDto.getDetail());
orders.setOrderCode(dragonPayBaseReqDto.getOrderCode());
orders.setOrderCodeId(dragonPayBaseReqDto.getOrderId());
orders.setClientIp(dragonPayBaseReqDto.getClientIp());
orders.setNotifyUrl(dragonPayBaseReqDto.getNotifyUrl());
orders.setNotifyStatus(Integer.valueOf(DragonConstant.PayNotifyStatusEnum.NOTIFY_INIT.getCode()));
orders.setPaymentType((dragonPayBaseReqDto.getDeviceFrom()+dragonPayBaseReqDto.getPayType()).toUpperCase());
// orders.setPaymentId();
orders.setPaymentAt(LocalDateTime.now());
// orders.setFinishedAt();
orders.setCreatedAt(LocalDateTime.now());
// orders.setUpdatedAt();
orders.setReceiptData(dragonPayBaseReqDto.getReceiptData());
long startTime = System.currentTimeMillis();
//放到redis缓存中
dataUtilsDragon.createPayOrder(orders.getCode(),orders);
log.info("redis-createPayOrder->耗时:{}",(System.currentTimeMillis() - startTime)+"毫秒");
// 持久化到数据库
startTime = System.currentTimeMillis();
boolean insertResult = mqHandleUtil.sendMySqlRedis(
SqlMapping.get("dragon_orders.insert"),
new Object[]{orders.getOrderId(),orders.getStatus(), orders.getCode(), orders.getType()
, orders.getPrice(), orders.getName(), orders.getDetail()
, orders.getOrderCode(),orders.getOrderCodeId(), orders.getClientIp()
, orders.getNotifyUrl(), orders.getNotifyStatus(),orders.getPaymentType(),
orders.getPaymentId(), orders.getPaymentAt()
, orders.getFinishedAt(), orders.getCreatedAt()
, orders.getUpdatedAt(),orders.getDeletedAt(),orders.getReceiptData()}
,DragonConstant.MysqlRedisQueueEnum.DRAGON_PAY_KEY.getCode()
);
log.info("redis-queue-sendMySqlRedis->耗时:{}",(System.currentTimeMillis() - startTime)+"毫秒");
return orders;
}
/**
* 更新支付状态
* @param code
* @param paymentId
* @return
*/
public boolean updateOrderStatus(String code,Integer status,String paymentId){
try {
LocalDateTime finishedAt = LocalDateTime.now();
LocalDateTime updateAt = LocalDateTime.now();
//t.status = ? ,t.payment_id = ?,t.finished_at = ?,t.updated_at =? where t.code = ?
boolean insertResult = mqHandleUtil.sendMySqlRedis(
SqlMapping.get("dragon_orders.updateOrderStatus"),
new Object[]{status,paymentId,finishedAt, updateAt,code}
,DragonConstant.MysqlRedisQueueEnum.DRAGON_PAY_KEY.getCode()
);
if(insertResult) return true;
} catch (Exception e) {
log.error("dragon:updateDragonOrderStatus:error msg:{}",e);
e.printStackTrace();
}
return false;
}
/**
* 更新支付通知状态
* @param code
* @return
*/
public boolean updateNotifyStatus(String code,Integer status){
try {
LocalDateTime updateAt = LocalDateTime.now();
//update dragon_orders t set t.notify_status = ? ,t.updated_at =? where t.code = ?
boolean insertResult = mqHandleUtil.sendMySqlRedis(
SqlMapping.get("dragon_orders.updateNotifyStatus"),
new Object[]{status,updateAt,code}
,DragonConstant.MysqlRedisQueueEnum.DRAGON_PAY_KEY.getCode()
);
if(insertResult) return true;
} catch (Exception e) {
log.error("dragon:updateNotifyStatus:error msg:{}",e);
e.printStackTrace();
}
return false;
}
/**
* 三方异步通知入库
* @param paymentType
* @param content
*/
public void createDragonOrderLogs(String code,String paymentType,String content){
try {
String orderId = IDGenerator.nextTimeId();
LocalDateTime createAt = LocalDateTime.now();
LocalDateTime updateAt = null;
LocalDateTime deleteAt = null;
boolean insertResult = mqHandleUtil.sendMySqlRedis(
SqlMapping.get("dragon_order_logs.insert"),
new Object[]{code,paymentType,content, createAt, updateAt,deleteAt}
,DragonConstant.MysqlRedisQueueEnum.DRAGON_PAY_NOTIFY_KEY.getCode()
);
} catch (Exception e) {
log.error("dragon:createOrderLog:error msg:{}",e);
e.printStackTrace();
}
}
/**
* 商户异步通知入库
* @param payNotifyReqBo
* @param notifyParam
*/
public void createDragonPayNotify(PayNotifyReqBo payNotifyReqBo,String notifyParam){
PayNotifyDto payNotifyDto = payNotifyReqBo.getPayNotifyDto();
try {
String code = payNotifyDto.getCode();
String orderCode = payNotifyDto.getOrderCode();
String notifyUrl = payNotifyReqBo.getNotifyUrl();
String notifyData = notifyParam;
LocalDateTime createAt = LocalDateTime.now();
LocalDateTime updateAt = LocalDateTime.now();
boolean insertResult = mqHandleUtil.sendMySqlRedis(
SqlMapping.get("dragon_pay_notify.insert"),
new Object[]{code,orderCode,notifyUrl,notifyData, createAt, updateAt}
,DragonConstant.MysqlRedisQueueEnum.PAY_MCH_NOTIFY_KEY.getCode()
);
log.info("dragon:createDragonPayNotify:success code:{}",code);
} catch (Exception e) {
log.error("dragon:createDragonPayNotify:error msg:{}",e);
e.printStackTrace();
}
}
/**
* 商户异步通知失败入库
* @param payNotifyReqBo
* @param notifyParam
*/
public void createDragonPayNotifyFail(PayNotifyReqBo payNotifyReqBo, String notifyParam){
PayNotifyDto payNotifyDto = payNotifyReqBo.getPayNotifyDto();
try {
String code = payNotifyDto.getCode();
String orderCode = payNotifyDto.getOrderCode();
String notifyUrl = payNotifyReqBo.getNotifyUrl();
String notifyData = notifyParam;
String failDesc = "通知失败";
LocalDateTime createAt = LocalDateTime.now();
LocalDateTime updateAt = LocalDateTime.now();
boolean insertResult = mqHandleUtil.sendMySqlRedis(
SqlMapping.get("dragon_pay_notify_fail.insert"),
new Object[]{code,orderCode,notifyUrl,notifyData,failDesc,createAt, updateAt}
, DragonConstant.MysqlRedisQueueEnum.PAY_MCH_NOTIFY_ERROR_KEY.getCode()
);
log.info("dragon:createDragonPayNotifyFail:success code:{}",code);
} catch (Exception e) {
log.error("dragon:createDragonPayNotifyFail:error msg:{}",e);
e.printStackTrace();
}
}
}
package com.liquidnet.service.dragon.bo;
import com.alibaba.fastjson.JSON;
import com.liquidnet.service.dragon.dto.PayNotifyDto;
import lombok.Data;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: PayNotifyReqDto
* @Package com.liquidnet.service.consumer.dragon.service.bo
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/14 20:22
*/
@Data
public class PayNotifyReqBo {
private String notifyUrl;
private String content;
private PayNotifyDto payNotifyDto;
@Override
public String toString(){
return JSON.toJSONString(this);
}
}
package com.liquidnet.service.dragon.channel.alipay.constant;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: AlipayConstant
* @Package com.liquidnet.service.dragon.channel.alipay.constant
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/13 20:52
*/
public class AlipayConstant {
public enum AlipayTradeStateEnum {
TRADE_CLOSED ("TRADE_CLOSED","交易关闭"),
TRADE_FINISHED ("TRADE_FINISHED","支付完成"),
TRADE_SUCCESS ("TRADE_SUCCESS","支付成功"),
WAIT_BUYER_PAY ("WAIT_BUYER_PAY","交易创建"),
FAIL("","支付失败");
private String code;
private String message;
AlipayTradeStateEnum(String code, String message) {
this.code = code;
this.message = message;
}
public String getCode() {
return code;
}
}
}
package com.liquidnet.service.dragon.channel.alipay.req;
import com.alibaba.fastjson.JSON;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: AlipayTradePayReq
* @Package com.liquidnet.service.dragon.channel.alipay.req
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/9 17:50
*/
@Data
public class AlipayTradePayReq implements Serializable, Cloneable{
private static final long serialVersionUID = -5827961038383330701L;
private String productCode;
private BigDecimal totalAmount;
private String subject;
private String body;
private String outTradeNo;
private String timeExpire;
private String notifyUrl;
private String timestamp;
private String authCode;
@Override
public String toString(){
return JSON.toJSONString(this);
}
private static final AlipayTradePayReq obj = new AlipayTradePayReq();
public static AlipayTradePayReq getNew() {
try {
return (AlipayTradePayReq) obj.clone();
} catch (CloneNotSupportedException e) {
return new AlipayTradePayReq();
}
}
}
/*
* Copyright 2015-2102 RonCoo(http://www.roncoo.com) Group.
*
* 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 com.liquidnet.service.dragon.channel.alipay.sign;
import org.apache.commons.codec.digest.DigestUtils;
import java.io.UnsupportedEncodingException;
import java.security.SignatureException;
/**
* 签名加密MD%
*/
public class MD5 {
/**
* 签名字符串
* @param text 需要签名的字符串
* @param key 密钥
* @param input_charset 编码格式
* @return 签名结果
*/
public static String sign(String text, String key, String input_charset) {
text = text + key;
return DigestUtils.md5Hex(getContentBytes(text, input_charset));
}
/**
* 签名字符串
* @param text 需要签名的字符串
* @param sign 签名结果
* @param key 密钥
* @param input_charset 编码格式
* @return 签名结果
*/
public static boolean verify(String text, String sign, String key, String input_charset) {
text = text + key;
String mysign = DigestUtils.md5Hex(getContentBytes(text, input_charset));
if(mysign.equals(sign)) {
return true;
}
else {
return false;
}
}
/**
* @param content
* @param charset
* @return
* @throws SignatureException
* @throws UnsupportedEncodingException
*/
private static byte[] getContentBytes(String content, String charset) {
if (charset == null || "".equals(charset)) {
return content.getBytes();
}
try {
return content.getBytes(charset);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);
}
}
}
\ No newline at end of file
package com.liquidnet.service.dragon.channel.alipay.strategy;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: Test
* @Package com.liquidnet.service.dragon.channel.strategy
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/10 14:27
*/
@Component
public class AlipayStrategyContext {
private final Map<String, IAlipayStrategy> handlerMap = new HashMap<>();
public IAlipayStrategy getStrategy(String type) {
return handlerMap.get(type);
}
public void putStrategy(String code, IAlipayStrategy strategy) {
handlerMap.put(code, strategy);
}
}
package com.liquidnet.service.dragon.channel.alipay.strategy;
import com.liquidnet.service.dragon.channel.alipay.strategy.annotation.StrategyAlipayHandler;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: Test
* @Package com.liquidnet.service.dragon.channel.strategy
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/10 14:27
*/
@Component
public class AlipayStrategyListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
Map<String, Object> beans = event.getApplicationContext().getBeansWithAnnotation(StrategyAlipayHandler.class);
AlipayStrategyContext strategyContext = event.getApplicationContext().getBean(AlipayStrategyContext.class);
beans.forEach((name, bean) -> {
StrategyAlipayHandler typeHandler = bean.getClass().getAnnotation(StrategyAlipayHandler.class);
strategyContext.putStrategy(typeHandler.value().getCode(), (IAlipayStrategy) bean);
});
}
}
\ No newline at end of file
package com.liquidnet.service.dragon.channel.alipay.strategy;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: Test
* @Package com.liquidnet.service.dragon.channel.strategy
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/10 14:27
*/
public interface IAlipayStrategy {
ResponseDto<DragonPayBaseRespDto> dragonPay(DragonPayBaseReqDto dragonPayBaseReqDto);
}
package com.liquidnet.service.dragon.channel.alipay.strategy.annotation;
import com.liquidnet.service.dragon.constant.DragonConstant;
import java.lang.annotation.*;
/**
* @author AnJiabin <jiabin.an@lightnet.io>
* @version V1.0
* @Description: TODO
* @class: StrategyGetFundDataHandler
* @Package com.liquidnet.service.reconciliation.strategy.annotation
* @Copyright: LightNet @ Copyright (c) 2020
* @date 2020/10/27 15:29
*/
@Documented
@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface StrategyAlipayHandler {
DragonConstant.DeviceFromEnum value();
}
package com.liquidnet.service.dragon.channel.alipay.strategy.impl;
import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.dragon.biz.DragonServiceCommonBiz;
import com.liquidnet.service.dragon.channel.alipay.req.AlipayTradePayReq;
import com.liquidnet.service.dragon.channel.alipay.strategy.IAlipayStrategy;
import com.liquidnet.service.dragon.channel.strategy.biz.DragonPayBiz;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Map;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: AbstractAlipayStrategy
* @Package com.liquidnet.service.dragon.channel.alipay.strategy.impl
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/12 12:36
*/
@Slf4j
public abstract class AbstractAlipayStrategy implements IAlipayStrategy {
@Autowired
private DragonPayBiz dragonPayBiz;
@Autowired
private DragonServiceCommonBiz dragonServiceCommonBiz;
protected String productCode = "QUICK_WAP_PAY";
@Override
public ResponseDto<DragonPayBaseRespDto> dragonPay(DragonPayBaseReqDto dragonPayBaseReqDto) {
//设置productCode
setProductCode();
AlipayTradePayReq alipayTradePayReq = AlipayTradePayReq.getNew();
alipayTradePayReq.setProductCode(this.productCode);
alipayTradePayReq.setTotalAmount(dragonPayBaseReqDto.getPrice());
alipayTradePayReq.setSubject(dragonPayBaseReqDto.getName());
alipayTradePayReq.setBody(dragonPayBaseReqDto.getDetail());
//dragon中支付编号
alipayTradePayReq.setOutTradeNo(dragonPayBaseReqDto.getCode());
//设置订单过期时间
String timeExpire = DateUtil.format(DateUtil.Formatter.yyyyMMddHHmmss.parse(dragonPayBaseReqDto.getCreateDate()).plusMinutes(Long.parseLong(dragonPayBaseReqDto.getExpireTime())),DateUtil.Formatter.yyyyMMddHHmmss);
alipayTradePayReq.setTimeExpire(timeExpire);
alipayTradePayReq.setNotifyUrl(this.getNotifyUrl());
alipayTradePayReq.setTimestamp(dragonPayBaseReqDto.getCreateDate());
alipayTradePayReq.setAuthCode(dragonPayBaseReqDto.getAuthCode());
//调用支付
long startTime = System.currentTimeMillis();
Map<String, Object> result = this.executePay(alipayTradePayReq);
// log.info("dragonPay:alipay:"+dragonPayBaseReqDto.getDeviceFrom()+" response xmlStr: {} ", JSON.toJSONString(result));
log.info("alipay-dragonPay->耗时:{}",(System.currentTimeMillis() - startTime)+"毫秒");
if(null!=result.get("code")&&result.get("code").toString().equals("40004")){
return null;
}
//拼接返回参数
DragonPayBaseRespDto respDto = buildCommonRespDto(dragonPayBaseReqDto);
respDto = this.buildResponseDto(respDto,result);
//支付订单持久化
dragonServiceCommonBiz.buildPayOrders(dragonPayBaseReqDto,null);
return ResponseDto.success(respDto);
}
/**
* 支付请求
* @param alipayTradePayReq
* @return
*/
protected abstract Map<String, Object> executePay(AlipayTradePayReq alipayTradePayReq);
/**
* 设置productCode
*/
protected abstract void setProductCode();
/**
* 设置notifyUrl
*/
protected abstract String getNotifyUrl();
/**
* 构造公共返回参数
* @param dragonPayBaseReqDto
* @return
*/
protected DragonPayBaseRespDto buildCommonRespDto(DragonPayBaseReqDto dragonPayBaseReqDto){
DragonPayBaseRespDto respDto = new DragonPayBaseRespDto();
respDto.setPayType(dragonPayBaseReqDto.getPayType());
respDto.setCode(dragonPayBaseReqDto.getCode());
respDto.setOrderCode(dragonPayBaseReqDto.getOrderCode());
DragonPayBaseRespDto.PayData payData = new DragonPayBaseRespDto.PayData();
respDto.setPayData(payData);
return respDto;
}
/**
* 构造返回参数
*/
abstract DragonPayBaseRespDto buildResponseDto(DragonPayBaseRespDto payBaseRespDto,Map<String, Object> respResult);
}
package com.liquidnet.service.dragon.channel.alipay.strategy.impl;
import com.liquidnet.service.dragon.channel.alipay.biz.AlipayBiz;
import com.liquidnet.service.dragon.channel.alipay.req.AlipayTradePayReq;
import com.liquidnet.service.dragon.channel.alipay.strategy.annotation.StrategyAlipayHandler;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: AlipayStrategyWapImpl
* @Package com.liquidnet.service.dragon.channel.alipay.strategy.impl
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/10 14:34
*/
@Slf4j
@Component
@StrategyAlipayHandler(DragonConstant.DeviceFromEnum.APP)
public class AlipayStrategyAppImpl extends AbstractAlipayStrategy {
@Value("${liquidnet.dragon.alipay.gataway-url}")
private String alipayGatewayUrl;
@Value("${liquidnet.dragon.url}")
private String notifyUrl;
@Autowired
StringRedisTemplate stringRedisTemplate;
@Autowired
private AlipayBiz alipayBiz;
@Override
protected Map<String, Object> executePay(AlipayTradePayReq alipayTradePayReq) {
return alipayBiz.tradeAppPay(alipayTradePayReq);
}
protected void setProductCode() {
this.productCode = "QUICK_MSECURITY_PAY";
}
@Override
protected String getNotifyUrl() {
// notifyUrl = "/notify/app/alipay/1";
return notifyUrl + "/notify/alipay/app";
}
@Override
DragonPayBaseRespDto buildResponseDto(DragonPayBaseRespDto payBaseRespDto, Map<String, Object> respResult) {
payBaseRespDto.getPayData().setOrderStr(respResult.get("body").toString());
return payBaseRespDto;
}
}
package com.liquidnet.service.dragon.channel.alipay.strategy.impl;
import com.liquidnet.service.dragon.channel.alipay.biz.AlipayBiz;
import com.liquidnet.service.dragon.channel.alipay.req.AlipayTradePayReq;
import com.liquidnet.service.dragon.channel.alipay.strategy.annotation.StrategyAlipayHandler;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: AlipayStrategyWapImpl
* @Package com.liquidnet.service.dragon.channel.alipay.strategy.impl
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/10 14:34
*/
@Slf4j
@Service
@StrategyAlipayHandler(DragonConstant.DeviceFromEnum.MICROPAY)
public class AlipayStrategyMicropayImpl extends AbstractAlipayStrategy {
@Value("${liquidnet.dragon.alipay.gataway-url}")
private String alipayGatewayUrl;
@Value("${liquidnet.dragon.url}")
private String notifyUrl;
@Autowired
StringRedisTemplate stringRedisTemplate;
@Autowired
private AlipayBiz alipayBiz;
@Override
protected Map<String, Object> executePay(AlipayTradePayReq alipayTradePayReq) {
return alipayBiz.tradeMicroPay(alipayTradePayReq);
}
protected void setProductCode() {
this.productCode = "QUICK_WAP_PAY";
}
@Override
protected String getNotifyUrl() {
// notifyUrl = "/notify/wap/alipay/1";
return notifyUrl + "/notify/alipay/wap";
}
@Override
DragonPayBaseRespDto buildResponseDto(DragonPayBaseRespDto payBaseRespDto, Map<String, Object> respResult) {
// payBaseRespDto.getPayData().setRedirectUrl(alipayGatewayUrl + "?" + respResult.get("body"));
return payBaseRespDto;
}
}
package com.liquidnet.service.dragon.channel.alipay.strategy.impl;
import com.liquidnet.service.dragon.channel.alipay.biz.AlipayBiz;
import com.liquidnet.service.dragon.channel.alipay.req.AlipayTradePayReq;
import com.liquidnet.service.dragon.channel.alipay.strategy.annotation.StrategyAlipayHandler;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: AlipayStrategyWapImpl
* @Package com.liquidnet.service.dragon.channel.alipay.strategy.impl
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/10 14:34
*/
@Slf4j
@Service
@StrategyAlipayHandler(DragonConstant.DeviceFromEnum.WAP)
public class AlipayStrategyWapImpl extends AbstractAlipayStrategy {
@Value("${liquidnet.dragon.alipay.gataway-url}")
private String alipayGatewayUrl;
@Value("${liquidnet.dragon.url}")
private String notifyUrl;
@Autowired
StringRedisTemplate stringRedisTemplate;
@Autowired
private AlipayBiz alipayBiz;
@Override
protected Map<String, Object> executePay(AlipayTradePayReq alipayTradePayReq) {
return alipayBiz.tradeWapPay(alipayTradePayReq);
}
protected void setProductCode() {
this.productCode = "QUICK_WAP_PAY";
}
@Override
protected String getNotifyUrl() {
// notifyUrl = "/notify/wap/alipay/1";
return notifyUrl + "/notify/alipay/wap";
}
@Override
DragonPayBaseRespDto buildResponseDto(DragonPayBaseRespDto payBaseRespDto, Map<String, Object> respResult) {
payBaseRespDto.getPayData().setRedirectUrl(alipayGatewayUrl + "?" + respResult.get("body"));
return payBaseRespDto;
}
}
package com.liquidnet.service.dragon.channel.douyinpay.biz;
import com.alibaba.fastjson.JSON;
import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.service.dragon.utils.PayDouYinpayUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
/**
* @author zhangfuxin
* @Description:
* @date 2021/11/12 上午11:15
*/
@Slf4j
@Component
public class DouYinPayBiz {
@Value("${liquidnet.dragon.wepay.merchantId}")
private String merchantId;
/**
* @author zhangfuxin
* @Description:抖音订单查询 实现
* @date 2021/11/12 上午11:27
*/
public Map<String, Object> tradeQuery(String outOrderNo, String appid) {
Map<String, Object> respMap =CollectionUtil.mapStringObject();
log.info("DouYinPayBiz.tradeQuery-->> request out_order_no:{} appid:{} ",outOrderNo,appid);
SortedMap<String, Object> parameters = new TreeMap<>();
parameters.put("app_id", appid);
parameters.put("out_order_no", outOrderNo);
//生成签名
String sign = PayDouYinpayUtils.getInstance().createSign(parameters);
parameters.put("sign", sign);
//map转string
String data = JSON.toJSONString(parameters);
log.info("抖音订单查询请求参数:{}",data);
try {
HttpPost httpost = new HttpPost("https://developer.toutiao.com/api/apps/ecpay/v1/query_order");
httpost.setEntity(new StringEntity(data, "UTF-8"));
CloseableHttpClient httpClient = PayDouYinpayUtils.getInstance().getHttpClient();
CloseableHttpResponse response = httpClient.execute(httpost);
HttpEntity entity = response.getEntity();
//接受到返回信息
String json = EntityUtils.toString(response.getEntity(), "UTF-8");
log.info("抖音订单查询接口返回:{}",json);
EntityUtils.consume(entity);
respMap=JSON.parseObject(json, HashMap.class);
}catch (Exception e){
log.error(e.getMessage());
}
return respMap;
}
}
package com.liquidnet.service.dragon.channel.douyinpay.constant;
/**
* @author zhangfuxin
* @Description: 抖音枚举
* @date 2021/11/9 下午3:37
*/
public class DouYinpayConstant {
public enum DouYinTradeStateEnum {
SUCCESS("0","成功");
private String code;
private String message;
DouYinTradeStateEnum(String code, String message) {
this.code = code;
this.message = message;
}
public String getCode() {
return code;
}
}
}
package com.liquidnet.service.dragon.channel.douyinpay.strategy;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
* @author zhangfuxin
* @Description:
* @date 2021/11/9 下午4:09
*/
@Component
public class DouYinayStrategyContext {
private final Map<String, IDouYinpayStrategy> handlerMap = new HashMap<>();
public IDouYinpayStrategy getStrategy(String type) {
return handlerMap.get(type);
}
public void putStrategy(String code, IDouYinpayStrategy strategy) {
handlerMap.put(code, strategy);
}
}
package com.liquidnet.service.dragon.channel.douyinpay.strategy;
import com.liquidnet.service.dragon.channel.douyinpay.strategy.annotation.StrategyDouYinPayHandler;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* @author zhangfuxin
* @Description:
* @date 2021/11/9 下午4:12
*/
@Component
public class DouYinpayStrategyListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
Map<String, Object> beans = event.getApplicationContext().getBeansWithAnnotation(StrategyDouYinPayHandler.class);
DouYinayStrategyContext strategyContext = event.getApplicationContext().getBean(DouYinayStrategyContext.class);
beans.forEach((name, bean) -> {
StrategyDouYinPayHandler typeHandler = bean.getClass().getAnnotation(StrategyDouYinPayHandler.class);
strategyContext.putStrategy(typeHandler.value().getCode(), (IDouYinpayStrategy) bean);
});
}
}
\ No newline at end of file
package com.liquidnet.service.dragon.channel.douyinpay.strategy;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import com.liquidnet.service.dragon.dto.DragonPayOrderQueryRespDto;
/**
* @author zhangfuxin
* @Description: 抖音支付接口
* @date 2021/11/9 下午1:42
*/
public interface IDouYinpayStrategy {
/**
* @author zhangfuxin
* @Description: 预支付
* @date 2021/11/9 下午1:44
*/
ResponseDto<DragonPayBaseRespDto> dragonPay(DragonPayBaseReqDto dragonPayBaseReqDto);
DragonPayOrderQueryRespDto checkOrderStatus(String code);
}
package com.liquidnet.service.dragon.channel.douyinpay.strategy.annotation;
import com.liquidnet.service.dragon.constant.DragonConstant;
import java.lang.annotation.*;
/**
* @author zhangfuxin
* @Description: 抖音标记
* @date 2021/11/9 下午1:40
*/
@Documented
@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface StrategyDouYinPayHandler {
DragonConstant.DeviceFromEnum value();
}
package com.liquidnet.service.dragon.channel.douyinpay.strategy.impl;
import com.alibaba.fastjson.JSON;
import com.liquidnet.common.exception.LiquidnetServiceException;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.dragon.biz.DragonServiceCommonBiz;
import com.liquidnet.service.dragon.channel.douyinpay.biz.DouYinPayBiz;
import com.liquidnet.service.dragon.channel.douyinpay.constant.DouYinpayConstant;
import com.liquidnet.service.dragon.channel.douyinpay.strategy.IDouYinpayStrategy;
import com.liquidnet.service.dragon.channel.strategy.biz.DragonPayBiz;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.constant.DragonErrorCodeEnum;
import com.liquidnet.service.dragon.dto.DragonOrdersDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import com.liquidnet.service.dragon.dto.DragonPayOrderQueryRespDto;
import com.liquidnet.service.dragon.utils.DataUtilsDragon;
import com.liquidnet.service.dragon.utils.PayDouYinpayUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
/**
* @author zhangfuxin
* @Description: 抖音支付的抽象类
* @date 2021/11/9 下午1:41
*/
@Slf4j
public abstract class AbstractDouYinPayStrategy implements IDouYinpayStrategy {
// 订单过期时间(秒); 最小 15 分钟,最大两天
private int valid_time=60*60*24*2;
@Autowired
private DouYinPayBiz douYinPayBiz;
@Autowired
private DataUtilsDragon dataUtilsDragon;
@Autowired
private DragonServiceCommonBiz dragonServiceCommonBiz;
@Autowired
private DragonPayBiz dragonPayBiz;
@Override
public ResponseDto<DragonPayBaseRespDto> dragonPay(DragonPayBaseReqDto dragonPayBaseReqDto) {
long startTimeTotal = System.currentTimeMillis();
long startTime = System.currentTimeMillis();
try {
//构造请求参数
SortedMap<String, Object> commonParams = this.buildRequestParamMap(dragonPayBaseReqDto);
//追加请求参数
SortedMap<String, Object> parameters = this.appendRequestParam(commonParams,dragonPayBaseReqDto);
//生成签名
String sign = PayDouYinpayUtils.getInstance().createSign(parameters);
parameters.put("sign", sign);
//map转string
String data = JSON.toJSONString(parameters);
log.info("dragonPay:douYinPay:"+dragonPayBaseReqDto.getDeviceFrom()+" request jsondata: {} ",data);
HttpPost httpost = new HttpPost(this.getRequestUrl());
httpost.setEntity(new StringEntity(data, "UTF-8"));
startTime = System.currentTimeMillis();
CloseableHttpClient httpClient = PayDouYinpayUtils.getInstance().getHttpClient();
log.info("douYinPay-->request--> getHttpClient耗时:{}",(System.currentTimeMillis() - startTime)+"毫秒");
startTime = System.currentTimeMillis();
CloseableHttpResponse response = httpClient.execute(httpost);
log.info("douYinPay-->request--> execute耗时:{}",(System.currentTimeMillis() - startTime)+"毫秒");
HttpEntity entity = response.getEntity();
//接收到返回信息
String json = EntityUtils.toString(response.getEntity(), "UTF-8");
EntityUtils.consume(entity);
log.info("dragonPay:douYinPay:"+dragonPayBaseReqDto.getDeviceFrom()+" response jsonStr: {} ",json);
//拼接返回参数
DragonPayBaseRespDto respDto = buildCommonRespDto(dragonPayBaseReqDto);
Map result=JSON.parseObject(json, HashMap.class);
if(DouYinpayConstant.DouYinTradeStateEnum.SUCCESS.getCode().equals(result.get("err_no").toString())){
//成功
respDto = this.buildResponseDto(respDto,result);
//支付订单持久化
dragonServiceCommonBiz.buildPayOrders(dragonPayBaseReqDto,respDto);
log.info("douYinpay-->dragonPay--> 耗时:{}",(System.currentTimeMillis() - startTimeTotal)+"毫秒");
return ResponseDto.success(respDto);
}else {
throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_PARAM_ERROR.getCode(),DragonErrorCodeEnum.TRADE_PARAM_ERROR.getMessage());
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 构造公共返回参数
* @param dragonPayBaseReqDto
* @return
*/
protected DragonPayBaseRespDto buildCommonRespDto(DragonPayBaseReqDto dragonPayBaseReqDto){
DragonPayBaseRespDto respDto = new DragonPayBaseRespDto();
respDto.setCode(dragonPayBaseReqDto.getCode());
respDto.setOrderCode(dragonPayBaseReqDto.getOrderCode());
DragonPayBaseRespDto.PayData payData = new DragonPayBaseRespDto.PayData();
respDto.setPayData(payData);
return respDto;
}
/**
* 构造请求参数
* @return
*/
protected SortedMap<String, Object> buildRequestParamMap(DragonPayBaseReqDto dragonPayBaseReqDto){
SortedMap<String, Object> parameters = new TreeMap<>();
parameters.put("total_amount", dragonPayBaseReqDto.getPrice().multiply(BigDecimal.valueOf(100L)).intValue());
//商品描述; 长度限制 128 字节,不超过 42 个汉字
parameters.put("subject", dragonPayBaseReqDto.getName());
//商品详情
parameters.put("body", dragonPayBaseReqDto.getDetail());
//开发者侧的订单号, 同一小程序下不可重复
parameters.put("out_order_no", dragonPayBaseReqDto.getCode());
parameters.put("notify_url", this.getNotifyUrl());
//订单过期时间(秒); 最小 15 分钟,最大两天
parameters.put("valid_time",Integer.parseInt(dragonPayBaseReqDto.getExpireTime())*60);
return parameters;
};
/**
* 追加请求参数
* @param requestMap
* @return
*/
abstract SortedMap<String, Object> appendRequestParam(SortedMap<String, Object> requestMap,DragonPayBaseReqDto dragonPayBaseReqDto);
/**
* 构造返回参数
*/
abstract DragonPayBaseRespDto buildResponseDto(DragonPayBaseRespDto payBaseRespDto,Map result);
/**
* 获取请求url
* @return
*/
protected abstract String getRequestUrl();
/**
* 设置notifyUrl
*/
protected abstract String getNotifyUrl();
@Override
public DragonPayOrderQueryRespDto checkOrderStatus(String code) {
DragonOrdersDto ordersDto = dataUtilsDragon.getPayOrderByCode(code);
Map<String, Object> resultMaps = douYinPayBiz.tradeQuery(code,this.getAppid());
DragonPayOrderQueryRespDto respDto = dragonPayBiz.buildPayOrderQueryRespDto(ordersDto);
Map<String, Object> resultMap= (Map<String, Object>) resultMaps.get("payment_info");
Object orderStatus = resultMap.get("order_status");
/* // 查询失败
if (null == orderStatus || "FAIL".equals(orderStatus)) {
throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_DOUYINPAY_QUERY_ERROR.getCode(),DragonErrorCodeEnum.TRADE_DOUYINPAY_QUERY_ERROR.getMessage());
}*/
// 当trade_state为SUCCESS时才返回result_code
if ("SUCCESS".equals(orderStatus)) {
respDto.setStatus(Integer.valueOf(DragonConstant.PayStatusEnum.STATUS_PAID.getCode()));
}else {
respDto.setStatus(Integer.valueOf(DragonConstant.PayStatusEnum.STATUS_PAY_FAIL.getCode()));
}
return respDto;
}
protected abstract String getAppid();
}
package com.liquidnet.service.dragon.channel.douyinpay.strategy.impl;
import com.liquidnet.service.dragon.channel.douyinpay.strategy.annotation.StrategyDouYinPayHandler;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import com.liquidnet.service.dragon.utils.PayDouYinpayUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.SortedMap;
/**
* @author zhangfuxin
* @Description: 抖音小程序支付实现
* @date 2021/11/9 下午1:45
*/
@Slf4j
@Component
@StrategyDouYinPayHandler(DragonConstant.DeviceFromEnum.APPLET)
public class DouYinPayStrategyAppletImpl extends AbstractDouYinPayStrategy {
@Value("${liquidnet.dragon.url}")
private String notifyUrl;
@Override
SortedMap<String, Object> appendRequestParam(SortedMap<String, Object> requestMap, DragonPayBaseReqDto dragonPayBaseReqDto) {
requestMap.put("app_id", PayDouYinpayUtils.getInstance().getAPP_ID());
return requestMap;
}
@Override
DragonPayBaseRespDto buildResponseDto(DragonPayBaseRespDto payBaseRespDto, Map result) {
Map data= (Map) result.get("data");
payBaseRespDto.getPayData().setOrderId(data.get("order_id").toString());
payBaseRespDto.getPayData().setOrderToken(data.get("order_token").toString());
return payBaseRespDto;
}
@Override
protected String getRequestUrl() {
return "https://developer.toutiao.com/api/apps/ecpay/v1/create_order";
}
@Override
protected String getNotifyUrl() {
return notifyUrl + "/notify/douyinpay/applet";
}
@Override
protected String getAppid() {
return PayDouYinpayUtils.getInstance().getAPP_ID();
}
}
package com.liquidnet.service.dragon.channel.strategy;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import com.liquidnet.service.dragon.dto.DragonPayOrderQueryRespDto;
import javax.servlet.http.HttpServletRequest;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: Test
* @Package com.liquidnet.service.dragon.channel.strategy
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/10 14:27
*/
public interface IPayChannelStrategy {
ResponseDto<DragonPayBaseRespDto> dragonPay(DragonPayBaseReqDto dragonPayBaseReqDto);
String dragonNotify(HttpServletRequest request,String payType,String deviceFrom);
DragonPayOrderQueryRespDto checkOrderStatus(String code);
}
package com.liquidnet.service.dragon.channel.strategy;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: Test
* @Package com.liquidnet.service.dragon.channel.strategy
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/10 14:27
*/
@Component
public class PayChannelStrategyContext {
private final Map<String, IPayChannelStrategy> handlerMap = new HashMap<>();
public IPayChannelStrategy getStrategy(String type) {
return handlerMap.get(type);
}
public void putStrategy(String code, IPayChannelStrategy strategy) {
handlerMap.put(code, strategy);
}
}
package com.liquidnet.service.dragon.channel.strategy;
import com.liquidnet.service.dragon.channel.strategy.annotation.StrategyPayChannelHandler;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: Test
* @Package com.liquidnet.service.dragon.channel.strategy
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/10 14:27
*/
@Component
public class PayChannelStrategyListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
Map<String, Object> beans = event.getApplicationContext().getBeansWithAnnotation(StrategyPayChannelHandler.class);
PayChannelStrategyContext strategyContext = event.getApplicationContext().getBean(PayChannelStrategyContext.class);
beans.forEach((name, bean) -> {
StrategyPayChannelHandler typeHandler = bean.getClass().getAnnotation(StrategyPayChannelHandler.class);
strategyContext.putStrategy(typeHandler.value().getCode(), (IPayChannelStrategy) bean);
});
}
}
\ No newline at end of file
package com.liquidnet.service.dragon.channel.strategy.annotation;
import com.liquidnet.service.dragon.constant.DragonConstant;
import java.lang.annotation.*;
/**
* @author AnJiabin <jiabin.an@lightnet.io>
* @version V1.0
* @Description: TODO
* @class: StrategyGetFundDataHandler
* @Package com.liquidnet.service.reconciliation.strategy.annotation
* @Copyright: LightNet @ Copyright (c) 2020
* @date 2020/10/27 15:29
*/
@Documented
@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface StrategyPayChannelHandler {
DragonConstant.PayChannelEnum value();
}
package com.liquidnet.service.dragon.channel.strategy.impl;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.dragon.biz.DragonServiceCommonBiz;
import com.liquidnet.service.dragon.channel.strategy.IPayChannelStrategy;
import com.liquidnet.service.dragon.channel.strategy.biz.DragonPayBiz;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.dto.DragonOrdersDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import com.liquidnet.service.dragon.dto.DragonPayOrderQueryRespDto;
import com.liquidnet.service.dragon.utils.DataUtilsDragon;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: AbstractPayChannelStrategyImpl
* @Package com.liquidnet.service.dragon.channel.strategy.impl
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/16 13:04
*/
@Slf4j
public abstract class AbstractPayChannelStrategyImpl implements IPayChannelStrategy {
@Autowired
private DragonPayBiz dragonPayBiz;
@Autowired
private DataUtilsDragon dataUtilsDragon;
@Autowired
private DragonServiceCommonBiz dragonServiceCommonBiz;
@Override
public abstract ResponseDto<DragonPayBaseRespDto> dragonPay(DragonPayBaseReqDto dragonPayBaseReqDto);
@Override
public abstract String dragonNotify(HttpServletRequest request, String payType, String deviceFrom);
@Override
public abstract DragonPayOrderQueryRespDto checkOrderStatus(String code);
/**
* 支付成功方法
* @param dragonOrdersDto
* @param bankTrxNo
* @param timeEnd
* @param bankReturnMsg
*/
@Transactional(rollbackFor = Exception.class)
public boolean completeSuccessOrder(DragonOrdersDto dragonOrdersDto, String bankTrxNo, LocalDateTime timeEnd, String bankReturnMsg) {
log.info("订单支付成功!");
dragonOrdersDto.setPaymentAt(timeEnd);
dragonOrdersDto.setPaymentId(bankTrxNo);// 设置银行流水号
dragonOrdersDto.setStatus(Integer.parseInt(DragonConstant.PayStatusEnum.STATUS_PAID.getCode()));
//更新缓存
dataUtilsDragon.updateOrderStatus(dragonOrdersDto.getCode(),dragonOrdersDto);
//修改订单状态
dragonServiceCommonBiz.updateOrderStatus(dragonOrdersDto.getCode(),dragonOrdersDto.getStatus(),bankTrxNo);
//通知商户
return dragonPayBiz.sendNotify(dragonPayBiz.buildPayNotifyReqBo(dragonOrdersDto));
}
@Transactional(rollbackFor = Exception.class)
public void completeSuccessOrderNoNotify(DragonOrdersDto dragonOrdersDto, String bankTrxNo, LocalDateTime timeEnd, String bankReturnMsg) {
log.info("订单支付成功!");
dragonOrdersDto.setPaymentAt(timeEnd);
dragonOrdersDto.setPaymentId(bankTrxNo);// 设置银行流水号
dragonOrdersDto.setStatus(Integer.parseInt(DragonConstant.PayStatusEnum.STATUS_PAID.getCode()));
//更新缓存
dataUtilsDragon.updateOrderStatus(dragonOrdersDto.getCode(),dragonOrdersDto);
//修改订单状态
dragonServiceCommonBiz.updateOrderStatus(dragonOrdersDto.getCode(),dragonOrdersDto.getStatus(),bankTrxNo);
}
/**
* 支付失败方法
* @param dragonOrdersDto
* @param bankReturnMsg
*/
public boolean completeFailOrder(DragonOrdersDto dragonOrdersDto, String bankReturnMsg) {
log.info("订单支付失败!");
// dragonOrdersDto.setPaymentAt(timeEnd);
// dragonOrdersDto.setPaymentId(bankTrxNo);// 设置银行流水号
dragonOrdersDto.setStatus(Integer.parseInt(DragonConstant.PayStatusEnum.STATUS_PAY_FAIL.getCode()));
//更新缓存
dataUtilsDragon.updateOrderStatus(dragonOrdersDto.getCode(),dragonOrdersDto);
//修改订单状态
dragonServiceCommonBiz.updateOrderStatus(dragonOrdersDto.getCode(),dragonOrdersDto.getStatus(),null);
//通知商户
return dragonPayBiz.sendNotify(dragonPayBiz.buildPayNotifyReqBo(dragonOrdersDto));
}
}
package com.liquidnet.service.dragon.channel.strategy.impl;
import com.alibaba.fastjson.JSONObject;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.dragon.channel.strategy.annotation.StrategyPayChannelHandler;
import com.liquidnet.service.dragon.channel.strategy.biz.DragonPayBiz;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.dto.DragonOrdersDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import com.liquidnet.service.dragon.dto.DragonPayOrderQueryRespDto;
import com.liquidnet.service.dragon.service.impl.DragonOrdersServiceImpl;
import com.liquidnet.service.dragon.utils.DataUtilsDragon;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: PayChannelStrategyAlipayImpl
* @Package com.liquidnet.service.dragon.channel.strategy.impl
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/13 13:06
*/
@Slf4j
@Component
@StrategyPayChannelHandler(DragonConstant.PayChannelEnum.APPLEPAY)
public class ApplepayImpl extends AbstractPayChannelStrategyImpl {
@Autowired
private DataUtilsDragon dataUtilsDragon;
@Autowired
private DragonOrdersServiceImpl dragonOrdersService;
@Autowired
private DragonPayBiz dragonPayBiz;
public void completeSuccessOrder(DragonOrdersDto dragonOrdersDto,String code,String result){
this.completeSuccessOrderNoNotify(dragonOrdersDto, code, LocalDateTime.now(), result);
}
@Override
public ResponseDto<DragonPayBaseRespDto> dragonPay(DragonPayBaseReqDto dragonPayBaseReqDto) {
return null;
}
@Override
public String dragonNotify(HttpServletRequest request, String payType, String deviceFrom) {
return null;
}
@Override
public DragonPayOrderQueryRespDto checkOrderStatus(String code) {
DragonOrdersDto ordersDto = dataUtilsDragon.getPayOrderByCode(code);
//调用 苹果效验
String verifyResult=dragonOrdersService.buyAppVerify(ordersDto.getReceiptData());
if (verifyResult == null) {
// 苹果服务器没有返回验证结果
log.info("苹果支付查询(checkOrderStatus),查不到订单信息");
return null;
} else {
JSONObject job = JSONObject.parseObject(verifyResult);
String states = job.getString("status");
if (states.equals("0")) { // 前端所提供的收据是有效的 验证成功
DragonPayOrderQueryRespDto respDto = dragonPayBiz.buildPayOrderQueryRespDto(ordersDto);
respDto.setStatus(Integer.valueOf(DragonConstant.PayStatusEnum.STATUS_PAID.getCode()));
return respDto;
}
}
return null;
}
}
package com.liquidnet.service.dragon.channel.strategy.impl;
import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.liquidnet.common.exception.LiquidnetServiceException;
import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.commons.lang.util.StringUtil;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.dragon.biz.DragonServiceCommonBiz;
import com.liquidnet.service.dragon.channel.alipay.biz.AlipayBiz;
import com.liquidnet.service.dragon.channel.alipay.constant.AlipayConstant;
import com.liquidnet.service.dragon.channel.alipay.strategy.AlipayStrategyContext;
import com.liquidnet.service.dragon.channel.strategy.annotation.StrategyPayChannelHandler;
import com.liquidnet.service.dragon.channel.strategy.biz.DragonPayBiz;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.constant.DragonErrorCodeEnum;
import com.liquidnet.service.dragon.dto.DragonOrdersDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import com.liquidnet.service.dragon.dto.DragonPayOrderQueryRespDto;
import com.liquidnet.service.dragon.service.impl.DragonOrderRefundsServiceImpl;
import com.liquidnet.service.dragon.utils.DataUtilsDragon;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: PayChannelStrategyAlipayImpl
* @Package com.liquidnet.service.dragon.channel.strategy.impl
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/13 13:06
*/
@Slf4j
@Component
@StrategyPayChannelHandler(DragonConstant.PayChannelEnum.ALIPAY)
public class PayChannelStrategyAlipayImpl extends AbstractPayChannelStrategyImpl {
@Autowired
private AlipayStrategyContext alipayStrategyContext;
@Autowired
private DataUtilsDragon dataUtilsDragon;
@Autowired
private AlipayBiz alipayBiz;
@Autowired
private DragonPayBiz dragonPayBiz;
@Autowired
private DragonServiceCommonBiz dragonServiceCommonBiz;
@Autowired
private DragonOrderRefundsServiceImpl dragonOrderRefundsService;
@Value("${liquidnet.dragon.alipay.appId}")
private String appId;
@Value("${liquidnet.dragon.alipay.merchantPubKey}")
private String merchantPubKey;
@Value("${liquidnet.dragon.alipay.merchantPrivateKey}")
private String merchantPrivateKey;
@Value("${liquidnet.dragon.alipay.signtType}")
private String signtType;
@Value("${liquidnet.dragon.alipay.charset}")
private String charset;
@Override
public ResponseDto<DragonPayBaseRespDto> dragonPay(DragonPayBaseReqDto dragonPayBaseReqDto) {
return alipayStrategyContext.getStrategy(dragonPayBaseReqDto.getDeviceFrom()).dragonPay(dragonPayBaseReqDto);
}
@Override
public String dragonNotify(HttpServletRequest request,String payType,String deviceFrom) {
log.info("alipay-->notify-->begin payType:{} deviceFrom:{}",payType,deviceFrom);
Map<String, String[]> requestParams = request.getParameterMap();
Map<String, String> notifyMap = new HashMap<String, String>();
notifyMap = alipayBiz.parseNotifyMsg(requestParams);
log.info("dragonNotify-->alipay json : {}", JSON.toJSONString(notifyMap));
log.info("接收到{}支付结果{}", payType, notifyMap);
String returnStr = "fail";
String code = notifyMap.get("out_trade_no");
if(StringUtil.isBlank(code)){
throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_ERROR_NOT_EXISTS.getCode(),DragonErrorCodeEnum.TRADE_ERROR_NOT_EXISTS.getMessage());
}
//持久化通知记录
dragonServiceCommonBiz.createDragonOrderLogs(code,dragonPayBiz.getPaymentType(payType,deviceFrom),JSON.toJSONString(notifyMap));
//退款
if(notifyMap.containsKey("refund_fee") || notifyMap.containsKey("gmt_refund") || notifyMap.containsKey("out_biz_no")) {
returnStr = dragonOrderRefundsService.aliPayRefundCallBack(JSON.toJSONString(notifyMap));
return returnStr;
}
// 根据银行订单号获取支付信息
DragonOrdersDto dragonOrdersDto = dataUtilsDragon.getPayOrderByCode(code);
if (dragonOrdersDto == null) {
throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_ERROR_NOT_EXISTS.getCode(),DragonErrorCodeEnum.TRADE_ERROR_NOT_EXISTS.getMessage());
}
if (DragonConstant.PayStatusEnum.STATUS_PAID.getCode().equals(dragonOrdersDto.getStatus())) {
throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_ERROR_HAS_PAID.getCode(),DragonErrorCodeEnum.TRADE_ERROR_HAS_PAID.getMessage());
}
try {
if (AlipaySignature.rsaCheckV1(notifyMap, merchantPubKey, "UTF-8", "RSA2")){
String tradeStatus = notifyMap.get("trade_status");
boolean notifyResult = false;
if (AlipayConstant.AlipayTradeStateEnum.TRADE_SUCCESS.name().equals(tradeStatus)
||AlipayConstant.AlipayTradeStateEnum.TRADE_FINISHED.name().equals(tradeStatus)) {
String gmtPaymentStr = notifyMap.get("gmt_payment");// 付款时间
LocalDateTime timeEnd = null;
if (!StringUtil.isEmpty(gmtPaymentStr)) {
timeEnd = DateUtil.Formatter.yyyyMMddHHmmss.parse(gmtPaymentStr);
}
notifyResult = this.completeSuccessOrder(dragonOrdersDto, notifyMap.get("trade_no"), timeEnd, notifyMap.toString());
} else {
notifyResult = this.completeFailOrder(dragonOrdersDto, notifyMap.toString());
}
if(notifyResult){
returnStr = "success";
}
} else {// 验证失败
log.error("alipay notify fail code:{} msg:{} ",DragonErrorCodeEnum.TRADE_ALIPAY_SIGN_ERROR.getCode(),DragonErrorCodeEnum.TRADE_ALIPAY_SIGN_ERROR.getMessage());
return returnStr;
}
} catch (AlipayApiException e) {
log.error("alipay notify fail 验签失败:e:{}" , e);
log.error("alipay notify fail 验签失败:code:{} msg:{}" ,DragonErrorCodeEnum.TRADE_ALIPAY_SIGN_ERROR.getCode(),DragonErrorCodeEnum.TRADE_ALIPAY_SIGN_ERROR.getMessage());
}
log.info("返回支付通道{}信息{}", payType, returnStr);
log.info("alipay-->notify-->end payType:{} deviceFrom:{}",payType,deviceFrom);
return returnStr;
}
@Override
public DragonPayOrderQueryRespDto checkOrderStatus(String code) {
/* DragonOrdersDto ordersDto = dataUtils.getPayOrderByCode(code);
DragonPayOrderQueryRespDto respDto = alipayStrategyContext.getStrategy(DragonConstant.PayTypeEnum.getEnumByCode(ordersDto.getPaymentType()).getDeviceFrom()).checkOrderStatus(code);
*/
DragonOrdersDto ordersDto = dataUtilsDragon.getPayOrderByCode(code);
Map<String, Object> resultMap = alipayBiz.tradeQuery(code);
DragonPayOrderQueryRespDto respDto = dragonPayBiz.buildPayOrderQueryRespDto(ordersDto);
if ("10000".equals(resultMap.get("code"))) {
// 当返回状态为“TRADE_FINISHED”交易成功结束和“TRADE_SUCCESS”支付成功时更新交易状态
if (AlipayConstant.AlipayTradeStateEnum.TRADE_SUCCESS.getCode().equals(resultMap.get("tradeStatus"))
|| AlipayConstant.AlipayTradeStateEnum.TRADE_FINISHED.getCode().equals(resultMap.get("tradeStatus"))) {
respDto.setStatus(Integer.valueOf(DragonConstant.PayStatusEnum.STATUS_PAID.getCode()));
if(ordersDto.getPaymentType().equals(DragonConstant.PayTypeEnum.PAYMENT_TYPE_MICROPAY_ALIPAY.getCode())){
this.completeSuccessOrder(ordersDto, resultMap.get("tradeNo").toString(), LocalDateTime.now(), resultMap.toString());
}
}else{
respDto.setStatus(Integer.valueOf(DragonConstant.PayStatusEnum.STATUS_PAY_FAIL.getCode()));
if(ordersDto.getPaymentType().equals(DragonConstant.PayTypeEnum.PAYMENT_TYPE_MICROPAY_ALIPAY.getCode())){
this.completeFailOrder(ordersDto, resultMap.toString());
}
}
// throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_ALIPAY_QUERY_ERROR.getCode(),DragonErrorCodeEnum.TRADE_ALIPAY_QUERY_ERROR.getMessage());
}else if("40004".equals(resultMap.get("code"))&&"ACQ.TRADE_NOT_EXIST".equalsIgnoreCase(resultMap.get("subCode").toString())){
respDto.setStatus(Integer.valueOf(DragonConstant.PayStatusEnum.STATUS_UNPAID.getCode()));
}else{
throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_ALIPAY_QUERY_ERROR.getCode(),DragonErrorCodeEnum.TRADE_ALIPAY_QUERY_ERROR.getMessage());
}
return respDto;
}
}
package com.liquidnet.service.dragon.channel.strategy.impl;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.dragon.channel.strategy.annotation.StrategyPayChannelHandler;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import com.liquidnet.service.dragon.dto.DragonPayOrderQueryRespDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: PayChannelStrategyApplepayImpl
* @Package com.liquidnet.service.dragon.channel.strategy.impl
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/13 13:06
*/
@Slf4j
@Component
@StrategyPayChannelHandler(DragonConstant.PayChannelEnum.APPLEPAY)
public class PayChannelStrategyApplepayImpl extends AbstractPayChannelStrategyImpl {
@Override
public ResponseDto<DragonPayBaseRespDto> dragonPay(DragonPayBaseReqDto dragonPayBaseReqDto) {
return null;
}
@Override
public String dragonNotify(HttpServletRequest request,String payType,String deviceFrom) {
return null;
}
@Override
public DragonPayOrderQueryRespDto checkOrderStatus(String code) {
return null;
}
}
package com.liquidnet.service.dragon.channel.strategy.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.liquidnet.common.exception.LiquidnetServiceException;
import com.liquidnet.commons.lang.util.StringUtil;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.dragon.biz.DragonServiceCommonBiz;
import com.liquidnet.service.dragon.channel.douyinpay.strategy.DouYinayStrategyContext;
import com.liquidnet.service.dragon.channel.strategy.annotation.StrategyPayChannelHandler;
import com.liquidnet.service.dragon.channel.strategy.biz.DragonPayBiz;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.constant.DragonErrorCodeEnum;
import com.liquidnet.service.dragon.dto.DragonOrdersDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import com.liquidnet.service.dragon.dto.DragonPayOrderQueryRespDto;
import com.liquidnet.service.dragon.utils.DataUtilsDragon;
import com.liquidnet.service.dragon.utils.PayDouYinpayUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
/**
* @author zhangfuxin
* @Description: 抖音
* @date 2021/11/9 上午11:47
*/
@Slf4j
@Component
@StrategyPayChannelHandler(DragonConstant.PayChannelEnum.DOUYINPAY)
public class PayChannelStrategyDouYinImpl extends AbstractPayChannelStrategyImpl {
@Autowired
private DouYinayStrategyContext douYinayStrategyContext;
@Autowired
private DataUtilsDragon dataUtilsDragon;
@Autowired
private DragonServiceCommonBiz dragonServiceCommonBiz;
@Autowired
private DragonPayBiz dragonPayBiz;
@Override
public ResponseDto<DragonPayBaseRespDto> dragonPay(DragonPayBaseReqDto dragonPayBaseReqDto) {
return douYinayStrategyContext.getStrategy(dragonPayBaseReqDto.getDeviceFrom()).dragonPay(dragonPayBaseReqDto);
}
@Override
public String dragonNotify(HttpServletRequest request,String payType,String deviceFrom) {
JSONObject jsonObject=PayDouYinpayUtils.getJsonObject(request);
try {
log.info("dragonNotify-->douYinPay json : {}", JSON.toJSONString(jsonObject));
log.info("接收到{}支付结果{}", payType, JSON.toJSONString(jsonObject));
if(!jsonObject.getString("type").equals("payment")){
throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_PARAM_ERROR.getCode(),DragonErrorCodeEnum.TRADE_PARAM_ERROR.getMessage());
}
JSONObject msg=jsonObject.getJSONObject("msg");
// Map msg= (Map) map.get("msg");
String code =msg.get("cp_orderno").toString();
if(StringUtil.isBlank(code)){
throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_ERROR_NOT_EXISTS.getCode(),DragonErrorCodeEnum.TRADE_ERROR_NOT_EXISTS.getMessage());
}
//持久化通知记录
dragonServiceCommonBiz.createDragonOrderLogs(code,dragonPayBiz.getPaymentType(payType,deviceFrom),JSON.toJSONString(jsonObject));
// 根据银行订单号获取支付信息
DragonOrdersDto dragonOrdersDto = dataUtilsDragon.getPayOrderByCode(code);
if (dragonOrdersDto == null) {
throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_ERROR_NOT_EXISTS.getCode(),DragonErrorCodeEnum.TRADE_ERROR_NOT_EXISTS.getMessage());
}
if (DragonConstant.PayStatusEnum.STATUS_PAID.getCode().equals(dragonOrdersDto.getStatus())) {
throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_ERROR_HAS_PAID.getCode(),DragonErrorCodeEnum.TRADE_ERROR_HAS_PAID.getMessage());
}
String sign = jsonObject.get("msg_signature").toString();
boolean notifyResult = false;
if (PayDouYinpayUtils.getInstance().notifySign( sign,jsonObject)) {// 根据配置信息验证签名
//抖音回调 就代表成功了
this.completeSuccessOrder(dragonOrdersDto,null, LocalDateTime.now(), JSON.toJSONString(jsonObject));
/*if (WepayConstant.WeixinTradeStateEnum.SUCCESS.getCode().equals(notifyMap.get("result_code"))) {// 业务结果
// 成功
notifyResult = this.completeSuccessOrder(dragonOrdersDto, notifyMap.get("transaction_id"), timeEnd, notifyMap.toString());
} else {
notifyResult = this.completeFailOrder(dragonOrdersDto, notifyMap.toString());
}
if(notifyResult){
returnStr = "<xml>\n" + " <return_code><![CDATA[SUCCESS]]></return_code>\n" + " <return_msg><![CDATA[OK]]></return_msg>\n" + "</xml>";
}*/
return "{\"err_no\": 0,\"err_tips\": \"success\"}";
} else {
log.error("touyin notify fail code:{} msg:{} ",DragonErrorCodeEnum.TRADE_DOUYINPAY_SIGN_ERROR.getCode(),DragonErrorCodeEnum.TRADE_DOUYINPAY_SIGN_ERROR.getMessage());
}
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
@Override
public DragonPayOrderQueryRespDto checkOrderStatus(String code) {
DragonOrdersDto ordersDto = dataUtilsDragon.getPayOrderByCode(code);
DragonPayOrderQueryRespDto respDto = douYinayStrategyContext.getStrategy(DragonConstant.PayTypeEnum.getEnumByCode(ordersDto.getPaymentType()).getDeviceFrom()).checkOrderStatus(code);
return respDto;
}
}
package com.liquidnet.service.dragon.channel.strategy.impl;
import com.alibaba.fastjson.JSON;
import com.liquidnet.common.exception.LiquidnetServiceException;
import com.liquidnet.commons.lang.util.StringUtil;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.dragon.biz.DragonServiceCommonBiz;
import com.liquidnet.service.dragon.channel.strategy.annotation.StrategyPayChannelHandler;
import com.liquidnet.service.dragon.channel.strategy.biz.DragonPayBiz;
import com.liquidnet.service.dragon.channel.unionpay.biz.UnionpayBiz;
import com.liquidnet.service.dragon.channel.unionpay.sdk.AcpService;
import com.liquidnet.service.dragon.channel.unionpay.sdk.SDKConstants;
import com.liquidnet.service.dragon.channel.unionpay.strategy.UnionpayStrategyContext;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.constant.DragonErrorCodeEnum;
import com.liquidnet.service.dragon.dto.DragonOrdersDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import com.liquidnet.service.dragon.dto.DragonPayOrderQueryRespDto;
import com.liquidnet.service.dragon.service.impl.DragonOrderRefundsServiceImpl;
import com.liquidnet.service.dragon.utils.DataUtilsDragon;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Map;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: PayChannelStrategyUnionpayImpl
* @Package com.liquidnet.service.dragon.channel.strategy.impl
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/11/08 18:06
*/
@Slf4j
@Component
@StrategyPayChannelHandler(DragonConstant.PayChannelEnum.UNIONPAY)
public class PayChannelStrategyUnionpayImpl extends AbstractPayChannelStrategyImpl {
@Autowired
private UnionpayStrategyContext unionpayStrategyContext;
@Autowired
private DataUtilsDragon dataUtilsDragon;
@Autowired
private UnionpayBiz unionpayBiz;
@Autowired
private DragonPayBiz dragonPayBiz;
@Autowired
private DragonServiceCommonBiz dragonServiceCommonBiz;
@Autowired
private DragonOrderRefundsServiceImpl dragonOrderRefundsService;
@Autowired
private AcpService acpService;
@Override
public ResponseDto<DragonPayBaseRespDto> dragonPay(DragonPayBaseReqDto dragonPayBaseReqDto) {
return unionpayStrategyContext.getStrategy(dragonPayBaseReqDto.getDeviceFrom()).dragonPay(dragonPayBaseReqDto);
}
@Override
public String dragonNotify(HttpServletRequest request,String payType,String deviceFrom) {
log.info("unionpay-->notify-->begin payType:{} deviceFrom:{}",payType,deviceFrom);
try {
String encoding = request.getParameter(SDKConstants.param_encoding);
Map<String , String> notifyMap = unionpayBiz.parseNotifyMsg(request);
log.info("dragonNotify-->unionpay json : {}", JSON.toJSONString(notifyMap));
log.info("接收到{}支付结果{}", payType, notifyMap);
//商户订单号
String code =notifyMap.get("orderId"); //获取后台通知的数据
if(StringUtil.isBlank(code)){
throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_ERROR_NOT_EXISTS.getCode(),DragonErrorCodeEnum.TRADE_ERROR_NOT_EXISTS.getMessage());
}
//持久化通知记录
dragonServiceCommonBiz.createDragonOrderLogs(code,dragonPayBiz.getPaymentType(payType,deviceFrom),JSON.toJSONString(notifyMap));
// 根据银行订单号获取支付信息
DragonOrdersDto dragonOrdersDto = dataUtilsDragon.getPayOrderByCode(code);
if (dragonOrdersDto == null) {
throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_ERROR_NOT_EXISTS.getCode(),DragonErrorCodeEnum.TRADE_ERROR_NOT_EXISTS.getMessage());
}
if (DragonConstant.PayStatusEnum.STATUS_PAID.getCode().equals(dragonOrdersDto.getStatus())) {
throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_ERROR_HAS_PAID.getCode(),DragonErrorCodeEnum.TRADE_ERROR_HAS_PAID.getMessage());
}
boolean notifyResult = false;
//1、验证签名
if (acpService.validate(notifyMap, encoding)) {
//判断respCode=00、A6后,对涉及资金类的交易,请再发起查询接口查询,确定交易成功后更新数据库。
//因发现00 是成功 a6为有缺陷的成功,所以如果是a6则要再查一下
boolean result=false;
if(notifyMap.get("respCode").equals("A6")){
//此处需要发起查询接口,要看下最终状态,等查询接口完毕后再写
result=true;
}else if (notifyMap.get("respCode").equals("00")){
result =true;
}else{
result =false;
}
if(result){
notifyResult = this.completeSuccessOrder(dragonOrdersDto, notifyMap.get("queryId"), LocalDateTime.now(), notifyMap.toString());
}else{
notifyResult = this.completeFailOrder(dragonOrdersDto, notifyMap.toString());
}
}else{
log.error("unionPay notify fail code:{} msg:{} ",DragonErrorCodeEnum.TRADE_UNIONPAY_SIGN_ERROR.getCode(),DragonErrorCodeEnum.TRADE_UNIONPAY_SIGN_ERROR.getMessage());
}
}catch (Exception e){
e.printStackTrace();
}
return "ok";
}
@Override
public DragonPayOrderQueryRespDto checkOrderStatus(String code) {
// 查看是哪个deviceForm 的支付
DragonOrdersDto ordersDto = dataUtilsDragon.getPayOrderByCode(code);
DragonPayOrderQueryRespDto respDto = unionpayStrategyContext.getStrategy(DragonConstant.PayTypeEnum.getEnumByCode(ordersDto.getPaymentType()).getDeviceFrom()).checkOrderStatus(code);
/* if(null==ordersDto){
throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_UNIONPAY_QUERY_ERROR.getCode(),DragonErrorCodeEnum.TRADE_UNIONPAY_QUERY_ERROR.getMessage());
}
DragonPayOrderQueryRespDto respDto = dragonPayBiz.buildPayOrderQueryRespDto(ordersDto);
*/
return respDto;
}
}
package com.liquidnet.service.dragon.channel.strategy.impl;
import com.alibaba.fastjson.JSON;
import com.liquidnet.common.exception.LiquidnetServiceException;
import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.commons.lang.util.StringUtil;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.dragon.biz.DragonServiceCommonBiz;
import com.liquidnet.service.dragon.channel.strategy.annotation.StrategyPayChannelHandler;
import com.liquidnet.service.dragon.channel.strategy.biz.DragonPayBiz;
import com.liquidnet.service.dragon.channel.wepay.constant.WepayConstant;
import com.liquidnet.service.dragon.channel.wepay.strategy.WepayStrategyContext;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.constant.DragonErrorCodeEnum;
import com.liquidnet.service.dragon.dto.DragonOrdersDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import com.liquidnet.service.dragon.dto.DragonPayOrderQueryRespDto;
import com.liquidnet.service.dragon.utils.DataUtilsDragon;
import com.liquidnet.service.dragon.utils.PayWepayUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: PayChannelStrategyWepayImpl
* @Package com.liquidnet.service.dragon.channel.strategy.impl
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/13 13:06
*/
@Slf4j
@Component
@StrategyPayChannelHandler(DragonConstant.PayChannelEnum.WEPAY)
public class PayChannelStrategyWepayImpl extends AbstractPayChannelStrategyImpl {
@Autowired
private WepayStrategyContext wepayStrategyContext;
@Autowired
private DataUtilsDragon dataUtilsDragon;
@Autowired
private DragonServiceCommonBiz dragonServiceCommonBiz;
@Autowired
private DragonPayBiz dragonPayBiz;
@Override
public ResponseDto<DragonPayBaseRespDto> dragonPay(DragonPayBaseReqDto dragonPayBaseReqDto) {
return wepayStrategyContext.getStrategy(dragonPayBaseReqDto.getDeviceFrom()).dragonPay(dragonPayBaseReqDto);
}
@Override
public String dragonNotify(HttpServletRequest request,String payType,String deviceFrom) {
String returnStr = "<xml>\n" + " <return_code><![CDATA[FAIL]]></return_code>\n" + " <return_msg><![CDATA[FAIL]]></return_msg>\n" + "</xml>";;
try {
InputStream inputStream = request.getInputStream();// 从request中取得输入流
Map<String, String> notifyMap = new HashMap<String, String>();
try {
notifyMap = PayWepayUtils.parseXml(inputStream);
log.info("dragonNotify-->wepay json : {}", JSON.toJSONString(notifyMap));
log.info("接收到{}支付结果{}", payType, notifyMap);
String code = notifyMap.get("out_trade_no");
if(StringUtil.isBlank(code)){
throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_ERROR_NOT_EXISTS.getCode(),DragonErrorCodeEnum.TRADE_ERROR_NOT_EXISTS.getMessage());
}
//持久化通知记录
dragonServiceCommonBiz.createDragonOrderLogs(code,dragonPayBiz.getPaymentType(payType,deviceFrom),JSON.toJSONString(notifyMap));
// 根据银行订单号获取支付信息
DragonOrdersDto dragonOrdersDto = dataUtilsDragon.getPayOrderByCode(code);
if (dragonOrdersDto == null) {
throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_ERROR_NOT_EXISTS.getCode(),DragonErrorCodeEnum.TRADE_ERROR_NOT_EXISTS.getMessage());
}
if (DragonConstant.PayStatusEnum.STATUS_PAID.getCode().equals(dragonOrdersDto.getStatus())) {
throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_ERROR_HAS_PAID.getCode(),DragonErrorCodeEnum.TRADE_ERROR_HAS_PAID.getMessage());
}
String sign = notifyMap.remove("sign");
boolean notifyResult = false;
if (PayWepayUtils.getInstance().notifySign(notifyMap, sign)) {// 根据配置信息验证签名
if (WepayConstant.WeixinTradeStateEnum.SUCCESS.getCode().equals(notifyMap.get("result_code"))) {// 业务结果
// 成功
String timeEndStr = notifyMap.get("time_end");
LocalDateTime timeEnd = null;
if (!StringUtil.isEmpty(timeEndStr)) {
timeEnd = DateUtil.Formatter.yyyyMMddHHmmssTrim.parse(timeEndStr);
}
notifyResult = this.completeSuccessOrder(dragonOrdersDto, notifyMap.get("transaction_id"), timeEnd, notifyMap.toString());
} else {
notifyResult = this.completeFailOrder(dragonOrdersDto, notifyMap.toString());
}
if(notifyResult){
returnStr = "<xml>\n" + " <return_code><![CDATA[SUCCESS]]></return_code>\n" + " <return_msg><![CDATA[OK]]></return_msg>\n" + "</xml>";
}
} else {
log.error("wepay notify fail code:{} msg:{} ",DragonErrorCodeEnum.TRADE_WEPAY_SIGN_ERROR.getCode(),DragonErrorCodeEnum.TRADE_WEPAY_SIGN_ERROR.getMessage());
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
return returnStr;
}
@Override
public DragonPayOrderQueryRespDto checkOrderStatus(String code) {
DragonOrdersDto ordersDto = dataUtilsDragon.getPayOrderByCode(code);
DragonPayOrderQueryRespDto respDto = wepayStrategyContext.getStrategy(DragonConstant.PayTypeEnum.getEnumByCode(ordersDto.getPaymentType()).getDeviceFrom()).checkOrderStatus(code);
return respDto;
}
}
package com.liquidnet.service.dragon.channel.unionpay.constant;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: UnionpayConstant
* @Package com.liquidnet.service.dragon.channel.unionpay.constant
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/11/8 18:12
*/
public class UnionpayConstant {
//默认配置的是UTF-8
public static String encoding = "UTF-8";
public enum UnionTradeStateEnum {
TRADE_CLOSED ("TRADE_CLOSED","交易关闭"),
TRADE_FINISHED ("TRADE_FINISHED","支付完成"),
TRADE_DEFECTIVENESS_SUCCESS ("A6","有缺陷的成功"),
TRADE_SUCCESS ("00","支付成功"),
WAIT_BUYER_PAY ("WAIT_BUYER_PAY","交易创建"),
FAIL("01","支付失败");
private String code;
private String message;
UnionTradeStateEnum(String code, String message) {
this.code = code;
this.message = message;
}
public String getCode() {
return code;
}
}
}
package com.liquidnet.service.dragon.channel.unionpay.req;
import lombok.Data;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: UnionpayBaseReq
* @Package com.liquidnet.service.dragon.channel.unionpay.req
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/11/10 11:20
*/
@Data
public class UnionpayBaseReq {
/***银联全渠道系统,产品参数***/
private String version;
private String encoding;
private String signMethod;
private String txnType;
private String txnSubType;
private String bizType;
private String channelType;
/***商户接入参数***/
private String merId;
private String accessType;
private String orderId;
private String txnTime;
private String txnAmt;
private String currencyCode;
private String backUrl;
/***app支付接入***/
private String accType; //
/***wap支付接入***/
private String riskRateInfo;
private String frontUrl;
private String payTimeout;
}
package com.liquidnet.service.dragon.channel.unionpay.req;
import com.alibaba.fastjson.JSON;
import lombok.Data;
import java.io.Serializable;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: UnionpayTradePayReq
* @Package com.liquidnet.service.dragon.channel.unionpay.req
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/9 17:50
*/
@Data
public class UnionpayTradePayReq extends UnionpayBaseReq implements Serializable, Cloneable{
private static final long serialVersionUID = -5827961038383330701L;
@Override
public String toString(){
return JSON.toJSONString(this);
}
private static final UnionpayTradePayReq obj = new UnionpayTradePayReq();
public static UnionpayTradePayReq getNew() {
try {
return (UnionpayTradePayReq) obj.clone();
} catch (CloneNotSupportedException e) {
return new UnionpayTradePayReq();
}
}
}
package com.liquidnet.service.dragon.channel.unionpay.sdk;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import java.io.IOException;
import java.security.PublicKey;
import java.util.Map;
/**
* @ClassName Acp6Service
* @Description 全渠道6.0接口服务类,接入商户集成请可以直接参考使用本类中的方法
* @date 2020/03
*/
@Slf4j
public class Acp6Service {
@Autowired
private SDKConfig sdkConfig;
@Autowired
private CertUtil certUtil;
@Autowired
private SDKUtil sdkUtil;
/**
* 请求报文签名(使用配置文件中配置的私钥证书或者对称密钥签名)<br>
* 功能:对请求报文进行签名,并计算赋值certid,signature字段并返回<br>
* @param reqData 请求报文map<br>
* @param encoding 上送请求报文域encoding字段的值<br>
* @return 签名后的map对象<br>
*/
public Map<String, String> sign(Map<String, String> reqData,String encoding) {
return signByCertInfo(reqData, sdkConfig.getSignCertPath(), sdkConfig.getSignCertPwd(), encoding);
}
/**
* 多证书签名(通过传入私钥证书路径和密码签名)<br>
* 功能:如果有多个商户号接入银联,每个商户号对应不同的证书可以使用此方法:传入私钥证书和密码(并且在acp_sdk.properties中 配置 acpsdk.singleMode=false)<br>
* @param reqData 请求报文map<br>
* @param certPath 签名私钥文件(带路径)<br>
* @param certPwd 签名私钥密码<br>
* @param encoding 上送请求报文域encoding字段的值<br>
* @return 签名后的map对象<br>
*/
public Map<String, String> signByCertInfo(Map<String, String> reqData, String certPath,
String certPwd, String encoding) {
Map<String, String> data = SDKUtil.filterBlank(reqData);
if (SDKUtil.isEmpty(encoding)) {
encoding = "UTF-8";
}
if (SDKUtil.isEmpty(certPath) || SDKUtil.isEmpty(certPwd)) {
log.error("CertPath or CertPwd is empty");
return data;
}
try {
data.put(SDKConstants.param_certId, certUtil.getCertIdByKeyStoreMap(certPath, certPwd));
data.put(SDKConstants.param_signature, sdkUtil.signRsa2(data, certPath, certPwd, encoding));
return data;
} catch (Exception e) {
log.error("Sign Error", e);
return data;
}
}
/**
* 验证签名<br>
* @param data 返回报文数据<br>
* @param encoding 上送请求报文域encoding字段的值<br>
* @return true 通过 false 未通过<br>
*/
public boolean validate(Map<String, String> data, String encoding) {
log.info("验签处理开始");
if (SDKUtil.isEmpty(encoding)) {
encoding = "UTF-8";
}
String certId = data.get(SDKConstants.param_certId);
log.info("对返回报文串验签使用的验签公钥序列号:[" + certId + "]");
PublicKey verifyKey = certUtil.getValidatePublicKey(certId);
if(verifyKey == null) {
log.error("未找到此序列号证书。");
return false;
}
try {
boolean result = SDKUtil.verifyRsa2(data, verifyKey, encoding);
log.info("验签" + (result ? "成功" : "失败") + "。");
return result;
} catch (Exception e) {
log.error(e.getMessage(), e);
return false;
}
}
/**
* 获取应答报文中的加密公钥证书,并存储到本地,备份原始证书,并自动替换证书<br>
* 更新成功则返回1,无更新返回0,失败异常返回-1<br>
* @return
*/
public int updateEncryptCert(String strCert, String certType) {
return sdkUtil.updateEncryptCert(strCert, certType);
}
/**
* 密码加密并做base64<br>
* @param accNo 卡号<br>
* @param pin 密码<br>
* @param encoding<br>
* @return 加密的内容<br>
*/
public String encryptPin(String accNo, String pin, String encoding) {
byte[] pinblock = SecureUtil.pinblock(accNo, pin);
return Base64.encodeBase64String(SecureUtil.encrypt(certUtil.getPinEncryptCert().pubKey, pinblock));
}
// /**
// * 密码加密并做base64<br>
// * @param accNo 卡号<br>
// * @param pin 密码<br>
// * @param encoding<br>
// * @return 加密的内容<br>
// */
// public String encryptPin(String pin, String encoding) {
// byte[] pinblock = SecureUtil.pinblock(pin);
// return Base64.encodeBase64String(SecureUtil.encrypt(CertUtil.getPinEncryptCert().pubKey, pinblock));
// }
/**
* 敏感信息加密并做base64(卡号,手机号,cvn2,有效期)<br>
* @param data 送 phoneNo,cvn2,有效期<br>
* @param encoding<br>
* @return 加密的密文<br>
*/
public String encryptData(String data, String encoding) {
return this.encryptData(data, encoding);
}
/**
* @param data 明文<br>
* @return 加密的密文<br>
*/
public String encryptData(byte[] data) {
try {
return Base64.encodeBase64String(SecureUtil.encrypt(certUtil.getEncryptCert().pubKey, data));
} catch (Exception e) {
log.error(e.getMessage(), e);
return null;
}
}
/**
* @param data 明文<br>
* @return 加密的密文<br>
*/
public String tripleDesEncryptECBPKCS5Padding(byte[] key, byte[] data) {
try {
return Base64.encodeBase64String(SecureUtil.tripleDesEncryptECBPKCS5Padding(key, SecureUtil.rightPadZero(data, 8)));
} catch (Exception e) {
log.error(e.getMessage(), e);
return null;
}
}
/**
* 敏感信息解密,使用配置文件acp_sdk.properties解密<br>
* @param base64EncryptedInfo 加密信息<br>
* @param encoding<br>
* @return 解密后的明文<br>
*/
public String decryptData(String base64EncryptedInfo, String encoding) {
return this.decryptData(base64EncryptedInfo, encoding);
}
/**
* 敏感信息解密,通过传入的私钥解密<br>
* @param base64EncryptedInfo 加密信息<br>
* @param certPath 私钥文件(带全路径)<br>
* @param certPwd 私钥密码<br>
* @param encoding<br>
* @return
*/
public String decryptData(String base64EncryptedInfo, String certPath,
String certPwd, String encoding) {
return this.decryptData(base64EncryptedInfo, certPath, certPwd, encoding);
}
/**
* 获取敏感信息加密证书的物理序列号<br>
* @return
*/
public String getEncryptCertId(){
return certUtil.getEncryptCert().certId;
}
/**
* 获取敏感信息加密证书的物理序列号<br>
* @return
*/
public String getPinEncryptCertId(){
return certUtil.getPinEncryptCert().certId;
}
/**
* 功能:后台交易提交请求报文并接收同步应答报文<br>
* @param reqData 请求报文<br>
* @param reqUrl 请求地址<br>
* @param encoding<br>
* @return 应答http 200返回true ,其他false<br>
*/
public Map<String,String> post(Map<String, String> reqData, String reqUrl,String encoding) {
if(reqData == null || reqUrl == null) {
log.error("null input");
return null;
}
log.info("请求银联地址:" + reqUrl + ",请求参数:" + reqData.toString());
if(reqUrl.startsWith("https://") && !sdkConfig.isIfValidateRemoteCert()) {
reqUrl = "u" + reqUrl;
}
try{
byte[] respBytes = HttpsUtil.post(reqUrl, SDKUtil.createLinkString(reqData, false, true, encoding).getBytes(encoding));
if(respBytes == null) {
log.error("post失败");
return null;
}
Map<String,String> result = SDKUtil.parseQString(new String(respBytes, encoding), encoding);
log.info("应答参数:" + result);
return result;
} catch (Exception e) {
log.error("post失败:" + e.getMessage(), e);
return null;
}
}
/**
* 功能:后台交易提交请求报文并接收同步应答报文<br>
* @param reqData 请求报文<br>
* @param reqUrl 请求地址<br>
* @param encoding<br>
* @return 应答http 200返回true ,其他false<br>
*/
public String postNotice(Map<String, String> reqData, String reqUrl,String encoding) {
if(reqData == null || reqUrl == null) {
log.error("null input");
return null;
}
log.info("请求银联地址:" + reqUrl + ",请求参数:" + reqData.toString());
if(reqUrl.startsWith("https://") && !sdkConfig.isIfValidateRemoteCert()) {
reqUrl = "u" + reqUrl;
}
try{
byte[] respBytes = HttpsUtil.post(reqUrl, SDKUtil.createLinkString(reqData, false, true, encoding).getBytes(encoding));
if(respBytes == null) {
log.error("post失败");
return null;
}
String result = new String(respBytes, encoding);
log.info("应答体:" + result);
return result;
} catch (Exception e) {
log.error("post失败:" + e.getMessage(), e);
return null;
}
}
/**
* 对字符串做base64<br>
* @param rawStr<br>
* @param encoding<br>
* @return<br>
* @throws IOException
*/
public String base64Encode(String rawStr, String encoding){
return AcpService.base64Encode(rawStr, encoding);
}
/**
* 对字符串做base64<br>
* @param base64Str<br>
* @param encoding<br>
* @return<br>
* @throws IOException
*/
public String base64Decode(String base64Str, String encoding){
return AcpService.base64Decode(base64Str, encoding);
}
}
【哪个sdk新就用哪个哦】【不完全向下兼容注意】
2020/9/29:
增加应答只需要关心200的post。
2020/6/23:
规范大改了,请参考最新规范进行修改。
1. 应答新增returnMsg,调整了应答码和交易状态相关字段。具体的值见规范。
目前使用的:
1)returnCode:代表此次交易请求的业务结果,查询交易表示查询操作的业务结果,具体交易结果,以交易应答码、交易状态码为准。
2)respCode:交易结果应答码。
3)xxxStatus:各类交易的状态
① transferStatus-转账状态,仅转账交易出现
② billStatus-账单状态,仅缴费交易用
③ entryStatus-入账状态,入账状态查询用
④ transStatus-消费/预授权交易的状态,仅消费和预授权查询和通知用
已删除的:resultCode、transCode、transMsg。
2. 应答新增merTransIndex,查询接口会原样应答,但目前并没有往发卡或者二维码的付款方送,大概没别的作用。
3. 应答新增preAuthId,没什么用,如果需要收单手工帮你处理预授权进行撤销或完成时可用提供他们,可方便他们处理。卡号+商户号+preAuthId在预授权超时或结束(完成或撤销)前是唯一的。
4. 新增respCode、transStatus取值TRANS_PRE_AUTH_COMPLETED,表示已被预授权完成。
5. 查询应答新增transStatus字段表示被查询的原交易的状态。
6. respCode和respMsg下沉到bizContent中.
7. traceNo和traceTime替换成清算主键settleKey,settleKey在收单和发卡的清算文件内是唯一的,可用于和收单对账,以及找银联和发卡查交易。
8. merCertId、cupCertId改为certId。
9. accessId:填写商户号。
10. accessType填写0。
11. 订单号、交易时间、商户代码从公共参数下沉到bizContent中。
12. 增加入账状态状态查询接口。
13. 转账交易termId从必填M改成可选O。
14. 两方转账也返回transferStatus。
2020/4/29:
6.0接口地址修正最终版,注意获取地址方式改getTransUrl,配置文件增加acpsdk.transUrl=https://gateway.test.95516.com/api/trans.do。
2020/4/4:
不完全向下兼容,注意对应修改,修改后的样例可参考assets/sdk测试类.
修改后:
全渠道5.0、5.1用AcpService。
全渠道6.0用Acp6Service。
二维码用QrcService。。
LogUtil删除,请改成直接调log4j或slf4j打印。
原二维码DemoBase中:
DemoBase.getAddnCond->QrcService.getKVBase64Field
DemoBase.formInfoBase64->QrcService.getKVBase64Field
DemoBase.getPayeeInfo->QrcService.getKVBase64Field
DemoBase.getPayeeInfoWithEncrpyt->QrcService.getKVEncBase64Field
DemoBase.getPayerInfo->QrcService.getKVBase64Field
DemoBase.getPayerInfoWithEncrpyt->QrcService.getKVEncBase64Field
\ No newline at end of file
package com.liquidnet.service.dragon.channel.unionpay.strategy;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import com.liquidnet.service.dragon.dto.DragonPayOrderQueryRespDto;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: Test
* @Package com.liquidnet.service.dragon.channel.strategy
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/10 14:27
*/
public interface IUnionpayStrategy {
ResponseDto<DragonPayBaseRespDto> dragonPay(DragonPayBaseReqDto dragonPayBaseReqDto);
DragonPayOrderQueryRespDto checkOrderStatus(String code);
}
package com.liquidnet.service.dragon.channel.unionpay.strategy;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: Test
* @Package com.liquidnet.service.dragon.channel.strategy
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/10 14:27
*/
@Component
public class UnionpayStrategyContext {
private final Map<String, IUnionpayStrategy> handlerMap = new HashMap<>();
public IUnionpayStrategy getStrategy(String type) {
return handlerMap.get(type);
}
public void putStrategy(String code, IUnionpayStrategy strategy) {
handlerMap.put(code, strategy);
}
}
package com.liquidnet.service.dragon.channel.unionpay.strategy;
import com.liquidnet.service.dragon.channel.unionpay.strategy.annotation.StrategyUnionpayHandler;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: Test
* @Package com.liquidnet.service.dragon.channel.strategy
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/10 14:27
*/
@Component
public class UnionpayStrategyListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
Map<String, Object> beans = event.getApplicationContext().getBeansWithAnnotation(StrategyUnionpayHandler.class);
UnionpayStrategyContext strategyContext = event.getApplicationContext().getBean(UnionpayStrategyContext.class);
beans.forEach((name, bean) -> {
StrategyUnionpayHandler typeHandler = bean.getClass().getAnnotation(StrategyUnionpayHandler.class);
strategyContext.putStrategy(typeHandler.value().getCode(), (IUnionpayStrategy) bean);
});
}
}
\ No newline at end of file
package com.liquidnet.service.dragon.channel.unionpay.strategy.annotation;
import com.liquidnet.service.dragon.constant.DragonConstant;
import java.lang.annotation.*;
/**
* @author AnJiabin <jiabin.an@lightnet.io>
* @version V1.0
* @Description: TODO
* @class: StrategyUnionpayHandler
* @Package com.liquidnet.service.dragon.channel.unionpay.strategy.annotation
* @Copyright: LightNet @ Copyright (c) 2020
* @date 2020/11/08 15:29
*/
@Documented
@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface StrategyUnionpayHandler {
DragonConstant.DeviceFromEnum value();
}
package com.liquidnet.service.dragon.channel.wepay.resp;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.Data;
@Data
@XStreamAlias("xml")
public class WePayRefundReturnCallBackDto {
@XStreamAlias("return_code")
private String returnCode;
@XStreamAlias("return_msg")
private String returnMsg;
@XStreamAlias("appid")
private String appId;
@XStreamAlias("mch_id")
private String mchId;
@XStreamAlias("nonce_str")
private String nonceStr;
@XStreamAlias("req_info")
private String reqInfo;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment