当前位置:   article > 正文

JAVA 微信APPV3支付(保姆级)_java微信支付

java微信支付

2024.05.07更新方法

更新WXPaySignatureCertificateUtil.java 工具类 详细看3.1

许多人对AutoUpdateCertificatesVerifier验证有疑问 

所以此次更新使用Verifier验证

这里有两种验证证书方式

AutoUpdateCertificatesVerifier和Verifier

两者自选使用

2024.02.05更新方法

去掉了重复代码 更新以下

更新验证签名方法

更新回调验签方法

更新随机字符串使用

小程序去下面

java微信小程序v3支付(保姆级)

java微信商户转账(保姆级)

现在Java微信支付文章五花八门 看不懂 看的懵 掺杂业务逻辑不知名的返回封装 爆红一片 不妨看看这篇

 由于微信更新了0.4.9版本 部分使用微信支付会解析报错 原因是微信内置了Jackson2.13.xxx依赖会与springboot这个Jackson产生冲突 可能会无法升级依赖 因为升级了也会使用老版本依赖

解决方法需要把微信支付解析 验签等方法分离重写 目前没时间写文章 无法自行解决的请私信

1.加入Maven依赖

  1. <!-- 微信支付V3 目前新版本-->
  2. <dependency>
  3. <groupId>com.github.wechatpay-apiv3</groupId>
  4. <artifactId>wechatpay-apache-httpclient</artifactId>
  5. <version>0.4.9</version>
  6. </dependency>

2.更新创建WxV3PayConfig.java配置类 

  1. /**
  2. * implements WXPayConfig
  3. */
  4. @Data
  5. public class WxV3PayConfig {
  6. //平台证书序列号
  7. public static String mchSerialNo = "xxxxxxxxxxxxxx";
  8. //appID
  9. public static String APP_ID = "xxxxxxxxxxxxxx";
  10. //商户id
  11. public static String Mch_ID = "xxxxxxxxxxxxxx";
  12. // API V3密钥
  13. public static String apiV3Key = "xxxxxxxxxxxxxx";
  14. }

3.创建WXPaySignatureCertificateUtil.java 工具类

使用AutoUpdateCertificatesVerifier验证

