App微信支付之php後台介面詳解

來源:互聯網
上載者:User
本文將和大家介紹App支付(2016.10.11)的php(7.0)後台支付和回調介面,架構是Thinkphp5.0:希望能協助到大家。

  • 賬戶的各種參數

  • 訂單資訊

  • 請求prepay_id

  • *返回APP資料處理

  • 回調

  • 修改訂單狀態

賬戶的各種參數

賬戶的各種參數就是像申請app支付的時候會給你的賬戶郵箱發郵件,裡面會有對應的支付分配的商戶號(MCHID),APPID和APPSECRET是在申請app支付許可權的時候返回的,還有KEY需要自己在使用者的商家後台裡面自己設定的,這個很重要!避免外泄!

訂單資訊

  • **用戶端會把購物車裡面的商品資料傳到後台,還包括使用者的資訊等,拿到資料後首先需要驗證這些資料,這裡的驗證一般都會在項目初期就和用戶端定好傳輸規則,比如傳輸方式,參數名,驗證參數的方式,這裡的重點就是驗證,一般都會採用簽名認證的方式:

  • //簽名步驟一:按字典序排序參數;

  • 這裡給出(格式化參數格式化成url參數)代碼執行個體:

/**     * 格式化參數格式化成url參數     */    public function ToUrlParams()    {        $buff = "";        foreach ($this->values as $k => $v)        {            if($k != "sign" && $v != "" && !is_array($v)){                $buff .= $k . "=" . $v . "&";            }        }        $buff = trim($buff, "&");        return $buff;    }
  • //簽名步驟二:在string後加入KEY(這個KEY與前端人員協商而定);


  • //簽名步驟三:MD5加密;


  • //簽名步驟四:所有字元轉為大寫


這些最好在項目初期就封裝好,後期會只要調用就好,例:
(後期只需要, $param = $this->request('參數名'));即可), 然後將訂單資訊預儲存.

請求prepay_id

這裡我就直接上代碼吧,(這裡給出介面文檔下載地址:),雖然網上也有很多自己寫請求介面,但是既然已經封裝好了,用就行了:

$input = new \app\wxpay\WxPayUnifiedOrder();//這裡引用的統一下單介面$input->SetBody($data['gname']['g_name']);//商品或支付單簡要描述$input->SetAttach($data['gname']['g_name']);//置附加資料 $input->SetOut_trade_no($order_sn); // 商戶訂單號$input->SetTotal_fee(intval($data['data']['order_price']*100)); $input->SetTime_start(date("YmdHis"));//訂單產生時間$input->SetTime_expire(date("YmdHis", time() + 600));//訂單失效時間$input->SetGoods_tag($data['gname']['g_name']); //商品標記  $input->SetNotify_url("http://www.weixin.qq.com/wxpay/notify.php"); // 支付成功後的回調地址,$input->SetTrade_type("APP");$order = \app\wxpay\WxPayApi::unifiedOrder($input);return $order['prepay_id'];

這裡給出官方統一下單介面說明地址:
https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1

返回用戶端資訊

$info = array();//帳號的資訊一般都放在設定檔裡面,用到的地方也很多$info['appid'] = config('APP_APPID');$info['partnerid'] = config('APP_MCHID');$info['package'] = config('APP_PACKAGE');$info['noncestr'] = $this->random_number();//產生隨機數,下面有產生執行個體,統一下單介面需要$info['timestamp'] = time();$info['prepayid'] = $prepay_id;$info['sign'] = self::_makeSign($info);//產生簽名return $info;

$info就是用戶端需要的資訊啦
產生隨機數執行個體

//產生隨機數    public function random_number($len=21,$format='ALL' ){        $is_abc = $is_numer = 0;        $password = $tmp ='';        switch($format){            case 'ALL':            $chars='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';            break;            case 'CHAR':            $chars='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';            break;            case 'NUMBER':            $chars='0123456789';            break;            default :            $chars='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';            break;        } // www.jb51.net        mt_srand((double)microtime()*1000000*getmypid());        while(strlen($password)<$len){            $tmp =substr($chars,(mt_rand()%strlen($chars)),1);            if(($is_numer <> 1 && is_numeric($tmp) && $tmp >0 )|| $format == 'CHAR'){                $is_numer = 1;            }            if(($is_abc <> 1 && preg_match('/[a-zA-Z]/',$tmp)) || $format == 'NUMBER'){                $is_abc = 1;            }            $password.= $tmp;        }        if($is_numer <> 1 || $is_abc <> 1 || empty($password) ){            $password = $this->random_number($len,$format);        }        return $password;        }

