ThinkPHP整合支付宝即时到账接口调用

时间:2021-12-31 09:55:03

首先是在支付宝的蚂蚁金服开放平台下载PHP的demo:

 https://doc.open.alipay.com/doc2/detail?treeId=62&articleId=103566&docType=1

下载地址如上,里面有个MD5加密方式UTF8的PHP的demo可以拿来用,可以直接在localhost上跑,传入合适的参数即使体验支付一次,这点和微信支付接口调用的demo相同。

现在我们尝试将其中demo的lib类文件整合到thinkphp之中去。

将四个lib改名放入Vendor文件夹:(文件在我的文件之中),相比官方demo仅仅改动里面的PHP文件include

ThinkPHP整合支付宝即时到账接口调用

点击支付并传入订单ID:

   public function pay_request()
     {
         $id = intval($_GET['order_id']);//传入订单ID
         if($id){
             $o = D('order_info');
             $order_info = $o->where('order_id = %d',$id)->find();//查询出所有订单信息

             if(empty($order_info['paycode'])){
                 $order_info['paycode'] = 'Alipay';
             }
             $class = 'Com\\Pay\\'.$order_info['paycode'];
             // import($path);
             $pay = new $class;//实例化支付宝类

             $pay->getCode($order_info);
         }
     }

类文件:
ThinkPHP整合支付宝即时到账接口调用

Alipay.class.php:

在alipay里面引用vendor文件夹里面类库文件操作:

         /**
          * 引入支付宝
          */
         vendor('Alipay.Corefunction');
         vendor('Alipay.Md5function');
         vendor('Alipay.Notify');
         vendor('Alipay.Submit');

在这里复习一下ThinkPHP之中第三方类库的引用:

1、当你把类文件放在liberary下面的任意一个文件夹时候,比如alipay.class.php,给他加上相应文件夹对应的命名空间就可以直接实例化;

保存到 ThinkPHP/Library/Org/Util/Auth.class.php

 namespace Org\Util;class Auth {    }

引用:

 new \Org\Util\Auth();

此时系统会自动加载那个类文件并进行实例化。

2、注册命名空间(自己在任意位置(用常量写出绝对路径)创建文件夹并且声明为一个命名空间);类库映射(命名空间过多导致类文件加载慢)加快类文件的加载。这两个不考虑使用,仅作了解。

