ThinkPHP实现支付宝接口功能实例


Posted in PHP onDecember 02, 2014

本文实例讲述了ThinkPHP实现支付宝接口功能的方法。分享给大家供大家参考。具体分析如下:

最近做系统,需要实现在线支付功能,毫不犹豫,选择的是支付宝的接口支付功能,这里我用的是即时到帐的接口,具体实现的步骤如下:

一、下载支付宝接口包

下载地址:https://b.alipay.com/order/productDetail.htm?productId=2012111200373124&tabId=4#ps-tabinfo-hash

具体如何下载,我就不在罗嗦了~~

二、重新整理接口包文件,这一步应该算是比较关键的(个人认为),下载下来的接口包文件有很多语言的源码

ThinkPHP实现支付宝接口功能实例

我们选择 create_direct_pay_by_user-PHP-UTF-8 这个名称的接口文件,里面包括如下文件:

ThinkPHP实现支付宝接口功能实例

images文件里是支付宝相关的一些标志的图片,我们暂不管他,lib文件很重要,是整个接口的核心类文件;

alipay.config.php是相关参数的配置文件

alipayapi.php 是支付宝接口入口文件

notify_url.php 是服务器异步通知页面文件;

return_url.php 是页面跳转同步通知文件;

在ThinkPHP的框架文件下,找到Extend 进入,再进入Vendor,在Vendor文件夹下,新建文件夹Alipay,把支付宝作为第三方类库引入,然后,复制支付宝接口文件包中lib文件里的所有文件,一共4个文件,如下:

ThinkPHP实现支付宝接口功能实例

现在对以上文件进行重命名.

alipay_core.function.php重命名为:Corefunction.php;

alipay_md5.function.php重命名为:Md5function.php;

alipay_notify.class.php重命名为:Notify.php;

alipay_submit.class.php重命名为:Submit.php;

然后,打开Submit.php文件,把以下代码去掉;

require_once("alipay_core.function.php");

require_once("alipay_md5.function.php");同样,打开Notify.php文件,把以下两段代码去掉require_once("alipay_core.function.php");

require_once("alipay_md5.function.php");为什么要去掉以上两个文件中的这两段代码,因为在项目中调用接口文件的时候,我把所有4个核心文件都通过vendor来进行引入。所以,这不再需要导入。

到此,支付宝接口包相关核心类库的整理基本完成。现在开始在项目中调用;

三、在项目中调用支付宝接口

调用分两步:

1、在配置文件中Conf/Config.php文件中对支付宝相关参数进行配置

//支付宝配置参数  

  

'alipay_config'=>array(  

       'partner' =>'20********50',   //这里是你在成功申请支付宝接口后获取到的PID;  

    'key'=>'9t***********ie',//这里是你在成功申请支付宝接口后获取到的Key  

    'sign_type'=>strtoupper('MD5'),  

    'input_charset'=> strtolower('utf-8'),  

    'cacert'=> getcwd().'\\cacert.pem',  

    'transport'=> 'http',  

      ),  

     //以上配置项,是从接口包中alipay.config.php 文件中复制过来,进行配置;  

      

'alipay'   =>array(  

 //这里是卖家的支付宝账号,也就是你申请接口时注册的支付宝账号  

'seller_email'=>'pay@xxx.com',  

  

//这里是异步通知页面url,提交到项目的Pay控制器的notifyurl方法;  

'notify_url'=>'http://www.xxx.com/Pay/notifyurl',   

  

//这里是页面跳转通知url,提交到项目的Pay控制器的returnurl方法;  

'return_url'=>'http://www.xxx.com/Pay/returnurl',  

  

//支付成功跳转到的页面,我这里跳转到项目的User控制器,myorder方法,并传参payed(已支付列表)  

'successpage'=>'User/myorder?ordtype=payed',     

  

//支付失败跳转到的页面,我这里跳转到项目的User控制器,myorder方法,并传参unpay(未支付列表)  

'errorpage'=>'User/myorder?ordtype=unpay',   

),

2、新建一个PayAction控制器代码如下
<?php  

class PayAction extends Action{  

