zoukankan      html  css  js  c++  java
  • 移动APP 微信支付完整过程(wxPay 方案一)

    前两天开始做移动端APP的微信支付,过程中遇到了一些问题,比如支付的过程中返回值总是:-1 {status:false},这些问题已经得到了解决。前人栽树,后人尽管乘凉,那么分享一下整个支付过程(wxPay 方案一):

    1、申请微信开发平台的账号、创建移动应用、申请开发者资质认证(整个过程APICLOUD官方网站已经给出了相当明确的操作步骤,与实际操作没有差异,按照文档一步一步来,是没有问题的),附带链接地址:http://docs.apicloud.com/Others/Open-SDK-Integration-Guide/weChat

    2、配置移动应用中 config.xml 文件

    <feature name="wxPay">
        <param name="urlScheme" value="***"/>
        <param name="apiKey" value="***"/>
        <param name="apiSecret" value="***"/>
      </feature>

    复制代码


    配置获取方式说明以及截图:从微信开发平台获取,登录微信开发平台 —>管理中心—>移动应用—>查看(urlScheme的值和apiKey相同)(微信开发平台链接:https://open.weixin.qq.com/

    3、getOrderId(),将获取预支付订单号,建议将获取预支付订单号放置服务器端执行。(服务端代码如下:)

    $dataArr = array(
        'appid' => $appId,
        'mch_id' => $mchId,
        'nonce_str' => getNonceStr(),
        'body' => $body,
        'attach' => $attach,
        'out_trade_no' => getNonceStr(),
        'total_fee' => $totalFee,
        'spbill_create_ip' => $cIp,
        'notify_url' => $url,
        'trade_type' => 'APP'
    );
    
    
    //转XML格式
    function createXML($rootNode, $arr)
    {
        //创建一个文档,文档时xml的,版本号为1.0,编码格式utf-8
        $xmlObj = new DOMDocument('1.0', 'UTF-8');
        //创建根节点
        $Node = $xmlObj->createElement($rootNode);
        //把创建好的节点加到文档中
        $root = $xmlObj->appendChild($Node);
        //开始把数组中的数据加入文档
        foreach ($arr as $key => $value) {
            //如果是$value是一个数组
            if (is_array($value)) {
                //先创建一个节点
                $childNode = $xmlObj->createElement($key);
                //将节点添加到$root中
                $root->appendChild($childNode);
                //循环添加数据
                foreach ($value as $key2 => $val2) {
                    //创建节点的同时添加数据
                    $childNode2 = $xmlObj->createElement($key2, $val2);
                    //将节点添加到$childNode
                    $childNode->appendChild($childNode2);
                }
            } else {
                //创建一个节点,根据键和值
                $childNode = $xmlObj->createElement($key, $value);
                //把节点加到根节点
                $root->appendChild($childNode);
            }
        }
        //把创建好的xml保存到本地
        $xmlObj->save('xml/log.xml');
        $str = $xmlObj->saveXML();
    //        echo $str;
        //返回xml字符串
        return $str;
    }
    
    
    //封装签名算法
    function MakeSign($arr)
    {
        //签名步骤一:按字典序排序参数
        ksort($arr);
        $string = ToUrlParams($arr);
        //签名步骤二:在string后加入KEY
        $string = $string . "&key=" . $key;
        //签名步骤三:MD5加密
        $string = md5($string);
        //签名步骤四:所有字符转为大写
        $result = strtoupper($string);
        return $result;
    }
    
    /**
    * 格式化参数格式化成url参数
    */
    function ToUrlParams($arr)
    {
        $buff = "";
        foreach ($arr as $k => $v) {
            if ($k != "sign" && $v != "" && !is_array($v)) {
                $buff .= $k . "=" . $v . "&";
            }
        }
    
        $buff = trim($buff, "&");
        return $buff;
    }
    
    
    //随机字符串(不长于32位)
    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;
    }
    
    
    function curl($url, $post_data)
    {
    
    
        $headerArray = array(
            'Accept:application/json, text/javascript, */*',
            'Content-Type:application/x-www-form-urlencoded',
            'Referer:https://mp.weixin.qq.com/'
        );
    
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        // 对认证证书来源的检查,0表示阻止对证书的合法性的检查。
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        // 从证书中检查SSL加密算法是否存在
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//关闭直接输出
        curl_setopt($ch, CURLOPT_POST, 1);//使用post提交数据
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);//设置 post提交的数据
        curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.69 Safari/537.36');//设置用户代理
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headerArray);//设置头信息
    
    
        $loginData = curl_exec($ch);//这里会返回token,需要处理一下。
    
    
        return $loginData;
    
        $token = array_pop($token);
        curl_close($ch);
    
    
    }
    
    /**
    * 解析xml文档,转化为对象
    * @param  String $xmlStr xml文档
    * @return Object         返回Obj对象
    */
    function xmlToObject($xmlStr)
    {
        if (!is_string($xmlStr) || empty($xmlStr)) {
            return false;
        }
        // 由于解析xml的时候,即使被解析的变量为空,依然不会报错,会返回一个空的对象,所以,我们这里做了处理,当被解析的变量不是字符串,或者该变量为空,直接返回false
        libxml_disable_entity_loader(true);
        $postObj = json_decode(json_encode(simplexml_load_string($xmlStr, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        //将xml数据转换成对象返回
        return $postObj;
    }
    
    
    
    
    //=====================执行=======================
    $sign = MakeSign($dataArr);//签名生成
    $dataArr['sign'] = $sign;
    
    $xmlStr = createXML('xml', $dataArr);//统一下单xml数据生成
    $reArr = explode('?>', $xmlStr);
    $reArr = end($reArr);
    
    $xml = curl('https://api.mch.weixin.qq.com/pay/unifiedorder', $reArr);//发送请求 统一下单数据
    
    //解析返回的xml字符串
    $re = xmlToObject($xml);
    
    //判断统一下单是否成功
    if ($re['result_code'] == 'SUCCESS') {
    
        //支付请求数据
        $payData = array(
            'appid' => $re['appid'],
            'partnerid' => $re['mch_id'],
            'prepayid' => $re['prepay_id'],
            'noncestr' => getNonceStr(),
            'package' => 'Sign=WXPay',
            'timestamp' => time()
        );
    
    
        //生成支付请求的签名
        $paySign = MakeSign($payData);
    
        $payData['sign'] = $paySign;
    
        //拼接成APICLOUD所需要支付数据请求
        $payDatas = array(
            'apiKey' => $re['appid'],
            'orderId' => $re['prepay_id'],
            'mchId' => $re['mch_id'],
            'nonceStr' => $payData['noncestr'],
            'package' => 'Sign=WXPay',
            'timeStamp' => $payData['timestamp'],
            'sign' => $paySign
        );
    
        //返回支付请求数据
        echo json_encode($payDatas);
    } else {
        $re['payData'] = "error";
        echo json_encode($re);
    }
    复制代码

    4、预支付下单成功后,将拼接好的支付请求数据返回,也就是上述代码中数组$payDatas(注意:第二次参与签名的字段是:appid、partnerid、prepayid、noncestr、package、timestamp),app端代码如下:

    $.ajax({
                url:url,
                data:{
                    body:body,
                    attach:attach,
                    total_fee:total_fee
                },
                dataType:"json",
                type:"post",
                success:function(data){
    
    
                    if(data.payData != "error"){
                        var wxPay = api.require('wxPay');
                        wxPay.payOrder(data, function(ret, err) {
    
                            if (ret.status) {
                                //支付成功
                                alert('支付成功');
                                }
    
    
    
                            } else {
                                alert(err.code);

    复制代码

    5、以上描述,已经亲测没有问题,如果代码或叙述有问题的,欢迎各位大神指教批评;如果有帮到各位初学者的不胜荣幸;另外说下我之前遇到过支付过程中返回-1的问题:

    官网上面payOrder()的参数为:appKey、orderId、mchId、nonceStr、timeStamp、package,就会以为参与第二次支付签名的参数是这些,但其实并不是,

    那么参与第二次支付签名的参数是:appid、partnerid、prepayid、noncestr、package、timestamp,

    生成签名后,需要将payOrder()所需要的参数一一对应重新填写(appKey==appid、orderId==prepayid、mchId==partnerid、nonceStr==noncestr、package==package、timeStamp==timestamp)。

  • 相关阅读:
    数据结构-树与二叉树-思维导图
    The last packet successfully received from the server was 2,272 milliseconds ago. The last packet sent successfully to the server was 2,258 milliseconds ago.
    idea连接mysql报错Server returns invalid timezone. Go to 'Advanced' tab and set 'serverTimezone' property
    redis学习笔记
    AJAX校验注册用户名是否存在
    AJAX学习笔记
    JSON学习笔记
    JQuery基础知识学习笔记
    Filter、Listener学习笔记
    三层架构学习笔记
  • 原文地址:https://www.cnblogs.com/APICloud/p/10796218.html
Copyright © 2011-2022 走看看