這篇文章給大家分享的內容是關於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的時候都平心靜氣一些,理智的找問題才會更快的找到問題( 如果實在不行就去找支付寶的手動支援,他會為你調試你的程式碼,會給出一個差不多的結論,然後你再去改就會容易很多:) ).
最後希望大家支付,回調都可以成功!
相關推薦:
以上是php實作支付寶app支付和非同步通知的程式碼實例的詳細內容。更多資訊請關注PHP中文網其他相關文章!