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

1.加入Maven依赖

com.github.wechatpay-apiv3wechatpay-apache-httpclient0.4.7

2.创建WxV3PayConfig.java配置类

/** * implements WXPayConfig */@Datapublic class WxV3PayConfig {//平台证书序列号public static String mchSerialNo = "xxxxxxxxxxxxxx";//appIDpublic static String APP_ID = "xxxxxxxxxxxxxx";//商户idpublic static String Mch_ID = "xxxxxxxxxxxxxx";// API V3密钥public static String apiV3Key = "xxxxxxxxxxxxxx";// 商户API V3私钥public static String privateKey = "-----BEGIN PRIVATE KEY-----xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -----END PRIVATE KEY-----";}

3.创建WXPaySignatureCertificateUtil.java 工具类

复制粘贴即可

public class WXPaySignatureCertificateUtil { /** * 证书验证 * 自动更新的签名验证器 */public static CloseableHttpClient checkSign() throws IOException {//验签CloseableHttpClient httpClient = null;PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(WxV3PayConfig.privateKey.getBytes("utf-8")));httpClient = WechatPayHttpClientBuilder.create().withMerchant(WxV3PayConfig.Mch_ID, WxV3PayConfig.mchSerialNo, merchantPrivateKey).withValidator(new WechatPay2Validator(WXPaySignatureCertificateUtil.getVerifier(WxV3PayConfig.mchSerialNo))).build();return httpClient;}/** * 保存微信平台证书 */private static final ConcurrentHashMap verifierMap = new ConcurrentHashMap();/** * 功能描述:获取平台证书,自动更新 * 注意:这个方法内置了平台证书的获取和返回值解密 */static AutoUpdateCertificatesVerifier getVerifier(String mchSerialNo) {AutoUpdateCertificatesVerifier verifier = null;if (verifierMap.isEmpty() || !verifierMap.containsKey(mchSerialNo)) {verifierMap.clear();try { //传入证书 PrivateKey privateKey = getPrivateKey();//刷新PrivateKeySigner signer = new PrivateKeySigner(mchSerialNo, privateKey);WechatPay2Credentials credentials = new WechatPay2Credentials(WxV3PayConfig.Mch_ID, signer);verifier = new AutoUpdateCertificatesVerifier(credentials, WxV3PayConfig.apiV3Key.getBytes("utf-8"));verifierMap.put(verifier.getValidCertificate().getSerialNumber()+"", verifier);} catch (UnsupportedEncodingException e) {e.printStackTrace();}} else {verifier = verifierMap.get(mchSerialNo);}return verifier;}/** * 生成带签名支付信息 * * @param timestamp 时间戳 * @param nonceStr随机数 * @param prepayId预付单 * @return 支付信息 * @throws Exception */public static String appPaySign(String timestamp, String nonceStr, String prepayId) throws Exception {//上传私钥PrivateKey privateKey = getPrivateKey();String signatureStr = Stream.of(WxV3PayConfig.APP_ID, timestamp, nonceStr, prepayId).collect(Collectors.joining("\n", "", "\n"));Signature sign = Signature.getInstance("SHA256withRSA");sign.initSign(privateKey);sign.update(signatureStr.getBytes(StandardCharsets.UTF_8));return Base64.getEncoder().encodeToString(sign.sign());}/** * 生成带签名支付信息 * * @param timestamp 时间戳 * @param nonceStr随机数 * @param prepayId预付单 * @return 支付信息 * @throws Exception */public static String jsApiPaySign(String timestamp, String nonceStr, String prepayId) throws Exception {//上传私钥PrivateKey privateKey = getPrivateKey();String signatureStr = Stream.of(WxV3PayConfig.APP_ID, timestamp, nonceStr, "prepay_id="+prepayId).collect(Collectors.joining("\n", "", "\n"));Signature sign = Signature.getInstance("SHA256withRSA");sign.initSign(privateKey);sign.update(signatureStr.getBytes(StandardCharsets.UTF_8));return Base64.getEncoder().encodeToString(sign.sign());}/** * 获取私钥。 * 证书路径 本地使用如: D:\\微信平台证书工具\\7.9\\apiclient_key.pem * 证书路径 线上使用如: /usr/apiclient_key.pem * String filename 私钥文件路径(required) * @return 私钥对象 */public static PrivateKey getPrivateKey() throws IOException {String content = new String(Files.readAllBytes(Paths.get("D:\\微信平台证书工具\\7.9\\apiclient_key.pem")), "utf-8");try {String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "").replaceAll("\\s+", "");KeyFactory kf = KeyFactory.getInstance("RSA");return kf.generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));} catch (NoSuchAlgorithmException e) {throw new RuntimeException("当前Java环境不支持RSA", e);} catch (InvalidKeySpecException e) {throw new RuntimeException("无效的密钥格式");}}/** * 功能描述: 验证签名 * 注意:使用微信支付平台公钥验签 * Wechatpay-Signature 微信返签名 * Wechatpay-Serial 微信平台证书序列号 * * @return java.lang.String * @author 影子 */@SneakyThrowspublic static boolean verifySign(HttpServletRequest request,String body) {boolean verify = false;try {String wechatPaySignature = request.getHeader("Wechatpay-Signature");String wechatPayTimestamp = request.getHeader("Wechatpay-Timestamp");String wechatPayNonce = request.getHeader("Wechatpay-Nonce");String wechatPaySerial = request.getHeader("Wechatpay-Serial");//组装签名串String signStr = Stream.of(wechatPayTimestamp, wechatPayNonce, body).collect(Collectors.joining("\n", "", "\n"));//获取平台证书AutoUpdateCertificatesVerifier verifier = getVerifier(wechatPaySerial);//获取失败 验证失败if (verifier != null) {Signature signature = Signature.getInstance("SHA256withRSA");signature.initVerify(verifier.getValidCertificate());//放入签名串signature.update(signStr.getBytes(StandardCharsets.UTF_8));verify = signature.verify(Base64.getDecoder().decode(wechatPaySignature.getBytes()));}} catch (InvalidKeyException e) {e.printStackTrace();} catch (NoSuchAlgorithmException e) {e.printStackTrace();}return verify;}}

创建WXPayConstants.java类

/** * 常量 */public class WXPayConstants {public static final String DOMAIN_API = "https://api.mch.weixin.qq.com/v3";//app下单public static final String PAY_TRANSACTIONS_APP = "/pay/transactions/app";//微信支付回调public static final String WECHAT_PAY_NOTIFY_URL = "https://xxx.xxxx.com/deal/api/appPayment/weChatPayNotify";//申请退款public static final String REFUND_DOMESTIC_REFUNDS= "/refund/domestic/refunds";//微信退款回调public static final String WECHAT_REFUNDS_NOTIFY_URL = "https://xxx.xxxx.com/api/appPayment/weChatPayRefundsNotify";//关闭订单public static final String PAY_TRANSACTIONS_OUT_TRADE_NO = "/pay/transactions/out-trade-no/{}/close"; }

这里以APP支付和退款为例

创建WechatPaymentService.java

/** * @author 影子 */public interface WechatPaymentService{/** * 微信商品支付 * @param payParam * @return */public MapweChatDoUnifiedOrder() throws Exception;/** * 微信支付回调通知 * @param * @return */public Map weChatNotificationHandler(HttpServletRequest request, HttpServletResponse response);/** *微信关闭订单 * @param outTradeNo * @return */public Map closeOrder(String outTradeNo);/** * 申请退款 * @param * @return */public Map weChatPayRefundsNotify(HttpServletRequest request); /** * 微信退款 * @param outTradeNo 订单号 * @return */public Map weChatRefunds(String outTradeNo);}

创建WeChatPaymentServiceImpl.java

public class WeChatPaymentServiceImpl implements WechatPaymentService { /** * V3微信支付统一下单 * * @param payParam * @return **/@Overridepublic MapweChatDoUnifiedOrder() {//支付总金额BigDecimal totalPrice = BigDecimal.ZERO;totalPrice = totalPrice.add(BigDecimal.valueOf(600));//转换金额保留两位小数点Integer money=new BigDecimal(String.valueOf(totalPrice)).movePointRight(2).intValue();try {//验证证书CloseableHttpClient httpClient = WXPaySignatureCertificateUtil.checkSign();//app下单HttpPost httpPost = new HttpPost(WXPayConstants.DOMAIN_API+WXPayConstants.PAY_TRANSACTIONS_APP);httpPost.addHeader("Accept", "application/json");httpPost.addHeader("Content-type", "application/json; charset=utf-8");ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectMapper objectMapper = new ObjectMapper();ObjectNode rootNode = objectMapper.createObjectNode();rootNode.put("mchid", "商户id").put("appid", "APPID").put("description","描述").put("notify_url", WXPayConstants.WECHAT_PAY_NOTIFY_URL)//回调.put("out_trade_no", "订单号");rootNode.putObject("amount").put("total","总金额");objectMapper.writeValue(bos, rootNode);httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));//完成签名并执行请求CloseableHttpResponse response = httpClient.execute(httpPost);//获取返回状态int statusCode = response.getStatusLine().getStatusCode();if (statusCode == 200) { //处理成功String result = EntityUtils.toString(response.getEntity(), "UTF-8");JSONObject object = JSONObject.parseObject(result);//获取预付单String prepayId = object.getString("prepay_id");//生成签名Long timestamp = System.currentTimeMillis() / 1000;//随机字符串String nonceStr = WXPayUtil.generateNonceStr();//生成带签名支付信息String paySign = WXPaySignatureCertificateUtil.appPaySign(String.valueOf(timestamp), nonceStr, prepayId);Map param = new HashMap();param.put("appid", WxV3PayConfig.APP_ID);param.put("partnerid", WxV3PayConfig.Mch_ID);param.put("prepayid", prepayId);param.put("package", "Sign=WXPay");param.put("noncestr", nonceStr);param.put("timestamp", String.valueOf(timestamp));param.put("sign", paySign);map.put("code",200);map.put("message", "下单成功");map.put("data", param);return map;}map.put("code",200);map.put("message", "下单失败");map.put("data", response);return map;} catch (Exception e) {e.printStackTrace();}}/** * 微信支付回调通知 * @return */@Overridepublic Map weChatNotificationHandler(HttpServletRequest request, HttpServletResponse response){Map map = new HashMap();try {BufferedReader br = request.getReader();String str = null;StringBuilder sb = new StringBuilder();while ((str = br.readLine())!=null) {sb.append(str);}// 构建request,传入必要参数NotificationRequest requests = new NotificationRequest.Builder().withSerialNumber(request.getHeader("Wechatpay-Serial")).withNonce(request.getHeader("Wechatpay-Nonce")).withTimestamp(request.getHeader("Wechatpay-Timestamp")).withSignature(request.getHeader("Wechatpay-Signature")).withBody(String.valueOf(sb)).build();//验签NotificationHandler handler = new NotificationHandler(WXPaySignatureCertificateUtil.getVerifier(WxV3PayConfig.mchSerialNo), WxV3PayConfig.apiV3Key.getBytes(StandardCharsets.UTF_8));//解析请求体Notification notification = handler.parse(requests);String decryptData = notification.getDecryptData();//解析JSONObject jsonObject = JSONObject.parseObject(decryptData);//支付状态交易状态,枚举值: SUCCESS:支付成功 REFUND:转入退款 NOTPAY:未支付 CLOSED:已关闭 REVOKED:已撤销(付款码支付)// USERPAYING:用户支付中(付款码支付) PAYERROR:支付失败(其他原因,如银行返回失败)String trade_state = String.valueOf(jsonObject.get("trade_state"));if (trade_state.equals("SUCCESS")) {//订单号String orderNumber = String.valueOf(jsonObject.get("out_trade_no"));//微信支付微信生成的订单号String transactionId = String.valueOf(jsonObject.get("transaction_id"));//省略查询订单//此处处理业务map.put("code","SUCCESS");map.put("message","成功");//消息推送成功return map;}map.put("code","RESOURCE_NOT_EXISTS");map.put("message", "订单不存在");return map;}catch (Exception e) {e.printStackTrace();}map.put("code","FAIL");map.put("message", "失败");return map;}/** * 关闭订单 * @param outTradeNo 订单号 * @return */@Overridepublic Map closeOrder(String outTradeNo) {Map map = new HashMap();try {//验证证书CloseableHttpClient httpClient = WXPaySignatureCertificateUtil.checkSign();//关闭订单String url = StrFormatter.format(WXPayConstants.DOMAIN_API+WXPayConstants.PAY_TRANSACTIONS_OUT_TRADE_NO, outTradeNo);HttpPost httpPost = new HttpPost(url);httpPost.addHeader("Accept", "application/json");httpPost.addHeader("Content-type", "application/json; charset=utf-8");ByteArrayOutputStream bos = new ByteArrayOutputStream();//2.添加商户idObjectMapper objectMapper = new ObjectMapper();ObjectNode rootNode = objectMapper.createObjectNode();rootNode.put("mchid", WxV3PayConfig.Mch_ID);objectMapper.writeValue(bos, rootNode);//3.调起微信关单接口httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));//完成签名并执行请求CloseableHttpResponse response = httpClient.execute(httpPost);System.out.println(response.getStatusLine().getStatusCode() == 204);//无数据(Http状态码为204) 微信返回结果无数据 状态码为204 成功if (response.getStatusLine().getStatusCode() == 204) {//code 退款码请前往微信支付文档查询map.put("code",200);map.put("message", "关闭订单成功!");return map;}} catch (Exception e) {log.error("关单失败:" + outTradeNo + e);}return null;} /** * 微信退款 * @param outTradeNo 订单号 * @return */@Overridepublic Map weChatRefunds(String outTradeNo) {Map map = new HashMap();//退款总金额BigDecimal totalPrice = BigDecimal.ZERO;totalPrice = totalPrice.add(BigDecimal.valueOf(600));//转换金额Integer money=new BigDecimal(String.valueOf(totalPrice)).movePointRight(2).intValue();try {//验证证书 CloseableHttpClient httpClient = WXPaySignatureCertificateUtil.checkSign();//申请退款接口HttpPost httpPost = new HttpPost(WXPayConstants.DOMAIN_API+WXPayConstants.REFUND_DOMESTIC_REFUNDS);httpPost.addHeader("Accept", "application/json");httpPost.addHeader("Content-type","application/json; charset=utf-8");ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectMapper objectMapper = new ObjectMapper();ObjectNode rootNode = objectMapper.createObjectNode();//微信支付订单号rootNode.put("transaction_id", "微信支付订单号")//退款订单号.put("out_refund_no","生成退款订单号").put("notify_url","退款回调");//退款金额rootNode.putObject("amount").put("refund", "100.00")//原订单金额.put("total", "100.00").put("currency","CNY");objectMapper.writeValue(bos, rootNode);httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));CloseableHttpResponse response = httpClient.execute(httpPost);//退款成功返回消息String bodyAsString = EntityUtils.toString(response.getEntity());JSONObject jsonObject = JSONObject.parseObject(bodyAsString);if (jsonObject.get("status").equals("SUCCESS") || jsonObject.get("status").equals("PROCESSING")) {//code返回map.put("code",200);map.put("message", "退款成功");return map;}}catch (Exception e) {e.printStackTrace();}map.put("code",500);map.put("message", "申请退款失败!");map.put("data", jsonObject);return map;}/** * 申请退款回调 * @param request * @return */@Overridepublic Map weChatPayRefundsNotify(HttpServletRequest request) {Map map = new HashMap();try {BufferedReader br = request.getReader();String str = null;StringBuilder sb = new StringBuilder();while ((str = br.readLine())!=null) {sb.append(str);}// 构建request,传入必要参数NotificationRequest requests = new NotificationRequest.Builder().withSerialNumber(request.getHeader("Wechatpay-Serial")).withNonce(request.getHeader("Wechatpay-Nonce")).withTimestamp(request.getHeader("Wechatpay-Timestamp")).withSignature(request.getHeader("Wechatpay-Signature")).withBody(String.valueOf(sb)).build();//验签NotificationHandler handler = new NotificationHandler(WXPaySignatureCertificateUtil.getVerifier(WxV3PayConfig.mchSerialNo), WxV3PayConfig.apiV3Key.getBytes(StandardCharsets.UTF_8));//解析请求体Notification notification = handler.parse(requests);String decryptData = notification.getDecryptData();//解析JSONObject jsonObject = JSONObject.parseObject(decryptData);String refund_status = String.valueOf(jsonObject.get("refund_status"));if (refund_status.equals("SUCCESS")) {//订单号String orderNumber = String.valueOf(jsonObject.get("out_trade_no"));//微信支付订单号String transactionId = String.valueOf(jsonObject.get("transaction_id"));//这里是处理业务逻辑//code 退款码请前往微信支付文档查询map.put("code","RESOURCE_NOT_EXISTS");map.put("message", "订单不存在");return map;}}catch (Exception e) {e.printStackTrace();}map.put("code","USER_ACCOUNT_ABNORMAL");map.put("message", "退款请求失败");return map;}}

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

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

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

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

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

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

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

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

你学废了吗?