小程序微信支付(詳解)

从一无所知到小程序支付开发,用了三天时间,看了很多网上的案例(主要是微信官方的文档实在是渣),下来整理一下自己的微信支付的详细步骤跟流程,写下来省的以后找不到东西。

1.前期准备

微信公众平台:https://mp.weixin.qq.com/

微信商户平台:https://pay.weixin.qq.com/index.php/core/home/login?return_url=%2F

微信支付开发文档:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_4&index=3

微信支付签名校验工具:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=20_1

小程序的开发需要在微信公众平台上注册小程序,以获取AppID和Secret,并且需要在微信商户平台中注册认证商户资质(其实就是微信对商户的备案与接口调用权限控制,)商户平台注册审核通过会给商户分配一个mch_id (10位数字字符串),并且在商户平台设置接口加密秘钥(mch_key :自己生成设置的32位随机字符串,在使用中为key)在微信支付流程中需要作为私钥进行加密使用

2.平台接入

商户平台,是企业或个人开发或使用微信支付功能必须注册的,因为这里面会有你的应用产生的所有交易(支付流水),并需要进行管理,比如退款,比如周结算,比如报表等是用来管理应用产生的支付的所有流水记录,并对接入微信支付功能的应用进行授权认证(比如小程序,公众号,H5,APP等多平台应用程序进行关联),具体关联办法是在商户平台后台对指定类型的应用进行关联绑定AppId,这个APPID是微信对H5,APP,小程序,公众号等程序认证颁发的具有唯一性,微信旗下的相关程序会有AppId和Secret两个值,作为微信对该应用的授权识别用,

3.测试开发

首先小程序的支付肯定是建立在小程序用户的授权登录后的

关于小程序的授权登录中的坑,我下一篇博文会进行详述,在此先略过,小程序的授权登录使用wx.login获取临时js_code,交给后台服务器端请求微信服务器验证js_code的有效性,验证成功返回该微信用户对该小程序的唯一标示openId,与会话标示session_key,后端将这两个值保存并传回前段,前段调用wx.getUserInfo()获取用户信息(坑1:获取用户信息自2018.5月以后不再支持弹窗wx.openAuthSetting()获取,推荐使用<button  open-type=getUserInfo> ),拿到用户信息后前段保留用户信息并将用户信息传给后端保存,后端将openId与用户绑定生成自己的用户信息记录,之后小程序前段使用wx.request()请求后台进行预付单生成调用,后台拿到请求调用微信统一下单接口。(坑2:统一下单接口是微信提供给第三方调用生成第三方订单与前端用户支付单的接口,该接口请求参数需要加密签名,且请求返回都是<XML> 格式得字符串,难点在对参数进行签名加密上,以及传递的参数上)下来贴一下排序代码、

//支付类型

String trade_type = "JSAPI"; String spbill_create_ip = HttpUtils.getIp(request);
//随机字符串

String randomString = StringUtils.getRandomString(32);

//数字签名

String sign = "";

//商品描述

String body = "用户支付的商品简述";

//商品订单号

String orderId = “自己系统生成的订单号”;

//微信支付结果回调结果通知URL

String callbackurl = wxPayCallBackUrl;

//支付金额(分) 1元 =  100分

String total_fee = "";

//微信官方文档给出将统一下单接口所需要的非空参数key进行Ascal码排序,并按排序顺序将参数名与参数值凭拼成 
// key=value&key1=value1&key2=value2...格式的待加密字符串,凭借完成需要在字符串最后面拼上"&key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 这里的KEY就是商户平台设置的API秘钥mch_key
SortedMap<String, Object> params = new TreeMap<>();
params.put("appid", appId);
params.put("mch_id", mch_Id);
params.put("nonce_str", randomString);
params.put("body", body);
params.put("out_trade_no", orderId);
params.put("openid", openId);
params.put("total_fee", total_fee);
params.put("spbill_create_ip", spbill_create_ip);
params.put("notify_url", callbackurl);
params.put("trade_type", trade_type);
//待加密字符串拼接完成后按微信要求进行MD5加密得到签名
sign = sortMapTools(params);
params.put("sign",sign );
//将所有统一下单接口需要的参数值进行xml转化拼接
//这里我用的比较笨的办法,但好处是不容易出错
String xml = "<xml>" + "<appid>" + appId + "</appid>" + "<body>" + body + "</body>" +
        "" + "<mch_id>" + mch_Id + "</mch_id>" + "<nonce_str>" + randomString + "</nonce_str>" +
        "<notify_url>" + callbackurl + "</notify_url>" + "<openid>" + openId + "</openid>" +
        "<out_trade_no>" + orderId + "</out_trade_no>" + "<spbill_create_ip>" + spbill_create_ip + "</spbill_create_ip>" +
        "<total_fee>" + Integer.parseInt(total_fee) + "" + "</total_fee>" + "<trade_type>" + trade_type + "</trade_type>" +
        "<sign>" + sign + "</sign>" + "</xml>";

String result = "";
System.out.println("xml---->" + xml);
try {
//http请求微信统一下单接口
    result = HttpUtil.doPost(wxCreatOrderAPI, xml);
} catch (Exception e) {
    logger.info("统一下单接口情求错误----------------------------------->" + result);
    e.printStackTrace();
}
//坑3.返回的全是xml字符串,且不能被JDOM,SAM,DOM4J等解析的xml
logger.info("result----------------------------------->" + result);

