微信支付JSAPI V3

直接上干货: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;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值