1. 程式人生 > >thinkphp3.2微信公眾號支付(jsapi支付)開發過程

thinkphp3.2微信公眾號支付(jsapi支付)開發過程

第一次做微信支付(網頁版本的),折騰了兩天,記錄一下方便下次自己再次使用,也希望能幫和我一樣初次接觸的朋友踩一下坑。

前期準備

1.開通微信認證服務號,並且開通商戶平臺

2.下載微信支付dome,下載地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1,解壓php版本如圖

a.doc資料夾說明文件     b.example一些dome示例    c.lib最重要的檔案介面檔案     d.logs日誌檔案

第一步dome檔案處理

1.解壓後獲得php_sdk_v3.0.9這個資料夾改名為WxPay整個複製到核心框架ThinkPHP\Library\Vendor中方便呼叫

2.開啟lib資料夾下的WxPay.Api.php檔案,在537行有一段curl網路請求配置程式碼:

curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE);
改為:
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
為了禁止 cURL 驗證證書

3.開啟example中的WxPay.Config.php配置GetAppId函式和GetMerchantId兩項(一個是公眾號APPID,一個是商戶號) 

第二步配置公眾號後臺授權路徑

1.網頁授權路徑,公眾號設定->功能設定->網頁授權域名(這個是為了獲取使用者openid的),直接填你的根目錄就OK

2.配置商戶授權路徑,登陸商戶->產品中心->開發配置,用於付款資料互動(微信伺服器與自己伺服器之間的)

 這裡有一個大坑要注意一下,他這個配置不支援pathinfo模式,比如

https://www.xxx.com/fukuan/index.php/Home/wxpay/notify

這種模式是不支援的,解決方法如下

根目錄(fukuan)中建立payment.php作為入口檔案,然後跳轉到相應頁面

 https://www.xxx.com/fukuan/payment.php

<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2014 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <[email protected]>
// +----------------------------------------------------------------------

// 應用入口檔案

// 檢測PHP環境
if(version_compare(PHP_VERSION,'5.3.0','<'))  die('require PHP > 5.3.0 !');

// 開啟除錯模式 建議開發階段開啟 部署階段註釋或者設為false
define('APP_DEBUG',True);

//指定模組控制器和方法 
$_GET['m']='Home'; 
$_GET['c']='Wxpay'; 
$_GET['a']='notify'; 

// 定義應用目錄
define('APP_PATH','./Application/');

// 引入ThinkPHP入口檔案
require './ThinkPHP/ThinkPHP.php';

// 親^_^ 後面不需要任何程式碼了 就是如此簡單

第三步前端程式碼

<script type="text/javascript">
    $('.btns').click(function(){
        var moneys = ($('.moneys').val());
        var openids = "<?php echo I('openid')?>";
        $.ajax({
            url: "{:U('wxpay')}",    //請求的url地址
            dataType: "json",   //返回格式為json
            async: true, //請求是否非同步,預設為非同步,這也是ajax重要特性
            data: { 
                'moneys': moneys,
                'openids': openids
            },//引數值
            type: "POST",   //請求方式
            success: function(req) {
                //console.log(req);
                function jsApiCall(){
                    WeixinJSBridge.invoke(
                        'getBrandWCPayRequest',
                        req,
                        function(res){
                            WeixinJSBridge.log(res.err_msg);
                            //alert(res.err_code+res.err_desc+res.err_msg);
                            if(res.err_msg == "get_brand_wcpay_request:ok"){              
                                window.location.reload();
                            }
                        }
                    );
                }
                function callpay(){
                    if (typeof WeixinJSBridge == "undefined"){
                    if( document.addEventListener ){
                        document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
                    }else if (document.attachEvent){
                        document.attachEvent('WeixinJSBridgeReady', jsApiCall); 
                        document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
                    }
                    }else{
                        jsApiCall();
                    }
                }
                callpay();
            },
            error: function() {
                alert('請求錯誤');
            }
        });
    })
    </script>

