ThinkPHP整合支付寶擔保交易

ThinkPHP整合支付寶擔保交易本代碼參考大神 http://www.thinkphp.cn/code/240.html 的思路 1.登錄支付寶後臺,下載擔保交易的集成包。 2.下載完成後的文件說明: 純擔保交易接口-create_partner_trade_by_buyer(2

ThinkPHP整合支付寶擔保交易
本代碼參考大神 http://www.thinkphp.cn/code/240.html 的思路

1.登錄支付寶後臺,下載擔保交易的集成包。


2.下載完成後的文件說明:

純擔保交易接口-create_partner_trade_by_buyer(20151015)
確認發貨接口-send_goods_confirm_by_platform(20150312)
根據本身須要去選擇,須要說明下,先擔保整合完成後纔回去處理確認發貨,由於確認發貨時須要擔保交易的支付寶交易編號

對應的代碼文件結構php

  1. ───────
  2. create_partner_trade_by_buyer-php-UTF-8
  3.   
  4.   lib┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈類文件夾
  5.     
  6.     alipay_core.function.php ┈┈┈┈┈┈支付寶接口公用函數文件
  7.     
  8.     alipay_notify.class.php┈┈┈┈┈┈┈支付寶通知處理類文件
  9.     
  10.     alipay_submit.class.php┈┈┈┈┈┈┈支付寶各接口請求提交類文件
  11.     
  12.     alipay_md5.function.php┈┈┈┈┈┈┈支付寶接口MD5函數文件
  13.   
  14.   log.txt┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈日誌文件
  15.   
  16.   alipay.config.php┈┈┈┈┈┈┈┈┈┈┈┈基礎配置類文件
  17.   
  18.   alipayapi.php┈┈┈┈┈┈┈┈┈┈┈┈┈┈支付寶接口入口文件
  19.   
  20.   notify_url.php ┈┈┈┈┈┈┈┈┈┈┈┈┈服務器異步通知頁面文件
  21.   
  22.   return_url.php ┈┈┈┈┈┈┈┈┈┈┈┈┈頁面跳轉同步通知文件
  23.   
  24.   cacert.pem ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈用於CURL中校驗SSLCA證書文件
  25.   
  26.   readme.txt ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈使用說明文本
複製

這裏咱們先處理代碼

3.核心處理代碼

把lib目錄文件下的4個核心文件放入 ThinkPHP/Library/Vendor/Alipay 下

修改文件名爲:html

  1. alipay_core.function.php       ->        Corefunction.php
  2. alipay_notify.class.php        ->        Notify.php
  3. alipay_submit.class.php        ->        Submit.php
  4. alipay_md5.function.php        ->        Md5function.php
  5. 其中 Notify.php  Md5function.php 須要刪除前面引入的兩行代碼
複製

require_once("alipay_core.function.php");
require_once("alipay_md5.function.php");
由於在使用TP第三方擴展類的時候會自動引入他須要的這兩個文件

核心框架整合完成以後咱們來整理邏輯代碼。

4.邏輯代碼整理

首先咱們把 簽名文件 cacert.pem 放在網站的跟目錄,其餘目錄也行,不過須要有訪問權限的

而後在公共配置文件conf.php中添加 支付寶配置node

  1.     //支付寶配置參數
  2. 'alipay_config'=>array(
  3.     'partner' =>'2088**********************',   //這裏是你在成功申請支付寶接口後獲取到的PID;
  4.     'key'=>'ob4x7k0*************************',//這裏是你在成功申請支付寶接口後獲取到的Key
  5.     'sign_type'=>strtoupper('MD5'),
  6.     'input_charset'=> strtolower('utf-8'),
  7.     'cacert'=> getcwd().'\\cacert.pem',//liunx這裏須要注意 \\ 和 / 在liunx的區別
  8.     'transport'=> 'http',
  9.     'seller_email'=>'775919499@qq.com',// 這裏是你的收款帳號,
  10. ),
  11. //以上配置項,是從接口包中alipay.config.php 文件中複製過來,進行配置;
  12.     'alipay'   =>array(
  13. //這裏是異步通知頁面url,提交到項目的Pay控制器的notifyurl方法;
  14. 'notify_url'=>'http://www.loveteemo.com/Pay/notifyurl', 
  15. //這裏是頁面跳轉通知url,提交到項目的Pay控制器的returnurl方法;
  16. 'return_url'=>'http://www.loveteemo.com/Pay/returnurl',
  17. ),
