直接上干货:SDK请从官方下载
官方文档地址:微信支付-开发者文档
入口:
@RequestMapping(value = "/wechat/v3/jsapi/orders") public Map<String, String> ordersV3() { // 组装字段,可见官方文档 JSONObject data = new JSONObject(); data.put("appid", AuthUtil.APPID); data.put("mchid", AuthUtil.MCHID); data.put("description", "测试商品"); data.put("out_trade_no", UUID.randomUUID().toString().replaceAll("-", "")); data.put("notify_url", "你的回调地址"); // 你的回调地址 JSONObject amount = new JSONObject(); amount.put("total", 1); // 多少钱?单位分 data.put("amount", amount); JSONObject payer = new JSONObject(); payer.put("openid", userService.getOpenId()); // 支付者的open ID data.put("payer", payer); //发送post请求"统一下单接口"返回预支付id:prepay_id //下单接口:https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi Map<String, Object> stringObjectMap = HttpUtils.doPostWexinV3(AuthUtil.UNIFIEDORDERURLWX, data.toJSONString()); System.out.println("返回结果为:" + stringObjectMap); //通过prepay_id获取签名信息 try { HashMap<String, Object> dataMap = WeixinchatPayUtils.getTokenWeixin(AuthUtil.APPID, String.valueOf(stringObjectMap.get("prepay_id"))); return new ResponseEntityUtils(dataMap, HttpStatus.OK); } catch (Exception ex) { return null; } }
关键点1:下单
public static Map<String,Object> doPostWexinV3(String url, String body) { // 自动更新证书功能 AutoUpdateCertificatesVerifier verifier = null; try { //这段是官方SDK,照抄就好 // 名词解释:CERTNO:证书序列号;CERTPATH:证书在你服务器的地址(apiclient_key.pem) verifier = new AutoUpdateCertificatesVerifier( new WechatPay2Credentials(AuthUtil.MCHID, new PrivateKeySigner(AuthUtil.CERTNO, PemUtil.loadPrivateKey(new FileInputStream(AuthUtil.CERTPATH)))), AuthUtil.PATERNERKEY.getBytes("utf-8")); } catch (FileNotFoundException e) { System.err.println("证书未找到!====================="); e.printStackTrace(); } catch (UnsupportedEncodingException e) { System.err.println("文件流错误!====================="); e.printStackTrace(); } WechatPayHttpClientBuilder builder = null; try { //这段是官方SDK,照抄就好 builder = WechatPayHttpClientBuilder.create() .withMerchant(AuthUtil.MCHID,AuthUtil.CERTNO, PemUtil.loadPrivateKey(new FileInputStream(AuthUtil.CERTPATH))) .withValidator(new WechatPay2Validator(verifier)); } catch (FileNotFoundException e) { System.err.println("证书未找到!====================="); e.printStackTrace(); } HttpClient httpClient = builder.build(); HttpPost httpPost = new HttpPost(url); httpPost.addHeader("Content-Type","application/json;chartset=utf-8"); httpPost.addHeader("Accept", "application/json"); try{ if(body==null){ throw new IllegalArgumentException("data参数不能为空"); } StringEntity stringEntity = new StringEntity(body,"utf-8"); httpPost.setEntity(stringEntity); // 直接执行execute方法,官方会自动处理签名和验签,并进行证书自动更新 HttpResponse httpResponse = httpClient.execute(httpPost); HttpEntity httpEntity = httpResponse.getEntity(); if(httpResponse.getStatusLine().getStatusCode() == 200){ String jsonResult = EntityUtils.toString(httpEntity); return JSON.readValue(jsonResult, HashMap.class); }else{ System.err.println("微信支付错误信息"+EntityUtils.toString(httpEntity)); } }catch (Exception e){ e.printStackTrace(); } return null; }
关键点1:签名
public static HashMap<String,Object> getTokenWeixin (String appId, String prepay_id) throws IOException, SignatureException, NoSuchAlgorithmException, InvalidKeyException { // 获取随机字符串 String nonceStr = getNonceStr(); // 获取微信小程序支付package String packagestr = "prepay_id=" + prepay_id; long timestamp = System.currentTimeMillis() / 1000; //签名,使用字段appId、timeStamp、nonceStr、package计算得出的签名值 String message = buildMessageTwo(appId,timestamp,nonceStr,packagestr); //获取对应的签名 String signature = sign(message.getBytes("utf-8")); // 组装返回 HashMap<String,Object> map = new HashMap<>(); map.put("timeStamp", String.valueOf(timestamp)); map.put("nonceStr", nonceStr); map.put("package", packagestr); map.put("signType", "RSA"); map.put("paySign", signature); map.put("appId", appId); return map; }
public static String getNonceStr(){
return UUID.randomUUID().toString()
.replaceAll("-", "")
.substring(0, 32);
}
private static String buildMessageTwo(String appId, long timestamp, String nonceStr, String packag) {
return appId + "\n"
+ timestamp + "\n"
+ nonceStr + "\n"
+ packag + "\n";
}
private static String sign(byte[] message) throws NoSuchAlgorithmException, SignatureException, IOException, InvalidKeyException {
Signature sign = Signature.getInstance("SHA256withRSA"); //SHA256withRSA
sign.initSign(PemUtil.loadPrivateKey(new FileInputStream(AuthUtil.CERTPATH))); // 微信证书私钥
sign.update(message);
return Base64.getEncoder().encodeToString(sign.sign());
}
返回处理:
@RequestMapping("/wechat/pay/callback/personal") public Map orderPayCallbackPersonal(@RequestBody Map body, HttpServletRequest request) { Map<String, Object> result = new HashMap(); //1:获取微信支付回调的获取签名信息 String timestamp = request.getHeader("Wechatpay-Timestamp"); String nonce = request.getHeader("Wechatpay-Nonce"); ObjectMapper objectMapper = new ObjectMapper(); try { // 2: 开始解析报文体 String data = objectMapper.writeValueAsString(body); String message = timestamp + "\n" + nonce + "\n" + data + "\n"; //3:获取应答签名 String sign = request.getHeader("Wechatpay-Signature"); //4:获取平台对应的证书 String serialNo = request.getHeader("Wechatpay-Serial"); X509Certificate x509Certificate = WechatPayUtils.refreshCertificate().get(serialNo); if (!WechatPayUtils.verify(x509Certificate, message.getBytes(), sign)) { throw new IllegalArgumentException("微信支付签名验证失败:" + message); } Map<String, String> resource = (Map) body.get("resource"); // 5:回调报文解密 AesUtil aesUtil = new AesUtil(AuthUtil.PATERNERKEY.getBytes()); //解密后json字符串 String decryptToString = aesUtil.decryptToString( resource.get("associated_data").getBytes(), resource.get("nonce").getBytes(), resource.get("ciphertext")); //6:获取微信支付返回的信息 JSONObject jsonData = JSONObject.parseObject(decryptToString); //7: 支付状态的判断 如果是success就代表支付成功 if ("SUCCESS".equals(jsonData.get("trade_state"))) { // 8:获取支付的交易单号,流水号,和附属参数 String out_trade_no = jsonData.get("out_trade_no").toString(); String transaction_id = jsonData.get("transaction_id").toString(); JSONObject amount = jsonData.getJSONObject("amount");// 订单金额信息 int payMoney = amount.getIntValue("payer_total"); //实际支付金额 } result.put("code", "SUCCESS"); result.put("message", "成功"); } catch (Exception e) { result.put("code", "fail"); result.put("message", "系统错误"); e.printStackTrace(); } return result; }