       //在类初始化方法中,引入相关类库      

       public function _initialize() {  

        vendor('Alipay.Corefunction');  

        vendor('Alipay.Md5function');  

        vendor('Alipay.Notify');  

        vendor('Alipay.Submit');      

    }  

      

    //doalipay方法  

          

    public function doalipay(){  

              

       // require_once("alipay.config.php");  

       // require_once("lib/alipay_submit.class.php");  

         

       //这里我们通过TP的C函数把配置项参数读出,赋给$alipay_config;  

       $alipay_config=C('alipay_config');    

  

          

  

        $payment_type = "1"; //支付类型 //必填,不能修改  

        $notify_url = C('alipay.notify_url'); //服务器异步通知页面路径  

        $return_url = C('alipay.return_url'); //页面跳转同步通知页面路径  

        $seller_email = C('alipay.seller_email');//卖家支付宝帐户必填  

        $out_trade_no = $_POST['trade_no'];//商户订单号 通过支付页面的表单进行传递,注意要唯一!  

        $subject = $_POST['ordsubject'];  //订单名称 //必填 通过支付页面的表单进行传递  

        $total_fee = $_POST['ordtotal_fee'];   //付款金额  //必填 通过支付页面的表单进行传递  

        $body = $_POST['ordbody'];  //订单描述 通过支付页面的表单进行传递  

        $show_url = $_POST['ordshow_url'];  //商品展示地址 通过支付页面的表单进行传递  

        $anti_phishing_key = "";//防钓鱼时间戳 //若要使用请调用类文件submit中的query_timestamp函数  

        $exter_invoke_ip = get_client_ip(); //客户端的IP地址   

      

        //构造要请求的参数数组,无需改动  

    $parameter = array(  

        "service" => "create_direct_pay_by_user",  

        "partner" => trim($alipay_config['partner']),  

        "payment_type"    => $payment_type,  

        "notify_url"    => $notify_url,  

        "return_url"    => $return_url,  

        "seller_email"    => $seller_email,  

        "out_trade_no"    => $out_trade_no,  

        "subject"    => $subject,  

        "total_fee"    => $total_fee,  

        "body"            => $body,  

        "show_url"    => $show_url,  

        "anti_phishing_key"    => $anti_phishing_key,  

        "exter_invoke_ip"    => $exter_invoke_ip,  

        "_input_charset"    => trim(strtolower($alipay_config['input_charset']))  

        );  

        //建立请求  

        $alipaySubmit = new AlipaySubmit($alipay_config);  

        $html_text = $alipaySubmit->buildRequestForm($parameter,"post", "确认");  

        echo $html_text;  

    }  

          

    function notifyurl(){  

                   

                //require_once("alipay.config.php");  

                //require_once("lib/alipay_notify.class.php");  

                  

                //这里还是通过C函数来读取配置项,赋值给$alipay_config  

        $alipay_config=C('alipay_config');  

  

        //计算得出通知验证结果  

        $alipayNotify = new AlipayNotify($alipay_config);  

        $verify_result = $alipayNotify->verifyNotify();  

  

        if($verify_result) {  

               //验证成功  

                   //获取支付宝的通知返回参数,可参考技术文档中服务器异步通知参数列表  

           $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(!checkorderstatus($out_trade_no)){  

               orderhandle($parameter);   

                           //进行订单处理,并传送从支付宝返回的参数;  

               }  

            }  

                echo "success";        //请不要修改或删除  

         }else {  

                //验证失败  

                echo "fail";  

        }      

    }  

      

    function returnurl(){  

                //头部的处理跟上面两个方法一样,这里不罗嗦了!  

        $alipay_config=C('alipay_config');  

        $alipayNotify = new AlipayNotify($alipay_config);//计算得出通知验证结果  

        $verify_result = $alipayNotify->verifyReturn();  

        if($verify_result) {  

            //验证成功  

            //获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表  

        $out_trade_no   = $_GET['out_trade_no'];      //商户订单号  

        $trade_no       = $_GET['trade_no'];          //支付宝交易号  

        $trade_status   = $_GET['trade_status'];      //交易状态  

        $total_fee      = $_GET['total_fee'];         //交易金额  

        $notify_id      = $_GET['notify_id'];         //通知校验ID。  

        $notify_time    = $_GET['notify_time'];       //通知的发送时间。  

        $buyer_email    = $_GET['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($_GET['trade_status'] == 'TRADE_FINISHED' || $_GET['trade_status'] == 'TRADE_SUCCESS') {  

        if(!checkorderstatus($out_trade_no)){  

             orderhandle($parameter);  //进行订单处理,并传送从支付宝返回的参数;  

    }  

        $this->redirect(C('alipay.successpage'));//跳转到配置项中配置的支付成功页面;  

    }else {  

        echo "trade_status=".$_GET['trade_status'];  

        $this->redirect(C('alipay.errorpage'));//跳转到配置项中配置的支付失败页面;  

    }  

}else {  

    //验证失败  

    //如要调试,请看alipay_notify.php页面的verifyReturn函数  

    echo "支付失败!";  

    }  

}  

}  

