热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

ThinkPHP实现支付宝接口功能

最近做系统,需要实现在线支付功能,毫不犹豫,选择的是支付宝的接口支付功能,这里我用的是即时到帐的接口,具体实现的步骤如下:一、下载支付宝接口包,下载地址:https://b.alipay.com/order/produc

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

一、下载支付宝接口包

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

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

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

\

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

\

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

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

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

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

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

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

\

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

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文件中对支付宝相关参数进行配置

  1. //支付宝配置参数 
  2.  
  3. 'alipay_config'=>array
  4.        'partner' =>'20********50',   //这里是你在成功申请支付宝接口后获取到的PID; 
  5.     'key'=>'9t***********ie',//这里是你在成功申请支付宝接口后获取到的Key 
  6.     'sign_type'=>strtoupper('MD5'), 
  7.     'input_charset'=> strtolower('utf-8'), 
  8.     'cacert'=> getcwd().'\\cacert.pem'
  9.     'transport'=> 'http'
  10.       ), 
  11.      //以上配置项,是从接口包中alipay.config.php 文件中复制过来,进行配置; 
  12.      
  13. 'alipay'   =>array
  14.  //这里是卖家的支付宝账号,也就是你申请接口时注册的支付宝账号 
  15. 'seller_email'=>'pay@xxx.com'
  16.  
  17. //这里是异步通知页面url,提交到项目的Pay控制器的notifyurl方法; 
  18. 'notify_url'=>'http://www.xxx.com/Pay/notifyurl',  
  19.  
  20. //这里是页面跳转通知url,提交到项目的Pay控制器的returnurl方法; 
  21. 'return_url'=>'http://www.xxx.com/Pay/returnurl'
  22.  
  23. //支付成功跳转到的页面,我这里跳转到项目的User控制器,myorder方法,并传参payed(已支付列表) 
  24. 'successpage'=>'User/myorder?ordtype=payed',    
  25.  
  26. //支付失败跳转到的页面,我这里跳转到项目的User控制器,myorder方法,并传参unpay(未支付列表) 
  27. 'errorpage'=>'User/myorder?ordtype=unpay',  
  28. ), 

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

  1.  
  2. class PayAction extends Action{ 
  3.        //在类初始化方法中,引入相关类库     
  4.        public function _initialize() { 
  5.         vendor('Alipay.Corefunction'); 
  6.         vendor('Alipay.Md5function'); 
  7.         vendor('Alipay.Notify'); 
  8.         vendor('Alipay.Submit');     
  9.     } 
  10.      
  11.     //doalipay方法 
  12.          
  13.     public function doalipay(){ 
  14.              
  15.        // require_once("alipay.config.php"); 
  16.        // require_once("lib/alipay_submit.class.php"); 
  17.         
  18.        //这里我们通过TP的C函数把配置项参数读出,赋给$alipay_config; 
  19.        $alipay_config=C('alipay_config');   
  20.  
  21.          
  22.  
  23.         $payment_type = "1"//支付类型 //必填,不能修改 
  24.         $notify_url = C('alipay.notify_url'); //服务器异步通知页面路径 
  25.         $return_url = C('alipay.return_url'); //页面跳转同步通知页面路径 
  26.         $seller_email = C('alipay.seller_email');//卖家支付宝帐户必填 
  27.         $out_trade_no = $_POST['trade_no'];//商户订单号 通过支付页面的表单进行传递,注意要唯一! 
  28.         $subject = $_POST['ordsubject'];  //订单名称 //必填 通过支付页面的表单进行传递 
  29.         $total_fee = $_POST['ordtotal_fee'];   //付款金额  //必填 通过支付页面的表单进行传递 
  30.         $body = $_POST['ordbody'];  //订单描述 通过支付页面的表单进行传递 
  31.         $show_url = $_POST['ordshow_url'];  //商品展示地址 通过支付页面的表单进行传递 
  32.         $anti_phishing_key = "";//防钓鱼时间戳 //若要使用请调用类文件submit中的query_timestamp函数 
  33.         $exter_invoke_ip = get_client_ip(); //客户端的IP地址  
  34.          
  35.      
  36.         //构造要请求的参数数组,无需改动 
  37.     $parameter = array
  38.         "service" => "create_direct_pay_by_user"
  39.         "partner" => trim($alipay_config['partner']), 
  40.         "payment_type"    => $payment_type
  41.         "notify_url"    => $notify_url
  42.         "return_url"    => $return_url
  43.         "seller_email"    => $seller_email
  44.         "out_trade_no"    => $out_trade_no
  45.         "subject"    => $subject
  46.         "total_fee"    => $total_fee
  47.         "body"            => $body
  48.         "show_url"    => $show_url
  49.         "anti_phishing_key"    => $anti_phishing_key
  50.         "exter_invoke_ip"    => $exter_invoke_ip
  51.         "_input_charset"    => trim(strtolower($alipay_config['input_charset'])) 
  52.         ); 
  53.         //建立请求 
  54.         $alipaySubmit = new AlipaySubmit($alipay_config); 
  55.         $html_text = $alipaySubmit->buildRequestForm($parameter,"post""确认"); 
  56.         echo $html_text
  57.     } 
  58.      
  59.  
  60.          
  61.     function notifyurl(){ 
  62.                   
  63.                 //require_once("alipay.config.php"); 
  64.                 //require_once("lib/alipay_notify.class.php"); 
  65.                  
  66.                 //这里还是通过C函数来读取配置项,赋值给$alipay_config 
  67.         $alipay_config=C('alipay_config'); 
  68.  
  69.         //计算得出通知验证结果 
  70.         $alipayNotify = new AlipayNotify($alipay_config); 
  71.         $verify_result = $alipayNotify->verifyNotify(); 
  72.  
  73.         if($verify_result) { 
  74.                //验证成功 
  75.                    //获取支付宝的通知返回参数,可参考技术文档中服务器异步通知参数列表 
  76.            $out_trade_no   = $_POST['out_trade_no'];      //商户订单号 
  77.            $trade_no       = $_POST['trade_no'];          //支付宝交易号 
  78.            $trade_status   = $_POST['trade_status'];      //交易状态 
  79.            $total_fee      = $_POST['total_fee'];         //交易金额 
  80.            $notify_id      = $_POST['notify_id'];         //通知校验ID。 
  81.            $notify_time    = $_POST['notify_time'];       //通知的发送时间。格式为yyyy-MM-dd HH:mm:ss。 
  82.            $buyer_email    = $_POST['buyer_email'];       //买家支付宝帐号; 
  83.                    $parameter = array
  84.              "out_trade_no"     => $out_trade_no//商户订单编号; 
  85.              "trade_no"     => $trade_no,     //支付宝交易号; 
  86.              "total_fee"     => $total_fee,    //交易金额; 
  87.              "trade_status"     => $trade_status//交易状态 
  88.              "notify_id"     => $notify_id,    //通知校验ID。 
  89.              "notify_time"   => $notify_time,  //通知的发送时间。 
  90.              "buyer_email"   => $buyer_email,  //买家支付宝帐号; 
  91.            ); 
  92.            if($_POST['trade_status'] == 'TRADE_FINISHED') { 
  93.                        // 
  94.            }else if ($_POST['trade_status'] == 'TRADE_SUCCESS') {                           if(!checkorderstatus($out_trade_no)){ 
  95.                orderhandle($parameter);  
  96.                            //进行订单处理,并传送从支付宝返回的参数; 
  97.                } 
  98.             } 
  99.                 echo "success";        //请不要修改或删除 
  100.          }else { 
  101.                 //验证失败 
  102.                 echo "fail"
  103.         }     
  104.     } 
  105.      
  106.      
  107.     function returnurl(){ 
  108.                 //头部的处理跟上面两个方法一样,这里不罗嗦了! 
  109.         $alipay_config=C('alipay_config'); 
  110.         $alipayNotify = new AlipayNotify($alipay_config);//计算得出通知验证结果 
  111.         $verify_result = $alipayNotify->verifyReturn(); 
  112.         if($verify_result) { 
  113.             //验证成功 
  114.             //获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表 
  115.         $out_trade_no   = $_GET['out_trade_no'];      //商户订单号 
  116.         $trade_no       = $_GET['trade_no'];          //支付宝交易号 
  117.         $trade_status   = $_GET['trade_status'];      //交易状态 
  118.         $total_fee      = $_GET['total_fee'];         //交易金额 
  119.         $notify_id      = $_GET['notify_id'];         //通知校验ID。 
  120.         $notify_time    = $_GET['notify_time'];       //通知的发送时间。 
  121.         $buyer_email    = $_GET['buyer_email'];       //买家支付宝帐号; 
  122.              
  123.         $parameter = array
  124.             "out_trade_no"     => $out_trade_no,      //商户订单编号; 
  125.             "trade_no"     => $trade_no,          //支付宝交易号; 
  126.             "total_fee"      => $total_fee,         //交易金额; 
  127.             "trade_status"     => $trade_status,      //交易状态 
  128.             "notify_id"      => $notify_id,         //通知校验ID。 
  129.             "notify_time"    => $notify_time,       //通知的发送时间。 
  130.             "buyer_email"    => $buyer_email,       //买家支付宝帐号 
  131.         ); 
  132.          
  133. if($_GET['trade_status'] == 'TRADE_FINISHED' || $_GET['trade_status'] == 'TRADE_SUCCESS') { 
  134.         if(!checkorderstatus($out_trade_no)){ 
  135.              orderhandle($parameter);  //进行订单处理,并传送从支付宝返回的参数; 
  136.     } 
  137.         $this->redirect(C('alipay.successpage'));//跳转到配置项中配置的支付成功页面; 
  138.     }else { 
  139.         echo "trade_status=".$_GET['trade_status']; 
  140.         $this->redirect(C('alipay.errorpage'));//跳转到配置项中配置的支付失败页面; 
  141.     } 
  142. }else { 
  143.     //验证失败 
  144.     //如要调试,请看alipay_notify.php页面的verifyReturn函数 
  145.     echo "支付失败!"
  146.     } 
  147. ?> 

