支付调整

This commit is contained in:
2026-01-14 17:04:48 +08:00
parent e8be5dee9d
commit 4eaedcce41
70 changed files with 1065 additions and 829 deletions

View File

@@ -0,0 +1,50 @@
package com.czg;
import com.czg.pay.CzgPayBaseReq;
import com.czg.pay.CzgRefundReq;
import com.czg.entity.resp.CzgBaseResp;
import com.czg.entity.resp.CzgRefundResp;
import com.czg.enums.CzgPayEnum;
import com.czg.pay.NativeMerchantDTO;
import com.czg.pay.PolyMerchantDTO;
import com.czg.resp.CzgResult;
import jakarta.validation.constraints.NotBlank;
import lombok.NonNull;
import java.util.Map;
/**
* 支付适配器接口
*
* @author ww
*
*/
public interface PayAdapter {
/**
* 支付渠道
* {@link com.czg.constant.PayChannelCst}
*/
String getChannel();
/**
* 统一支付接口
*
* @param payType 支付类型
* @param payData 支付数据 Json类型
* 对应 聚合支付参数 {@link PolyMerchantDTO}
* 对应 原生支付参数 {@link NativeMerchantDTO}
* @param domain 域名 请求地址
* @param notifyUrl 通知地址
* @param bizData 业务数据
*/
CzgResult<Map<String, Object>> pay(@NonNull CzgPayEnum payType, @NotBlank String payData, @NotBlank String domain,
@NotBlank String notifyUrl, CzgPayBaseReq<?> bizData);
CzgResult<CzgRefundResp> refund(@NotBlank String domain, @NotBlank String payData, String notifyUrl, CzgRefundReq bizData);
CzgResult<CzgBaseResp> queryPayOrder(@NotBlank String domain, @NotBlank String payData, String payOrderId, String mchOrderNo);
CzgResult<CzgRefundResp> queryRefund(@NotBlank String domain, @NotBlank String payData, String mchRefundNo, String refundOrderId);
}

View File

@@ -0,0 +1,39 @@
package com.czg;
import com.czg.constant.PayChannelCst;
import com.czg.impl.NativePayAdapter;
import com.czg.impl.PolyPayAdapter;
import java.util.HashMap;
import java.util.Map;
/**
* 支付适配器工厂
*
* @author ww
*/
public class PayAdapterFactory {
private static final Map<String, PayAdapter> ADAPTER_MAP = new HashMap<>();
static {
ADAPTER_MAP.put(PayChannelCst.POLY, new PolyPayAdapter());
ADAPTER_MAP.put(PayChannelCst.NATIVE, new NativePayAdapter());
}
/**
* 获取支付适配器
*
* @param channel 支付渠道,仅支持 {@link PayChannelCst}
*/
public static PayAdapter getAdapter(String channel) {
PayAdapter adapter = ADAPTER_MAP.get(channel);
if (adapter == null) {
throw new IllegalStateException("支付渠道未注册适配器: " + channel);
}
return adapter;
}
}

View File

