首先是在支付宝的蚂蚁金服开放平台下载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
点击支付并传入订单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); } }
类文件:
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>
更详细参考文档:
http://www.thinkphp.cn/code/240.html
说了那么多,四个官方给的lib里面的类文件还是得看啊,兄弟!!!