//生成二次签名需要的随机字符串
//没错,统一下单接口调用成功后给前端返回的的参数仍需要进行加密验签
String randomString1 = StringUtils.getRandomString(32);

if(result.contains("prepay_id")&&result.contains("<return_code><![CDATA[SUCCESS]]></return_code>")){
    String prepay_id = result.substring(result.indexOf("<prepay_id>"), result.indexOf("</prepay_id>")).substring(20,56);
//生成二次签名需要的时间戳
    Long timeStamp=System.currentTimeMillis();
    SortedMap  map=new TreeMap();
    map.put("appId",appId);
    map.put("timeStamp",timeStamp);
    map.put("nonceStr",randomString1);
//这里的package其实就是微信在自己服务器中缓存的预付单消息数据,在外界智能接触到后台调用统一下单接口返回的prepay_id(个人猜测这个应该是生成的支付单数据的key)
//这里需要注意package的value需要用"prepay_id="进行拼接,否则报错
    map.put("package","prepay_id="+prepay_id);
    map.put("signType","MD5");
    String reSign = sortMapTools(map);
    logger.info("解析订单ID值--------------------------->>>>"+prepay_id);
    logger.info("二次签名字符串------------------------->>>>"+reSign);
    map.put("paySign",reSign);
    map.put("prepay_id=",prepay_id);
    resultMap.put("code",200);
    resultMap.put("data",map);
    resultMap.put("message","请求成功");
    resultMap.put("error","{}");
    return resultMap;
}

 

到这后端在微信支付流程中的活基本就干完了,对没错,就这一个稍微复杂的交互后段就完成自己的任务了,总结就是将小程序前台的支付请求拿来自己生成一下自己的订单,然后报送给微信生成预付单,之后将微信返回的预付单进行加密验签给前端,前端识别正确的签名以及预付单ID就可以继续下来的操作,重点**支付流程** 

前端微信支付代码:

 wx.requestPayment({

          'timeStamp': data.timeStamp,

          'nonceStr': data.nonceStr,

          'package': data.package,

          'signType': 'MD5',

          'paySign': data.paySign,

          success: function (event) {  进行支付成功后的业务处理},

         fail: function(err){ 支付失败的逻辑处理}

之后说明一下小程序开发工具以为内嵌虚拟机并不能拉起微信应用所以会生成一个需要支付的二维码,这个在手机上不会这样

4.回顾感悟

微信支付中的坑不算很多,难点在于对统一下单接口调用时候的参数签名加密与对返回参数在进行二次签名加密,就是说我们的后端在收到前段的下单请求后之后的请求微信服务器统一下单接口以及返回给前端的参数都是需要签名加密的(先排序,在拼接key=xxxxxxxxxxxx,之后MD5,最后在封装xml格式数据),前端的开发流程反而更为简单易处理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
老规矩,先看本节效果图我们实现这个支付功能完全是借助小程序云开发实现的,不用搭建自己的服务器,不用买域名,不用备案域名,不用支持https。只需要一个简单的云函数,就可以轻松的实现微信小程序支付功能。核心代码就下面这些一,创建一个云开发小程序关于如何创建云开发小程序,这里我就不再做具体讲解。不知道怎么创建云开发小程序的同学,可以去翻看我之前的文章,或者看下我录制的视频:https://edu.csdn.net/course/play/9604/204528创建云开发小程序有几点注意的1,一定不要忘记在app.js里初始化云开发环境。2,创建完云函数后,一定要记得上传二, 创建支付的云函数1,创建云函数pay三,引入三方依赖tenpay我们这里引入三方依赖的目的,是创建我们支付时需要的一些参数。我们安装依赖是使用里npm 而npm必须安装node,关于如何安装node,我这里不做讲解,百度一下,网上一大堆。1,首先右键pay,然后选择在终端中打开2,我们使用npm来安装这个依赖。在命令行里执行 npm i tenpay安装完成后,我们的pay云函数多出一个package.json 文件到这里我们的tenpay依赖就安装好了。四,编写云函数pay完整代码如下//云开发实现支付 const cloud = require('wx-server-sdk')cloud.init() //1,引入支付的三方依赖 const tenpay = require('tenpay'); //2,配置支付信息 const config = ;exports.main = async(event, context) => 一定要注意把appid,mchid,partnerKey换成你自己的。到这里我们获取小程序支付所需参数的云函数代码就编写完成了。不要忘记上传这个云函数。出现下图就代表上传成功五,写一个简单的页面,用来提交订单,调用pay云函数。这个页面很简单,1,自己随便编写一个订单号(这个订单号要大于6位)2,自己随便填写一个订单价(单位是分)3,点击按钮,调用pay云函数。获取支付所需参数。下图是官方支付api所需要的一些必须参数。下图是我们调用pay云函数获取的参数,和上图所需要的是不是一样。六,调用wx.requestPayment实现支付下图是官方的示例代码这里不在做具体讲解了,完整的可以看视频。实现效果1,调起支付键盘2,支付完成3,log日志,可以看出不同支付状态的回调上图是支付成功的回调,我们可以在支付成功回调时,改变订单支付状态。下图是支付失败的回调,下图是支付完成的状态。到这里我们就轻松的实现了微信小程序支付功能了。是不是很简单啊,完整的讲解可以看视频。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值