|
|
@@ -596,22 +596,36 @@ public class WxPayScoreStrategy implements PayScoreStrategy {
|
|
|
|
|
|
@Override
|
|
|
public PayScoreResult refundServiceOrder(PayScoreRefundRequest request) {
|
|
|
- log.info("[微信支付分] 申请退款 - 订单号: {}, 金额: {}元", request.getOutOrderNo(), request.getRefundAmount());
|
|
|
+ log.info("[微信支付分] 申请退款 - 订单号: {}, 金额: {}元, transactionId: {}",
|
|
|
+ request.getOutOrderNo(), request.getRefundAmount(), request.getTransactionId());
|
|
|
|
|
|
PayScoreResult checkResult = checkServiceAvailable();
|
|
|
if (checkResult != null) {
|
|
|
return checkResult;
|
|
|
}
|
|
|
|
|
|
+ if (request.getTransactionId() == null || request.getTransactionId().isEmpty()) {
|
|
|
+ log.error("[微信支付分] 退款失败: transaction_id 为空,可能回调尚未处理完成");
|
|
|
+ return PayScoreResult.fail("MISSING_TRANSACTION_ID", "缺少微信支付订单号,请等待支付回调完成后重试");
|
|
|
+ }
|
|
|
+
|
|
|
try {
|
|
|
+ // 支付分退款使用通用退款接口 /v3/refund/domestic/refunds
|
|
|
ObjectNode body = objectMapper.createObjectNode();
|
|
|
- body.put("appid", wxPayConfig.getAppId());
|
|
|
- body.put("service_id", wxPayConfig.getServiceId());
|
|
|
+ body.put("transaction_id", request.getTransactionId());
|
|
|
+ body.put("out_refund_no", request.getOutRefundNo() != null
|
|
|
+ ? request.getOutRefundNo() : "RF" + request.getOutOrderNo());
|
|
|
body.put("reason", request.getReason() != null ? request.getReason() : "用户申请退款");
|
|
|
- body.put("amount", yuanToFen(request.getRefundAmount()));
|
|
|
+
|
|
|
+ ObjectNode amount = objectMapper.createObjectNode();
|
|
|
+ amount.put("refund", yuanToFen(request.getRefundAmount()));
|
|
|
+ amount.put("total", request.getTotalAmount() != null
|
|
|
+ ? yuanToFen(request.getTotalAmount()) : yuanToFen(request.getRefundAmount()));
|
|
|
+ amount.put("currency", "CNY");
|
|
|
+ body.set("amount", amount);
|
|
|
|
|
|
String requestBody = objectMapper.writeValueAsString(body);
|
|
|
- String url = PAY_SCORE_BASE_URL + "/" + request.getOutOrderNo() + "/pay/refund";
|
|
|
+ String url = "https://api.mch.weixin.qq.com/v3/refund/domestic/refunds";
|
|
|
log.info("[微信支付分] 退款请求: url={}, body={}", url, requestBody);
|
|
|
|
|
|
HttpRequest httpRequest = new HttpRequest.Builder()
|
|
|
@@ -626,11 +640,12 @@ public class WxPayScoreStrategy implements PayScoreStrategy {
|
|
|
Map<String, Object> responseMap = response.getServiceResponse();
|
|
|
JsonNode respJson = objectMapper.valueToTree(responseMap);
|
|
|
|
|
|
- String outOrderNo = getJsonString(respJson, "out_order_no");
|
|
|
String refundId = getJsonString(respJson, "refund_id");
|
|
|
+ String status = getJsonString(respJson, "status");
|
|
|
|
|
|
- PayScoreResult result = PayScoreResult.success(outOrderNo, null);
|
|
|
+ PayScoreResult result = PayScoreResult.success(request.getOutOrderNo(), status);
|
|
|
result.setPackageStr(refundId);
|
|
|
+ log.info("[微信支付分] 退款申请成功 - refundId: {}, status: {}", refundId, status);
|
|
|
return result;
|
|
|
|
|
|
} catch (HttpException e) {
|
|
|
@@ -766,6 +781,18 @@ public class WxPayScoreStrategy implements PayScoreStrategy {
|
|
|
result.setTotalAmount(fenToYuan(totalAmountFen));
|
|
|
}
|
|
|
|
|
|
+ // 提取微信支付订单号(用于退款)
|
|
|
+ if (dataJson.has("collection")) {
|
|
|
+ JsonNode collection = dataJson.get("collection");
|
|
|
+ if (collection.has("details") && collection.get("details").isArray()) {
|
|
|
+ JsonNode details = collection.get("details");
|
|
|
+ if (details.size() > 0) {
|
|
|
+ String transactionId = getJsonString(details.get(0), "transaction_id");
|
|
|
+ result.setTransactionId(transactionId);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// 解析支付时间
|
|
|
if (dataJson.has("pay_succ_time") && !dataJson.get("pay_succ_time").isNull()) {
|
|
|
String paySuccTime = dataJson.get("pay_succ_time").asText();
|