|  |  |  | 
|---|
|  |  |  | package com.ruoyi.system.wxPay.utils; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | import com.fasterxml.jackson.core.JsonProcessingException; | 
|---|
|  |  |  | import com.fasterxml.jackson.core.type.TypeReference; | 
|---|
|  |  |  | import com.fasterxml.jackson.databind.JsonNode; | 
|---|
|  |  |  | import com.fasterxml.jackson.databind.ObjectMapper; | 
|---|
|  |  |  | import com.ruoyi.system.utils.wx.tools.WxUtils; | 
|---|
|  |  |  | import com.ruoyi.system.wxPay.model.WeixinPayProperties; | 
|---|
|  |  |  | import com.ruoyi.system.wxPay.model.WxCloseOrderModel; | 
|---|
|  |  |  | import com.ruoyi.system.wxPay.model.WxPaymentInfoModel; | 
|---|
|  |  |  | import com.ruoyi.system.wxPay.model.WxPaymentRefundModel; | 
|---|
|  |  |  | import com.ruoyi.system.wxPay.resp.NotifyV3PayDecodeRespBody; | 
|---|
|  |  |  | import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder; | 
|---|
|  |  |  | import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner; | 
|---|
|  |  |  | import com.wechat.pay.contrib.apache.httpclient.auth.Verifier; | 
|---|
|  |  |  | import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials; | 
|---|
|  |  |  | import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator; | 
|---|
|  |  |  | import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager; | 
|---|
|  |  |  | import com.wechat.pay.contrib.apache.httpclient.util.PemUtil; | 
|---|
|  |  |  | import lombok.Getter; | 
|---|
|  |  |  | import lombok.extern.slf4j.Slf4j; | 
|---|
|  |  |  | import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; | 
|---|
|  |  |  | import org.apache.http.impl.client.CloseableHttpClient; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | import javax.servlet.http.HttpServletRequest; | 
|---|
|  |  |  | import java.nio.charset.StandardCharsets; | 
|---|
|  |  |  | import java.security.PrivateKey; | 
|---|
|  |  |  | import java.util.Map; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | 
|---|
|  |  |  | checkWxConfig(); | 
|---|
|  |  |  | this.privateKey = PemUtil.loadPrivateKey(config.getV3().getPrivateKeyStream()); | 
|---|
|  |  |  | this.privateKeySigner = new PrivateKeySigner(config.getV3().getMchSerialNo(), privateKey); | 
|---|
|  |  |  | // 获取证书管理器实例 | 
|---|
|  |  |  | CertificatesManager certificatesManager = CertificatesManager.getInstance(); | 
|---|
|  |  |  | // 向证书管理器增加需要自动更新平台证书的商户信息 | 
|---|
|  |  |  | certificatesManager.putMerchant(config.getMchId(), new WechatPay2Credentials(config.getMchId(), | 
|---|
|  |  |  | this.privateKeySigner), config.getV3().getApiKey().getBytes(StandardCharsets.UTF_8)); | 
|---|
|  |  |  | // 从证书管理器中获取verifier | 
|---|
|  |  |  | this.verifier = certificatesManager.getVerifier(config.getMchId()); | 
|---|
|  |  |  | this.validator = new WechatPay2Validator(verifier); | 
|---|
|  |  |  | this.builder = WechatPayHttpClientBuilder.create() | 
|---|
|  |  |  | .withMerchant(config.getMchId(), config.getV3().getMchSerialNo(), this.privateKey) | 
|---|
|  |  |  | 
|---|
|  |  |  | * @author xiaochen | 
|---|
|  |  |  | * @date 2022-03-22 12:47 | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | public Map<String, Object> jsApi(String tradeNo, Integer amount, String openid, String notify_url, String description) { | 
|---|
|  |  |  | WxPaymentInfoModel requestBody = WxPaymentInfoModel.builder() | 
|---|
|  |  |  | .mchid(this.config.getMchId()) | 
|---|
|  |  |  | .appid(this.config.getAppId()) | 
|---|
|  |  |  | .description(description) | 
|---|
|  |  |  | .out_trade_no(tradeNo) | 
|---|
|  |  |  | .notify_url(notify_url) | 
|---|
|  |  |  | //                .attach("") | 
|---|
|  |  |  | .amount(WxPaymentInfoModel.Amount.builder().total(amount).build()) | 
|---|
|  |  |  | .payer(WxPaymentInfoModel.Payer.builder().openid(openid).build()) | 
|---|
|  |  |  | // 分不分账 | 
|---|
|  |  |  | //                .settle_info(WxPaymentInfoModel.SettleInfo.builder().profit_sharing(true).build()) | 
|---|
|  |  |  | .build(); | 
|---|
|  |  |  | // 封装基础数据 | 
|---|
|  |  |  | String reqBody = buildBaseParam(requestBody | 
|---|
|  |  |  | , this.config.getV3().getNotifyPayUrl()); | 
|---|
|  |  |  | //请求URL | 
|---|
|  |  |  | HttpEntityEnclosingRequestBase httpPost = requestPost( | 
|---|
|  |  |  | "/v3/pay/transactions/jsapi" | 
|---|
|  |  |  | , this.config.getHttpReadTimeoutMs() | 
|---|
|  |  |  | , this.config.getHttpConnectTimeoutMs() | 
|---|
|  |  |  | , reqBody); | 
|---|
|  |  |  | String repBody = result(httpClient, httpPost); | 
|---|
|  |  |  | ObjectMapper om = new ObjectMapper(); | 
|---|
|  |  |  | public Map<String, Object> jsApi(String tradeNo, Long amount, String openid, String description,String attach) { | 
|---|
|  |  |  | JsapiPrepay client = new JsapiPrepay( | 
|---|
|  |  |  | this.config.getMchId(),                    // 商户号,是由微信支付系统生成并分配给每个商户的唯一标识符,商户号获取方式参考 https://pay.weixin.qq.com/doc/v3/merchant/4013070756 | 
|---|
|  |  |  | this.config.getV3().getMchSerialNo(),         // 商户API证书序列号,如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013053053 | 
|---|
|  |  |  | this.config.getV3().getPrivateKeyPath(),     // 商户API证书私钥文件路径,本地文件路径 | 
|---|
|  |  |  | this.config.getV3().getPublicKeyId(),      // 微信支付公钥ID,如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013038816 | 
|---|
|  |  |  | this.config.getV3().getPublicKeyPath()           // 微信支付公钥文件路径,本地文件路径 | 
|---|
|  |  |  | ); | 
|---|
|  |  |  | JsapiPrepay.DirectAPIv3JsapiPrepayRequest request = new JsapiPrepay.DirectAPIv3JsapiPrepayRequest(); | 
|---|
|  |  |  | request.appid = this.config.getAppId(); | 
|---|
|  |  |  | request.mchid = this.config.getMchId(); | 
|---|
|  |  |  | request.description = description; | 
|---|
|  |  |  | request.outTradeNo = tradeNo; | 
|---|
|  |  |  | //        request.timeExpire = "2018-06-08T10:34:56+08:00"; | 
|---|
|  |  |  | request.attach = attach; | 
|---|
|  |  |  | request.notifyUrl = this.config.getCallBackUrl(); | 
|---|
|  |  |  | request.goodsTag = "WXG"; | 
|---|
|  |  |  | request.supportFapiao = false; | 
|---|
|  |  |  | request.amount = new JsapiPrepay.CommonAmountInfo(); | 
|---|
|  |  |  | request.amount.total = amount; | 
|---|
|  |  |  | request.amount.currency = "CNY"; | 
|---|
|  |  |  | request.payer = new JsapiPrepay.JsapiReqPayerInfo(); | 
|---|
|  |  |  | request.payer.openid = openid; | 
|---|
|  |  |  | try { | 
|---|
|  |  |  | JsonNode rootNode = om.readTree(repBody); | 
|---|
|  |  |  | String prepayId = rootNode.path("prepay_id").asText(); | 
|---|
|  |  |  | return wxTuneUp(this.privateKeySigner, requestBody.getAppid(), prepayId); | 
|---|
|  |  |  | } catch (JsonProcessingException e) { | 
|---|
|  |  |  | JsapiPrepay.DirectAPIv3JsapiPrepayResponse response = client.run(request); | 
|---|
|  |  |  | return wxTuneUp(this.privateKeySigner, this.config.getAppId(), response.prepayId); | 
|---|
|  |  |  | } catch (WXPayUtility.ApiException e) { | 
|---|
|  |  |  | throw new RuntimeException("获取支付数据错误!"); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | //    /** | 
|---|
|  |  |  | //     * jsApi下单 | 
|---|
|  |  |  | //     * | 
|---|
|  |  |  | //     * @param tradeNo     订单号 | 
|---|
|  |  |  | //     * @param amount      金额 分 | 
|---|
|  |  |  | //     * @param openid      openid | 
|---|
|  |  |  | //     * @param description 订单描述 | 
|---|
|  |  |  | //     * @return java.util.Map<java.lang.String, java.lang.Object> | 
|---|
|  |  |  | //     * @author xiaochen | 
|---|
|  |  |  | //     * @date 2022-03-22 12:47 | 
|---|
|  |  |  | //     */ | 
|---|
|  |  |  | //    public Map<String, Object> jsApi(String tradeNo, Integer amount, String openid, String description) { | 
|---|
|  |  |  | //        WxPaymentInfoModel requestBody = WxPaymentInfoModel.builder() | 
|---|
|  |  |  | //                .mchid(this.config.getMchId()) | 
|---|
|  |  |  | //                .appid(this.config.getAppId()) | 
|---|
|  |  |  | //                .description(description) | 
|---|
|  |  |  | //                .out_trade_no(tradeNo) | 
|---|
|  |  |  | ////                .attach("") | 
|---|
|  |  |  | //                .amount(WxPaymentInfoModel.Amount.builder().total(amount).build()) | 
|---|
|  |  |  | //                .payer(WxPaymentInfoModel.Payer.builder().openid(openid).build()) | 
|---|
|  |  |  | //                .build(); | 
|---|
|  |  |  | //        // 封装基础数据 | 
|---|
|  |  |  | //        String reqBody = buildBaseParam(requestBody | 
|---|
|  |  |  | //                , this.config.getV3().getNotifyPayUrl()); | 
|---|
|  |  |  | //        //请求URL | 
|---|
|  |  |  | //        HttpEntityEnclosingRequestBase httpPost = requestPost( | 
|---|
|  |  |  | //                "/v3/pay/transactions/jsapi" | 
|---|
|  |  |  | //                , this.config.getHttpReadTimeoutMs() | 
|---|
|  |  |  | //                , this.config.getHttpConnectTimeoutMs() | 
|---|
|  |  |  | //                , reqBody); | 
|---|
|  |  |  | //        String repBody = result(httpClient, httpPost); | 
|---|
|  |  |  | //        ObjectMapper om = new ObjectMapper(); | 
|---|
|  |  |  | //        try { | 
|---|
|  |  |  | //            JsonNode rootNode = om.readTree(repBody); | 
|---|
|  |  |  | //            String prepayId = rootNode.path("prepay_id").asText(); | 
|---|
|  |  |  | //            return wxTuneUp(this.privateKeySigner, requestBody.getAppid(), prepayId); | 
|---|
|  |  |  | //        } catch (JsonProcessingException e) { | 
|---|
|  |  |  | //            throw new RuntimeException("获取支付数据错误!"); | 
|---|
|  |  |  | //        } | 
|---|
|  |  |  | //    } | 
|---|
|  |  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /** | 
|---|