@@ -0,0 +1,73 @@
package com.czg.impl;
import com.alibaba.fastjson2.JSONObject;
import com.czg.PayAdapter;
import com.czg.constant.PayChannelCst;
import com.czg.entity.resp.CzgBaseResp;
import com.czg.entity.resp.CzgRefundResp;
import com.czg.enums.CzgPayEnum;
import com.czg.exception.CzgException;
import com.czg.pay.CzgPayBaseReq;
import com.czg.pay.CzgRefundReq;
import com.czg.pay.NativeMerchantDTO;
import com.czg.resp.CzgResult;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
/**
* 原生支付适配器
*
* @author ww
* @date 2023/10/20 14:20
*/
@Slf4j
public class NativePayAdapter implements PayAdapter {
@Override
public String getChannel() {
return PayChannelCst.NATIVE;
}
@Override
public CzgResult<Map<String, Object>> pay(@NonNull CzgPayEnum payType, String payData, String domain, String notifyUrl, CzgPayBaseReq<?> bizData) {
try {
NativeMerchantDTO polyMerchantDTO = JSONObject.parseObject(payData, NativeMerchantDTO.class);
switch (payType) {
// case H5_PAY:
// return h5Pay(polyMerchantDTO, domain, notifyUrl, bizData);
// case JS_PAY:
// return jsPay(polyMerchantDTO, domain, notifyUrl, bizData);
// case LT_PAY:
// return ltPay(polyMerchantDTO, domain, notifyUrl, bizData);
// case SCAN_PAY:
// return scanPay(polyMerchantDTO, domain, notifyUrl, bizData);
// case MICRO_PAY:
// //扫码支付 扫描码
// return microPay(polyMerchantDTO, domain, notifyUrl, (CzgPayBaseReq<String>) bizData);
default:
throw new CzgException("原生支付不支持该支付方式: " + bizData.getPayType());
}
} catch (Exception e) {
log.error("聚合支付处理失败: {}", e.getMessage(), e);
return CzgResult.failure("聚合支付处理失败: " + e.getMessage());
}
}
@Override
public CzgResult<CzgRefundResp> refund(String domain, String payData, String notifyUrl, CzgRefundReq bizData) {
return null;
}
@Override
public CzgResult<CzgBaseResp> queryPayOrder(String domain, String payData, String payOrderId, String mchOrderNo) {
return null;
}
@Override
public CzgResult<CzgRefundResp> queryRefund(String domain, String payData, String mchRefundNo, String refundOrderId) {
return null;
}
}

View File

