当前位置:首页 » 《随便一记》 » 正文

微信小程序对接微信支付详细教程

24 人参与  2022年07月21日 16:58  分类 : 《随便一记》  评论

点击全文阅读


小程序 微信支付官方文档

https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_11&index=2

https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_8_0.shtml

前提

在进行对接微信支付之前,我们首先需要将以下几点准备好:

申请APPID申请商户号小程序开通微信支付,绑定已经申请好的商户号。登录小程序后台(mp.weixin.qq.com)。点击左侧导航栏的微信支付,在页面中进行开通。(开通申请要求小程序已发布上线)

注意事项

appid必须为最后拉起收银台的小程序appid;mch_id为和appid成对绑定的支付商户号,收款资金会进入该商户号;trade_type请填写JSAPI;openid为appid对应的用户标识,即使用wx.login接口获得的openid。

本文主要记录后端步骤,前端步骤无非就是获取后端数据然后调用提供的API进行支付,大家可自行查看官方文档。

1. 整体流程

小程序支付的交互图如下:清晰图片可以到官网查看.

image-20220405142409539

商户系统和微信支付系统主要交互:

1、小程序内调用登录接口,获取到用户的openid,api参见公共api【小程序登录API】

2、商户server调用支付统一下单,api参见公共api【统一下单API】

3、商户server调用再次签名,api参见公共api【再次签名】

4、商户server接收支付通知,api参见公共api【支付结果通知API】

5、商户server查询支付结果,如未收到支付通知的情况,商户后台系统可调用【查询订单API】 (查单实现可参考:支付回调和查单实现指引)

2. 后端项目搭建

大致了解流程之后,我们就可以进行代码的编写了,首先大家自行创建一个Spring Boot项目即可。这里就不演示了,大家自行根据自己的需求搭建即可,需要注意的是我们需要添加微信支付的sdk以及相关依赖。

 <!--微信支付请求-->        <dependency>            <groupId>com.github.wxpay</groupId>            <artifactId>wxpay-sdk</artifactId>            <version>0.0.3</version>        </dependency>        <dependency>            <groupId>commons-codec</groupId>            <artifactId>commons-codec</artifactId>            <version>1.13</version>        </dependency>        <dependency>            <groupId>org.jdom</groupId>            <artifactId>jdom</artifactId>            <version>1.1.3</version>        </dependency>        <dependency>            <groupId>com.thoughtworks.xstream</groupId>            <artifactId>xstream</artifactId>            <version>1.4.10</version>        </dependency>        <dependency>            <groupId>com.google.zxing</groupId>            <artifactId>core</artifactId>            <version>3.1.0</version>        </dependency>        <dependency>            <groupId>com.fasterxml.jackson.dataformat</groupId>            <artifactId>jackson-dataformat-avro</artifactId>        </dependency>        <dependency>            <groupId>org.apache.commons</groupId>            <artifactId>commons-lang3</artifactId>            <version>3.6</version>        </dependency>        <dependency>            <groupId>org.apache.httpcomponents</groupId>            <artifactId>httpclient</artifactId>            <version>4.5.13</version>        </dependency>        <dependency>            <groupId>commons-httpclient</groupId>            <artifactId>commons-httpclient</artifactId>            <version>3.1</version>        </dependency>

3. 获取open_id

我们在小程序端通过login方法获取code,然后调用我们编写的接口请求微信服务端获取open_id。

该步骤具体可以查看 微信小程序对接微信登录 。

