php app支付寶回調(異步通知)

之前寫過支付寶app支付的支付的後臺代碼,現在來說一下異步通知:

個人感覺支付寶的異步通知,步驟比微信簡單點,但裏面的坑可是沒少多少,就一個驗籤就把我整的快瘋了….

異步通知::

  • 1,先確定在支付的時候寫的回調地址的正確性!!!!!!

  • 2.找到支付寶封裝的驗籤類,rsaCheckV1(這個也是在app2.0接口裏面)

  • 3.驗證回調參數

  • *4.檢驗訂單


先確定在支付的時候寫的回調地址的正確性!!!!!!

一定要確定回調地址的寫的是否指到是你寫回調驗證的那個放裏面,別到時候在回頭找錯誤的時候,抓耳撓腮..

找到支付寶封裝的驗籤類,rsaCheckV1(這個也是在app2.0接口裏面)

這是支付寶已經封裝好的類:

/** rsaCheckV1 & rsaCheckV2
     *  驗證簽名
     *  在使用本方法前,必須初始化AopClient且傳入公鑰參數。
     *  公鑰是否是讀取字符串還是讀取文件,是根據初始化傳入的值判斷的。
     **/
    public function rsaCheckV1($params, $rsaPublicKeyFilePath,$signType='RSA') {
        $sign = $params['sign'];
        $params['sign_type'] = null;
        $params['sign'] = null;
        $this->alipayrsaPublicKey = $rsaPublicKeyFilePath;

        return $this->verify($this->getSignContent($params), $sign, $rsaPublicKeyFilePath,$signType);
    }
    public function rsaCheckV2($params, $rsaPublicKeyFilePath, $signType='RSA') {
        $sign = $params['sign'];
        $params['sign'] = null;
        return $this->verify($this->getSignContent($params), $sign, $rsaPublicKeyFilePath, $signType);
    }
    function verify($data, $sign, $rsaPublicKeyFilePath, $signType = 'RSA') {

        if($this->checkEmpty($this->alipayPublicKey)){

            $pubKey= $this->alipayrsaPublicKey;
            $res = "-----BEGIN PUBLIC KEY-----\n" .
                wordwrap($pubKey, 64, "\n", true) .
                "\n-----END PUBLIC KEY-----";
        }else {
            //讀取公鑰文件
            $pubKey = file_get_contents($rsaPublicKeyFilePath);
            //轉換爲openssl格式密鑰
            $res = openssl_get_publickey($pubKey);
        }

        ($res) or die('支付寶RSA公鑰錯誤。請檢查公鑰文件格式是否正確');  

        //調用openssl內置方法驗籤,返回bool值
        if ("RSA2" == $signType) {
            $result = (bool)openssl_verify($data, base64_decode($sign), $res, OPENSSL_ALGO_SHA256);
        } else {
            $result = (bool)openssl_verify($data, base64_decode($sign), $res);
        }

        if(!$this->checkEmpty($this->alipayPublicKey)) {
            //釋放資源
            openssl_free_key($res);
        }

        return $result;
    }

還有就是別把這兩個方法混淆了,前者需要傳signtype,後者不需要(前面兩個方法都會調用第三個方法),還有一點很重要,就是這個方法的本身是從文件裏面提取公鑰的的,但是本人是直接傳的,就把這個方法稍加改動了一下,讓它直接讀取我傳的公鑰.這個驗籤方法返回的是(bool)true或者(bool)false,來判斷驗籤是否成功.

在這裏要注意三點:
1—注意公鑰的正確性,還有用的是支付寶公鑰不是你當初生成的公鑰
2—區別這裏的方法和支付寶接口本身方法的公鑰獲取方式
3—注意接口方法本身的註釋,很重要

驗證回調參數

支付寶的回調參數是以post的方式回傳的,但是我們在測試的時候可以直接把回調url直接寫在地址欄裏面,然後用get方式接受,這樣就不用拼參數了,結果是一樣的(回調url可以記錄在log文件裏面),還有就是驗籤的時候需要所有的回傳參數原封不動的去驗籤,而這裏自己需要什麼參數就接收什麼參數就可以,這裏就不多說了,就是正常的接受參數的問題.下面給出我在驗證參數時,檢驗訂單金額和商家編號的代碼,僅做參考(我用的tp5):

public function check($receipt_amount,$buyer_pay_amount,$order_price,$app_id,$seller_email){
        if($receipt_amount !== $order_price || $buyer_pay_amount !== $order_price){
//              echo 1;
            return $this->log('訂單支付金額有誤!');
        }
        //支付寶支付的所有參數
        $alipay_config = Config::get('alipay_config');
        if($app_id !== $alipay_config['appid']){
//          echo 2;
             return $this->log('商家編號有誤!');
        }

        //驗證收款商家是否正確
        if($seller_email !== $alipay_config['seller_id']){
//          echo 3;
            return $this->log('收款商家有誤!');
        }
        return 'success';
    }

檢驗訂單

這裏主要就是檢驗庫存,這裏最好用事物處理,(雖然你的訂單量可能不一定回到這個地步),下面給出我的代碼,僅做參考(tp5):

public function index($order_sn='')
    {
        if(isset($_POST['order_sn']) && empty($order_sn)){
            $order_sn = $_POST['order_sn'];
        }

        $table = self::order_info($order_sn);
        if($table == 'failure'){return 'false';}
        $oid = $table['order_id'];
        //通過訂單id  $oid 查詢出訂單中物品的id
        $goodsTable = Db::name('goods');
        $allgoods = Db::name("test1")->where('o_id', $oid)->field('g_id,g_num')->select();
        foreach ($allgoods as $k => $v) {
            //事務處理
            $goodsTable->startTrans();//事物開始
            try {
                //判斷庫存數量
                $goodsTable->query('update test2 set g_num = g_num-' . $v['g_num'] . ' where g_num >= ' . $v['g_num'] . ' and gid =' . $v['g_id']);

            } catch (\Exception $e) {
                $goodsTable->rollBack();//事物回滾
            }

            $goodsTable->commit();//   事物提交
        }

        //修改訂單
        $res = Db::name('test3')->where('order_sn',$order_sn)->update(['order_state' => '1','pay_time'=>time()]);
        if($res != 0){
            return 'success';
        }
    }

接下來就是把結果返回給支付寶就可以,失敗:return ‘failure’;成功:return ‘success’;到這裏就結束了.

還有就是在出錯後和在找bug的時候都平心靜氣一些,理智的找問題纔會更快的找到問題 ( 如果實在不行就去找支付寶的人工支持,他會爲你調試你的代碼,會給出一個差不多的結論,然後你再去改就會容易很多 :) ).

最後希望大家支付,回調都可以成功!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章