mirror of
https://gitee.com/dromara/dax-pay.git
synced 2025-09-05 20:18:22 +00:00
feat 签名算法支持嵌套参数优化, 新增支付演示模块
This commit is contained in:
@@ -1,21 +1,16 @@
|
|||||||
# CHANGELOG
|
# CHANGELOG
|
||||||
## [v1.0.1] 支付之路: 多商户适配
|
## [v2.0.0]
|
||||||
- 新增: 钱包支持多商户和多应用
|
- 支持请求参数签名和验签机制,已经支持SHA256和
|
||||||
- 新增: 储值卡支持多商户和多应用
|
- 去除调用时的用户概念,作为独立的支付网关使用
|
||||||
- 新增: 网关同步记录进行保存
|
- 支持支付功能、已对支付宝、微信进行支持
|
||||||
- 新增: 钱包支持设置开通时的默认金额
|
- 支持支付订单超时自动进行关闭
|
||||||
- 新增: 储值卡多卡支付演示
|
- 支持支付订单关闭功能,关闭
|
||||||
- 优化: 结算台支持多商户
|
- 支持支付退款功能,可以进行全部退款或部分退款
|
||||||
- 优化: 重构支付消息通知结构, 使后期支持多种消息中间件
|
- 支持支付同步功能,通过同步接口可以获取第三方支付网关的状态
|
||||||
- 优化: 拆分网关同步相关代码
|
- 支持支付和退款订单的修复功能,根据取第三方支付网关订单的状态,对订单进行修正,如支付同步、退款同步、消息回调等可触发
|
||||||
- 优化: 保存各渠道的支付单
|
- 部分支付对账功能,已经实现支付宝和微信对账单下载解析和保存的功能
|
||||||
|
- 支持对各支付通道进行管理,包括是否启用、显示Logo图等
|
||||||
## [v1.0.0] 支付之路
|
- 支持对支付网关对外暴露的接口进行管理,支持启停用、是否验签、是否消息通知等功能
|
||||||
- 支持单渠道支付、聚合支付、组合支付、退款功能
|
- 组合支付已预先进行支持,支持一个异步支付+多个同步支付通道组合进行收单支付
|
||||||
- 单渠道支付:支持支付宝、微信、现金、钱包、储值卡等多种支付方式
|
- 提供Java版本SDK,简化业务系统对支付网关的调用
|
||||||
- 聚合支付:支持微信或支付宝使用同一个码
|
- 对回调记录、同步记录、修复记录、关闭记录、进行报错
|
||||||
- 组合支付:支持多种同步支付和一个异步支付(微信、支付宝)进行组合支付
|
|
||||||
- 支持退款:部分对款、全部退款等方式
|
|
||||||
- 储值卡:支持单卡支付、多卡支付,退款时支持退款到原储值卡中,也支持将余额退到同一个卡上
|
|
||||||
- 支付宝:支持web支付、wap支付、扫码支付、付款码支付、APP支付
|
|
||||||
- 微信:wap支付、扫码支付、付款码支付、APP支付、公众号/小程序支付
|
|
||||||
|
@@ -1,10 +1,15 @@
|
|||||||
|
2.0.1 里程碑
|
||||||
|
- 支持各类回调通知
|
||||||
|
- 现金、钱包、储值卡功能进行重构
|
||||||
|
-
|
||||||
|
|
||||||
2.0.0 重构进度
|
2.0.0 重构进度
|
||||||
- 已经完成的
|
- 已经完成的
|
||||||
- [x] 参数签名和验签机制
|
- [x] 参数签名和验签机制
|
||||||
- [x] 开放接口供第三方调用
|
- [x] 开放接口供第三方调用
|
||||||
- [x] 将零散的上下文对象进行抽取为统一的上下文对象
|
- [x] 将零散的上下文对象进行抽取为统一的上下文对象
|
||||||
- [x] 拆分原有的策略类,实现粒度更细
|
- [x] 拆分原有的策略类,实现粒度更细
|
||||||
- [x] 去除用户概念,作为独立的支付网关使用, 不与其他系统产生耦合性
|
- [x] 去除用户概念,作为独立的支付网关使用,不与其他系统产生耦合性
|
||||||
- 2023-12-31:
|
- 2023-12-31:
|
||||||
- [x] 支付关闭相关逻辑
|
- [x] 支付关闭相关逻辑
|
||||||
- [x] 各支付通道补充相关未实现的逻辑
|
- [x] 各支付通道补充相关未实现的逻辑
|
||||||
@@ -55,7 +60,7 @@
|
|||||||
- 2024-01-13:
|
- 2024-01-13:
|
||||||
- [x] (前端) 微信/支付宝支付通道配置
|
- [x] (前端) 微信/支付宝支付通道配置
|
||||||
- [x] 支付通道支持停用
|
- [x] 支付通道支持停用
|
||||||
- [x] 请求支付网关时区退款号以R开头, 用于与支付ID的区分
|
- [x] ~~请求支付网关时区退款号以R开头, 用于与支付ID的区分~~
|
||||||
- [x] (前端) 平台配置
|
- [x] (前端) 平台配置
|
||||||
- 2024-01-15:
|
- 2024-01-15:
|
||||||
- [x] 优化支付相关订单和记录的查询条件
|
- [x] 优化支付相关订单和记录的查询条件
|
||||||
|
43
daxpay-single-demo/pom.xml
Normal file
43
daxpay-single-demo/pom.xml
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>cn.bootx.platform</groupId>
|
||||||
|
<artifactId>dax-pay</artifactId>
|
||||||
|
<version>2.0.0</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>daxpay-single-demo</artifactId>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!-- lombok -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Bootx Platform 基础API -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.bootx.platform</groupId>
|
||||||
|
<artifactId>service-baseapi</artifactId>
|
||||||
|
<version>${bootx-platform.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 支付SDK 结算台 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.bootx.platform</groupId>
|
||||||
|
<artifactId>daxpay-single-sdk</artifactId>
|
||||||
|
<version>2.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
@@ -0,0 +1,12 @@
|
|||||||
|
package cn.bootx.platform.daxpay.demo;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付演示模块
|
||||||
|
* @author xxm
|
||||||
|
* @since 2024/2/8
|
||||||
|
*/
|
||||||
|
@ComponentScan
|
||||||
|
public class DaxPaySingleDemoApp {
|
||||||
|
}
|
@@ -0,0 +1,28 @@
|
|||||||
|
package cn.bootx.platform.daxpay.demo.config;
|
||||||
|
|
||||||
|
import cn.bootx.platform.daxpay.sdk.code.SignTypeEnum;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 演示模块配置类
|
||||||
|
* @author xxm
|
||||||
|
* @since 2024/2/8
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ConfigurationProperties(prefix = "dax-pay.demo")
|
||||||
|
public class DaxPayDemoProperties {
|
||||||
|
/** 服务地址 */
|
||||||
|
private String serverUrl;
|
||||||
|
|
||||||
|
/** 签名方式 */
|
||||||
|
private SignTypeEnum signType = SignTypeEnum.MD5;
|
||||||
|
|
||||||
|
/** 签名秘钥 */
|
||||||
|
private String signSecret;
|
||||||
|
|
||||||
|
/** 请求超时时间 */
|
||||||
|
private int reqTimeout = 30000;
|
||||||
|
}
|
@@ -0,0 +1,37 @@
|
|||||||
|
package cn.bootx.platform.daxpay.demo.config;
|
||||||
|
|
||||||
|
import cn.bootx.platform.daxpay.sdk.net.DaxPayConfig;
|
||||||
|
import cn.bootx.platform.daxpay.sdk.net.DaxPayKit;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.boot.context.event.ApplicationStartedEvent;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.event.EventListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化
|
||||||
|
* @author xxm
|
||||||
|
* @since 2024/2/8
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@EnableConfigurationProperties(DaxPayDemoProperties.class)
|
||||||
|
public class DaxPayKitConfiguration {
|
||||||
|
|
||||||
|
private final DaxPayDemoProperties daxPayDemoProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化
|
||||||
|
*/
|
||||||
|
@EventListener(ApplicationStartedEvent.class)
|
||||||
|
// @EventListener(webstarteve.class)
|
||||||
|
public void initDaxPayKit(){
|
||||||
|
DaxPayConfig config = DaxPayConfig.builder()
|
||||||
|
.serviceUrl(daxPayDemoProperties.getServerUrl())
|
||||||
|
.signType(daxPayDemoProperties.getSignType())
|
||||||
|
.signSecret(daxPayDemoProperties.getSignSecret())
|
||||||
|
.reqTimeout(daxPayDemoProperties.getReqTimeout())
|
||||||
|
.build();
|
||||||
|
DaxPayKit.initConfig(config);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,39 @@
|
|||||||
|
package cn.bootx.platform.daxpay.demo.controller;
|
||||||
|
|
||||||
|
import cn.bootx.platform.common.core.rest.Res;
|
||||||
|
import cn.bootx.platform.common.core.rest.ResResult;
|
||||||
|
import cn.bootx.platform.common.core.util.ValidationUtil;
|
||||||
|
import cn.bootx.platform.daxpay.demo.param.CashierSimplePayParam;
|
||||||
|
import cn.bootx.platform.daxpay.demo.result.PayOrderResult;
|
||||||
|
import cn.bootx.platform.daxpay.demo.service.DaxPayCashierService;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结算台演示
|
||||||
|
* @author xxm
|
||||||
|
* @since 2024/2/8
|
||||||
|
*/
|
||||||
|
@Tag(name = "结算台演示")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/demo/cashier")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class DaxPayCashierController {
|
||||||
|
|
||||||
|
private final DaxPayCashierService cashierService;
|
||||||
|
|
||||||
|
@Operation(summary = "创建支付订单并发起")
|
||||||
|
@PostMapping("/simplePayCashier")
|
||||||
|
public ResResult<PayOrderResult> simplePayCashier(@RequestBody CashierSimplePayParam param){
|
||||||
|
ValidationUtil.validateParam(param);
|
||||||
|
return Res.ok(cashierService.simplePayCashier(param));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "查询支付订单")
|
||||||
|
@GetMapping("/queryPayOrder")
|
||||||
|
public ResResult<Boolean> queryPayOrder(Long paymentId){
|
||||||
|
return Res.ok(cashierService.queryPayOrder(paymentId));
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,47 @@
|
|||||||
|
package cn.bootx.platform.daxpay.demo.param;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结算台简单支付参数(单通道支付)
|
||||||
|
*
|
||||||
|
* @author xxm
|
||||||
|
* @since 2022/2/23
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@Schema(title = "结算台简单支付参数(单通道支付)")
|
||||||
|
public class CashierSimplePayParam {
|
||||||
|
|
||||||
|
@Schema(description = "业务号")
|
||||||
|
@NotNull
|
||||||
|
private String businessNo;
|
||||||
|
|
||||||
|
@Schema(description = "标题")
|
||||||
|
@NotNull
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
@Schema(description = "金额")
|
||||||
|
@NotNull
|
||||||
|
private BigDecimal amount;
|
||||||
|
|
||||||
|
@Schema(description = "openId(微信支付时使用)")
|
||||||
|
private String openId;
|
||||||
|
|
||||||
|
@Schema(description = "支付渠道")
|
||||||
|
@NotNull
|
||||||
|
private String channel;
|
||||||
|
|
||||||
|
@Schema(description = "支付方式")
|
||||||
|
@NotNull
|
||||||
|
private String payWay;
|
||||||
|
|
||||||
|
@Schema(description = "付款码")
|
||||||
|
private String authCode;
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,31 @@
|
|||||||
|
package cn.bootx.platform.daxpay.demo.result;
|
||||||
|
|
||||||
|
import cn.bootx.platform.daxpay.sdk.code.PayChannelEnum;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发起支付后响应对象
|
||||||
|
* @author xxm
|
||||||
|
* @since 2024/2/8
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class PayOrderResult {
|
||||||
|
/** 支付ID */
|
||||||
|
private Long paymentId;
|
||||||
|
|
||||||
|
/** 是否是异步支付 */
|
||||||
|
private boolean asyncPay;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异步支付通道
|
||||||
|
* @see PayChannelEnum
|
||||||
|
*/
|
||||||
|
private String asyncChannel;
|
||||||
|
|
||||||
|
|
||||||
|
/** 支付参数体(通常用于发起异步支付的参数) */
|
||||||
|
private String payBody;
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,128 @@
|
|||||||
|
package cn.bootx.platform.daxpay.demo.service;
|
||||||
|
|
||||||
|
import cn.bootx.platform.common.core.exception.BizException;
|
||||||
|
import cn.bootx.platform.common.spring.util.WebServletUtil;
|
||||||
|
import cn.bootx.platform.daxpay.demo.param.CashierSimplePayParam;
|
||||||
|
import cn.bootx.platform.daxpay.demo.result.PayOrderResult;
|
||||||
|
import cn.bootx.platform.daxpay.sdk.code.PayChannelEnum;
|
||||||
|
import cn.bootx.platform.daxpay.sdk.code.PayStatusEnum;
|
||||||
|
import cn.bootx.platform.daxpay.sdk.code.PayWayEnum;
|
||||||
|
import cn.bootx.platform.daxpay.sdk.model.pay.PayOrderModel;
|
||||||
|
import cn.bootx.platform.daxpay.sdk.model.pay.QueryPayOrderModel;
|
||||||
|
import cn.bootx.platform.daxpay.sdk.net.DaxPayKit;
|
||||||
|
import cn.bootx.platform.daxpay.sdk.param.channel.AliPayParam;
|
||||||
|
import cn.bootx.platform.daxpay.sdk.param.channel.WeChatPayParam;
|
||||||
|
import cn.bootx.platform.daxpay.sdk.param.pay.QueryPayOrderParam;
|
||||||
|
import cn.bootx.platform.daxpay.sdk.param.pay.SimplePayParam;
|
||||||
|
import cn.bootx.platform.daxpay.sdk.response.DaxPayResult;
|
||||||
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
|
import cn.hutool.extra.servlet.ServletUtil;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付结算台服务类
|
||||||
|
* @author xxm
|
||||||
|
* @since 2024/2/8
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class DaxPayCashierService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结算台简单支付, 创建支付订单并拉起支付
|
||||||
|
*/
|
||||||
|
public PayOrderResult simplePayCashier(CashierSimplePayParam param){
|
||||||
|
// 将参数转换为简单支付参数
|
||||||
|
SimplePayParam simplePayParam = new SimplePayParam();
|
||||||
|
simplePayParam.setBusinessNo(param.getBusinessNo());
|
||||||
|
int amount = param.getAmount()
|
||||||
|
.multiply(BigDecimal.valueOf(100))
|
||||||
|
.intValue();
|
||||||
|
simplePayParam.setTitle(param.getTitle());
|
||||||
|
simplePayParam.setAmount(amount);
|
||||||
|
simplePayParam.setChannel(param.getChannel());
|
||||||
|
simplePayParam.setPayWay(param.getPayWay());
|
||||||
|
|
||||||
|
// 支付宝通道
|
||||||
|
if (Objects.equals(PayChannelEnum.ALI.getCode(), param.getChannel())){
|
||||||
|
// 付款码支付
|
||||||
|
if (Objects.equals(PayWayEnum.BARCODE.getCode(), param.getPayWay())){
|
||||||
|
AliPayParam aliPayParam = new AliPayParam();
|
||||||
|
aliPayParam.setAuthCode(param.getAuthCode());
|
||||||
|
simplePayParam.setChannelParam(aliPayParam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 微信通道
|
||||||
|
if (Objects.equals(PayChannelEnum.WECHAT.getCode(), param.getChannel())){
|
||||||
|
WeChatPayParam wechatPayParam = new WeChatPayParam();
|
||||||
|
// 付款码支付
|
||||||
|
if (Objects.equals(PayWayEnum.BARCODE.getCode(), param.getPayWay())){
|
||||||
|
wechatPayParam.setAuthCode(param.getAuthCode());
|
||||||
|
simplePayParam.setChannelParam(wechatPayParam);
|
||||||
|
}
|
||||||
|
// 微信jsapi 方式支付
|
||||||
|
if (Objects.equals(PayWayEnum.JSAPI.getCode(), param.getPayWay())){
|
||||||
|
wechatPayParam.setOpenId(param.getOpenId());
|
||||||
|
simplePayParam.setChannelParam(wechatPayParam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String ip = Optional.ofNullable(WebServletUtil.getRequest())
|
||||||
|
.map(ServletUtil::getClientIP)
|
||||||
|
.orElse("127.0.0.1");
|
||||||
|
simplePayParam.setClientIp(ip);
|
||||||
|
// 异步回调地址
|
||||||
|
simplePayParam.setNotifyUrl("http://localhost:9000");
|
||||||
|
// 同步回调地址
|
||||||
|
simplePayParam.setReturnUrl("http://localhost:9000");
|
||||||
|
|
||||||
|
// 发起支付
|
||||||
|
DaxPayResult<PayOrderModel> execute = DaxPayKit.execute(simplePayParam);
|
||||||
|
// 判断是否支付成功
|
||||||
|
if (execute.getCode() != 0){
|
||||||
|
throw new BizException(execute.getMsg());
|
||||||
|
}
|
||||||
|
// 判断是否发起支付成功
|
||||||
|
PayOrderModel payOrderModel = execute.getData();
|
||||||
|
|
||||||
|
// 状态 支付中或支付完成返回
|
||||||
|
List<String> list = Arrays.asList(PayStatusEnum.PROGRESS.getCode(), PayStatusEnum.SUCCESS.getCode());
|
||||||
|
if (list.contains(payOrderModel.getStatus())){
|
||||||
|
PayOrderResult payOrderResult = new PayOrderResult();
|
||||||
|
BeanUtil.copyProperties(payOrderModel, payOrderResult);
|
||||||
|
return payOrderResult;
|
||||||
|
} else {
|
||||||
|
throw new BizException("订单状态异常,无法进行支付");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单查询接口
|
||||||
|
*/
|
||||||
|
public boolean queryPayOrder(Long paymentId){
|
||||||
|
QueryPayOrderParam queryPayOrderParam = new QueryPayOrderParam();
|
||||||
|
queryPayOrderParam.setPaymentId(paymentId);
|
||||||
|
DaxPayResult<QueryPayOrderModel> execute = DaxPayKit.execute(queryPayOrderParam);
|
||||||
|
if (execute.getCode() != 0){
|
||||||
|
throw new BizException(execute.getMsg());
|
||||||
|
}
|
||||||
|
QueryPayOrderModel data = execute.getData();
|
||||||
|
String status = data.getStatus();
|
||||||
|
if (Objects.equals(status, PayStatusEnum.PROGRESS.getCode())){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (Objects.equals(status, PayStatusEnum.SUCCESS.getCode())){
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
throw new BizException("订单状态不是支付中或支付完成,请检查");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1 @@
|
|||||||
|
cn.bootx.platform.daxpay.demo.DaxPaySingleDemoApp
|
@@ -51,23 +51,34 @@
|
|||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<!-- 工具类 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-all</artifactId>
|
<artifactId>hutool-all</artifactId>
|
||||||
<version>${hutool.version}</version>
|
<version>${hutool.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- 日志框架 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>ch.qos.logback</groupId>
|
<groupId>ch.qos.logback</groupId>
|
||||||
<artifactId>logback-classic</artifactId>
|
<artifactId>logback-classic</artifactId>
|
||||||
<version>${logback-classic.version}</version>
|
<version>${logback-classic.version}</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- Lombok -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
<version>${lombok.version}</version>
|
<version>${lombok.version}</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- 注解标识 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jetbrains</groupId>
|
||||||
|
<artifactId>annotations</artifactId>
|
||||||
|
<version>13.0</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- 测试类 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
|
@@ -8,7 +8,7 @@ import lombok.Setter;
|
|||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支付相应对象
|
* 发起支付后响应对象
|
||||||
* @author xxm
|
* @author xxm
|
||||||
* @since 2024/2/2
|
* @since 2024/2/2
|
||||||
*/
|
*/
|
||||||
|
@@ -8,6 +8,7 @@ import cn.hutool.http.HttpResponse;
|
|||||||
import cn.hutool.http.HttpUtil;
|
import cn.hutool.http.HttpUtil;
|
||||||
import cn.hutool.json.JSONUtil;
|
import cn.hutool.json.JSONUtil;
|
||||||
import lombok.experimental.UtilityClass;
|
import lombok.experimental.UtilityClass;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@@ -16,12 +17,14 @@ import java.util.Objects;
|
|||||||
* @author xxm
|
* @author xxm
|
||||||
* @since 2024/2/2
|
* @since 2024/2/2
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
@UtilityClass
|
@UtilityClass
|
||||||
public class DaxPayKit {
|
public class DaxPayKit {
|
||||||
|
|
||||||
private DaxPayConfig config;
|
private DaxPayConfig config;
|
||||||
|
|
||||||
public void initConfig(DaxPayConfig config){
|
public void initConfig(DaxPayConfig config){
|
||||||
|
log.debug("DaxPayKit初始化...");
|
||||||
DaxPayKit.config = config;
|
DaxPayKit.config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,12 +57,14 @@ public class DaxPayKit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
String data = JSONUtil.toJsonStr(request);
|
String data = JSONUtil.toJsonStr(request);
|
||||||
|
log.debug("请求参数:{}", data);
|
||||||
String path = config.getServiceUrl() + request.path();
|
String path = config.getServiceUrl() + request.path();
|
||||||
HttpResponse execute = HttpUtil.createPost(path)
|
HttpResponse execute = HttpUtil.createPost(path)
|
||||||
.body(data, ContentType.JSON.getValue())
|
.body(data, ContentType.JSON.getValue())
|
||||||
.timeout(config.getReqTimeout())
|
.timeout(config.getReqTimeout())
|
||||||
.execute();
|
.execute();
|
||||||
String body = execute.body();
|
String body = execute.body();
|
||||||
|
log.debug("响应参数:{}", body);
|
||||||
return request.toModel(body);
|
return request.toModel(body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -5,5 +5,5 @@ package cn.bootx.platform.daxpay.sdk.param;
|
|||||||
* @author xxm
|
* @author xxm
|
||||||
* @since 2023/12/17
|
* @since 2023/12/17
|
||||||
*/
|
*/
|
||||||
public interface ChannelParam {
|
public interface ChannelParam extends SortMapParam {
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,9 @@
|
|||||||
|
package cn.bootx.platform.daxpay.sdk.param;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标示字段可以转换为MAP进行排序
|
||||||
|
* @author xxm
|
||||||
|
* @since 2024/2/8
|
||||||
|
*/
|
||||||
|
public interface SortMapParam {
|
||||||
|
}
|
@@ -15,7 +15,7 @@ import lombok.EqualsAndHashCode;
|
|||||||
*/
|
*/
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@Data
|
@Data
|
||||||
public class QueryPayParam extends DaxPayRequest<QueryPayOrderModel> {
|
public class QueryPayOrderParam extends DaxPayRequest<QueryPayOrderModel> {
|
||||||
|
|
||||||
/** 支付ID */
|
/** 支付ID */
|
||||||
private Long paymentId;
|
private Long paymentId;
|
@@ -15,6 +15,7 @@ import cn.hutool.json.JSONUtil;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 简单支付请求参数
|
* 简单支付请求参数
|
||||||
@@ -27,9 +28,11 @@ import lombok.ToString;
|
|||||||
public class SimplePayParam extends DaxPayRequest<PayOrderModel> {
|
public class SimplePayParam extends DaxPayRequest<PayOrderModel> {
|
||||||
|
|
||||||
/** 业务号 */
|
/** 业务号 */
|
||||||
|
@NotNull
|
||||||
private String businessNo;
|
private String businessNo;
|
||||||
|
|
||||||
/** 支付标题 */
|
/** 支付标题 */
|
||||||
|
@NotNull
|
||||||
private String title;
|
private String title;
|
||||||
|
|
||||||
/** 支付描述 */
|
/** 支付描述 */
|
||||||
@@ -42,17 +45,21 @@ public class SimplePayParam extends DaxPayRequest<PayOrderModel> {
|
|||||||
private String quitUrl;
|
private String quitUrl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 支付通道
|
||||||
* @see PayChannelEnum#getCode()
|
* @see PayChannelEnum#getCode()
|
||||||
*/
|
*/
|
||||||
|
@NotNull
|
||||||
private String channel;
|
private String channel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支付方式编码
|
* 支付方式编码
|
||||||
* @see PayWayEnum#getCode()
|
* @see PayWayEnum#getCode()
|
||||||
*/
|
*/
|
||||||
|
@NotNull
|
||||||
private String payWay;
|
private String payWay;
|
||||||
|
|
||||||
/** 支付金额 */
|
/** 支付金额 */
|
||||||
|
@NotNull
|
||||||
private Integer amount;
|
private Integer amount;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -15,7 +15,7 @@ import lombok.EqualsAndHashCode;
|
|||||||
*/
|
*/
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@Data
|
@Data
|
||||||
public class QueryRefundParam extends DaxPayRequest<QueryRefundOrderModel> {
|
public class QueryRefundOrderParam extends DaxPayRequest<QueryRefundOrderModel> {
|
||||||
|
|
||||||
/** 退款ID */
|
/** 退款ID */
|
||||||
private Long refundId;
|
private Long refundId;
|
@@ -2,6 +2,7 @@ package cn.bootx.platform.daxpay.sdk.util;
|
|||||||
|
|
||||||
import cn.bootx.platform.daxpay.sdk.param.SortMapParam;
|
import cn.bootx.platform.daxpay.sdk.param.SortMapParam;
|
||||||
import cn.hutool.core.util.ClassUtil;
|
import cn.hutool.core.util.ClassUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.crypto.SecureUtil;
|
import cn.hutool.crypto.SecureUtil;
|
||||||
import cn.hutool.crypto.digest.HmacAlgorithm;
|
import cn.hutool.crypto.digest.HmacAlgorithm;
|
||||||
import cn.hutool.json.JSONUtil;
|
import cn.hutool.json.JSONUtil;
|
||||||
@@ -94,9 +95,8 @@ public class PaySignUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 把所有元素排序, 并拼接成字符, 用于签名
|
* 把所有元素排序, 并拼接成字符, 用于签名, 同时会过滤掉 " 和 \ 字符
|
||||||
*/
|
*/
|
||||||
public static String createLinkString(Map<String, String> params) {
|
public static String createLinkString(Map<String, String> params) {
|
||||||
String connStr = "&";
|
String connStr = "&";
|
||||||
@@ -118,10 +118,12 @@ public class PaySignUtil {
|
|||||||
.append(connStr);
|
.append(connStr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return content.toString();
|
String s = content.toString();
|
||||||
|
s = StrUtil.replace(s,"\\","");
|
||||||
|
s = StrUtil.replace(s,"\"","");
|
||||||
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成16进制 MD5 字符串
|
* 生成16进制 MD5 字符串
|
||||||
*
|
*
|
||||||
|
@@ -3,7 +3,7 @@ package cn.bootx.platform.daxpay.sdk.query;
|
|||||||
import cn.bootx.platform.daxpay.sdk.model.pay.QueryPayOrderModel;
|
import cn.bootx.platform.daxpay.sdk.model.pay.QueryPayOrderModel;
|
||||||
import cn.bootx.platform.daxpay.sdk.net.DaxPayConfig;
|
import cn.bootx.platform.daxpay.sdk.net.DaxPayConfig;
|
||||||
import cn.bootx.platform.daxpay.sdk.net.DaxPayKit;
|
import cn.bootx.platform.daxpay.sdk.net.DaxPayKit;
|
||||||
import cn.bootx.platform.daxpay.sdk.param.pay.QueryPayParam;
|
import cn.bootx.platform.daxpay.sdk.param.pay.QueryPayOrderParam;
|
||||||
import cn.bootx.platform.daxpay.sdk.response.DaxPayResult;
|
import cn.bootx.platform.daxpay.sdk.response.DaxPayResult;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -27,7 +27,7 @@ public class QueryPayOrderTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPay() {
|
public void testPay() {
|
||||||
QueryPayParam param = new QueryPayParam();
|
QueryPayOrderParam param = new QueryPayOrderParam();
|
||||||
|
|
||||||
param.setBusinessNo("2");
|
param.setBusinessNo("2");
|
||||||
|
|
||||||
|
@@ -3,7 +3,7 @@ package cn.bootx.platform.daxpay.sdk.query;
|
|||||||
import cn.bootx.platform.daxpay.sdk.model.refund.QueryRefundOrderModel;
|
import cn.bootx.platform.daxpay.sdk.model.refund.QueryRefundOrderModel;
|
||||||
import cn.bootx.platform.daxpay.sdk.net.DaxPayConfig;
|
import cn.bootx.platform.daxpay.sdk.net.DaxPayConfig;
|
||||||
import cn.bootx.platform.daxpay.sdk.net.DaxPayKit;
|
import cn.bootx.platform.daxpay.sdk.net.DaxPayKit;
|
||||||
import cn.bootx.platform.daxpay.sdk.param.refund.QueryRefundParam;
|
import cn.bootx.platform.daxpay.sdk.param.refund.QueryRefundOrderParam;
|
||||||
import cn.bootx.platform.daxpay.sdk.response.DaxPayResult;
|
import cn.bootx.platform.daxpay.sdk.response.DaxPayResult;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -27,7 +27,7 @@ public class QueryRefundOrderTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPay() {
|
public void testPay() {
|
||||||
QueryRefundParam param = new QueryRefundParam();
|
QueryRefundOrderParam param = new QueryRefundOrderParam();
|
||||||
|
|
||||||
param.setRefundId(1755263825769361408L);
|
param.setRefundId(1755263825769361408L);
|
||||||
|
|
||||||
|
@@ -2,6 +2,7 @@ package cn.bootx.platform.daxpay.sdk.util;
|
|||||||
|
|
||||||
import cn.bootx.platform.daxpay.sdk.code.PayChannelEnum;
|
import cn.bootx.platform.daxpay.sdk.code.PayChannelEnum;
|
||||||
import cn.bootx.platform.daxpay.sdk.code.PayWayEnum;
|
import cn.bootx.platform.daxpay.sdk.code.PayWayEnum;
|
||||||
|
import cn.bootx.platform.daxpay.sdk.param.channel.WeChatPayParam;
|
||||||
import cn.bootx.platform.daxpay.sdk.param.pay.PayChannelParam;
|
import cn.bootx.platform.daxpay.sdk.param.pay.PayChannelParam;
|
||||||
import cn.bootx.platform.daxpay.sdk.param.pay.PayParam;
|
import cn.bootx.platform.daxpay.sdk.param.pay.PayParam;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -43,7 +44,42 @@ public class PayParamSignTest {
|
|||||||
Map<String, String> map = PaySignUtil.toMap(param);
|
Map<String, String> map = PaySignUtil.toMap(param);
|
||||||
log.info("转换为有序MAP后的内容: {}",map);
|
log.info("转换为有序MAP后的内容: {}",map);
|
||||||
String data = PaySignUtil.createLinkString(map);
|
String data = PaySignUtil.createLinkString(map);
|
||||||
log.info("将MAP拼接字符串: {}",data);
|
log.info("将MAP拼接字符串, 并过滤掉特殊字符: {}",data);
|
||||||
|
String sign = "123456";
|
||||||
|
data += "&sign="+sign;
|
||||||
|
data = data.toUpperCase();
|
||||||
|
log.info("添加秘钥并转换为大写的字符串: {}",data);
|
||||||
|
log.info("MD5: {}",PaySignUtil.md5(data));
|
||||||
|
log.info("HmacSHA256: {}",PaySignUtil.hmacSha256(data,sign));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多层嵌套对象签名测试
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void sign2(){
|
||||||
|
|
||||||
|
PayParam param = new PayParam();
|
||||||
|
param.setClientIp("127.0.0.1");
|
||||||
|
|
||||||
|
param.setBusinessNo("P0002");
|
||||||
|
param.setTitle("测试接口支付");
|
||||||
|
PayChannelParam payChannelParam = new PayChannelParam();
|
||||||
|
payChannelParam.setChannel(PayChannelEnum.WECHAT.getCode());
|
||||||
|
payChannelParam.setWay(PayWayEnum.QRCODE.getCode());
|
||||||
|
payChannelParam.setAmount(1);
|
||||||
|
WeChatPayParam weChatPayParam = new WeChatPayParam();
|
||||||
|
weChatPayParam.setOpenId("6688812");
|
||||||
|
weChatPayParam.setAuthCode("123456");
|
||||||
|
payChannelParam.setChannelParam(weChatPayParam);
|
||||||
|
|
||||||
|
List<PayChannelParam> payChannels = Collections.singletonList(payChannelParam);
|
||||||
|
param.setPayChannels(payChannels);
|
||||||
|
|
||||||
|
Map<String, String> map = PaySignUtil.toMap(param);
|
||||||
|
log.info("转换为有序MAP后的内容: {}",map);
|
||||||
|
String data = PaySignUtil.createLinkString(map).replaceAll("\\\"","").replaceAll("\"","");
|
||||||
|
log.info("将MAP拼接字符串, 并过滤掉特殊字符: {}",data);
|
||||||
String sign = "123456";
|
String sign = "123456";
|
||||||
data += "&sign="+sign;
|
data += "&sign="+sign;
|
||||||
data = data.toUpperCase();
|
data = data.toUpperCase();
|
||||||
|
@@ -16,8 +16,9 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.bootx.platform</groupId>
|
<groupId>cn.bootx.platform</groupId>
|
||||||
<artifactId>daxpay-single-service</artifactId>
|
<artifactId>daxpay-single-service</artifactId>
|
||||||
<version>${dax.version}</version>
|
<version>${daxpay.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- 安全认证 -->
|
<!-- 安全认证 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.bootx.platform</groupId>
|
<groupId>cn.bootx.platform</groupId>
|
||||||
|
@@ -11,6 +11,7 @@ import lombok.Data;
|
|||||||
|
|
||||||
import javax.validation.constraints.NotBlank;
|
import javax.validation.constraints.NotBlank;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 同意下单支付方式参数
|
* 同意下单支付方式参数
|
||||||
@@ -48,5 +49,5 @@ public class PayChannelParam {
|
|||||||
* @see WalletPayParam
|
* @see WalletPayParam
|
||||||
*/
|
*/
|
||||||
@Schema(description = "附加支付参数")
|
@Schema(description = "附加支付参数")
|
||||||
private String channelParam;
|
private Map<String,Object> channelParam;
|
||||||
}
|
}
|
||||||
|
@@ -16,6 +16,7 @@ import javax.validation.constraints.Min;
|
|||||||
import javax.validation.constraints.NotBlank;
|
import javax.validation.constraints.NotBlank;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 简单下单参数
|
* 简单下单参数
|
||||||
@@ -71,7 +72,7 @@ public class SimplePayParam extends PayCommonParam{
|
|||||||
* @see WalletPayParam
|
* @see WalletPayParam
|
||||||
*/
|
*/
|
||||||
@Schema(description = "附加通道支付参数")
|
@Schema(description = "附加通道支付参数")
|
||||||
private String channelParam;
|
private Map<String, Object> channelParam;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -2,6 +2,7 @@ package cn.bootx.platform.daxpay.util;
|
|||||||
|
|
||||||
import cn.bootx.platform.common.core.util.LocalDateTimeUtil;
|
import cn.bootx.platform.common.core.util.LocalDateTimeUtil;
|
||||||
import cn.hutool.core.util.ClassUtil;
|
import cn.hutool.core.util.ClassUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.crypto.SecureUtil;
|
import cn.hutool.crypto.SecureUtil;
|
||||||
import cn.hutool.crypto.digest.HmacAlgorithm;
|
import cn.hutool.crypto.digest.HmacAlgorithm;
|
||||||
import cn.hutool.json.JSONUtil;
|
import cn.hutool.json.JSONUtil;
|
||||||
@@ -99,7 +100,7 @@ public class PaySignUtil {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 把所有元素排序, 并拼接成字符, 用于签名
|
* 把所有元素排序, 并拼接成字符, 用于签名, 同时会过滤掉 " 和 \ 字符
|
||||||
*/
|
*/
|
||||||
public static String createLinkString(Map<String, String> params) {
|
public static String createLinkString(Map<String, String> params) {
|
||||||
String connStr = "&";
|
String connStr = "&";
|
||||||
@@ -121,7 +122,10 @@ public class PaySignUtil {
|
|||||||
.append(connStr);
|
.append(connStr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return content.toString();
|
String s = content.toString();
|
||||||
|
s = StrUtil.replace(s,"\\","");
|
||||||
|
s = StrUtil.replace(s,"\"","");
|
||||||
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.bootx.platform</groupId>
|
<groupId>cn.bootx.platform</groupId>
|
||||||
<artifactId>daxpay-single-service</artifactId>
|
<artifactId>daxpay-single-service</artifactId>
|
||||||
<version>${dax.version}</version>
|
<version>${daxpay.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
@@ -70,7 +70,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.bootx.platform</groupId>
|
<groupId>cn.bootx.platform</groupId>
|
||||||
<artifactId>daxpay-single-core</artifactId>
|
<artifactId>daxpay-single-core</artifactId>
|
||||||
<version>${dax.version}</version>
|
<version>${daxpay.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- 支付宝支付 -->
|
<!-- 支付宝支付 -->
|
||||||
@@ -109,6 +109,7 @@
|
|||||||
<artifactId>junit-jupiter</artifactId>
|
<artifactId>junit-jupiter</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- 分布式锁 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.baomidou</groupId>
|
<groupId>com.baomidou</groupId>
|
||||||
<artifactId>lock4j-redis-template-spring-boot-starter</artifactId>
|
<artifactId>lock4j-redis-template-spring-boot-starter</artifactId>
|
||||||
|
@@ -1,5 +1,8 @@
|
|||||||
package cn.bootx.platform.daxpay.service.core.channel.voucher.service;
|
package cn.bootx.platform.daxpay.service.core.channel.voucher.service;
|
||||||
|
|
||||||
|
import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
|
||||||
|
import cn.bootx.platform.daxpay.param.channel.VoucherPayParam;
|
||||||
|
import cn.bootx.platform.daxpay.param.pay.PayChannelParam;
|
||||||
import cn.bootx.platform.daxpay.service.code.VoucherCode;
|
import cn.bootx.platform.daxpay.service.code.VoucherCode;
|
||||||
import cn.bootx.platform.daxpay.service.core.channel.voucher.dao.VoucherLogManager;
|
import cn.bootx.platform.daxpay.service.core.channel.voucher.dao.VoucherLogManager;
|
||||||
import cn.bootx.platform.daxpay.service.core.channel.voucher.dao.VoucherManager;
|
import cn.bootx.platform.daxpay.service.core.channel.voucher.dao.VoucherManager;
|
||||||
@@ -9,17 +12,17 @@ import cn.bootx.platform.daxpay.service.core.channel.voucher.entity.VoucherLog;
|
|||||||
import cn.bootx.platform.daxpay.service.core.channel.voucher.entity.VoucherPayOrder;
|
import cn.bootx.platform.daxpay.service.core.channel.voucher.entity.VoucherPayOrder;
|
||||||
import cn.bootx.platform.daxpay.service.core.channel.voucher.entity.VoucherRecord;
|
import cn.bootx.platform.daxpay.service.core.channel.voucher.entity.VoucherRecord;
|
||||||
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
|
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
|
||||||
import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
import cn.bootx.platform.daxpay.param.channel.VoucherPayParam;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.bootx.platform.daxpay.param.pay.PayChannelParam;
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.json.JSONException;
|
import cn.hutool.json.JSONException;
|
||||||
import cn.hutool.json.JSONUtil;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 储值卡支付
|
* 储值卡支付
|
||||||
*
|
*
|
||||||
@@ -46,9 +49,10 @@ public class VoucherPayService {
|
|||||||
VoucherPayParam voucherPayParam;
|
VoucherPayParam voucherPayParam;
|
||||||
try {
|
try {
|
||||||
// 储值卡参数验证
|
// 储值卡参数验证
|
||||||
String extraParamsJson = payChannelParam.getChannelParam();
|
|
||||||
if (StrUtil.isNotBlank(extraParamsJson)) {
|
Map<String, Object> channelParam = payChannelParam.getChannelParam();
|
||||||
voucherPayParam = JSONUtil.toBean(extraParamsJson, VoucherPayParam.class);
|
if (CollUtil.isNotEmpty(channelParam)) {
|
||||||
|
voucherPayParam = BeanUtil.toBean(channelParam, VoucherPayParam.class);
|
||||||
} else {
|
} else {
|
||||||
throw new PayFailureException("储值卡支付参数错误");
|
throw new PayFailureException("储值卡支付参数错误");
|
||||||
}
|
}
|
||||||
|
@@ -2,6 +2,9 @@ package cn.bootx.platform.daxpay.service.core.order.pay.builder;
|
|||||||
|
|
||||||
import cn.bootx.platform.daxpay.code.PayChannelEnum;
|
import cn.bootx.platform.daxpay.code.PayChannelEnum;
|
||||||
import cn.bootx.platform.daxpay.code.PayStatusEnum;
|
import cn.bootx.platform.daxpay.code.PayStatusEnum;
|
||||||
|
import cn.bootx.platform.daxpay.param.pay.PayChannelParam;
|
||||||
|
import cn.bootx.platform.daxpay.param.pay.PayParam;
|
||||||
|
import cn.bootx.platform.daxpay.result.pay.PayResult;
|
||||||
import cn.bootx.platform.daxpay.service.common.context.AsyncPayLocal;
|
import cn.bootx.platform.daxpay.service.common.context.AsyncPayLocal;
|
||||||
import cn.bootx.platform.daxpay.service.common.context.NoticeLocal;
|
import cn.bootx.platform.daxpay.service.common.context.NoticeLocal;
|
||||||
import cn.bootx.platform.daxpay.service.common.context.PlatformLocal;
|
import cn.bootx.platform.daxpay.service.common.context.PlatformLocal;
|
||||||
@@ -9,20 +12,15 @@ import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
|
|||||||
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayChannelOrder;
|
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayChannelOrder;
|
||||||
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
|
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
|
||||||
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrderExtra;
|
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrderExtra;
|
||||||
import cn.bootx.platform.daxpay.entity.RefundableInfo;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.bootx.platform.daxpay.param.pay.PayParam;
|
|
||||||
import cn.bootx.platform.daxpay.param.pay.PayChannelParam;
|
|
||||||
import cn.bootx.platform.daxpay.result.pay.PayResult;
|
|
||||||
import cn.hutool.core.collection.CollectionUtil;
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.hutool.json.JSONUtil;
|
||||||
import lombok.experimental.UtilityClass;
|
import lombok.experimental.UtilityClass;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.Collections;
|
import java.util.Map;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支付对象构建器
|
* 支付对象构建器
|
||||||
@@ -91,28 +89,19 @@ public class PayBuilder {
|
|||||||
* 构建订单关联通道信息
|
* 构建订单关联通道信息
|
||||||
*/
|
*/
|
||||||
public PayChannelOrder buildPayChannelOrder(PayChannelParam channelParam) {
|
public PayChannelOrder buildPayChannelOrder(PayChannelParam channelParam) {
|
||||||
return new PayChannelOrder()
|
PayChannelOrder payChannelOrder = new PayChannelOrder()
|
||||||
.setAsync(PayChannelEnum.ASYNC_TYPE_CODE.contains(channelParam.getChannel()))
|
.setAsync(PayChannelEnum.ASYNC_TYPE_CODE.contains(channelParam.getChannel()))
|
||||||
.setChannel(channelParam.getChannel())
|
.setChannel(channelParam.getChannel())
|
||||||
.setPayWay(channelParam.getWay())
|
.setPayWay(channelParam.getWay())
|
||||||
.setAmount(channelParam.getAmount())
|
.setAmount(channelParam.getAmount())
|
||||||
.setRefundableBalance(channelParam.getAmount())
|
.setRefundableBalance(channelParam.getAmount());
|
||||||
.setChannelExtra(channelParam.getChannelParam());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
Map<String, Object> cp = channelParam.getChannelParam();
|
||||||
* 构建支付订单的可退款信息列表
|
if (CollUtil.isNotEmpty(cp)){
|
||||||
*/
|
payChannelOrder.setChannelExtra(JSONUtil.toJsonStr(cp));
|
||||||
@Deprecated
|
|
||||||
private List<RefundableInfo> buildRefundableInfo(List<PayChannelParam> payChannelParamList) {
|
|
||||||
if (CollectionUtil.isEmpty(payChannelParamList)) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
}
|
||||||
return payChannelParamList.stream()
|
|
||||||
.map(o-> new RefundableInfo()
|
return payChannelOrder;
|
||||||
.setChannel(o.getChannel())
|
|
||||||
.setAmount(o.getAmount()))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -11,6 +11,8 @@ import cn.bootx.platform.daxpay.service.core.order.pay.convert.PayOrderConvert;
|
|||||||
import cn.bootx.platform.daxpay.service.dto.order.pay.PayChannelOrderDto;
|
import cn.bootx.platform.daxpay.service.dto.order.pay.PayChannelOrderDto;
|
||||||
import cn.bootx.table.modify.annotation.DbColumn;
|
import cn.bootx.table.modify.annotation.DbColumn;
|
||||||
import cn.bootx.table.modify.annotation.DbTable;
|
import cn.bootx.table.modify.annotation.DbTable;
|
||||||
|
import com.baomidou.mybatisplus.annotation.FieldStrategy;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
@@ -66,6 +68,7 @@ public class PayChannelOrder extends MpCreateEntity implements EntityBaseFunctio
|
|||||||
* @see WalletPayParam
|
* @see WalletPayParam
|
||||||
*/
|
*/
|
||||||
@DbColumn(comment = "附加支付参数")
|
@DbColumn(comment = "附加支付参数")
|
||||||
|
@TableField(updateStrategy = FieldStrategy.NEVER)
|
||||||
private String channelExtra;
|
private String channelExtra;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -12,6 +12,7 @@ import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayChannelOrder;
|
|||||||
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
|
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
|
||||||
import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundChannelOrder;
|
import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundChannelOrder;
|
||||||
import cn.bootx.platform.daxpay.service.dto.order.pay.PayChannelOrderDto;
|
import cn.bootx.platform.daxpay.service.dto.order.pay.PayChannelOrderDto;
|
||||||
|
import cn.hutool.json.JSONUtil;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@@ -19,6 +20,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@@ -57,6 +59,12 @@ public class PayChannelOrderService {
|
|||||||
PayStatusEnum payStatus = asyncPayInfo.isPayComplete() ? PayStatusEnum.SUCCESS : PayStatusEnum.PROGRESS;
|
PayStatusEnum payStatus = asyncPayInfo.isPayComplete() ? PayStatusEnum.SUCCESS : PayStatusEnum.PROGRESS;
|
||||||
// 判断新发起的
|
// 判断新发起的
|
||||||
Optional<PayChannelOrder> payOrderChannelOpt = channelOrderManager.findByPaymentIdAndChannel(payOrder.getId(), payChannelParam.getChannel());
|
Optional<PayChannelOrder> payOrderChannelOpt = channelOrderManager.findByPaymentIdAndChannel(payOrder.getId(), payChannelParam.getChannel());
|
||||||
|
// 扩展信息处理
|
||||||
|
Map<String, Object> channelParam = payChannelParam.getChannelParam();
|
||||||
|
String channelParamStr = null;
|
||||||
|
if (Objects.nonNull(channelParam)){
|
||||||
|
channelParamStr = JSONUtil.toJsonStr(channelParam);
|
||||||
|
}
|
||||||
if (!payOrderChannelOpt.isPresent()){
|
if (!payOrderChannelOpt.isPresent()){
|
||||||
PayChannelOrder payChannelOrder = new PayChannelOrder();
|
PayChannelOrder payChannelOrder = new PayChannelOrder();
|
||||||
// 替换原有的的支付通道信息
|
// 替换原有的的支付通道信息
|
||||||
@@ -68,7 +76,7 @@ public class PayChannelOrderService {
|
|||||||
.setAmount(payChannelParam.getAmount())
|
.setAmount(payChannelParam.getAmount())
|
||||||
.setRefundableBalance(payChannelParam.getAmount())
|
.setRefundableBalance(payChannelParam.getAmount())
|
||||||
.setPayTime(LocalDateTime.now())
|
.setPayTime(LocalDateTime.now())
|
||||||
.setChannelExtra(payChannelParam.getChannelParam())
|
.setChannelExtra(channelParamStr)
|
||||||
.setStatus(payStatus.getCode());
|
.setStatus(payStatus.getCode());
|
||||||
channelOrderManager.deleteByPaymentIdAndAsync(payOrder.getId());
|
channelOrderManager.deleteByPaymentIdAndAsync(payOrder.getId());
|
||||||
channelOrderManager.save(payChannelOrder);
|
channelOrderManager.save(payChannelOrder);
|
||||||
@@ -77,7 +85,7 @@ public class PayChannelOrderService {
|
|||||||
payOrderChannelOpt.get()
|
payOrderChannelOpt.get()
|
||||||
.setPayWay(payChannelParam.getWay())
|
.setPayWay(payChannelParam.getWay())
|
||||||
.setPayTime(LocalDateTime.now())
|
.setPayTime(LocalDateTime.now())
|
||||||
.setChannelExtra(payChannelParam.getChannelParam())
|
.setChannelExtra(channelParamStr)
|
||||||
.setStatus(payStatus.getCode());
|
.setStatus(payStatus.getCode());
|
||||||
channelOrderManager.updateById(payOrderChannelOpt.get());
|
channelOrderManager.updateById(payOrderChannelOpt.get());
|
||||||
}
|
}
|
||||||
|
@@ -10,13 +10,15 @@ import cn.bootx.platform.daxpay.service.core.channel.alipay.service.AliPayConfig
|
|||||||
import cn.bootx.platform.daxpay.service.core.channel.alipay.service.AliPayService;
|
import cn.bootx.platform.daxpay.service.core.channel.alipay.service.AliPayService;
|
||||||
import cn.bootx.platform.daxpay.service.core.order.pay.service.PayChannelOrderService;
|
import cn.bootx.platform.daxpay.service.core.order.pay.service.PayChannelOrderService;
|
||||||
import cn.bootx.platform.daxpay.service.func.AbsPayStrategy;
|
import cn.bootx.platform.daxpay.service.func.AbsPayStrategy;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.json.JSONException;
|
import cn.hutool.json.JSONException;
|
||||||
import cn.hutool.json.JSONUtil;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.context.annotation.Scope;
|
import org.springframework.context.annotation.Scope;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;
|
import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,9 +54,9 @@ public class AliPayStrategy extends AbsPayStrategy {
|
|||||||
public void doBeforePayHandler() {
|
public void doBeforePayHandler() {
|
||||||
try {
|
try {
|
||||||
// 支付宝参数验证
|
// 支付宝参数验证
|
||||||
String extraParamsJson = this.getPayChannelParam().getChannelParam();
|
Map<String, Object> channelParam = this.getPayChannelParam().getChannelParam();
|
||||||
if (StrUtil.isNotBlank(extraParamsJson)) {
|
if (CollUtil.isNotEmpty(channelParam)) {
|
||||||
this.aliPayParam = JSONUtil.toBean(extraParamsJson, AliPayParam.class);
|
this.aliPayParam = BeanUtil.toBean(channelParam, AliPayParam.class);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.aliPayParam = new AliPayParam();
|
this.aliPayParam = new AliPayParam();
|
||||||
|
@@ -1,23 +1,24 @@
|
|||||||
package cn.bootx.platform.daxpay.service.core.payment.pay.strategy;
|
package cn.bootx.platform.daxpay.service.core.payment.pay.strategy;
|
||||||
|
|
||||||
import cn.bootx.platform.daxpay.code.PayChannelEnum;
|
import cn.bootx.platform.daxpay.code.PayChannelEnum;
|
||||||
import cn.bootx.platform.daxpay.service.code.WalletCode;
|
|
||||||
import cn.bootx.platform.daxpay.service.core.channel.wallet.entity.Wallet;
|
|
||||||
import cn.bootx.platform.daxpay.service.core.channel.wallet.service.WalletPayService;
|
|
||||||
import cn.bootx.platform.daxpay.service.core.channel.wallet.service.WalletPayOrderService;
|
|
||||||
import cn.bootx.platform.daxpay.service.core.channel.wallet.service.WalletQueryService;
|
|
||||||
import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
|
import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
|
||||||
import cn.bootx.platform.daxpay.exception.waller.WalletBannedException;
|
import cn.bootx.platform.daxpay.exception.waller.WalletBannedException;
|
||||||
import cn.bootx.platform.daxpay.exception.waller.WalletLackOfBalanceException;
|
import cn.bootx.platform.daxpay.exception.waller.WalletLackOfBalanceException;
|
||||||
|
import cn.bootx.platform.daxpay.service.code.WalletCode;
|
||||||
|
import cn.bootx.platform.daxpay.service.core.channel.wallet.entity.Wallet;
|
||||||
|
import cn.bootx.platform.daxpay.service.core.channel.wallet.service.WalletPayOrderService;
|
||||||
|
import cn.bootx.platform.daxpay.service.core.channel.wallet.service.WalletPayService;
|
||||||
|
import cn.bootx.platform.daxpay.service.core.channel.wallet.service.WalletQueryService;
|
||||||
import cn.bootx.platform.daxpay.service.func.AbsPayStrategy;
|
import cn.bootx.platform.daxpay.service.func.AbsPayStrategy;
|
||||||
import cn.bootx.platform.daxpay.service.param.channel.wallet.WalletPayParam;
|
import cn.bootx.platform.daxpay.service.param.channel.wallet.WalletPayParam;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.json.JSONException;
|
import cn.hutool.json.JSONException;
|
||||||
import cn.hutool.json.JSONUtil;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.context.annotation.Scope;
|
import org.springframework.context.annotation.Scope;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;
|
import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;
|
||||||
@@ -54,9 +55,9 @@ public class WalletPayStrategy extends AbsPayStrategy {
|
|||||||
WalletPayParam walletPayParam = new WalletPayParam();
|
WalletPayParam walletPayParam = new WalletPayParam();
|
||||||
try {
|
try {
|
||||||
// 钱包参数验证
|
// 钱包参数验证
|
||||||
String extraParamsJson = this.getPayChannelParam().getChannelParam();
|
Map<String, Object> channelParam = this.getPayChannelParam().getChannelParam();
|
||||||
if (StrUtil.isNotBlank(extraParamsJson)) {
|
if (CollUtil.isNotEmpty(channelParam)) {
|
||||||
walletPayParam = JSONUtil.toBean(extraParamsJson, WalletPayParam.class);
|
walletPayParam = BeanUtil.toBean(channelParam, WalletPayParam.class);
|
||||||
}
|
}
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
throw new PayFailureException("支付参数错误");
|
throw new PayFailureException("支付参数错误");
|
||||||
|
@@ -2,7 +2,6 @@ package cn.bootx.platform.daxpay.service.core.payment.pay.strategy;
|
|||||||
|
|
||||||
import cn.bootx.platform.daxpay.code.PayChannelEnum;
|
import cn.bootx.platform.daxpay.code.PayChannelEnum;
|
||||||
import cn.bootx.platform.daxpay.exception.pay.PayAmountAbnormalException;
|
import cn.bootx.platform.daxpay.exception.pay.PayAmountAbnormalException;
|
||||||
import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
|
|
||||||
import cn.bootx.platform.daxpay.param.pay.PayChannelParam;
|
import cn.bootx.platform.daxpay.param.pay.PayChannelParam;
|
||||||
import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WeChatPayConfig;
|
import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WeChatPayConfig;
|
||||||
import cn.bootx.platform.daxpay.service.core.channel.wechat.service.WeChatPayConfigService;
|
import cn.bootx.platform.daxpay.service.core.channel.wechat.service.WeChatPayConfigService;
|
||||||
@@ -10,13 +9,14 @@ import cn.bootx.platform.daxpay.service.core.channel.wechat.service.WeChatPaySer
|
|||||||
import cn.bootx.platform.daxpay.service.core.order.pay.service.PayChannelOrderService;
|
import cn.bootx.platform.daxpay.service.core.order.pay.service.PayChannelOrderService;
|
||||||
import cn.bootx.platform.daxpay.service.func.AbsPayStrategy;
|
import cn.bootx.platform.daxpay.service.func.AbsPayStrategy;
|
||||||
import cn.bootx.platform.daxpay.service.param.channel.wechat.WeChatPayParam;
|
import cn.bootx.platform.daxpay.service.param.channel.wechat.WeChatPayParam;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
import cn.hutool.json.JSONException;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.json.JSONUtil;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.context.annotation.Scope;
|
import org.springframework.context.annotation.Scope;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;
|
import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -53,18 +53,12 @@ public class WeChatPayStrategy extends AbsPayStrategy {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void doBeforePayHandler() {
|
public void doBeforePayHandler() {
|
||||||
try {
|
// 微信参数验证
|
||||||
// 微信参数验证
|
Map<String, Object> channelParam = this.getPayChannelParam().getChannelParam();
|
||||||
String extraParamsJson = this.getPayChannelParam().getChannelParam();
|
if (CollUtil.isNotEmpty(channelParam)) {
|
||||||
if (StrUtil.isNotBlank(extraParamsJson)) {
|
this.weChatPayParam = BeanUtil.toBean(channelParam, WeChatPayParam.class);
|
||||||
this.weChatPayParam = JSONUtil.toBean(extraParamsJson, WeChatPayParam.class);
|
} else {
|
||||||
}
|
this.weChatPayParam = new WeChatPayParam();
|
||||||
else {
|
|
||||||
this.weChatPayParam = new WeChatPayParam();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (JSONException e) {
|
|
||||||
throw new PayFailureException("支付参数错误");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查金额
|
// 检查金额
|
||||||
|
@@ -54,6 +54,10 @@ public class PayExpiredTimeTask {
|
|||||||
paySyncParam.setPaymentId(paymentId);
|
paySyncParam.setPaymentId(paymentId);
|
||||||
paySyncService.sync(paySyncParam);
|
paySyncService.sync(paySyncParam);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
// 如果是未查询到取消支付订单, 则删除这个任务
|
||||||
|
if (Objects.equals("未查询到支付订单", e.getMessage())){
|
||||||
|
repository.removeKeys(expiredKey);
|
||||||
|
}
|
||||||
log.error("超时取消任务 异常", e);
|
log.error("超时取消任务 异常", e);
|
||||||
} finally {
|
} finally {
|
||||||
lockTemplate.releaseLock(lock);
|
lockTemplate.releaseLock(lock);
|
||||||
|
@@ -1,17 +1,18 @@
|
|||||||
package cn.bootx.platform.daxpay.core.payment.common.service;
|
package cn.bootx.platform.daxpay.core.util;
|
||||||
|
|
||||||
import cn.bootx.platform.daxpay.param.channel.AliPayParam;
|
import cn.bootx.platform.daxpay.param.channel.AliPayParam;
|
||||||
import cn.bootx.platform.daxpay.param.channel.WeChatPayParam;
|
import cn.bootx.platform.daxpay.param.channel.WeChatPayParam;
|
||||||
import cn.bootx.platform.daxpay.param.pay.PayChannelParam;
|
import cn.bootx.platform.daxpay.param.pay.PayChannelParam;
|
||||||
import cn.bootx.platform.daxpay.param.pay.PayParam;
|
import cn.bootx.platform.daxpay.param.pay.PayParam;
|
||||||
import cn.bootx.platform.daxpay.util.PaySignUtil;
|
import cn.bootx.platform.daxpay.util.PaySignUtil;
|
||||||
import cn.hutool.json.JSONUtil;
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支付签名服务
|
* 支付签名服务
|
||||||
@@ -19,7 +20,7 @@ import java.util.List;
|
|||||||
* @since 2023/12/24
|
* @since 2023/12/24
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
class PaymentSignServiceTest {
|
class PayParamSignTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void toMap() {
|
void toMap() {
|
||||||
@@ -40,7 +41,7 @@ class PaymentSignServiceTest {
|
|||||||
p1.setWay("wx_app");
|
p1.setWay("wx_app");
|
||||||
AliPayParam aliPayParam = new AliPayParam();
|
AliPayParam aliPayParam = new AliPayParam();
|
||||||
aliPayParam.setAuthCode("6688");
|
aliPayParam.setAuthCode("6688");
|
||||||
p1.setChannelParam(JSONUtil.toJsonStr(aliPayParam));
|
p1.setChannelParam(BeanUtil.beanToMap(aliPayParam,false,true));
|
||||||
|
|
||||||
PayChannelParam p2 = new PayChannelParam();
|
PayChannelParam p2 = new PayChannelParam();
|
||||||
p2.setAmount(100);
|
p2.setAmount(100);
|
||||||
@@ -49,17 +50,21 @@ class PaymentSignServiceTest {
|
|||||||
WeChatPayParam weChatPayParam = new WeChatPayParam();
|
WeChatPayParam weChatPayParam = new WeChatPayParam();
|
||||||
weChatPayParam.setOpenId("w2qsz2xawe3gbhyyff28fs01fd");
|
weChatPayParam.setOpenId("w2qsz2xawe3gbhyyff28fs01fd");
|
||||||
weChatPayParam.setAuthCode("8866");
|
weChatPayParam.setAuthCode("8866");
|
||||||
p2.setChannelParam(JSONUtil.toJsonStr(weChatPayParam));
|
p2.setChannelParam(BeanUtil.beanToMap(aliPayParam,false,true));
|
||||||
List<PayChannelParam> payWays = Arrays.asList(p1, p2);
|
List<PayChannelParam> payWays = Arrays.asList(p1, p2);
|
||||||
payParam.setPayChannels(payWays);
|
payParam.setPayChannels(payWays);
|
||||||
|
|
||||||
// 签名
|
|
||||||
String sign = "123456";
|
|
||||||
String md5Sign = PaySignUtil.md5Sign(payParam, sign);
|
|
||||||
String hmacSha256Sign = PaySignUtil.hmacSha256Sign(payParam, sign);
|
|
||||||
log.info("MD5: {}",md5Sign);
|
|
||||||
log.info("HmacSHA256: {}", hmacSha256Sign);
|
|
||||||
|
|
||||||
|
Map<String, String> map = PaySignUtil.toMap(payParam);
|
||||||
|
log.info("转换为有序MAP后的内容: {}",map);
|
||||||
|
String data = PaySignUtil.createLinkString(map);
|
||||||
|
log.info("将MAP拼接字符串, 并过滤掉特殊字符: {}",data);
|
||||||
|
String sign = "123456";
|
||||||
|
data += "&sign="+sign;
|
||||||
|
data = data.toUpperCase();
|
||||||
|
log.info("添加秘钥并转换为大写的字符串: {}",data);
|
||||||
|
log.info("MD5: {}",PaySignUtil.md5(data));
|
||||||
|
log.info("HmacSHA256: {}",PaySignUtil.hmacSha256(data,sign));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -16,13 +16,13 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.bootx.platform</groupId>
|
<groupId>cn.bootx.platform</groupId>
|
||||||
<artifactId>daxpay-single-gateway</artifactId>
|
<artifactId>daxpay-single-gateway</artifactId>
|
||||||
<version>${dax.version}</version>
|
<version>${daxpay.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- 管理平台 -->
|
<!-- 管理平台 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.bootx.platform</groupId>
|
<groupId>cn.bootx.platform</groupId>
|
||||||
<artifactId>daxpay-single-admin</artifactId>
|
<artifactId>daxpay-single-admin</artifactId>
|
||||||
<version>${dax.version}</version>
|
<version>${daxpay.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- 定时任务 -->
|
<!-- 定时任务 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -35,7 +35,11 @@
|
|||||||
<artifactId>common-starter-code-gen</artifactId>
|
<artifactId>common-starter-code-gen</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- 支付演示模块 -->
|
<!-- 支付演示模块 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.bootx.platform</groupId>
|
||||||
|
<artifactId>daxpay-single-demo</artifactId>
|
||||||
|
<version>${daxpay.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
@@ -72,6 +72,7 @@ bootx:
|
|||||||
base-packages:
|
base-packages:
|
||||||
"[支付网关API]": cn.bootx.platform.daxpay.gateway
|
"[支付网关API]": cn.bootx.platform.daxpay.gateway
|
||||||
"[支付管理接口]": cn.bootx.platform.daxpay.admin
|
"[支付管理接口]": cn.bootx.platform.daxpay.admin
|
||||||
|
"[支付演示模块]": cn.bootx.platform.daxpay.demo
|
||||||
"[BootxPlatform接口]":
|
"[BootxPlatform接口]":
|
||||||
- cn.bootx.platform.common
|
- cn.bootx.platform.common
|
||||||
- cn.bootx.platform.starter
|
- cn.bootx.platform.starter
|
||||||
@@ -150,3 +151,11 @@ dromara:
|
|||||||
enableStorage: true
|
enableStorage: true
|
||||||
# 文件存储路径
|
# 文件存储路径
|
||||||
storage-path: D:/data/files/
|
storage-path: D:/data/files/
|
||||||
|
# 支付系统配置
|
||||||
|
dax-pay:
|
||||||
|
# 演示模块
|
||||||
|
demo:
|
||||||
|
# 网关地址
|
||||||
|
server-url: http://localhost:9000
|
||||||
|
# 签名秘钥
|
||||||
|
sign-secret: 123456
|
||||||
|
3
pom.xml
3
pom.xml
@@ -20,6 +20,7 @@
|
|||||||
<modules>
|
<modules>
|
||||||
<module>daxpay-single</module>
|
<module>daxpay-single</module>
|
||||||
<module>daxpay-single-sdk</module>
|
<module>daxpay-single-sdk</module>
|
||||||
|
<module>daxpay-single-demo</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
@@ -29,7 +30,7 @@
|
|||||||
|
|
||||||
<!-- 二方库版本 -->
|
<!-- 二方库版本 -->
|
||||||
<bootx-platform.version>1.3.6.1</bootx-platform.version>
|
<bootx-platform.version>1.3.6.1</bootx-platform.version>
|
||||||
<dax.version>2.0.0</dax.version>
|
<daxpay.version>2.0.0</daxpay.version>
|
||||||
<!-- 三方库 -->
|
<!-- 三方库 -->
|
||||||
<slf4j.version>1.7.30</slf4j.version>
|
<slf4j.version>1.7.30</slf4j.version>
|
||||||
<redisson.version>3.16.8</redisson.version>
|
<redisson.version>3.16.8</redisson.version>
|
||||||
|
Reference in New Issue
Block a user