在开发中需要使用支付宝的快捷移动支付接口,通过文档知道,当完成客户端请求完成后,支付宝服务器会异步通知客户端的服务器。这里的关键是提供给支付宝的这个用于异步通知的controller该做些什么事情呢?以及如何将支付宝提供的这些sdk放到服务器上面去?
我的软件环境: hinkphp+mysql
如何将快捷支付的服务端sdk整合到thinkphp有以下五个步骤:
一、生成公钥、私钥,这部分请参考支付宝提供的手册,不在多余的描述,此步非常关键,如果公司钥生成错误,那后面所有的都是错误。
二、将获得的公钥通过支付宝控制台获取支付宝的公钥。并将公钥内容复制到【服务端demo\PHP-UTF-8\key\alipay_public_key.pem】中.把生成的私钥也拷贝到这个文件夹中来,最终文件有如下两个文件,并且名字也必须保持一致:
三、在thinkphp中的Vendor文件夹下,新建文件夹Alipay,把【服务端demo\PHP-UTF-8\lib】中的文件拷贝进去,支付宝作为第三方类库引入。
现在对以上文件进行重命名
alipay_core.function.php重命名为:Corefunction.php;
alipay_rsa.function.php重命名为:RSAfunction.php;
alipay_notify.class.php重命名为:Notify.php;
然后,打开Notify.php文件,把以下代码去掉:
require_once("alipay_core.function.php");
require_once("alipay_rsa.function.php");
四、通过第三步,已经完成了支付宝SDK的引入。现在应该引入一些公私钥,以及支付宝的配置。请把key目录以及cacert.pem拷贝到你项目的一个目录,然后在项目的配置目录中写入支付宝相关的配置。我这里是全部拷贝到了Common\Conf目录中了。目录结构如下:
其中alipay_config.php的内容大部分来源于:demo中alipay.config.php这个文件夹,最终示例如下:
<?php
return array(
//支付宝配置参数
'alipay_config'=>array(
'partner' => '2088***********63', //合作身份者id,以2088开头的16位纯数字
'private_key_path' => getcwd().'/TaTa/Common/Conf/key/alipay_public_key.pem', //商户的私钥(后缀是.pen)文件相对路径
'ali_public_key_path' => getcwd().'/TaTa/Common/Conf/key/alipay_public_key.pem',//支付宝公钥(后缀是.pen)文件相对路径
'sign_type' => strtoupper('RSA'), //签名方式 不需修改
'input_charset' => strtolower('utf-8'), //字符编码格式 目前支持 gbk 或 utf-8
'cacert' => getcwd().'/TaTa/Common/Conf/cacert.pem', //ca证书路径地址,用于curl中ssl校验
//请保证cacert.pem文件在当前文件夹目录中
//访问模式,根据自己的服务器是否支持ssl访问,若支持请选择https;若不支持请选择http
'transport' => 'http',
),
//以上配置项,是从接口包中alipay.config.php 文件中复制过来,进行配置;
'alipay'=>array(
//这里是卖家的支付宝账号,也就是你申请接口时注册的支付宝账号
'seller_email' => 'xxxxxx@qq.com',
),
);
到此,需要引入的文件,已经全部完成,只剩下最后一步,来完成这个异步通知的controller了。
五、完成提供给支付宝进行异步通知的Controller,代码如下:
<?php
namespace Api\Controller;
use Think\Controller;
use Home\Service\OrderService;
/**
* 支付宝快捷支付notify接口
* 该接口提供给支付宝通知服务端使用
*
* @author admin
*
*/
class AlipayController extends Controller {
/**
* 初始化方法,通过初始化方法,引入支付宝的SDK,这就是为什么需要提前去掉Notify.php中的几个require_once的原因
*/
public function _initialize () {
vendor('Alipay.Corefunction');
vendor('Alipay.RSAfunction');
vendor('Alipay.Notify');
}
/**
* 提供给支付宝调用的接口
*/
public function notifyurl () {
// 计算得出通知验证结果
$alipay_config = C('alipay_config');
$alipayNotify = new \AlipayNotify($alipay_config);
$verify_result = $alipayNotify->verifyNotify();
if ($verify_result) { // 验证成功
$data = $_POST;// 获取所有数据
$out_trade_no = $data['out_trade_no']; // 唯一订单号
$notify_time = $data['notify_time']; //通知时间
$notify_type = $data['notify_type']; //通知类型
$notify_id = $data['notify_id']; // 通知校验ID
$trade_no = $data['trade_no']; //支付宝交易号
$trade_status = $data['trade_status']; //交易状态
$buyer_email = $data['buyer_email']; //买家支付宝账号
$pay_time = $data['gmt_payment']; // 交易付款时间
// 金额相关
$total_fee = $data['total_fee'];//交易金额
$seller_email = $data['seller_email'];//卖家支付宝账号
// 数据库相关参数
$parameter = array(
"pay_trade_no" => $trade_no, //支付宝交易号;
"total_fee" => sprintf("%.2f", $total_fee), //交易金额;
"pay_trade_status" => $trade_status, //交易状态
"pay_notify_id" => $notify_id, //通知校验ID。
"pay_notify_time" => $notify_time, //通知的发送时间。
"pay_buyer_email" => $buyer_email, //买家支付宝帐号;
"pay_time" => $pay_time, // 交易付款时间
);
if ($trade_status == 'TRADE_FINISHED') {
} elseif ($trade_status == 'TRADE_SUCCESS') {
if($this->checkOrderStatus($out_trade_no, $total_fee, $seller_email)){
$parameter['pay_status'] = 1;
$this->orderHandle($out_trade_no, $parameter);
}else{
echo "fail";exit;
}
}
echo "success"; // 请不要修改或删除
} else {
// 验证失败
echo "fail";
}
}
/**
* 检查支付宝返回的关键数据是否合法
* @param string $order_sn 订单账号
* @param float $total_fee 总价格
* @param string $seller 收款账号
*/
private function checkOrderStatus($order_sn, $total_fee, $seller){
$account = C('alipay')['seller_email'];
$OrderSer = new OrderService();
$sumPrice = $OrderSer->getOrderTotalFee($order_sn);//获得该订单的价格,比较价格是否正确
if($sumPrice==$total_fee && $account==$seller){
return true;
}
return false;
}
/**
* 支付宝订单返回的数据处理,将需要保存的结果,存入到数据库中去
* @param string $orderno 支付宝返回的订单号
* @param array $orderData 支付宝返回的相关信息
*/
private function orderHandle($orderno, $orderData){
$where['order_sn'] = trim($orderno);
$OrderSer = new OrderService();
$OrderSer->updateOrder($where, $orderData);
}
}
通过以上五步,整合快捷支付接口的服务端工作就OK了,剩下的工作,就是移动端的事情了,你只需要把这个url提供给移动端开发人员,他们配置参数的时候将notify_url参数配置为你提供的即可。
当然支付宝还返回了很多其他参数,你可以保存一些你认为需要的数据,或者你在检验的时候,检验更多的数据,检查这次支付是否合法。
app后端开发系列文章目录