@@ -0,0 +1,120 @@
package com.czg.impl;
import com.alibaba.fastjson2.JSONObject;
import com.czg.PayAdapter;
import com.czg.PolyPayUtils;
import com.czg.constant.PayChannelCst;
import com.czg.entity.resp.CzgBaseResp;
import com.czg.entity.resp.CzgRefundResp;
import com.czg.enums.CzgPayEnum;
import com.czg.exception.CzgException;
import com.czg.pay.CzgPayBaseReq;
import com.czg.pay.CzgRefundReq;
import com.czg.pay.PolyMerchantDTO;
import com.czg.resp.CzgResult;
import com.czg.utils.AssertUtil;
import jakarta.validation.constraints.NotBlank;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
/**
* @author ww
*/
@Slf4j
public class PolyPayAdapter implements PayAdapter {
@Override
public String getChannel() {
return PayChannelCst.POLY;
}
@Override
public CzgResult<Map<String, Object>> pay(@NonNull CzgPayEnum payType, @NotBlank String payData, @NotBlank String domain,
@NotBlank String notifyUrl, CzgPayBaseReq<?> bizData) {
try {
PolyMerchantDTO polyMerchantDTO = JSONObject.parseObject(payData, PolyMerchantDTO.class);
return switch (payType) {
case H5_PAY -> h5Pay(polyMerchantDTO, domain, notifyUrl, bizData);
case JS_PAY -> jsPay(polyMerchantDTO, domain, notifyUrl, bizData);
case LT_PAY -> ltPay(polyMerchantDTO, domain, notifyUrl, bizData);
case SCAN_PAY -> scanPay(polyMerchantDTO, domain, notifyUrl, bizData);
case MICRO_PAY -> microPay(polyMerchantDTO, domain, notifyUrl, (CzgPayBaseReq<String>) bizData);
default -> throw new CzgException("聚合支付不支持该支付方式: " + bizData.getPayType());
};
} catch (Exception e) {
log.error("聚合支付处理失败: {}", e.getMessage(), e);
return CzgResult.failure("聚合支付处理失败: " + e.getMessage());
}
}
@Override
public CzgResult<CzgRefundResp> refund(@NotBlank String domain, @NotBlank String payData, String notifyUrl, CzgRefundReq bizData) {
PolyMerchantDTO shopMerchant = JSONObject.parseObject(payData, PolyMerchantDTO.class);
bizData.setNotifyUrl(notifyUrl);
return PolyPayUtils.refundOrder(domain, shopMerchant.getAppId(), shopMerchant.getAppSecret(), bizData);
}
@Override
public CzgResult<CzgBaseResp> queryPayOrder(@NotBlank String payData, @NotBlank String domain, String payOrderId, String mchOrderNo) {
PolyMerchantDTO shopMerchant = JSONObject.parseObject(payData, PolyMerchantDTO.class);
PolyPayUtils.queryPayOrder(domain, shopMerchant.getAppId(), shopMerchant.getAppSecret(), payOrderId, mchOrderNo);
return null;
}
@Override
public CzgResult<CzgRefundResp> queryRefund(@NotBlank String payData, @NotBlank String domain, String mchRefundNo, String refundOrderId) {
PolyMerchantDTO shopMerchant = JSONObject.parseObject(payData, PolyMerchantDTO.class);
return PolyPayUtils.queryRefundOrder(domain, shopMerchant.getAppId(), shopMerchant.getAppSecret(), mchRefundNo, refundOrderId);
}
private CzgResult<Map<String, Object>> h5Pay(PolyMerchantDTO shopMerchant, String domain, String notifyUrl, CzgPayBaseReq<?> bizData) {
bizData.polyBase(shopMerchant.getStoreId(), notifyUrl);
return PolyPayUtils.h5Pay(domain, shopMerchant.getAppId(), shopMerchant.getAppSecret(), bizData);
}
private CzgResult<Map<String, Object>> jsPay(PolyMerchantDTO shopMerchant, String domain, String notifyUrl, CzgPayBaseReq<?> bizData) {
bizData.setSubAppid("aliPay".equals(bizData.getPayType()) ? shopMerchant.getAlipaySmallAppid() : shopMerchant.getWechatSmallAppid());
AssertUtil.isBlank(bizData.getSubAppid(), "暂不可用,请联系商家配置" + ("aliPay".equals(bizData.getPayType()) ? "支付宝" : "微信") + "小程序");
bizData.setPayType("aliPay".equals(bizData.getPayType()) ? "ALIPAY" : "WECHAT");
bizData.polyBase(shopMerchant.getStoreId(), notifyUrl);
return PolyPayUtils.jsPay(domain, shopMerchant.getAppId(), shopMerchant.getAppSecret(), bizData);
}
private CzgResult<Map<String, Object>> ltPay(PolyMerchantDTO shopMerchant, String domain, String notifyUrl, CzgPayBaseReq<?> bizData) {
bizData.setSubAppid("aliPay".equals(bizData.getPayType()) ? shopMerchant.getAlipaySmallAppid() : shopMerchant.getWechatSmallAppid());
AssertUtil.isBlank(bizData.getSubAppid(), "暂不可用,请联系商家配置" + ("aliPay".equals(bizData.getPayType()) ? "支付宝" : "微信") + "小程序");
bizData.polyBase(shopMerchant.getStoreId(), notifyUrl);
return PolyPayUtils.ltPay(domain, shopMerchant.getAppId(), shopMerchant.getAppSecret(), bizData);
}
private CzgResult<Map<String, Object>> scanPay(PolyMerchantDTO shopMerchant, String domain, String notifyUrl, CzgPayBaseReq<?> bizData) {
bizData.polyBase(shopMerchant.getStoreId(), notifyUrl);
return PolyPayUtils.scanPay(domain, shopMerchant.getAppId(), shopMerchant.getAppSecret(), bizData);
}
private CzgResult<Map<String, Object>> microPay(PolyMerchantDTO shopMerchant, String domain, String notifyUrl, CzgPayBaseReq<String> bizData) {
AssertUtil.isBlank(bizData.getData(), "扫码失败,请重试");
if (bizData.getData().length() > 26) {
throw new CzgException("支付失败,不支持的条码");
}
bizData.polyBase(shopMerchant.getStoreId(), notifyUrl);
String firstTwoDigitsStr = bizData.getData().substring(0, 2);
// 将截取的字符串转换为整数
int firstTwoDigits = Integer.parseInt(firstTwoDigitsStr);
// 判断范围
if (firstTwoDigits >= 10 && firstTwoDigits <= 15) {
//微信支付
bizData.setSubAppid(shopMerchant.getWechatSmallAppid());
} else if (firstTwoDigits >= 25 && firstTwoDigits <= 30) {
//支付宝支付
bizData.setSubAppid(shopMerchant.getAlipaySmallAppid());
} else {
throw new CzgException("扫描码非法或暂不支持");
}
return PolyPayUtils.microPay(domain, shopMerchant.getAppId(), shopMerchant.getAppSecret(), bizData);
}
}