微信小程序支付开发流程?

一、官方流程图

小程序支付的交互图如下:
wxa72.jpg

二、小程序调用登录接口获取code,传递给商户服务器获取用户的openID

apilogin.2fcc9f35.jpg

1.小程序调用wx.login() 获取 临时登录凭证code ,并回传到开发者服务器。
2.开发者服务器以code换取 用户唯一标识openid 和 会话密钥session_key。
小程序端:

getToken: function () {
    //调用登录接口
    wx.login({
      success: function (res) {
        var code = res.code;
        wx.request({
          url: 商户服务器接口地址, 
          data: {
            code: code
          },
          method: 'POST', 
          success: function (res) { 
            wx.setStorageSync('token', res.data.token); //存在小程序缓存中
          },
          fail: function (res) {
            console.log(res.data);
          }
        })
      }
    })
  }

服务端:
我们通过小程序提交的code,和小程序的APPID以及APPSECRET和拼接下列的url,并用curl进行get请求。

https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code

返回的数据是一个json对象,我门通过使用json_decode(JSON,true)解析为数组,数据包括用户的openID以及session_key,获取到了后我们应该将openID存入数据库中,它代表着用户的身份,那么令牌应该怎么生成呢。

三、token的生成以及缓存

我们根据一个用户表将id和openid联系起来,对应openID的id则是用户的uid,我们可以这么封装

//要缓存的数据数组
$cacheValue = $result;   //包含openID和session_key
$cacheValue['uid'] =$uid;   //用户id
 
$cacheValue['scope'] =ScopeEnum::User;   //用户权限级别

缓存的方式我们可以选择redis,memcache, 文件缓存等等,采用键值对(key-value)的方式进行存储,记得设置好过期时间。这里的key我们用token来赋值,token可以通过这样的方式进行生成:

//获取32位随机字符串
$str = getRandChar(32);   //自定义方法生成32位随机串
//三组字符串进行md5加密
$timeStamp =$_SERVER['REQUEST_TIME_FLOAT'];
//salt
$salt = config('secure.token_salt'); //随机字符串
//返回token
 
return md5($str.$timeStamp.$salt);

这种算法基本保障了token的唯一性。因为值是我们获取到的openID和session_key所在的数组,所以需要将数组转成json才能存进去。以后的代码当我们需要openID或者uid等时可以直接通过取缓存的方式来取。

四、调用统一下单接口,获取prepay_id,再次签名

4.1 下载微信JS-SDK

(https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1)
解压打开进入lib文件夹中。
我们需要将lib中的文件放到我们的框架中,例如我使用的是tp5,就放到extend下,最好是在extend下建个子文件夹。其中WxPay.Api.php是入口,WxPay.Config.php是配置文件。下好后需要改动一些地方。在WxPay.Config.php中修改下列的东西改成你的。
然后在WxPay.Api.php中require一下WxPay.Notify.php。
在某个控制器或者服务层的代码先是用Loader::import()引入WxPay.Api.php,相当于五个都引入了。

4.2 调用统一下单api

在我们引入了上面那个文件后,先实例化这个类WxPayUnifiedOrder,把需要的参数通过调用对应的方法传入。

//调用微信支付统一下单接口
        $wxOrderData = new \WxPayUnifiedOrder();
        //设置相关参数
        $wxOrderData->SetOut_trade_no($this->orderNO);
        $wxOrderData->SetTrade_type('JSAPI');
        $wxOrderData->SetTotal_fee($totalPrice * 100); //这里的价格单位是分
        $wxOrderData->SetBody('Mc');
        $wxOrderData->SetOpenid($openid);
        $wxOrderData->SetNotify_url(config('secure.pay_back_url'));//支付回调

参数设置好了之后,就直接调用SDK的方法了

 $wxOrder = \WxPayApi::unifiedOrder($wxOrderData);

4.3 再次签名

//  提交JSAPI输入对象
        $jsApiPayData = new \WxPayJsApiPay();
        //设置appid
        $jsApiPayData->SetAppid(config('wx.app_id'));
        //timeStamp
        $jsApiPayData->SetTimeStamp((string)time());
        //随机串
        $randStr = md5(time().mt_rand(0,1000));
        $jsApiPayData->SetNonceStr($randStr);
        //数据报
        $jsApiPayData->SetPackage('prepay_id='.$wxOrder['prepay_id']);
        //类型
        $jsApiPayData->SetSignType('MD5');
        //生成签名
        $sign  = $jsApiPayData->MakeSign();
        //获得签名数组
        $signData = $jsApiPayData->GetValues();
        //增加字段paySign
        $signData['paySign']=$sign;
        //删除signData中的app_Id字段
        unset($signData['appId']);
        return $signData;

再次签名完成后,就把五个参数返回给小程序。

五、小程序获取五个参数后,鉴权调起支付

小程序端:

pay: function () {
    var token = wx.getStorageSync('token');
    var that = this;
  
    wx.request({
      url: baseUrl + '/order',
      header: {
        token: token
      },
      data: {   //产品的数据
        products:
        [
          {
            product_id: 1, count: 1
          },
          
          {
            product_id: 2, count: 1
          }
        ]
      },
      method: 'POST',
      success: function (res) {
        console.log(res.data);
        if (res.data.pass) {
          wx.setStorageSync('order_id', res.data.order_id);
          that.getPreOrder(token, res.data.order_id); //调用getPreOrder
        }
        else {
          console.log('订单未创建成功');
        }
      }
    })
  },
 
  getPreOrder: function (token, orderID) {
    if (token) {
      wx.request({
        url: baseUrl + '/pay/pre_order',
        method: 'POST',
        header: {
          token: token
        },
        data: {
          id: orderID
        },
        success: function (res) {
          var preData = res.data;
          console.log(preData);
          
          wx.requestPayment({    //请求支付
            timeStamp: preData.timeStamp.toString(),
            nonceStr: preData.nonceStr,
            package: preData.package,
            signType: preData.signType,
            paySign: preData.paySign,
            success: function (res) {
              console.log(res.data);     
            },
            fail: function (error) {
              console.log(error);
            }
          })
        }
      })
    }
  },

六、支付回调

我们需要重写WxPayNotify类的NotifyProcess方法,这里记得Loader::impor()引入那个入口类。


/**
	 * 
	 * 回调方法入口,子类可重写该方法
	 * 注意:
	 * 1、微信回调超时时间为2s,建议用户使用异步处理流程,确认成功之后立刻回复微信服务器
	 * 2、微信服务器在调用失败或者接到回包为非确认包的时候,会发起重试,需确保你的回调是可以重入
	 * @param array $data 回调解释出的参数
	 * @param string $msg 如果回调处理失败,可以将错误信息输出到该方法
	 * @return true 回调出来完成不需要继续回调,false回调处理未完成需要继续回调
	 */
	public function NotifyProcess($data, &$msg)
	{
		//TODO 用户基础该类之后需要重写该方法,成功的时候返回true,失败返回false
		return true;
	}
回到稻壳网首页
稻壳客服

扫一扫,微信咨询

请留下需求和联系方式,我们即刻为您准备方案
需求提交成功

提交成功

免费服务热线021-61676039(工作日9:00 ~ 18:00)
×
稻壳客服

扫一扫,微信咨询