?>

3、这里有几个支付处理过程中需要用到的函数,我把这些函数写到了项目的Common/common.php中,这样不用手动调用,即可直接使用这些函数,代码如下:
//Orderlist数据表,用于保存用户的购买订单记录;  

  

//在线交易订单支付处理函数  

//函数功能:根据支付接口传回的数据判断该订单是否已经支付成功;  

//返回值:如果订单已经成功支付,返回true,否则返回false;  

function checkorderstatus($ordid){  

    $Ord=M('Orderlist');  

    $ordstatus=$Ord->where('ordid='.$ordid)->getField('ordstatus');  

    if($ordstatus==1){  

        return true;  

    }else{  

        return false;      

    }  

}  

  

//处理订单函数  

//更新订单状态,写入订单支付后返回的数据  

function orderhandle($parameter){  

    $ordid=$parameter['out_trade_no'];  

    $data['payment_trade_no']      =$parameter['trade_no'];  

    $data['payment_trade_status']  =$parameter['trade_status'];  

    $data['payment_notify_id']     =$parameter['notify_id'];  

    $data['payment_notify_time']   =$parameter['notify_time'];  

    $data['payment_buyer_email']   =$parameter['buyer_email'];  

    $data['ordstatus']             =1;  

    $Ord=M('Orderlist');  

    $Ord->where('ordid='.$ordid)->save($data);  

}   

  

//获取一个随机且唯一的订单号;  

function getordcode(){  

    $Ord=M('Orderlist');  

    $numbers = range (10,99);  

    shuffle ($numbers);   

    $code=array_slice($numbers,0,4);   

    $ordcode=$code[0].$code[1].$code[2].$code[3];  

    $oldcode=$Ord->where("ordcode='".$ordcode."'")->getField('ordcode');  

    if($oldcode){  

        getordcode();  

    }else{  

        return $ordcode;  

    }  

}

四、总结几点

1、接口包中lib文件中的文件复制到Vendor后,重命名为TP规范的命名规则,为的是调用方便,当然你要改成其他名称也可以;

2、把执行支付操作(doalipay),处理异步返回结果(notifyurl),处理跳转返回结果(returnurl)三个支付接口的核心页面写到一个PayAction控制器中。

3、提交支付的页面中,可以在提交之前先把一些参数要传递的内容先通过隐藏域的方法组合好,比如金额先计算好,订单名称,订单描述等先用字符串组合好。然后提交表单,这样,在doalipay方法中只要直接构造传递参数,直接进行提交就行过了。

4、支付返回后的处理因为要在异步和跳转两个方法中都要进行相应的判断和处理,所以,把这些判断和处理写到一个自定义函数中,这样只要调用函数即可,使得代码更加清晰明了。

5、notify_url和return_url两种模式的返回url必须使用http://xxxxxxx这样的绝对路径,因为里是从支付宝平台返回到你的项目页面,不能使用相对路径。

以上代码在ThinkPHP3.0中正常使用!!

希望本文所述对大家的ThinkPHP框架程序设计有所帮助。

