自己整理过支付宝的担保交易,这里的话就来整理下,方便大家和自己以后的查阅。
上一篇文章有说到怎么去申请,这里的操作都是申请下来后的操作,没通过的时候可以看下就好,实际操作不了的。
1.登陆支付宝后台,下载担保交易的集成包。
2.下载完成后的文件说明:
纯担保交易接口-create_partner_trade_by_buyer(20151015) 确认发货接口-send_goods_confirm_by_platform(20150312)
根据自己需要去选择,需要说明下,先担保整合完成后才回去处理确认发货,因为确认发货时需要担保交易的支付宝交易编号
对应的代码文件结构
─────── create_partner_trade_by_buyer-php-UTF-8 │ ├lib┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈类文件夹 │ │ │ ├alipay_core.function.php ┈┈┈┈┈┈支付宝接口公用函数文件 │ │ │ ├alipay_notify.class.php┈┈┈┈┈┈┈支付宝通知处理类文件 │ │ │ ├alipay_submit.class.php┈┈┈┈┈┈┈支付宝各接口请求提交类文件 │ │ │ └alipay_md5.function.php┈┈┈┈┈┈┈支付宝接口MD5函数文件 │ ├log.txt┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈日志文件 │ ├alipay.config.php┈┈┈┈┈┈┈┈┈┈┈┈基础配置类文件 │ ├alipayapi.php┈┈┈┈┈┈┈┈┈┈┈┈┈┈支付宝接口入口文件 │ ├notify_url.php ┈┈┈┈┈┈┈┈┈┈┈┈┈服务器异步通知页面文件 │ ├return_url.php ┈┈┈┈┈┈┈┈┈┈┈┈┈页面跳转同步通知文件 │ ├cacert.pem ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈用于CURL中校验SSL的CA证书文件 │ └readme.txt ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈使用说明文本
这里我们先处理代码
3.核心处理代码
把lib目录文件下的4个核心文件放入 ThinkPHP/Library/Vendor/Alipay 下
修改文件名为:
alipay_core.function.php -> Corefunction.php alipay_notify.class.php -> Notify.php alipay_submit.class.php -> Submit.php alipay_md5.function.php -> Md5function.php
其中 Notify.php 和 Md5function.php 需要删除前面引入的两行代码
require_once("alipay_core.function.php"); require_once("alipay_md5.function.php");
因为在使用TP第三方扩展类的时候会自动引入他需要的这两个文件
核心框架整合完成之后我们来整理逻辑代码。
4.逻辑代码整理
首先我们把 签名文件 cacert.pem 放在网站的跟目录,其他目录也行,不过需要有访问权限的
然后在公共配置文件conf.php中添加 支付宝配置
//支付宝配置参数 'alipay_config'=>array( 'partner' =>'2088**********************', //这里是你在成功申请支付宝接口后获取到的PID; 'key'=>'ob4x7k0*************************',//这里是你在成功申请支付宝接口后获取到的Key 'sign_type'=>strtoupper('MD5'), 'input_charset'=> strtolower('utf-8'), 'cacert'=> getcwd().'\\cacert.pem',//liunx这里需要注意 \\ 和 / 在liunx的区别 'transport'=> 'http', 'seller_email'=>'775919499@qq.com',// 这里是你的收款账号, ), //以上配置项,是从接口包中alipay.config.php 文件中复制过来,进行配置; 'alipay' =>array( //这里是异步通知页面url,提交到项目的Pay控制器的notifyurl方法; 'notify_url'=>'http://www.loveteemo.com/Pay/notifyurl', //这里是页面跳转通知url,提交到项目的Pay控制器的returnurl方法; 'return_url'=>'http://www.loveteemo.com/Pay/returnurl', ),
然后去创建一个 Key 控制器,然后处理代码:
<?php namespace Home\Controller; use Think\Controller; class KeyController extends Controller { //利用构造函数引入核心文件 public function _initialize() { vendor('Alipay.Corefunction'); vendor('Alipay.Md5function'); vendor('Alipay.Notify'); vendor('Alipay.Submit'); } //首页,用来展示商品页 public function index(){ $this->display(); } //订单页,我写死了的,可以根据自己需要进行修改 public function order(){ $type = I('get.type'); if($type==1){ $date = array('type'=>1,"price"=>'0.01',"name"=>"《火星救援》"); }elseif($type==2){ $date = array('type'=>2,"price"=>'0.01',"name"=>"《死神的精确度》"); }elseif($type==3){ $date = array('type'=>3,"price"=>'0.01',"name"=>"《寂寞是毒,也是解药》"); }elseif($type==4){ $date = array('type'=>4,"price"=>'0.01',"name"=>"《只要不忘了回家的路》"); }elseif($type==5){ $date = array('type'=>5,"price"=>'0.01',"name"=>"《异想星球 hello,我是托比小黑》"); }elseif($type==6){ $date = array('type'=>6,"price"=>'0.01',"name"=>"《张鸣说历史:大国的虚与实》"); } $this->time = time(); $this->assign("data",$date); $this->display(); } //订单页点击提交,传递必要参数后开始支付,可自行修改 public function payorder(){ //传递数组配置 $alipay_config=C('alipay_config'); /**************************请求参数**************************/ //支付类型 $payment_type = "1"; //必填,不能修改 //服务器异步通知页面路径 $notify_url = C('alipay.notify_url'); //需http://格式的完整路径,不能加?id=123这类自定义参数 //页面跳转同步通知页面路径 $return_url = C('alipay.return_url'); //需http://格式的完整路径,不能加?id=123这类自定义参数,不能写成http://localhost/ //商户订单号 $out_trade_no = $_POST['orderid']; //商户网站订单系统中唯一订单号,必填 //订单名称 $subject = $_POST['ordername']; //必填 //付款金额 $price = $_POST['orderprice']; //必填 //商品数量 $quantity = "1"; //必填,建议默认为1,不改变值,把一次交易看成是一次下订单而非购买一件商品 //物流费用 $logistics_fee = "0.00"; //必填,即运费 //物流类型 $logistics_type = "EXPRESS"; //必填,三个值可选:EXPRESS(快递)、POST(平邮)、EMS(EMS) //物流支付方式 $logistics_payment = "SELLER_PAY"; //必填,两个值可选:SELLER_PAY(卖家承担运费)、BUYER_PAY(买家承担运费) //订单描述 $body = $_POST['orderbody']; //商品展示地址 $show_url = $_POST['ordershow']; //需以http://开头的完整路径,如:http://www.商户网站.com/myorder.html //收货人姓名 $receive_name = $_POST['user_name']; //如:张三 //收货人地址 $receive_address = $_POST['user_address']; //如:XX省XXX市XXX区XXX路XXX小区XXX栋XXX单元XXX号 //收货人邮编 $receive_zip = $_POST['user_zip']; //如:123456 //收货人电话号码 $receive_phone = $_POST['user_phone']; //如:0571-88158090 //收货人手机号码 $receive_mobile = $_POST['user_mobile']; //如:13312341234 /************************************************************/ //构造要请求的参数数组,无需改动 $parameter = array( "service" => "create_partner_trade_by_buyer", "partner" => trim($alipay_config['partner']), "seller_email" => trim($alipay_config['seller_email']), "payment_type"=> $payment_type, "notify_url"=> $notify_url, "return_url"=> $return_url, "out_trade_no"=> $out_trade_no, "subject"=> $subject, "price"=> $price, "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($alipay_config['input_charset'])) ); //存入数据库订单信息 static为99是无效订单 M('test')->add(array("orderid"=>$out_trade_no,"addtime"=>time(),"ordername"=>$subject,"orderprice"=>$price,"static"=>99)); //建立请求 $alipaySubmit = new \AlipaySubmit($alipay_config); //dump($alipaySubmit);die; $html_text = $alipaySubmit->buildRequestForm($parameter,"get", "确认"); echo $html_text; } /****************************** 服务器异步通知页面方法 *******************************/ public function notifyurl(){ //防止乱码 header("Content-Type:text/html;charset=utf-8"); //计算得出通知验证结果 $alipay_config=C('alipay_config'); $alipayNotify = new \AlipayNotify($alipay_config); $verify_result = $alipayNotify->verifyNotify(); if($verify_result) {//验证成功 //商户订单号 logResult("订单编号:".$_POST['out_trade_no'].",状态".$_POST['trade_status'].""); $out_trade_no = $_POST['out_trade_no']; //支付宝交易号 $trade_no = $_POST['trade_no']; //交易状态 $trade_status = $_POST['trade_status']; if($_POST['trade_status'] == 'WAIT_BUYER_PAY') { //该判断表示买家已在支付宝交易管理中产生了交易记录,但没有付款 //判断该笔订单是否在商户网站中已经做过处理 //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 //如果有做过处理,不执行商户的业务程序 echo "success";//请不要修改或删除 //调试用,写文本函数记录程序运行情况是否正常 //获取支付宝的订单号后写入数据库,修改订单状态为0 待支付 M('test')->where(array("orderid"=>$out_trade_no))->save(array("static"=>0,"lasttime"=>time(),'payid'=>$trade_no)); //文本日志文件,这里的日志文件会在网站根目录生成一个log.txt文件 logResult("这里是等待付款"); } else if($_POST['trade_status'] == 'WAIT_SELLER_SEND_GOODS') { //该判断表示买家已在支付宝交易管理中产生了交易记录且付款成功,但卖家没有发货 //判断该笔订单是否在商户网站中已经做过处理 //买家支付后,修改状态为已支付代发货 M('test')->where(array("orderid"=>$out_trade_no))->save(array("static"=>1,"lasttime"=>time())); //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 //如果有做过处理,不执行商户的业务程序 echo "success";//请不要修改或删除 //调试用,写文本函数记录程序运行情况是否正常 logResult("支付完成!订单编号:".$out_trade_no.",状态".$_POST['trade_status'].""); } else if($_POST['trade_status'] == 'WAIT_BUYER_CONFIRM_GOODS') { //该判断表示卖家已经发了货,但买家还没有做确认收货的操作 //判断该笔订单是否在商户网站中已经做过处理 //发货完成后会修改状态 M('test')->where(array("orderid"=>$out_trade_no))->save(array("static"=>2,"lasttime"=>time())); //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 //如果有做过处理,不执行商户的业务程序 echo "success";//请不要修改或删除 //调试用,写文本函数记录程序运行情况是否正常 logResult("发货完成,等待买家收货"); } else if($_POST['trade_status'] == 'TRADE_FINISHED') { //该判断表示买家已经确认收货,这笔交易完成 //判断该笔订单是否在商户网站中已经做过处理 //买家收货后订单完成 M('test')->where(array("orderid"=>$out_trade_no))->save(array("static"=>3,"lasttime"=>time())); //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 //如果有做过处理,不执行商户的业务程序 echo "success";//请不要修改或删除 //调试用,写文本函数记录程序运行情况是否正常 logResult("交易完成!"); } else { //其他状态判断 echo "success"; //调试用,写文本函数记录程序运行情况是否正常 logResult ("错误"); } } else { //验证失败 echo "fail"; //调试用,写文本函数记录程序运行情况是否正常 logResult("验证失败"); } } /* 页面跳转处理方法; */ public 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']; if($_GET['trade_status'] == 'WAIT_SELLER_SEND_GOODS') { //判断该笔订单是否在商户网站中已经做过处理 //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 //如果有做过处理,不执行商户的业务程序 } // else { echo "trade_status=".$_GET['trade_status']; } $this->assign("payid",$trade_no); } else { //验证失败 //如要调试,请看alipay_notify.php页面的verifyReturn函数 echo "验证失败"; } $this->display(); } //自动发货 利用隐藏表单传递必须数据过来 public function sendgoods(){ $alipay_config=C('alipay_config'); /**************************请求参数**************************/ //支付宝交易号 $trade_no = $_POST['WIDtrade_no']; //必填 //物流公司名称 $logistics_name = $_POST['WIDlogistics_name']; //必填 //物流发货单号 $invoice_no = $_POST['WIDinvoice_no']; //物流运输类型 $transport_type = $_POST['WIDtransport_type']; //三个值可选:POST(平邮)、EXPRESS(快递)、EMS(EMS) /************************************************************/ //构造要请求的参数数组,无需改动 $parameter = array( "service" => "send_goods_confirm_by_platform", "partner" => trim($alipay_config['partner']), "trade_no"=> $trade_no, "logistics_name"=> $logistics_name, "invoice_no"=> $invoice_no, "transport_type"=> $transport_type, "_input_charset"=> trim(strtolower($alipay_config['input_charset'])) ); //建立请求 $alipaySubmit = new \AlipaySubmit($alipay_config); $html_text = $alipaySubmit->buildRequestHttp($parameter); //解析XML //注意:该功能PHP5环境及以上支持,需开通curl、SSL等PHP配置环境。建议本地调试时使用PHP开发软件 $doc = new \DOMDocument(); $doc->loadXML($html_text); //请在这里加上商户的业务逻辑程序代码 //——请根据您的业务逻辑来编写程序(以下代码仅作参考)—— //获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表 //解析XML if( ! empty($doc->getElementsByTagName( "alipay" )->item(0)->nodeValue) ) { $alipay = $doc->getElementsByTagName( "alipay" )->item(0)->nodeValue; //echo $alipay; //M('test')->where(array("orderid"=>$out_trade_no))->save(array("static"=>2,"lasttime"=>time())); $this->success("自动发货完成!","/Home/Key/lists"); } } //筛选无效订单后展示 public function lists(){ $lists = M('test')->where("static != 99")->limit(20)->order("id desc")->select(); $this->assign("lists",$lists); $this->display(); } }
到这里基本的业务逻辑就完成了,附带测试的数据库给大家分享下
CREATE TABLE `web_test` ( `id` int(11) NOT NULL AUTO_INCREMENT, `orderid` varchar(16) NOT NULL, `ordername` varchar(128) NOT NULL, `orderprice` varchar(16) NOT NULL, `static` int(11) NOT NULL COMMENT '0为未支付,1为已支付未发货,2为发货为确认收,3为确认收,4为取消', `addtime` int(11) NOT NULL, `lasttime` int(11) NOT NULL, `payid` varchar(32) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `orderid` (`orderid`) ) ENGINE=InnoDB AUTO_INCREMENT=43 DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
5.需要注意的地方:
签名的目录,上面有说过,签名的目录在liunx和windows是有区别的,liunx需要改成
'cacert'=> getcwd().'/cacert.pem',
不然会报错说签名没找到
在部署完成后测试的时候会遇到有些浏览器乱码,谷歌正常
这里需要注意的是TP在异步的时候会出现,在urldecode的时候中文出现乱码,所以在这里我在前面加一行代码防止乱码
header("Content-Type:text/html;charset=utf-8");
本地测试异步中写操作数据库是没任何意义的
因为异步需要服务器上测试才行的。
好了,说到这里基本完成了我们的支付宝整合,如果有问题或者哪里不对,请留言告诉我,非常感谢。如果觉得本文写的不错可以点击下面的按钮哟
上一篇: 支付宝交易接口申请...
下一篇: 分享一个IP库...