laravel+php+微信掃碼支付

第一個博客

寫這個的原因是因爲以前配置過很多環境,過一段就會忘掉,當需要在用的時候就要重新花費好久來搞。這詞做這個關於微信支付的項目,在如何使用php的laravel框架加入微信掃碼支付的功能上花了太久的時間,不希望自己以後再踩同樣的坑,也希望可以幫到別人。第一次寫博客,可能寫不清楚,請大家見諒。

說明:本文說的是微信支付的第二種模式

準備工作:

  • 在微信支付官網的SDK下載中下載對應的php代碼
  • 配置好laravel需要的基本環境
  • 獲得支付所需的配置信息:appid、cmhid、key,獲取方式在sdk中有說明
/**
     * TODO: 修改這裏配置爲您自己申請的商戶信息
     * 微信公衆號信息配置
     * 
     * APPID:綁定支付的APPID(必須配置,開戶郵件中可查看)
     * 
     * MCHID:商戶號(必須配置,開戶郵件中可查看)
     * 
     * KEY:商戶支付密鑰,參考開戶郵件設置(必須配置,登錄商戶平臺自行設置)
     * 設置地址:https://pay.weixin.qq.com/index.php/account/api_cert
     * 
     * APPSECRET:公衆帳號secert(僅JSAPI支付的時候需要配置, 登錄公衆平臺,進入開發者中心可設置),
     * 獲取地址:https://mp.weixin.qq.com/advanced/advanced?action=dev&t=advanced/dev&token=2005451881&lang=zh_CN
     * @var string
     */
    const APPID = 'wx8dce35348ad73e3';
    const MCHID = '131547990';
    const KEY = '5f980c0c9548833f3260e82dc2ce33';
    const APPSECRET = '01c6d59a3f9024db6336662ac95c8e74';

配置當然就是寫在sdk的這個配置文件中:WxPay.config.php,就是上面貼的那段代碼。

重要的坑

sdk中的所有文件引用都是 相對路徑,但是laravel的所有相對路徑都是以單入口文件public/index.php爲當前文件的,所以 要把sdk中所有的require_once 以及log的目錄地址,都換成以public/index.php爲當前目錄的相對路徑。比如:我把整個sdk放在了項目路徑app/Http/下面,和controller並立(不要吐槽我),那麼我的sdk中的相對路徑就是 require_once "../app/Http/WxPaySDK/lib/WxPay.Exception.php";這樣的。其中lib是對應sdk中的lib,當然也有是example的,根據需要換掉就行。換掉所有的相對路徑後,就可以開始做支付功能了。

順便吐槽,本來想用namespace 和 use 來處理的 可是微信的sdk中一個文件裏好幾個類,還有log這樣的很容易衝突的類名,最後懶得處理,就還用require引用了。

生成二維碼連接

在sdk中,負責生成二維碼的是native.php這個文件,其中的有用代碼是:

//模式一
/**
 * 流程:
 * 1、組裝包含支付信息的url,生成二維碼
 * 2、用戶掃描二維碼,進行支付
 * 3、確定支付之後,微信服務器會回調預先配置的回調地址,在【微信開放平臺-微信支付-支付配置】中進行配置
 * 4、在接到回調通知之後,用戶進行統一下單支付,並返回支付信息以完成支付(見:native_notify.php)
 * 5、支付完成之後,微信服務器會通知支付成功
 * 6、在支付成功通知中需要查單確認是否真正支付成功(見:notify.php)
 */
$notify = new NativePay();
$url1 = $notify->GetPrePayUrl("123456789");

//模式二
/**
 * 流程:
 * 1、調用統一下單,取得code_url,生成二維碼
 * 2、用戶掃描二維碼,進行支付
 * 3、支付完成之後,微信服務器會通知支付成功
 * 4、在支付成功通知中需要查單確認是否真正支付成功(見:notify.php)
 */
$input = new WxPayUnifiedOrder();
$input->SetBody("test");
$input->SetAttach("ljm");
$input->SetOut_trade_no(WxPayConfig::MCHID.date("YmdHis"));
$input->SetTotal_fee("1");
$input->SetTime_start(date("YmdHis"));
$input->SetTime_expire(date("YmdHis", time() + 600));
$input->SetGoods_tag("test");
$input->SetNotify_url("http://paysdk.weixin.qq.com/example/notify.php");
$input->SetTrade_type("NATIVE");
$input->SetProduct_id("123456789");
$result = $notify->GetPayUrl($input);
// var_dump($result);die;
$url2 = $result["code_url"];