回調

支付結果通知 notify.php(這裡的地址就是統一下單時填寫的回調地址,已經封裝好),文檔下載地址
http://mch.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1
其實這個頁面最主要的代碼就兩行

[php] view plain copy

    $notify = new PayNotifyCallBack();      $notify->Handle(false);

其中大部分邏輯在 Handle 函數中處理 檔案 WxPay.Notify.php

[php] view plain copy

    final public function Handle($needSign = true)          {              $msg = "OK";              //當返回false的時候,表示notify中調用NotifyCallBack回調失敗擷取簽名校正失敗,此時直接回複失敗              $result = WxpayApi::notify(array($this, 'NotifyCallBack'), $msg);              if($result == false){                  $this->SetReturn_code("FAIL");                  $this->SetReturn_msg($msg);                  $this->ReplyNotify(false);                  return;              } else {                  //該分支在成功回調到NotifyCallBack方法,處理完成之後流程                  $this->SetReturn_code("SUCCESS");                  $this->SetReturn_msg("OK");              }              $this->ReplyNotify($needSign);          }

主要代碼:
[php] view plain copy

    $result = WxpayApi::notify(array($this, 'NotifyCallBack'), $msg);

跟蹤函數 notify 檔案WxPay.Api.php

[php] view plain copy

    public static function notify($callback, &$msg)          {              //擷取通知的資料              $xml = $GLOBALS['HTTP_RAW_POST_DATA'];              //如果返回成功則驗證簽名              try {                  $result = WxPayResults::Init($xml);              } catch (WxPayException $e){                  $msg = $e->errorMessage();                  return false;              }              return call_user_func($callback, $result);          }

通過 $GLOBALS[‘HTTP_RAW_POST_DATA’]; 擷取同志資料 然後 Init 函數驗證簽名等。驗簽成功運行代碼.
這裡需要說明一下,php7本身不支援$GLOBALS[‘HTTP_RAW_POST_DATA’],需要下載一個外掛程式,具體什麼可自行百度,我想說的是可以用file_get_contents(‘php://input’),具體原因可參照下面的部落格,寫的很詳細(https://my.oschina.net/jiec/blog/485359)
[php] view plain copy

return call_user_func($callback, $result);

即調用了一個回呼函數,NotifyCallBack() 函數並傳遞參數 $result 在NotifyCallBack函數中會調用我們重寫的NotifyProcess()函數(此函數在notify.php 中被重寫)

NotifyProcess() 判斷也沒有問題就會 設定返回 success的xml資訊

[php] view plain copy

$this->SetReturn_code("SUCCESS");  $this->SetReturn_msg("OK");

並最終調用函數 this−>ReplyNotify(this−>ReplyNotify(needSign); echo success的結果

函數ReplyNotify 需要修改一處代碼:

[php] view plain copy

final private function ReplyNotify($needSign = true)      {          //如果需要簽名          if($needSign == true &&               $this->GetReturn_code($return_code) == "SUCCESS")          {              $this->SetSign();          }          WxpayApi::replyNotify($this->ToXml());      }

[php] view plain copy

$this->GetReturn_code($return_code) == "SUCCESS")

改為

[php] view plain copy

$this->GetReturn_code() == "SUCCESS")

即可。
然後是根據返回資訊修改訂單狀態,主要就是,在什麼地方修改,我是在notify.php裡面建立了一個方法

//修改訂單狀態    public function updateState($data){        if($data){            $order_sn = $data['out_trade_no'];\            $data = array();            $data['order_id'] = $order_id;            //修改訂單狀態(用curlpost方法請求至thinkphp目錄下的Controller裡面控制器裡面的方法,修改狀態)            $url = 'www.test.com';            header('content-type:text/html;charset=utf8');            $curl = curl_init();            curl_setopt($curl, CURLOPT_URL, $url);            curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);            curl_setopt($curl, CURLOPT_POST, true);            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);            $result = curl_exec($curl);            curl_close($curl);            if($result == 'success'){                return true;            }else{                return false;            }        }    }

然後在notify.php 的

$notify = new PayNotifyCallBack();$notify->Handle(false);

下面加上

//接受參數,修改狀態$xml = file_get_contents("php://input");$data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);$notify->updateState($data);

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.