微信公众号-JSAPI支付

微信公众号-JSAPI支付

微信公众号-JSAPI支付

1、微信公众号配置

https://mp.weixin.qq.com/cgi-bin/home

① 开通网页授权域名(前置条件:需开通网页授权接口权限)


②暴露网络授权域名


③获取基本配置中的AppID、AppSecret


④微信支付关联商户号



2、微信支付配置

https://pay.weixin.qq.com/

① 配置API证书 获取证书序列号


②获取正式序列号



③设置APIV3秘钥


④ 产品中心—开通JSAPI支付



⑤添加支付域名配置


⑥暴露域名


⑦AppId账号设置-商户关联公众号



程序配置

必要配置信息:

公众号appId

公众号appSecret

商户id

证书序列号

商户API秘钥

①配置yml文件


② 微信支付平台下载的秘钥证书放入项目resources目录下



主要流程及代码实现

①前端通过url获取code

(url参数配置)

Appid:公众号的appid

Redirect_uri:重定向至微信支付调用接口

Scope:snsapi_base(授权方式 无需弹窗静默授权)

https://open.weixin.qq.com/connect/oauth2/authorize?appid=xx&redirect_uri=xxx&response_type=code&scope=snsapi_base&state=STATE&connect_redirect=1#wechat_redirect


②通过前端获取的code,传入指定支付接口(Redirect_uri),获取openId

1)通过appID、appSecret、code构建请求URL,解析返回结果获取openId


 public static String getOpenId(String code) throws Exception {

        // 构建请求URL

        String requestUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + APP_ID

                + "&secret=" + APP_SECRET

                + "&code=" + code

                + "&grant_type=authorization_code";


        // 发送HTTP GET请求

        URL url = new URL(requestUrl);

        HttpURLConnection connection = (HttpURLConnection) url.openConnection();

        connection.setRequestMethod("GET");

        int responseCode = connection.getResponseCode();


        if (responseCode == HttpURLConnection.HTTP_OK) { // 请求成功

            BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));

            StringBuilder response = new StringBuilder();

            String line;

            while ((line = in.readLine()) != null) {

                response.append(line);

            }

            in.close();


            // 解析JSON响应,获取openid

            String jsonResponse = response.toString();

            JsonObject jsonObject = new Gson().fromJson(jsonResponse, JsonObject.class);

            String openid = jsonObject.get("openid").getAsString();

            return openid;

        } else {

            throw new Exception("HTTP GET请求失败:" + responseCode);

        }


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

②获取到openId后,构建请求参数


 log.info("code:{}", code);

        String openId = WXGetOpenIdUtil.getOpenId(code);

        //请求URL

        HttpPost httpPost = new HttpPost(WxPayJsApiConstant.JS_API_URL);

        // 请求body参数

        WxPayJsApiAmountBO amount = new WxPayJsApiAmountBO();

        amount.setTotal(1);//总金额

        amount.setCurrency("CNY");//货币类型


        WxPayPayerBO payer = new WxPayPayerBO();

        payer.setOpenid(openId);//openId


        WxPayJsApiOrderBO request = new WxPayJsApiOrderBO();

        request.setMchid(mchId);//商户号

        String out_trade_no = DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_PATTERN);

        request.setOut_trade_no(out_trade_no);//生成的订单号

        request.setAttach("--非必填数据--");//附加信息

        request.setAppid(appId);//appId

        request.setDescription("停车费用");//描述

        request.setNotify_url(notifyUrl);//异步接收微信支付结果通知的回调地址

        request.setAmount(amount);//订单金额信息:总金额 货币类型

        request.setPayer(payer);//openId如何获取


        StringEntity entity = new StringEntity(JSONUtil.toJsonStr(request), "utf-8");

        entity.setContentType("application/json");

        httpPost.setEntity(entity);

        httpPost.setHeader(WxPayJsApiHeaderConstant.HTTP_HEADER_ACCEPT, WxPayJsApiHeaderConstant.HTTP_HEADER_ACCEPT_VAL);


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

