fix(payment): 修复微信 Native支付参数错误问题

- 添加获取 Native 支付配置的方法- 在构建预支付请求时设置必填字段:appId、mchId 和 notifyUrl
- 实现微信支付状态查询功能
-优化日志输出,增加支付配置信息
This commit is contained in:
2025-08-30 17:17:58 +08:00
parent 495e6a72c6
commit 797cfdf6c2
3 changed files with 278 additions and 12 deletions

View File

@@ -46,6 +46,20 @@ public class WxPayConfigService {
@Value("${spring.profiles.active:dev}")
private String activeProfile;
/**
* 获取支付配置信息Payment对象- 公开方法
*
* @param tenantId 租户ID
* @return 支付配置信息
* @throws PaymentException 配置获取失败时抛出
*/
public Payment getPaymentConfigForStrategy(Integer tenantId) throws PaymentException {
if (tenantId == null) {
throw PaymentException.paramError("租户ID不能为空");
}
return getPaymentConfig(tenantId);
}
/**
* 获取微信支付配置
*
@@ -107,13 +121,13 @@ public class WxPayConfigService {
System.out.println("payment = " + payment);
if (payment != null) {
log.debug("从缓存获取支付配置成功租户ID: {}", tenantId);
return payment;
// return payment;
}
// 缓存中没有,尝试从数据库查询
try {
final PaymentParam paymentParam = new PaymentParam();
paymentParam.setType(1);
paymentParam.setType(102);
paymentParam.setTenantId(tenantId);
payment = paymentService.getByType(paymentParam);
System.out.println("payment1 = " + payment);
@@ -133,7 +147,8 @@ public class WxPayConfigService {
}
log.debug("开发环境模式将使用测试配置租户ID: {}", tenantId);
return null; // 开发环境返回null使用测试配置
// 开发环境返回测试Payment配置
return createDevTestPayment(tenantId);
}
/**
@@ -214,12 +229,33 @@ public class WxPayConfigService {
}
}
/**
* 创建开发环境测试Payment配置
*/
private Payment createDevTestPayment(Integer tenantId) {
Payment testPayment = new Payment();
testPayment.setTenantId(tenantId);
testPayment.setType(102); // Native支付
testPayment.setAppId("wxa67c676fc445590e"); // 开发环境测试AppID
testPayment.setMchId("1246610101"); // 开发环境测试商户号
testPayment.setMerchantSerialNumber("48749613B40AA8F1D768583FC352358E13EB5AF0");
testPayment.setApiKey(certificateProperties.getWechatPay().getDev().getApiV3Key());
testPayment.setNotifyUrl("http://frps-10550.s209.websoft.top/api/payment/notify");
testPayment.setName("微信Native支付-开发环境");
testPayment.setStatus(true); // 启用
log.info("创建开发环境测试Payment配置租户ID: {}, AppID: {}, 商户号: {}",
tenantId, testPayment.getAppId(), testPayment.getMchId());
return testPayment;
}
/**
* 创建开发环境测试配置
*/
private Config createDevTestConfig(String certificatePath) throws PaymentException {
String testMerchantId = "1246610101";
String testMerchantSerialNumber = "2903B872D5CA36E525FAEC37AEDB22E54ECDE7B7";
String testMerchantSerialNumber = "48749613B40AA8F1D768583FC352358E13EB5AF0";
String testApiV3Key = certificateProperties.getWechatPay().getDev().getApiV3Key();
if (testApiV3Key == null || testApiV3Key.trim().isEmpty()) {

View File

@@ -1,9 +1,11 @@
package com.gxwebsoft.payment.strategy;
import com.gxwebsoft.common.core.utils.CommonUtil;
import com.gxwebsoft.common.system.entity.Payment;
import com.gxwebsoft.payment.constants.PaymentConstants;
import com.gxwebsoft.payment.dto.PaymentRequest;
import com.gxwebsoft.payment.dto.PaymentResponse;
import com.gxwebsoft.payment.enums.PaymentStatus;
import com.gxwebsoft.payment.enums.PaymentType;
import com.gxwebsoft.payment.exception.PaymentException;
import com.gxwebsoft.payment.service.WxPayConfigService;
@@ -13,6 +15,8 @@ import com.wechat.pay.java.service.payments.nativepay.NativePayService;
import com.wechat.pay.java.service.payments.nativepay.model.Amount;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse;
import com.wechat.pay.java.service.payments.nativepay.model.QueryOrderByOutTradeNoRequest;
import com.wechat.pay.java.service.payments.model.Transaction;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
@@ -96,11 +100,14 @@ public class WechatNativeStrategy implements PaymentStrategy {
// 生成订单号
String orderNo = generateOrderNo(request);
// 获取Native支付的Payment配置包含appId等信息
Payment paymentConfig = wxPayConfigService.getPaymentConfigForStrategy(request.getTenantId());
// 获取微信支付配置
Config wxPayConfig = wxPayConfigService.getWxPayConfig(request.getTenantId());
// 构建预支付请求
PrepayRequest prepayRequest = buildPrepayRequest(request, orderNo);
PrepayRequest prepayRequest = buildPrepayRequest(request, orderNo, paymentConfig);
// 调用微信支付API
PrepayResponse prepayResponse = callWechatPayApi(prepayRequest, wxPayConfig);
@@ -131,8 +138,34 @@ public class WechatNativeStrategy implements PaymentStrategy {
@Override
public PaymentResponse queryPayment(String orderNo, Integer tenantId) throws PaymentException {
// TODO: 实现微信支付查询逻辑
throw PaymentException.unsupportedPayment("暂不支持微信支付查询", PaymentType.WECHAT_NATIVE);
log.info("开始查询微信Native支付状态, 订单号: {}, 租户ID: {}", orderNo, tenantId);
try {
// 参数验证
if (!StringUtils.hasText(orderNo)) {
throw PaymentException.paramError("订单号不能为空");
}
if (tenantId == null) {
throw PaymentException.paramError("租户ID不能为空");
}
// 获取支付配置(包含商户号等信息)
Payment paymentConfig = wxPayConfigService.getPaymentConfigForStrategy(tenantId);
// 获取微信支付配置
Config wxPayConfig = wxPayConfigService.getWxPayConfig(tenantId);
// 调用微信支付查询API
return queryWechatPaymentStatus(orderNo, tenantId, paymentConfig, wxPayConfig);
} catch (Exception e) {
if (e instanceof PaymentException) {
throw e;
}
log.error("查询微信Native支付状态失败, 订单号: {}, 租户ID: {}, 错误: {}",
orderNo, tenantId, e.getMessage(), e);
throw PaymentException.systemError("查询微信支付状态失败: " + e.getMessage(), e);
}
}
@Override
@@ -200,12 +233,18 @@ public class WechatNativeStrategy implements PaymentStrategy {
return CommonUtil.createOrderNo();
}
/**
* 构建微信预支付请求
*/
private PrepayRequest buildPrepayRequest(PaymentRequest request, String orderNo) {
private PrepayRequest buildPrepayRequest(PaymentRequest request, String orderNo, Payment paymentConfig) {
PrepayRequest prepayRequest = new PrepayRequest();
// 设置应用ID和商户号关键修复
prepayRequest.setAppid(paymentConfig.getAppId());
prepayRequest.setMchid(paymentConfig.getMchId());
// 设置金额
Amount amount = new Amount();
amount.setTotal(request.getAmountInCents());
@@ -216,17 +255,109 @@ public class WechatNativeStrategy implements PaymentStrategy {
prepayRequest.setOutTradeNo(orderNo);
prepayRequest.setDescription(request.getEffectiveDescription());
// 设置回调URL
// 设置回调URL(必填字段)
String notifyUrl = null;
if (StringUtils.hasText(request.getNotifyUrl())) {
prepayRequest.setNotifyUrl(request.getNotifyUrl());
// 优先使用请求中的回调URL
notifyUrl = request.getNotifyUrl();
} else if (StringUtils.hasText(paymentConfig.getNotifyUrl())) {
// 使用配置中的回调URL
notifyUrl = paymentConfig.getNotifyUrl();
} else {
// 如果都没有,抛出异常
throw new RuntimeException("回调通知地址不能为空请在支付请求中设置notifyUrl或在支付配置中设置notifyUrl");
}
prepayRequest.setNotifyUrl(notifyUrl);
log.debug("构建微信预支付请求完成, 订单号: {}, 金额: {}分",
orderNo, request.getAmountInCents());
log.debug("构建微信预支付请求完成, 订单号: {}, 金额: {}分, AppID: {}, 商户号: {}, 回调URL: {}",
orderNo, request.getAmountInCents(), paymentConfig.getAppId(), paymentConfig.getMchId(), notifyUrl);
return prepayRequest;
}
/**
* 查询微信支付状态
*/
private PaymentResponse queryWechatPaymentStatus(String orderNo, Integer tenantId, Payment paymentConfig, Config wxPayConfig) throws PaymentException {
try {
// 构建查询请求
QueryOrderByOutTradeNoRequest queryRequest = new QueryOrderByOutTradeNoRequest();
queryRequest.setOutTradeNo(orderNo);
queryRequest.setMchid(paymentConfig.getMchId());
// 构建服务
NativePayService service = new NativePayService.Builder().config(wxPayConfig).build();
// 调用查询接口
Transaction transaction = service.queryOrderByOutTradeNo(queryRequest);
if (transaction == null) {
throw PaymentException.systemError("微信支付查询返回空结果", null);
}
// 转换支付状态
PaymentStatus paymentStatus = convertWechatPaymentStatus(transaction.getTradeState());
// 构建响应
PaymentResponse response = new PaymentResponse();
response.setSuccess(true);
response.setOrderNo(orderNo);
response.setPaymentStatus(paymentStatus);
response.setTenantId(tenantId);
response.setPaymentType(PaymentType.WECHAT_NATIVE);
if (transaction.getAmount() != null) {
// 微信返回的金额是分,需要转换为元
BigDecimal amount = new BigDecimal(transaction.getAmount().getTotal()).divide(new BigDecimal("100"));
response.setAmount(amount);
}
if (transaction.getTransactionId() != null) {
response.setTransactionId(transaction.getTransactionId());
}
log.info("微信Native支付状态查询成功, 订单号: {}, 状态: {}, 微信交易号: {}",
orderNo, paymentStatus, transaction.getTransactionId());
return response;
} catch (Exception e) {
if (e instanceof PaymentException) {
throw e;
}
log.error("查询微信支付状态失败, 订单号: {}, 错误: {}", orderNo, e.getMessage(), e);
throw PaymentException.networkError("查询微信支付状态失败: " + e.getMessage(), PaymentType.WECHAT_NATIVE, e);
}
}
/**
* 转换微信支付状态
*/
private PaymentStatus convertWechatPaymentStatus(Transaction.TradeStateEnum tradeState) {
if (tradeState == null) {
return PaymentStatus.PENDING;
}
switch (tradeState) {
case SUCCESS:
return PaymentStatus.SUCCESS;
case REFUND:
return PaymentStatus.REFUNDED;
case NOTPAY:
return PaymentStatus.PENDING;
case CLOSED:
return PaymentStatus.CANCELLED;
case REVOKED:
return PaymentStatus.CANCELLED;
case USERPAYING:
return PaymentStatus.PROCESSING;
case PAYERROR:
return PaymentStatus.FAILED;
default:
return PaymentStatus.PENDING;
}
}
/**
* 调用微信支付API
*/