花了几天时间写小程序的支付模块界面。我可能在微信官方账号有一些开发的经验,但是我没有进入太多的漏洞。我想在这里记录整个过程。
一、移动小程序微信支付的图片:
相信会查百度的同学对文档的描述基本都不是很了解。下面我就简单总结一下业务逻辑的全过程。
微信小程序的商家系统一般以界面的形式开发,小程序通过调用与后端约定的界面来传递参数和接收数据。在小程序支付中,我们还需要与微信服务器进行交互。过程大致是这样的:
1.小程序调用登录界面获取代码,代码被传递给商家服务器获取用户的openID
我们知道在微信平台中,同一个微信官方账号的openid是不一样的,是用户标识的id,也就是说我们用openID来区分不同的用户,有微信开发基础的人应该都很熟悉。为了知道谁在付费,需要先获取当前用户的openid,那么应该如何获取openID呢?请看下图:
小程序调用wx.login()获取临时登录证书代码,并将其发送回开发人员服务器。开发人员服务器交换用户唯一标识符openid和会话密钥session_key的代码。你看不懂吗?别担心,让我慢慢解释。这个业务流程大致是你必须先在小程序的代码中调用wx.login()从微信获取代码,然后通过请求将代码发送给商家服务器,然后商家服务器会通过骚操作向微信服务器索要session_key和openID。
伪代码如下(小程序端):
gettoken 3360 function(){//调用登录接口wx . log in({ success 3360 function(RES){ varcode=RES . code;Wx.request({ url:商户服务器接口地址,data: {code:code},method:' post ',success 3360 function(RES){ wx . setstorageync(' token ',RES . data . token);//存在于小程序缓存中},fail : function(RES){ console . log(RES . data);}})}}}调用这几行代码从微信服务器获取代码,并发送到商家服务器。请记住,最好使用post在此发送请求。我不应该谈论安全性,因为我们避免其他人滥用接口,所以我们使用令牌进行验证。并将商家服务器返回的令牌存储在小程序缓存中。
那么服务器应该怎么做呢?
我们使用小程序提交的代码、小程序的APPID、APPSECRET和下面的url,并使用curl发出get请求。
https://api.weixin.qq.com/sns/jscode2session?appid=APPIDsecret=SECRETjs _ code=JSCODEgrant _ type=authorization _ code
返回的数据是一个json对象,使用json_decode(JSON,true)将其解析为一个数组。数据包括用户的openID和session_key。我们得到之后,应该把openID存储在数据库中,它代表了用户的身份,那么应该如何生成令牌呢?
二.令牌生成和缓存
我们根据一个用户表把id和openid关联起来,openID对应的id就是用户的uid,所以我们可以这样封装
//要缓存的数据数组$ cacheValue=$ result//包括openID和session _ key $ cache value[' uid ']=$ uid;//用户id $ cache value[' scope ']=scope num 33603360 user;//我们可以选择redis、memcache、文件缓存等。并以键值方式存储它们。记得设置到期时间。这里,我们使用token来赋值,token可以这样生成:
//获取32位随机字符串$ str=getRandChar(32);//通过自定义方法生成32位随机字符串//用MD5 $ timestamp=$ _ server[' request _ time _ float ']加密三组字符串;//salt $ salt=config(' secure . token _ salt ');//随机字符串//返回令牌返回MD5 ($ str)。$时间戳。$盐);该算法基本保证了令牌的唯一性。因为该值是openID和session_key所在的数组,所以我们需要在存储之前将该数组转换为json。将来需要openID或者uid的时候,可以直接通过取数缓存来取数。
第三,调用统一订单界面,获取预付费_id,再次签名
完成订单操作后,如何让用户支付订单费用?这里是重点,我会一步步说出来:
1.下载微信JS-SDK:
(https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?篇=11_1)
解压并打开到lib文件夹:
我们需要将文件放入框架中的lib中。例如,如果我使用tp5,我会将它们放在extend下,最好在extend下构建子文件夹。其中WxPay.Api.php是入口,WxPay.Config.php是配置文件。安装后需要进行一些更改。在WxPay.Config.php把下列物品换成你的。
然后问WxPay.Api.php的WxPay.Notify.php,如图:
首先,将某个控制器或服务层中的代码用Loader:import()引入WxPay.Api.php,相当于引入了5个代码。
2.调用统一订购api
在这里,你怎么写一个关于买卖商品的小程序,所以你需要在付款前再次检查库存,因为用户在下单后可能不会立即付款,如果在付款期间库存没有了,就会出现问题。我不会过多谈论业务逻辑,这取决于您编写代码的严谨性。
在我们介绍了上面的文件之后,首先实例化这个类WxPayUnifiedOrder,并通过调用相应的方法传入所需的参数。
伪代码如下:
//调用微信支付统一订单界面$ wxoorderdata=new wxpayunified order();//设置相关参数$ wxoorderdata-setout _ trade _ no($ this-order no);$ wxoorderdata-setrade _ type(' JSAPI ');$ wxoorderdata-SetTotal _ fee($ total price * 100);//这里的价格单位是$ wxoorderdata-set body(' Mc ');$ wxoorderdata-setpenid($ open id);$ wxoorderdata-SetNotify _ URL(config(' secure . pay _ back _ URL '));//在支付回拨中,第一个是你的订单号,订单号的生成方式可以自定义。第二个是死参数,第三个是订单总价,第四个是中文的话要转码的名字,第四个是openID,这个时候可以从缓存中检索。最后一个是支付回拨,支付成功后微信要访问的地址。它必须可由公共网络访问,或者您可以使用ngrok来反向代理和转发本地服务器。
设置好参数后,直接调用SDK的方法
$ wxoorder= wxpayapi :3360 unified order($ wxoorderdata);如果参数中没有错误,返回的数据将包含predate _ id,这是我们需要的参数。
3.再次签名
//提交JSAPI输入对象$ jsapipaydata=new wxpayjsapipaye();//set appid $ jsapipaydata-set appid(config(' wx . app _ id '));//timeStamp $ jsApiPayData-SetTimeStamp((字符串)time());//随机字符串$ randstr=MD5 (time()。mt _ rand (0,1000));$ jsApiPayData-SetNonceStr($ randStr);//数据报$ jsapipaydata-setpackage('预付费_ id=')。$ wxoorder['预付费_ id ']);//type $ jsApiPayData-SetSignType(' MD5 ');//生成签名$ $ sign=$ jsApiPayData-MakeSign();//获取签名数组$ sign data=$ jsapipaydata-getvalues();//添加字段pay sign $ sign data[' pay sign ']=$ sign;//删除signData中未设置的app_Id字段($ sign data[' appid ']);返回$ signData重新签名后,这五个参数被返回给小程序。
第四,小程序获得五个参数后,对支付进行认证和调整
伪代码(小程序)
//提交JSAPI输入对象$ jsapipaydata=new wxpayjsapipaye();//set appid $ jsapipaydata-set appid(config(' wx . app _ id '));//timeStamp $ jsApiPayData-SetTimeStamp((字符串)time());//随机字符串$ randstr=MD5 (time()。mt _ rand (0,1000));$ jsApiPayData-SetNonceStr($ randStr);//数据报$ jsapipaydata-setpackage('预付费_ id=')。$ wxoorder['预付费_ id ']);//type $ jsApiPayData-SetSignType(' MD5 ');//生成签名$ $ sign=$ jsApiPayData-MakeSign();//获取签名数组$ sign data=$ jsapipaydata-getvalues();//添加字段pay sign $ sign data[' pay sign ']=$ sign;//删除signData中未设置的app_Id字段($ sign data[' appid ']);返回$ signData如果一切正常,二维码会显示在微信开发者工具中。
如果在真机上测试,付款页面会直接弹出。小程序会直接显示支付成败页面,然后微信服务器会开始访问我们之前设置的支付回拨地址推送支付结果,并根据结果更新订单状态。这里不写业务逻辑,只是说说而已。
第五,支付回拨
实际上,我们需要重写WxPayNotify类的NotifyProcess方法。这里,请记住Loader:impor()引入了那个入口类。
/* * * * *回调方法条目,可以被子类覆盖。*注:* 1。微信回拨超时为2s,建议用户使用异步处理流程,确认成功后立即回复微信服务器。* 2.当通话失败或收到的包未确认时,微信服务器会开始重试。确保您的回调可以重新输入由* @ param array $数据回调解释的参数。* @param string $msg如果回调处理失败,您可以向此方法输出错误消息。* @返回true回调在不继续回调的情况下完成。True回调处理未完成,回调需要继续*/public function notify process($ data,$ msg) {//todo user base,这个方法需要在这个类之后重写,成功则返回true,失败则返回false;}也就是说,需要编写一个新的类来继承WxPayNotify,然后重写NotifyProcess方法。您可以通过检查$data['result_code']是否成功来判断它是否成功。如果成功,可以根据业务需求编写业务逻辑,最后返回true。这个时候我就在想,重写这个方法之后怎么打微信。其实微信并不直接调用这个方法。您应该在微信支付回调的方法中实例化这个新类,然后根据获得的对象调用Handle()方法。$obj=新的新类(),$obj-Handle()。
以上就是本文的全部内容。希望对大家的学习有帮助,支持我们。