1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
| @Service @Slf4j public class WechatPayService {
@Value("${wechat.pay.appid}") private String appId;
@Value("${wechat.pay.mchid}") private String mchId;
@Value("${wechat.pay.api-key}") private String apiKey;
@Value("${wechat.pay.cert-path}") private String certPath;
@Autowired private RestTemplate restTemplate;
public WechatPayResult transferToWallet(String openid, BigDecimal amount, String orderNo) { try { Map<String, Object> params = buildTransferParams(openid, amount, orderNo);
String sign = generateSign(params); params.put("sign", sign);
String xml = mapToXml(params); String response = restTemplate.postForObject( "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers", xml, String.class );
Map<String, Object> responseMap = xmlToMap(response);
if (!verifySign(responseMap)) { throw new BusinessException("微信支付签名验证失败"); }
if ("SUCCESS".equals(responseMap.get("result_code"))) { return WechatPayResult.success(responseMap.get("partner_trade_no").toString()); } else { return WechatPayResult.failed(responseMap.get("err_code_des").toString()); }
} catch (Exception e) { log.error("微信支付转账异常: openid={}, amount={}, orderNo={}", openid, amount, orderNo, e); return WechatPayResult.failed("系统异常: " + e.getMessage()); } }
private Map<String, Object> buildTransferParams(String openid, BigDecimal amount, String orderNo) { Map<String, Object> params = new HashMap<>(); params.put("mch_appid", appId); params.put("mchid", mchId); params.put("nonce_str", generateNonceStr()); params.put("partner_trade_no", orderNo); params.put("openid", openid); params.put("check_name", "NO_CHECK"); params.put("amount", amount.multiply(new BigDecimal("100")).intValue()); params.put("desc", "账户余额提现"); params.put("spbill_create_ip", getClientIp()); return params; }
private String generateSign(Map<String, Object> params) { List<String> keys = new ArrayList<>(params.keySet()); keys.sort(String::compareTo);
StringBuilder sb = new StringBuilder(); for (String key : keys) { Object value = params.get(key); if (value != null && !value.toString().isEmpty()) { sb.append(key).append("=").append(value).append("&"); } } sb.append("key=").append(apiKey);
return DigestUtils.md5Hex(sb.toString()).toUpperCase(); }
private boolean verifySign(Map<String, Object> params) { String sign = params.get("sign").toString(); params.remove("sign"); String calculatedSign = generateSign(params); return sign.equals(calculatedSign); }
private String mapToXml(Map<String, Object> params) { StringBuilder sb = new StringBuilder(); sb.append("<xml>"); for (Map.Entry<String, Object> entry : params.entrySet()) { sb.append("<").append(entry.getKey()).append(">") .append(entry.getValue()) .append("</").append(entry.getKey()).append(">"); } sb.append("</xml>"); return sb.toString(); }
private Map<String, Object> xmlToMap(String xml) { Map<String, Object> map = new HashMap<>(); return map; }
private String generateNonceStr() { return UUID.randomUUID().toString().replace("-", ""); }
private String getClientIp() { return "127.0.0.1"; } }
|