PHP 相关文章推荐
Win2000+Apache+MySql+PHP4+PERL安装使用小结
Oct 09 PHP
用PHP发电子邮件
Oct 09 PHP
php下删除一篇文章生成的多个静态页面
Aug 08 PHP
理解和运用PHP中的多态性[译]
Aug 02 PHP
php实现遍历目录并删除指定文件中指定内容
Jan 21 PHP
php命令行(cli)模式下报require 加载路径错误的解决方法
Nov 23 PHP
PHP实现的简单分页类及用法示例
May 06 PHP
php文件上传 你真的掌握了吗
Nov 28 PHP
PHPstorm快捷键(分享)
Jul 17 PHP
快速解决PHP调用Word组件DCOM权限的问题
Dec 27 PHP
详解php协程知识点
Sep 21 PHP
Laravel 之url参数,获取路由参数的例子
Oct 21 PHP
ThinkPHP实现ajax仿官网搜索功能实例
Dec 02 #PHP
php递归json类实例
Dec 02 #PHP
php实现的SESSION类
Dec 02 #PHP
thinkphp配置连接数据库技巧
Dec 02 #PHP
Yii核心组件AssetManager原理分析
Dec 02 #PHP
php实现微信公众平台账号自定义菜单类
Dec 02 #PHP
php获取CSS文件中图片地址并下载到本地的方法
Dec 02 #PHP
You might like
20个PHP常用类库小结
2011/09/11 PHP
php中使用DOM类读取XML文件的实现代码
2011/12/14 PHP
PHP _construct()函数讲解
2019/02/03 PHP
给网站上的广告“加速”显示的方法
2007/04/08 Javascript
关于javascript中this关键字(翻译+自我理解)
2010/10/20 Javascript
jquery1.83 之前所有与异步列队相关的模块详细介绍
2012/11/13 Javascript
js onload事件不起作用示例分析
2013/10/09 Javascript
js控制当再次点击按钮时的间隔时间
2014/06/03 Javascript
js实现非常简单的焦点图切换特效实例
2015/05/07 Javascript
今天抽时间给大家整理jquery和ajax的相关知识
2015/11/17 Javascript
详解JavaScript中常用的函数类型
2015/11/18 Javascript
jQuery实现导航高亮的方法【附demo源码下载】
2016/11/09 Javascript
Bootstrap源码解读表单(2)
2016/12/22 Javascript
vue.js实现只弹一次弹框
2018/01/29 Javascript
layui点击导航栏刷新tab页的示例代码
2018/08/14 Javascript
vue中当图片地址无效的时候,显示默认图片的方法
2018/09/18 Javascript
实用的Vue开发技巧
2019/05/30 Javascript
利用百度echarts实现图表功能简单入门示例【附源码下载】
2019/06/10 Javascript
Nuxt页面级缓存的实现
2020/03/09 Javascript
一分钟学会JavaScript中的try-catch
2020/12/14 Javascript
[33:09]完美世界DOTA2联赛循环赛 Forest vs DM BO2第二场 10.29
2020/10/29 DOTA
Python 文件操作技巧(File operation) 实例代码分析
2008/08/11 Python
Python3.5装饰器原理及应用实例详解
2019/04/30 Python
python3.6 如何将list存入txt后再读出list的方法
2019/07/02 Python
python数据处理之如何选取csv文件中某几行的数据
2019/09/02 Python
Python socket模块ftp传输文件过程解析
2019/11/05 Python
用Python实现童年贪吃蛇小游戏功能的实例代码
2020/12/07 Python
如何用python爬取微博热搜数据并保存
2021/02/20 Python
塔吉特百货公司官网:Target
2017/04/27 全球购物
美国知名保健品网站:LuckyVitamin(支持中文)
2017/08/09 全球购物
工伤赔偿协议书
2014/04/15 职场文书
会计试用期自我评价
2014/09/19 职场文书
推普周国旗下讲话稿
2014/09/21 职场文书
工伤死亡理赔协议书
2014/10/20 职场文书
2014年人事专员工作总结
2014/11/19 职场文书
MySQL实例精讲单行函数以及字符数学日期流程控制
2021/10/15 MySQL