Java源码示例:com.github.wxpay.sdk.WXPayUtil
示例1
/**
* 退款结果通知
*
* 特别说明:退款结果对重要的数据进行了加密,商户需要用商户秘钥进行解密后才能获得结果通知的内容
* @param request
* @throws Exception
*/
@RequestMapping("/refund/notify")
public String refundNotify(HttpServletRequest request) throws Exception {
// Map<String, String> notifyMap = new HashMap<>();
// notifyMap.put("nonce_str", "9b4e428ae262d5dca96178027e849fa9");
// notifyMap.put("req_info", "VKGj8c81RwQ45LcyWEVBE9/HsNfADGbgmbIAQZ2ydcbIFhIIcJFKFQwGfcSGgFGtQlWvg6KDNsRjmCjN+PvipJ3roynJ7cME0LOFG50VGtk4EYHqdjFzUVANI7GpT+i6Ok+ZWivH0MwoGK2fsz3WG+bYs2XJBwav/K89tKjFhZGitCKKBeGqcP99fa/gAL0swNXXNQHmL806Zi+QcACzL3E89BtP9FlXM2Gi+wPQafvPr+/iE+LrPdMlNUa5LiZnenZXUF24kMdhaTafczcKL4sZjRXQHEfEyc/pIZPbIjcNIETvHsskyzKuHVr/SAFkxaM6RR1Kl9pyWZGUjkH5SOeqsT8uL7YQmTlDXrnXmno3AvZdnepTGL5w69yIOmQNPeMqsd01ES9WX36GZYOigfi2+BJ9RRXjIffmpB/MFF+zryyvLTaJE2obCwFSHrmOD8YbaJqrZXOUvWZQrn7wIQgaCypo8V57cD3w5d2RSgIHNrdnEDYlbRcLNYgKuL+T9+1HPhU/frowZgwPN9IB53OahZV3p1Yvos23kvhqPCLn3BYgUihRbey6QhEtL2QyifiQ9e8WVLzWpRZ+DOa8VrhYvSuTfjRdjoNanqHFvXGP6uEsEa+DETqnexpB7xOS9m/CdmlNCwbdUplPEVzNQQdzYT4kybi00Y8A+EdairxfVyK9A7MAYAMtAO9yxV2ht0bn3SofFyZe/YSzdJgxdtcxBf1CVYN6x+yHcSueCSgq4cM/2VCwh4J1+pUVmNpEm0OVcdKbV5USkaxJR0h7Yd+n5FTz5Q2S/qvyDo202cUzLFPI5UqQm5X+FOrWDAkmmr5yVcDQIm3dAdb31jkz0X2TPYt5g7ciQ1h9heyVxJ67FexKvEM4pKCCubtWx6nyxcOUghHMrh8DSoBtewtNjbnwGVIbLsSb6X9MIYAkWIDbqNVP1f63GiZU+cJlhBmvcb8aeQUdTTj7EX5pOTIVSVv5D6SkKmpGU4FGvV+WjufuGX4ZRZo+01p6xl0sfZVmucG1UtxhX6bMCJb06yDwxpv7tGwkwS4TCK4SQp40Xe0=");
// notifyMap.put("appid", "xxx");
// notifyMap.put("mch_id", "xxx");
// notifyMap.put("return_code", "SUCCESS");
// 注意:同样的通知可能会多次发送给商户系统。商户系统必须能够正确处理重复的通知。
// 推荐的做法是,当收到通知进行处理时,首先检查对应业务数据的状态,判断该通知是否已经处理过,如果没有处理过再进行处理,如果处理过直接返回结果成功。
// 在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱。
// TODO 处理业务
Map<String, String> requstInfoMap = wxPayClient.decodeRefundNotify(request);
// 商户处理退款通知参数后同步返回给微信参数
Map<String, String> responseMap = new HashMap<>();
responseMap.put("return_code", "SUCCESS");
responseMap.put("return_msg", "OK");
String responseXml = WXPayUtil.mapToXml(responseMap);
return responseXml;
}
示例2
/**
* 注意:如果是沙箱环境,一提交订单就会立即异步通知,而无需拉起微信支付收银台的中间页面
* @param request
* @throws Exception
*/
@RequestMapping("/notify")
public void payNotify(HttpServletRequest request, HttpServletResponse response) throws Exception{
Map<String, String> reqData = wxPayClient.getNotifyParameter(request);
log.info(reqData.toString());
String returnCode = reqData.get("return_code");
String resultCode = reqData.get("result_code");
if (WXPayConstants.SUCCESS.equals(returnCode) && WXPayConstants.SUCCESS.equals(resultCode)) {
boolean signatureValid = wxPay.isPayResultNotifySignatureValid(reqData);
if (signatureValid) {
// TODO 业务处理
Map<String, String> responseMap = new HashMap<>(2);
responseMap.put("return_code", "SUCCESS");
responseMap.put("return_msg", "OK");
String responseXml = WXPayUtil.mapToXml(responseMap);
response.setContentType("text/xml");
response.getWriter().write(responseXml);
response.flushBuffer();
}
}
}
示例3
/**
* 从request的inputStream中获取参数
* @param request
* @return
* @throws Exception
*/
public Map<String, String> getNotifyParameter(HttpServletRequest request) throws Exception {
InputStream inputStream = request.getInputStream();
ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length = 0;
while ((length = inputStream.read(buffer)) != -1) {
outSteam.write(buffer, 0, length);
}
outSteam.close();
inputStream.close();
// 获取微信调用我们notify_url的返回信息
String resultXml = new String(outSteam.toByteArray(), "utf-8");
Map<String, String> notifyMap = WXPayUtil.xmlToMap(resultXml);
return notifyMap;
}
示例4
/**
* 解密退款通知
*
* <a href="https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_16&index=11>退款结果通知文档</a>
* @return
* @throws Exception
*/
public Map<String, String> decodeRefundNotify(HttpServletRequest request) throws Exception {
// 从request的流中获取参数
Map<String, String> notifyMap = this.getNotifyParameter(request);
log.info(notifyMap.toString());
String reqInfo = notifyMap.get("req_info");
//(1)对加密串A做base64解码,得到加密串B
byte[] bytes = new BASE64Decoder().decodeBuffer(reqInfo);
//(2)对商户key做md5,得到32位小写key* ( key设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置 )
Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING);
SecretKeySpec key = new SecretKeySpec(WXPayUtil.MD5(config.getKey()).toLowerCase().getBytes(), ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, key);
//(3)用key*对加密串B做AES-256-ECB解密(PKCS7Padding)
// java.security.InvalidKeyException: Illegal key size or default parameters
// https://www.cnblogs.com/yaks/p/5608358.html
String responseXml = new String(cipher.doFinal(bytes),"UTF-8");
Map<String, String> responseMap = WXPayUtil.xmlToMap(responseXml);
return responseMap;
}
示例5
/**
* 从request的inputStream中获取参数
* code come from https://github.com/mengday/springboot-pay-example/blob/master/src/main/java/com/example/pay/configuration/WXPayClient.java
* @param request
* @return
* @throws Exception
*/
public static Map<String, String> getNotifyParameter(HttpServletRequest request) throws Exception {
InputStream inputStream = request.getInputStream();
ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length = 0;
while ((length = inputStream.read(buffer)) != -1) {
outSteam.write(buffer, 0, length);
}
outSteam.close();
inputStream.close();
// 获取微信调用我们notify_url的返回信息
String resultXml = new String(outSteam.toByteArray(), "utf-8");
Map<String, String> notifyMap = WXPayUtil.xmlToMap(resultXml);
return notifyMap;
}
示例6
public static void main(String[] args) throws Exception {
//解密
String req_info="Ih5osM/5IbPfHouVrUmwebd1yAW2Gys91jv006W1237sSi3z022KxHafLIDMrQLYiBttTadgvy2cbx6DnmwDIQ52lPWfo6pAAHt7Q9DjBIpDRQ7JsbEBlomoQP2ZkdNHnWscVYuFEVlItaSlkSlcKLdB4UwMduqDYseFsUUthz6htPeBu987zXS6dKrgIbRwOxt5RfPmk1sf0oVB2yU3UH0Ly8SzBjmN1jrh4qAaUkfH6VkeMJcsZSGchQn2VresxJTbGH++JE1UsXUF3gyYpweyxBPtHoKdaggsIONR20UKNxJYPJLnEOnfQF/Ipmk8/QmTVRK7iqfVLC9EA1Auma0AlKBjZlYqynUlF3y+E2ZzgWMUlvDHZVWDbzp/TcE0q+Ukc7yQ3HBsibDR474SPlLTkCWz1iydXzkVcLqJKamsh76Liv1a0hzu0sI3qasMAfmwU6/q7/N6quq031toO1GxqkVaxBRK7e64gSOx9ArxxVFgZ7WN+JPq2OH/pTKH8ToxHA0rtxN5+aAgZGkXiIOUiHtp4mjpRxqe34WK7C7Nr0DQyOVwsXT2TTegSgWGm34aa//ZYxHedubv2iX+E7K222lptg9IqHlMXBbwKFtKtIcal61+8ciz+sB1FBpqHchC+3whTqWv5ZANiHBzaOhbIbA/mKX2XZ6Cy0iYh+bL/8Y/Hvz/UnMGzor+2anIUeBAGRQmseL4jY+Qic46WLuEhDcarCaO4JgJSAOC+VmsdrER9TRum26PFwTQwtNpxkrKCiO9Gv36Ood5D8hXnLHUH+4nbsek8ouxkCcFXq4Us0mipB3i5ksQpt23LiJm9Ahxyvptp9Q41SytS48NXiz3IxTOqDdknowedZwAtJ/fhBlwiOHD9N+pECXuNBKLaCZcatGycr0/DPELiCF+MIRQ6V60wzaZD74TKRFULd1ljNsoQIAbuGaT40WMDY6a28jBHQ/IXnD4gvSvfeumwQzp3Q9PiPyFtF6JxH7RBRj9/lmQuQozJIPZCaCNVTBfWQOdcFaBnPLN0ZNvzjA93g6jcIxHzkXHmiGfh98vq2E=";
// String req_info = "m4NnwrtY0jhpDgNp65H1V/0OWMtSoTYhhY89MHbflhmnaHq9ZKjx9ABq6Jpg4SccA876HVy7J9P85NpdvCMNGInZ4fANDRE+YfZe4HeF+bbFj6JETcEFPpE9YW+bTbC0D+gl/otScJfvB2QUK7+EeBGPHN1EWX9zbr2Gw6AUaORdFk3mGxV5dtjuwWQrv5juzkXDs33Z2dUMslO+i3j0cTDHqwS4hptx2j6h2HvzgzltFbjo7nysU+4rArqJvrGW/9r18e1St9XgG21NALqixfaSmqetOR4zLVL4/+z3CEz8cg5r+/4GUOTf3XFmLCZ/wEkRQhKRNVibG0NFfiG3KnqArMJ/dheQHCd7qL+XX/ZV6tj8RLMgL7R6hOiR03Ljyikdxq9M3K9CTYgf03pHJd3geXX1LgXrLxc1flL6NW+zD3ZayGYpr1WpLsSMG7z8W5j1pme6cRj3n2+CwSFnOnOkxaFuLKoJAJIqM3gbC0eN++vY73RKphlI4zZqg6o5s3MXI6ju1yoi/ZQ+XbTg2JttsdbU0aySernKwkt0rYMf0j/Mcvo2axgHbI3w/iTm141WxHUjkQ+ga2X1pOWdGifGhSmMP8oGaA/WD5MAsK1qXX0eFvUWS/PTauCSTWq5Cmr8loA/KL3jgvB0nyR4mfccB+tPy4Ny7kzOlr/VNeb0ULf96R0AWFWCtdt8AmujAP0DYiM5FSmYLI0XRhpSDjnEbBM8+isNE1GlAVR3NzzemwQORihScovpAktbRSN/d3N+NgTjSoVDiJvCOxCs3thX9qt9iwYbA+/X/gv8lza2FZyIzwkQxGRcYl8JWKpXzNW8EWUNVnSLdHvQttDeV3CvgP/x579RGd6whyFYS6AaI0qw7oTjCFh2EHS/VzGvFuv166ZlVIJ4MNvg79O9h63ZOSE1LzVqEsVh8fDCfM2GgJ9aUdl95Djgunit4yIZOdoigR3f/BEHKrYCEham11rYohaAXs4XAXWihsV3WD5j4G/P+txvjAwujvf4HDwzHgFsmSml013U2mUiy+v4zw==";
//String req_info = "T87GAHG17TGAHG1TGHAHAHA1Y1CIOA9UGJH1GAHV871HAGAGQYQQPOOJMXNBCXBVNMNMAJAA";
String B = AESUtil.decryptData(req_info,"2IBtBXdrqC3kCBs4gaceL7nl2nnFadQv");
// System.out.println(B);
Map<String,String> map = WXPayUtil.xmlToMap(B);
System.out.println(map.get("refund_status"));
//加密
String str = "<root>"+
"<out_refund_no><![CDATA[2531340110812300]]></out_refund_no>"+
"<out_trade_no><![CDATA[2531340110812100]]></out_trade_no>"+
"<refund_account><![CDATA[REFUND_SOURCE_RECHARGE_FUNDS]]></refund_account>"+
"<refund_fee><![CDATA[1]]></refund_fee>"+
"<refund_id><![CDATA[50000505542018011003064518841]]></refund_id>"+
"<refund_recv_accout><![CDATA[支付用户零钱]]></refund_recv_accout>"+
"<refund_request_source><![CDATA[API]]></refund_request_source>"+
"<refund_status><![CDATA[SUCCESS]]></refund_status>"+
"<settlement_refund_fee><![CDATA[1]]></settlement_refund_fee>"+
"<settlement_total_fee><![CDATA[1]]></settlement_total_fee>"+
"<success_time><![CDATA[2018-01-10 10:31:24]]></success_time>"+
"<total_fee><![CDATA[1]]></total_fee>"+
"<transaction_id><![CDATA[4200000052201801101409025381]]></transaction_id>"+
"</root>";
// System.out.println(encryptData(str,"2IBtBXdrqC3kCBs4gaceL7nl2nnFadQv"));
}
示例7
@Override
public AbstractResponse completePayment(PaymentNotifyRequest request) throws BizException {
request.requestCheck();
PaymentNotifyResponse response = new PaymentNotifyResponse();
Map xmlMap = new HashMap();
String xml = request.getXml();
try {
xmlMap = WXPayUtil.xmlToMap(xml);
} catch (Exception e) {
e.printStackTrace();
}
SortedMap<Object, Object> paraMap = new TreeMap<>();
xmlMap.forEach(paraMap::put);
//组装返回的结果的签名字符串
String rsSign = paraMap.remove("sign").toString();
String sign = WeChatBuildRequest.createSign(paraMap, wechatPaymentConfig.getWechatMchsecret());
//验证签名
if (rsSign.equals(sign)) {
//SUCCESS、FAIL
String resultCode = paraMap.get("return_code").toString();
if ("SUCCESS".equals(resultCode)) {
if ("SUCCESS".equals(paraMap.get("result_code"))) {
//更新支付表
Payment payment = new Payment();
payment.setStatus(PayResultEnum.TRADE_SUCCESS.getCode());
payment.setPaySuccessTime((UtilDate.parseStrToDate(UtilDate.simple,paraMap.get("time_end").toString(),new Date())));
Example example = new Example(Payment.class);
example.createCriteria().andEqualTo("orderId", paraMap.get("out_trade_no"));
paymentMapper.updateByExampleSelective(payment, example);
//更新订单表状态
orderCoreService.updateOrder(1, paraMap.get("out_trade_no").toString());
response.setResult(WeChatBuildRequest.setXML("SUCCESS", "OK"));
}
}
} else {
throw new BizException("微信返回结果签名验证失败");
}
return response;
}
示例8
/**
* 获取沙箱环境验签秘钥API
* <a href="https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=23_1">获取验签秘钥API文档</a>
* @return
* @throws Exception
*/
public Map<String, String> getSignKey() throws Exception {
Map<String, String> reqData = new HashMap<>();
reqData.put("appid", config.getAppID());
reqData.put("mch_id", config.getMchID());
reqData.put("nonce_str", WXPayUtil.generateNonceStr());
String sign = WXPayUtil.generateSignature(reqData, config.getKey(), WXPayConstants.SignType.MD5);
reqData.put("sign", sign);
String responseXml = this.requestWithoutCert("https://api.mch.weixin.qq.com/sandboxnew/pay/getsignkey", reqData,
config.getHttpConnectTimeoutMs(), config.getHttpReadTimeoutMs());
Map<String, String> responseMap = WXPayUtil.xmlToMap(responseXml);
return responseMap;
}
示例9
/**
*
* @param request
* @return
* @throws Exception
*/
@RequestMapping("/notify")
public void precreateNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
Map<String, String> reqData = wxPayClient.getNotifyParameter(request);
/**
* {
* transaction_id=4200000138201806180751222945,
* nonce_str=aaaf3fe4d3aa44d8b245bc6c97bda7a8,
* bank_type=CFT,
* openid=xxx,
* sign=821A5F42F5E180ED9EF3743499FBCF13,
* fee_type=CNY,
* mch_id=xxx,
* cash_fee=1,
* out_trade_no=186873223426017,
* appid=xxx,
* total_fee=1,
* trade_type=NATIVE,
* result_code=SUCCESS,
* time_end=20180618131247,
* is_subscribe=N,
* return_code=SUCCESS
* }
*/
log.info(reqData.toString());
// 特别提醒:商户系统对于支付结果通知的内容一定要做签名验证,并校验返回的订单金额是否与商户侧的订单金额一致,防止数据泄漏导致出现“假通知”,造成资金损失。
boolean signatureValid = wxPay.isPayResultNotifySignatureValid(reqData);
if (signatureValid) {
/**
* 注意:同样的通知可能会多次发送给商户系统。商户系统必须能够正确处理重复的通知。
* 推荐的做法是,当收到通知进行处理时,首先检查对应业务数据的状态,
* 判断该通知是否已经处理过,如果没有处理过再进行处理,如果处理过直接返回结果成功。
* 在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱。
*/
Map<String, String> responseMap = new HashMap<>(2);
responseMap.put("return_code", "SUCCESS");
responseMap.put("return_msg", "OK");
String responseXml = WXPayUtil.mapToXml(responseMap);
response.setContentType("text/xml");
response.getWriter().write(responseXml);
response.flushBuffer();
}
}