mirror of
https://gitee.com/dromara/dax-pay.git
synced 2025-10-13 21:30:25 +00:00
feat: 新增支付宝分账和微信服务
This commit is contained in:
@@ -9,7 +9,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.daxpay.channel.alipay.param.config.AliPayConfigParam;
|
||||
import org.dromara.daxpay.channel.alipay.result.config.AlipayConfigResult;
|
||||
import org.dromara.daxpay.channel.alipay.result.config.AliPayConfigResult;
|
||||
import org.dromara.daxpay.channel.alipay.service.config.AliPayConfigService;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@@ -31,7 +31,7 @@ public class AliPayConfigController {
|
||||
@RequestPath("获取配置")
|
||||
@Operation(summary = "获取配置")
|
||||
@GetMapping("/findById")
|
||||
public Result<AlipayConfigResult> findById(@NotNull(message = "ID不可为空") Long id) {
|
||||
public Result<AliPayConfigResult> findById(@NotNull(message = "ID不可为空") Long id) {
|
||||
return Res.ok(alipayConfigService.findById(id));
|
||||
}
|
||||
|
||||
|
@@ -2,7 +2,7 @@ package org.dromara.daxpay.channel.alipay.convert.config;
|
||||
|
||||
import org.dromara.daxpay.channel.alipay.entity.config.AliPayConfig;
|
||||
import org.dromara.daxpay.channel.alipay.param.config.AliPayConfigParam;
|
||||
import org.dromara.daxpay.channel.alipay.result.config.AlipayConfigResult;
|
||||
import org.dromara.daxpay.channel.alipay.result.config.AliPayConfigResult;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
@@ -12,10 +12,10 @@ import org.mapstruct.factory.Mappers;
|
||||
* @since 2024/6/25
|
||||
*/
|
||||
@Mapper
|
||||
public interface AlipayConfigConvert {
|
||||
AlipayConfigConvert CONVERT = Mappers.getMapper(AlipayConfigConvert.class);
|
||||
public interface AliPayConfigConvert {
|
||||
AliPayConfigConvert CONVERT = Mappers.getMapper(AliPayConfigConvert.class);
|
||||
|
||||
AlipayConfigResult toResult(AliPayConfig in);
|
||||
AliPayConfigResult toResult(AliPayConfig in);
|
||||
|
||||
AliPayConfig copy(AliPayConfig in);
|
||||
|
@@ -3,8 +3,8 @@ package org.dromara.daxpay.channel.alipay.entity.config;
|
||||
import cn.bootx.platform.common.mybatisplus.function.ToResult;
|
||||
import cn.bootx.platform.core.util.JsonUtil;
|
||||
import org.dromara.daxpay.channel.alipay.code.AliPayCode;
|
||||
import org.dromara.daxpay.channel.alipay.convert.config.AlipayConfigConvert;
|
||||
import org.dromara.daxpay.channel.alipay.result.config.AlipayConfigResult;
|
||||
import org.dromara.daxpay.channel.alipay.convert.config.AliPayConfigConvert;
|
||||
import org.dromara.daxpay.channel.alipay.result.config.AliPayConfigResult;
|
||||
import org.dromara.daxpay.core.enums.ChannelEnum;
|
||||
import org.dromara.daxpay.service.entity.config.ChannelConfig;
|
||||
import lombok.Data;
|
||||
@@ -19,7 +19,7 @@ import java.math.BigDecimal;
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AliPayConfig implements ToResult<AlipayConfigResult> {
|
||||
public class AliPayConfig implements ToResult<AliPayConfigResult> {
|
||||
|
||||
/** 主键 */
|
||||
private Long id;
|
||||
@@ -78,7 +78,7 @@ public class AliPayConfig implements ToResult<AlipayConfigResult> {
|
||||
channelConfig.setAppId(this.getAppId());
|
||||
channelConfig.setEnable(this.getEnable());
|
||||
channelConfig.setChannel(ChannelEnum.ALI.getCode());
|
||||
AliPayConfig copy = AlipayConfigConvert.CONVERT.copy(this);
|
||||
AliPayConfig copy = AliPayConfigConvert.CONVERT.copy(this);
|
||||
// 清空不需要序列化的字段
|
||||
copy.setId(null).setAppId(null).setEnable(null).setAliAppId(null).setAppId(null);
|
||||
String jsonStr = JsonUtil.toJsonStr(copy);
|
||||
@@ -99,7 +99,7 @@ public class AliPayConfig implements ToResult<AlipayConfigResult> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AlipayConfigResult toResult() {
|
||||
return AlipayConfigConvert.CONVERT.toResult(this);
|
||||
public AliPayConfigResult toResult() {
|
||||
return AliPayConfigConvert.CONVERT.toResult(this);
|
||||
}
|
||||
}
|
||||
|
@@ -10,7 +10,7 @@ import lombok.Data;
|
||||
*/
|
||||
@Data
|
||||
@Schema(title = "支付宝支付参数")
|
||||
public class AlipayParam {
|
||||
public class AliPayParam {
|
||||
/**
|
||||
* 授权码(主动扫描用户的付款码)
|
||||
*/
|
@@ -16,7 +16,7 @@ import java.math.BigDecimal;
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "支付宝配置")
|
||||
public class AlipayConfigResult {
|
||||
public class AliPayConfigResult {
|
||||
|
||||
/** 主键 */
|
||||
@Schema(description = "主键")
|
@@ -0,0 +1,178 @@
|
||||
package org.dromara.daxpay.channel.alipay.service.allocation;
|
||||
|
||||
import cn.bootx.platform.common.mybatisplus.base.MpIdEntity;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alipay.api.AlipayApiException;
|
||||
import com.alipay.api.AlipayResponse;
|
||||
import com.alipay.api.domain.AlipayTradeOrderSettleModel;
|
||||
import com.alipay.api.domain.OpenApiRoyaltyDetailInfoPojo;
|
||||
import com.alipay.api.domain.SettleExtendParams;
|
||||
import com.alipay.api.request.AlipayTradeOrderSettleRequest;
|
||||
import com.alipay.api.response.AlipayTradeOrderSettleResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.daxpay.channel.alipay.code.AliPayCode;
|
||||
import org.dromara.daxpay.channel.alipay.service.config.AliPayConfigService;
|
||||
import org.dromara.daxpay.core.enums.AllocDetailResultEnum;
|
||||
import org.dromara.daxpay.core.exception.TradeFailException;
|
||||
import org.dromara.daxpay.core.util.PayUtil;
|
||||
import org.dromara.daxpay.service.bo.allocation.AllocStartResultBo;
|
||||
import org.dromara.daxpay.service.entity.allocation.transaction.AllocDetail;
|
||||
import org.dromara.daxpay.service.entity.allocation.transaction.AllocOrder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 支付宝分账服务
|
||||
* @author xxm
|
||||
* @since 2024/12/9
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AliPayAllocationService {
|
||||
private final AliPayConfigService aliPayConfigService;
|
||||
|
||||
/**
|
||||
* 发起分账
|
||||
*/
|
||||
public AllocStartResultBo start(AllocOrder allocOrder, List<AllocDetail> orderDetails){
|
||||
// 分账主体参数
|
||||
AlipayTradeOrderSettleModel model = new AlipayTradeOrderSettleModel();
|
||||
model.setOutRequestNo(allocOrder.getAllocNo());
|
||||
model.setTradeNo(allocOrder.getOutOrderNo());
|
||||
model.setRoyaltyMode(AliPayCode.ALLOC_ASYNC);
|
||||
|
||||
// 分账子参数 根据Id排序
|
||||
orderDetails.sort(Comparator.comparing(MpIdEntity::getId));
|
||||
List<OpenApiRoyaltyDetailInfoPojo> royaltyParameters = orderDetails.stream()
|
||||
.map(o -> {
|
||||
OpenApiRoyaltyDetailInfoPojo infoPojo = new OpenApiRoyaltyDetailInfoPojo();
|
||||
infoPojo.setAmount(PayUtil.toDecimal(o.getAmount()).toPlainString());
|
||||
infoPojo.setTransIn(o.getReceiverAccount());
|
||||
return infoPojo;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
model.setRoyaltyParameters(royaltyParameters);
|
||||
AlipayTradeOrderSettleRequest request = new AlipayTradeOrderSettleRequest();
|
||||
request.setBizModel(model);
|
||||
AlipayTradeOrderSettleResponse response = null;
|
||||
try {
|
||||
response = aliPayConfigService.execute(request);
|
||||
this.verifyErrorMsg(response);
|
||||
} catch (AlipayApiException e) {
|
||||
log.error("网关返回分账失败: {}", e.getMessage());
|
||||
throw new TradeFailException(e.getMessage());
|
||||
}
|
||||
// 需要写入到分账订单中
|
||||
String settleNo = response.getSettleNo();
|
||||
return new AllocStartResultBo().setOutAllocNo(settleNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分账完结
|
||||
*/
|
||||
public void finish(AllocOrder allocOrder, List<AllocDetail> orderDetails){
|
||||
// 分账主体参数
|
||||
AlipayTradeOrderSettleModel model = new AlipayTradeOrderSettleModel();
|
||||
model.setOutRequestNo(String.valueOf(allocOrder.getAllocNo()));
|
||||
model.setTradeNo(allocOrder.getOutOrderNo());
|
||||
model.setRoyaltyMode(AliPayCode.ALLOC_ASYNC);
|
||||
// 分账完结参数
|
||||
SettleExtendParams extendParams = new SettleExtendParams();
|
||||
extendParams.setRoyaltyFinish(Boolean.TRUE.toString());
|
||||
model.setExtendParams(extendParams);
|
||||
|
||||
// 分账子参数 根据Id排序
|
||||
orderDetails.sort(Comparator.comparing(MpIdEntity::getId));
|
||||
List<OpenApiRoyaltyDetailInfoPojo> royaltyParameters = orderDetails.stream()
|
||||
.map(o -> {
|
||||
OpenApiRoyaltyDetailInfoPojo infoPojo = new OpenApiRoyaltyDetailInfoPojo();
|
||||
infoPojo.setAmount(PayUtil.toDecimal(o.getAmount()).toPlainString());
|
||||
infoPojo.setTransIn(o.getReceiverAccount());
|
||||
return infoPojo;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
model.setRoyaltyParameters(royaltyParameters);
|
||||
AlipayTradeOrderSettleRequest request = new AlipayTradeOrderSettleRequest();
|
||||
request.setBizModel(model);
|
||||
AlipayTradeOrderSettleResponse response = null;
|
||||
try {
|
||||
response = aliPayConfigService.execute(request);
|
||||
} catch (AlipayApiException e) {
|
||||
log.error("网关返回分账失败: {}", e.getMessage());
|
||||
throw new TradeFailException(e.getMessage());
|
||||
}
|
||||
this.verifyErrorMsg(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分账状态同步
|
||||
*/
|
||||
// @SneakyThrows
|
||||
// public AllocRemoteSyncResult sync(AllocOrder allocOrder, List<AllocDetail> allocOrderDetails, AliPayConfig config){
|
||||
// AlipayClient alipayClient = aliPayConfigService.getAlipayClient(config);
|
||||
// AlipayTradeOrderSettleQueryModel model = new AlipayTradeOrderSettleQueryModel();
|
||||
// model.setTradeNo(allocOrder.getOutOrderNo());
|
||||
// model.setOutRequestNo(allocOrder.getAllocNo());
|
||||
// AlipayTradeOrderSettleQueryRequest request = new AlipayTradeOrderSettleQueryRequest();
|
||||
// request.setBizModel(model);
|
||||
// AlipayTradeOrderSettleQueryResponse response = alipayClient.execute(request);
|
||||
// // 验证
|
||||
// this.verifyErrorMsg(response);
|
||||
// Map<String, AllocOrderDetail> detailMap = allocOrderDetails.stream()
|
||||
// .collect(Collectors.toMap(AllocOrderDetail::getReceiverAccount, Function.identity(), CollectorsFunction::retainLatest));
|
||||
// List<RoyaltyDetail> royaltyDetailList = response.getRoyaltyDetailList();
|
||||
// for (RoyaltyDetail receiver : royaltyDetailList) {
|
||||
// AllocOrderDetail detail = detailMap.get(receiver.getTransIn());
|
||||
// if (Objects.nonNull(detail)) {
|
||||
// detail.setResult(this.getDetailResultEnum(receiver.getState()).getCode());
|
||||
// detail.setErrorCode(receiver.getErrorCode());
|
||||
// detail.setErrorMsg(receiver.getErrorDesc());
|
||||
// // 如果是完成, 更新时间
|
||||
// if (AllocDetailResultEnum.SUCCESS.getCode().equals(detail.getResult())){
|
||||
// LocalDateTime finishTime = LocalDateTimeUtil.of(receiver.getExecuteDt());
|
||||
// detail.setFinishTime(finishTime)
|
||||
// .setErrorMsg(null)
|
||||
// .setErrorCode(null);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return new AllocRemoteSyncResult().setSyncInfo(JSONUtil.toJsonStr(response));
|
||||
// }
|
||||
|
||||
/**
|
||||
* 验证错误信息
|
||||
*/
|
||||
private void verifyErrorMsg(AlipayResponse alipayResponse) {
|
||||
if (alipayResponse.isSuccess()) {
|
||||
String errorMsg = alipayResponse.getSubMsg();
|
||||
if (StrUtil.isBlank(errorMsg)) {
|
||||
errorMsg = alipayResponse.getMsg();
|
||||
}
|
||||
log.error("分账处理失败 {}", errorMsg);
|
||||
throw new TradeFailException(errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换支付宝分账类型到系统中统一的状态
|
||||
*/
|
||||
private AllocDetailResultEnum getDetailResultEnum (String result){
|
||||
// 进行中
|
||||
if(Objects.equals(AliPayCode.ALLOC_PROCESSING, result)){
|
||||
return AllocDetailResultEnum.PENDING;
|
||||
}
|
||||
// 成功
|
||||
if(Objects.equals(AliPayCode.ALLOC_SUCCESS, result)){
|
||||
return AllocDetailResultEnum.SUCCESS;
|
||||
}
|
||||
// 失败
|
||||
return AllocDetailResultEnum.FAIL;
|
||||
}
|
||||
|
||||
}
|
@@ -12,10 +12,10 @@ import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.daxpay.channel.alipay.code.AliPayCode;
|
||||
import org.dromara.daxpay.channel.alipay.convert.config.AlipayConfigConvert;
|
||||
import org.dromara.daxpay.channel.alipay.convert.config.AliPayConfigConvert;
|
||||
import org.dromara.daxpay.channel.alipay.entity.config.AliPayConfig;
|
||||
import org.dromara.daxpay.channel.alipay.param.config.AliPayConfigParam;
|
||||
import org.dromara.daxpay.channel.alipay.result.config.AlipayConfigResult;
|
||||
import org.dromara.daxpay.channel.alipay.result.config.AliPayConfigResult;
|
||||
import org.dromara.daxpay.core.enums.ChannelEnum;
|
||||
import org.dromara.daxpay.core.exception.ChannelNotEnableException;
|
||||
import org.dromara.daxpay.core.exception.ConfigNotEnableException;
|
||||
@@ -48,7 +48,7 @@ public class AliPayConfigService {
|
||||
/**
|
||||
* 查询
|
||||
*/
|
||||
public AlipayConfigResult findById(Long id) {
|
||||
public AliPayConfigResult findById(Long id) {
|
||||
return channelConfigManager.findById(id)
|
||||
.map(AliPayConfig::convertConfig)
|
||||
.map(AliPayConfig::toResult)
|
||||
@@ -71,7 +71,7 @@ public class AliPayConfigService {
|
||||
* 添加
|
||||
*/
|
||||
public void save(AliPayConfigParam param) {
|
||||
AliPayConfig entity = AlipayConfigConvert.CONVERT.toEntity(param);
|
||||
AliPayConfig entity = AliPayConfigConvert.CONVERT.toEntity(param);
|
||||
ChannelConfig channelConfig = entity.toChannelConfig();
|
||||
// 判断商户应用下是否存在该配置
|
||||
if (channelConfigManager.existsByAppIdAndChannel(channelConfig.getAppId(), channelConfig.getChannel())){
|
||||
|
@@ -3,7 +3,7 @@ package org.dromara.daxpay.channel.alipay.service.pay;
|
||||
import cn.bootx.platform.core.util.BigDecimalUtil;
|
||||
import org.dromara.daxpay.channel.alipay.code.AliPayCode;
|
||||
import org.dromara.daxpay.channel.alipay.entity.config.AliPayConfig;
|
||||
import org.dromara.daxpay.channel.alipay.param.pay.AlipayParam;
|
||||
import org.dromara.daxpay.channel.alipay.param.pay.AliPayParam;
|
||||
import org.dromara.daxpay.channel.alipay.service.config.AliPayConfigService;
|
||||
import org.dromara.daxpay.core.enums.PayMethodEnum;
|
||||
import org.dromara.daxpay.core.exception.AmountExceedLimitException;
|
||||
@@ -57,7 +57,7 @@ public class AliPayService {
|
||||
/**
|
||||
* 调起支付
|
||||
*/
|
||||
public PayResultBo pay(PayOrder payOrder, AlipayParam aliPayParam) {
|
||||
public PayResultBo pay(PayOrder payOrder, AliPayParam aliPayParam) {
|
||||
String amount = PayUtil.toDecimal(payOrder.getAmount()).toString();
|
||||
String payBody = null;
|
||||
// 异步线程存储
|
||||
@@ -209,7 +209,7 @@ public class AliPayService {
|
||||
* jsapi支付
|
||||
*/
|
||||
@SneakyThrows
|
||||
public String jsapiPay(String amount, PayOrder payOrder, AlipayParam aliPayParam) {
|
||||
public String jsapiPay(String amount, PayOrder payOrder, AliPayParam aliPayParam) {
|
||||
// 构造请求参数以调用接口
|
||||
AlipayTradeCreateRequest request = new AlipayTradeCreateRequest();
|
||||
AlipayTradeCreateModel model = new AlipayTradeCreateModel();
|
||||
@@ -280,7 +280,7 @@ public class AliPayService {
|
||||
* 付款码支付
|
||||
*/
|
||||
@SneakyThrows
|
||||
public void barCode(String amount, PayOrder payOrder, AlipayParam aliPayParam, PayResultBo result) {
|
||||
public void barCode(String amount, PayOrder payOrder, AliPayParam aliPayParam, PayResultBo result) {
|
||||
AlipayTradePayModel model = new AlipayTradePayModel();
|
||||
model.setSubject(payOrder.getTitle());
|
||||
model.setOutTradeNo(payOrder.getOrderNo());
|
||||
|
@@ -0,0 +1,46 @@
|
||||
package org.dromara.daxpay.channel.alipay.strategy;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.daxpay.channel.alipay.service.allocation.AliPayAllocationService;
|
||||
import org.dromara.daxpay.core.enums.ChannelEnum;
|
||||
import org.dromara.daxpay.service.bo.allocation.AllocStartResultBo;
|
||||
import org.dromara.daxpay.service.strategy.AbsAllocationStrategy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 支付宝分账
|
||||
* @author xxm
|
||||
* @since 2024/12/9
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class AliAllocationStrategy extends AbsAllocationStrategy {
|
||||
|
||||
private final AliPayAllocationService aliPayAllocationService;
|
||||
|
||||
/**
|
||||
* 分账通道
|
||||
*/
|
||||
@Override
|
||||
public String getChannel() {
|
||||
return ChannelEnum.ALI.getCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始分账
|
||||
*/
|
||||
@Override
|
||||
public AllocStartResultBo start() {
|
||||
return aliPayAllocationService.start(getOrder(), getDetails());
|
||||
}
|
||||
|
||||
/**
|
||||
* 分账完结
|
||||
*/
|
||||
@Override
|
||||
public void finish() {
|
||||
aliPayAllocationService.finish(getOrder(), getDetails());
|
||||
}
|
||||
}
|
@@ -25,7 +25,7 @@ import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROT
|
||||
@Service
|
||||
@Scope(SCOPE_PROTOTYPE)
|
||||
@RequiredArgsConstructor
|
||||
public class AlipayReconcileStrategy extends AbsReconcileStrategy {
|
||||
public class AliPayReconcileStrategy extends AbsReconcileStrategy {
|
||||
|
||||
private final AliPayReconcileService reconcileService;
|
||||
|
@@ -2,7 +2,7 @@ package org.dromara.daxpay.channel.alipay.strategy;
|
||||
|
||||
import cn.bootx.platform.core.exception.ValidationFailedException;
|
||||
import cn.bootx.platform.core.util.JsonUtil;
|
||||
import org.dromara.daxpay.channel.alipay.param.pay.AlipayParam;
|
||||
import org.dromara.daxpay.channel.alipay.param.pay.AliPayParam;
|
||||
import org.dromara.daxpay.channel.alipay.service.pay.AliPayService;
|
||||
import org.dromara.daxpay.core.enums.ChannelEnum;
|
||||
import org.dromara.daxpay.service.bo.trade.PayResultBo;
|
||||
@@ -27,7 +27,7 @@ public class AliPayStrategy extends AbsPayStrategy {
|
||||
|
||||
private final AliPayService aliPayService;
|
||||
|
||||
private AlipayParam aliPayParam;
|
||||
private AliPayParam aliPayParam;
|
||||
|
||||
@Override
|
||||
public String getChannel() {
|
||||
@@ -43,10 +43,10 @@ public class AliPayStrategy extends AbsPayStrategy {
|
||||
// 支付宝参数验证
|
||||
String channelParam = this.getPayParam().getExtraParam();
|
||||
if (StrUtil.isNotBlank(channelParam)) {
|
||||
this.aliPayParam = JsonUtil.toBean(channelParam, AlipayParam.class);
|
||||
this.aliPayParam = JsonUtil.toBean(channelParam, AliPayParam.class);
|
||||
}
|
||||
else {
|
||||
this.aliPayParam = new AlipayParam();
|
||||
this.aliPayParam = new AliPayParam();
|
||||
}
|
||||
}
|
||||
catch (JSONException e) {
|
||||
|
@@ -0,0 +1,16 @@
|
||||
package org.dromara.daxpay.channel.wechat.service.allocation;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 微信分账V2版本接口
|
||||
* @author xxm
|
||||
* @since 2024/12/9
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class WeChatPayAllocationV2Service {
|
||||
}
|
@@ -0,0 +1,106 @@
|
||||
package org.dromara.daxpay.channel.wechat.service.allocation;
|
||||
|
||||
import com.github.binarywang.wxpay.bean.profitsharing.request.ProfitSharingUnfreezeV3Request;
|
||||
import com.github.binarywang.wxpay.bean.profitsharing.request.ProfitSharingV3Request;
|
||||
import com.github.binarywang.wxpay.bean.profitsharing.result.ProfitSharingV3Result;
|
||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||
import com.github.binarywang.wxpay.service.ProfitSharingService;
|
||||
import com.github.binarywang.wxpay.service.WxPayService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.daxpay.channel.wechat.entity.config.WechatPayConfig;
|
||||
import org.dromara.daxpay.channel.wechat.service.config.WechatPayConfigService;
|
||||
import org.dromara.daxpay.core.enums.AllocReceiverTypeEnum;
|
||||
import org.dromara.daxpay.core.exception.ConfigErrorException;
|
||||
import org.dromara.daxpay.core.exception.OperationFailException;
|
||||
import org.dromara.daxpay.core.util.PayUtil;
|
||||
import org.dromara.daxpay.service.bo.allocation.AllocStartResultBo;
|
||||
import org.dromara.daxpay.service.entity.allocation.transaction.AllocDetail;
|
||||
import org.dromara.daxpay.service.entity.allocation.transaction.AllocOrder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.dromara.daxpay.core.enums.AllocReceiverTypeEnum.MERCHANT_NO;
|
||||
import static org.dromara.daxpay.core.enums.AllocReceiverTypeEnum.OPEN_ID;
|
||||
|
||||
/**
|
||||
* 微信分账V3版本接口
|
||||
* @author xxm
|
||||
* @since 2024/12/9
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class WeChatPayAllocationV3Service {
|
||||
private final WechatPayConfigService wechatPayConfigService;
|
||||
|
||||
/**
|
||||
* 发起分账
|
||||
*/
|
||||
public AllocStartResultBo start(AllocOrder allocOrder, List<AllocDetail> orderDetails, WechatPayConfig config){
|
||||
|
||||
WxPayService wxPayService = wechatPayConfigService.wxJavaSdk(config);
|
||||
ProfitSharingService sharingService = wxPayService.getProfitSharingService();
|
||||
|
||||
ProfitSharingV3Request request = new ProfitSharingV3Request();
|
||||
request.setOutOrderNo(allocOrder.getAllocNo());
|
||||
request.setTransactionId(allocOrder.getOutOrderNo());
|
||||
request.setUnfreezeUnsplit(true);
|
||||
|
||||
// 分账接收方信息
|
||||
var receivers = orderDetails.stream()
|
||||
.map(o -> {
|
||||
AllocReceiverTypeEnum receiverTypeEnum = AllocReceiverTypeEnum.findByCode(o.getReceiverType());
|
||||
String receiverType = this.getReceiverType(receiverTypeEnum);
|
||||
var receiver = new ProfitSharingV3Request.Receiver();
|
||||
receiver.setType(receiverType);
|
||||
receiver.setAmount(PayUtil.convertCentAmount(o.getAmount()));
|
||||
receiver.setAccount(o.getReceiverAccount());
|
||||
receiver.setName(o.getReceiverName());
|
||||
receiver.setDescription("订单分账");
|
||||
receiver.setRelationType("PARTNER");
|
||||
return receiver;
|
||||
})
|
||||
.toList();
|
||||
|
||||
request.setReceivers(receivers);
|
||||
try {
|
||||
ProfitSharingV3Result result = sharingService.profitSharingV3(request);
|
||||
|
||||
return new AllocStartResultBo().setOutAllocNo(result.getOrderId());
|
||||
} catch (WxPayException e) {
|
||||
throw new OperationFailException("微信分账V3失败: "+e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 分账完结
|
||||
*/
|
||||
public void finish(AllocOrder allocOrder, List<AllocDetail> orderDetails, WechatPayConfig config){
|
||||
WxPayService wxPayService = wechatPayConfigService.wxJavaSdk(config);
|
||||
ProfitSharingService sharingService = wxPayService.getProfitSharingService();
|
||||
var request = new ProfitSharingUnfreezeV3Request();
|
||||
request.setOutOrderNo(allocOrder.getAllocNo());
|
||||
request.setTransactionId(allocOrder.getOutOrderNo());
|
||||
request.setDescription("分账完结");
|
||||
try {
|
||||
sharingService.profitSharingUnfreeze(request);
|
||||
} catch (WxPayException e) {
|
||||
throw new OperationFailException("微信分账V3失败: "+e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分账接收方类型编码
|
||||
*/
|
||||
private String getReceiverType(AllocReceiverTypeEnum receiverTypeEnum){
|
||||
if (receiverTypeEnum == OPEN_ID){
|
||||
return "PERSONAL_OPENID";
|
||||
}
|
||||
if (receiverTypeEnum == MERCHANT_NO){
|
||||
return "MERCHANT_ID";
|
||||
}
|
||||
throw new ConfigErrorException("分账接收方类型错误");
|
||||
}
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
package org.dromara.daxpay.channel.wechat.service.allocation;
|
||||
package org.dromara.daxpay.channel.wechat.service.allocation.receiver;
|
||||
|
||||
import com.github.binarywang.wxpay.bean.profitsharing.Receiver;
|
||||
import com.github.binarywang.wxpay.bean.profitsharing.request.ProfitSharingReceiverRequest;
|
@@ -1,4 +1,4 @@
|
||||
package org.dromara.daxpay.channel.wechat.service.allocation;
|
||||
package org.dromara.daxpay.channel.wechat.service.allocation.receiver;
|
||||
|
||||
import com.github.binarywang.wxpay.bean.profitsharing.request.ProfitSharingReceiverV3Request;
|
||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
@@ -4,8 +4,8 @@ import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.daxpay.channel.wechat.code.WechatPayCode;
|
||||
import org.dromara.daxpay.channel.wechat.entity.config.WechatPayConfig;
|
||||
import org.dromara.daxpay.channel.wechat.service.allocation.WechatPayAllocReceiverV2Service;
|
||||
import org.dromara.daxpay.channel.wechat.service.allocation.WechatPayAllocReceiverV3Service;
|
||||
import org.dromara.daxpay.channel.wechat.service.allocation.receiver.WechatPayAllocReceiverV2Service;
|
||||
import org.dromara.daxpay.channel.wechat.service.allocation.receiver.WechatPayAllocReceiverV3Service;
|
||||
import org.dromara.daxpay.channel.wechat.service.config.WechatPayConfigService;
|
||||
import org.dromara.daxpay.core.enums.AllocReceiverTypeEnum;
|
||||
import org.dromara.daxpay.core.enums.ChannelEnum;
|
||||
|
@@ -0,0 +1,49 @@
|
||||
package org.dromara.daxpay.channel.wechat.strategy;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.daxpay.core.enums.ChannelEnum;
|
||||
import org.dromara.daxpay.service.bo.allocation.AllocStartResultBo;
|
||||
import org.dromara.daxpay.service.strategy.AbsAllocationStrategy;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;
|
||||
|
||||
/**
|
||||
* 微信分账策略
|
||||
* @author xxm
|
||||
* @since 2024/12/9
|
||||
*/
|
||||
@Slf4j
|
||||
@Scope(SCOPE_PROTOTYPE)
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class WechatAllocationStrategy extends AbsAllocationStrategy {
|
||||
|
||||
|
||||
/**
|
||||
* 分账通道
|
||||
*/
|
||||
@Override
|
||||
public String getChannel() {
|
||||
return ChannelEnum.WECHAT.getCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始分账
|
||||
*/
|
||||
@Override
|
||||
public AllocStartResultBo start() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public void finish() {
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -2,6 +2,7 @@ package org.dromara.daxpay.service.bo.allocation;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.dromara.daxpay.core.enums.AllocationStatusEnum;
|
||||
|
||||
/**
|
||||
* 分账操作结果
|
||||
@@ -14,4 +15,9 @@ public class AllocStartResultBo {
|
||||
|
||||
/** 通道分账号 */
|
||||
private String outAllocNo;
|
||||
/**
|
||||
* 分账状态
|
||||
* @see AllocationStatusEnum
|
||||
*/
|
||||
private String status;
|
||||
}
|
||||
|
@@ -18,25 +18,27 @@ import java.util.List;
|
||||
@Getter
|
||||
@Setter
|
||||
public abstract class AbsAllocationStrategy implements PaymentStrategy{
|
||||
private AllocOrder transaction;
|
||||
private AllocOrder order;
|
||||
|
||||
private List<AllocDetail> details;
|
||||
|
||||
/**
|
||||
* 初始化参数
|
||||
*/
|
||||
public void initParam(AllocOrder transaction, List<AllocDetail> details) {
|
||||
this.transaction = transaction;
|
||||
public void initParam(AllocOrder order, List<AllocDetail> details) {
|
||||
this.order = order;
|
||||
this.details = details;
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作前处理, 校验和初始化支付配置
|
||||
*/
|
||||
public abstract void doBeforeHandler();
|
||||
public void doBeforeHandler(){
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* 分账启动
|
||||
* 开始分账
|
||||
*/
|
||||
public abstract AllocStartResultBo start();
|
||||
|
||||
|
Reference in New Issue
Block a user