API开发第五篇:服务端整合支付宝快捷移动支付接口

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"><span style="white-space:pre">	</span>在开发中需要使用支付宝的快捷移动支付接口,通过文档知道,当完成客户端请求完成后,支付宝服务器会异步通知客户端的服务器。这里的关键是提供给支付宝的这个用于异步通知的controller该做些什么事情呢?以及如何将支付宝提供的这些sdk放到服务器上面去?</span>

        我的软件环境:thinkphp+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'          =>  '[email protected]',
    ),
);
到此,需要引入的文件,已经全部完成,只剩下最后一步,来完成这个异步通知的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参数配置为你提供的即可。

当然支付宝还返回了很多其他参数,你可以保存一些你认为需要的数据,或者你在检验的时候,检验更多的数据,检查这次支付是否合法。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。