zoukankan      html  css  js  c++  java
  • thinkphp 支付宝接口的实现

    最近做系统,需要实现在线支付功能,毫不犹豫,选择的是支付宝的接口支付功能。这里我用的是即时到帐的接口,具体实现的步骤如下:
    一、下载支付宝接口包
    下载地址:
    https://b.alipay.com/order/productDetail.htm?productId=2012111200373124&tabId=4#ps-tabinfo-hash
    具体如何下载,我就不在罗嗦了~~

    很多人反映,用支付宝的接口到最后面会出现验证错误。其实,这里需要对接口程序进行一下改造。需要添加几个自定义函数。为了让大家以后避免出现同样的问题,我把我改造好的支付宝接口程序上传了(--> 猛戳这里下载附件)。大家可以下载下来,解压后放到框架的Vendor目录中即可~

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

    我们选择 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文件,把以下代码去掉;

    1. require_once("alipay_core.function.php");
    2. require_once("alipay_md5.function.php");
    复制代码

    同样,打开Notify.php文件,把以下两段代码去掉

    1. require_once("alipay_core.function.php");
    2. require_once("alipay_md5.function.php");
    复制代码

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

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

    三、在项目中调用支付宝接口
    调用分两步:
    1、在配置文件中Conf/Config.php文件中对支付宝相关参数进行配置:

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

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

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

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

      1. //////////////////////////////////////////////////////
      2. //Orderlist数据表,用于保存用户的购买订单记录;
      3. /* Orderlist数据表结构;
      4. CREATE TABLE `tb_orderlist` (
      5.   `id` int(11) NOT NULL AUTO_INCREMENT,
      6.   `userid` int(11) DEFAULT NULL,购买者userid
      7.   `username` varchar(255) DEFAULT NULL,购买者姓名
      8.   `ordid` varchar(255) DEFAULT NULL,订单号
      9.   `ordtime` int(11) DEFAULT NULL,订单时间
      10.   `productid` int(11) DEFAULT NULL,产品ID
      11.   `ordtitle` varchar(255) DEFAULT NULL,订单标题
      12.   `ordbuynum` int(11) DEFAULT '0',购买数量
      13.   `ordprice` float(10,2) DEFAULT '0.00',产品单价
      14.   `ordfee` float(10,2) DEFAULT '0.00',订单总金额
      15.   `ordstatus` int(11) DEFAULT '0',订单状态
      16.   `payment_type` varchar(255) DEFAULT NULL,支付类型
      17.   `payment_trade_no` varchar(255) DEFAULT NULL,支付接口交易号
      18.   `payment_trade_status` varchar(255) DEFAULT NULL,支付接口返回的交易状态
      19.   `payment_notify_id` varchar(255) DEFAULT NULL,
      20.   `payment_notify_time` varchar(255) DEFAULT NULL,
      21.   `payment_buyer_email` varchar(255) DEFAULT NULL,
      22.   `ordcode` varchar(255) DEFAULT NULL,       //这个字段不需要的,大家看我西面的修正补充部分的说明!
      23.   `isused` int(11) DEFAULT '0',
      24.   `usetime` int(11) DEFAULT NULL,
      25.   `checkuser` int(11) DEFAULT NULL,
      26.   PRIMARY KEY (`id`)
      27. ) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
      28. */
      29. //在线交易订单支付处理函数
      30. //函数功能:根据支付接口传回的数据判断该订单是否已经支付成功;
      31. //返回值:如果订单已经成功支付,返回true,否则返回false;
      32. function checkorderstatus($ordid){
      33.     $Ord=M('Orderlist');
      34.     $ordstatus=$Ord->where('ordid='.$ordid)->getField('ordstatus');
      35.     if($ordstatus==1){
      36.         return true;
      37.     }else{
      38.         return false;    
      39.     }
      40. }
      41. //处理订单函数
      42. //更新订单状态,写入订单支付后返回的数据
      43. function orderhandle($parameter){
      44.     $ordid=$parameter['out_trade_no'];
      45.     $data['payment_trade_no']      =$parameter['trade_no'];
      46.     $data['payment_trade_status']  =$parameter['trade_status'];
      47.     $data['payment_notify_id']     =$parameter['notify_id'];
      48.     $data['payment_notify_time']   =$parameter['notify_time'];
      49.     $data['payment_buyer_email']   =$parameter['buyer_email'];
      50.     $data['ordstatus']             =1;
      51.     $Ord=M('Orderlist');
      52.     $Ord->where('ordid='.$ordid)->save($data);
      53. }
  • 相关阅读:
    poj 1273 Drainage Ditches
    网络流之--混合图的欧拉回路 出自yzmduncan.iteye.com/blog/1149049
    hdu 2203 亲和串 kmp
    hdu 1711 kmp
    KMP算法详解 出自matrix67.com
    zoj 2016 Play on Words 欧拉回路
    修改document.domain的注意事项(转)
    ActiveXObject函数详解(转)
    angularjs
    sbt
  • 原文地址:https://www.cnblogs.com/chenfeizhou/p/3458248.html
Copyright © 2011-2022 走看看