ThinkPHP整合支付宝担保交易
ThinkPHP整合支付宝担保交易
本代码参考大神 http://www.thinkphp.cn/code/240.html 的思路
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();
}
}[code]到这里基本的业务逻辑就完成了,附带测试的数据库给大家分享下[code]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");
本地测试异步中写操作数据库是没任何意义的
因为异步需要服务器上测试才行的。
ThinkPHP整合支付宝担保交易相关推荐
- thinkphp整合支付宝担保交易接口
第一步: 先下载支付宝担保交易的demo(php utf-8). 第二步: 首先在项目Lib目录下简历自己的lib库,比如thlib: 将alipay_notify.class.php.alipay_ ...
- ThinkPHP集成支付宝担保支付
概述 支付宝担保支付 ThinkPHP集成支付宝担保交易 1.准备工作 2.自定义Action类 3.代码下载 概述 现在的网站功能越来越全乎了,很多网站都需要做支付功能,而且很多大平台都提供了各式各 ...
- 支付宝担保交易接口 php,ThinkPHP实现支付宝接口功能(担保交易)
ThinkPHP实现支付宝接口功能(担保交易),(即时交易)@托米,已经有人发过了.这个不是我写的,是在csdn上看到的,顺便转载过来,有什么问题,可以到原作者博客提问http://blog.csdn ...
- Discuz 3.2接入支付宝担保交易
支付宝双功能收款,已经不再支持,取而代之的是支付宝担保交易.而Discuz 3.2仅支持双功能收款,这种已经不再支持的服务 那么我们就该修改支付代码吧,希望你用的是VIM 输入一下命令替换所有的tra ...
- 支付宝担保交易收款接口使用
支付宝担保交易收款接口使用 担保交易收款 API ,下载地址http://club.alipay.com/read-htm-tid-9976972.html 以下是我和支付宝客服的咨询记录 您好! 欢 ...
- Alipay Escow (Guanrantee) Payment 支付宝担保交易(OpenCart 2.x)
根据支付宝方面的政策调整,自2014年12月份起,不再签署相关双接口协议,目前仍在生效的,到期日后不再续签. ,因此新的支付宝插件,按照即时到账和担保交易分别设计,以适应相关客户的具体需求. 关于担保 ...
- 记录 “Thinkphp 3.2及以上版本实现支付宝担保交易、即时到账接口类、函数和使用方法”
转自:http://www.zioor.com/view/1668 在此感谢那些爱奉献的人... 给客户开发网站时需要用到支付宝在线付款功能,小云到thinkphp网站溜了一圈,代码是有,可是都不怎么 ...
- Thinkphp 3.2及以上版本实现支付宝担保交易、即时到账接口类、函数和使用方法
给客户开发网站时需要用到支付宝在线付款功能,小云到thinkphp网站溜了一圈,代码是有,可是都不怎么全,因此这篇文章诞生了! 本篇文章讲解了三个类的实现,担保交易.即时到账.双功能收款(该功能支付宝 ...
- 支付宝担保交易接口问题
支付宝论坛 http://zhidao.baidu.com/question/385702165.html 我准备做B2C网,使用支付宝接口,请问我对在我网站交易的金额有管理权和使用权吗? 就是说我开 ...
最新文章
- 第18章:MYSQL分区
- 电子文件归档为什么非云不可
- HDU 5693 D Game 区间dp
- python绘制雷达图代码实例-Matplotlib绘制雷达图和三维图的示例代码
- 「云网络」VS「云计算」- vecloud微云服务器
- VS2008中设置字体大小和添加显示行号
- java消费kafka数据之后,进行堆积之后在插入数据库
- LeetCode--434--字符串中的单词数
- Can't create handler inside thread that has not called Looper.prepare()
- 个人vscode插件配置全记录
- Linux下的Java虚拟机性能监控常用命令
- c语言课程信息系统排序学分_您可以免费访问具有实际大学学分的400多种在线课程
- Windows Server 2012和2016从Evaluation评估版升级到正式版方法(附带产品密钥/key)
- outlook邮件插入HTML格式内容调试
- 计算天数(函数)(C语言实现)
- 个人身份认证接口介绍
- PDF Shaper Professional v11.3 全能PDF工具箱单文件版
- 网络技术这十个术语你知道吗?
- 聊聊互联网行业对35岁码农的偏见,以及大龄码农的破局之道
- windows下对python的pip更新到最新版本
热门文章
- 服务器报错c.a.druid.pool.DruidAbstractDataSource : discard long time none received connection.
- 网站漏洞扫描 渗透方法基础大全
- react表单双向绑定处理
- [Verilog HDL]简易电子琴_北京邮电大学2019级信通院数字电路实验
- 计算机病毒与反病毒技术论文
- [绍棠] iOS设置Label上显示不同字体大小和字体颜色
- 08年思科认证考试:子网划分实例267台电脑子网划分
- 【AUTOSAR】Classic Platform R22-11新增哪些规范
- 一个基于JQuery的日历时间控件
- 高压电控产品电气设计入门与进阶(中)