3、第三方类库文件的引用,比如上面的vendor文件夹下面的Alipay文件夹下面的四个类文件(里面连namespace都木有,直接就是class{###}),引用有两种方法:第一种是在任意文件夹下面乱放,然后用import方法

 // 导入Org类库包 Library/Org/Util/Date.class.php类库import("Org.Util.Date");  // 导入Home模块下面的 Application/Home/Util/UserUtil.class.php类库import("Home.Util.UserUtil");  // 导入当前模块下面的类库 import("@.Util.Array");  // 导入Vendor类库包 Library/Vendor/Zend/Server.class.phpimport('Vendor.Zend.Server');

这个我们不考虑如何具体使用,我们以后规定,统统放在vendor文件夹下面,然后我们就用一个方便的方法引用类文件,

 如果你的第三方类库都放在Vendor目录下面,并且都以.php为类文件后缀,也没用采用命名空间的话,那么可以使用系统内置的Vendor函数简化导入。例如,我们把 Zend 的 Filter\Dir.php 放到 Vendor 目录下面,这个时候 Dir 文件的路径就是 Vendor\Zend\Filter\Dir.php,我们使用vendor 方法导入只需要使用:
 Vendor('Zend.Filter.Dir');                具体看看上面alipay四个类文件的引用;
     'YUMING'    =>    'https://www.homewide.cn',
 <?php
 namespace Com\Pay;

 class Alipay
 {

     private $config;

     public function __construct($config = null)
     {
         if($config){
             $this->config = unserialize($config);
         }else{
             $this->config = array(
                 'pid'=>'**卖家申请成功后得到的PID****',
                 'key'=>'**卖家申请成功后获取的key**',
                 'seller_email'=>'***卖家支付宝账号**',
                 'notify_url'=>(C('YUMING').U('Home/Login/pay_respone')),//C(‘yunyin’)这个常量是网址www.haveadream.win
                 'return_url'=>(C('YUMING').U('Home/User/my_order')),
             );
         }
         //这里我们通过TP的C函数把配置项参数读出,赋给$alipay_config;
         $this->config['alipay_config'] = array(
            'partner' =>$this->config['pid'],   //这里是你在成功申请支付宝接口后获取到的PID;
             'key'=>$this->config['key'],//这里是你在成功申请支付宝接口后获取到的Key
             'sign_type'=>strtoupper('MD5'),
             'input_charset'=> strtolower('utf-8'),
             // 'cacert'=> getcwd().'\\domain.crt',
             'cacert'=> getcwd().'\\cacert.pem',
             'transport'=> 'http',
         );

         /**
          * 引入支付宝
          */
         vendor('Alipay.Corefunction');
         vendor('Alipay.Md5function');
         vendor('Alipay.Notify');
         vendor('Alipay.Submit');

     }

 /*生成支付按钮*/
     public function getCode($order_info)//跑这个方法的时候就已经在construct函数里面将config数据传递进去了
     {
         /*********************************************************
         把alipayapi.php中复制过来的如下两段代码去掉,
         第一段是引入配置项,
         第二段是引入submit.class.php这个类。
        为什么要去掉??
         第一,配置项的内容已经在项目的Config.php文件中进行了配置,我们只需用C函数进行调用即可;
         第二,这里调用的submit.class.php类库我们已经在PayAction的_initialize()中已经引入;所以这里不再需要;
               *****************************************************/

           /**************************请求参数**************************/
           $payment_type = "1"; //支付类型 //必填,不能修改
           $notify_url = $this->config['notify_url']; //服务器异步通知页面路径
           $return_url = $this->config['return_url']; //页面跳转同步通知页面路径
           $seller_email = $this->config['seller_email'];//卖家支付宝帐户必填
           $out_trade_no = $order_info['order_sn'];//商户订单号 通过支付页面的表单进行传递,注意要唯一!
           $subject = '家安采购订单';  //订单名称 //必填 通过支付页面的表单进行传递
           $total_fee = $order_info['pay_money'];   //付款金额  //必填 通过支付页面的表单进行传递
           //$total_fee = 0.01;   //付款金额  //必填 通过支付页面的表单进行传递
           $body = '采购上家安';  //订单描述 通过支付页面的表单进行传递
           $show_url = '';  //商品展示地址 通过支付页面的表单进行传递
           $anti_phishing_key = "";//防钓鱼时间戳 //若要使用请调用类文件submit中的query_timestamp函数
           $exter_invoke_ip = get_client_ip(); //客户端的IP地址,这个方法是ThinkPHP之中自带的方法的

           //商品数量
           $quantity = "1";
           //必填,建议默认为1,不改变值,把一次交易看成是一次下订单而非购买一件商品
           //物流费用
           $logistics_fee = "0.00";
           //必填,即运费
           //物流类型
           $logistics_type = "EXPRESS";
           //必填,三个值可选:EXPRESS(快递)、POST(平邮)、EMS(EMS)
           //物流支付方式
           $logistics_payment = "SELLER_PAY";
           //必填,两个值可选:SELLER_PAY(卖家承担运费)、BUYER_PAY(买家承担运费)
           //订单描述
           //收货人姓名
           $receive_name = $order_info['consignee'];
           //如:张三
           //收货人地址
           $receive_address = 'XX省XXX市XXX区XXX路XXX小区XXX栋XXX单元XXX号';
           //如:XX省XXX市XXX区XXX路XXX小区XXX栋XXX单元XXX号
           //收货人邮编
           $receive_zip = '123456';
           //如:123456

           //收货人电话号码
           $receive_phone = '0000-0000000';
           //如:0571-88158090

           //收货人手机号码
           $receive_mobile = '13***21';
           //如:13312341234

           /************************************************************/

       //构造要请求的参数数组,无需改动
       $parameter = array(
           "service" => "create_direct_pay_by_user",
           "partner" => trim($this->config['pid']),
           "payment_type"  => $payment_type,
           "notify_url"  => $notify_url,
           "return_url"  => $return_url,
           "seller_email"  => $seller_email,
           "out_trade_no"  => $out_trade_no,
           "subject" => $subject,
           "price" => $total_fee,
           "quantity"  => $quantity,
           "logistics_fee" => $logistics_fee,
           "logistics_type"  => $logistics_type,
           "logistics_payment" => $logistics_payment,
           "body"  => $body,
           "show_url"  => $show_url,
           "receive_name"  => $receive_name,
           "receive_address" => $receive_address,
           "receive_zip" => $receive_zip,
           "receive_phone" => $receive_phone,
           "receive_mobile"  => $receive_mobile,
           "_input_charset"  => trim(strtolower($this->config['alipay_config']['input_charset']))
       );
     //   var_dump($parameter);die;

     //   var_dump($parameter);die;

         //建立请求
         $alipaySubmit = new \AlipaySubmit($this->config['alipay_config']);
         $html_text = $alipaySubmit->buildRequestForm($parameter,"post", "");
         echo $html_text;die;
     }

     public function respone()
     {
         // file_put_contents('./pay.txt',var_export($_REQUEST,true));
         /*
         同理去掉以下两句代码;
         */
         //require_once("alipay.config.php");
         //require_once("lib/alipay_notify.class.php");
         //计算得出通知验证结果
         $alipayNotify = new \AlipayNotify($this->config['alipay_config']);
         $verify_result = $alipayNotify->verifyNotify();
         // if(!$verify_result){
         //     file_put_contents('./pay.txt','验证失败',FILE_APPEND);
         // }else{
         //     file_put_contents('./pay.txt','验证成功!',FILE_APPEND);
         // }

         if($verify_result) {
             // file_put_contents('./pay.txt','进来了',FILE_APPEND);
        //验证成功
            //获取支付宝的通知返回参数,可参考技术文档中服务器异步通知参数列表
            $out_trade_no   = $_POST['out_trade_no'];      //商户订单号
            $trade_no       = $_POST['trade_no'];          //支付宝交易号
            $trade_status   = $_POST['trade_status'];      //交易状态
            $total_fee      = $_POST['total_fee'];         //交易金额
            $notify_id      = $_POST['notify_id'];         //通知校验ID。
            $notify_time    = $_POST['notify_time'];       //通知的发送时间。格式为yyyy-MM-dd HH:mm:ss。
            $buyer_email    = $_POST['buyer_email'];       //买家支付宝帐号;
            $parameter = array(
              "out_trade_no"     => $out_trade_no, //商户订单编号;
              "trade_no"     => $trade_no,     //支付宝交易号;
              "total_fee"     => $total_fee,    //交易金额;
              "trade_status"     => $trade_status, //交易状态
              "notify_id"     => $notify_id,    //通知校验ID。
              "notify_time"   => $notify_time,  //通知的发送时间。
              "buyer_email"   => $buyer_email,  //买家支付宝帐号;
            );
            if($_POST['trade_status'] == 'TRADE_FINISHED') {

            }else if ($_POST['trade_status'] == 'TRADE_SUCCESS') {

                if(!check_order_status($out_trade_no)){
                 //    file_put_contents('./pay.txt','1进来了',FILE_APPEND);
                    $data = array(
                        'order_sn'=>$out_trade_no,
                        'des'=>('订单交易:'.$out_trade_no),
                        'money'=>$total_fee,
                    );
                    orderhandle($data);
                    //进行订单处理,并传送从支付宝返回的参数;
                }
             }
             echo "success";        //请不要修改或删除
         }else {
             //验证失败
             echo "fail";
             // file_put_contents('./pay.txt',var_export($verify_result,true),FILE_APPEND);
             // file_put_contents('./pay.txt',var_export($this->config,true),FILE_APPEND);
             file_put_contents('./pay.txt','验证失败',FILE_APPEND);
         }
     }

 }
 ?>
U('Home/Login/pay_respone')://服务器异步通知页面路径
   public function pay_respone()
     {
         // file_put_contents('./pay.txt',var_export($_REQUEST,true));
         if(IS_POST){
             $o = D('order_info');
             $order_info = $o->where('order_sn = "%s"',$_POST['out_trade_no'])->find();
             if(empty($order_info['paycode'])){
                 $order_info['paycode'] = 'Alipay';
             }
             $class = 'Com\\Pay\\'.$order_info['paycode'];
             // import($path);
             $pay = new $class;
             $pay->respone();
         }
     }
U('Home/User/my_order')://页面跳转同步通知页面路径
  public function my_order(){
        /* 取出左边分类栏目start */
        $c = D('category');
        $left_menu = $c->get_category();
        $this->assign('category_menu',$left_menu);
        /* 取出左边分类栏目end */
        //取出该采购商所有订单信息
        $o = D('order_info');
        $list = $o->getList();
        $page = $o->getPage();
        $countNum = $o->getCount();
        //  var_dump($res);
        $this->assign('list',$list);
        $this->assign('page',$page);
        $this->assign('countNum',$countNum);
        //获取总金额
        $this->assign('countMoney',sprintf('%.2f',$o->get_order_count_num()));

        $other = array(
            'is_submit'=>$o->get_order_num('is_submit'),
            'is_send'=>$o->get_order_num('is_send'),
            'is_ok'=>$o->get_order_num('is_ok'),
            'is_cancel'=>$o->get_order_num('is_cancel'),
        );
        $this->assign($other);

        $this->display();
    }

上面就是所有的alipay的接口调用,以及回调数据处理了

付款成功跳转的HTML:

 <div class="status">
 <ul class="title_tab">
  <li id="btn_alreadyCommit" onclick="location.href='{:U('User/my_order',array('other'=>'is_submit'))}'" class="li <?php if($_GET['other'] == 'is_submit'){echo 'cur';} ?>" style="cursor:pointer">已提交<em class="f_bold c_f00">({$is_submit})</em></li>
  <li id="btn_alreadySure" onclick="location.href='{:U('User/my_order',array('other'=>'is_send'))}'" class="li <?php if($_GET['other'] == 'is_send'){echo 'cur';} ?>" style="cursor:pointer">已发货<em class="f_bold c_f00">({$is_send})</em></li>
  <li id="btn_alreadyComplay" class="li <?php if($_GET['other'] == 'is_ok'){echo 'cur';} ?>" onclick="location.href='{:U('User/my_order',array('other'=>'is_ok'))}'" style="cursor:pointer">交易完成<em class="f_bold c_f00">({$is_ok})</em></li>
  <li id="btn_alreadyCancel" onclick="location.href='{:U('User/my_order',array('other'=>'is_cancel'))}'" class="li <?php if($_GET['other'] == 'is_cancel'){echo 'cur';} ?>" style="cursor:pointer">已取消<em class="f_bold c_f00">({$is_cancel})</em></li>
 </ul>
 </div>

ThinkPHP整合支付宝即时到账接口调用

更详细参考文档:

 http://www.thinkphp.cn/code/240.html

说了那么多,四个官方给的lib里面的类文件还是得看啊,兄弟!!!