mirror of
https://gitee.com/dromara/dax-pay.git
synced 2025-10-14 22:00: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 jakarta.validation.constraints.NotNull;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.dromara.daxpay.channel.alipay.param.config.AliPayConfigParam;
|
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.dromara.daxpay.channel.alipay.service.config.AliPayConfigService;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
@@ -31,7 +31,7 @@ public class AliPayConfigController {
|
|||||||
@RequestPath("获取配置")
|
@RequestPath("获取配置")
|
||||||
@Operation(summary = "获取配置")
|
@Operation(summary = "获取配置")
|
||||||
@GetMapping("/findById")
|
@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));
|
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.entity.config.AliPayConfig;
|
||||||
import org.dromara.daxpay.channel.alipay.param.config.AliPayConfigParam;
|
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.Mapper;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
@@ -12,10 +12,10 @@ import org.mapstruct.factory.Mappers;
|
|||||||
* @since 2024/6/25
|
* @since 2024/6/25
|
||||||
*/
|
*/
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface AlipayConfigConvert {
|
public interface AliPayConfigConvert {
|
||||||
AlipayConfigConvert CONVERT = Mappers.getMapper(AlipayConfigConvert.class);
|
AliPayConfigConvert CONVERT = Mappers.getMapper(AliPayConfigConvert.class);
|
||||||
|
|
||||||
AlipayConfigResult toResult(AliPayConfig in);
|
AliPayConfigResult toResult(AliPayConfig in);
|
||||||
|
|
||||||
AliPayConfig copy(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.common.mybatisplus.function.ToResult;
|
||||||
import cn.bootx.platform.core.util.JsonUtil;
|
import cn.bootx.platform.core.util.JsonUtil;
|
||||||
import org.dromara.daxpay.channel.alipay.code.AliPayCode;
|
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.result.config.AlipayConfigResult;
|
import org.dromara.daxpay.channel.alipay.result.config.AliPayConfigResult;
|
||||||
import org.dromara.daxpay.core.enums.ChannelEnum;
|
import org.dromara.daxpay.core.enums.ChannelEnum;
|
||||||
import org.dromara.daxpay.service.entity.config.ChannelConfig;
|
import org.dromara.daxpay.service.entity.config.ChannelConfig;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -19,7 +19,7 @@ import java.math.BigDecimal;
|
|||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
public class AliPayConfig implements ToResult<AlipayConfigResult> {
|
public class AliPayConfig implements ToResult<AliPayConfigResult> {
|
||||||
|
|
||||||
/** 主键 */
|
/** 主键 */
|
||||||
private Long id;
|
private Long id;
|
||||||
@@ -78,7 +78,7 @@ public class AliPayConfig implements ToResult<AlipayConfigResult> {
|
|||||||
channelConfig.setAppId(this.getAppId());
|
channelConfig.setAppId(this.getAppId());
|
||||||
channelConfig.setEnable(this.getEnable());
|
channelConfig.setEnable(this.getEnable());
|
||||||
channelConfig.setChannel(ChannelEnum.ALI.getCode());
|
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);
|
copy.setId(null).setAppId(null).setEnable(null).setAliAppId(null).setAppId(null);
|
||||||
String jsonStr = JsonUtil.toJsonStr(copy);
|
String jsonStr = JsonUtil.toJsonStr(copy);
|
||||||
@@ -99,7 +99,7 @@ public class AliPayConfig implements ToResult<AlipayConfigResult> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AlipayConfigResult toResult() {
|
public AliPayConfigResult toResult() {
|
||||||
return AlipayConfigConvert.CONVERT.toResult(this);
|
return AliPayConfigConvert.CONVERT.toResult(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -10,7 +10,7 @@ import lombok.Data;
|
|||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@Schema(title = "支付宝支付参数")
|
@Schema(title = "支付宝支付参数")
|
||||||
public class AlipayParam {
|
public class AliPayParam {
|
||||||
/**
|
/**
|
||||||
* 授权码(主动扫描用户的付款码)
|
* 授权码(主动扫描用户的付款码)
|
||||||
*/
|
*/
|
@@ -16,7 +16,7 @@ import java.math.BigDecimal;
|
|||||||
@Data
|
@Data
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
@Schema(title = "支付宝配置")
|
@Schema(title = "支付宝配置")
|
||||||
public class AlipayConfigResult {
|
public class AliPayConfigResult {
|
||||||
|
|
||||||
/** 主键 */
|
/** 主键 */
|
||||||
@Schema(description = "主键")
|
@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.SneakyThrows;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.dromara.daxpay.channel.alipay.code.AliPayCode;
|
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.entity.config.AliPayConfig;
|
||||||
import org.dromara.daxpay.channel.alipay.param.config.AliPayConfigParam;
|
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.enums.ChannelEnum;
|
||||||
import org.dromara.daxpay.core.exception.ChannelNotEnableException;
|
import org.dromara.daxpay.core.exception.ChannelNotEnableException;
|
||||||
import org.dromara.daxpay.core.exception.ConfigNotEnableException;
|
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)
|
return channelConfigManager.findById(id)
|
||||||
.map(AliPayConfig::convertConfig)
|
.map(AliPayConfig::convertConfig)
|
||||||
.map(AliPayConfig::toResult)
|
.map(AliPayConfig::toResult)
|
||||||
@@ -71,7 +71,7 @@ public class AliPayConfigService {
|
|||||||
* 添加
|
* 添加
|
||||||
*/
|
*/
|
||||||
public void save(AliPayConfigParam param) {
|
public void save(AliPayConfigParam param) {
|
||||||
AliPayConfig entity = AlipayConfigConvert.CONVERT.toEntity(param);
|
AliPayConfig entity = AliPayConfigConvert.CONVERT.toEntity(param);
|
||||||
ChannelConfig channelConfig = entity.toChannelConfig();
|
ChannelConfig channelConfig = entity.toChannelConfig();
|
||||||
// 判断商户应用下是否存在该配置
|
// 判断商户应用下是否存在该配置
|
||||||
if (channelConfigManager.existsByAppIdAndChannel(channelConfig.getAppId(), channelConfig.getChannel())){
|
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 cn.bootx.platform.core.util.BigDecimalUtil;
|
||||||
import org.dromara.daxpay.channel.alipay.code.AliPayCode;
|
import org.dromara.daxpay.channel.alipay.code.AliPayCode;
|
||||||
import org.dromara.daxpay.channel.alipay.entity.config.AliPayConfig;
|
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.channel.alipay.service.config.AliPayConfigService;
|
||||||
import org.dromara.daxpay.core.enums.PayMethodEnum;
|
import org.dromara.daxpay.core.enums.PayMethodEnum;
|
||||||
import org.dromara.daxpay.core.exception.AmountExceedLimitException;
|
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 amount = PayUtil.toDecimal(payOrder.getAmount()).toString();
|
||||||
String payBody = null;
|
String payBody = null;
|
||||||
// 异步线程存储
|
// 异步线程存储
|
||||||
@@ -209,7 +209,7 @@ public class AliPayService {
|
|||||||
* jsapi支付
|
* jsapi支付
|
||||||
*/
|
*/
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public String jsapiPay(String amount, PayOrder payOrder, AlipayParam aliPayParam) {
|
public String jsapiPay(String amount, PayOrder payOrder, AliPayParam aliPayParam) {
|
||||||
// 构造请求参数以调用接口
|
// 构造请求参数以调用接口
|
||||||
AlipayTradeCreateRequest request = new AlipayTradeCreateRequest();
|
AlipayTradeCreateRequest request = new AlipayTradeCreateRequest();
|
||||||
AlipayTradeCreateModel model = new AlipayTradeCreateModel();
|
AlipayTradeCreateModel model = new AlipayTradeCreateModel();
|
||||||
@@ -280,7 +280,7 @@ public class AliPayService {
|
|||||||
* 付款码支付
|
* 付款码支付
|
||||||
*/
|
*/
|
||||||
@SneakyThrows
|
@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();
|
AlipayTradePayModel model = new AlipayTradePayModel();
|
||||||
model.setSubject(payOrder.getTitle());
|
model.setSubject(payOrder.getTitle());
|
||||||
model.setOutTradeNo(payOrder.getOrderNo());
|
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
|
@Service
|
||||||
@Scope(SCOPE_PROTOTYPE)
|
@Scope(SCOPE_PROTOTYPE)
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class AlipayReconcileStrategy extends AbsReconcileStrategy {
|
public class AliPayReconcileStrategy extends AbsReconcileStrategy {
|
||||||
|
|
||||||
private final AliPayReconcileService reconcileService;
|
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.exception.ValidationFailedException;
|
||||||
import cn.bootx.platform.core.util.JsonUtil;
|
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.channel.alipay.service.pay.AliPayService;
|
||||||
import org.dromara.daxpay.core.enums.ChannelEnum;
|
import org.dromara.daxpay.core.enums.ChannelEnum;
|
||||||
import org.dromara.daxpay.service.bo.trade.PayResultBo;
|
import org.dromara.daxpay.service.bo.trade.PayResultBo;
|
||||||
@@ -27,7 +27,7 @@ public class AliPayStrategy extends AbsPayStrategy {
|
|||||||
|
|
||||||
private final AliPayService aliPayService;
|
private final AliPayService aliPayService;
|
||||||
|
|
||||||
private AlipayParam aliPayParam;
|
private AliPayParam aliPayParam;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getChannel() {
|
public String getChannel() {
|
||||||
@@ -43,10 +43,10 @@ public class AliPayStrategy extends AbsPayStrategy {
|
|||||||
// 支付宝参数验证
|
// 支付宝参数验证
|
||||||
String channelParam = this.getPayParam().getExtraParam();
|
String channelParam = this.getPayParam().getExtraParam();
|
||||||
if (StrUtil.isNotBlank(channelParam)) {
|
if (StrUtil.isNotBlank(channelParam)) {
|
||||||
this.aliPayParam = JsonUtil.toBean(channelParam, AlipayParam.class);
|
this.aliPayParam = JsonUtil.toBean(channelParam, AliPayParam.class);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.aliPayParam = new AlipayParam();
|
this.aliPayParam = new AliPayParam();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (JSONException e) {
|
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.Receiver;
|
||||||
import com.github.binarywang.wxpay.bean.profitsharing.request.ProfitSharingReceiverRequest;
|
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.bean.profitsharing.request.ProfitSharingReceiverV3Request;
|
||||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
import com.github.binarywang.wxpay.exception.WxPayException;
|
@@ -4,8 +4,8 @@ import lombok.RequiredArgsConstructor;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.dromara.daxpay.channel.wechat.code.WechatPayCode;
|
import org.dromara.daxpay.channel.wechat.code.WechatPayCode;
|
||||||
import org.dromara.daxpay.channel.wechat.entity.config.WechatPayConfig;
|
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.receiver.WechatPayAllocReceiverV2Service;
|
||||||
import org.dromara.daxpay.channel.wechat.service.allocation.WechatPayAllocReceiverV3Service;
|
import org.dromara.daxpay.channel.wechat.service.allocation.receiver.WechatPayAllocReceiverV3Service;
|
||||||
import org.dromara.daxpay.channel.wechat.service.config.WechatPayConfigService;
|
import org.dromara.daxpay.channel.wechat.service.config.WechatPayConfigService;
|
||||||
import org.dromara.daxpay.core.enums.AllocReceiverTypeEnum;
|
import org.dromara.daxpay.core.enums.AllocReceiverTypeEnum;
|
||||||
import org.dromara.daxpay.core.enums.ChannelEnum;
|
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.Data;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
|
import org.dromara.daxpay.core.enums.AllocationStatusEnum;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分账操作结果
|
* 分账操作结果
|
||||||
@@ -14,4 +15,9 @@ public class AllocStartResultBo {
|
|||||||
|
|
||||||
/** 通道分账号 */
|
/** 通道分账号 */
|
||||||
private String outAllocNo;
|
private String outAllocNo;
|
||||||
|
/**
|
||||||
|
* 分账状态
|
||||||
|
* @see AllocationStatusEnum
|
||||||
|
*/
|
||||||
|
private String status;
|
||||||
}
|
}
|
||||||
|
@@ -18,25 +18,27 @@ import java.util.List;
|
|||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
public abstract class AbsAllocationStrategy implements PaymentStrategy{
|
public abstract class AbsAllocationStrategy implements PaymentStrategy{
|
||||||
private AllocOrder transaction;
|
private AllocOrder order;
|
||||||
|
|
||||||
private List<AllocDetail> details;
|
private List<AllocDetail> details;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化参数
|
* 初始化参数
|
||||||
*/
|
*/
|
||||||
public void initParam(AllocOrder transaction, List<AllocDetail> details) {
|
public void initParam(AllocOrder order, List<AllocDetail> details) {
|
||||||
this.transaction = transaction;
|
this.order = order;
|
||||||
this.details = details;
|
this.details = details;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 操作前处理, 校验和初始化支付配置
|
* 操作前处理, 校验和初始化支付配置
|
||||||
*/
|
*/
|
||||||
public abstract void doBeforeHandler();
|
public void doBeforeHandler(){
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分账启动
|
* 开始分账
|
||||||
*/
|
*/
|
||||||
public abstract AllocStartResultBo start();
|
public abstract AllocStartResultBo start();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user