mirror of
http://git.pig4cloud.com/pig/pigx.git
synced 2026-11-08 04:39:00 +08:00
feat(pigx-pay-platform): 支持微信支付 APIV3 回调与下单,
This commit is contained in:
1 parent
a1edbfcc6e
commit
26efa7acbf
11 files changed
+300
-59
No files matched your search
+30
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2026, lengleng All rights reserved.
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
@@ -19,6 +19,7 @@ package com.pig4cloud.pigx.pay.controller;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
@@ -32,9 +33,14 @@ import com.pig4cloud.pigx.common.log.annotation.SysLog;
|
||||
import com.pig4cloud.pigx.common.security.annotation.HasPermission;
|
||||
import com.pig4cloud.pigx.common.security.annotation.Inner;
|
||||
import com.pig4cloud.pigx.common.xss.core.XssCleanIgnore;
|
||||
import com.pig4cloud.pigx.pay.entity.PayChannel;
|
||||
import com.pig4cloud.pigx.pay.entity.PayNotifyRecord;
|
||||
import com.pig4cloud.pigx.pay.handler.PayNotifyCallbakHandler;
|
||||
import com.pig4cloud.pigx.pay.service.PayChannelService;
|
||||
import com.pig4cloud.pigx.pay.service.PayNotifyRecordService;
|
||||
import com.pig4cloud.pigx.pay.utils.PayChannelNameEnum;
|
||||
import com.pig4cloud.pigx.pay.utils.WeChatPayV3Config;
|
||||
import com.pig4cloud.pigx.pay.utils.WeChatPayV3NotifyParser;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
@@ -44,7 +50,9 @@ import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.web.server.header.ContentTypeOptionsServerHttpHeadersWriter;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@@ -67,6 +75,8 @@ public class PayNotifyRecordController {
|
||||
|
||||
private final PayNotifyRecordService payNotifyRecordService;
|
||||
|
||||
private final PayChannelService payChannelService;
|
||||
|
||||
private final PayNotifyCallbakHandler alipayCallback;
|
||||
|
||||
private final PayNotifyCallbakHandler weChatCallback;
|
||||
@@ -179,11 +189,25 @@ public class PayNotifyRecordController {
|
||||
@XssCleanIgnore
|
||||
@PostMapping("/wx/callbak")
|
||||
@Operation(summary = "微信渠道支付回调", description = "微信渠道支付回调")
|
||||
public String wxCallbak(HttpServletRequest request) {
|
||||
String xmlMsg = HttpKit.readData(request);
|
||||
log.info("微信订单回调信息:{}", xmlMsg);
|
||||
Map<String, String> params = WxPayKit.xmlToMap(xmlMsg);
|
||||
return weChatCallback.handle(params);
|
||||
public ResponseEntity<String> wxCallbak(HttpServletRequest request) {
|
||||
String body = HttpKit.readData(request);
|
||||
log.info("微信 APIV3 订单回调信息:{}", body);
|
||||
try {
|
||||
PayChannel channel = payChannelService.getOne(Wrappers.<PayChannel>lambdaQuery()
|
||||
.eq(PayChannel::getChannelId, PayChannelNameEnum.WEIXIN_MP.name()), false);
|
||||
WeChatPayV3Config config = WeChatPayV3Config.from(channel);
|
||||
String decryptData = WxPayKit.verifyNotify(request.getHeader("Wechatpay-Serial"), body,
|
||||
request.getHeader("Wechatpay-Nonce"), request.getHeader("Wechatpay-Timestamp"),
|
||||
request.getHeader("Wechatpay-Signature"), config.getApiV3Key(), config.platformCertInputStream());
|
||||
Map<String, String> params = WeChatPayV3NotifyParser.parse(decryptData);
|
||||
weChatCallback.handle(params);
|
||||
return ResponseEntity.noContent().build();
|
||||
} catch (Exception ex) {
|
||||
log.warn("微信 APIV3 订单回调处理失败", ex);
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.body(JSONUtil.createObj().set("code", "FAIL").set("message", ex.getMessage()).toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+10
-7
@@ -60,13 +60,16 @@ public abstract class AbstractPayOrderHandler implements PayOrderHandler {
|
||||
PayChannel payChannel = preparePayParams();
|
||||
ChannelPayApiConfigKit.put(payChannel);
|
||||
|
||||
createGoodsOrder(payGoodsOrder);
|
||||
PayTradeOrder tradeOrder = createTradeOrder(payGoodsOrder);
|
||||
Object result = pay(payGoodsOrder, tradeOrder);
|
||||
updateOrder(payGoodsOrder, tradeOrder);
|
||||
// 情况ttl
|
||||
ChannelPayApiConfigKit.remove();
|
||||
return result;
|
||||
try {
|
||||
createGoodsOrder(payGoodsOrder);
|
||||
PayTradeOrder tradeOrder = createTradeOrder(payGoodsOrder);
|
||||
Object result = pay(payGoodsOrder, tradeOrder);
|
||||
updateOrder(payGoodsOrder, tradeOrder);
|
||||
return result;
|
||||
} finally {
|
||||
// 清理 ThreadLocal
|
||||
ChannelPayApiConfigKit.remove();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+41
-40
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2026, lengleng All rights reserved.
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
@@ -21,13 +21,15 @@ import cn.hutool.extra.servlet.JakartaServletUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.ijpay.core.enums.SignType;
|
||||
import com.ijpay.core.enums.TradeType;
|
||||
import com.ijpay.core.IJPayHttpResponse;
|
||||
import com.ijpay.core.enums.RequestMethodEnum;
|
||||
import com.ijpay.core.kit.WxPayKit;
|
||||
import com.ijpay.wxpay.WxPayApi;
|
||||
import com.ijpay.wxpay.WxPayApiConfig;
|
||||
import com.ijpay.wxpay.WxPayApiConfigKit;
|
||||
import com.ijpay.wxpay.model.UnifiedOrderModel;
|
||||
import com.ijpay.wxpay.enums.WxDomainEnum;
|
||||
import com.ijpay.wxpay.enums.v3.BasePayApiEnum;
|
||||
import com.ijpay.wxpay.model.v3.Amount;
|
||||
import com.ijpay.wxpay.model.v3.Payer;
|
||||
import com.ijpay.wxpay.model.v3.UnifiedOrderModel;
|
||||
import com.pig4cloud.pigx.common.core.util.WebUtils;
|
||||
import com.pig4cloud.pigx.common.data.tenant.TenantContextHolder;
|
||||
import com.pig4cloud.pigx.pay.entity.PayChannel;
|
||||
@@ -39,13 +41,12 @@ import com.pig4cloud.pigx.pay.mapper.PayTradeOrderMapper;
|
||||
import com.pig4cloud.pigx.pay.utils.ChannelPayApiConfigKit;
|
||||
import com.pig4cloud.pigx.pay.utils.OrderStatusEnum;
|
||||
import com.pig4cloud.pigx.pay.utils.PayChannelNameEnum;
|
||||
import com.pig4cloud.pigx.pay.utils.WeChatPayV3Config;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @date 2019-05-31
|
||||
@@ -78,14 +79,8 @@ public class WeChatMpPayOrderHandler extends AbstractPayOrderHandler {
|
||||
throw new IllegalArgumentException("微信公众号支付渠道配置为空");
|
||||
}
|
||||
|
||||
JSONObject params = JSONUtil.parseObj(channel.getParam());
|
||||
WxPayApiConfig wx = WxPayApiConfig.builder()
|
||||
.appId(channel.getAppId())
|
||||
.mchId(channel.getChannelMchId())
|
||||
.partnerKey(params.getStr("partnerKey"))
|
||||
.build();
|
||||
|
||||
WxPayApiConfigKit.setThreadLocalWxPayApiConfig(wx);
|
||||
// 提前验证 APIV3 配置完整性,避免在写入订单后才抛出配置异常
|
||||
WeChatPayV3Config.from(channel);
|
||||
return channel;
|
||||
}
|
||||
|
||||
@@ -100,7 +95,7 @@ public class WeChatMpPayOrderHandler extends AbstractPayOrderHandler {
|
||||
tradeOrder.setOrderId(goodsOrder.getPayOrderId());
|
||||
tradeOrder.setAmount(goodsOrder.getAmount());
|
||||
tradeOrder.setChannelId(PayChannelNameEnum.WEIXIN_MP.getName());
|
||||
tradeOrder.setChannelMchId(WxPayApiConfigKit.getWxPayApiConfig().getMchId());
|
||||
tradeOrder.setChannelMchId(ChannelPayApiConfigKit.get().getChannelMchId());
|
||||
tradeOrder.setClientIp(JakartaServletUtil.getClientIP(request));
|
||||
tradeOrder.setCurrency("CNY");
|
||||
tradeOrder.setStatus(OrderStatusEnum.INIT.getStatus());
|
||||
@@ -116,32 +111,38 @@ public class WeChatMpPayOrderHandler extends AbstractPayOrderHandler {
|
||||
*/
|
||||
@Override
|
||||
public Object pay(PayGoodsOrder goodsOrder, PayTradeOrder tradeOrder) {
|
||||
String ip = JakartaServletUtil.getClientIP(request);
|
||||
WxPayApiConfig wxPayApiConfig = WxPayApiConfigKit.getWxPayApiConfig();
|
||||
|
||||
// 判断是否是单体架构
|
||||
Map<String, String> params = UnifiedOrderModel.builder()
|
||||
.appid(wxPayApiConfig.getAppId())
|
||||
.mch_id(wxPayApiConfig.getMchId())
|
||||
.nonce_str(WxPayKit.generateStr())
|
||||
.body(goodsOrder.getGoodsName())
|
||||
WeChatPayV3Config config = WeChatPayV3Config.from(ChannelPayApiConfigKit.get());
|
||||
String notifyUrl = String.format("%s/api/%s/notify/wx/callbak", ChannelPayApiConfigKit.get().getNotifyUrl(),
|
||||
WebUtils.isMicro() ? "pay" : "admin");
|
||||
UnifiedOrderModel orderModel = UnifiedOrderModel.builder()
|
||||
.appid(config.getAppId())
|
||||
.mchid(config.getMchId())
|
||||
.description(goodsOrder.getGoodsName())
|
||||
.attach(TenantContextHolder.getTenantId().toString())
|
||||
.out_trade_no(String.valueOf(tradeOrder.getOrderId()))
|
||||
.total_fee(goodsOrder.getAmount())
|
||||
.spbill_create_ip(ip)
|
||||
.notify_url(String.format("%s/api/%s/notify/wx/callbak", ChannelPayApiConfigKit.get().getNotifyUrl(),
|
||||
WebUtils.isMicro() ? "pay" : "admin"))
|
||||
.trade_type(TradeType.JSAPI.getTradeType())
|
||||
.openid(goodsOrder.getUserId())
|
||||
.build()
|
||||
.createSign(wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);
|
||||
.notify_url(notifyUrl)
|
||||
.amount(Amount.builder().total(Integer.parseInt(goodsOrder.getAmount())).currency("CNY").build())
|
||||
.payer(Payer.builder().openid(goodsOrder.getUserId()).build())
|
||||
.build();
|
||||
|
||||
String xmlResult = WxPayApi.pushOrder(false, params);
|
||||
log.info("微信统一下单返回 {}", xmlResult);
|
||||
Map<String, String> resultMap = WxPayKit.xmlToMap(xmlResult);
|
||||
String prepayId = resultMap.get("prepay_id");
|
||||
return WxPayKit.prepayIdCreateSign(prepayId, wxPayApiConfig.getAppId(), wxPayApiConfig.getPartnerKey(),
|
||||
SignType.HMACSHA256);
|
||||
try {
|
||||
IJPayHttpResponse response = WxPayApi.v3(RequestMethodEnum.POST, WxDomainEnum.CHINA.getDomain(),
|
||||
BasePayApiEnum.JS_API_PAY.getUrl(), config.getMchId(), config.getMerchantSerialNo(), null,
|
||||
config.getPrivateKey(), JSONUtil.toJsonStr(orderModel));
|
||||
log.info("微信 APIV3 JSAPI 下单返回: status={}, body={}", response.getStatus(), response.getBody());
|
||||
if (response.getStatus() < 200 || response.getStatus() >= 300) {
|
||||
throw new IllegalStateException("微信支付 APIV3 下单失败: " + response.getBody());
|
||||
}
|
||||
|
||||
JSONObject result = JSONUtil.parseObj(response.getBody());
|
||||
String prepayId = result.getStr("prepay_id");
|
||||
if (prepayId == null) {
|
||||
throw new IllegalStateException("微信支付 APIV3 下单未返回 prepay_id");
|
||||
}
|
||||
return WxPayKit.jsApiCreateSign(config.getAppId(), prepayId, config.getPrivateKey());
|
||||
} catch (Exception ex) {
|
||||
throw new IllegalStateException("微信支付 APIV3 下单失败", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -100,7 +100,7 @@ public class YungouosMergePayOrderHandler extends AbstractPayOrderHandler {
|
||||
return MergePay.nativePay(String.valueOf(tradeOrder.getOrderId()), money, channel.getChannelMchId(),
|
||||
tradeOrder.getBody(), "1", TenantContextHolder.getTenantId().toString(),
|
||||
String.format("%s/api/%s/notify/merge/callbak", ChannelPayApiConfigKit.get().getNotifyUrl(), WebUtils.isMicro() ? "pay" : "admin"),
|
||||
ChannelPayApiConfigKit.get().getReturnUrl(), "", "", "0", "pay", null, key);
|
||||
ChannelPayApiConfigKit.get().getReturnUrl(), "", "", "0", null, null, key);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.pay.utils;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.ijpay.core.enums.AuthTypeEnum;
|
||||
import com.ijpay.core.kit.PayKit;
|
||||
import com.pig4cloud.pigx.pay.entity.PayChannel;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.PrivateKey;
|
||||
|
||||
/**
|
||||
* 微信支付 APIV3 渠道配置
|
||||
*
|
||||
* @author lengleng
|
||||
* @date 2026-05-10
|
||||
*/
|
||||
@Getter
|
||||
public class WeChatPayV3Config {
|
||||
|
||||
/**
|
||||
* 公众号 AppID。
|
||||
*/
|
||||
private final String appId;
|
||||
|
||||
/**
|
||||
* 微信支付商户号(channelMchId)。
|
||||
*/
|
||||
private final String mchId;
|
||||
|
||||
/**
|
||||
* APIv3 密钥,32 位字符串,用于回调解密。
|
||||
*/
|
||||
private final String apiV3Key;
|
||||
|
||||
/**
|
||||
* 商户 API 证书序列号,用于签名请求头。
|
||||
*/
|
||||
private final String merchantSerialNo;
|
||||
|
||||
/**
|
||||
* 商户私钥 PEM 文本,换行符已从 \n 还原为真实换行。
|
||||
*/
|
||||
private final String privateKeyContent;
|
||||
|
||||
/**
|
||||
* 微信平台证书 PEM 文本,换行符已从 \n 还原为真实换行。
|
||||
*/
|
||||
private final String platformCertContent;
|
||||
|
||||
/**
|
||||
* 解析后的商户私钥对象,用于 APIV3 签名。
|
||||
*/
|
||||
private final PrivateKey privateKey;
|
||||
|
||||
private WeChatPayV3Config(String appId, String mchId, String apiV3Key, String merchantSerialNo,
|
||||
String privateKeyContent, String platformCertContent, PrivateKey privateKey) {
|
||||
this.appId = appId;
|
||||
this.mchId = mchId;
|
||||
this.apiV3Key = apiV3Key;
|
||||
this.merchantSerialNo = merchantSerialNo;
|
||||
this.privateKeyContent = privateKeyContent;
|
||||
this.platformCertContent = platformCertContent;
|
||||
this.privateKey = privateKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从渠道配置构建 APIV3 配置对象,并验证必填字段。
|
||||
*
|
||||
* @param channel 支付渠道配置,不允许为空;param JSON 需含 apiV3Key / merchantSerialNo / privateKey / platformCert
|
||||
* @return 解析完成的配置对象
|
||||
* @throws IllegalArgumentException 配置缺失或私钥解析失败
|
||||
*/
|
||||
public static WeChatPayV3Config from(PayChannel channel) {
|
||||
if (channel == null) {
|
||||
throw new IllegalArgumentException("微信公众号支付渠道配置为空");
|
||||
}
|
||||
|
||||
JSONObject params = JSONUtil.parseObj(channel.getParam());
|
||||
String appId = require(channel.getAppId(), "appId");
|
||||
String mchId = require(channel.getChannelMchId(), "channelMchId");
|
||||
String apiV3Key = require(params.getStr("apiV3Key"), "param.apiV3Key");
|
||||
String merchantSerialNo = require(params.getStr("merchantSerialNo"), "param.merchantSerialNo");
|
||||
String privateKeyContent = normalizePem(require(params.getStr("privateKey"), "param.privateKey"));
|
||||
String platformCertContent = normalizePem(require(params.getStr("platformCert"), "param.platformCert"));
|
||||
|
||||
try {
|
||||
PrivateKey privateKey = PayKit.getPrivateKeyByKeyContent(privateKeyContent, AuthTypeEnum.RSA.getCode());
|
||||
return new WeChatPayV3Config(appId, mchId, apiV3Key, merchantSerialNo, privateKeyContent,
|
||||
platformCertContent, privateKey);
|
||||
} catch (Exception ex) {
|
||||
throw new IllegalArgumentException("微信支付 APIV3 私钥解析失败", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回平台证书内容的字节流,用于传入 WxPayKit.verifyNotify 验签。
|
||||
*
|
||||
* @return 平台证书 UTF-8 字节流,每次调用返回新实例
|
||||
*/
|
||||
public InputStream platformCertInputStream() {
|
||||
return new ByteArrayInputStream(platformCertContent.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
static String normalizePem(String value) {
|
||||
return value.replace("\\n", "\n").trim();
|
||||
}
|
||||
|
||||
private static String require(String value, String field) {
|
||||
if (StrUtil.isBlank(value)) {
|
||||
throw new IllegalArgumentException("微信支付 APIV3 配置缺失: " + field);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.pay.utils;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 微信支付 APIV3 回调报文适配器
|
||||
*
|
||||
* @author lengleng
|
||||
* @date 2026-05-10
|
||||
*/
|
||||
public final class WeChatPayV3NotifyParser {
|
||||
|
||||
private WeChatPayV3NotifyParser() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 将微信 APIV3 回调解密后的 JSON 转换为旧版回调处理器兼容的 Map。
|
||||
* <p>trade_state 为 SUCCESS 时 result_code=SUCCESS,否则为 FAIL。
|
||||
*
|
||||
* @param decryptData WxPayKit.verifyNotify 解密后的 JSON 字符串,不允许为空
|
||||
* @return 包含 out_trade_no / result_code / openid / total_fee 等字段的参数 Map
|
||||
*/
|
||||
public static Map<String, String> parse(String decryptData) {
|
||||
JSONObject data = JSONUtil.parseObj(decryptData);
|
||||
Map<String, String> params = new LinkedHashMap<>();
|
||||
String tradeState = data.getStr("trade_state");
|
||||
|
||||
params.put(PayConstants.OUT_TRADE_NO, data.getStr("out_trade_no"));
|
||||
params.put("transaction_id", data.getStr("transaction_id"));
|
||||
params.put("attach", data.getStr("attach"));
|
||||
params.put("trade_state", tradeState);
|
||||
params.put("trade_state_desc", data.getStr("trade_state_desc"));
|
||||
params.put("success_time", data.getStr("success_time"));
|
||||
params.put(PayConstants.RESULT_CODE, StrUtil.equals("SUCCESS", tradeState) ? "SUCCESS" : "FAIL");
|
||||
params.put("err_code", tradeState);
|
||||
params.put("err_code_des", data.getStr("trade_state_desc"));
|
||||
|
||||
JSONObject payer = data.getJSONObject("payer");
|
||||
if (payer != null) {
|
||||
params.put("openid", payer.getStr("openid"));
|
||||
}
|
||||
|
||||
JSONObject amount = data.getJSONObject("amount");
|
||||
if (amount != null) {
|
||||
params.put("total_fee", amount.getStr("total"));
|
||||
params.put("payer_total", amount.getStr("payer_total"));
|
||||
params.put("currency", amount.getStr("currency"));
|
||||
params.put("payer_currency", amount.getStr("payer_currency"));
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<!--
|
||||
~
|
||||
~ Copyright (c) 2018-2026, lengleng All rights reserved.
|
||||
~ Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
~
|
||||
~ Redistribution and use in source and binary forms, with or without
|
||||
~ modification, are permitted provided that the following conditions are met:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<!--
|
||||
~
|
||||
~ Copyright (c) 2018-2026, lengleng All rights reserved.
|
||||
~ Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
~
|
||||
~ Redistribution and use in source and binary forms, with or without
|
||||
~ modification, are permitted provided that the following conditions are met:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<!--
|
||||
~
|
||||
~ Copyright (c) 2018-2026, lengleng All rights reserved.
|
||||
~ Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
~
|
||||
~ Redistribution and use in source and binary forms, with or without
|
||||
~ modification, are permitted provided that the following conditions are met:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<!--
|
||||
~
|
||||
~ Copyright (c) 2018-2026, lengleng All rights reserved.
|
||||
~ Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
~
|
||||
~ Redistribution and use in source and binary forms, with or without
|
||||
~ modification, are permitted provided that the following conditions are met:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<!--
|
||||
~
|
||||
~ Copyright (c) 2018-2026, lengleng All rights reserved.
|
||||
~ Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
~
|
||||
~ Redistribution and use in source and binary forms, with or without
|
||||
~ modification, are permitted provided that the following conditions are met:
|
||||
|
||||
Reference in new issue
Block a user