复制粘贴即可

  1. /***
  2. *
  3. *包都在这
  4. *
  5. *
  6. *
  7. */
  8. import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
  9. import com.wechat.pay.contrib.apache.httpclient.auth.AutoUpdateCertificatesVerifier;
  10. import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
  11. import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
  12. import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
  13. import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
  14. import lombok.SneakyThrows;
  15. import org.apache.http.impl.client.CloseableHttpClient;
  16. import javax.servlet.http.HttpServletRequest;
  17. import java.io.ByteArrayInputStream;
  18. import java.io.IOException;
  19. import java.io.UnsupportedEncodingException;
  20. import java.nio.charset.StandardCharsets;
  21. import java.nio.file.Files;
  22. import java.nio.file.Paths;
  23. import java.security.*;
  24. import java.security.spec.InvalidKeySpecException;
  25. import java.security.spec.PKCS8EncodedKeySpec;
  26. import java.util.Base64;
  27. import java.util.concurrent.ConcurrentHashMap;
  28. import java.util.stream.Collectors;
  29. import java.util.stream.Stream;
  30. public class WXPaySignatureCertificateUtil {
  31. /**
  32. * 证书验证
  33. * 自动更新的签名验证器
  34. */
  35. public static CloseableHttpClient checkSign() throws IOException {
  36. //验签
  37. CloseableHttpClient httpClient = null;
  38. PrivateKey merchantPrivateKey = WXPaySignatureCertificateUtil.getPrivateKey();
  39. httpClient = WechatPayHttpClientBuilder.create()
  40. .withMerchant(WxV3PayConfig.Mch_ID, WxV3PayConfig.mchSerialNo, merchantPrivateKey)
  41. .withValidator(new WechatPay2Validator(WXPaySignatureCertificateUtil.getVerifier(WxV3PayConfig.mchSerialNo)))
  42. .build();
  43. return httpClient;
  44. }
  45. /**
  46. * 保存微信平台证书
  47. */
  48. private static final ConcurrentHashMap<String, AutoUpdateCertificatesVerifier> verifierMap = new ConcurrentHashMap<>();
  49. /**
  50. * 功能描述:获取平台证书,自动更新
  51. * 注意:这个方法内置了平台证书的获取和返回值解密
  52. */
  53. static AutoUpdateCertificatesVerifier getVerifier() {
  54. String mchSerialNo = WxV3PayConfig.mchSerialNo;
  55. AutoUpdateCertificatesVerifier verifier = null;
  56. if (verifierMap.isEmpty() || !verifierMap.containsKey(mchSerialNo)) {
  57. verifierMap.clear();
  58. try {
  59. //传入证书
  60. PrivateKey privateKey = getPrivateKey();
  61. //刷新
  62. PrivateKeySigner signer = new PrivateKeySigner(mchSerialNo, privateKey);
  63. WechatPay2Credentials credentials = new WechatPay2Credentials(WxV3PayConfig.Mch_ID, signer);
  64. verifier = new AutoUpdateCertificatesVerifier(credentials
  65. , WxV3PayConfig.apiV3Key.getBytes("utf-8"));
  66. verifierMap.put(verifier.getValidCertificate().getSerialNumber()+"", verifier);
  67. } catch (UnsupportedEncodingException e) {
  68. e.printStackTrace();
  69. }
  70. } else {
  71. verifier = verifierMap.get(mchSerialNo);
  72. }
  73. return verifier;
  74. }
  75. /**
  76. * app生成带签名支付信息
  77. *
  78. * @param timestamp 时间戳
  79. * @param nonceStr 随机数
  80. * @param prepayId 预付单
  81. * @return 支付信息
  82. * @throws Exception
  83. */
  84. public static String appPaySign(String timestamp, String nonceStr, String prepayId) throws Exception {
  85. //上传私钥
  86. PrivateKey privateKey = getPrivateKey();
  87. String signatureStr = Stream.of(WxV3PayConfig.APP_ID, timestamp, nonceStr, prepayId)
  88. .collect(Collectors.joining("\n", "", "\n"));
  89. Signature sign = Signature.getInstance("SHA256withRSA");
  90. sign.initSign(privateKey);
  91. sign.update(signatureStr.getBytes(StandardCharsets.UTF_8));
  92. return Base64.getEncoder().encodeToString(sign.sign());
  93. }
  94. /**
  95. * 小程序及其它支付生成带签名支付信息
  96. *
  97. * @param timestamp 时间戳
  98. * @param nonceStr 随机数
  99. * @param prepayId 预付单
  100. * @return 支付信息
  101. * @throws Exception
  102. */
  103. public static String jsApiPaySign(String timestamp, String nonceStr, String prepayId) throws Exception {
  104. //上传私钥
  105. PrivateKey privateKey = getPrivateKey();
  106. String signatureStr = Stream.of(WxV3PayConfig.APP_ID, timestamp, nonceStr, "prepay_id="+prepayId)
  107. .collect(Collectors.joining("\n", "", "\n"));
  108. Signature sign = Signature.getInstance("SHA256withRSA");
  109. sign.initSign(privateKey);
  110. sign.update(signatureStr.getBytes(StandardCharsets.UTF_8));
  111. return Base64.getEncoder().encodeToString(sign.sign());
  112. }
  113. /**
  114. * 获取私钥。
  115. * 证书路径 本地使用如: D:\\微信平台证书工具\\7.9\\apiclient_key.pem
  116. * 证书路径 线上使用如: /usr/apiclient_key.pem
  117. * String filename 私钥文件路径 (required)
  118. * @return 私钥对象
  119. */
  120. public static PrivateKey getPrivateKey() throws IOException {
  121. String content = new String(Files.readAllBytes(Paths.get("D:\\微信平台证书工具\\7.9\\apiclient_key.pem")), "utf-8");
  122. try {
  123. String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "")
  124. .replace("-----END PRIVATE KEY-----", "")
  125. .replaceAll("\\s+", "");
  126. KeyFactory kf = KeyFactory.getInstance("RSA");
  127. return kf.generatePrivate(
  128. new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
  129. } catch (NoSuchAlgorithmException e) {
  130. throw new RuntimeException("当前Java环境不支持RSA", e);
  131. } catch (InvalidKeySpecException e) {
  132. throw new RuntimeException("无效的密钥格式");
  133. }
  134. }
  135. }