第四步後端程式碼

    //付款呼叫
    public function wxpay(){
        $money = abs(I('moneys'))*100;  //單位為分
        $openid = I('openids');
        if(empty($money)){
            return 0;
        }
        if(empty($openid)){
            return 0;
        }
        //echo $money;
        Vendor('WxPayAPI.lib.WxPay#Api');
        Vendor('WxPayAPI.example.WxPay#Config');
        Vendor('WxPayAPI.example.WxPay#JsApiPay');
        //②、統一下單
        $tools = new \JsApiPay();
        $input = new \WxPayUnifiedOrder();
        $input->SetBody("微信還款");    //這裡是支付內容
        $input->SetAttach(I('fq'));    //此處可傳值,待支付成功後可取這部分的值
        $input->SetOut_trade_no("3".date("YmdHis"));  //訂單編號
        $input->SetTotal_fee($money);  //金額
        $input->SetTime_start(date("YmdHis"));
        $input->SetTime_expire(date("YmdHis", time() + 600));
        $input->SetGoods_tag("test");
        $input->SetNotify_url("https://wechat.labao168.com/fukuan/payment.php"); 
        $input->SetTrade_type("JSAPI");
        $input->SetOpenid($openid);

        $config = new \WxPayConfig();
        $order = \WxPayApi::unifiedOrder($config, $input);
        $jsApiParameters = $tools->GetJsApiParameters($order);
        echo $jsApiParameters;
    }

第五步支付成功後入庫處理(這裡真的是操碎了心),回撥地址就是上面在商戶號上配置地址,支付成功後微信伺服器會訪問這個地址

a.坑1這個地址是不允許有許可權管理的,就是說你在網頁上能直接訪問,否則微信伺服器無法傳值到這個地址

b.坑2微信伺服器為了將訊息準確送到我們的伺服器,會對這個地址請求多次,頻率從高到低(導致一條資料被插入很多次資料庫),我的解決方法比較笨,就是插入資料庫之前檢測一下訂單是否存在,存在的話就直接跳過插入資料

c.坑3由於是伺服器與伺服器間的請求,無法在頁面上顯示,就是說你丫沒辦法在頁面上除錯,解決辦法將接受到的資料寫入文字中,然後檢視文字是否有問題

d.傳值問題,支付後端中$input->SetAttach(I('fq'));是可以傳值的

<?php
namespace Home\Controller;
use Think\Controller;
class WxpayController extends Controller{
    public function notify(){

        
        //獲取返回的xml
        $testxml = file_get_contents("php://input");

        //將xml轉化為json格式
        $jsonxml = json_encode(simplexml_load_string($testxml, 'SimpleXMLElement', LIBXML_NOCDATA));

        //轉成陣列
        $result = json_decode($jsonxml,true);

        //file_put_contents('test.txt',$jsonxml);   --這裡是除錯方法根目錄中test.txt中可檢視資料情況

        if($result){
            //如果成功返回了
            if($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS'){

                //file_put_contents('test.txt',$data);

                //獲取伺服器返回的資料
                $order_sn = $result['transaction_id']; //訂單單號
                $openid = $result['openid'];   //付款人openID 
                $total_fee = ($result['total_fee']/100); //付款金額 
                $fq = $result['attach'];    //分期數

                //判斷訂單是否已經入庫
                $results = M('zhangdan')->where(array('tranid'=>$order_sn))->find();
                if($results){
                    exit();
                }

                //更新資料庫 
                $uid = M('user')->where(array('openid'=>$openid))->getField('id');

                //判斷是否滿足分期
                M('fqjl')->where(array('uid'=>$uid,'fq'=>$fq))->setInc('yhk',$total_fee); // 使用者的積分加3
                //file_put_contents('test.txt',$datast['yhk']);

                $sj['money'] = $total_fee;
                $sj['ztime'] = strtotime(date('Y-m-d'));
                $sj['contents'] = "微信還款";
                $sj['uid'] = $uid;
                $sj['tranid'] = $order_sn;

                //file_put_contents('test.txt',$sj);
                $res = M('zhangdan')->add($sj);

                echo exit('<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>');
            }
        }
    }

}



至此支付就完成了,希望有一點對第一次接觸的朋友有一點小小的幫助