其中initCloseableHttpClientV3方法为:读取resources下的apiclient_key.pem密钥文件 获取秘钥 构建请求信息


    /**

     * 构造 - 通用CloseableHttpClient(定时更新平台证书功能)

     **/

    protected CloseableHttpClient initCloseableHttpClientV3() throws IOException, HttpCodeException, GeneralSecurityException, NotFoundException {

        // 获取 - 秘钥证书信息

        PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(new FileInputStream(WxPayJsApiHttpUtil.getResourcesPath() + "apiclient_key.pem"));

        // 获取 - 证书管理器实例

        CertificatesManager certificatesManager = CertificatesManager.getInstance();


        // 操作 - 向证书管理器增加需要自动更新平台证书的商户信息

        certificatesManager.putMerchant(mchId, new WechatPay2Credentials(mchId,

                new PrivateKeySigner(mchSerialNo, merchantPrivateKey)), apiV3Key.getBytes(StandardCharsets.UTF_8));

        // ... 若有多个商户号,可继续调用putMerchant添加商户信息

        // 操作 - 从证书管理器中获取verifier

        Verifier verifier = certificatesManager.getVerifier(mchId);

        WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()

                .withMerchant(mchId, mchSerialNo, merchantPrivateKey)

                .withValidator(new WechatPay2Validator(verifier));


        // 构造通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新

        return builder.build();

    }


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

构建完成后,调用微信JSAPI下单地址httpPost: https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi


 // 构建 - 请求信息

        CloseableHttpClient closeableHttpClient = initCloseableHttpClientV3();

        // 操作 - 完成请求

        CloseableHttpResponse response = closeableHttpClient.execute(httpPost);

        String bodyAsString = EntityUtils.toString(response.getEntity());

        System.out.println(bodyAsString);

        try {

            int statusCode = response.getStatusLine().getStatusCode();

            if (statusCode == 200) {

                JsonObject jsonObject = new Gson().fromJson(bodyAsString, JsonObject.class);

                //获取微信支付中的预支付id

                String prepayId = jsonObject.get("prepay_id").getAsString();

                System.out.println("success,return body = " + EntityUtils.toString(response.getEntity())

                        + "prepay_id = " + prepayId);

            } else if (statusCode == 204) {

                System.out.println("success");

            } else {

                System.out.println("failed,resp code = " + statusCode + ",return body = " + EntityUtils.toString(response.getEntity()));

                throw new IOException("request failed");

            }

        } finally {

            response.close();

            closeableHttpClient.close();

        }

        // 构造 - 响应信息 prepay_id

        WxPayJsApiPreVO result = convertWxPayJsApiPreInfo((String) JSONUtil.parseObj(bodyAsString).get(WxPayJsApiOtherConstant.HTTP_OTHER_PREPAY_ID));

        System.out.println("result -> " + JSONUtil.toJsonStr(result));

        return result;


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

其中convertWxPayJsApiPreInfo方法获取JSAPI加密串,构造响应信息result


    protected WxPayJsApiPreVO convertWxPayJsApiPreInfo(String prepayId) throws Exception {

        logger.info("[开始]预支付信息-prepayId : {}", prepayId);

        // 构建 - 相关参数

        String time = String.valueOf(System.currentTimeMillis() / 1000);

        String nonceStr = UUID.randomUUID().toString().replace("-", "");

        String packageStr = StrUtil.format(WxPayJsApiConstant.SIGN_PACKAGE_STR, prepayId);

        // 构建 - 签名信息

        ArrayList<String> list = new ArrayList<>();

        list.add(appId);

        list.add(time);

        list.add(nonceStr);

        list.add(packageStr);


        // 操作 - 签名

        String packageSign = wxPayJsApiSignUtil.signV3(WxPayJsApiSignUtil.buildSignMessage(list).getBytes());


        // 构建 - 响应信息

        WxPayJsApiPreVO result = new WxPayJsApiPreVO();

        result.setWxAppId(appId);

        result.setWxTimeStamp(time);

        result.setWxNonceStr(nonceStr);

        result.setWxPackage(packageStr);

        result.setWxSignType(WxPayJsApiConstant.SIGN_TYPE);

        result.setWxPaySign(packageSign);

        logger.info("[结束]预支付信息-WxPayJsApiPreVO : {}", JSONUtil.toJsonStr(result));

        return result;

    }


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

