搜索
首页微信小程序小程序开发微信小程序支付的流程问题解析(代码解析)

微信小程序支付的流程问题解析(代码解析)

Aug 14, 2018 pm 05:23 PM
微信小程序支付

本篇文章给大家带来的内容是关于微信小程序支付的流程问题解析(代码解析),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

这几天在做小程序的支付,没有用官方的SDK,这里就纯用官方的文档搞一发。

* 注:使用的PHP,不过支付流程都是这样

开发前必读

主要流程

  • 小程序前端发送求参请求

  • 接受请求封装 “统一下单” 获取package

  • 小程序接受 “统一下单” 获取的package值带入wx.requestPayment发起支付请求

准备工具

  • 申请小程序微信支付

  • 拿到小程序微信支付的商户号及设置秘钥

注意:小程序就只需要这两步,如果是web的话还需要设置支付目录授权域名,文档里面也有写的:https://pay.weixin.qq.com/wik..

统一下单

官方文档:https://pay.weixin.qq.com/wik...
/**
 * 统一订单
 */
public function unifiedorder(){
    // 以下配置是必填项,如有其它需求请自行配置
    $config = array(
        'appid'         =>    'xxxxxxx',//这里是小程序appid
        'mch_id'        =>    'xxxxxxx',//商户ID
        'nonce_str'     =>    $this->getNonceStr(),//随机字符串
        'body'          =>    '这里是测试 - 测试',//请按照文档要求填写合格名称
        'out_trade_no'  =>    time().$this->getNonceStr(2),//流水单号
        'total_fee'     =>    '20',//金额,分为单位,这里是0.2元
        'spbill_create_ip' => '123.123.123.123',//当前IP
        'notify_url'    =>    'http://xxxx.com',//请恕我愚昧,我没搞懂他有什么用
        'trade_type'    =>    'JSAPI',//必须填写JSAPI
        'openid'        =>    'xxxxxxxx'//当前用户的openid,在trade_type=JSAPI的时候,此项就变成必填项了
    );
    $config['sign'] = $this->getSignPay($config);
    $xmlData = $this->ToXml($config);//转成xml数据
    $postData = $this->http_post($xmlData);
    $arrayData = $this->FromXml($postData);
    if($arrayData['return_code'] == 'SUCCESS' || $arrayData['result_code'] == 'SUCCESS'){
        return $arrayData['prepay_id'];//重点来了:走了这么多路,就为了这个值。到这一步就证明成功一多半了。
    }else{
        return $arrayData;//返回错误
    }
}

/**
 * 获取签名
 */
public function getSignPay($config){
    $key = 'xxxxxxx';//商户秘钥,就是自己生成的32位密码
    $strA = 'appid='.$config['appid'].'&body='.$config['body'].'&mch_id='.$config['mch_id'].'&nonce_str='.$config['nonce_str'].'&notify_url='.$config['notify_url'].'&spbill_create_ip'.$config['spbill_create_ip'].'&total_fee='.$config['total_fee'].'&trade_type='.$config['trade_type'];//ASCII 字典序
    $strB = $strA.'&key='.$key;
    $sign = strtoupper(md5($strB));//大写MD5
    return $sign;
}

/**
 * 随机字符串 32位
 */
public function getNonceStr($length = 32){
    $chars = "abcdefghijklmnopqrstuvwxyz0123456789";  
    $str ="";
    for ( $i = 0; $i < $length; $i++ )  {  
        $str .= substr($chars, mt_rand(0, strlen($chars)-1), 1);  
    } 
    return $str;
}

/**
 * array转XML
 */
public function ToXml($data){
    if(!is_array($data) || count($data) <= 0){
        throw new WxPayException("数组数据异常!");
    }
    $xml = "<xml>";
    foreach ($data as $key=>$val){
        $xml.="<".$key.">".$val."</".$key.">";
    }
    $xml.="</xml>";
    return $xml; 
}

/**
 * xml转array
 */
public function FromXml($xml){    
    if(!$xml){
        throw new WxPayException("xml数据异常!");
    }
    libxml_disable_entity_loader(true);
    $this->values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
    return $this->values;
}


/**
 * post 请求
 */
