feat 支付宝服务商支付

This commit is contained in:
DaxPay
2024-12-24 18:52:09 +08:00
parent a5c72b8578
commit fb1014d907
54 changed files with 1013 additions and 454 deletions

View File

@@ -4,16 +4,15 @@
- [ ] 同步回调页
- [ ] 收银台功能优化
- [ ] 支持配置背景色和图标
- [ ] 定时同步任务频次不要太高, 预防产生过多的数据
- [ ] 对各种交易增加新的同步失败异常处理, 防止同步失败后无限进行同步
- [ ] 增加首页驾驶舱功能
- [ ] 商户应用要有类似删除的功能, 实现停用冻结, 但不影响数据的关联
- [ ] 同步接口优化, 返回同步完的数据
- [ ] 服务商支付支持
- [ ] 支付宝
- [x] 支付宝
- [ ] 微信
- [ ] 微信增加公钥证书方式
- [ ] 分账重试
- [ ] 对各种交易增加新的异常处理, 防止同步失败后无限进行同步
## 3.0.0.bate3: 分账
- [x] SDK接口
- [x] 分账相关接口: 分账,完结,同步,查询

View File

@@ -12,7 +12,7 @@ import lombok.EqualsAndHashCode;
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class AliReconcileBillDetail extends MpIdEntity {
public class AlipayReconcileBillDetail extends MpIdEntity {
@Alias("支付宝交易号")
private String tradeNo;
@Alias("商户订单号")

View File

@@ -14,7 +14,7 @@ import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
@TableName("pay_alipay_reconcile_bill_total")
public class AliReconcileBillTotal extends MpIdEntity {
public class AlipayReconcileBillTotal extends MpIdEntity {
@Alias("门店编号")
private String storeId;
@Alias("门店名称")

View File

@@ -6,7 +6,7 @@ package org.dromara.daxpay.channel.alipay.code;
* @author xxm
* @since 2021/2/27
*/
public interface AliPayCode {
public interface AlipayCode {
/**
* 支付网管地址

View File

@@ -5,7 +5,7 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.dromara.daxpay.channel.alipay.service.callback.AliPayCallbackService;
import org.dromara.daxpay.channel.alipay.service.callback.AlipayCallbackService;
import org.dromara.daxpay.service.service.assist.PaymentAssistService;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
@@ -23,15 +23,22 @@ import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/unipay/callback/{AppId}")
@RequiredArgsConstructor
public class AliPayCallbackController {
public class AlipayCallbackController {
private final PaymentAssistService paymentAssistService;
private final AliPayCallbackService payCallbackService;
private final AlipayCallbackService payCallbackService;
@Operation(summary = "支付宝回调")
@Operation(summary = "支付宝回调(普通商户)")
@PostMapping("/alipay")
public String aliPayNotify( @PathVariable("AppId") String appId, HttpServletRequest request) {
public String aliPayNotify(@PathVariable("AppId") String appId, HttpServletRequest request) {
paymentAssistService.initMchApp(appId);
return payCallbackService.callbackHandle(request);
return payCallbackService.callbackHandle(request,false);
}
@Operation(summary = "支付宝回调(特约商户)")
@PostMapping("/alipay/isv")
public String aliPayIsvNotify(@PathVariable("AppId") String appId, HttpServletRequest request) {
paymentAssistService.initMchApp(appId);
return payCallbackService.callbackHandle(request, true);
}
}

View File

@@ -8,9 +8,9 @@ import io.swagger.v3.oas.annotations.Operation;
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.service.config.AliPayConfigService;
import org.dromara.daxpay.channel.alipay.param.config.AlipayConfigParam;
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.*;
@@ -25,20 +25,20 @@ import org.springframework.web.bind.annotation.*;
@RequestMapping("/alipay/config")
@RequiredArgsConstructor
@RequestGroup(groupCode = "AlipayConfig", groupName = "支付宝配置", moduleCode = "alipay", moduleName = "支付宝通道")
public class AliPayConfigController {
private final AliPayConfigService alipayConfigService;
public class AlipayConfigController {
private final AlipayConfigService alipayConfigService;
@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));
}
@RequestPath("新增或更新")
@Operation(summary = "新增或更新")
@PostMapping("/saveOrUpdate")
public Result<Void> saveOrUpdate(@RequestBody AliPayConfigParam param) {
public Result<Void> saveOrUpdate(@RequestBody AlipayConfigParam param) {
alipayConfigService.saveOrUpdate(param);
return Res.ok();
}

View File

@@ -1,12 +1,12 @@
package org.dromara.daxpay.channel.alipay.controller;
import cn.bootx.platform.core.annotation.IgnoreAuth;
import org.dromara.daxpay.channel.alipay.service.notice.AliPayNoticeReceiverService;
import org.dromara.daxpay.service.service.assist.PaymentAssistService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.dromara.daxpay.channel.alipay.service.notice.AlipayNoticeReceiverService;
import org.dromara.daxpay.service.service.assist.PaymentAssistService;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -22,16 +22,22 @@ import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/unipay/notice/{AppId}")
@RequiredArgsConstructor
public class AliPayNoticeReceiverController {
public class AlipayNoticeReceiverController {
private final AliPayNoticeReceiverService aliPayNoticeReceiverService;
private final AlipayNoticeReceiverService aliPayNoticeReceiverService;
private final PaymentAssistService paymentAssistService;
@Operation(summary = "支付宝消息通知")
@Operation(summary = "支付宝消息通知(普通商户)")
@PostMapping("/alipay")
public String aliPayNotice(@PathVariable("AppId") String appId, HttpServletRequest request) {
public String aliPay(@PathVariable("AppId") String appId, HttpServletRequest request) {
paymentAssistService.initMchApp(appId);
return aliPayNoticeReceiverService.noticeReceiver(request);
return aliPayNoticeReceiverService.noticeReceiver(request,false);
}
@Operation(summary = "支付宝消息通知(特约商户)")
@PostMapping("/alipay/isv")
public String aliPayIsv(@PathVariable("AppId") String appId, HttpServletRequest request) {
paymentAssistService.initMchApp(appId);
return aliPayNoticeReceiverService.noticeReceiver(request,true);
}
}

View File

@@ -1,7 +1,7 @@
package org.dromara.daxpay.channel.alipay.controller;
import cn.bootx.platform.core.annotation.IgnoreAuth;
import org.dromara.daxpay.channel.alipay.service.redirect.AliPayRedirectUrlService;
import org.dromara.daxpay.channel.alipay.service.redirect.AlipayRedirectUrlService;
import org.dromara.daxpay.service.service.assist.PaymentAssistService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -23,15 +23,22 @@ import org.springframework.web.servlet.ModelAndView;
@RestController
@RequestMapping("/unipay/return/{AppId}")
@RequiredArgsConstructor
public class AliPayRedirectUrlController {
private final AliPayRedirectUrlService redirectUrlService;
public class AlipayRedirectUrlController {
private final AlipayRedirectUrlService redirectUrlService;
private final PaymentAssistService paymentAssistService;
@Operation(summary = "支付宝同步跳转通知")
@GetMapping("/alipay")
public ModelAndView alipay(@PathVariable("AppId") String appId, HttpServletRequest request){
paymentAssistService.initMchApp(appId);
String redirect = redirectUrlService.redirect(request);
String redirect = redirectUrlService.redirect(request,false);
return new ModelAndView("redirect:"+redirect);
}
@Operation(summary = "支付宝同步跳转通知")
@GetMapping("/alipay/isv")
public ModelAndView alipayIsv(@PathVariable("AppId") String appId, HttpServletRequest request){
paymentAssistService.initMchApp(appId);
String redirect = redirectUrlService.redirect(request, true);
return new ModelAndView("redirect:"+redirect);
}
}

View File

@@ -1,23 +0,0 @@
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.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
/**
*
* @author xxm
* @since 2024/6/25
*/
@Mapper
public interface AliPayConfigConvert {
AliPayConfigConvert CONVERT = Mappers.getMapper(AliPayConfigConvert.class);
AliPayConfigResult toResult(AliPayConfig in);
AliPayConfig copy(AliPayConfig in);
AliPayConfig toEntity(AliPayConfigParam in);
}

View File

@@ -0,0 +1,23 @@
package org.dromara.daxpay.channel.alipay.convert.config;
import org.dromara.daxpay.channel.alipay.entity.AliPayConfig;
import org.dromara.daxpay.channel.alipay.param.config.AlipayConfigParam;
import org.dromara.daxpay.channel.alipay.result.config.AlipayConfigResult;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
/**
*
* @author xxm
* @since 2024/6/25
*/
@Mapper
public interface AlipayConfigConvert {
AlipayConfigConvert CONVERT = Mappers.getMapper(AlipayConfigConvert.class);
AlipayConfigResult toResult(AliPayConfig in);
AliPayConfig copy(AliPayConfig in);
AliPayConfig toEntity(AlipayConfigParam in);
}

View File

@@ -1,10 +1,9 @@
package org.dromara.daxpay.channel.alipay.entity.config;
package org.dromara.daxpay.channel.alipay.entity;
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;
@@ -13,20 +12,25 @@ import lombok.experimental.Accessors;
import java.math.BigDecimal;
/**
* 支付宝配置
* 支付宝配置(防止与sdk中类重名, P大写)
* @author xxm
* @since 2024/6/25
*/
@Data
@Accessors(chain = true)
public class AliPayConfig implements ToResult<AliPayConfigResult> {
public class AliPayConfig implements ToResult<AlipayConfigResult> {
/** 主键 */
private Long id;
/** 是否为ISV商户(特约商户) */
private boolean isv;
/** 支付宝商户appId */
private String aliAppId;
/** 支付宝特约商户Token */
private String appAuthToken;
/** 是否启用 */
private Boolean enable;
@@ -77,10 +81,10 @@ public class AliPayConfig implements ToResult<AliPayConfigResult> {
channelConfig.setOutAppId(this.getAliAppId());
channelConfig.setAppId(this.getAppId());
channelConfig.setEnable(this.getEnable());
channelConfig.setChannel(ChannelEnum.ALIPAY.getCode());
AliPayConfig copy = AliPayConfigConvert.CONVERT.copy(this);
channelConfig.setChannel(this.isv?ChannelEnum.ALIPAY_ISV.getCode():ChannelEnum.ALIPAY.getCode());
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);
String jsonStr = JsonUtil.toJsonStr(copy);
channelConfig.setExt(jsonStr);
return channelConfig;
@@ -91,15 +95,15 @@ public class AliPayConfig implements ToResult<AliPayConfigResult> {
*/
public static AliPayConfig convertConfig(ChannelConfig channelConfig) {
AliPayConfig config = JsonUtil.toBean(channelConfig.getExt(), AliPayConfig.class);
config.setId(channelConfig.getId())
.setAliAppId(channelConfig.getOutAppId())
.setAppId(channelConfig.getAppId())
.setEnable(channelConfig.isEnable());
return config;
}
@Override
public AliPayConfigResult toResult() {
return AliPayConfigConvert.CONVERT.toResult(this);
public AlipayConfigResult toResult() {
return AlipayConfigConvert.CONVERT.toResult(this);
}
}

View File

@@ -1,6 +1,5 @@
package org.dromara.daxpay.channel.alipay.param.config;
import org.dromara.daxpay.channel.alipay.code.AliPayCode;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
@@ -16,12 +15,19 @@ import java.math.BigDecimal;
@Data
@Accessors(chain = true)
@Schema(title = "支付宝配置参数")
public class AliPayConfigParam {
public class AlipayConfigParam {
/** 主键 */
@Schema(description = "主键")
private Long id;
/** 是否为ISV商户(特约商户) */
@Schema(description = "是否为ISV商户(特约商户)")
private boolean isv;
/** 支付宝特约商户Token */
@Schema(description = "支付宝特约商户Token")
private String appAuthToken;
/** 支付宝商户appId */
@NotBlank(message = "支付宝AppId不可为空")
@@ -40,7 +46,7 @@ public class AliPayConfigParam {
/**
* 认证类型 证书/公钥
* @see AliPayCode.AuthType
* @see org.dromara.daxpay.channel.alipay.code.AlipayCode.AuthType
*/
@Schema(description = "认证类型")
@NotBlank(message = "认证类型不可为空")

View File

@@ -10,7 +10,7 @@ import lombok.Data;
*/
@Data
@Schema(title = "支付宝支付参数")
public class AliPayParam {
public class AlipayParam {
/**
* 授权码(主动扫描用户的付款码)
*/

View File

@@ -1,7 +1,6 @@
package org.dromara.daxpay.channel.alipay.result.config;
import cn.bootx.platform.common.jackson.sensitive.SensitiveInfo;
import org.dromara.daxpay.channel.alipay.code.AliPayCode;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
@@ -16,7 +15,7 @@ import java.math.BigDecimal;
@Data
@Accessors(chain = true)
@Schema(title = "支付宝配置")
public class AliPayConfigResult {
public class AlipayConfigResult {
/** 主键 */
@Schema(description = "主键")
@@ -34,9 +33,13 @@ public class AliPayConfigResult {
@Schema(description = "支付限额")
private BigDecimal limitAmount;
/** 支付宝特约商户Token */
@Schema(description = "支付宝特约商户Token")
private String appAuthToken;
/**
* 认证类型 证书/公钥
* @see AliPayCode#AUTH_TYPE_KEY
* @see org.dromara.daxpay.channel.alipay.code.AlipayCode.AuthType
*/
@Schema(description = "认证类型")
private String authType;
@@ -80,6 +83,10 @@ public class AliPayConfigResult {
@Schema(description = "是否沙箱环境")
private boolean sandbox;
/** 商户号 */
@Schema(description = "商户号")
private String mchNo;
/** 商户AppId */
@Schema(description = "商户AppId")
private String appId;

View File

@@ -11,7 +11,7 @@ import lombok.experimental.Accessors;
*/
@Data
@Accessors(chain = true)
public class AliPayOrderChangedResult {
public class AlipayOrderChangedResult {
/**
* 必选string(64)

View File

@@ -12,8 +12,9 @@ import com.alipay.api.response.AlipayTradeRoyaltyRelationUnbindResponse;
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.service.config.AliPayConfigService;
import org.dromara.daxpay.channel.alipay.code.AlipayCode;
import org.dromara.daxpay.channel.alipay.entity.AliPayConfig;
import org.dromara.daxpay.channel.alipay.service.config.AlipayConfigService;
import org.dromara.daxpay.core.enums.AllocReceiverTypeEnum;
import org.dromara.daxpay.core.exception.ConfigErrorException;
import org.dromara.daxpay.core.exception.TradeStatusErrorException;
@@ -27,7 +28,6 @@ import java.util.Objects;
import static org.dromara.daxpay.core.enums.AllocReceiverTypeEnum.*;
/**
* 支付宝分账
* @author xxm
@@ -37,7 +37,7 @@ import static org.dromara.daxpay.core.enums.AllocReceiverTypeEnum.*;
@Service
@RequiredArgsConstructor
public class AliPayAllocReceiverService {
private final AliPayConfigService aliPayConfigService;
private final AlipayConfigService aliPayConfigService;
/**
* 校验
@@ -52,7 +52,7 @@ public class AliPayAllocReceiverService {
* 绑定关系
*/
@SneakyThrows
public void bind(AllocReceiver allocReceiver){
public void bind(AllocReceiver allocReceiver, AliPayConfig aliPayConfig){
AlipayTradeRoyaltyRelationBindModel model = new AlipayTradeRoyaltyRelationBindModel();
RoyaltyEntity entity = new RoyaltyEntity();
@@ -67,7 +67,7 @@ public class AliPayAllocReceiverService {
AlipayTradeRoyaltyRelationBindRequest request = new AlipayTradeRoyaltyRelationBindRequest();
model.setOutRequestNo(String.valueOf(allocReceiver.getId()));
request.setBizModel(model);
AlipayTradeRoyaltyRelationBindResponse response = aliPayConfigService.execute(request);
AlipayTradeRoyaltyRelationBindResponse response = aliPayConfigService.execute(request,aliPayConfig);
this.verifyErrorMsg(response);
}
@@ -75,7 +75,7 @@ public class AliPayAllocReceiverService {
* 解绑关系
*/
@SneakyThrows
public void unbind(AllocReceiver allocReceiver){
public void unbind(AllocReceiver allocReceiver, AliPayConfig aliPayConfig){
AlipayTradeRoyaltyRelationUnbindModel model = new AlipayTradeRoyaltyRelationUnbindModel();
model.setOutRequestNo(String.valueOf(allocReceiver.getId()));
@@ -87,9 +87,9 @@ public class AliPayAllocReceiverService {
model.setReceiverList(Collections.singletonList(entity));
AlipayTradeRoyaltyRelationUnbindRequest request = new AlipayTradeRoyaltyRelationUnbindRequest();
request.setBizModel(model);
AlipayTradeRoyaltyRelationUnbindResponse response = aliPayConfigService.execute(request);
AlipayTradeRoyaltyRelationUnbindResponse response = aliPayConfigService.execute(request,aliPayConfig);
// 如果出现分账方不存在也视为成功
if (Objects.equals(response.getSubCode(), AliPayCode.USER_NOT_EXIST)) {
if (Objects.equals(response.getSubCode(), AlipayCode.USER_NOT_EXIST)) {
return;
}
this.verifyErrorMsg(response);
@@ -99,7 +99,7 @@ public class AliPayAllocReceiverService {
* 验证错误信息
*/
private void verifyErrorMsg(AlipayResponse alipayResponse) {
if (!Objects.equals(alipayResponse.getCode(), AliPayCode.ResponseCode.SUCCESS)) {
if (!Objects.equals(alipayResponse.getCode(), AlipayCode.ResponseCode.SUCCESS)) {
String errorMsg = alipayResponse.getSubMsg();
if (StrUtil.isBlank(errorMsg)) {
errorMsg = alipayResponse.getMsg();

View File

@@ -2,6 +2,17 @@ package org.dromara.daxpay.channel.alipay.service.allocation;
import cn.bootx.platform.common.mybatisplus.base.MpIdEntity;
import cn.bootx.platform.common.mybatisplus.function.CollectorsFunction;
import org.dromara.daxpay.channel.alipay.code.AlipayCode;
import org.dromara.daxpay.channel.alipay.entity.AliPayConfig;
import org.dromara.daxpay.channel.alipay.service.config.AlipayConfigService;
import org.dromara.daxpay.core.enums.AllocDetailResultEnum;
import org.dromara.daxpay.core.exception.OperationFailException;
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.bo.allocation.AllocSyncResultBo;
import org.dromara.daxpay.service.entity.allocation.order.AllocDetail;
import org.dromara.daxpay.service.entity.allocation.order.AllocOrder;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
@@ -14,16 +25,6 @@ import com.alipay.api.response.AlipayTradeOrderSettleQueryResponse;
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.OperationFailException;
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.bo.allocation.AllocSyncResultBo;
import org.dromara.daxpay.service.entity.allocation.order.AllocDetail;
import org.dromara.daxpay.service.entity.allocation.order.AllocOrder;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
@@ -43,17 +44,17 @@ import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
public class AliPayAllocationService {
private final AliPayConfigService aliPayConfigService;
private final AlipayConfigService aliPayConfigService;
/**
* 发起分账
*/
public AllocStartResultBo start(AllocOrder allocOrder, List<AllocDetail> orderDetails){
public AllocStartResultBo start(AllocOrder allocOrder, List<AllocDetail> orderDetails, AliPayConfig aliPayConfig){
// 分账主体参数
AlipayTradeOrderSettleModel model = new AlipayTradeOrderSettleModel();
model.setOutRequestNo(allocOrder.getAllocNo());
model.setTradeNo(allocOrder.getOutOrderNo());
model.setRoyaltyMode(AliPayCode.ALLOC_ASYNC);
model.setRoyaltyMode(AlipayCode.ALLOC_ASYNC);
// 分账子参数 根据Id排序
orderDetails.sort(Comparator.comparing(MpIdEntity::getId));
@@ -70,7 +71,7 @@ public class AliPayAllocationService {
request.setBizModel(model);
AlipayTradeOrderSettleResponse response;
try {
response = aliPayConfigService.execute(request);
response = aliPayConfigService.execute(request,aliPayConfig);
this.verifyErrorMsg(response);
} catch (AlipayApiException e) {
log.error("网关返回分账失败: {}", e.getMessage());
@@ -84,12 +85,12 @@ public class AliPayAllocationService {
/**
* 分账完结
*/
public void finish(AllocOrder allocOrder, List<AllocDetail> orderDetails){
public void finish(AllocOrder allocOrder, List<AllocDetail> orderDetails, AliPayConfig aliPayConfig){
// 分账主体参数
AlipayTradeOrderSettleModel model = new AlipayTradeOrderSettleModel();
model.setOutRequestNo(allocOrder.getAllocNo());
model.setTradeNo(allocOrder.getOutOrderNo());
model.setRoyaltyMode(AliPayCode.ALLOC_ASYNC);
model.setRoyaltyMode(AlipayCode.ALLOC_ASYNC);
// 分账完结参数
SettleExtendParams extendParams = new SettleExtendParams();
extendParams.setRoyaltyFinish(Boolean.TRUE.toString());
@@ -110,7 +111,7 @@ public class AliPayAllocationService {
request.setBizModel(model);
AlipayTradeOrderSettleResponse response = null;
try {
response = aliPayConfigService.execute(request);
response = aliPayConfigService.execute(request,aliPayConfig);
} catch (AlipayApiException e) {
log.error("网关返回分账失败: {}", e.getMessage());
throw new TradeFailException(e.getMessage());
@@ -121,7 +122,7 @@ public class AliPayAllocationService {
/**
* 分账状态同步
*/
public AllocSyncResultBo sync(AllocOrder allocOrder, List<AllocDetail> allocOrderDetails){
public AllocSyncResultBo sync(AllocOrder allocOrder, List<AllocDetail> allocOrderDetails, AliPayConfig aliPayConfig){
AlipayTradeOrderSettleQueryModel model = new AlipayTradeOrderSettleQueryModel();
model.setOutRequestNo(allocOrder.getAllocNo());
model.setTradeNo(allocOrder.getOutOrderNo());
@@ -129,7 +130,7 @@ public class AliPayAllocationService {
request.setBizModel(model);
AlipayTradeOrderSettleQueryResponse response;
try {
response = aliPayConfigService.execute(request);
response = aliPayConfigService.execute(request,aliPayConfig);
} catch (AlipayApiException e) {
throw new OperationFailException(e.getMessage());
}
@@ -175,11 +176,11 @@ public class AliPayAllocationService {
*/
private AllocDetailResultEnum getDetailResultEnum (String result){
// 进行中
if(Objects.equals(AliPayCode.ALLOC_PROCESSING, result)){
if(Objects.equals(AlipayCode.ALLOC_PROCESSING, result)){
return AllocDetailResultEnum.PENDING;
}
// 成功
if(Objects.equals(AliPayCode.ALLOC_SUCCESS, result)){
if(Objects.equals(AlipayCode.ALLOC_SUCCESS, result)){
return AllocDetailResultEnum.SUCCESS;
}
// 失败

View File

@@ -1,6 +1,14 @@
package org.dromara.daxpay.channel.alipay.service.callback;
import org.dromara.daxpay.channel.alipay.service.config.AliPayConfigService;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.daxpay.channel.alipay.code.AlipayCode.PayStatus;
import org.dromara.daxpay.channel.alipay.code.AlipayCode.ResponseParams;
import org.dromara.daxpay.channel.alipay.service.config.AlipayConfigService;
import org.dromara.daxpay.core.enums.CallbackStatusEnum;
import org.dromara.daxpay.core.enums.ChannelEnum;
import org.dromara.daxpay.core.enums.PayStatusEnum;
@@ -11,12 +19,6 @@ import org.dromara.daxpay.service.common.local.PaymentContextLocal;
import org.dromara.daxpay.service.service.record.callback.TradeCallbackRecordService;
import org.dromara.daxpay.service.service.trade.pay.PayCallbackService;
import org.dromara.daxpay.service.service.trade.refund.RefundCallbackService;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
@@ -24,8 +26,6 @@ import java.time.LocalDateTime;
import java.util.Map;
import java.util.Objects;
import static org.dromara.daxpay.channel.alipay.code.AliPayCode.*;
/**
* 支付宝回调服务
*
@@ -35,9 +35,9 @@ import static org.dromara.daxpay.channel.alipay.code.AliPayCode.*;
@Slf4j
@Service
@RequiredArgsConstructor
public class AliPayCallbackService {
public class AlipayCallbackService {
private final AliPayConfigService aliPayConfigService;
private final AlipayConfigService aliPayConfigService;
private final PayCallbackService payCallbackService;
private final TradeCallbackRecordService tradeCallbackRecordService;
private final RefundCallbackService refundCallbackService;
@@ -45,14 +45,14 @@ public class AliPayCallbackService {
/**
* 回调处理
*/
public String callbackHandle(HttpServletRequest request) {
public String callbackHandle(HttpServletRequest request, boolean isv) {
Map<String, String> callbackParam = PayUtil.toMap(request);
// 判断为支付还是退款
TradeTypeEnum tradeTypeEnum = this.resolveAndGetType(callbackParam);
TradeTypeEnum tradeTypeEnum = this.resolveAndGetType(callbackParam,isv);
if (tradeTypeEnum == TradeTypeEnum.PAY){
// 支付回调处理
if (this.payHandler(callbackParam)){
if (this.payHandler(callbackParam,isv)){
// 执行回调业务处理
payCallbackService.payCallback();
// 保存记录
@@ -65,7 +65,7 @@ public class AliPayCallbackService {
}
} else {
// 解析数据
if (this.refundHandle(callbackParam)){
if (this.refundHandle(callbackParam,isv)){
// 执行退款回调处理
refundCallbackService.refundCallback();
// 保存记录
@@ -82,11 +82,11 @@ public class AliPayCallbackService {
/**
* 解析回调内容并返回类型
*/
public TradeTypeEnum resolveAndGetType(Map<String, String> callbackParam){
public TradeTypeEnum resolveAndGetType(Map<String, String> callbackParam, boolean isv){
CallbackLocal callback = PaymentContextLocal.get().getCallbackInfo();
callback.setCallbackData(callbackParam);
// 通道和回调类型
callback.setChannel(ChannelEnum.ALIPAY.getCode());
callback.setChannel(isv? ChannelEnum.ALIPAY_ISV.getCode():ChannelEnum.ALIPAY.getCode());
String refundFee = callbackParam.get(ResponseParams.REFUND_FEE);
// 如果有退款金额,说明是退款回调
if (StrUtil.isNotBlank(refundFee)){
@@ -102,15 +102,14 @@ public class AliPayCallbackService {
/**
* 支付回调处理, 解析数据
*/
public boolean payHandler(Map<String, String> callbackParam) {
public boolean payHandler(Map<String, String> callbackParam, boolean isv) {
CallbackLocal callback = PaymentContextLocal.get().getCallbackInfo();
if (!aliPayConfigService.verifyNotify(callbackParam)) {
if (!aliPayConfigService.verifyNotify(callbackParam,isv)) {
log.error("支付宝回调报文验签失败");
callback.setCallbackStatus(CallbackStatusEnum.FAIL).setCallbackErrorMsg("支付宝回调报文验签失败");
return false;
}
// 网关订单号
callback.setOutTradeNo(callbackParam.get(ResponseParams.TRADE_NO));
// 支付订单ID
@@ -136,10 +135,10 @@ public class AliPayCallbackService {
/**
* 退款回调处理
*/
public boolean refundHandle(Map<String, String> callbackParam ) {
public boolean refundHandle(Map<String, String> callbackParam, boolean isv) {
CallbackLocal callback = PaymentContextLocal.get().getCallbackInfo();
// 验签
if (!aliPayConfigService.verifyNotify(callbackParam)) {
if (!aliPayConfigService.verifyNotify(callbackParam, isv)) {
log.error("支付宝回调报文验签失败");
callback.setCallbackStatus(CallbackStatusEnum.FAIL).setCallbackErrorMsg("支付宝回调报文验签失败");
return false;

View File

@@ -1,15 +1,16 @@
package org.dromara.daxpay.channel.alipay.service.close;
import org.dromara.daxpay.channel.alipay.code.AliPayCode;
import org.dromara.daxpay.channel.alipay.entity.config.AliPayConfig;
import org.dromara.daxpay.channel.alipay.service.config.AliPayConfigService;
import org.dromara.daxpay.channel.alipay.service.sync.AliPaySyncService;
import org.dromara.daxpay.channel.alipay.code.AlipayCode;
import org.dromara.daxpay.channel.alipay.entity.AliPayConfig;
import org.dromara.daxpay.channel.alipay.service.config.AlipayConfigService;
import org.dromara.daxpay.channel.alipay.service.sync.AlipaySyncService;
import org.dromara.daxpay.core.enums.PayStatusEnum;
import org.dromara.daxpay.core.exception.OperationFailException;
import org.dromara.daxpay.core.exception.TradeStatusErrorException;
import org.dromara.daxpay.service.bo.sync.PaySyncResultBo;
import org.dromara.daxpay.service.entity.order.pay.PayOrder;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayConstants;
import com.alipay.api.domain.AlipayTradeCancelModel;
import com.alipay.api.domain.AlipayTradeCloseModel;
import com.alipay.api.request.AlipayTradeCancelRequest;
@@ -32,8 +33,8 @@ import java.util.Objects;
@Service
@RequiredArgsConstructor
public class AliPayCloseService {
private final AliPayConfigService aliPayConfigService;
private final AliPaySyncService aliPaySyncService;
private final AlipayConfigService aliPayConfigService;
private final AlipaySyncService aliPaySyncService;
/**
* 关闭支付 此处使用交易关闭接口
@@ -43,22 +44,26 @@ public class AliPayCloseService {
* 2. 如果返回"当前交易状态不支持此操作", 同步网关支付状态, 判断网关是否已经被关闭
*
*/
public void close(PayOrder payOrder, AliPayConfig config) {
public void close(PayOrder payOrder, AliPayConfig aliPayConfig) {
AlipayTradeCloseModel model = new AlipayTradeCloseModel();
model.setOutTradeNo(payOrder.getOrderNo());
AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
// 特约商户调用
if (aliPayConfig.isIsv()){
request.putOtherTextParam(AlipayConstants.APP_AUTH_TOKEN, aliPayConfig.getAppAuthToken());
}
request.setBizModel(model);
try {
AlipayTradeCloseResponse response = aliPayConfigService.execute(request);
if (!Objects.equals(AliPayCode.ResponseCode.SUCCESS, response.getCode())) {
AlipayTradeCloseResponse response = aliPayConfigService.execute(request,aliPayConfig);
if (!response.isSuccess()) {
// 如果返回"当前交易状态不支持此操作", 查询网关支付状态, 判断网关是否已经被关闭
if (Objects.equals(response.getSubCode(),AliPayCode.ResponseCode.ACQ_TRADE_STATUS_ERROR)){
if (this.syncStatus(payOrder, config)){
if (Objects.equals(response.getSubCode(), AlipayCode.ResponseCode.ACQ_TRADE_STATUS_ERROR)){
if (this.syncStatus(payOrder, aliPayConfig)){
return;
}
}
// 返回"交易不存在"视同关闭成功
if (Objects.equals(response.getSubCode(),AliPayCode.ResponseCode.ACQ_TRADE_NOT_EXIST)){
if (Objects.equals(response.getSubCode(), AlipayCode.ResponseCode.ACQ_TRADE_NOT_EXIST)){
return;
}
log.error("网关返回关闭失败: {}", response.getSubMsg());
@@ -74,28 +79,30 @@ public class AliPayCloseService {
* 可以视为一个特殊的接口, 需要专门签约这个接口的权限
*
*/
public void cancel(PayOrder payOrder, AliPayConfig config) {
public void cancel(PayOrder payOrder, AliPayConfig aliPayConfig) {
AlipayTradeCancelModel model = new AlipayTradeCancelModel();
model.setOutTradeNo(payOrder.getOrderNo());
AlipayTradeCancelRequest request = new AlipayTradeCancelRequest();
// 特约商户调用
if (aliPayConfig.isIsv()){
request.putOtherTextParam(AlipayConstants.APP_AUTH_TOKEN, aliPayConfig.getAppAuthToken());
}
request.setBizModel(model);
try {
AlipayTradeCancelResponse response = aliPayConfigService.execute(request);
if (!Objects.equals(AliPayCode.ResponseCode.SUCCESS, response.getCode())) {
if (!Objects.equals(AliPayCode.ResponseCode.SUCCESS, response.getCode())) {
AlipayTradeCancelResponse response = aliPayConfigService.execute(request,aliPayConfig);
if (!response.isSuccess()) {
// 如果返回"当前交易状态不支持此操作", 查询网关支付状态, 判断网关是否已经被关闭
if (Objects.equals(response.getSubCode(),AliPayCode.ResponseCode.ACQ_TRADE_STATUS_ERROR)){
if (this.syncStatus(payOrder, config)){
if (Objects.equals(response.getSubCode(), AlipayCode.ResponseCode.ACQ_TRADE_STATUS_ERROR)){
if (this.syncStatus(payOrder, aliPayConfig)){
return;
}
}
// 返回"交易不存在"视同关闭成功
if (Objects.equals(response.getSubCode(),AliPayCode.ResponseCode.ACQ_TRADE_NOT_EXIST)){
if (Objects.equals(response.getSubCode(), AlipayCode.ResponseCode.ACQ_TRADE_NOT_EXIST)){
return;
}
log.error("网关返回关闭失败: {}", response.getSubMsg());
throw new OperationFailException(response.getSubMsg());
}
}
} catch (AlipayApiException e) {
log.error("关闭订单失败:", e);
@@ -108,7 +115,7 @@ public class AliPayCloseService {
* 关闭失败后, 获取支付网关的状态, 如果是关闭返回true, 其他情况抛出异常
*/
private boolean syncStatus(PayOrder payOrder, AliPayConfig config){
PaySyncResultBo gatewaySyncResult = aliPaySyncService.syncPayStatus(payOrder);
PaySyncResultBo gatewaySyncResult = aliPaySyncService.syncPayStatus(payOrder,config);
// 已经关闭
if (Objects.equals(gatewaySyncResult.getPayStatus(), PayStatusEnum.CLOSE)){
return true;

View File

@@ -11,11 +11,11 @@ import com.alipay.api.internal.util.AlipaySignature;
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.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.code.AlipayCode;
import org.dromara.daxpay.channel.alipay.convert.config.AlipayConfigConvert;
import org.dromara.daxpay.channel.alipay.entity.AliPayConfig;
import org.dromara.daxpay.channel.alipay.param.config.AlipayConfigParam;
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;
@@ -24,6 +24,7 @@ import org.dromara.daxpay.service.common.cache.ChannelConfigCacheService;
import org.dromara.daxpay.service.common.context.MchAppLocal;
import org.dromara.daxpay.service.common.local.PaymentContextLocal;
import org.dromara.daxpay.service.dao.config.ChannelConfigManager;
import org.dromara.daxpay.service.dao.merchant.MchAppManager;
import org.dromara.daxpay.service.entity.config.ChannelConfig;
import org.dromara.daxpay.service.service.config.PlatformConfigService;
import org.springframework.stereotype.Service;
@@ -40,26 +41,28 @@ import java.util.Objects;
@Slf4j
@Service
@RequiredArgsConstructor
public class AliPayConfigService {
public class AlipayConfigService {
private final ChannelConfigManager channelConfigManager;
private final ChannelConfigCacheService channelConfigCacheService;
private final PlatformConfigService platformConfigService;
private final MchAppManager mchAppManager;
/**
* 查询
*/
public AliPayConfigResult findById(Long id) {
public AlipayConfigResult findById(Long id) {
return channelConfigManager.findById(id)
.map(AliPayConfig::convertConfig)
.map(AliPayConfig::toResult)
.orElseThrow(() -> new ConfigNotEnableException("支付宝配置不存在"));
.orElseThrow(() -> new ConfigNotEnableException("支付宝商户配置不存在"));
}
/**
* 新增或更新
* 新增或更新商户信息
*/
@Transactional(rollbackFor = Exception.class)
public void saveOrUpdate(AliPayConfigParam param){
public void saveOrUpdate(AlipayConfigParam param){
if (param.getId() == null){
this.save(param);
} else {
@@ -68,13 +71,13 @@ public class AliPayConfigService {
}
/**
* 添加
* 添加商户信息
*/
public void save(AliPayConfigParam param) {
AliPayConfig entity = AliPayConfigConvert.CONVERT.toEntity(param);
public void save(AlipayConfigParam param) {
var entity = AlipayConfigConvert.CONVERT.toEntity(param);
ChannelConfig channelConfig = entity.toChannelConfig();
// 判断商户应用下是否存在该配置
if (channelConfigManager.existsByAppIdAndChannel(channelConfig.getAppId(), channelConfig.getChannel())){
// 判断商户应用下是否存在该配置
if (channelConfigManager.existsByAppIdAndChannel(param.getAppId(), channelConfig.getChannel())){
throw new DataErrorException("该应用下已存在支付宝配置, 请勿重新添加");
}
channelConfigManager.save(channelConfig);
@@ -83,7 +86,7 @@ public class AliPayConfigService {
/**
* 更新
*/
public void update(AliPayConfigParam param){
public void update(AlipayConfigParam param){
ChannelConfig channelConfig = channelConfigManager.findById(param.getId())
.orElseThrow(() -> new ConfigNotEnableException("支付宝配置不存在"));
// 通道配置 --转换--> 支付宝配置 ----> 从更新参数赋值 --转换--> 通道配置 ----> 保存更新
@@ -96,52 +99,47 @@ public class AliPayConfigService {
channelConfigManager.updateById(channelConfig);
}
/**
* 获取异步通知地址
*/
public String getNotifyUrl() {
public String getNotifyUrl(boolean isv) {
String url = isv?"{}/unipay/callback/{}/alipay/isv":"{}/unipay/callback/{}/alipay";
var mchAppInfo = PaymentContextLocal.get().getMchAppInfo();
var platformInfo = platformConfigService.getConfig();
return StrUtil.format("{}/unipay/callback/{}/alipay",platformInfo.getGatewayServiceUrl(), mchAppInfo.getAppId());
return StrUtil.format(url,platformInfo.getGatewayServiceUrl(), mchAppInfo.getAppId());
}
/**
* 获取同步通知地址
*/
public String getReturnUrl() {
public String getReturnUrl(boolean isv) {
String url = isv?"{}/unipay/return/{}/alipay/isv":"{}/unipay/return/{}/alipay";
MchAppLocal mchAppInfo = PaymentContextLocal.get().getMchAppInfo();
var platformInfo = platformConfigService.getConfig();
return StrUtil.format("{}/unipay/return/{}/alipay",platformInfo.getGatewayServiceUrl(), mchAppInfo.getAppId());
return StrUtil.format(url,platformInfo.getGatewayServiceUrl(), mchAppInfo.getAppId());
}
/**
* 获取支付宝支付配置
*/
public AliPayConfig getAliPayConfig(){
public AliPayConfig getAliPayConfig(boolean isv){
MchAppLocal mchAppInfo = PaymentContextLocal.get().getMchAppInfo();
ChannelConfig channelConfig = channelConfigCacheService.get(mchAppInfo.getAppId(), ChannelEnum.ALIPAY.getCode());
ChannelConfig channelConfig = channelConfigCacheService.get(mchAppInfo.getAppId(), isv?ChannelEnum.ALIPAY_ISV.getCode():ChannelEnum.ALIPAY.getCode());
return AliPayConfig.convertConfig(channelConfig);
}
/**
* 获取并检查支付配置
*/
public AliPayConfig getAndCheckConfig() {
var payConfig = this.getAliPayConfig();
public AliPayConfig getAndCheckConfig(boolean isv) {
var payConfig = this.getAliPayConfig(isv);
if (!payConfig.getEnable()){
throw new ChannelNotEnableException("支付宝支付通道未启用");
}
return payConfig;
}
/**
* 获取支付宝SDK的配置
*/
public AlipayClient getAlipayClient(){
AliPayConfig aliPayConfig = this.getAndCheckConfig();
return this.getAlipayClient(aliPayConfig);
}
/**
* 获取支付宝SDK的配置
*/
@@ -153,7 +151,7 @@ public class AliPayConfigService {
config.setCharset("UTF-8");
config.setSignType(aliPayConfig.getSignType());
// 证书
if (Objects.equals(aliPayConfig.getAuthType(), AliPayCode.AuthType.AUTH_TYPE_CART)){
if (Objects.equals(aliPayConfig.getAuthType(), AlipayCode.AuthType.AUTH_TYPE_CART)){
config.setPrivateKey(aliPayConfig.getPrivateKey());
config.setAppCertContent(aliPayConfig.getAppCert());
config.setRootCertContent(aliPayConfig.getAlipayRootCert());
@@ -165,18 +163,17 @@ public class AliPayConfigService {
}
// 沙箱
if (aliPayConfig.isSandbox()){
config.setServerUrl(AliPayCode.ServerUrl.SANDBOX);
config.setServerUrl(AlipayCode.ServerUrl.SANDBOX);
} else {
config.setServerUrl(AliPayCode.ServerUrl.PRODUCTION);
config.setServerUrl(AlipayCode.ServerUrl.PRODUCTION);
}
return new DefaultAlipayClient(config);
}
/**
* 校验消息通知
*/
public boolean verifyNotify(Map<String, String> params) {
public boolean verifyNotify(Map<String, String> params, boolean isv) {
String callReq = JsonUtil.toJsonStr(params);
log.info("支付宝消息通知报文: {}", callReq);
String appId = params.get("app_id");
@@ -184,14 +181,14 @@ public class AliPayConfigService {
log.error("支付宝消息通知报文appId为空");
return false;
}
AliPayConfig alipayConfig = this.getAliPayConfig();
AliPayConfig alipayConfig = this.getAliPayConfig(isv);
if (Objects.isNull(alipayConfig)) {
log.error("支付宝支付配置不存在");
return false;
}
// 根据认证类型使用证书或公钥验签
try {
if (Objects.equals(alipayConfig.getAuthType(), AliPayCode.AuthType.AUTH_TYPE_KEY)) {
if (Objects.equals(alipayConfig.getAuthType(), AlipayCode.AuthType.AUTH_TYPE_KEY)) {
return AlipaySignature.verifyV1(params, alipayConfig.getAlipayPublicKey(), CharsetUtil.UTF_8, AlipayConstants.SIGN_TYPE_RSA2);
}
else {
@@ -203,17 +200,16 @@ public class AliPayConfigService {
}
}
/**
* 接口调用
*/
public <T extends AlipayResponse> T execute(AlipayRequest<T> request) throws AlipayApiException {
AliPayConfig aliPayConfig = this.getAliPayConfig();
public <T extends AlipayResponse> T execute(AlipayRequest<T> request, AliPayConfig aliPayConfig) throws AlipayApiException {
AlipayClient alipayClient = this.getAlipayClient(aliPayConfig);
if (Objects.equals(aliPayConfig.getAuthType(), AliPayCode.AuthType.AUTH_TYPE_CART)){
return this.getAlipayClient().certificateExecute(request);
if (Objects.equals(aliPayConfig.getAuthType(), AlipayCode.AuthType.AUTH_TYPE_CART)){
return alipayClient.certificateExecute(request);
} else {
return alipayClient.execute(request);
}
}
}

View File

@@ -1,21 +1,19 @@
package org.dromara.daxpay.channel.alipay.service.extra;
import cn.bootx.platform.core.exception.BizException;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alipay.api.AlipayClient;
import com.alipay.api.request.AlipaySystemOauthTokenRequest;
import com.alipay.api.response.AlipaySystemOauthTokenResponse;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.dromara.daxpay.channel.alipay.entity.config.AliPayConfig;
import org.dromara.daxpay.channel.alipay.service.config.AliPayConfigService;
import org.dromara.daxpay.channel.alipay.entity.AliPayConfig;
import org.dromara.daxpay.channel.alipay.service.config.AlipayConfigService;
import org.dromara.daxpay.core.param.assist.GenerateAuthUrlParam;
import org.dromara.daxpay.core.result.assist.AuthResult;
import org.dromara.daxpay.core.result.assist.AuthUrlResult;
import org.dromara.daxpay.service.entity.config.PlatformConfig;
import org.dromara.daxpay.service.service.config.PlatformConfigService;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alipay.api.request.AlipaySystemOauthTokenRequest;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
@@ -26,9 +24,9 @@ import org.springframework.stereotype.Service;
@Slf4j
@Service
@RequiredArgsConstructor
public class AliPayAuthService {
public class AlipayAuthService {
private final AliPayConfigService aliPayConfigService;
private final AlipayConfigService aliPayConfigService;
private final PlatformConfigService platformsConfigService;
@@ -37,19 +35,17 @@ public class AliPayAuthService {
* 1. 如果手动传输授权回调地址, 不进行处理
* 2. 如果未手动传输授权回调地址, 使用系统默认的授权页地址, 返回授权页地址和用于查询的标识码
*/
public AuthUrlResult generateAuthUrl(GenerateAuthUrlParam param) {
public AuthUrlResult generateAuthUrl(GenerateAuthUrlParam param, AliPayConfig aliPayConfig) {
// 如果手动传输, 直接返回空, 因为支付宝OpenId方式不用通过回调获取
if (StrUtil.isAllNotBlank(param.getAuthRedirectUrl())){
return new AuthUrlResult();
} else {
PlatformConfig platformConfig = platformsConfigService.getConfig();
AliPayConfig aliPayConfig = aliPayConfigService.getAndCheckConfig();
String queryCode = RandomUtil.randomString(10);
// 授权地址
String serverUrl = platformConfig.getGatewayMobileUrl();
String serverUrl = platformConfig.getGatewayMobileUrl();
String authUrl = StrUtil.format("{}/auth/alipay/{}/{}/{}/{}",
serverUrl, param.getAppId(),param.getChannel(),queryCode,aliPayConfig.getAliAppId());
serverUrl, param.getAppId(), param.getChannel(), queryCode, aliPayConfig.getAliAppId());
return new AuthUrlResult().setAuthUrl(authUrl).setQueryCode(queryCode);
}
@@ -59,16 +55,15 @@ public class AliPayAuthService {
* 获取OpenId或者userid用户标识
*/
@SneakyThrows
public AuthResult getOpenIdOrUserId(String authCode) {
public AuthResult getOpenIdOrUserId(String authCode, AliPayConfig aliPayConfig) {
// 初始化SDK
AlipayClient alipayClient = aliPayConfigService.getAlipayClient();
// 构造请求参数以调用接口
AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
// 设置授权码
request.setCode(authCode);
// 设置授权方式
request.setGrantType("authorization_code");
AlipaySystemOauthTokenResponse response = alipayClient.execute(request);
var response = aliPayConfigService.execute(request,aliPayConfig);
if (!response.isSuccess()) {
log.warn("获取支付宝OpenId失败,原因:{}", response.getSubMsg());
throw new BizException("获取支付宝OpenId失败");

View File

@@ -1,6 +1,6 @@
package org.dromara.daxpay.channel.alipay.service.notice;
import org.dromara.daxpay.channel.alipay.service.config.AliPayConfigService;
import org.dromara.daxpay.channel.alipay.service.config.AlipayConfigService;
import org.dromara.daxpay.core.util.PayUtil;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
@@ -17,19 +17,19 @@ import java.util.Map;
@Slf4j
@Service
@RequiredArgsConstructor
public class AliPayNoticeReceiverService {
public class AlipayNoticeReceiverService {
private final AliPayConfigService aliPayConfigService;
private final AlipayConfigService aliPayConfigService;
private final AliPayTransferNoticeService aliPayTransferNoticeService;
private final AlipayTransferNoticeService aliPayTransferNoticeService;
/**
* 通知消息处理
*/
public String noticeReceiver(HttpServletRequest request) {
public String noticeReceiver(HttpServletRequest request, boolean isv) {
Map<String, String> map = PayUtil.toMap(request);
// 首先进行验签
if (!aliPayConfigService.verifyNotify(map)){
if (!aliPayConfigService.verifyNotify(map,isv)){
log.error("支付宝消息通知验签失败");
return "fail";
}

View File

@@ -1,8 +1,11 @@
package org.dromara.daxpay.channel.alipay.service.notice;
import cn.bootx.platform.core.util.JsonUtil;
import org.dromara.daxpay.channel.alipay.code.AliPayCode;
import org.dromara.daxpay.channel.alipay.result.notice.AliPayOrderChangedResult;
import cn.hutool.core.bean.BeanUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.daxpay.channel.alipay.code.AlipayCode;
import org.dromara.daxpay.channel.alipay.result.notice.AlipayOrderChangedResult;
import org.dromara.daxpay.core.enums.CallbackStatusEnum;
import org.dromara.daxpay.core.enums.ChannelEnum;
import org.dromara.daxpay.core.enums.TradeTypeEnum;
@@ -11,9 +14,6 @@ import org.dromara.daxpay.service.common.context.CallbackLocal;
import org.dromara.daxpay.service.common.local.PaymentContextLocal;
import org.dromara.daxpay.service.service.record.callback.TradeCallbackRecordService;
import org.dromara.daxpay.service.service.trade.transfer.TransferCallbackService;
import cn.hutool.core.bean.BeanUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
@@ -28,7 +28,7 @@ import java.util.Objects;
@Slf4j
@Service
@RequiredArgsConstructor
public class AliPayTransferNoticeService {
public class AlipayTransferNoticeService {
private final TransferCallbackService transferCallbackService;
private final TradeCallbackRecordService tradeCallbackRecordService;
@@ -57,7 +57,7 @@ public class AliPayTransferNoticeService {
// 通过 biz_content 获取值
try {
String bizContent = map.get("biz_content");
var response = JsonUtil.toBean(bizContent, AliPayOrderChangedResult.class);
var response = JsonUtil.toBean(bizContent, AlipayOrderChangedResult.class);
callbackInfo.setCallbackData(BeanUtil.beanToMap(response));
this.resolveData(response);
return "success";
@@ -71,7 +71,7 @@ public class AliPayTransferNoticeService {
/**
* 解析数据
*/
public void resolveData(AliPayOrderChangedResult response) {
public void resolveData(AlipayOrderChangedResult response) {
CallbackLocal callbackInfo = PaymentContextLocal.get().getCallbackInfo();
// 设置网关订单号
@@ -79,19 +79,19 @@ public class AliPayTransferNoticeService {
String status = response.getStatus();
// SUCCESS转账成功
if (Objects.equals(status, AliPayCode.TransferStatus.SUCCESS)){
if (Objects.equals(status, AlipayCode.TransferStatus.SUCCESS)){
callbackInfo.setTradeStatus(TransferStatusEnum.SUCCESS.getCode());
}
// WAIT_PAY等待支付DEALING处理中适用于"单笔转账到银行卡"
if (List.of(AliPayCode.TransferStatus.DEALING, AliPayCode.TransferStatus.WAIT_PAY).contains(status)){
if (List.of(AlipayCode.TransferStatus.DEALING, AlipayCode.TransferStatus.WAIT_PAY).contains(status)){
callbackInfo.setTradeStatus(TransferStatusEnum.PROGRESS.getCode());
}
// FAIL失败适用于"单笔转账到银行卡"
if (Objects.equals(AliPayCode.TransferStatus.FAIL, status)){
if (Objects.equals(AlipayCode.TransferStatus.FAIL, status)){
callbackInfo.setTradeStatus(TransferStatusEnum.FAIL.getCode()).setTradeErrorMsg(response.getSubOrderFailReason());
}
// REFUND退票适用于"单笔转账到银行卡" CLOSED订单超时关闭
if (List.of(AliPayCode.TransferStatus.CLOSED, AliPayCode.TransferStatus.REFUND).contains(status)){
if (List.of(AlipayCode.TransferStatus.CLOSED, AlipayCode.TransferStatus.REFUND).contains(status)){
callbackInfo.setTradeStatus(TransferStatusEnum.CLOSE.getCode()).setTradeErrorMsg(response.getSubOrderFailReason());
}
}

View File

@@ -1,10 +1,10 @@
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.service.config.AliPayConfigService;
import org.dromara.daxpay.channel.alipay.code.AlipayCode;
import org.dromara.daxpay.channel.alipay.entity.AliPayConfig;
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;
import org.dromara.daxpay.core.exception.TradeFailException;
@@ -17,6 +17,7 @@ import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayConstants;
import com.alipay.api.AlipayResponse;
import com.alipay.api.domain.*;
import com.alipay.api.request.*;
@@ -41,15 +42,14 @@ import java.util.Objects;
@RequiredArgsConstructor
public class AliPayService {
private final AliPayConfigService aliPayConfigService;
private final AlipayConfigService aliPayConfigService;
/**
* 支付前检查支付方式是否可用
*/
public void validation(PayParam payParam) {
AliPayConfig alipayConfig = aliPayConfigService.getAndCheckConfig();
public void validation(PayParam payParam, AliPayConfig aliPayConfig) {
// 验证订单金额是否超限
if(BigDecimalUtil.isGreaterThan(payParam.getAmount(), alipayConfig.getLimitAmount())){
if(BigDecimalUtil.isGreaterThan(payParam.getAmount(), aliPayConfig.getLimitAmount())){
throw new AmountExceedLimitException("支付宝支付金额超过限额");
}
}
@@ -57,34 +57,34 @@ public class AliPayService {
/**
* 调起支付
*/
public PayResultBo pay(PayOrder payOrder, AliPayParam aliPayParam) {
public PayResultBo pay(PayOrder payOrder, AlipayParam aliPayParam, AliPayConfig aliPayConfig) {
String amount = PayUtil.toDecimal(payOrder.getAmount()).toString();
String payBody = null;
// 异步线程存储
PayResultBo payResult = new PayResultBo();
// wap支付
if (Objects.equals(payOrder.getMethod(), PayMethodEnum.WAP.getCode())) {
payBody = this.wapPay(amount, payOrder);
payBody = this.wapPay(amount, payOrder, aliPayConfig);
}
// APP支付
// 程序支付
else if (Objects.equals(payOrder.getMethod(), PayMethodEnum.APP.getCode())) {
payBody = this.appPay(amount, payOrder);
payBody = this.appPay(amount, payOrder, aliPayConfig);
}
// pc支付
else if (Objects.equals(payOrder.getMethod(), PayMethodEnum.WEB.getCode())) {
payBody = this.webPay(amount, payOrder);
payBody = this.webPay(amount, payOrder, aliPayConfig);
}
// jsapi支付
else if (Objects.equals(payOrder.getMethod(), PayMethodEnum.JSAPI.getCode())) {
payBody = this.jsapiPay(amount, payOrder, aliPayParam);
payBody = this.jsapiPay(amount, payOrder, aliPayParam, aliPayConfig);
}
// 二维码支付
else if (Objects.equals(payOrder.getMethod(), PayMethodEnum.QRCODE.getCode())) {
payBody = this.qrCodePay(amount, payOrder);
payBody = this.qrCodePay(amount, payOrder, aliPayConfig);
}
// 付款码支付, 付款码存在直接支付成功的情况, 所以返回结果特殊处理
else if (Objects.equals(payOrder.getMethod(), PayMethodEnum.BARCODE.getCode())) {
this.barCode(amount, payOrder, aliPayParam, payResult);
this.barCode(amount, payOrder, aliPayParam, payResult, aliPayConfig);
return payResult;
}
// 通常是发起支付的参数
@@ -96,9 +96,9 @@ public class AliPayService {
* wap支付
*/
@SneakyThrows
public String wapPay(String amount, PayOrder payOrder) {
public String wapPay(String amount, PayOrder payOrder, AliPayConfig aliPayConfig) {
// 获取支付宝客户端
AlipayClient alipayClient = aliPayConfigService.getAlipayClient();
AlipayClient alipayClient = aliPayConfigService.getAlipayClient(aliPayConfig);
AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
model.setSubject(payOrder.getTitle());
@@ -106,7 +106,7 @@ public class AliPayService {
model.setTotalAmount(amount);
// 过期时间
model.setTimeExpire(this.getAliTimeExpire(payOrder.getExpiredTime()));
model.setProductCode(AliPayCode.Products.QUICK_WAP_PAY);
model.setProductCode(AlipayCode.Products.QUICK_WAP_PAY);
// 是否分账
if (payOrder.getAllocation()){
ExtendParams extendParams = new ExtendParams();
@@ -115,11 +115,15 @@ public class AliPayService {
}
AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
// 特约商户调用
if (aliPayConfig.isIsv()){
request.putOtherTextParam(AlipayConstants.APP_AUTH_TOKEN, aliPayConfig.getAppAuthToken());
}
request.setBizModel(model);
// 异步回调必须到当前支付网关系统中, 然后系统负责转发
request.setNotifyUrl(aliPayConfigService.getNotifyUrl());
request.setNotifyUrl(aliPayConfigService.getNotifyUrl(aliPayConfig.isIsv()));
// 同步回调地址必须到当前支付网关系统中, 然后系统负责跳转
request.setReturnUrl(aliPayConfigService.getReturnUrl());
request.setReturnUrl(aliPayConfigService.getReturnUrl(aliPayConfig.isIsv()));
try {
// 通过GET方式的请求, 返回URL的响应, 默认是POST方式的请求, 返回的是表单响应
@@ -136,10 +140,10 @@ public class AliPayService {
* app支付
*/
@SneakyThrows
public String appPay(String amount, PayOrder payOrder) {
public String appPay(String amount, PayOrder payOrder, AliPayConfig aliPayConfig) {
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.setSubject(payOrder.getTitle());
model.setProductCode(AliPayCode.Products.QUICK_MSECURITY_PAY);
model.setProductCode(AlipayCode.Products.QUICK_MSECURITY_PAY);
model.setOutTradeNo(payOrder.getOrderNo());
// 过期时间
model.setTimeExpire(this.getAliTimeExpire(payOrder.getExpiredTime()));
@@ -151,11 +155,15 @@ public class AliPayService {
model.setExtendParams(extendParams);
}
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
// 特约商户调用
if (aliPayConfig.isIsv()){
request.putOtherTextParam(AlipayConstants.APP_AUTH_TOKEN, aliPayConfig.getAppAuthToken());
}
request.setBizModel(model);
request.setNotifyUrl(aliPayConfigService.getNotifyUrl());
request.setNotifyUrl(aliPayConfigService.getNotifyUrl(aliPayConfig.isIsv()));
try {
// 异步回调必须到当前系统中
AlipayTradeAppPayResponse response = aliPayConfigService.execute(request);
AlipayTradeAppPayResponse response = aliPayConfigService.execute(request,aliPayConfig);
return response.getBody();
}
catch (AlipayApiException e) {
@@ -168,10 +176,9 @@ public class AliPayService {
* PC支付
*/
@SneakyThrows
public String webPay(String amount, PayOrder payOrder) {
public String webPay(String amount, PayOrder payOrder, AliPayConfig aliPayConfig) {
// 获取支付宝客户端
AlipayClient alipayClient = aliPayConfigService.getAlipayClient();
AlipayClient alipayClient = aliPayConfigService.getAlipayClient(aliPayConfig);
AlipayTradePagePayModel model = new AlipayTradePagePayModel();
model.setSubject(payOrder.getTitle());
model.setOutTradeNo(payOrder.getOrderNo());
@@ -179,7 +186,7 @@ public class AliPayService {
model.setTimeExpire(this.getAliTimeExpire(payOrder.getExpiredTime()));
model.setTotalAmount(amount);
// 目前仅支持FAST_INSTANT_TRADE_PAY
model.setProductCode(AliPayCode.Products.FAST_INSTANT_TRADE_PAY);
model.setProductCode(AlipayCode.Products.FAST_INSTANT_TRADE_PAY);
// 是否分账
if (payOrder.getAllocation()){
@@ -187,13 +194,16 @@ public class AliPayService {
extendParams.setRoyaltyFreeze(Boolean.TRUE.toString());
model.setExtendParams(extendParams);
}
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
// 特约商户调用
if (aliPayConfig.isIsv()){
request.putOtherTextParam(AlipayConstants.APP_AUTH_TOKEN, aliPayConfig.getAppAuthToken());
}
request.setBizModel(model);
// 异步回调必须到当前系统中
request.setNotifyUrl(aliPayConfigService.getNotifyUrl());
request.setNotifyUrl(aliPayConfigService.getNotifyUrl(aliPayConfig.isIsv()));
// 同步回调
request.setReturnUrl(aliPayConfigService.getReturnUrl());
request.setReturnUrl(aliPayConfigService.getReturnUrl(aliPayConfig.isIsv()));
try {
// 通过GET方式的请求, 返回URL的响应, 默认是POST方式的请求, 返回的是表单响应
AlipayTradePagePayResponse response = alipayClient.pageExecute(request, HttpMethod.GET.name());
@@ -209,12 +219,10 @@ public class AliPayService {
* jsapi支付
*/
@SneakyThrows
public String jsapiPay(String amount, PayOrder payOrder, AliPayParam aliPayParam) {
// 构造请求参数以调用接口
AlipayTradeCreateRequest request = new AlipayTradeCreateRequest();
public String jsapiPay(String amount, PayOrder payOrder, AlipayParam aliPayParam, AliPayConfig aliPayConfig) {
AlipayTradeCreateModel model = new AlipayTradeCreateModel();
model.setOutTradeNo(payOrder.getOrderNo());
model.setProductCode(AliPayCode.Products.JSAPI_PAY);
model.setProductCode(AlipayCode.Products.JSAPI_PAY);
model.setOpAppId(aliPayParam.getOpAppId());
model.setTotalAmount(amount);
model.setSubject(payOrder.getTitle());
@@ -233,9 +241,15 @@ public class AliPayService {
extendParams.setRoyaltyFreeze(Boolean.TRUE.toString());
model.setExtendParams(extendParams);
}
// 构造请求参数以调用接口
AlipayTradeCreateRequest request = new AlipayTradeCreateRequest();
// 特约商户调用
if (aliPayConfig.isIsv()){
request.putOtherTextParam(AlipayConstants.APP_AUTH_TOKEN, aliPayConfig.getAppAuthToken());
}
request.setBizModel(model);
try {
AlipayTradeCreateResponse response = aliPayConfigService.execute(request);
AlipayTradeCreateResponse response = aliPayConfigService.execute(request,aliPayConfig);
this.verifyErrorMsg(response);
// my.tradePay使用支付宝交易号调起支付
return response.getTradeNo();
@@ -249,7 +263,7 @@ public class AliPayService {
* 二维码支付(扫码支付)
*/
@SneakyThrows
public String qrCodePay(String amount, PayOrder payOrder) {
public String qrCodePay(String amount, PayOrder payOrder, AliPayConfig aliPayConfig) {
AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
model.setSubject(payOrder.getTitle());
model.setOutTradeNo(payOrder.getOrderNo());
@@ -263,10 +277,14 @@ public class AliPayService {
// 过期时间
model.setTimeExpire(this.getAliTimeExpire(payOrder.getExpiredTime()));
AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
// 特约商户调用
if (aliPayConfig.isIsv()){
request.putOtherTextParam(AlipayConstants.APP_AUTH_TOKEN, aliPayConfig.getAppAuthToken());
}
request.setBizModel(model);
request.setNotifyUrl(aliPayConfigService.getNotifyUrl());
request.setNotifyUrl(aliPayConfigService.getNotifyUrl(aliPayConfig.isIsv()));
try {
AlipayTradePrecreateResponse response = aliPayConfigService.execute(request);
AlipayTradePrecreateResponse response = aliPayConfigService.execute(request,aliPayConfig);
this.verifyErrorMsg(response);
return response.getQrCode();
}
@@ -280,11 +298,11 @@ 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, AliPayConfig aliPayConfig) {
AlipayTradePayModel model = new AlipayTradePayModel();
model.setSubject(payOrder.getTitle());
model.setOutTradeNo(payOrder.getOrderNo());
model.setScene(AliPayCode.Products.BAR_CODE);
model.setScene(AlipayCode.Products.BAR_CODE);
model.setAuthCode(aliPayParam.getAuthCode());
// 是否分账
if (payOrder.getAllocation()){
@@ -296,19 +314,23 @@ public class AliPayService {
model.setTimeExpire(this.getAliTimeExpire(payOrder.getExpiredTime()));
model.setTotalAmount(amount);
AlipayTradePayRequest request = new AlipayTradePayRequest();
// 特约商户调用
if (aliPayConfig.isIsv()){
request.putOtherTextParam(AlipayConstants.APP_AUTH_TOKEN, aliPayConfig.getAppAuthToken());
}
request.setBizModel(model);
request.setNotifyUrl(aliPayConfigService.getNotifyUrl());
request.setNotifyUrl(aliPayConfigService.getNotifyUrl(aliPayConfig.isIsv()));
try {
AlipayTradePayResponse response = aliPayConfigService.execute(request);
AlipayTradePayResponse response = aliPayConfigService.execute(request,aliPayConfig);
// 支付成功处理 金额2000以下免密支付, 记录支付完成相关信息
if (Objects.equals(response.getCode(), AliPayCode.ResponseCode.SUCCESS)) {
if (Objects.equals(response.getCode(), AlipayCode.ResponseCode.SUCCESS)) {
Date gmtPayment = response.getGmtPayment();
result.setOutOrderNo(response.getTradeNo())
.setComplete(true)
.setFinishTime(LocalDateTimeUtil.of(gmtPayment));
}
// 非支付中响应码, 进行错误处理
if (!Objects.equals(response.getCode(), AliPayCode.ResponseCode.INPROCESS)) {
if (!Objects.equals(response.getCode(), AlipayCode.ResponseCode.INPROCESS)) {
this.verifyErrorMsg(response);
}
}
@@ -322,7 +344,7 @@ public class AliPayService {
* 验证错误信息
*/
private void verifyErrorMsg(AlipayResponse alipayResponse) {
if (!Objects.equals(alipayResponse.getCode(), AliPayCode.ResponseCode.SUCCESS)) {
if (!alipayResponse.isSuccess()) {
String errorMsg = alipayResponse.getSubMsg();
if (StrUtil.isBlank(errorMsg)) {
errorMsg = alipayResponse.getMsg();

View File

@@ -1,15 +1,5 @@
package org.dromara.daxpay.channel.alipay.service.reconcile;
import org.dromara.daxpay.channel.alipay.bo.reconcile.AliReconcileBillDetail;
import org.dromara.daxpay.channel.alipay.bo.reconcile.AliReconcileBillTotal;
import org.dromara.daxpay.channel.alipay.code.AliPayCode;
import org.dromara.daxpay.channel.alipay.service.config.AliPayConfigService;
import org.dromara.daxpay.core.enums.TradeStatusEnum;
import org.dromara.daxpay.core.enums.TradeTypeEnum;
import org.dromara.daxpay.core.exception.ReconciliationFailException;
import org.dromara.daxpay.service.bo.reconcile.ChannelReconcileTradeBo;
import org.dromara.daxpay.service.bo.reconcile.ReconcileResolveResultBo;
import org.dromara.daxpay.service.entity.reconcile.ReconcileStatement;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.io.IoUtil;
@@ -18,14 +8,24 @@ import cn.hutool.core.text.csv.CsvUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayConstants;
import com.alipay.api.domain.AlipayDataDataserviceBillDownloadurlQueryModel;
import com.alipay.api.request.AlipayDataDataserviceBillDownloadurlQueryRequest;
import com.alipay.api.response.AlipayDataDataserviceBillDownloadurlQueryResponse;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.dromara.daxpay.channel.alipay.bo.reconcile.AlipayReconcileBillDetail;
import org.dromara.daxpay.channel.alipay.bo.reconcile.AlipayReconcileBillTotal;
import org.dromara.daxpay.channel.alipay.entity.AliPayConfig;
import org.dromara.daxpay.channel.alipay.service.config.AlipayConfigService;
import org.dromara.daxpay.core.enums.TradeStatusEnum;
import org.dromara.daxpay.core.enums.TradeTypeEnum;
import org.dromara.daxpay.core.exception.ReconciliationFailException;
import org.dromara.daxpay.service.bo.reconcile.ChannelReconcileTradeBo;
import org.dromara.daxpay.service.bo.reconcile.ReconcileResolveResultBo;
import org.dromara.daxpay.service.entity.reconcile.ReconcileStatement;
import org.dromara.x.file.storage.core.FileInfo;
import org.dromara.x.file.storage.core.FileStorageService;
import org.dromara.x.file.storage.core.upload.UploadPretreatment;
@@ -50,9 +50,9 @@ import java.util.stream.Collectors;
@Slf4j
@Service
@RequiredArgsConstructor
public class AliPayReconcileService {
public class AlipayReconcileService {
private final AliPayConfigService aliPayConfigService;
private final AlipayConfigService aliPayConfigService;
private final FileStorageService fileStorageService;
@@ -65,16 +65,21 @@ public class AliPayReconcileService {
*/
@SneakyThrows
@Transactional(rollbackFor = Exception.class)
public ReconcileResolveResultBo downAndResolve(String date, ReconcileStatement statement){
public ReconcileResolveResultBo downAndResolve(String date, ReconcileStatement statement, AliPayConfig aliPayConfig){
try {
AlipayDataDataserviceBillDownloadurlQueryModel model = new AlipayDataDataserviceBillDownloadurlQueryModel();
model.setBillDate(date);
// 下载交易类型
model.setBillType("trade");
AlipayDataDataserviceBillDownloadurlQueryRequest request = new AlipayDataDataserviceBillDownloadurlQueryRequest();
// 特约商户调用
if (aliPayConfig.isIsv()){
request.putOtherTextParam(AlipayConstants.APP_AUTH_TOKEN, aliPayConfig.getAppAuthToken());
}
request.setBizModel(model);
AlipayDataDataserviceBillDownloadurlQueryResponse response = aliPayConfigService.execute(request);
var response = aliPayConfigService.execute(request,aliPayConfig);
// 判断返回结果
if (!Objects.equals(AliPayCode.ResponseCode.SUCCESS, response.getCode())) {
if (!response.isSuccess()) {
log.error("获取支付宝对账单失败: {}", response.getSubMsg());
throw new ReconciliationFailException(response.getSubMsg());
}
@@ -85,7 +90,7 @@ public class AliPayReconcileService {
// 使用 Apache commons-compress 包装流, 读取返回的对账CSV文件
ZipArchiveInputStream zipArchiveInputStream = new ZipArchiveInputStream(new ByteArrayInputStream(zipBytes), "GBK");
ZipArchiveEntry entry;
List<AliReconcileBillDetail> billDetails = new ArrayList<>();
List<AlipayReconcileBillDetail> billDetails = new ArrayList<>();
byte[] bytes = null;
while ((entry = zipArchiveInputStream.getNextZipEntry()) != null) {
bytes = IoUtil.readBytes(zipArchiveInputStream);
@@ -120,7 +125,7 @@ public class AliPayReconcileService {
public ReconcileResolveResultBo upload(ReconcileStatement statement, byte[] bytes) {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(bytes),"GBK"));
List<String> strings = IoUtil.readLines(bufferedReader, new ArrayList<>());
List<AliReconcileBillDetail> billDetails = this.parseDetail(strings);
List<AlipayReconcileBillDetail> billDetails = this.parseDetail(strings);
// 保存原始对账文件
String originalFile = this.saveOriginalFile(statement, bytes);
// 将原始交易明细对账记录转换通用结构
@@ -134,7 +139,7 @@ public class AliPayReconcileService {
/**
* 转换为通用对账记录对象
*/
private List<ChannelReconcileTradeBo> convertReconcileTrade(List<AliReconcileBillDetail> billDetails){
private List<ChannelReconcileTradeBo> convertReconcileTrade(List<AlipayReconcileBillDetail> billDetails){
return billDetails.stream()
.map(this::convert)
.toList();
@@ -143,7 +148,7 @@ public class AliPayReconcileService {
/**
* 转换为通用对账记录对象
*/
private ChannelReconcileTradeBo convert(AliReconcileBillDetail billDetail){
private ChannelReconcileTradeBo convert(AlipayReconcileBillDetail billDetail){
// 金额
var amount = new BigDecimal(billDetail.getOrderAmount());
// 默认为支付对账记录
@@ -172,7 +177,7 @@ public class AliPayReconcileService {
/**
* 解析明细
*/
private List<AliReconcileBillDetail> parseDetail(List<String> list){
private List<AlipayReconcileBillDetail> parseDetail(List<String> list){
// 截取需要进行解析的文本内容
String billDetail = list.stream()
.collect(Collectors.joining(System.lineSeparator()));
@@ -181,13 +186,13 @@ public class AliPayReconcileService {
"#-----------------------------------------业务明细列表结束------------------------------------");
billDetail = billDetail.replaceAll("\t", "");
CsvReader reader = CsvUtil.getReader();
return reader.read(billDetail, AliReconcileBillDetail.class);
return reader.read(billDetail, AlipayReconcileBillDetail.class);
}
/**
* 解析汇总
*/
private List<AliReconcileBillTotal> parseTotal(List<String> list){
private List<AlipayReconcileBillTotal> parseTotal(List<String> list){
// 去除前 4 行和后 2 然后合并是个一个字符串
String billTotal = list.stream()
.collect(Collectors.joining(System.lineSeparator()));
@@ -197,7 +202,7 @@ public class AliPayReconcileService {
billTotal = billTotal.replaceAll("\t", "");
CsvReader reader = CsvUtil.getReader();
return reader.read(billTotal, AliReconcileBillTotal.class);
return reader.read(billTotal, AlipayReconcileBillTotal.class);
}
/**

View File

@@ -2,8 +2,8 @@ package org.dromara.daxpay.channel.alipay.service.redirect;
import cn.bootx.platform.core.exception.DataNotExistException;
import cn.bootx.platform.core.exception.ValidationFailedException;
import org.dromara.daxpay.channel.alipay.code.AliPayCode;
import org.dromara.daxpay.channel.alipay.service.config.AliPayConfigService;
import org.dromara.daxpay.channel.alipay.code.AlipayCode;
import org.dromara.daxpay.channel.alipay.service.config.AlipayConfigService;
import org.dromara.daxpay.core.util.PayUtil;
import org.dromara.daxpay.service.dao.order.pay.PayOrderManager;
import org.dromara.daxpay.service.entity.config.PlatformConfig;
@@ -25,23 +25,23 @@ import java.util.Map;
@Slf4j
@Service
@RequiredArgsConstructor
public class AliPayRedirectUrlService {
private final AliPayConfigService aliPayConfigService;
public class AlipayRedirectUrlService {
private final AlipayConfigService aliPayConfigService;
private final PayOrderManager payOrderManager;
private final PlatformConfigService platformConfigService;
/**
* 回调地址处理
*/
public String redirect(HttpServletRequest request){
public String redirect(HttpServletRequest request, boolean isv){
Map<String, String> map = PayUtil.toMap(request);
// 首先进行验签
if (!aliPayConfigService.verifyNotify(map)){
if (!aliPayConfigService.verifyNotify(map,isv)){
log.error("支付宝同步通知消息验签失败");
throw new ValidationFailedException("支付宝同步通知消息验签失败");
}
// 获取订单号
String outTradeNo = map.get(AliPayCode.ResponseParams.OUT_TRADE_NO);
String outTradeNo = map.get(AlipayCode.ResponseParams.OUT_TRADE_NO);
PayOrder order = payOrderManager.findByOrderNo(outTradeNo)
.orElseThrow(() -> new DataNotExistException("订单不存在"));
// 订单配置后跳转到指定的地址, 不存在跳转到预设的地址
@@ -51,6 +51,7 @@ public class AliPayRedirectUrlService {
PlatformConfig platformConfig = platformConfigService.getConfig();
String serverUrl = platformConfig.getGatewayMobileUrl();
return StrUtil.format("{}/alipay/pay/finish", serverUrl);
}
}
}

View File

@@ -1,7 +1,7 @@
package org.dromara.daxpay.channel.alipay.service.refund;
import org.dromara.daxpay.channel.alipay.code.AliPayCode;
import org.dromara.daxpay.channel.alipay.service.config.AliPayConfigService;
import org.dromara.daxpay.channel.alipay.entity.AliPayConfig;
import org.dromara.daxpay.channel.alipay.service.config.AlipayConfigService;
import org.dromara.daxpay.core.enums.RefundStatusEnum;
import org.dromara.daxpay.core.exception.OperationFailException;
import org.dromara.daxpay.core.exception.TradeFailException;
@@ -9,6 +9,7 @@ import org.dromara.daxpay.core.util.PayUtil;
import org.dromara.daxpay.service.bo.trade.RefundResultBo;
import org.dromara.daxpay.service.entity.order.refund.RefundOrder;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayConstants;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeRefundResponse;
@@ -18,7 +19,6 @@ import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
/**
* 支付宝退款服务
@@ -28,16 +28,16 @@ import java.util.Objects;
@Slf4j
@Service
@RequiredArgsConstructor
public class AliPayRefundService {
public class AlipayRefundService {
private final AliPayConfigService aliPayConfigService;
private final AlipayConfigService aliPayConfigService;
/**
* 退款, 调用支付宝退款
*/
public RefundResultBo refund(RefundOrder refundOrder) {
public RefundResultBo refund(RefundOrder refundOrder,AliPayConfig aliPayConfig) {
RefundResultBo refundInfo = new RefundResultBo();
AlipayTradeRefundModel model = new AlipayTradeRefundModel();
var model = new AlipayTradeRefundModel();
model.setOutTradeNo(refundOrder.getOrderNo());
model.setOutRequestNo(refundOrder.getRefundNo());
// 金额格式化
@@ -45,12 +45,15 @@ public class AliPayRefundService {
model.setRefundAmount(refundAmount);
// 银行卡冲退信息, 只有传输了此值, 才会触发退款回调
model.setQueryOptions(List.of("deposit_back_info"));
AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
// 特约商户调用
if (aliPayConfig.isIsv()){
request.putOtherTextParam(AlipayConstants.APP_AUTH_TOKEN, aliPayConfig.getAppAuthToken());
}
request.setBizModel(model);
try {
AlipayTradeRefundResponse response = aliPayConfigService.execute(request);
if (!Objects.equals(AliPayCode.ResponseCode.SUCCESS, response.getCode())) {
AlipayTradeRefundResponse response = aliPayConfigService.execute(request,aliPayConfig);
if (!response.isSuccess()) {
TradeFailException operationFailException = new TradeFailException("支付宝退款失败: "+response.getSubMsg());
log.error("支付宝退款失败: {}", response.getSubMsg());
throw operationFailException;

View File

@@ -1,13 +1,15 @@
package org.dromara.daxpay.channel.alipay.service.sync;
import cn.bootx.platform.core.util.JsonUtil;
import org.dromara.daxpay.channel.alipay.code.AliPayCode;
import org.dromara.daxpay.channel.alipay.service.config.AliPayConfigService;
import org.dromara.daxpay.channel.alipay.code.AlipayCode;
import org.dromara.daxpay.channel.alipay.entity.AliPayConfig;
import org.dromara.daxpay.channel.alipay.service.config.AlipayConfigService;
import org.dromara.daxpay.core.enums.RefundStatusEnum;
import org.dromara.daxpay.service.bo.sync.RefundSyncResultBo;
import org.dromara.daxpay.service.entity.order.refund.RefundOrder;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayConstants;
import com.alipay.api.domain.AlipayTradeFastpayRefundQueryModel;
import com.alipay.api.request.AlipayTradeFastpayRefundQueryRequest;
import com.alipay.api.response.AlipayTradeFastpayRefundQueryResponse;
@@ -27,15 +29,15 @@ import java.util.Objects;
@Slf4j
@Service
@RequiredArgsConstructor
public class AliPayRefundSyncService {
public class AlipayRefundSyncService {
private final AliPayConfigService aliPayConfigService;
private final AlipayConfigService aliPayConfigService;
/**
* 退款同步查询
* 注意: 支付宝退款没有网关订单号, 网关订单号是支付单的
*/
public RefundSyncResultBo syncRefundStatus(RefundOrder refundOrder){
public RefundSyncResultBo syncRefundStatus(RefundOrder refundOrder,AliPayConfig aliPayConfig){
RefundSyncResultBo syncResult = new RefundSyncResultBo();
try {
AlipayTradeFastpayRefundQueryModel model = new AlipayTradeFastpayRefundQueryModel();
@@ -44,13 +46,17 @@ public class AliPayRefundSyncService {
// 商户订单号
model.setOutTradeNo(String.valueOf(refundOrder.getOrderNo()));
// 设置返回退款完成时间
model.setQueryOptions(Collections.singletonList(AliPayCode.ResponseParams.GMT_REFUND_PAY));
model.setQueryOptions(Collections.singletonList(AlipayCode.ResponseParams.GMT_REFUND_PAY));
AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
// 特约商户调用
if (aliPayConfig.isIsv()){
request.putOtherTextParam(AlipayConstants.APP_AUTH_TOKEN, aliPayConfig.getAppAuthToken());
}
request.setBizModel(model);
AlipayTradeFastpayRefundQueryResponse response = aliPayConfigService.execute(request);
AlipayTradeFastpayRefundQueryResponse response = aliPayConfigService.execute(request,aliPayConfig);
syncResult.setSyncData(JsonUtil.toJsonStr(response));
// 失败
if (!Objects.equals(AliPayCode.ResponseCode.SUCCESS, response.getCode())) {
if (!response.isSuccess()) {
syncResult.setSyncSuccess(false)
.setSyncErrorCode(response.getSubCode())
.setRefundStatus(RefundStatusEnum.FAIL)
@@ -59,7 +65,7 @@ public class AliPayRefundSyncService {
}
String tradeStatus = response.getRefundStatus();
// 成功
if (Objects.equals(tradeStatus, AliPayCode.RefundStatus.REFUND_SUCCESS)){
if (Objects.equals(tradeStatus, AlipayCode.RefundStatus.REFUND_SUCCESS)){
LocalDateTime localDateTime = LocalDateTimeUtil.of(response.getGmtRefundPay());
return syncResult.setFinishTime(localDateTime).setRefundStatus(RefundStatusEnum.SUCCESS);
} else {
@@ -67,10 +73,10 @@ public class AliPayRefundSyncService {
}
} catch (AlipayApiException e) {
log.error("退款订单同步失败:", e);
syncResult.setSyncErrorMsg(e.getErrMsg());
syncResult.setSyncErrorMsg(e.getErrMsg())
.setSyncSuccess(false)
.setRefundStatus(RefundStatusEnum.FAIL);
}
return syncResult;
}
}

View File

@@ -1,14 +1,16 @@
package org.dromara.daxpay.channel.alipay.service.sync;
import cn.bootx.platform.core.util.JsonUtil;
import org.dromara.daxpay.channel.alipay.code.AliPayCode;
import org.dromara.daxpay.channel.alipay.code.AliPayCode.PayStatus;
import org.dromara.daxpay.channel.alipay.service.config.AliPayConfigService;
import org.dromara.daxpay.channel.alipay.code.AlipayCode;
import org.dromara.daxpay.channel.alipay.code.AlipayCode.PayStatus;
import org.dromara.daxpay.channel.alipay.entity.AliPayConfig;
import org.dromara.daxpay.channel.alipay.service.config.AlipayConfigService;
import org.dromara.daxpay.core.enums.PayStatusEnum;
import org.dromara.daxpay.service.bo.sync.PaySyncResultBo;
import org.dromara.daxpay.service.entity.order.pay.PayOrder;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayConstants;
import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeQueryResponse;
@@ -29,8 +31,8 @@ import java.util.Objects;
@Slf4j
@Service
@RequiredArgsConstructor
public class AliPaySyncService {
private final AliPayConfigService aliPayConfigService;
public class AlipaySyncService {
private final AlipayConfigService aliPayConfigService;
/**
* 与支付宝网关同步状态, 退款状态有
@@ -40,15 +42,19 @@ public class AliPaySyncService {
* 4 查询不到
* 5 查询失败
*/
public PaySyncResultBo syncPayStatus(PayOrder payOrder){
public PaySyncResultBo syncPayStatus(PayOrder payOrder,AliPayConfig aliPayConfig){
PaySyncResultBo syncResult = new PaySyncResultBo();
// 查询
try {
AlipayTradeQueryModel model = new AlipayTradeQueryModel();
model.setOutTradeNo(payOrder.getOrderNo());
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
// 特约商户调用
if (aliPayConfig.isIsv()){
request.putOtherTextParam(AlipayConstants.APP_AUTH_TOKEN, aliPayConfig.getAppAuthToken());
}
request.setBizModel(model);
AlipayTradeQueryResponse response = aliPayConfigService.execute(request);
AlipayTradeQueryResponse response = aliPayConfigService.execute(request,aliPayConfig);
String tradeStatus = response.getTradeStatus();
syncResult.setSyncData(JsonUtil.toJsonStr(response));
// 设置网关订单号
@@ -73,11 +79,11 @@ public class AliPaySyncService {
}
}
// 支付宝支付后, 客户未进行操作将不会创建出订单, 所以交易不存在约等于未查询订单
if (Objects.equals(response.getSubCode(), AliPayCode.ResponseCode.ACQ_TRADE_NOT_EXIST)) {
if (Objects.equals(response.getSubCode(), AlipayCode.ResponseCode.ACQ_TRADE_NOT_EXIST)) {
return syncResult.setPayStatus(PayStatusEnum.PROGRESS);
}
// 查询失败
if (!Objects.equals(AliPayCode.ResponseCode.SUCCESS, response.getCode())) {
if (!response.isSuccess()) {
return syncResult.setSyncSuccess(false)
.setSyncErrorCode(response.getSubCode())
.setSyncErrorMsg(response.getSubMsg());
@@ -85,7 +91,9 @@ public class AliPaySyncService {
}
catch (AlipayApiException e) {
log.error("支付订单同步失败:", e);
syncResult.setSyncErrorMsg(e.getErrMsg()).setSyncSuccess(false);
syncResult.setSyncErrorMsg(e.getErrMsg())
.setSyncSuccess(false)
.setPayStatus(PayStatusEnum.FAIL);
}
return syncResult;
}

View File

@@ -1,12 +1,14 @@
package org.dromara.daxpay.channel.alipay.service.sync;
import cn.bootx.platform.core.util.JsonUtil;
import org.dromara.daxpay.channel.alipay.code.AliPayCode.TransferStatus;
import org.dromara.daxpay.channel.alipay.service.config.AliPayConfigService;
import org.dromara.daxpay.channel.alipay.code.AlipayCode.TransferStatus;
import org.dromara.daxpay.channel.alipay.entity.AliPayConfig;
import org.dromara.daxpay.channel.alipay.service.config.AlipayConfigService;
import org.dromara.daxpay.core.enums.TransferStatusEnum;
import org.dromara.daxpay.service.bo.sync.TransferSyncResultBo;
import org.dromara.daxpay.service.entity.order.transfer.TransferOrder;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayConstants;
import com.alipay.api.domain.AlipayFundTransCommonQueryModel;
import com.alipay.api.request.AlipayFundTransCommonQueryRequest;
import lombok.RequiredArgsConstructor;
@@ -24,17 +26,20 @@ import java.util.Objects;
@Slf4j
@Service
@RequiredArgsConstructor
public class AliPayTransferSyncService {
public class AlipayTransferSyncService {
private final AliPayConfigService aliPayConfigService;
private final AlipayConfigService aliPayConfigService;
/**
* 转账同步
*/
public TransferSyncResultBo syncTransferStatus(TransferOrder transferOrder){
public TransferSyncResultBo syncTransferStatus(TransferOrder transferOrder, AliPayConfig aliPayConfig){
TransferSyncResultBo syncResult = new TransferSyncResultBo();
// 构造请求参数以调用接口
AlipayFundTransCommonQueryRequest request = new AlipayFundTransCommonQueryRequest();
var request = new AlipayFundTransCommonQueryRequest();
// 特约商户调用
if (aliPayConfig.isIsv()){
request.putOtherTextParam(AlipayConstants.APP_AUTH_TOKEN, aliPayConfig.getAppAuthToken());
}
AlipayFundTransCommonQueryModel model = new AlipayFundTransCommonQueryModel();
// 设置销售产品码
model.setProductCode("STD_RED_PACKET");
@@ -44,7 +49,7 @@ public class AliPayTransferSyncService {
model.setOutBizNo(transferOrder.getTransferNo());
request.setBizModel(model);
try {
var response = aliPayConfigService.execute(request);
var response = aliPayConfigService.execute(request,aliPayConfig);
// 设置网关订单号
syncResult.setSyncData(JsonUtil.toJsonStr(response));
// 设置网关订单号
@@ -70,7 +75,9 @@ public class AliPayTransferSyncService {
return syncResult;
} catch (AlipayApiException e) {
log.error("支付宝转账记录同步失败:", e);
return syncResult.setSyncErrorMsg(e.getErrMsg()).setSyncSuccess(false);
return syncResult.setSyncErrorMsg(e.getErrMsg())
.setSyncSuccess(false)
.setTransferStatus(TransferStatusEnum.FAIL);
}
}
}

View File

@@ -1,8 +1,8 @@
package org.dromara.daxpay.channel.alipay.service.transfer;
import org.dromara.daxpay.channel.alipay.code.AliPayCode;
import org.dromara.daxpay.channel.alipay.entity.config.AliPayConfig;
import org.dromara.daxpay.channel.alipay.service.config.AliPayConfigService;
import org.dromara.daxpay.channel.alipay.code.AlipayCode;
import org.dromara.daxpay.channel.alipay.entity.AliPayConfig;
import org.dromara.daxpay.channel.alipay.service.config.AlipayConfigService;
import org.dromara.daxpay.core.enums.TransferPayeeTypeEnum;
import org.dromara.daxpay.core.enums.TransferStatusEnum;
import org.dromara.daxpay.core.exception.OperationFailException;
@@ -30,9 +30,9 @@ import java.util.Objects;
@Slf4j
@Service
@RequiredArgsConstructor
public class AliPayTransferService {
public class AlipayTransferService {
private final AliPayConfigService aliPayConfigService;
private final AlipayConfigService aliPayConfigService;
/**
* 余额查询接口
@@ -40,18 +40,18 @@ public class AliPayTransferService {
@SneakyThrows
public void queryAccountAmount(AliPayConfig config, AliPayConfig aliPayConfig){
AlipayFundAccountQueryModel model = new AlipayFundAccountQueryModel();
model.setAccountType(AliPayCode.Products.QUERY_ACCOUNT_TYPE);
model.setAccountType(AlipayCode.Products.QUERY_ACCOUNT_TYPE);
model.setAlipayUserId(config.getAlipayUserId());
AlipayFundAccountQueryRequest request = new AlipayFundAccountQueryRequest();
request.setBizModel(model);
AlipayFundAccountQueryResponse response = aliPayConfigService.execute(request);
AlipayFundAccountQueryResponse response = aliPayConfigService.execute(request,aliPayConfig);
}
/**
* 转账接口
*/
@SneakyThrows
public TransferResultBo transfer(TransferOrder order){
public TransferResultBo transfer(TransferOrder order,AliPayConfig aliPayConfig){
TransferResultBo transferInfo = new TransferResultBo();
// 构造请求参数以调用接口
AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
@@ -84,15 +84,15 @@ public class AliPayTransferService {
model.setPayeeInfo(payeeInfo);
model.setRemark(order.getReason());
request.setBizModel(model);
AlipayFundTransUniTransferResponse response = aliPayConfigService.execute(request);
if (!Objects.equals(AliPayCode.ResponseCode.SUCCESS, response.getCode())) {
AlipayFundTransUniTransferResponse response = aliPayConfigService.execute(request,aliPayConfig);
if (!response.isSuccess()) {
log.error("支付宝转账失败: {}", response.getSubMsg());
throw new TradeFailException("支付宝转账失败: "+response.getSubMsg());
}
// 通道转账号
transferInfo.setOutTransferNo(response.getOrderId());
// 有完成时间代表处理完成
if (Objects.equals(response.getStatus(), AliPayCode.ResponseCode.TRANSFER_SUCCESS)){
if (Objects.equals(response.getStatus(), AlipayCode.ResponseCode.TRANSFER_SUCCESS)){
// 时间
String transDate = response.getTransDate();
LocalDateTime time = LocalDateTimeUtil.parse(transDate, DatePattern.NORM_DATETIME_PATTERN);

View File

@@ -1,26 +0,0 @@
package org.dromara.daxpay.channel.alipay.strategy;
import org.dromara.daxpay.core.enums.ChannelEnum;
import org.dromara.daxpay.service.strategy.AbsCashierCodeStrategy;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* 支付宝收银码牌支付
* @author xxm
* @since 2024/9/29
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class AliPayCashierCodeStrategy extends AbsCashierCodeStrategy {
/**
* 策略标识, 可以自行进行扩展
*/
@Override
public String getChannel() {
return ChannelEnum.ALIPAY.getCode();
}
}

View File

@@ -0,0 +1,56 @@
package org.dromara.daxpay.channel.alipay.strategy.isv;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.daxpay.channel.alipay.entity.AliPayConfig;
import org.dromara.daxpay.channel.alipay.service.config.AlipayConfigService;
import org.dromara.daxpay.channel.alipay.service.extra.AlipayAuthService;
import org.dromara.daxpay.core.enums.ChannelEnum;
import org.dromara.daxpay.core.param.assist.AuthCodeParam;
import org.dromara.daxpay.core.param.assist.GenerateAuthUrlParam;
import org.dromara.daxpay.core.result.assist.AuthResult;
import org.dromara.daxpay.core.result.assist.AuthUrlResult;
import org.dromara.daxpay.service.strategy.AbsChannelAuthStrategy;
import org.springframework.stereotype.Component;
/**
* 支付宝授权策略
* @author xxm
* @since 2024/9/24
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class AlipayIsvAuthStrategy extends AbsChannelAuthStrategy {
private final AlipayAuthService aliPayAuthService;
private final AlipayConfigService aliPayConfigService;
/**
* 策略标识, 可以自行进行扩展
*
* @see ChannelEnum
*/
@Override
public String getChannel() {
return ChannelEnum.ALIPAY_ISV.getCode();
}
/**
* 获取授权链接
*/
@Override
public AuthUrlResult generateAuthUrl(GenerateAuthUrlParam param) {
AliPayConfig aliPayConfig = aliPayConfigService.getAliPayConfig(true);
return aliPayAuthService.generateAuthUrl(param, aliPayConfig);
}
/**
* 通过AuthCode兑换认证结果
*/
@Override
public AuthResult doAuth(AuthCodeParam param) {
AliPayConfig aliPayConfig = aliPayConfigService.getAliPayConfig(true);
return aliPayAuthService.getOpenIdOrUserId(param.getAuthCode(), aliPayConfig);
}
}

View File

@@ -0,0 +1,38 @@
package org.dromara.daxpay.channel.alipay.strategy.isv;
import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.daxpay.core.enums.ChannelEnum;
import org.dromara.daxpay.service.strategy.AbsCheckoutStrategy;
import org.springframework.stereotype.Component;
/**
* 支付宝
* @author xxm
* @since 2024/12/2
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class AlipayIsvCheckoutStrategy extends AbsCheckoutStrategy {
/**
* 策略标识, 可以自行进行扩展
*
* @see ChannelEnum
*/
@Override
public String getChannel() {
return ChannelEnum.ALIPAY_ISV.getCode();
}
/**
* 检测付款码
*/
@Override
public boolean checkBarCode(String barCode){
String[] ali = { "25", "26", "27", "28", "29", "30" };
return StrUtil.startWithAny(barCode.substring(0, 2), ali);
}
}

View File

@@ -0,0 +1,54 @@
package org.dromara.daxpay.channel.alipay.strategy.isv;
import org.dromara.daxpay.channel.alipay.entity.AliPayConfig;
import org.dromara.daxpay.channel.alipay.service.close.AliPayCloseService;
import org.dromara.daxpay.channel.alipay.service.config.AlipayConfigService;
import org.dromara.daxpay.core.enums.ChannelEnum;
import org.dromara.daxpay.core.enums.CloseTypeEnum;
import org.dromara.daxpay.service.strategy.AbsPayCloseStrategy;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* 支付宝支付订单关闭
* @author xxm
* @since 2023/12/30
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class AlipayIsvCloseStrategy extends AbsPayCloseStrategy {
private final AlipayConfigService alipayConfigService;
private final AliPayCloseService aliPayCloseService;
private AliPayConfig alipayConfig;
@Override
public String getChannel() {
return ChannelEnum.ALIPAY_ISV.getCode();
}
/**
* 关闭前的处理方式
*/
@Override
public void doBeforeCloseHandler() {
this.alipayConfig = alipayConfigService.getAndCheckConfig(true);
}
/**
* 关闭操作
*/
@Override
public CloseTypeEnum doCloseHandler() {
if (this.isUseCancel()){
aliPayCloseService.cancel(this.getOrder(), this.alipayConfig);
return CloseTypeEnum.CANCEL;
} else {
aliPayCloseService.close(this.getOrder(), this.alipayConfig);
return CloseTypeEnum.CLOSE;
}
}
}

View File

@@ -0,0 +1,73 @@
package org.dromara.daxpay.channel.alipay.strategy.isv;
import cn.bootx.platform.core.exception.ValidationFailedException;
import cn.bootx.platform.core.util.JsonUtil;
import org.dromara.daxpay.channel.alipay.entity.AliPayConfig;
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.pay.AliPayService;
import org.dromara.daxpay.core.enums.ChannelEnum;
import org.dromara.daxpay.service.bo.trade.PayResultBo;
import org.dromara.daxpay.service.strategy.AbsPayStrategy;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONException;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;
/**
* 支付宝支付
* @author xxm
* @since 2021/2/27
*/
@Scope(SCOPE_PROTOTYPE)
@Component
@RequiredArgsConstructor
public class AlipayIsvPayStrategy extends AbsPayStrategy {
private final AliPayService aliPayService;
private final AlipayConfigService aliPayConfigService;
private AlipayParam aliPayParam;
private AliPayConfig aliPayConfig;
@Override
public String getChannel() {
return ChannelEnum.ALIPAY_ISV.getCode();
}
/**
* 支付前操作
*/
@Override
public void doBeforePayHandler() {
try {
// 支付宝参数验证
String channelParam = this.getPayParam().getExtraParam();
if (StrUtil.isNotBlank(channelParam)) {
this.aliPayParam = JsonUtil.toBean(channelParam, AlipayParam.class);
}
else {
this.aliPayParam = new AlipayParam();
}
}
catch (JSONException e) {
throw new ValidationFailedException("支付参数错误");
}
aliPayConfig = aliPayConfigService.getAndCheckConfig(true);
// 支付宝相关校验
aliPayService.validation(this.getPayParam(),aliPayConfig);
}
/**
* 发起支付操作
*/
@Override
public PayResultBo doPayHandler() {
return aliPayService.pay(this.getOrder(), this.aliPayParam,aliPayConfig);
}
}

View File

@@ -0,0 +1,64 @@
package org.dromara.daxpay.channel.alipay.strategy.isv;
import org.dromara.daxpay.channel.alipay.entity.AliPayConfig;
import org.dromara.daxpay.channel.alipay.service.config.AlipayConfigService;
import org.dromara.daxpay.channel.alipay.service.reconcile.AlipayReconcileService;
import org.dromara.daxpay.core.enums.ChannelEnum;
import org.dromara.daxpay.service.bo.reconcile.ReconcileResolveResultBo;
import org.dromara.daxpay.service.enums.ReconcileFileTypeEnum;
import org.dromara.daxpay.service.strategy.AbsReconcileStrategy;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;
/**
* 支付宝对账策略
* @author xxm
* @since 2024/1/17
*/
@Slf4j
@Service
@Scope(SCOPE_PROTOTYPE)
@RequiredArgsConstructor
public class AlipayIsvReconcileStrategy extends AbsReconcileStrategy {
private final AlipayReconcileService reconcileService;
private final AlipayConfigService aliPayConfigService;
/**
* 策略标识, 可以自行进行扩展
*
* @see ChannelEnum
*/
@Override
public String getChannel() {
return ChannelEnum.ALIPAY_ISV.getCode();
}
/**
* 上传对账单解析并保存
*
*/
@SneakyThrows
@Override
public ReconcileResolveResultBo uploadAndResolve(MultipartFile file, ReconcileFileTypeEnum fileType) {
return reconcileService.upload(this.getStatement(), file.getBytes());
}
/**
* 下载对账单到本地进行保存
*/
@Override
public ReconcileResolveResultBo downAndResolve() {
AliPayConfig aliPayConfig = aliPayConfigService.getAliPayConfig(true);
String date = LocalDateTimeUtil.format(this.getStatement().getDate(), DatePattern.NORM_DATE_PATTERN);
return reconcileService.downAndResolve(date, this.getStatement(),aliPayConfig);
}
}

View File

@@ -0,0 +1,46 @@
package org.dromara.daxpay.channel.alipay.strategy.isv;
import org.dromara.daxpay.channel.alipay.entity.AliPayConfig;
import org.dromara.daxpay.channel.alipay.service.config.AlipayConfigService;
import org.dromara.daxpay.channel.alipay.service.refund.AlipayRefundService;
import org.dromara.daxpay.core.enums.ChannelEnum;
import org.dromara.daxpay.service.bo.trade.RefundResultBo;
import org.dromara.daxpay.service.strategy.AbsRefundStrategy;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;
/**
* 支付宝退款
* @author xxm
* @since 2023/7/4
*/
@Scope(SCOPE_PROTOTYPE)
@Component
@RequiredArgsConstructor
public class AlipayIsvRefundStrategy extends AbsRefundStrategy {
private final AlipayRefundService aliRefundService;
private final AlipayConfigService aliPayConfigService;
/**
* 策略标识
* @see ChannelEnum
*/
@Override
public String getChannel() {
return ChannelEnum.ALIPAY_ISV.getCode();
}
/**
* 退款
*/
@Override
public RefundResultBo doRefundHandler() {
AliPayConfig aliPayConfig = aliPayConfigService.getAliPayConfig(true);
return aliRefundService.refund(this.getRefundOrder(), aliPayConfig);
}
}

View File

@@ -0,0 +1,45 @@
package org.dromara.daxpay.channel.alipay.strategy.isv;
import org.dromara.daxpay.channel.alipay.entity.AliPayConfig;
import org.dromara.daxpay.channel.alipay.service.config.AlipayConfigService;
import org.dromara.daxpay.channel.alipay.service.sync.AlipaySyncService;
import org.dromara.daxpay.core.enums.ChannelEnum;
import org.dromara.daxpay.service.bo.sync.PaySyncResultBo;
import org.dromara.daxpay.service.strategy.AbsSyncPayOrderStrategy;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;
/**
* 支付宝支付同步
* @author xxm
* @since 2023/7/14
*/
@Scope(SCOPE_PROTOTYPE)
@Component
@RequiredArgsConstructor
public class AlipayIsvSyncOrderStrategy extends AbsSyncPayOrderStrategy {
private final AlipaySyncService alipaySyncService;
private final AlipayConfigService aliPayConfigService;
/**
* 策略标识
*/
@Override
public String getChannel() {
return ChannelEnum.ALIPAY_ISV.getCode();
}
/**
* 异步支付单与支付网关进行状态比对
*/
@Override
public PaySyncResultBo doSync() {
AliPayConfig andCheckConfig = aliPayConfigService.getAndCheckConfig(true);
return alipaySyncService.syncPayStatus(this.getOrder(),andCheckConfig);
}
}

View File

@@ -0,0 +1,66 @@
package org.dromara.daxpay.channel.alipay.strategy.isv;
import org.dromara.daxpay.channel.alipay.entity.AliPayConfig;
import org.dromara.daxpay.channel.alipay.service.config.AlipayConfigService;
import org.dromara.daxpay.channel.alipay.service.sync.AlipayRefundSyncService;
import org.dromara.daxpay.core.enums.ChannelEnum;
import org.dromara.daxpay.core.exception.OperationFailException;
import org.dromara.daxpay.service.bo.sync.RefundSyncResultBo;
import org.dromara.daxpay.service.entity.order.refund.RefundOrder;
import org.dromara.daxpay.service.strategy.AbsSyncRefundOrderStrategy;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;
/**
* 支付宝退款订单查询
* @author xxm
* @since 2024/7/25
*/
@Scope(SCOPE_PROTOTYPE)
@Component
@RequiredArgsConstructor
public class AlipayIsvSyncRefundStrategy extends AbsSyncRefundOrderStrategy {
private final AlipayRefundSyncService alipaySyncService;
private final AlipayConfigService aliPayConfigService;
/**
* 策略标识, 可以自行进行扩展
*
* @see ChannelEnum
*/
@Override
public String getChannel() {
return ChannelEnum.ALIPAY_ISV.getCode();
}
/**
* 间隔10秒以上再发起退款查询请求。小于10s可能会导致查询到的状态不正确, 因为支付宝没有转账失败的状态
*/
@Override
public void doBeforeHandler() {
RefundOrder refundOrder = this.getRefundOrder();
if (refundOrder.getReqTime().plusSeconds(10).isAfter(LocalDateTime.now())) {
throw new OperationFailException("间隔10秒以上再发起退款查询请求");
}
}
/**
* 异步支付单与支付网关进行状态比对后的结果
*
*/
@Override
public RefundSyncResultBo doSync() {
AliPayConfig aliPayConfig = aliPayConfigService.getAndCheckConfig(true);
return alipaySyncService.syncRefundStatus(this.getRefundOrder(),aliPayConfig);
}
}

View File

@@ -1,4 +1,4 @@
package org.dromara.daxpay.channel.alipay.strategy;
package org.dromara.daxpay.channel.alipay.strategy.merchant;
import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;

View File

@@ -1,8 +1,10 @@
package org.dromara.daxpay.channel.alipay.strategy;
package org.dromara.daxpay.channel.alipay.strategy.merchant;
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.entity.AliPayConfig;
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.pay.AliPayService;
import org.dromara.daxpay.core.enums.ChannelEnum;
import org.dromara.daxpay.service.bo.trade.PayResultBo;
@@ -27,7 +29,11 @@ public class AliPayStrategy extends AbsPayStrategy {
private final AliPayService aliPayService;
private AliPayParam aliPayParam;
private final AlipayConfigService aliPayConfigService;
private AlipayParam aliPayParam;
private AliPayConfig aliPayConfig;
@Override
public String getChannel() {
@@ -43,17 +49,18 @@ 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) {
throw new ValidationFailedException("支付参数错误");
}
aliPayConfig = aliPayConfigService.getAndCheckConfig(false);
// 支付宝相关校验
aliPayService.validation(this.getPayParam());
aliPayService.validation(this.getPayParam(),aliPayConfig);
}
/**
@@ -61,7 +68,7 @@ public class AliPayStrategy extends AbsPayStrategy {
*/
@Override
public PayResultBo doPayHandler() {
return aliPayService.pay(this.getOrder(), this.aliPayParam);
return aliPayService.pay(this.getOrder(), this.aliPayParam,aliPayConfig);
}
}

View File

@@ -1,10 +1,12 @@
package org.dromara.daxpay.channel.alipay.strategy;
package org.dromara.daxpay.channel.alipay.strategy.merchant;
import lombok.RequiredArgsConstructor;
import org.dromara.daxpay.channel.alipay.service.sync.AliPayTransferSyncService;
import org.dromara.daxpay.channel.alipay.entity.AliPayConfig;
import org.dromara.daxpay.channel.alipay.service.config.AlipayConfigService;
import org.dromara.daxpay.channel.alipay.service.sync.AlipayTransferSyncService;
import org.dromara.daxpay.core.enums.ChannelEnum;
import org.dromara.daxpay.service.bo.sync.TransferSyncResultBo;
import org.dromara.daxpay.service.strategy.AbsSyncTransferOrderStrategy;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@@ -20,7 +22,8 @@ import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROT
@RequiredArgsConstructor
public class AliPaySyncTransferStrategy extends AbsSyncTransferOrderStrategy {
private final AliPayTransferSyncService syncTransferOrderStrategy;
private final AlipayTransferSyncService syncTransferOrderStrategy;
private final AlipayConfigService aliPayConfigService;
/**
* 策略标识, 可以自行进行扩展
@@ -37,7 +40,8 @@ public class AliPaySyncTransferStrategy extends AbsSyncTransferOrderStrategy {
*/
@Override
public TransferSyncResultBo doSync() {
return syncTransferOrderStrategy.syncTransferStatus(getTransferOrder());
AliPayConfig aliPayConfig = aliPayConfigService.getAliPayConfig(false);
return syncTransferOrderStrategy.syncTransferStatus(this.getTransferOrder(),aliPayConfig);
}
}

View File

@@ -1,9 +1,11 @@
package org.dromara.daxpay.channel.alipay.strategy;
package org.dromara.daxpay.channel.alipay.strategy.merchant;
import cn.bootx.platform.core.exception.ValidationFailedException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.daxpay.channel.alipay.entity.AliPayConfig;
import org.dromara.daxpay.channel.alipay.service.allocation.AliPayAllocReceiverService;
import org.dromara.daxpay.channel.alipay.service.config.AlipayConfigService;
import org.dromara.daxpay.core.enums.AllocReceiverTypeEnum;
import org.dromara.daxpay.core.enums.ChannelEnum;
import org.dromara.daxpay.service.strategy.AbsAllocReceiverStrategy;
@@ -23,10 +25,12 @@ import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROT
@Service
@Scope(SCOPE_PROTOTYPE)
@RequiredArgsConstructor
public class AliPayAllocReceiverStrategy extends AbsAllocReceiverStrategy {
public class AlipayAllocReceiverStrategy extends AbsAllocReceiverStrategy {
private final AliPayAllocReceiverService receiverService;
private final AlipayConfigService aliPayConfigService;
/**
* 策略标识
*/
@@ -45,6 +49,7 @@ public class AliPayAllocReceiverStrategy extends AbsAllocReceiverStrategy {
*/
@Override
public boolean validation(){
AliPayConfig aliPayConfig = aliPayConfigService.getAliPayConfig(false);
return receiverService.validation(this.getAllocReceiver());
}
@@ -53,10 +58,11 @@ public class AliPayAllocReceiverStrategy extends AbsAllocReceiverStrategy {
*/
@Override
public void bind() {
AliPayConfig aliPayConfig = aliPayConfigService.getAliPayConfig(false);
if (!receiverService.validation(this.getAllocReceiver())){
throw new ValidationFailedException("分账接收者参数未通过校验");
}
receiverService.bind(this.getAllocReceiver());
receiverService.bind(this.getAllocReceiver(),aliPayConfig);
}
/**
@@ -64,9 +70,10 @@ public class AliPayAllocReceiverStrategy extends AbsAllocReceiverStrategy {
*/
@Override
public void unbind() {
AliPayConfig aliPayConfig = aliPayConfigService.getAliPayConfig(false);
if (!receiverService.validation(this.getAllocReceiver())){
throw new ValidationFailedException("分账参数未通过校验");
}
receiverService.unbind(this.getAllocReceiver());
receiverService.unbind(this.getAllocReceiver(),aliPayConfig);
}
}

View File

@@ -1,12 +1,14 @@
package org.dromara.daxpay.channel.alipay.strategy;
package org.dromara.daxpay.channel.alipay.strategy.merchant;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.daxpay.channel.alipay.entity.AliPayConfig;
import org.dromara.daxpay.channel.alipay.service.allocation.AliPayAllocationService;
import org.dromara.daxpay.channel.alipay.service.config.AlipayConfigService;
import org.dromara.daxpay.core.enums.ChannelEnum;
import org.dromara.daxpay.service.bo.allocation.AllocStartResultBo;
import org.dromara.daxpay.service.bo.allocation.AllocSyncResultBo;
import org.dromara.daxpay.service.strategy.AbsAllocationStrategy;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
@@ -17,10 +19,12 @@ import org.springframework.stereotype.Component;
@Slf4j
@Component
@RequiredArgsConstructor
public class AliAllocationStrategy extends AbsAllocationStrategy {
public class AlipayAllocationStrategy extends AbsAllocationStrategy {
private final AliPayAllocationService aliPayAllocationService;
private final AlipayConfigService aliPayConfigService;
/**
* 分账通道
*/
@@ -34,7 +38,8 @@ public class AliAllocationStrategy extends AbsAllocationStrategy {
*/
@Override
public AllocStartResultBo start() {
return aliPayAllocationService.start(getOrder(), getDetails());
AliPayConfig aliPayConfig = aliPayConfigService.getAliPayConfig(false);
return aliPayAllocationService.start(getOrder(), getDetails(), aliPayConfig);
}
/**
@@ -42,7 +47,8 @@ public class AliAllocationStrategy extends AbsAllocationStrategy {
*/
@Override
public void finish() {
aliPayAllocationService.finish(getOrder(), getDetails());
AliPayConfig aliPayConfig = aliPayConfigService.getAliPayConfig(false);
aliPayAllocationService.finish(getOrder(), getDetails(), aliPayConfig);
}
/**
@@ -50,6 +56,7 @@ public class AliAllocationStrategy extends AbsAllocationStrategy {
*/
@Override
public AllocSyncResultBo doSync() {
return aliPayAllocationService.sync(getOrder(), getDetails());
AliPayConfig aliPayConfig = aliPayConfigService.getAliPayConfig(false);
return aliPayAllocationService.sync(getOrder(), getDetails(), aliPayConfig);
}
}

View File

@@ -1,6 +1,8 @@
package org.dromara.daxpay.channel.alipay.strategy;
package org.dromara.daxpay.channel.alipay.strategy.merchant;
import org.dromara.daxpay.channel.alipay.service.extra.AliPayAuthService;
import org.dromara.daxpay.channel.alipay.entity.AliPayConfig;
import org.dromara.daxpay.channel.alipay.service.config.AlipayConfigService;
import org.dromara.daxpay.channel.alipay.service.extra.AlipayAuthService;
import org.dromara.daxpay.core.enums.ChannelEnum;
import org.dromara.daxpay.core.param.assist.AuthCodeParam;
import org.dromara.daxpay.core.param.assist.GenerateAuthUrlParam;
@@ -19,8 +21,10 @@ import org.springframework.stereotype.Component;
@Slf4j
@Component
@RequiredArgsConstructor
public class AliPayAuthStrategy extends AbsChannelAuthStrategy {
private final AliPayAuthService aliPayAuthService;
public class AlipayAuthStrategy extends AbsChannelAuthStrategy {
private final AlipayAuthService aliPayAuthService;
private final AlipayConfigService aliPayConfigService;
/**
* 策略标识, 可以自行进行扩展
@@ -37,7 +41,8 @@ public class AliPayAuthStrategy extends AbsChannelAuthStrategy {
*/
@Override
public AuthUrlResult generateAuthUrl(GenerateAuthUrlParam param) {
return aliPayAuthService.generateAuthUrl(param);
AliPayConfig aliPayConfig = aliPayConfigService.getAliPayConfig(false);
return aliPayAuthService.generateAuthUrl(param, aliPayConfig);
}
/**
@@ -45,7 +50,8 @@ public class AliPayAuthStrategy extends AbsChannelAuthStrategy {
*/
@Override
public AuthResult doAuth(AuthCodeParam param) {
return aliPayAuthService.getOpenIdOrUserId(param.getAuthCode());
AliPayConfig aliPayConfig = aliPayConfigService.getAliPayConfig(false);
return aliPayAuthService.getOpenIdOrUserId(param.getAuthCode(), aliPayConfig);
}
}

View File

@@ -1,8 +1,8 @@
package org.dromara.daxpay.channel.alipay.strategy;
package org.dromara.daxpay.channel.alipay.strategy.merchant;
import org.dromara.daxpay.channel.alipay.entity.config.AliPayConfig;
import org.dromara.daxpay.channel.alipay.entity.AliPayConfig;
import org.dromara.daxpay.channel.alipay.service.close.AliPayCloseService;
import org.dromara.daxpay.channel.alipay.service.config.AliPayConfigService;
import org.dromara.daxpay.channel.alipay.service.config.AlipayConfigService;
import org.dromara.daxpay.core.enums.ChannelEnum;
import org.dromara.daxpay.core.enums.CloseTypeEnum;
import org.dromara.daxpay.service.strategy.AbsPayCloseStrategy;
@@ -18,8 +18,8 @@ import org.springframework.stereotype.Service;
@Slf4j
@Service
@RequiredArgsConstructor
public class AliPayCloseStrategy extends AbsPayCloseStrategy {
private final AliPayConfigService alipayConfigService;
public class AlipayCloseStrategy extends AbsPayCloseStrategy {
private final AlipayConfigService alipayConfigService;
private final AliPayCloseService aliPayCloseService;
@@ -35,7 +35,7 @@ public class AliPayCloseStrategy extends AbsPayCloseStrategy {
*/
@Override
public void doBeforeCloseHandler() {
this.alipayConfig = alipayConfigService.getAndCheckConfig();
this.alipayConfig = alipayConfigService.getAndCheckConfig(false);
}
/**

View File

@@ -1,6 +1,8 @@
package org.dromara.daxpay.channel.alipay.strategy;
package org.dromara.daxpay.channel.alipay.strategy.merchant;
import org.dromara.daxpay.channel.alipay.service.reconcile.AliPayReconcileService;
import org.dromara.daxpay.channel.alipay.entity.AliPayConfig;
import org.dromara.daxpay.channel.alipay.service.config.AlipayConfigService;
import org.dromara.daxpay.channel.alipay.service.reconcile.AlipayReconcileService;
import org.dromara.daxpay.core.enums.ChannelEnum;
import org.dromara.daxpay.service.bo.reconcile.ReconcileResolveResultBo;
import org.dromara.daxpay.service.enums.ReconcileFileTypeEnum;
@@ -25,9 +27,10 @@ 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;
private final AlipayReconcileService reconcileService;
private final AlipayConfigService aliPayConfigService;
/**
@@ -55,7 +58,8 @@ public class AliPayReconcileStrategy extends AbsReconcileStrategy {
*/
@Override
public ReconcileResolveResultBo downAndResolve() {
AliPayConfig aliPayConfig = aliPayConfigService.getAliPayConfig(false);
String date = LocalDateTimeUtil.format(this.getStatement().getDate(), DatePattern.NORM_DATE_PATTERN);
return reconcileService.downAndResolve(date, this.getStatement());
return reconcileService.downAndResolve(date, this.getStatement(),aliPayConfig);
}
}

View File

@@ -1,6 +1,8 @@
package org.dromara.daxpay.channel.alipay.strategy;
package org.dromara.daxpay.channel.alipay.strategy.merchant;
import org.dromara.daxpay.channel.alipay.service.refund.AliPayRefundService;
import org.dromara.daxpay.channel.alipay.entity.AliPayConfig;
import org.dromara.daxpay.channel.alipay.service.config.AlipayConfigService;
import org.dromara.daxpay.channel.alipay.service.refund.AlipayRefundService;
import org.dromara.daxpay.core.enums.ChannelEnum;
import org.dromara.daxpay.service.bo.trade.RefundResultBo;
import org.dromara.daxpay.service.strategy.AbsRefundStrategy;
@@ -18,9 +20,10 @@ import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROT
@Scope(SCOPE_PROTOTYPE)
@Component
@RequiredArgsConstructor
public class AliPayRefundStrategy extends AbsRefundStrategy {
public class AlipayRefundStrategy extends AbsRefundStrategy {
private final AliPayRefundService aliRefundService;
private final AlipayRefundService aliRefundService;
private final AlipayConfigService aliPayConfigService;
/**
* 策略标识
@@ -37,6 +40,7 @@ public class AliPayRefundStrategy extends AbsRefundStrategy {
*/
@Override
public RefundResultBo doRefundHandler() {
return aliRefundService.refund(this.getRefundOrder());
AliPayConfig aliPayConfig = aliPayConfigService.getAliPayConfig(false);
return aliRefundService.refund(this.getRefundOrder(), aliPayConfig);
}
}

View File

@@ -1,10 +1,12 @@
package org.dromara.daxpay.channel.alipay.strategy;
package org.dromara.daxpay.channel.alipay.strategy.merchant;
import lombok.RequiredArgsConstructor;
import org.dromara.daxpay.channel.alipay.service.sync.AliPaySyncService;
import org.dromara.daxpay.channel.alipay.entity.AliPayConfig;
import org.dromara.daxpay.channel.alipay.service.config.AlipayConfigService;
import org.dromara.daxpay.channel.alipay.service.sync.AlipaySyncService;
import org.dromara.daxpay.core.enums.ChannelEnum;
import org.dromara.daxpay.service.bo.sync.PaySyncResultBo;
import org.dromara.daxpay.service.strategy.AbsSyncPayOrderStrategy;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@@ -18,9 +20,10 @@ import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROT
@Scope(SCOPE_PROTOTYPE)
@Component
@RequiredArgsConstructor
public class AliPaySyncOrderStrategy extends AbsSyncPayOrderStrategy {
public class AlipaySyncOrderStrategy extends AbsSyncPayOrderStrategy {
private final AliPaySyncService alipaySyncService;
private final AlipaySyncService alipaySyncService;
private final AlipayConfigService aliPayConfigService;
/**
* 策略标识
@@ -35,6 +38,7 @@ public class AliPaySyncOrderStrategy extends AbsSyncPayOrderStrategy {
*/
@Override
public PaySyncResultBo doSync() {
return alipaySyncService.syncPayStatus(this.getOrder());
AliPayConfig aliPayConfig = aliPayConfigService.getAliPayConfig(false);
return alipaySyncService.syncPayStatus(this.getOrder(),aliPayConfig);
}
}

View File

@@ -1,12 +1,14 @@
package org.dromara.daxpay.channel.alipay.strategy;
package org.dromara.daxpay.channel.alipay.strategy.merchant;
import lombok.RequiredArgsConstructor;
import org.dromara.daxpay.channel.alipay.service.sync.AliPayRefundSyncService;
import org.dromara.daxpay.channel.alipay.entity.AliPayConfig;
import org.dromara.daxpay.channel.alipay.service.config.AlipayConfigService;
import org.dromara.daxpay.channel.alipay.service.sync.AlipayRefundSyncService;
import org.dromara.daxpay.core.enums.ChannelEnum;
import org.dromara.daxpay.core.exception.OperationFailException;
import org.dromara.daxpay.service.bo.sync.RefundSyncResultBo;
import org.dromara.daxpay.service.entity.order.refund.RefundOrder;
import org.dromara.daxpay.service.strategy.AbsSyncRefundOrderStrategy;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@@ -22,9 +24,11 @@ import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROT
@Scope(SCOPE_PROTOTYPE)
@Component
@RequiredArgsConstructor
public class AliPaySyncRefundStrategy extends AbsSyncRefundOrderStrategy {
public class AlipaySyncRefundStrategy extends AbsSyncRefundOrderStrategy {
private final AliPayRefundSyncService alipaySyncService;
private final AlipayRefundSyncService alipaySyncService;
private final AlipayConfigService aliPayConfigService;
/**
* 策略标识, 可以自行进行扩展
@@ -54,7 +58,8 @@ public class AliPaySyncRefundStrategy extends AbsSyncRefundOrderStrategy {
*/
@Override
public RefundSyncResultBo doSync() {
return alipaySyncService.syncRefundStatus(getRefundOrder());
AliPayConfig aliPayConfig = aliPayConfigService.getAliPayConfig(false);
return alipaySyncService.syncRefundStatus(this.getRefundOrder(), aliPayConfig);
}
}

View File

@@ -1,13 +1,15 @@
package org.dromara.daxpay.channel.alipay.strategy;
package org.dromara.daxpay.channel.alipay.strategy.merchant;
import cn.bootx.platform.core.exception.ValidationFailedException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.daxpay.channel.alipay.service.transfer.AliPayTransferService;
import org.dromara.daxpay.channel.alipay.entity.AliPayConfig;
import org.dromara.daxpay.channel.alipay.service.config.AlipayConfigService;
import org.dromara.daxpay.channel.alipay.service.transfer.AlipayTransferService;
import org.dromara.daxpay.core.enums.ChannelEnum;
import org.dromara.daxpay.core.param.trade.transfer.TransferParam;
import org.dromara.daxpay.service.bo.trade.TransferResultBo;
import org.dromara.daxpay.service.strategy.AbsTransferStrategy;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
@@ -25,14 +27,16 @@ import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROT
@Service
@Scope(SCOPE_PROTOTYPE)
@RequiredArgsConstructor
public class AliPayTransferStrategy extends AbsTransferStrategy {
public class AlipayTransferStrategy extends AbsTransferStrategy {
private final AliPayTransferService aliPayTransferService;
private final AlipayTransferService aliPayTransferService;
private final AlipayConfigService aliPayConfigService;
/**
* 策略标识
*/
@Override
@Override
public String getChannel() {
return ChannelEnum.ALIPAY.getCode();
}
@@ -51,6 +55,7 @@ public class AliPayTransferStrategy extends AbsTransferStrategy {
*/
@Override
public TransferResultBo doTransferHandler() {
return aliPayTransferService.transfer(this.getTransferOrder());
AliPayConfig aliPayConfig = aliPayConfigService.getAliPayConfig(false);
return aliPayTransferService.transfer(this.getTransferOrder(),aliPayConfig);
}
}

View File

@@ -53,7 +53,7 @@ public class WeChatPayAllocationV2Service {
private final WechatPayConfigService wechatPayConfigService;
/**
* 分账
* 发起分账 使用分账号作为请求号
*/
public AllocStartResultBo start(AllocOrder allocOrder, List<AllocDetail> details, WechatPayConfig config) {
WxPayService wxPayService = wechatPayConfigService.wxJavaSdk(config);
@@ -89,7 +89,7 @@ public class WeChatPayAllocationV2Service {
}
/**
* 完结
* 分账完结 使用ID作为请求号
*/
public void finish(AllocOrder allocOrder, WechatPayConfig config) {
WxPayService wxPayService = wechatPayConfigService.wxJavaSdk(config);

View File

@@ -16,8 +16,12 @@ public enum ChannelEnum {
/** 支付宝 - 直连商户 */
ALIPAY("ali_pay"),
/** 支付宝 - 服务商 */
ALIPAY_ISV("alipay_isv"),
/** 微信支付 */
WECHAT("wechat_pay"),
/** 微信支付服务商 */
WECHAT_ISV("wechat_pay_isv"),
/** 云闪付 */
UNION_PAY("union_pay"),