複製

而後去建立一個 Key 控制器,而後處理代碼:web

  1. <?php
  2. namespace Home\Controller;
  3. use Think\Controller;
  4. class KeyController extends Controller {
  5.     //利用構造函數引入核心文件
  6.     public function _initialize() {
  7.         vendor('Alipay.Corefunction');
  8.         vendor('Alipay.Md5function');
  9.         vendor('Alipay.Notify');
  10.         vendor('Alipay.Submit');    
  11.     }
  12.   //首頁,用來展現商品頁
  13.     public function index(){
  14.         $this->display();
  15.     }
  16.     //訂單頁,我寫死了的,能夠根據本身須要進行修改
  17.     public function order(){
  18.         $type = I('get.type');
  19.         if($type==1){
  20.         $date = array('type'=>1,"price"=>'0.01',"name"=>"《火星救援》");
  21.         }elseif($type==2){
  22.         $date = array('type'=>2,"price"=>'0.01',"name"=>"《死神的精確度》");
  23.         }elseif($type==3){
  24.         $date = array('type'=>3,"price"=>'0.01',"name"=>"《寂寞是毒,也是解藥》");
  25.         }elseif($type==4){
  26.         $date = array('type'=>4,"price"=>'0.01',"name"=>"《只要不忘了回家的路》");
  27.         }elseif($type==5){
  28.         $date = array('type'=>5,"price"=>'0.01',"name"=>"《異想星球 hello,我是託比小黑》");
  29.         }elseif($type==6){
  30.         $date = array('type'=>6,"price"=>'0.01',"name"=>"《張鳴說歷史:大國的虛與實》");
  31.         }
  32.         $this->time = time();
  33.         $this->assign("data",$date);
  34.         $this->display();
  35.     }
  36.     //訂單頁點擊提交,傳遞必要參數後開始支付,可自行修改
  37.     public function payorder(){
  38.         //傳遞數組配置
  39.         $alipay_config=C('alipay_config');
  40.         /**************************請求參數**************************/
  41.             //支付類型
  42.         $payment_type = "1";        //必填,不能修改
  43.         //服務器異步通知頁面路徑
  44.         $notify_url = C('alipay.notify_url');        //需http://格式的完整路徑,不能加?id=123這類自定義參數
  45.         //頁面跳轉同步通知頁面路徑
  46.         $return_url = C('alipay.return_url');         //需http://格式的完整路徑,不能加?id=123這類自定義參數,不能寫成http://localhost/
  47.         //商戶訂單號
  48.         $out_trade_no = $_POST['orderid'];        //商戶網站訂單系統中惟一訂單號,必填
  49.         //訂單名稱
  50.         $subject = $_POST['ordername'];        //必填
  51.         //付款金額
  52.         $price = $_POST['orderprice'];        //必填
  53.         //商品數量
  54.         $quantity = "1";        //必填,建議默認爲1,不改變值,把一次交易當作是一次下訂單而非購買一件商品
  55.         //物流費用
  56.         $logistics_fee = "0.00";        //必填,即運費
  57.         //物流類型
  58.         $logistics_type = "EXPRESS";        //必填,三個值可選:EXPRESS(快遞)、POST(平郵)、EMS(EMS)
  59.         //物流支付方式
  60.         $logistics_payment = "SELLER_PAY";        //必填,兩個值可選:SELLER_PAY(賣家承擔運費)、BUYER_PAY(買家承擔運費)
  61.         //訂單描述
  62.         $body = $_POST['orderbody'];
  63.             //商品展現地址
  64.         $show_url = $_POST['ordershow'];        //需以http://開頭的完整路徑,如:http://www.商戶網站.com/myorder.html
  65.         //收貨人姓名
  66.         $receive_name = $_POST['user_name'];        //如:張三
  67.         //收貨人地址
  68.         $receive_address = $_POST['user_address'];        //如:XX省XXX市XXX區XXX路XXX小區XXX棟XXX單元XXX號
  69.         //收貨人郵編
  70.         $receive_zip = $_POST['user_zip'];        //如:123456
  71.         //收貨人電話號碼
  72.         $receive_phone = $_POST['user_phone'];        //如:0571-88158090
  73.         //收貨人手機號碼
  74.         $receive_mobile = $_POST['user_mobile'];        //如:13312341234
  75.         /************************************************************/
  76.     
  77.         //構造要請求的參數數組,無需改動
  78.             $parameter = array(
  79.             "service" => "create_partner_trade_by_buyer",
  80.             "partner" => trim($alipay_config['partner']),
  81.             "seller_email" => trim($alipay_config['seller_email']),
  82.             "payment_type"=> $payment_type,
  83.             "notify_url"=> $notify_url,
  84.             "return_url"=> $return_url,
  85.             "out_trade_no"=> $out_trade_no,
  86.             "subject"=> $subject,
  87.             "price"=> $price,
  88.             "quantity"=> $quantity,
  89.             "logistics_fee"=> $logistics_fee,
  90.             "logistics_type"=> $logistics_type,
  91.             "logistics_payment"=> $logistics_payment,
  92.             "body"=> $body,
  93.             "show_url"=> $show_url,
  94.             "receive_name"=> $receive_name,
  95.             "receive_address"=> $receive_address,
  96.             "receive_zip"=> $receive_zip,
  97.             "receive_phone"=> $receive_phone,
  98.             "receive_mobile"=> $receive_mobile,
  99.             "_input_charset"=> trim(strtolower($alipay_config['input_charset']))
  100.             );
  101.             //存入數據庫訂單信息 static爲99是無效訂單
  102.             M('test')->add(array("orderid"=>$out_trade_no,"addtime"=>time(),"ordername"=>$subject,"orderprice"=>$price,"static"=>99));
  103.             //創建請求
  104.             $alipaySubmit = new \AlipaySubmit($alipay_config);
  105.             //dump($alipaySubmit);die;
  106.             $html_text = $alipaySubmit->buildRequestForm($parameter,"get", "確認");
  107.             echo $html_text;
  108.             }
  109.     /******************************    服務器異步通知頁面方法    *******************************/
  110.     public function notifyurl(){
  111.         //防止亂碼
  112.         header("Content-Type:text/html;charset=utf-8");
  113.         //計算得出通知驗證結果
  114.         $alipay_config=C('alipay_config');
  115.         $alipayNotify = new \AlipayNotify($alipay_config);
  116.         $verify_result = $alipayNotify->verifyNotify();
  117.         if($verify_result) {//驗證成功
  118.         //商戶訂單號
  119.         logResult("訂單編號:".$_POST['out_trade_no'].",狀態".$_POST['trade_status']."");
  120.         $out_trade_no = $_POST['out_trade_no'];
  121.         //支付寶交易號
  122.         $trade_no = $_POST['trade_no'];
  123.         //交易狀態
  124.         $trade_status = $_POST['trade_status'];
  125.         if($_POST['trade_status'] == 'WAIT_BUYER_PAY') {
  126.         //該判斷表示買家已在支付寶交易管理中產生了交易記錄,但沒有付款
  127.         //判斷該筆訂單是否在商戶網站中已經作過處理
  128.         //若是沒有作過處理,根據訂單號(out_trade_no)在商戶網站的訂單系統中查到該筆訂單的詳細,並執行商戶的業務程序
  129.         //若是有作過處理,不執行商戶的業務程序
  130.                 echo "success";//請不要修改或刪除
  131.                 //調試用,寫文本函數記錄程序運行狀況是否正常
  132.                 //獲取支付寶的訂單號後寫入數據庫,修改訂單狀態爲0 待支付
  133.                M('test')->where(array("orderid"=>$out_trade_no))->save(array("static"=>0,"lasttime"=>time(),'payid'=>$trade_no));
  134.                //文本日誌文件,這裏的日誌文件會在網站根目錄生成一個log.txt文件
  135.                 logResult("這裏是等待付款");
  136.             }
  137.         else if($_POST['trade_status'] == 'WAIT_SELLER_SEND_GOODS') {
  138.         //該判斷表示買家已在支付寶交易管理中產生了交易記錄且付款成功,但賣家沒有發貨
  139.         //判斷該筆訂單是否在商戶網站中已經作過處理
  140.         //買家支付後,修改狀態爲已支付代發貨
  141.         M('test')->where(array("orderid"=>$out_trade_no))->save(array("static"=>1,"lasttime"=>time()));
  142.         //若是沒有作過處理,根據訂單號(out_trade_no)在商戶網站的訂單系統中查到該筆訂單的詳細,並執行商戶的業務程序
  143.         //若是有作過處理,不執行商戶的業務程序
  144.                 echo "success";//請不要修改或刪除
  145.                 //調試用,寫文本函數記錄程序運行狀況是否正常
  146.                 logResult("支付完成!訂單編號:".$out_trade_no.",狀態".$_POST['trade_status']."");
  147.             }
  148.         else if($_POST['trade_status'] == 'WAIT_BUYER_CONFIRM_GOODS') {
  149.         //該判斷表示賣家已經發了貨,但買家尚未作確認收貨的操做
  150.         //判斷該筆訂單是否在商戶網站中已經作過處理
  151.         //發貨完成後會修改狀態
  152.         M('test')->where(array("orderid"=>$out_trade_no))->save(array("static"=>2,"lasttime"=>time()));
  153.         //若是沒有作過處理,根據訂單號(out_trade_no)在商戶網站的訂單系統中查到該筆訂單的詳細,並執行商戶的業務程序
  154.         //若是有作過處理,不執行商戶的業務程序
  155.                 echo "success";//請不要修改或刪除
  156.                 //調試用,寫文本函數記錄程序運行狀況是否正常
  157.                 logResult("發貨完成,等待買家收貨");
  158.             }
  159.         else if($_POST['trade_status'] == 'TRADE_FINISHED') {
  160.         //該判斷表示買家已經確認收貨,這筆交易完成
  161.         //判斷該筆訂單是否在商戶網站中已經作過處理
  162.         //買家收貨後訂單完成
  163.         M('test')->where(array("orderid"=>$out_trade_no))->save(array("static"=>3,"lasttime"=>time()));
  164.         //若是沒有作過處理,根據訂單號(out_trade_no)在商戶網站的訂單系統中查到該筆訂單的詳細,並執行商戶的業務程序
  165.         //若是有作過處理,不執行商戶的業務程序
  166.                 echo "success";//請不要修改或刪除
  167.                 //調試用,寫文本函數記錄程序運行狀況是否正常
  168.                 logResult("交易完成!");
  169.             }
  170.             else {
  171.         //其餘狀態判斷
  172.                 echo "success";
  173.                 //調試用,寫文本函數記錄程序運行狀況是否正常
  174.                 logResult ("錯誤");
  175.             }
  176.         }
  177.         else {
  178.             //驗證失敗
  179.             echo "fail";
  180.             //調試用,寫文本函數記錄程序運行狀況是否正常
  181.             logResult("驗證失敗");
  182.         }
  183.     }
  184.     
  185.     /*        頁面跳轉處理方法;        */
  186.     public function returnurl(){
  187.         $alipay_config=C('alipay_config');
  188.          //計算得出通知驗證結果
  189.         $alipayNotify = new \AlipayNotify($alipay_config);
  190.         $verify_result = $alipayNotify->verifyReturn();
  191.         if($verify_result) {//驗證成功
  192.         //——請根據您的業務邏輯來編寫程序(如下代碼僅做參考)——
  193.             //獲取支付寶的通知返回參數,可參考技術文檔中頁面跳轉同步通知參數列表
  194.         //商戶訂單號
  195.         $out_trade_no = $_GET['out_trade_no'];
  196.         //支付寶交易號
  197.         $trade_no = $_GET['trade_no'];
  198.         //交易狀態
  199.         $trade_status = $_GET['trade_status'];
  200.             if($_GET['trade_status'] == 'WAIT_SELLER_SEND_GOODS') {
  201.         //判斷該筆訂單是否在商戶網站中已經作過處理
  202.         //若是沒有作過處理,根據訂單號(out_trade_no)在商戶網站的訂單系統中查到該筆訂單的詳細,並執行商戶的業務程序
  203.         //若是有作過處理,不執行商戶的業務程序
  204.             }
  205.         //
  206.             else {
  207.               echo "trade_status=".$_GET['trade_status'];
  208.             }
  209.         $this->assign("payid",$trade_no);
  210.         }
  211.         else {
  212.             //驗證失敗
  213.             //如要調試,請看alipay_notify.php頁面的verifyReturn函數
  214.             echo "驗證失敗";
  215.         }
  216.         $this->display();
  217. }
  218. //自動發貨 利用隱藏表單傳遞必須數據過來
  219.        public function sendgoods(){
  220.             $alipay_config=C('alipay_config');
  221.              /**************************請求參數**************************/
  222.         //支付寶交易號
  223.         $trade_no = $_POST['WIDtrade_no'];
  224.         //必填
  225.         //物流公司名稱
  226.         $logistics_name = $_POST['WIDlogistics_name'];
  227.         //必填
  228.         //物流發貨單號
  229.         $invoice_no = $_POST['WIDinvoice_no'];
  230.         //物流運輸類型
  231.         $transport_type = $_POST['WIDtransport_type'];
  232.         //三個值可選:POST(平郵)、EXPRESS(快遞)、EMS(EMS)
  233.         /************************************************************/
  234.         //構造要請求的參數數組,無需改動
  235.         $parameter = array(
  236.         "service" => "send_goods_confirm_by_platform",
  237.         "partner" => trim($alipay_config['partner']),
  238.         "trade_no"=> $trade_no,
  239.         "logistics_name"=> $logistics_name,
  240.         "invoice_no"=> $invoice_no,
  241.         "transport_type"=> $transport_type,
  242.         "_input_charset"=> trim(strtolower($alipay_config['input_charset']))
  243.         );
  244.         //創建請求
  245.         $alipaySubmit = new \AlipaySubmit($alipay_config);
  246.         $html_text = $alipaySubmit->buildRequestHttp($parameter);
  247.         //解析XML
  248.         //注意:該功能PHP5環境及以上支持,需開通curl、SSL等PHP配置環境。建議本地調試時使用PHP開發軟件
  249.         $doc = new \DOMDocument();
  250.         $doc->loadXML($html_text);
  251.         //請在這裏加上商戶的業務邏輯程序代碼
  252.         //——請根據您的業務邏輯來編寫程序(如下代碼僅做參考)——
  253.         //獲取支付寶的通知返回參數,可參考技術文檔中頁面跳轉同步通知參數列表
  254.         //解析XML
  255.         if( ! empty($doc->getElementsByTagName( "alipay" )->item(0)->nodeValue) ) {
  256.         $alipay = $doc->getElementsByTagName( "alipay" )->item(0)->nodeValue;
  257.         //echo $alipay;
  258.         //M('test')->where(array("orderid"=>$out_trade_no))->save(array("static"=>2,"lasttime"=>time()));
  259.         $this->success("自動發貨完成!","/Home/Key/lists");
  260.         }
  261. }
  262.     //篩選無效訂單後展現
  263.     public function lists(){
  264.         $lists = M('test')->where("static != 99")->limit(20)->order("id desc")->select();
  265.         $this->assign("lists",$lists);
  266.         $this->display();
  267.     }
  268. }[code]到這裏基本的業務邏輯就完成了,附帶測試的數據庫給你們分享下[code]CREATE TABLE `web_test` (
  269.   `id` int(11) NOT NULL AUTO_INCREMENT,
  270.   `orderid` varchar(16) NOT NULL,
  271.   `ordername` varchar(128) NOT NULL,
  272.   `orderprice` varchar(16) NOT NULL,
  273.   `static` int(11) NOT NULL COMMENT '0爲未支付,1爲已支付未發貨,2爲發貨爲確認收,3爲確認收,4爲取消',
  274.   `addtime` int(11) NOT NULL,
  275.   `lasttime` int(11) NOT NULL,
  276.   `payid` varchar(32) NOT NULL,
  277.   PRIMARY KEY (`id`),
  278.   UNIQUE KEY `orderid` (`orderid`)
  279. ) ENGINE=InnoDB AUTO_INCREMENT=43 DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
複製

5.須要注意的地方:

簽名的目錄,上面有說過,簽名的目錄在liunx和windows是有區別的,liunx須要改爲thinkphp

  1.  'cacert'=> getcwd().'/cacert.pem',
複製

否則會報錯說簽名沒找到



在部署完成後測試的時候會遇到有些瀏覽器亂碼,谷歌正常

這裏須要注意的是TP在異步的時候會出現,在urldecode的時候中文出現亂碼,因此在這裏我在前面加一行代碼防止亂碼數據庫

  1. header("Content-Type:text/html;charset=utf-8");
複製

本地測試異步中寫操做數據庫是沒任何意義的

由於異步須要服務器上測試才行的。windows

相關文章
相關標籤/搜索