3.1.更新创建WXPaySignatureCertificateUtil.java 工具类

使用Verifier验证

复制粘贴即可

  1. /***
  2. *
  3. *包都在这
  4. *
  5. *
  6. *
  7. */
  8. import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
  9. import com.wechat.pay.contrib.apache.httpclient.auth.AutoUpdateCertificatesVerifier;
  10. import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
  11. import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
  12. import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
  13. import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
  14. import lombok.SneakyThrows;
  15. import org.apache.http.impl.client.CloseableHttpClient;
  16. import javax.servlet.http.HttpServletRequest;
  17. import java.io.ByteArrayInputStream;
  18. import java.io.IOException;
  19. import java.io.UnsupportedEncodingException;
  20. import java.nio.charset.StandardCharsets;
  21. import java.nio.file.Files;
  22. import java.nio.file.Paths;
  23. import java.security.*;
  24. import java.security.spec.InvalidKeySpecException;
  25. import java.security.spec.PKCS8EncodedKeySpec;
  26. import java.util.Base64;
  27. import java.util.concurrent.ConcurrentHashMap;
  28. import java.util.stream.Collectors;
  29. import java.util.stream.Stream;
  30. public class WXPaySignatureCertificateUtil {
  31. private static final ConcurrentHashMap<String, Verifier> verifierMaps = new ConcurrentHashMap<>();
  32. /**
  33. * 证书验证
  34. * 自动更新的签名验证器
  35. */
  36. public static CloseableHttpClient checkSign() throws IOException {
  37. //验签
  38. CloseableHttpClient httpClient = null;
  39. PrivateKey merchantPrivateKey = WXPaySignatureCertificateUtil.getPrivateKey();
  40. httpClient = WechatPayHttpClientBuilder.create()
  41. .withMerchant(WxV3PayConfig.Mch_ID, WxV3PayConfig.mchSerialNo, merchantPrivateKey)
  42. .withValidator(new WechatPay2Validator(WXPaySignatureCertificateUtil.getVerifier(WxV3PayConfig.mchSerialNo)))
  43. .build();
  44. return httpClient;
  45. }
  46. /**
  47. * 功能描述:获取平台证书,自动更新
  48. * 注意:这个方法内置了平台证书的获取和返回值解密
  49. */
  50. public static Verifier getVerifiers(String mchSerialNo) {
  51. Verifier verifier = null;
  52. if (verifierMaps.isEmpty() || !verifierMaps.containsKey(mchSerialNo)) {
  53. verifierMaps.clear();
  54. try {
  55. PrivateKey privateKey = getPrivateKey();
  56. //刷新
  57. PrivateKeySigner signer = new PrivateKeySigner(mchSerialNo, privateKey);
  58. WechatPay2Credentials credentials = new WechatPay2Credentials(WxV3PayConfig.Mch_ID, signer);
  59. verifier = new AutoUpdateCertificatesVerifier(credentials
  60. , apiV3Key.getBytes("utf-8"));
  61. verifierMaps.put(verifier.getValidCertificate().getSerialNumber()+"", verifier);
  62. } catch (UnsupportedEncodingException e) {
  63. e.printStackTrace();
  64. } catch (IOException e) {
  65. throw new RuntimeException(e);
  66. }
  67. } else {
  68. verifier = verifierMaps.get(mchSerialNo);
  69. }
  70. return verifier;
  71. }
  72. /**
  73. * app生成带签名支付信息
  74. *
  75. * @param timestamp 时间戳
  76. * @param nonceStr 随机数
  77. * @param prepayId 预付单
  78. * @return 支付信息
  79. * @throws Exception
  80. */
  81. public static String appPaySign(String timestamp, String nonceStr, String prepayId) throws Exception {
  82. //上传私钥
  83. PrivateKey privateKey = getPrivateKey();
  84. String signatureStr = Stream.of(WxV3PayConfig.APP_ID, timestamp, nonceStr, prepayId)
  85. .collect(Collectors.joining("\n", "", "\n"));
  86. Signature sign = Signature.getInstance("SHA256withRSA");
  87. sign.initSign(privateKey);
  88. sign.update(signatureStr.getBytes(StandardCharsets.UTF_8));
  89. return Base64.getEncoder().encodeToString(sign.sign());
  90. }
  91. /**
  92. * 小程序及其它支付生成带签名支付信息
  93. *
  94. * @param timestamp 时间戳
  95. * @param nonceStr 随机数
  96. * @param prepayId 预付单
  97. * @return 支付信息
  98. * @throws Exception
  99. */
  100. public static String jsApiPaySign(String timestamp, String nonceStr, String prepayId) throws Exception {
  101. //上传私钥
  102. PrivateKey privateKey = getPrivateKey();
  103. String signatureStr = Stream.of(WxV3PayConfig.APP_ID, timestamp, nonceStr, "prepay_id="+prepayId)
  104. .collect(Collectors.joining("\n", "", "\n"));
  105. Signature sign = Signature.getInstance("SHA256withRSA");
  106. sign.initSign(privateKey);
  107. sign.update(signatureStr.getBytes(StandardCharsets.UTF_8));
  108. return Base64.getEncoder().encodeToString(sign.sign());
  109. }
  110. /**
  111. * 获取私钥。
  112. * 证书路径 本地使用如: D:\\微信平台证书工具\\7.9\\apiclient_key.pem
  113. * 证书路径 线上使用如: /usr/apiclient_key.pem
  114. * String filename 私钥文件路径 (required)
  115. * @return 私钥对象
  116. */
  117. public static PrivateKey getPrivateKey() throws IOException {
  118. String content = new String(Files.readAllBytes(Paths.get("D:\\微信平台证书工具\\7.9\\apiclient_key.pem")), "utf-8");
  119. try {
  120. String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "")
  121. .replace("-----END PRIVATE KEY-----", "")
  122. .replaceAll("\\s+", "");
  123. KeyFactory kf = KeyFactory.getInstance("RSA");
  124. return kf.generatePrivate(
  125. new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
  126. } catch (NoSuchAlgorithmException e) {
  127. throw new RuntimeException("当前Java环境不支持RSA", e);
  128. } catch (InvalidKeySpecException e) {
  129. throw new RuntimeException("无效的密钥格式");
  130. }
  131. }
  132. }