注意模式一的第一行new的對象,在模式二中最後有用,我用的是模式二的方式。以上代碼,其實是用來生成一個$result,這是sdk根據設置的參數生成好的,參數裏SetBody是掃碼支付時最上面的標題,SetOut_trade_no是設置商戶訂單號(支付結果會帶回來,以便對相應訂單狀態做更改)。SetTotal_fee是支付金額,單位是分。其他具體參數,參看統一訂單(不太需要了)。

知道了怎麼配置參數,那接下來就需要把這些代碼拷貝到controller的某處,做一個接口來調用,接口傳入商家要支付的商品的那個訂單號(不是微信的支付號,是商家自己的訂單編號),然後用某種方式生成out_trade_no就行了。不廢話,貼代碼

/**
     *GET localhost/youge/blog/public/File/getQrcode
     *
     *獲取付款二維碼url的參數
     *
     */
    require_once "../app/Http/WxPaySDK/lib/WxPay.Api.php";
    require_once "../app/Http/WxPaySDK/example/WxPay.NativePay.php";
    //注意引入文件的路徑
    public function getQrcode(Request $request)
    {
        $file_id = $request->input('file_id', '');
        $out_trade_no = WxPayConfig::MCHID . date("YmdHis") . $file_id;
        //我的out_trade_no是這麼做的 由於我的file_id(就是我的商家訂單)是唯一的,所以無論如何這個結果都是唯一的
        $notify = new NativePay();
        $input = new WxPayUnifiedOrder();
        $input->SetBody("這裏寫這是什麼服務項目的支付");
        $input->SetAttach("ljm");
        $input->SetOut_trade_no($out_trade_no);
        $input->SetTotal_fee("600");
        $input->SetTime_start(date("YmdHis"));
        $input->SetTime_expire(date("YmdHis", time() + 600));
        $input->SetGoods_tag("test");
        $input->SetNotify_url("http://127.0.0.1/youge/blog/public/index.php/payNotify");
        //這裏設置支付成功後的回調接口,不能有參數。還有,這裏的127.0.0.1是收不到微信後臺發出的回調函數的,只能用服務器來測試了。
        $input->SetTrade_type("NATIVE");
        $input->SetProduct_id("123456789");
        $result = $notify->GetPayUrl($input);

        $url = $result["code_url"];

        $file = File::where('id', $file_id)->first();
        if (!empty($file)) {
            $file->out_trade_no = $out_trade_no;
            $file->save();
        }
        //這段是把out_trade_no和要處理的訂單關聯起來
        return "http://paysdk.weixin.qq.com/example/qrcode.php?data=" . $url;
    }

最後的return是一個微信的連接,data後面的值是sdk生成的一小串字符串,用來生成二維碼。把這個return的完整字符串放入HTML的img標籤,就是一個二維碼了。

支付通知獲取

根據官網的說明 點這裏,支付成功後,微信會發送POST的請求,到上面你設置的通知回調接口,在sdk中,回調接口是example/notify.php
但是在laravel中,接口要放在controller中,所以我們新建一個controller,寫個route文件接口,從這個controller中調用這個notify.php,怎麼調用呢。
首先,把notify中的最下面的幾行和最上面的幾行不在函數中的代碼

$logHandler= new CLogFileHandler("../app/Http/WxPaySDK/logs/".date('Y-m-d').'.log');
$log = Log::Init($logHandler, 15);
Log::DEBUG("begin notify");
$notify = new PayNotifyCallBack();
$notify->Handle(false);

然後寫個public static function notifyReceive()放進去,這樣就可以從controller中直接調用它了

PayNotifyCallBack::notifyReceive();
//PayNotifyCallBack 是notify.php中的類名

至此,應該說掃碼支付的模式二就實現了。

此外,在notify.php的回調函數中可以把自己業務的邏輯代碼放在這裏

    public function NotifyProcess($data, &$msg)
    {
        Log::DEBUG("call back:" . json_encode($data));
        $notfiyOutput = array();

        if(!array_key_exists("transaction_id", $data)){
            $msg = "輸入參數不正確";
            return false;
        }
        //查詢訂單,判斷訂單真實性
        if(!$this->Queryorder($data["transaction_id"])){
            $msg = "訂單查詢失敗";
            return false;
        }
//這裏以下////////////////////////
        $file = File::where('out_trade_no', $data['out_trade_no'])->first();
        if (!empty($file)) {
            $file->status = File::FILE_PAYED;
            $file->save();
        }
//這裏以上///////////////////////就是在這個return true之前,表示驗證沒有問題,支付成功時執行這部分業務邏輯     
        return true;
    }

相關文檔

微信掃碼模式二介紹
二維碼生成(統一下單接口)
支付結果通知回調接口

發佈了30 篇原創文章 · 獲贊 22 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章