微信支付APIV3

作者: 帷幕丶归心 | 来源:发表于2021-06-07 14:34 被阅读0次

    准备工作

      <dependency>
        <groupId>com.github.wechatpay-apiv3</groupId>
        <artifactId>wechatpay-apache-httpclient</artifactId>
        <version>0.2.1</version>
      </dependency>
      <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
      </dependency>
    

    1.统一下单

    private Map<String, String> wxPay(String openId, BigDecimal consume, Orders orders, String notifyUrl) throws IOException, NoSuchAlgorithmException, SignatureException, InvalidKeyException {
            //WxPayConfig.certPath 为证书存放路径,绝对路径。eg:/root/xx/xx/xx.pem
            PrivateKey privateKey = WxUtils.create().getPrivateKey(WxPayConfig.certPath);
            CloseableHttpClient client = WxUtils.create().client();
            String param = ModelOrder.WxCreateOrder.create()
                    .setAmount(new ModelOrder.WxCreateOrder.Amount(consume.intValue(), "CNY"))
                    .setMchid(WxPayConfig.mchId)
                    .setDescription(orders.getContent())
                    .setNotify_url(WxPayConfig.notifyUrl + notifyUrl)
                    .setPayer(new ModelOrder.WxCreateOrder.Payer(openId))
                    .setOut_trade_no(orders.getCode())
                    .setAppid(WxPayConfig.appId).build();
            logger.debug(param);
            Map<String, String> headers = new HashMap<>(3);
            headers.put("Accept", "application/json");
            headers.put("Content-Type", "application/json");
           //参考另一篇文章中的HttpUtils
            String ret = HttpUtils.create().headers(headers).client(client).post(WxUtils.CREATE_ORDER, param);
            ModelOrder.WxCreateOrderResult result = new Gson().fromJson(ret, new TypeToken<ModelOrder.WxCreateOrderResult>() {
            }.getType());
            String nonceStr = WxUtils.create().nonceStr(32).toUpperCase();
            String timeStamp = String.valueOf(System.currentTimeMillis() / 1000);
            String packAge = "prepay_id=" + result.getPrepay_id();
            String signType = "RSA";
            String message = WxPayConfig.appId + "\n" + timeStamp + "\n" + nonceStr + "\n" + packAge + "\n";
            logger.debug(message);
            String sign = WxUtils.create().paySign(message, privateKey);
            Map<String, String> data = new HashMap<>(6);
            data.put("appId", WxPayConfig.appId);
            data.put("timeStamp", timeStamp);
            data.put("nonceStr", nonceStr);
            data.put("package", packAge);
            data.put("signType", signType);
            data.put("paySign", sign);
            return data;
        }
    

    2.微信支付相关处理类 WxUtils.java

    public class WxUtils {
        //生成微信支付nonce使用的字符
        private static final String BASE_CHAR = "qwertyuiopasdfghjklzxcvbnm1234567890";
        //以下static final 均为微信支付所需url,自行查看文档
        public static final String CODE_SESSION = "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code";
        public static final String SEND_MESSAGE = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=ACCESS_TOKEN";
        public static final String ACCESS_TOKEN = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
        public static final String CREATE_CODE = "https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token=ACCESS_TOKEN";
        public static final String CREATE_ORDER = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi";
        public static final String REFUND = "https://api.mch.weixin.qq.com/v3/refund/domestic/refunds";
        public static final String QUERY_ORDER = "https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/{order}?mchid={mchid}";
        private WxUtils() {
        }
    
        public static WxUtils create() {
            return new WxUtils();
        }
    
        public String paySign(String message, PrivateKey key) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
            Signature sign = Signature.getInstance("SHA256withRSA");
            sign.initSign(key);
            sign.update(message.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(sign.sign());
        }
    
        public String nonceStr(int len) {
            Random random = new Random();
            StringBuilder sb = new StringBuilder();
            int length = BASE_CHAR.length();
            for (int i = 0; i < len; i++) {
                int number = random.nextInt(length);
                sb.append(BASE_CHAR.charAt(number));
            }
            return sb.toString();
        }
    
        /**
         * 获取私钥。
         *
         * @param filename 私钥文件路径  (required)
         * @return 私钥对象
         */
        public PrivateKey getPrivateKey(String filename) throws IOException {
            String content = new String(Files.readAllBytes(Paths.get(filename)), StandardCharsets.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("无效的密钥格式");
            }
        }
    
        public CloseableHttpClient client() throws IOException {
            //WxPayConfig.mchId 商户ID,WxPayConfig.v3Secret apiv3 secret
            //WxPayConfig.mchSerial 商户序列号
            PrivateKey privateKey = getPrivateKey(WxPayConfig.certPath);
            AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(
                    new WechatPay2Credentials(WxPayConfig.mchId, new PrivateKeySigner(WxPayConfig.mchSerial, privateKey)),
                    WxPayConfig.v3Secret.getBytes(StandardCharsets.UTF_8));
            WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
                    .withMerchant(WxPayConfig.mchId, WxPayConfig.mchSerial, privateKey)
                    .withValidator(new WechatPay2Validator(verifier));
            return builder.build();
        }
    }
    

    3.支付回调

    public NotifyResult invest(@RequestBody NotifyBody body) throws IOException, GeneralSecurityException {
            logger.info("余额充值支付回调:" + body.toString());
            if (StringUtils.equals("TRANSACTION.SUCCESS", body.getEvent_type())) {
                NotifyBody.Resource resource = body.getResource();
                String ret = new AesUtil(WxPayConfig.v3Secret.getBytes(StandardCharsets.UTF_8)).decryptToString(resource.getAssociated_data().getBytes(StandardCharsets.UTF_8), resource.getNonce().getBytes(StandardCharsets.UTF_8), resource.getCiphertext());
                NotifyResource result = new Gson().fromJson(ret, NotifyResource.class);
                if (StringUtils.equals(result.getTrade_state(), "SUCCESS")) {
                    //支付回调 数据解析成功后,相关处理
                }
                logger.debug(ret);
            }
            return NotifyResult.create().success();
        }
    

    4.接收回调参数类 NotifyBody.java

    public class NotifyBody {
        private String id;
        private String create_time;
        private String event_type;
        private String resource_type;
        private String summary;
        private Resource resource;
    
        public static class Resource {
            private String algorithm;
            private String ciphertext;
            private String associated_data;
            private String original_type;
            private String nonce;
    
            @Override
            public String toString() {
                return "Resource{" +
                        "algorithm='" + algorithm + '\'' +
                        ", ciphertext='" + ciphertext + '\'' +
                        ", associated_data='" + associated_data + '\'' +
                        ", original_type='" + original_type + '\'' +
                        ", nonce='" + nonce + '\'' +
                        '}';
            }
    
            public String getAlgorithm() {
                return algorithm;
            }
    
            public void setAlgorithm(String algorithm) {
                this.algorithm = algorithm;
            }
    
            public String getCiphertext() {
                return ciphertext;
            }
    
            public void setCiphertext(String ciphertext) {
                this.ciphertext = ciphertext;
            }
    
            public String getAssociated_data() {
                return associated_data;
            }
    
            public void setAssociated_data(String associated_data) {
                this.associated_data = associated_data;
            }
    
            public String getOriginal_type() {
                return original_type;
            }
    
            public void setOriginal_type(String original_type) {
                this.original_type = original_type;
            }
    
            public String getNonce() {
                return nonce;
            }
    
            public void setNonce(String nonce) {
                this.nonce = nonce;
            }
        }
    
        @Override
        public String toString() {
            return "NotifyBody{" +
                    "id='" + id + '\'' +
                    ", create_time='" + create_time + '\'' +
                    ", event_type='" + event_type + '\'' +
                    ", resource_type='" + resource_type + '\'' +
                    ", summary='" + summary + '\'' +
                    ", resource=" + resource +
                    '}';
        }
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
        public String getCreate_time() {
            return create_time;
        }
    
        public void setCreate_time(String create_time) {
            this.create_time = create_time;
        }
    
        public String getEvent_type() {
            return event_type;
        }
    
        public void setEvent_type(String event_type) {
            this.event_type = event_type;
        }
    
        public String getResource_type() {
            return resource_type;
        }
    
        public void setResource_type(String resource_type) {
            this.resource_type = resource_type;
        }
    
        public String getSummary() {
            return summary;
        }
    
        public void setSummary(String summary) {
            this.summary = summary;
        }
    
        public Resource getResource() {
            return resource;
        }
    
        public void setResource(Resource resource) {
            this.resource = resource;
        }
    }
    

    5.向微信返回结果类NotifyResult.java

    public class NotifyResult {
        private String code;
        private String message;
    
        public NotifyResult() {
        }
        public static NotifyResult create(){
            return new NotifyResult();
        }
        public NotifyResult success(){
            this.code = "SUCCESS";
            this.message = "成功";
            return this;
        }
        public NotifyResult fail(){
            this.code = "FAIL";
            this.message = "失败";
            return this;
        }
        public NotifyResult fail(String message){
            this.code = "FAIL";
            this.message = message;
            return this;
        }
    
        public String getCode() {
            return code;
        }
    
        public void setCode(String code) {
            this.code = code;
        }
    
        public String getMessage() {
            return message;
        }
    
        public void setMessage(String message) {
            this.message = message;
        }
    }
    

    6.至此 微信支付集成完毕

    相关文章

      网友评论

        本文标题:微信支付APIV3

        本文链接:https://www.haomeiwen.com/subject/iojosltx.html