创建WXPayConstants.java类

  1. /**
  2. * 常量
  3. */
  4. public class WXPayConstants {
  5. public static final String DOMAIN_API = "https://api.mch.weixin.qq.com/v3";
  6. //app下单
  7. public static final String PAY_TRANSACTIONS_APP = "/pay/transactions/app";
  8. //微信支付回调
  9. public static final String WECHAT_PAY_NOTIFY_URL =
  10. "https://xxx.xxxx.com/deal/api/appPayment/weChatPayNotify";
  11. //申请退款
  12. public static final String REFUND_DOMESTIC_REFUNDS = "/refund/domestic/refunds";
  13. //微信退款回调
  14. public static final String WECHAT_REFUNDS_NOTIFY_URL = "https://xxx.xxxx.com/api/appPayment/weChatPayRefundsNotify";
  15. //关闭订单
  16. public static final String PAY_TRANSACTIONS_OUT_TRADE_NO = "/pay/transactions/out-trade-no/{}/close";
  17. }

这里以APP支付和退款为例

创建WechatPaymentService.java

  1. /**
  2. * @author 影子
  3. */
  4. public interface WechatPaymentService
  5. {
  6. /**
  7. * 微信商品支付
  8. * @param payParam
  9. * @return
  10. */
  11. public Map<String, Object>weChatDoUnifiedOrder() throws Exception;
  12. /**
  13. * 微信支付回调通知
  14. * @param
  15. * @return
  16. */
  17. public Map<String, Object> weChatNotificationHandler(HttpServletRequest request, HttpServletResponse response);
  18. /**
  19. *微信关闭订单
  20. * @param outTradeNo
  21. * @return
  22. */
  23. public Map<String, Object> closeOrder(String outTradeNo);
  24. /**
  25. * 申请退款
  26. * @param
  27. * @return
  28. */
  29. public Map<String, Object> weChatPayRefundsNotify(HttpServletRequest request);
  30. /**
  31. * 微信退款
  32. * @param outTradeNo 订单号
  33. * @return
  34. */
  35. public Map<String, Object> weChatRefunds(String outTradeNo);
  36. }