public function http_post($url,$param,$post_file=false){
    $oCurl = curl_init();
    if(stripos($url,"https://")!==FALSE){
        curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1
    }
    if (PHP_VERSION_ID >= 50500 && class_exists('\CURLFile')) {
        $is_curlFile = true;
    } else {
        $is_curlFile = false;
        if (defined('CURLOPT_SAFE_UPLOAD')) {
            curl_setopt($oCurl, CURLOPT_SAFE_UPLOAD, false);
        }
    }
    if (is_string($param)) {
        $strPOST = $param;
    }elseif($post_file) {
        if($is_curlFile) {
            foreach ($param as $key => $val) {
                if (substr($val, 0, 1) == '@') {

                }
            }
        }
        $strPOST = $param;
    } else {
        $aPOST = array();
        foreach($param as $key=>$val){
            $aPOST[] = $key."=".urlencode($val);
        }
        $strPOST =  join("&", $aPOST);
    }
    curl_setopt($oCurl, CURLOPT_URL, $url);
    curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1 );
    curl_setopt($oCurl, CURLOPT_POST,true);
    curl_setopt($oCurl, CURLOPT_POSTFIELDS,$strPOST);
    $sContent = curl_exec($oCurl);
    $aStatus = curl_getinfo($oCurl);
    curl_close($oCurl);
    if(intval($aStatus["http_code"])==200){
        return $sContent;
    }else{
        return false;
    }
}

好了现在已经获取到了 prepay_id 的值,我们的统一下单就算完成了,其实我更乐意叫他数据封

小程序微信支付

官方文档:https://developers.weixin.qq....

先来一个插曲,首先我们小程序的前端需要去触发pay,实现的功能肯定是要点击小程序的一个触发,然后才能支付对吧,

pay:function(e){
    //这里面使用post去请求。然后通过我接下来要写的API支付代码获取小程序支付参数
    success:function(res){
         wx.requestPayment({
             'timeStamp':toString(res.timeStamp),//这里转字符串,这里被坑过,不转的话可能会出现total_fee为空
             'nonceStr':toString(res.nonceStr),
             'package':toString(res.package),
             'signType':'MD5',
             'paySign':toString(res.paySign),
             success:function(res){
                 console.log(res);//这里可以跳转到带参地址
             },
             fail:function(res){
                 console.info('支付失败',res);
             },
             complete:function(){
                 console.info('支付触发回调',res);
             }
         })  
    }
       
}

api支付

也就是上面小程序代码的后端请求地址

/**
 * api组装数据
 */
public function payApiBlack(){
    $appid = 'xxxxxx';//小程序appid,上面有重复,不过这样比较直观
    $timeStamp = time();
    $nonceStr = $this->getNonceStr();//这是调用统一下单里面的方法,为了直观,我把这些代码都写在了一个类里
    $package = 'prepay_id='.$this->unifiedorder();
    $signType = 'MD5';
    $key = 'xxxxxx';//这里是商户秘钥,32位,同上面也有
    $strA = 'appId='.$appid.'&nonceStr='.$nonceStr.'package='.$package.'&= signType='.$signType.'&timeStamp='.$timeStamp.'&key='.$key;
    $paySign = strtoupper(md5($strA));
    $data = array(
        'appid'=>$appid,
        'timeStamp'=>$timeStamp,
        'nonceStr'=>$nonceStr,
        'package'=>$package,
        'signType'=>$signType
    );
    return $data;//返回给小程序
}

以上就是全部代码,还有小程序的支付回调没有什么信息,所以,我的思路判断success后进行跳转带参

//此代码为wx.requestPayment success,部分代码省略
//res 回调参数包括用户uid及其他重要传递
success:function(res){
    wx.redirect({
        url:'pages/pay/done?uid='+res.uid
    })
}

当然那个统一下单的 notify_url 好像与回调有关,至于怎么用,试了几次回调的CURD都没反应,所以有空再研究啦。

以上代码仅作为支付流程解释,所以真正要用到项目上,还是去套官方的SDK吧,毕竟涉及到钱嘛

相关推荐:

微信小程序和支付宝小程序对比区别介绍

微信小程序如何从0开始进入支付

微信小程序微信支付接入开发

以上是微信小程序支付的流程问题解析(代码解析)的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

VSCode Windows 64位 下载

VSCode Windows 64位 下载

微软推出的免费、功能强大的一款IDE编辑器

MinGW - 适用于 Windows 的极简 GNU

MinGW - 适用于 Windows 的极简 GNU

这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

EditPlus 中文破解版

EditPlus 中文破解版

体积小,语法高亮,不支持代码提示功能

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。

Dreamweaver Mac版

Dreamweaver Mac版

视觉化网页开发工具