3、这里有几个支付处理过程中需要用到的函数,我把这些函数写到了项目的Common/common.php中,这样不用手动调用,即可直接使用这些函数,代码如下:

  1. //Orderlist数据表,用于保存用户的购买订单记录; 
  2.  
  3. //在线交易订单支付处理函数 
  4. //函数功能:根据支付接口传回的数据判断该订单是否已经支付成功; 
  5. //返回值:如果订单已经成功支付,返回true,否则返回false; 
  6. function checkorderstatus($ordid){ 
  7.     $Ord=M('Orderlist'); 
  8.     $ordstatus=$Ord->where('ordid='.$ordid)->getField('ordstatus'); 
  9.     if($ordstatus==1){ 
  10.         return true; 
  11.     }else
  12.         return false;     
  13.     } 
  14.  
  15. //处理订单函数 
  16. //更新订单状态,写入订单支付后返回的数据 
  17. function orderhandle($parameter){ 
  18.     $ordid=$parameter['out_trade_no']; 
  19.     $data['payment_trade_no']      =$parameter['trade_no']; 
  20.     $data['payment_trade_status']  =$parameter['trade_status']; 
  21.     $data['payment_notify_id']     =$parameter['notify_id']; 
  22.     $data['payment_notify_time']   =$parameter['notify_time']; 
  23.     $data['payment_buyer_email']   =$parameter['buyer_email']; 
  24.     $data['ordstatus']             =1; 
  25.     $Ord=M('Orderlist'); 
  26.     $Ord->where('ordid='.$ordid)->save($data); 
  27. }  
  28.  
  29.  
  30. //获取一个随机且唯一的订单号; 
  31. function getordcode(){ 
  32.     $Ord=M('Orderlist'); 
  33.     $numbers = range (10,99); 
  34.     shuffle ($numbers);  
  35.     $code=array_slice($numbers,0,4);  
  36.     $ordcode=$code[0].$code[1].$code[2].$code[3]; 
  37.     $oldcode=$Ord->where("ordcode='".$ordcode."'")->getField('ordcode'); 
  38.     if($oldcode){ 
  39.         getordcode(); 
  40.     }else
  41.         return $ordcode
  42.     } 