创建WeChatPaymentServiceImpl.java

  1. /*
  2. *
  3. *改了七八遍 照顾找包困难的朋友吧
  4. *
  5. */
  6. import com.alibaba.fastjson.JSONObject;
  7. import com.alipay.api.internal.util.file.ByteArrayOutputStream;
  8. import com.fasterxml.jackson.databind.ObjectMapper;
  9. import com.fasterxml.jackson.databind.node.ObjectNode;
  10. import com.github.wxpay.sdk.WXPayUtil;
  11. import com.wechat.pay.contrib.apache.httpclient.notification.Notification;
  12. import com.wechat.pay.contrib.apache.httpclient.notification.NotificationHandler;
  13. import com.wechat.pay.contrib.apache.httpclient.notification.NotificationRequest;
  14. import org.apache.http.client.methods.CloseableHttpResponse;
  15. import org.apache.http.client.methods.HttpPost;
  16. import org.apache.http.entity.StringEntity;
  17. import org.apache.http.impl.client.CloseableHttpClient;
  18. import org.apache.http.util.EntityUtils;
  19. public class WeChatPaymentServiceImpl implements WechatPaymentService {
  20. /**
  21. * V3微信支付统一下单
  22. *
  23. * @param payParam
  24. * @return
  25. *
  26. */
  27. @Override
  28. public Map<String, Object>weChatDoUnifiedOrder() {
  29. Map<String,Object> map =new HashMap<>();
  30. //支付总金额
  31. BigDecimal totalPrice = BigDecimal.ZERO;
  32. totalPrice = totalPrice.add(BigDecimal.valueOf(600));
  33. //转换金额保留两位小数点
  34. Integer money=new BigDecimal(String.valueOf(totalPrice)).movePointRight(2).intValue();
  35. try {
  36. //验证证书
  37. CloseableHttpClient httpClient = WXPaySignatureCertificateUtil.checkSign();
  38. //app下单
  39. HttpPost httpPost = new HttpPost(WXPayConstants.DOMAIN_API+WXPayConstants.PAY_TRANSACTIONS_APP);
  40. httpPost.addHeader("Accept", "application/json");
  41. httpPost.addHeader("Content-type", "application/json; charset=utf-8");
  42. ByteArrayOutputStream bos = new ByteArrayOutputStream();
  43. ObjectMapper objectMapper = new ObjectMapper();
  44. ObjectNode rootNode = objectMapper.createObjectNode();
  45. rootNode.put("mchid", "商户id")
  46. .put("appid", "APPID")
  47. .put("description","描述")
  48. .put("notify_url", WXPayConstants.WECHAT_PAY_NOTIFY_URL)//回调
  49. .put("out_trade_no", "订单号");
  50. rootNode.putObject("amount")
  51. .put("total","总金额");
  52. objectMapper.writeValue(bos, rootNode);
  53. httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
  54. //完成签名并执行请求
  55. CloseableHttpResponse response = httpClient.execute(httpPost);
  56. //获取返回状态
  57. int statusCode = response.getStatusLine().getStatusCode();
  58. if (statusCode == 200) { //处理成功
  59. String result = EntityUtils.toString(response.getEntity(), "UTF-8");
  60. JSONObject object = JSONObject.parseObject(result);
  61. //获取预付单
  62. String prepayId = object.getString("prepay_id");
  63. //生成签名
  64. Long timestamp = System.currentTimeMillis() / 1000;
  65. //随机字符串 这个是微信支付maven自带的 也可以用其它的
  66. //这个是v2支付依赖自带的工具包 可以去掉了
  67. //String nonceStr = WXPayUtil.generateNonceStr();
  68. //该方法org.apache.commons.lang3.RandomStringUtils依赖自带随机生成字符串 RandomStringUtils.randomAlphanumeric(32) 代表生成32位
  69. String nonceStr = RandomStringUtils.randomAlphanumeric(32);
  70. //生成带签名支付信息
  71. String paySign = WXPaySignatureCertificateUtil.appPaySign(String.valueOf(timestamp), nonceStr, prepayId);
  72. Map<String, String> param = new HashMap<>();
  73. param.put("appid", WxV3PayConfig.APP_ID);
  74. param.put("partnerid", WxV3PayConfig.Mch_ID);
  75. param.put("prepayid", prepayId);
  76. param.put("package", "Sign=WXPay");
  77. param.put("noncestr", nonceStr);
  78. param.put("timestamp", String.valueOf(timestamp));
  79. param.put("sign", paySign);
  80. map.put("code",200);
  81. map.put("message", "下单成功");
  82. map.put("data", param);
  83. return map;
  84. }
  85. map.put("code",200);
  86. map.put("message", "下单失败");
  87. map.put("data", response);
  88. return map;
  89. } catch (Exception e) {
  90. e.printStackTrace();
  91. }
  92. }
  93. /**
  94. * 微信支付回调通知
  95. * @return
  96. */
  97. @Override
  98. public Map<String, Object> weChatNotificationHandler(HttpServletRequest request, HttpServletResponse response){
  99. Map<String,Object> map = new HashMap<>();
  100. try {
  101. BufferedReader br = request.getReader();
  102. String str = null;
  103. StringBuilder sb = new StringBuilder();
  104. while ((str = br.readLine())!=null) {
  105. sb.append(str);
  106. }
  107. // 构建request,传入必要参数
  108. NotificationRequest requests = new NotificationRequest.Builder()
  109. .withSerialNumber(request.getHeader("Wechatpay-Serial"))
  110. .withNonce(request.getHeader("Wechatpay-Nonce"))
  111. .withTimestamp(request.getHeader("Wechatpay-Timestamp"))
  112. .withSignature(request.getHeader("Wechatpay-Signature"))
  113. .withBody(String.valueOf(sb))
  114. .build();
  115. //验签
  116. NotificationHandler handler = new NotificationHandler(WXPaySignatureCertificateUtil.getVerifier(), WxV3PayConfig.apiV3Key.getBytes(StandardCharsets.UTF_8));
  117. //解析请求体
  118. Notification notification = handler.parse(requests);
  119. String decryptData = notification.getDecryptData();
  120. //解析
  121. JSONObject jsonObject = JSONObject.parseObject(decryptData);
  122. //支付状态交易状态,枚举值: SUCCESS:支付成功 REFUND:转入退款 NOTPAY:未支付 CLOSED:已关闭 REVOKED:已撤销(付款码支付)
  123. // USERPAYING:用户支付中(付款码支付) PAYERROR:支付失败(其他原因,如银行返回失败)
  124. String trade_state = String.valueOf(jsonObject.get("trade_state"));
  125. if (trade_state.equals("SUCCESS")) {
  126. //订单号
  127. String orderNumber = String.valueOf(jsonObject.get("out_trade_no"));
  128. //微信支付微信生成的订单号
  129. String transactionId = String.valueOf(jsonObject.get("transaction_id"));
  130. //省略查询订单
  131. //此处处理业务
  132. map.put("code","SUCCESS");
  133. map.put("message","成功");
  134. //消息推送成功
  135. return map;
  136. }
  137. map.put("code","RESOURCE_NOT_EXISTS");
  138. map.put("message", "订单不存在");
  139. return map;
  140. }catch (Exception e) {
  141. e.printStackTrace();
  142. }
  143. map.put("code","FAIL");
  144. map.put("message", "失败");
  145. return map;
  146. }
  147. /**
  148. * 关闭订单
  149. * @param outTradeNo 订单号
  150. * @return
  151. */
  152. @Override
  153. public Map<String, Object> closeOrder(String outTradeNo) {
  154. Map<String,Object> map = new HashMap<>();
  155. try {
  156. //验证证书
  157. CloseableHttpClient httpClient = WXPaySignatureCertificateUtil.checkSign();
  158. //关闭订单
  159. String url = StrFormatter.format(WXPayConstants.DOMAIN_API+WXPayConstants.PAY_TRANSACTIONS_OUT_TRADE_NO, outTradeNo);
  160. HttpPost httpPost = new HttpPost(url);
  161. httpPost.addHeader("Accept", "application/json");
  162. httpPost.addHeader("Content-type", "application/json; charset=utf-8");
  163. ByteArrayOutputStream bos = new ByteArrayOutputStream();
  164. //2.添加商户id
  165. ObjectMapper objectMapper = new ObjectMapper();
  166. ObjectNode rootNode = objectMapper.createObjectNode();
  167. rootNode.put("mchid", WxV3PayConfig.Mch_ID);
  168. objectMapper.writeValue(bos, rootNode);
  169. //3.调起微信关单接口
  170. httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
  171. //完成签名并执行请求
  172. CloseableHttpResponse response = httpClient.execute(httpPost);
  173. System.out.println(response.getStatusLine().getStatusCode() == 204);
  174. //无数据(Http状态码为204) 微信返回结果无数据 状态码为204 成功
  175. if (response.getStatusLine().getStatusCode() == 204) {
  176. //code 退款码请前往微信支付文档查询
  177. map.put("code",200);
  178. map.put("message", "关闭订单成功!");
  179. return map;
  180. }
  181. } catch (Exception e) {
  182. log.error("关单失败:" + outTradeNo + e);
  183. }
  184. return null;
  185. }
  186. /**
  187. * 微信退款
  188. * @param outTradeNo 订单号
  189. * @return
  190. */
  191. @Override
  192. public Map<String, Object> weChatRefunds(String outTradeNo) {
  193. Map<String,Object> map = new HashMap<>();
  194. //退款总金额
  195. BigDecimal totalPrice = BigDecimal.ZERO;
  196. totalPrice = totalPrice.add(BigDecimal.valueOf(600));
  197. //转换金额
  198. Integer money=new BigDecimal(String.valueOf(totalPrice)).movePointRight(2).intValue();
  199. try {
  200. //验证证书
  201. CloseableHttpClient httpClient = WXPaySignatureCertificateUtil.checkSign();
  202. //申请退款接口
  203. HttpPost httpPost = new HttpPost(WXPayConstants.DOMAIN_API+WXPayConstants.REFUND_DOMESTIC_REFUNDS);
  204. httpPost.addHeader("Accept", "application/json");
  205. httpPost.addHeader("Content-type","application/json; charset=utf-8");
  206. ByteArrayOutputStream bos = new ByteArrayOutputStream();
  207. ObjectMapper objectMapper = new ObjectMapper();
  208. ObjectNode rootNode = objectMapper.createObjectNode();
  209. //微信支付订单号
  210. rootNode.put("transaction_id", "微信支付订单号")
  211. //退款订单号
  212. .put("out_refund_no","生成退款订单号")
  213. .put("notify_url","退款回调");
  214. //退款金额
  215. rootNode.putObject("amount")
  216. .put("refund", "100.00")
  217. //原订单金额
  218. .put("total", "100.00")
  219. .put("currency","CNY");
  220. objectMapper.writeValue(bos, rootNode);
  221. httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
  222. CloseableHttpResponse response = httpClient.execute(httpPost);
  223. //退款成功返回消息
  224. String bodyAsString = EntityUtils.toString(response.getEntity());
  225. JSONObject jsonObject = JSONObject.parseObject(bodyAsString);
  226. if (jsonObject.get("status").equals("SUCCESS") || jsonObject.get("status").equals("PROCESSING")) {
  227. //code返回
  228. map.put("code",200);
  229. map.put("message", "退款成功");
  230. return map;
  231. }
  232. }catch (Exception e) {
  233. e.printStackTrace();
  234. }
  235. map.put("code",500);
  236. map.put("message", "申请退款失败!");
  237. map.put("data", jsonObject);
  238. return map;
  239. }
  240. /**
  241. * 申请退款回调
  242. * @param request
  243. * @return
  244. */
  245. @Override
  246. public Map<String,Object> weChatPayRefundsNotify(HttpServletRequest request) {
  247. Map<String,Object> map = new HashMap<>();
  248. try {
  249. BufferedReader br = request.getReader();
  250. String str = null;
  251. StringBuilder sb = new StringBuilder();
  252. while ((str = br.readLine())!=null) {
  253. sb.append(str);
  254. }
  255. // 构建request,传入必要参数
  256. NotificationRequest requests = new NotificationRequest.Builder()
  257. .withSerialNumber(request.getHeader("Wechatpay-Serial"))
  258. .withNonce(request.getHeader("Wechatpay-Nonce"))
  259. .withTimestamp(request.getHeader("Wechatpay-Timestamp"))
  260. .withSignature(request.getHeader("Wechatpay-Signature"))
  261. .withBody(String.valueOf(sb))
  262. .build();
  263. //验签
  264. NotificationHandler handler = new NotificationHandler(WXPaySignatureCertificateUtil.getVerifier(), WxV3PayConfig.apiV3Key.getBytes(StandardCharsets.UTF_8));
  265. //解析请求体
  266. Notification notification = handler.parse(requests);
  267. String decryptData = notification.getDecryptData();
  268. //解析
  269. JSONObject jsonObject = JSONObject.parseObject(decryptData);
  270. String refund_status = String.valueOf(jsonObject.get("refund_status"));
  271. if (refund_status.equals("SUCCESS")) {
  272. //订单号
  273. String orderNumber = String.valueOf(jsonObject.get("out_trade_no"));
  274. //微信支付订单号
  275. String transactionId = String.valueOf(jsonObject.get("transaction_id"));
  276. //这里是处理业务逻辑
  277. //code 退款码请前往微信支付文档查询
  278. map.put("code","RESOURCE_NOT_EXISTS");
  279. map.put("message", "订单不存在");
  280. return map;
  281. }
  282. }catch (Exception e) {
  283. e.printStackTrace();
  284. }
  285. map.put("code","USER_ACCOUNT_ABNORMAL");
  286. map.put("message", "退款请求失败");
  287. return map;
  288. }
  289. }

代码可复制粘贴使用 无业务逻辑代码 支付代码简洁

如果更换支付类型如:APP、二维码支付、扫码支付、JSAPI支付

请看以下示例二维码支付代码

 HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3"+"/pay/transactions/native");

 HttpPost httpPost = new HttpPost("这里更换")

整体不变只需要微信返回正确状态码内处理即可 如以下返回为 二维码支付参数

  1. //完成签名并执行请求
  2. CloseableHttpResponse response = httpClient.execute(httpPost);
  3. //获取返回状态
  4. int statusCode = response.getStatusLine().getStatusCode();
  5. if (statusCode == 200) { //处理成功
  6. String result = EntityUtils.toString(response.getEntity(), "UTF-8");
  7. JSONObject object = JSONObject.parseObject(result);
  8. map.put("code",200);
  9. map.put("message", "下单成功");
  10. map.put("data", object);
  11. return map;
  12. }
  13. map.put("code",500);
  14. map.put("message", "下单失败");
  15. map.put("data", response);
  16. return map;

修改方式 根据官方文档返回参数类型为准

你学废了吗?

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小桥流水78/article/detail/980559
推荐阅读
相关标签
  

闽ICP备14008679号