wx.login({  success (res) {    if (res.code) {      //发起网络请求      wx.request({        url: 'https://example.com/onLogin',        data: {          code: res.code        }      })    } else {      console.log('登录失败!' + res.errMsg)    }  }})

4. 小程序调起支付API

小程序调起支付数据签名字段列表:

字段名变量名必填类型示例值描述
小程序IDappIdStringwxd678efh567hg6787微信分配的小程序ID
时间戳timeStampString1490840662时间戳从1970年1月1日00:00:00至今的秒数,即当前的时间
随机串nonceStrString5K8264ILTKCH16CQ2502SI8ZNMTM67VS随机字符串,不长于32位。推荐随机数生成算法
数据包packageStringprepay_id=wx2017033010242291fcfe0db70013231072统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=wx2017033010242291fcfe0db70013231072
签名方式signTypeStringMD5签名类型,默认为MD5,支持HMAC-SHA256和MD5。注意此处需与统一下单的签名类型一致

举例如下:

paySign = MD5(appId=wxd678efh567hg6787&nonceStr=5K8264ILTKCH16CQ2502SI8ZNMTM67VS&package=prepay_id=wx2017033010242291fcfe0db70013231072&signType=MD5&timeStamp=1490840662&key=qazwsxedcrfvtgbyhnujmikolp111111) = 22D9B4E54AB1950F51E0649E8810ACD6

从官方文档给出的参数可以看出,小程序调用支付API,有一些参数需要我们从后端接口返回,所以我们来进行后端支付接口的编写。

5. 下单及回调接口

实现步骤

定义配置类 保存支付相关参数定义支付接口,组装数据发起请求小程序调用支付接口

相关配置类,签名,随机字符串的代码在文末给出,本文就不贴出来了。

@RestController@RequestMapping(value = "/api/v1")public class WXPayController {    /**     * 下单     */    @RequestMapping(            value = "/weixin/payment",            method = RequestMethod.POST    )    public Map payment() {        Map<String, Object> map = new HashMap<>();        String money = "10";        String title = "商品名字";        try {            OrderInfo order = new OrderInfo();            order.setAppid(Configure.getAppID());            order.setMch_id(Configure.getMch_id());            order.setNonce_str(RandomStringGenerator.getRandomStringByLength(32));            order.setBody(title);            order.setOut_trade_no(RandomStringGenerator.getRandomStringByLength(32));            order.setTotal_fee(Integer.parseInt(money));     // 该金钱其实10 是 0.1元            order.setSpbill_create_ip("127.0.0.1");            order.setNotify_url(Configure.getNotify_url());            order.setTrade_type(Configure.getTrade_type());            //这里直接使用当前用户的openid            order.setOpenid("ohfYG5O2mdXZLoszDAWwqtodOZRM");            order.setSign_type("MD5");            //生成签名            String sign = Signature.getSign(order);            order.setSign(sign);            String result = HttpRequest.sendPost(Configure.getUrl(), order);            System.out.println(result);            XStream xStream = new XStream();            xStream.alias("xml", OrderReturnInfo.class);            OrderReturnInfo returnInfo = (OrderReturnInfo) xStream.fromXML(result);            // 二次签名            if ("SUCCESS".equals(returnInfo.getReturn_code()) && returnInfo.getReturn_code().equals(returnInfo.getResult_code())) {                SignInfo signInfo = new SignInfo();                signInfo.setAppId(Configure.getAppID());                long time = System.currentTimeMillis() / 1000;                signInfo.setTimeStamp(String.valueOf(time));                signInfo.setNonceStr(RandomStringGenerator.getRandomStringByLength(32));                signInfo.setRepay_id("prepay_id=" + returnInfo.getPrepay_id());                signInfo.setSignType("MD5");                //生成签名                String sign1 = Signature.getSign(signInfo);                Map<String, String> payInfo = new HashMap<>();                payInfo.put("timeStamp", signInfo.getTimeStamp());                payInfo.put("nonceStr", signInfo.getNonceStr());                payInfo.put("package", signInfo.getRepay_id());                payInfo.put("signType", signInfo.getSignType());                payInfo.put("paySign", sign1);                map.put("status", 200);                map.put("msg", "统一下单成功!");                map.put("data", payInfo);                // 此处可以写唤起支付前的业务逻辑                // 业务逻辑结束 回传给小程序端唤起支付                return map;            }            map.put("status", 500);            map.put("msg", "统一下单失败!");            map.put("data", null);            return map;        } catch (Exception e) {            e.printStackTrace();        }        return null;    }    /**     * 微信小程序支付成功回调函数     */    @RequestMapping(value = "/weixin/callback")    public void wxNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {        BufferedReader br = new BufferedReader(new InputStreamReader((ServletInputStream) request.getInputStream()));        String line = null;        StringBuilder sb = new StringBuilder();        while ((line = br.readLine()) != null) {            sb.append(line);        }        br.close();        //sb为微信返回的xml        String notityXml = sb.toString();        String resXml = "";        System.out.println("接收到的报文:" + notityXml);        Map map = PayUtil.doXMLParse(notityXml);        String returnCode = (String) map.get("return_code");        if ("SUCCESS".equals(returnCode)) {            //验证签名是否正确            Map<String, String> validParams = PayUtil.paraFilter(map);  //回调验签时需要去除sign和空值参数            String validStr = PayUtil.createLinkString(validParams);//把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串            String sign = PayUtil.sign(validStr, Configure.getKey(), "utf-8").toUpperCase();//拼装生成服务器端验证的签名            // 因为微信回调会有八次之多,所以当第一次回调成功了,那么我们就不再执行逻辑了            //根据微信官网的介绍,此处不仅对回调的参数进行验签,还需要对返回的金额与系统订单的金额进行比对等            if (sign.equals(map.get("sign"))) {                /**此处添加自己的业务逻辑代码start**/                // bla bla bla....                /**此处添加自己的业务逻辑代码end**/                //通知微信服务器已经支付成功                resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"                        + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";            } else {                System.out.println("微信支付回调失败!签名不一致");            }        } else {            resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"                    + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";        }        System.out.println(resXml);        System.out.println("微信支付回调数据结束");        BufferedOutputStream out = new BufferedOutputStream(                response.getOutputStream());        out.write(resXml.getBytes());        out.flush();        out.close();    }}

6. 项目地址

微信支付案例

具体代码大家自行查看,相关商户号没有给出,大家自行申请。


点击全文阅读


本文链接:http://zhangshiyu.com/post/43648.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1