四、总结几点

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

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

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

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

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

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


推荐阅读
  • 本文介绍了如何通过安装 VirtualBox 和 Vagrant 来快速搭建和管理虚拟机环境。我们将详细探讨如何选择合适的 Box 镜像,以及如何高效地下载、添加和管理这些镜像。 ... [详细]
  • 多版本CUDA共存与即时切换方案
    本文探讨了在同一台机器上安装并管理多个CUDA版本的方法,以适应不同软件或项目的需求。特别是在使用旧版PyTorch等依赖特定CUDA版本的软件时,该方法尤为实用。 ... [详细]
  • 深度兴趣网络在点击率预测中的应用研究
    本文探讨了一种名为深度兴趣网络(Deep Interest Network, DIN)的新方法,该方法通过捕捉用户的历史行为和当前上下文之间的交互来提高点击率预测的准确性。DIN模型不仅考虑了用户的静态偏好,还动态地调整了对不同商品的兴趣权重,从而实现了更加个性化的推荐。 ... [详细]
  • 在 PHP 4, PHP 5 和 PHP 7 中,fstat 函数用于获取已打开文件指针的文件统计信息。此函数与 stat() 类似,但其操作对象为已打开的文件指针而非文件名称。 ... [详细]
  • 本文汇集了使用C#中不同HTTP客户端向Web API上传文件的实例,旨在为开发者提供实用的技术指南。 ... [详细]
  • 本文详细介绍了在PHP中如何创建新文件以及如何使自定义函数在整个项目中全局可用的方法,包括最新的实践技巧。 ... [详细]
  • 本文介绍了在一卡通项目中设计加密管理方案时,证书服务器的配置步骤及其在用户权限控制中的应用。首先概述了证书服务器的基本设置,包括操作系统的选择和证书服务的安装,随后详细描述了服务器证书及客户端证书的创建过程。 ... [详细]
  • 解决phpMyAdmin运行错误:mysqli_init(): 属性访问尚未允许
    本文探讨了在使用phpMyAdmin过程中遇到的mysqli_init()函数错误,并提供了有效的解决方案。 ... [详细]
  • 本文探讨了在执行SQL查询时遇到的因字符集不同而导致查询结果差异的问题,特别是涉及中文字符时。文章分析了在不同字符集设置下,SQL查询结果的变化,并提供了详细的解决方案。 ... [详细]
  • 本文探讨了如何在JavaScript中调用PHP函数及实现两者之间的有效交互,包括通过AJAX请求、动态生成JavaScript代码等方法。 ... [详细]
  • 本文介绍如何利用Python中的Epoll机制构建一个高效的Web服务器,该服务器能够处理多个并发连接,并向每个连接的客户端返回预定义的响应文本。通过使用Epoll,服务器可以实现高性能的I/O多路复用。 ... [详细]
  • HTML中用于创建表单的标签是什么
    本文将详细介绍HTML中用于创建表单的标签及其基本用法,包括表单的主要特性和常用的属性设置。如果您正在学习HTML或需要了解如何在网页中添加表单,这将是一个很好的起点。 ... [详细]
  • SQL注入实验:SqliLabs第38至45关解析
    本文深入探讨了SqliLabs项目中的第38至45关,重点讲解了堆叠注入(Stacked Queries)的应用技巧及防御策略。通过实际案例分析,帮助读者理解如何利用和防范此类SQL注入攻击。 ... [详细]
  • 本文探讨了梯形图为何成为嵌入式软件机器编程中的理想选择,分析其特点及优势。 ... [详细]
  • Elasticsearch基础操作指南:使用Postman进行数据管理
    本文将介绍如何利用Postman工具执行基本的日志写入和数据管理操作。通过本教程,您将了解如何连接至Elasticsearch服务,创建索引,存储及检索数据。 ... [详细]
author-avatar
我心飞翔
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有