Yii2集成支付宝

背景知识:

  1. 本文主要以电脑网站支付为主讲解支付宝的应用,官方文档
  2. 事先准备好官方的PHP例子,下载地址:传送门

1.首先在vendor下新建一个alipay目录,将下载好的sdk拖入该目录中:

2.在配置文件中配置支付相关信息:

<?php
return [
    'alipay'=>[
        //应用的ID
        'app_id'=>"",

        //商户私钥
        'merchant_private_key' => "",

        //异步通知地址(注意地址不能有get参数)
        //例如:http://blog.w.labyun.com.cn/notify.php
        'notify_url'=>"",

        //同步通知地址(可以有get参数)
        //例如:http://blog.w.labyun.com.cn/index.php?r=pay/return
        'return_url'=>"",

        'charset'=>'UTF-8',

        //签名方式
        'sign_type'=>'RSA2',

        //支付宝网关
        'gatewayUrl' => "https://openapi.alipay.com/gateway.do",

        //支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
        'alipay_public_key' => "",
    ]
];


关于同步通知和异步通知:由于同步通知有着不稳定性,例如用户在支付完成之后关闭了页面或者服务器网络抖
动等等都会导致同步回调的失败,因此需要异步回调来保证通知结果一定传达到。




3.笔者是在应用目录下新建来一个services目录,并新建了一个Pay类:

4.Pay类中的核心代码如下:

<?php
namespace app\services;
//引入官方demo中封装好的类
require '../vendor/alipay/pagepay/service/AlipayTradeService.php';
require '../vendor/alipay/pagepay/buildermodel/AlipayTradePagePayContentBuilder.php';
class Pay{
    
    //发起支付
    public static function alipay(){
        //注意在使用类的时候加上"\",因为是通过require的方式引入的类(在公共空间中)
        //并且本文件中又声明了app\services命名空间,因此需要加上\显示表明
        //使用公共空间中的类
        $payRequestBuilder = new \AlipayTradePagePayContentBuilder();
        $payRequestBuilder->setBody('描述信息');
        $payRequestBuilder->setSubject('主题');
        $payRequestBuilder->setTotalAmount('金额');
        $payRequestBuilder->setOutTradeNo('订单号');
        //加载alipay相关的配置文件
        $config=\Yii::$app->params['alipay'];
        $aop = new \AlipayTradeService($config);
        $response = $aop->pagePay($payRequestBuilder,$config['return_url'],$config['notify_url']);
        echo $response;
        \Yii::$app->end();
    }
}

5.由于我设置了如下回调参数:


'notify_url'=>'http://blog.w.labyun.com.cn/notify.php',

'return_url'=>'http://blog.w.labyun.com.cn/index.php?r=pay/return',

因此当支付成功时,支付宝的同步回调会调用Pay控制器下的return方法,相应的代码如下:


//PayController控制器中的方法

//同步回调(注意是:GET方式)
public function actionReturn(){

    if(\Yii::$app->request->isGet){
        $get = \Yii::$app->request->get();
        Pay::handleReturn($get);
        $this->redirect(['order/my-order']);
        \Yii::$app->end();
        }

}




//services下Pay类新增handleReturn方法

public static function handleReturn($get){
    $config=\Yii::$app->params['alipay'];
    $alipaySevice = new \AlipayTradeService($config);
    try{
        //注意由于同步回调的地址是http://blog.w.labyun.com.cn/index.php?r=pay/return
        //因此$get数组中会有'r'=>'pay/return'这一项,但是这一项是多余的需要删除
        //否则校验会一直失败
        unset($get['r']);
        $result = $alipaySevice->check($get);
        if(!$result){
            \Yii::$app->getSession()->setFlash('Error','验证失败');
            return false;
        }

        //这里可以做自己相应的业务处理 
  
        return true;
        }catch(\Exception $e){
            \Yii::$app->getSession()->setFlash('Error','验证失败');
            return false;
        }

    }

由于支付宝的异步通知地址不能携带任何参数,这也是为什么异步地址不像同步地址那样设置成:http://blog.w.labyun.com.cn/index.php?r=pay/notify 而设置成 http://blog.w.labyun.com.cn/notify.php 的原因。

在web目录下新建notify.php文件,如下:

编写如下代码:

<?php


$url="http://blog.w.labyun.com.cn/index.php?r=pay/notify";
//获得支付宝异步传递的数据(注意是post请求,与同步不同)
$post = $_POST;
$ch=curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);

//将支付宝异步回调的数据传递给指定的url解析
curl_setopt($ch,CURLOPT_POST,1);
curl_setopt($ch,CURLOPT_POSTFIELDS,$post);
$out=curl_exec($ch);
curl_close($ch);
echo $out;

从上面我们可以看出notify.php相当于是一个中间件做了一次转发,接下来是异步通知的核心代码:


//PayController控制器中的方法

//需要关闭yii2默认post方式提交的csrf验证
public $enableCsrfValidation=false;

//只能返回success或者fail,这是支付宝规定的
//success表示成功响应了异步通知,之后支付宝就不会再发送异步通知了
//fail表示未成功响应,支付宝会陆续发送异步通知,具体周期可以百度
public function actionNotify(){
    if(\Yii::$app->request->isPost){
        $post=\Yii::$app->request->post();
        if(Pay::handleNotify($post)){
            echo 'success';exit; 
        }else{
            echo 'fail';exit;
        }
    }
}



//services下的Pay类新增如下方法

public static function handleNotify($post){
        $config=\Yii::$app->params['alipay'];
        $alipaySevice = new \AlipayTradeService($config);
        //校验
        $result = $alipaySevice->check($post);
        if(!$result){
            return false;
        }
        //订单号
        $out_trade_no = $post['out_trade_no'];
        //交易状态
        $status = $post['trade_status'];
        //支付宝交易号
        $trade_no = $post['trade_no'];
        //支付金额
        $amount = $post['total_amount'];
        if('TRADE_SUCCESS'===$status||'TRADE_FINISHED'===$status){
            try{

                //自己的业务处理,例如检查订单的价格和付款的钱是否一致

            }catch(\Exception $e){
                return false;
            }
        }
        return false;
    }

以上就是Yii2集成支付宝的过程。

猜你喜欢

转载自blog.csdn.net/wx145/article/details/83118960
今日推荐