public class WxPayUtil { private CloseableHttpClient httpClient; private String mchid; private String appid; private Signature sign; private String mchSerialNo; private String apiV3Key; PrivateKey merchantPrivateKey ; AesUtil aesUtil ; /** * * @param privateKeyPath 商户私钥 路径 * @param mchId 商户号 * @param mchSerialNo 商户证书序列号 * @param apiV3Key */ public WxPayUtil(HttpClientConnectionManager poolingHttpClientConnectionManager, String privateKeyPath, String mchId, String mchSerialNo, String apiV3Key, String appid ) { System.out.println("初始化微信支付工具"); merchantPrivateKey = PemUtil.loadPrivateKey(this.getClass().getResourceAsStream(privateKeyPath)); System.out.println(poolingHttpClientConnectionManager); //建立微信连接 this.httpClient = WechatPayHttpClientBuilder.create() .withMerchant(mchId, mchSerialNo, merchantPrivateKey) .withValidator(new WechatPay2Validator(getVerifier(mchId,mchSerialNo,apiV3Key,merchantPrivateKey))) .setConnectionManager(poolingHttpClientConnectionManager) .build(); this.mchid=mchId; this.appid=appid; this.mchSerialNo=mchSerialNo; this.apiV3Key=apiV3Key; aesUtil=new AesUtil(apiV3Key.getBytes(StandardCharsets.UTF_8)); try { this.sign = Signature.getInstance("SHA256withRSA"); sign.initSign(merchantPrivateKey); } catch (NoSuchAlgorithmException | InvalidKeyException e) { e.printStackTrace(); } } private AutoUpdateCertificatesVerifier getVerifier(String mchId, String mchSerialNo,String apiV3Key,PrivateKey merchantPrivateKey){ return new AutoUpdateCertificatesVerifier( new WechatPay2Credentials(mchId, new PrivateKeySigner(mchSerialNo, merchantPrivateKey)), apiV3Key.getBytes(StandardCharsets.UTF_8)); } /** * 预下单 * @param description 商品描述 * @param orderId 订单id * @param totalMoney 总金额 * @param openid 用户的openid * @param wx_callback_url 回调地址 * @return * @throws IOException * @throws SignatureException */ public String createPreOrder (String description, String orderId, Integer totalMoney, String openid,String wx_callback_url) throws IOException { HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi"); 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",mchid) .put("appid", appid) .put("description", description) .put("notify_url", wx_callback_url) .put("out_trade_no", orderId); rootNode.putObject("amount") .put("total", totalMoney);//totalMoney !!!!!!!先写死1分钱 rootNode.putObject("payer") .put("openid", openid); 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()); JsonNode node=objectMapper.readTree(bodyAsString); JsonNode prepayId = node.get("prepay_id"); if (prepayId==null){ //预下单为空 处理 返回报错 System.out.println(bodyAsString); return null; } return prepayId.asText(); } //下单 public Map<String, Object> createOrder(String prepayId) throws SignatureException { //拿到预下单 StringBuilder builder = new StringBuilder(); // 小程序appId String timestamp=System.currentTimeMillis()/1000+"";// 时间戳 单位秒 String nonce= RandomUtils.getRandomStr()+RandomUtils.getRandomStr(); //32 位随机字符串 builder.append(appid).append("\n"); builder.append(timestamp).append("\n"); builder.append(nonce).append("\n"); builder.append("prepay_id=").append(prepayId).append("\n");//订单详情扩展字符串 预付款id // System.out.println("明文"+builder); //立志"prepay_id=wx201410272009395522657a690389285100" String paySign = this.paySign(builder.toString().getBytes()); //签名 Map<String, Object> result = new HashMap<>(); result.put("timeStamp",timestamp); result.put("nonceStr",nonce); result.put("package","prepay_id="+prepayId); result.put("signType","RSA"); result.put("paySign",paySign); return result; } private String paySign(byte[] message) throws SignatureException { if (sign!=null){ sign.update(message); return Base64.getEncoder().encodeToString(sign.sign()); } return null; } //验签 public Boolean checkSign(HttpServletRequest request,String body){ String wxTimestamp=request.getHeader("Wechatpay-Timestamp"); //时间戳 String wxNonce=request.getHeader("Wechatpay-Nonce"); //随机字符串 String wxSignture=request.getHeader("Wechatpay-Signature"); //签名 String wxSerial=request.getHeader("Wechatpay-Serial"); //序列号 if (wxTimestamp==null||wxNonce==null||wxSignture==null||wxSerial==null){ return false; } System.out.println("请求头都有数据"); StringBuilder signStr=new StringBuilder(); signStr.append(wxTimestamp).append("\n"); signStr.append(wxNonce).append("\n"); signStr.append(body).append("\n"); return getVerifier(mchid,mchSerialNo,apiV3Key,merchantPrivateKey).verify(wxSerial, signStr.toString().getBytes(StandardCharsets.UTF_8), wxSignture); } //回调解密 public String decode(Map<String,Object> body){ Object resource = body.get("resource"); if (resource==null){ return null; } Map<String, Object> map = (Map)resource; Object ciphertext = map.get("ciphertext"); Object associatedData = map.get("associated_data"); Object nonce = map.get("nonce"); String json = null; try { //解密 json = this.aesUtil.decryptToString(associatedData.toString().getBytes(StandardCharsets.UTF_8), nonce.toString().getBytes(StandardCharsets.UTF_8), ciphertext.toString()); } catch (GeneralSecurityException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return json; } public int closeOrder(String orderId) throws IOException { HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/"+orderId+"/close"); 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",mchid); objectMapper.writeValue(bos, rootNode); httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8")); CloseableHttpResponse response = httpClient.execute(httpPost); return response.getStatusLine().getStatusCode(); } }