mirror of
https://gitee.com/dromara/dax-pay.git
synced 2025-09-07 21:17:42 +00:00
feat 云闪付对接
This commit is contained in:
@@ -92,6 +92,7 @@
|
||||
<artifactId>IJPay-WxPay</artifactId>
|
||||
<version>${IJPay.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 微信支付 wxjava -->
|
||||
<dependency>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
@@ -99,6 +100,13 @@
|
||||
<version>${wxjava.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 云闪付 -->
|
||||
<dependency>
|
||||
<groupId>com.github.javen205</groupId>
|
||||
<artifactId>IJPay-UnionPay</artifactId>
|
||||
<version>${IJPay.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 微信工具包 -->
|
||||
<dependency>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
|
@@ -79,7 +79,7 @@ public class AliPayConfigService {
|
||||
public AliPayConfig getAndCheckConfig() {
|
||||
AliPayConfig alipayConfig = this.getConfig();
|
||||
if (!alipayConfig.getEnable()){
|
||||
throw new PayFailureException("支付宝支付方式未启用");
|
||||
throw new PayFailureException("支付宝支付未启用");
|
||||
}
|
||||
return alipayConfig;
|
||||
}
|
||||
|
@@ -2,14 +2,21 @@ package cn.bootx.platform.daxpay.service.core.channel.union.entity;
|
||||
|
||||
import cn.bootx.platform.common.core.function.EntityBaseFunction;
|
||||
import cn.bootx.platform.common.mybatisplus.base.MpBaseEntity;
|
||||
import cn.bootx.platform.common.mybatisplus.handler.StringListTypeHandler;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.union.convert.UnionPayConvert;
|
||||
import cn.bootx.platform.daxpay.service.dto.channel.union.UnionPayConfigDto;
|
||||
import cn.bootx.table.modify.annotation.DbColumn;
|
||||
import cn.bootx.table.modify.annotation.DbTable;
|
||||
import cn.bootx.table.modify.mysql.annotation.DbMySqlFieldType;
|
||||
import cn.bootx.table.modify.mysql.constants.MySqlFieldTypeEnum;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 云闪付支付配置
|
||||
*
|
||||
@@ -20,9 +27,44 @@ import lombok.experimental.Accessors;
|
||||
@Data
|
||||
@DbTable(comment = "云闪付支付配置")
|
||||
@Accessors(chain = true)
|
||||
@TableName("pay_union_pay_config")
|
||||
@TableName(value = "pay_union_pay_config",autoResultMap = true)
|
||||
public class UnionPayConfig extends MpBaseEntity implements EntityBaseFunction<UnionPayConfigDto> {
|
||||
|
||||
/** 商户号 */
|
||||
@DbColumn(comment = "商户号")
|
||||
private String machId;
|
||||
|
||||
/** 是否启用, 只影响支付和退款操作 */
|
||||
@DbColumn(comment = "是否启用")
|
||||
private Boolean enable;
|
||||
|
||||
/** 密钥 */
|
||||
@DbColumn(comment = "密钥")
|
||||
private String appKey;
|
||||
|
||||
/** 支付网关地址 */
|
||||
@DbColumn(comment = "支付网关地址")
|
||||
private String serverUrl;
|
||||
|
||||
/**
|
||||
* 服务器异步通知页面路径, 需要填写本网关服务的地址, 不可以直接填写业务系统的地址
|
||||
* 1. 需http://或者https://格式的完整路径,
|
||||
* 2. 不能加?id=123这类自定义参数,必须外网可以正常访问
|
||||
* 3. 消息顺序 银联网关 -> 本网关进行处理 -> 发送消息通知业务系统
|
||||
*/
|
||||
@DbColumn(comment = "异步通知路径")
|
||||
private String notifyUrl;
|
||||
|
||||
/** 可用支付方式 */
|
||||
@DbColumn(comment = "可用支付方式")
|
||||
@DbMySqlFieldType(MySqlFieldTypeEnum.LONGTEXT)
|
||||
@TableField(typeHandler = StringListTypeHandler.class)
|
||||
private List<String> payWays;
|
||||
|
||||
/** 备注 */
|
||||
@DbColumn(comment = "备注")
|
||||
private String remark;
|
||||
|
||||
@Override
|
||||
public UnionPayConfigDto toDto() {
|
||||
return UnionPayConvert.CONVERT.convert(this);
|
||||
|
@@ -1,11 +1,27 @@
|
||||
package cn.bootx.platform.daxpay.service.core.channel.union.service;
|
||||
|
||||
import cn.bootx.platform.common.core.exception.DataNotExistException;
|
||||
import cn.bootx.platform.common.core.rest.dto.LabelValue;
|
||||
import cn.bootx.platform.daxpay.code.PayChannelEnum;
|
||||
import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
|
||||
import cn.bootx.platform.daxpay.service.code.AliPayWay;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.union.dao.UnionPayConfigManager;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.union.entity.UnionPayConfig;
|
||||
import cn.bootx.platform.daxpay.service.core.system.config.service.PayChannelConfigService;
|
||||
import cn.bootx.platform.daxpay.service.param.channel.alipay.AliPayConfigParam;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.bean.copier.CopyOptions;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 云闪付支付配置
|
||||
* @author xxm
|
||||
* @since 2022/3/11
|
||||
*/
|
||||
@@ -13,7 +29,52 @@ import org.springframework.stereotype.Service;
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class UnionPayConfigService {
|
||||
|
||||
/** 默认云闪付配置的主键ID */
|
||||
private final static Long ID = 0L;
|
||||
private final UnionPayConfigManager unionPayConfigManager;
|
||||
private final PayChannelConfigService payChannelConfigService;
|
||||
|
||||
/**
|
||||
* 修改
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void update(AliPayConfigParam param) {
|
||||
UnionPayConfig unionPayConfig = unionPayConfigManager.findById(ID).orElseThrow(() -> new DataNotExistException("支付宝配置不存在"));
|
||||
// 启用或停用
|
||||
if (!Objects.equals(param.getEnable(), unionPayConfig.getEnable())){
|
||||
payChannelConfigService.setEnable(PayChannelEnum.UNION_PAY.getCode(), param.getEnable());
|
||||
}
|
||||
|
||||
BeanUtil.copyProperties(param, unionPayConfig, CopyOptions.create().ignoreNullValue());
|
||||
unionPayConfigManager.updateById(unionPayConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付宝支持支付方式
|
||||
*/
|
||||
public List<LabelValue> findPayWays() {
|
||||
return AliPayWay.getPayWays()
|
||||
.stream()
|
||||
.map(e -> new LabelValue(e.getName(),e.getCode()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取支付配置
|
||||
*/
|
||||
public UnionPayConfig getConfig(){
|
||||
return unionPayConfigManager.findById(ID).orElseThrow(() -> new DataNotExistException("支付宝配置不存在"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取并检查支付配置
|
||||
*/
|
||||
public UnionPayConfig getAndCheckConfig() {
|
||||
UnionPayConfig unionPayConfig = this.getConfig();
|
||||
if (!unionPayConfig.getEnable()){
|
||||
throw new PayFailureException("云闪付支付未启用");
|
||||
}
|
||||
return unionPayConfig;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,10 +1,30 @@
|
||||
package cn.bootx.platform.daxpay.service.core.channel.union.service;
|
||||
|
||||
import cn.bootx.platform.daxpay.code.PayWayEnum;
|
||||
import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
|
||||
import cn.bootx.platform.daxpay.param.channel.UnionPayParam;
|
||||
import cn.bootx.platform.daxpay.param.pay.PayChannelParam;
|
||||
import cn.bootx.platform.daxpay.service.code.AliPayWay;
|
||||
import cn.bootx.platform.daxpay.service.common.context.PayLocal;
|
||||
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.union.entity.UnionPayConfig;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
|
||||
import cn.bootx.platform.daxpay.util.PayUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.ijpay.core.enums.SignType;
|
||||
import com.ijpay.core.kit.WxPayKit;
|
||||
import com.ijpay.unionpay.UnionPayApi;
|
||||
import com.ijpay.unionpay.enums.ServiceEnum;
|
||||
import com.ijpay.unionpay.model.UnifiedOrderModel;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 云闪付支付
|
||||
* @author xxm
|
||||
* @since 2022/3/11
|
||||
*/
|
||||
@@ -13,4 +33,59 @@ import org.springframework.stereotype.Service;
|
||||
@RequiredArgsConstructor
|
||||
public class UnionPayService {
|
||||
|
||||
/**
|
||||
* 支付接口
|
||||
*/
|
||||
public void pay(PayOrder payOrder, PayChannelParam payChannelParam, UnionPayParam unionPayParam, UnionPayConfig config){
|
||||
|
||||
Integer amount = payChannelParam.getAmount();
|
||||
String totalFee = String.valueOf(amount);
|
||||
PayLocal asyncPayInfo = PaymentContextLocal.get().getPayInfo();;
|
||||
String payBody = null;
|
||||
PayWayEnum payWayEnum = PayWayEnum.findByCode(payChannelParam.getWay());
|
||||
|
||||
// 二维码支付
|
||||
if (payWayEnum == PayWayEnum.QRCODE){
|
||||
payBody = this.qrCodePay(totalFee, payOrder, config);
|
||||
}
|
||||
|
||||
asyncPayInfo.setPayBody(payBody);
|
||||
}
|
||||
|
||||
/**
|
||||
* 扫码支付
|
||||
*/
|
||||
public String qrCodePay(String totalFee, PayOrder payOrder, UnionPayConfig config){
|
||||
Map<String, String> params = UnifiedOrderModel.builder()
|
||||
.service(ServiceEnum.NATIVE.toString())
|
||||
.mch_id(config.getMachId())
|
||||
.out_trade_no(String.valueOf(payOrder.getId()))
|
||||
.body(payOrder.getTitle())
|
||||
.total_fee(totalFee)
|
||||
.time_expire(PayUtil.getUnionExpiredTime(payOrder.getExpiredTime()))
|
||||
.mch_create_ip("127.0.0.1")
|
||||
.notify_url(config.getNotifyUrl())
|
||||
.nonce_str(WxPayKit.generateStr())
|
||||
.build()
|
||||
.createSign(config.getAppKey(), SignType.MD5);
|
||||
String xmlResult = UnionPayApi.execution(config.getServerUrl(), params);
|
||||
Map<String, String> result = WxPayKit.xmlToMap(xmlResult);
|
||||
return result.get("code_url");
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付前检查支付方式是否可用
|
||||
*/
|
||||
public void validation(PayChannelParam payChannelParam, UnionPayConfig unionPayConfig) {
|
||||
|
||||
if (CollUtil.isEmpty(unionPayConfig.getPayWays())){
|
||||
throw new PayFailureException("云闪付未配置可用的支付方式");
|
||||
}
|
||||
// 发起的支付类型是否在支持的范围内
|
||||
PayWayEnum payWayEnum = Optional.ofNullable(AliPayWay.findByCode(payChannelParam.getWay()))
|
||||
.orElseThrow(() -> new PayFailureException("非法的云闪付支付类型"));
|
||||
if (!unionPayConfig.getPayWays().contains(payWayEnum.getCode())) {
|
||||
throw new PayFailureException("该云闪付支付方式不可用");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,16 +0,0 @@
|
||||
package cn.bootx.platform.daxpay.service.core.channel.union.service;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author xxm
|
||||
* @since 2022/3/11
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class UnionPaymentService {
|
||||
|
||||
}
|
@@ -63,7 +63,7 @@ public class WeChatPayConfigService {
|
||||
public WeChatPayConfig getAndCheckConfig(){
|
||||
WeChatPayConfig weChatPayConfig = getConfig();
|
||||
if (!weChatPayConfig.getEnable()){
|
||||
throw new PayFailureException("微信支付配置未启用");
|
||||
throw new PayFailureException("微信支付未启用");
|
||||
}
|
||||
return weChatPayConfig;
|
||||
}
|
||||
|
@@ -1,12 +1,28 @@
|
||||
package cn.bootx.platform.daxpay.service.core.payment.pay.strategy;
|
||||
|
||||
import cn.bootx.platform.daxpay.code.PayChannelEnum;
|
||||
import cn.bootx.platform.daxpay.exception.pay.PayAmountAbnormalException;
|
||||
import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
|
||||
import cn.bootx.platform.daxpay.param.channel.UnionPayParam;
|
||||
import cn.bootx.platform.daxpay.param.pay.PayChannelParam;
|
||||
import cn.bootx.platform.daxpay.service.common.context.PayLocal;
|
||||
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.union.entity.UnionPayConfig;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.union.service.UnionPayConfigService;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.union.service.UnionPayService;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayChannelOrder;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.service.PayChannelOrderService;
|
||||
import cn.bootx.platform.daxpay.service.func.AbsPayStrategy;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.json.JSONException;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;
|
||||
|
||||
/**
|
||||
@@ -21,14 +37,74 @@ import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROT
|
||||
@RequiredArgsConstructor
|
||||
public class UnionPayStrategy extends AbsPayStrategy {
|
||||
|
||||
private final PayChannelOrderService channelOrderService;
|
||||
private final UnionPayService unionPayService;
|
||||
|
||||
private final UnionPayConfigService unionPayConfigService;
|
||||
|
||||
private UnionPayParam unionPayParam;
|
||||
|
||||
private UnionPayConfig unionPayConfig;
|
||||
|
||||
@Override
|
||||
public PayChannelEnum getChannel() {
|
||||
return PayChannelEnum.UNION_PAY;
|
||||
}
|
||||
/**
|
||||
* 支付前操作
|
||||
*/
|
||||
@Override
|
||||
public void doBeforePayHandler() {
|
||||
try {
|
||||
// 支付宝参数验证
|
||||
Map<String, Object> channelParam = this.getPayChannelParam().getChannelParam();
|
||||
if (CollUtil.isNotEmpty(channelParam)) {
|
||||
this.unionPayParam = BeanUtil.toBean(channelParam, UnionPayParam.class);
|
||||
}
|
||||
else {
|
||||
this.unionPayParam = new UnionPayParam();
|
||||
}
|
||||
}
|
||||
catch (JSONException e) {
|
||||
throw new PayFailureException("支付参数错误");
|
||||
}
|
||||
// 检查金额
|
||||
PayChannelParam payMode = this.getPayChannelParam();
|
||||
if (payMode.getAmount() <= 0) {
|
||||
throw new PayAmountAbnormalException();
|
||||
}
|
||||
// 检查并获取支付宝支付配置
|
||||
this.unionPayConfig = unionPayConfigService.getAndCheckConfig();
|
||||
unionPayService.validation(this.getPayChannelParam(), unionPayConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发起支付操作
|
||||
*/
|
||||
@Override
|
||||
public void doPayHandler() {
|
||||
unionPayService.pay(this.getOrder(), this.getPayChannelParam(), this.unionPayParam, this.unionPayConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* 不使用默认的生成通道支付单方法, 异步支付通道的支付订单自己管理
|
||||
* channelOrderService.switchAsyncPayChannel 进行切换
|
||||
*/
|
||||
@Override
|
||||
public void generateChannelOrder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付调起成功, 保存或更新通道支付订单
|
||||
*/
|
||||
@Override
|
||||
public void doSuccessHandler() {
|
||||
PayLocal asyncPayInfo = PaymentContextLocal.get().getPayInfo();
|
||||
PayChannelOrder payChannelOrder = channelOrderService.switchAsyncPayChannel(this.getOrder(), this.getPayChannelParam());
|
||||
// 支付完成, 保存记录
|
||||
if (asyncPayInfo.isPayComplete()) {
|
||||
// aliRecordService.pay(this.getOrder(), payChannelOrder);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user