返回预支付相关信息 Result示例参数:

{“status”:200,“msg”:“OK”,“data”:{“wxAppId”:“xxx”,“wxTimeStamp”:“xxx”,“wxNonceStr”:“xxxx”,“wxPackage”:"prepay_id=“xxxx”,“wxSignType”:“RSA”,“wxPaySign”:“xxxx”}}

③Result返回给前端,前端调用WeixinJSBridge方法,完成微信支付


1. function onBridgeReady() {  

2.     WeixinJSBridge.invoke('getBrandWCPayRequest', {  

3.         "appId": "xxx",     //公众号ID,由商户传入       

4.         "timeStamp": "xxx",     //时间戳,自1970年以来的秒数       

5.         "nonceStr": "xxx",      //随机串       

6.         "package": "prepay_id=xxx",  

7.         "signType": "RSA",     //微信签名方式:       

8.         "paySign": "xxx" //微信签名   

9.     },  

10.     function(res) {  

11.         if (res.err_msg == "get_brand_wcpay_request:ok") {  

12.             // 使用以上方式判断前端返回,微信团队郑重提示:  

13.             //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。  

14.         }  

15.     });  

16. } 



1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

④微信回调 支付后微信向改地址发送支付结果通知


1. //读取微信回调的内容  

2. InputStream inStream = request.getInputStream();  

3. ByteArrayOutputStream outSteam = new ByteArrayOutputStream();  

4. byte[] buffer = new byte[1024];  

5. int len;  

6. while ((len = inStream.read(buffer)) != -1) {  

7.     outSteam.write(buffer, 0, len);  

8. }  

9. String resultXml = new String(outSteam.toByteArray(), "utf-8");  

10. outSteam.close();  

11. inStream.close();  

12. //xml转成map  

13. Map<String, String> params = WXPayUtil.xmlToMap(resultXml);  

14. Map<String, String> return_data = new HashMap<>(); //返回给微信信息  

15. if ("SUCCESS".equals(params.get("return_code"))) { //返回成功 付款成功  

16.     String outTradeNo = params.get("out_trade_no"); //返回的商户订单号  

17.     Integer totalFee = Integer.parseInt(params.get("total_fee")); //总金额  

18.     ParkingBasicInfo parkingBasicInfo = parkingBasicInfoService.lambdaQuery().eq(ParkingBasicInfo::getOutTradeNo, outTradeNo).one();  

19.     if (ObjectUtil.isNotEmpty(parkingBasicInfo)) {  

20.         if (totalFee.equals(parkingBasicInfo.getPayMoney())) {  

21.             String paymentTime = params.get("time_end"); //支付完成时间  

22.             //发票表添加支付时间  

23.             String transactionId = params.get("transaction_id"); //微信支付订单号  

24.             //支付成功后修改订单信息 paymentTime transactionId微信支付订单号  

25.         }  

26.     }  

27.     //正确返回给微信  

28.     return_data.put("return_code", "SUCCESS");  

29.     return_data.put("return_msg", "OK");  

30.     return WXPayUtil.mapToXml(return_data);  

31. }  

32. // 支付失败  

33. return_data.put("return_code", "FAIL");  

34. return_data.put("return_msg", "return_code不正确");  

35. return WXPayUtil.mapToXml(return_data);


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36


————————————————


                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

                        

原文链接:https://blog.csdn.net/qq_43890604/article/details/136938311


<以上资讯仅供参考,如果您需解决具体问题,建议您关注作者;如果有软件产品开发需求,可在线咨询加速度产品经理获取方案和报价>

****更多行业产品开发方案,请关注jsudo加速度 https://www.jsudo.com***

【加速度jsudo(www.jsudo.com)】是国内知名企业数字化建设提供商,为企业提供电商平台搭建(多种模式电商平台搭建:B2B/B2B2C/B2C/O2O/新零售等)、智慧园区建设、数字化营销、人才外包等服务,点击这里查看了解更多行业解决方案。

相关文章

评论 (0)

上一页 下一页

我要点评

您还未登录,无法发表评论!

最新发布