基于CI(codeigniter)3框架接入支付宝PC网站支付详细步骤

项目环境

  • PHP语言CI(codeigniter)3.x框架
  • 测试环境:windows,发布环境:CentOS7

注册成为支付宝开发者

支付宝PC电脑支付文档传送门:点这里

申请成为开发者

  1. 支付宝扫码登录蚂蚁金服开放平台
  2. 选择“开发中心=>研发服务”,如图:
    在这里插入图片描述
  3. 下载秘钥生成工具,传送门:点这里
    注意:需要吧下载的文件放到非中文目录的目录下面才可以正常生成秘钥,否则,如果文件夹名称中包含中文,将会出现闪退情况。
    在这里插入图片描述
    同时,生工具同级目录下会生成公钥私钥文件,java语言选择私钥文件是rsa_private_key_pkcs8.pem,其他语言选择私钥文件是rsa_private_key.pem
  4. 把第三步生成的公钥复制并保存到下图中RSA2对应的支付宝公钥里面:
    在这里插入图片描述
    私钥文件自己保存好,下面的支付配置文件中会用到。
  5. 下载沙箱支付测试工具,注意仅支持安卓版本:
    在这里插入图片描述

正式环境支付签约

参考文档:https://blog.csdn.net/meixi_android/article/details/86489870

项目接入支付宝SDK

获取SDK

官方SDK下载地址:SDK传送门
我项目里没有使用官方SDK,这里使用的是github一个大神提供的支付宝支付和微信支付集成的包,

GitBook传送门:点这里
GitHub传送门:点这里

根据文档要求在项目根目录执行composer,安装sdk包:

composer require yansongda/pay -vvv

安装完成后会发现vendor目录多了几个文件夹目录,这都是该SDK的依赖包:
在这里插入图片描述

支付配置

文档中的示例吧配置文件写到了控制器里面,但是不够优雅,我决定把配置文件提取出来放到一个专门的配置文件中:
在这里插入图片描述
配置文件:pay_config.php:

<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
 * Created by PhpStorm.
 * User: 15237
 * Date: 2019/6/22
 * Time: 15:34
 */
$http = 'http://';
$domain = $_SERVER['HTTP_HOST'];
$sub_domain = explode('.', $domain)[1];
$http_domain = $http.$domain;
$notify_url = $http_domain.'/assemble_pay/ali_pay_notify';//异步回调通知接口地址
$return_url = $http_domain.'/assemble_pay/ali_pay_return';//同步回调通知接口地址

if($sub_domain == 'ihibuilding'){
    $cfg_ary = [
        //企业沙箱
        'app_id' => '你的apiiid',//去支付宝平台查看
        'ali_public_key' => '支付宝公钥',//注意这里是公钥,而不是应用公钥,一定要与上面支付宝开发者填的保证一直,否则支付时会有错误提示
        'private_key' => '你生成的私钥文件里面的内容',//由于生成的私钥文件内有回车键,需要吧回车键去掉,私钥内容是-----BEGIN RSA PRIVATE KEY-----与-----END RSA PRIVATE KEY-----之间的字符串,首行和尾行禁止包含
        'mode' => 'dev', // optional,设置此参数,将进入沙箱模式,改参数是指定使用支付宝网关正式地址还是还发地址的
    ];
}else if($sub_domain == 'hibuilding'){
    $cfg_ary = [
        //正式环境
        'app_id' => '你的apiiid',//去支付宝平台查看
        'ali_public_key' => '支付宝公钥',//注意这里是公钥,而不是应用公钥,一定要与上面支付宝开发者填的保证一直,否则支付时会有错误提示
        'private_key' => '你生成的私钥文件里面的内容',//由于生成的私钥文件内有回车键,需要吧回车键去掉,私钥内容是-----BEGIN RSA PRIVATE KEY-----与-----END RSA PRIVATE KEY-----之间的字符串,首行和尾行禁止包含
    ];
}else{
    $cfg_ary = [
        //企业沙箱
         'app_id' => '你的apiiid',//去支付宝平台查看
        'ali_public_key' => '支付宝公钥',//注意这里是公钥,而不是应用公钥,一定要与上面支付宝开发者填的保证一直,否则支付时会有错误提示
        'private_key' => '你生成的私钥文件里面的内容',//由于生成的私钥文件内有回车键,需要吧回车键去掉,私钥内容是-----BEGIN RSA PRIVATE KEY-----与-----END RSA PRIVATE KEY-----之间的字符串,首行和尾行禁止包含
        'mode' => 'dev', // optional,设置此参数,将进入沙箱模式
    ];
}

$common = [
    'notify_url' => $notify_url,
    'return_url' => $return_url,
    // 加密方式: **RSA2**
    'log' => [ // optional
        'file' => './logs/alipay.log',
        'level' => 'info', // 建议生产环境等级调整为 info,开发环境为 debug
        'type' => 'single', // optional, 可选 daily.
        'max_file' => 30, // optional, 当 type 为 daily 时有效,默认 30 天
    ],
    'http' => [ // optional
        'timeout' => 5.0,
        'connect_timeout' => 5.0,
        // 更多配置项请参考 [Guzzle](https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html)
    ],
];
$config['ali_pay_cfg'] = array_merge($cfg_ary, $common);

支付业务实现

初始化配置等

发起支付代码

异步回调代码

同步回调代码

以上四步全部写在下面的两个文件中,开发者可以参考:
控制器文件,Assemble_pay.php:

<?php
defined('BASEPATH') OR exit('No direct script access allowed');

/**
 * 使用该支付需要注意的地方:
 * 0.部署支付sdk时,需要执行 composer require yansongda/pay -vvv ,或将 "yansongda/pay": "^2.7" 加入到composer.json 中
 * 1.开启PHP扩展openssl
 * 2.开启mbstring.encoding_translation
 * 3.为了保证异步回调通知验签成功,需要在 vendor/yansongda/pay/src/Gateways/Alipay.php 中,
 *   把:
 *   const URL = [
        self::MODE_NORMAL => 'https://openapi.alipay.com/gateway.do',
        self::MODE_DEV    => 'https://openapi.alipaydev.com/gateway.do',
     ];
 *   改为:
 *   const URL = [
        self::MODE_NORMAL => 'https://openapi.alipay.com/gateway.do?charset=utf-8',
        self::MODE_DEV    => 'https://openapi.alipaydev.com/gateway.do?charset=utf-8',
     ];
 */

/**
 * Created by PhpStorm.
 * User: 15237
 * Date: 2019/6/22
 * Time: 15:16
 */

use Yansongda\Pay\Pay;
use Yansongda\Pay\Log;
use Yansongda\Pay\Gateways\Alipay;
use Symfony\Component\HttpFoundation\Response;
use Yansongda\Supports\Config;

class Assemble_pay extends PS_Controller
{
    public $CI;
    protected $alipay_cfg;
    protected $wechat_pay_cfg;
    protected $alipay;//支付宝支付对象
    protected $wechatpay;//微信支付对象

    function __construct()
    {
        parent::__construct();

        $this->CI = get_instance();

        $this->alipay_cfg = $this->config->item('ali_pay_cfg');
        $this->wechat_pay_cfg = $this->config->item('wechat_pay_cfg');

        $this->CI->load->helper('pay');

        $this->alipay = Pay::alipay($this->alipay_cfg);
        //$this->wechatpay = Pay::wechat($this->wechat_pay_cfg);

        $this->load->service('assemble_pay_service', '', 'assemble_pay_s');
    }

    public function pay()
    {
        $params = $this->input->post();
        $test = [
            'pay_type' => 'ali_pay',
            'pay_way' => 'web',
            'order_no' => '15614439004',
        ];
        $params = !empty($params) ? $params : $test;

        $res = $this->assemble_pay_s->pay_serv($params);

        //output_data(['html' => $res]);
    }

    /**
     * 方法 ali_pay_return,支付宝支付同步回调接口
     *
     */
    public function ali_pay_return()
    {
        $params = $this->input->get();

        $result = $this->alipay->verify(); // 是的,验签就这么简单!

        $params = deal_ary_trim($params);
        $trade_no = htmlspecialchars($params['trade_no']);
        $params['total_amount'] = $params['total_amount']*100;

        //实际验证过程建议商户添加以下校验。
        //1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,
        //2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),
        //3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email)
        //4、验证app_id是否为该商户本身。
        $order = $this->check_ali_pay_params($params, 3);

        if($result) {//验证成功
            //请在这里加上商户的业务逻辑程序代码
            //修改订单状态
            if(empty($order)){
                $order_where = ['order_no'=>$params['out_trade_no']];
                $order_data = [
                    'order_status'=>3,
                    'pay_date'=>$params['timestamp'],
                    'pay_money'=>$params['total_amount'],
                    'trade_no'=>$trade_no,
                    'trade_date'=>$params['timestamp'],
                ];
                $this->assemble_pay_s->update_order_serv($order_where, $order_data);
            }
            //获取订单信息
            $order_info_where = ['o.order_no' => $params['out_trade_no'], 'order_status' => 3];//1,未支付,3:已支付,4:关闭,5:完成
            $order = $this->assemble_pay_s->get_order_info_serv($order_info_where);
            //增加收支流水记录
            //查看是否有订单流水产生,有则不处理,无则需要添加
            $order_bill = $this->assemble_pay_s->get_order_bill_info_serv(['order_id'=>$order['order_id']]);
            if(empty($order_bill)){
                $this->create_order_bill($order, $trade_no);
            }

            //——请根据您的业务逻辑来编写程序(以下代码仅作参考)——
            //获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表
            //商户订单号
            //$out_trade_no = htmlspecialchars($params['out_trade_no']);
            //支付宝交易号
            //echo "验证成功<br />支付宝交易号:".$trade_no;
            //echo '<br/>去支付页查看订单信息吧!<br/>';
            $data['res'] = 'success';
            $data['message'] = '验证支付成功。</br>支付宝交易号:%s </br>去支付页查看订单信息吧!</br>';
            $data['trade_no'] = $trade_no;
            //——请根据您的业务逻辑来编写程序(以上代码仅作参考)——
        } else {
            //验证失败
            //echo "验证失败</br>";
            //echo '请去支付页确认问题!';
            $data['res'] = 'fail';
            $data['message'] = '验证失败。</br>请去支付页确认问题!</br>';
        }
        $this->load->view('assemble_pay/ali_pay_return', $data);
        // 订单号:$data->out_trade_no
        // 支付宝交易号:$data->trade_no
        // 订单总金额:$data->total_amount
    }

    /**
     * 方法 ali_pay_notify,支付宝支付异步回调接口
     *
     */
    public function ali_pay_notify()
    {
        //接收待验签的数据
        $input_stream = $this->input->raw_input_stream;
        $input_stream = html_entity_decode(htmlspecialchars(iconv('GBK', 'UTF-8', urldecode($input_stream))));
        $input_stream_ary = explode('&', $input_stream);
        $data = array();
        foreach($input_stream_ary as $value){
            $value_ary = explode('=', $value);
            if($value_ary[0] == 'sign'){
                $data[$value_ary[0]] = mb_substr($value, 5);
            }else{
                $data[$value_ary[0]] = $value_ary[1];
            }
        }
        file_put_contents(FCPATH."logs/post.log", json_encode($input_stream).PHP_EOL);
        file_put_contents(FCPATH."logs/post.log", json_encode($data).PHP_EOL);

        try{
            $result = $this->alipay->verify($data); // 是的,验签就这么简单!
            $params = $result->all();

            $trade_status = $result->get('trade_status');
            $params['total_amount'] = $result->get('total_amount')*100;
            $trade_no = $result->get('trade_no');

            // 请自行对 trade_status 进行判断及其它逻辑进行判断,在支付宝的业务通知中,只有交易通知状态为 TRADE_SUCCESS 或 TRADE_FINISHED 时,支付宝才会认定为买家付款成功。
            // 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号;
            // 2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额);
            // 3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email);
            // 4、验证app_id是否为该商户本身。
            // 5、其它业务逻辑情况
            $order = $this->check_ali_pay_params($params, 1);

            if($result) {//验证成功
                /
                //请在这里加上商户的业务逻辑程序代
                //订单状态未修改,这里进行再次处理
                $order_data = [
                    'order_status'=>3,
                    'pay_date'=>$result->get('gmt_payment'),
                    'pay_money'=>$result->get('total_amount')*100,
                    'trade_no'=>$trade_no,
                    'trade_date'=>$result->get('notify_time'),
                    'pay_user' => $result->get('buyer_id'),
                    'trade_result' => $trade_status
                ];
                $order_where = ['order_no'=>$result->get('out_trade_no')];
                $this->assemble_pay_s->update_order_serv($order_where, $order_data);
                //增加订单流水记录
                $this->create_order_bill($order, $trade_no);

                //——请根据您的业务逻辑来编写程序(以下代码仅作参考)——
                //获取支付宝的通知返回参数,可参考技术文档中服务器异步通知参数列表
                //商户订单号
                //$out_trade_no = $params['out_trade_no'];
                //支付宝交易号
                //$trade_no = $params['trade_no'];
                //交易状态
                if($trade_status == 'TRADE_FINISHED') {
                    //判断该笔订单是否在商户网站中已经做过处理
                    //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
                    //请务必判断请求时的total_amount与通知时获取的total_fee为一致的
                    //如果有做过处理,不执行商户的业务程序
                    //注意:
                    //退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知
                }else if ($trade_status == 'TRADE_SUCCESS') {
                    //判断该笔订单是否在商户网站中已经做过处理
                    //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
                    //请务必判断请求时的total_amount与通知时获取的total_fee为一致的
                    //如果有做过处理,不执行商户的业务程序
                    //注意:
                    //付款完成后,支付宝系统发送该交易状态通知
                }
                //——请根据您的业务逻辑来编写程序(以上代码仅作参考)——
                //header("HTTP/1.1 200 OK");
                echo "success";	//请不要修改或删除
                //$res = true;
            }else {
                //验证失败
                echo "fail";
                //$res = false;
            }

            Log::debug('Alipay notify', $result->all());
        } catch (\Exception $e) {
            // $e->getMessage();
        }
        return $this->alipay->success()->send();
        //exit();
        //$this->load->view('assemble_pay/ali_pay_notify', $res);
    }

    /**
     * 方法 check_ali_pay_params,支付包支付返回的参数校验
     *
     * @param array $params 参数数组
     * @param string $order_status 订单状态
     *
     */
    private function check_ali_pay_params($params, $order_status){
        $order_info_where = ['o.order_no' => $params['out_trade_no'], 'order_status' => $order_status];//1,未支付,3:已支付,4:关闭,5:完成
        $order = $this->assemble_pay_s->get_order_info_serv($order_info_where);
        if($order_status == 3 && empty($order)){
            return $order;
        }
        if(empty($order)) output_error(-1, '订单状态异常,订单不存在,请联系卖家!');
        if($order['order_money'] != $params['total_amount']) output_error(-1, '订单金额异常,订单金额与实际支付金额不一致,请联系卖家确认!');
        return $order;
    }

    /**
     * 方法 create_order_bill,创建订单流水记录
     *
     * @param array $order 订单信息
     *
     * @param string $trade_no 支付宝交易流水号
     *
     */
    private function create_order_bill($order, $trade_no){
        $this->load->model('XT_Model');
        $order_bill = $this->XT_Model->execute("select f_bill_no() as order_bill_no");
        $order_bill_no = $order_bill['order_bill_no'];
        $order_bill_data = [
            'order_id' => $order['order_id'],
            'order_bill_no' => $order_bill_no,
            'trade_no' => $trade_no,
            'bill_date' => date('Y-m-d H:i:s', time()),
            'income' => $order['order_money'],
            'pay' => '0',
            'balance' => '0',
            'bill_period' => date('Ym', time()),
            'remark' => '购物下单',
        ];
        $res = $this->assemble_pay_s->create_order_bill_serv($order_bill_data);
    }

    /**
     * 方法 wechat_pay_notify,微信支付异步回调接口
     *
     */
    public function wechat_pay_notify()
    {
        $pay = Pay::wechat($this->wechat_pay_cfg);

        try{
            $result = $pay->verify(); // 是的,验签就这么简单!

            Log::debug('Wechat notify', $result->all());
        } catch (\Exception $e) {
            // $e->getMessage();
        }

        return $pay->success()->send();
    }

}

service服务层文件,assemble_pay_service.php:

<?php
defined('BASEPATH') OR exit('No direct script access allowed');

/**
 * Created by PhpStorm.
 * User: 15237
 * Date: 2019/6/22
 * Time: 15:54
 */
use Yansongda\Pay\Pay;
use Yansongda\Pay\Log;

class assemble_pay_service
{
    public $CI;
    public $_order_tb = 'order';
    public $_product_tb = 'product';
    public $_order_det_tb = 'order_det';
    public $_order_bill_tb = 'order_bill';

    protected $alipay_cfg;//支付宝支付配置
    protected $wechat_pay_cfg;//微信支付配置
    protected $alipay;//支付宝支付对象
    protected $wechatpay;//微信支付对象

    function __construct()
    {
        $this->CI = get_instance();
        //$this->config->load('pay_config');
        $this->alipay_cfg = $this->CI->config->item('ali_pay_cfg');
        $this->wechat_pay_cfg = $this->CI->config->item('wechat_pay_cfg');

        $this->CI->load->helper('pay');

        $this->alipay = Pay::alipay($this->alipay_cfg);
        //$this->wechatpay = Pay::wechat($this->wechat_pay_cfg);
    }

    /**
     * 方法 pay_serv,聚合支付判断方法
     *
     * @param array $params 参数数组
     *
     */
    public function pay_serv($params){
        //1.参数数组两边去空处理
        $params = deal_ary_trim($params);

        //2.判断支付类型调用相关方法
        if(!array_key_exists('pay_type', $params)) output_error(-1, '支付类型参数为空或不存在,无法进行支付!');
        if(!array_key_exists('pay_way', $params)) output_error(-1, '支付方式参数为空或不存在,无法进行支付!');
        $pay_type = $params['pay_type'];
        $pay_way = $params['pay_way'];
        unset($params['pay_type'], $params['pay_way']);

        //3.检查订单是否存在
        $check_where = ['order_no'=>"'".$params['order_no']."'", 'order_status'=>1];
        check_exists_name($check_where, $this->_order_tb, -1, '付款失败,订单不存在或不在待付款状态!',1);

        //4.修改订单状态:支付中
        /*
        $order_where = ['order_no'=>$params['order_no']];
        $order_data = ['order_status'=>2,'pay_type'=>$pay_type];
        $this->update_order_serv($order_where, $order_data);
        */

        //5.库存检查
        //$this->check_product_num($params['order_no']);

        //5.获取订单详情信息
        $order_info_where = ['o.order_no' => $params['order_no'], 'order_status' => 1];//1,未支付,3:已支付,4:关闭,5:完成
        $order = $this->get_order_info_serv($order_info_where);
        if(empty($order)) output_error(-1, '付款失败,不存在未付款的订单记录!');
        $order_name = $order['order_name'];
        $data = [
            'order_no' => $order['order_no'],
            'order_money' => $order['order_money'],
            'order_name' => mb_strlen($order_name) > 256 ? (mb_substr($order_name, 0, 252).'等') : $order_name,
            'auth_code' => $order['auth_code'] ?? '',
        ];

        switch($pay_type){
            case 'ali_pay':
                $this->ali_pay_serv($pay_way, $data);
                break;
            case 'wechat_pay':
                $this->wechat_pay_serv($pay_way, $data);
                break;
            default:
                output_error(-1, '未知的支付类型,请确认!');
        }
    }

    /**
     *方法 check_product_num,付款前核对订单库存
     *
     * @param string $order_no 订单编号(数据库订单唯一编号)
     *
     */
    public function check_product_num(){

    }

    /**
     * 方法 get_order_info_serv,获取订单信息
     *
     * @param array $where 条件数组
     *
     * @return array $order 返回订单信息数组
     *
     */
    public function get_order_info_serv($where){
        $fields = "o.order_id, o.order_no, o.order_status, o.order_money, group_concat(product_name) as order_name";
        $order = $this->CI->db->select($fields, true)
                          ->from($this->_order_tb.' as o')
                          ->join($this->_order_det_tb, $this->_order_det_tb.'.order_no=o.order_no')
                          ->where($where)
                          ->group_by($this->_order_det_tb.'.order_no')
                          ->get()
                          ->row_array();
        return $order;
    }

    /**
     * 方法 update_order_serv,更新订单信息
     *
     * @param array $where 条件数组
     * @param array $data 更新数据
     *
     */
    public function update_order_serv($where, $data){
        $this->CI->load->model('XT_Model');
        $this->CI->XT_Model->mTable = $this->_order_tb;
        $res = $this->CI->XT_Model->update_by_where($where, $data);
        return $res;
    }

    /**
     * 方法 get_order_bill_info_serv,获取订单流水信息
     *
     * @param array $where 条件数组
     *
     * @return array $order_bill 返回订单流水信息数组
     *
     */
    public function get_order_bill_info_serv($where){
        $fields = "order_bill_id, order_id, order_bill_no, trade_no, remark";
        $order_bill = $this->CI->db->select($fields, true)
            ->from($this->_order_bill_tb)
            ->where($where)
            ->get()
            ->row_array();
        return $order_bill;
    }

    /**
     * 方法 create_order_bill_serv,新增订单流水记录
     *
     * @param array $data 插入数据数组
     *
     */
    public function create_order_bill_serv($data){
        $this->CI->load->model('XT_Model');
        $this->CI->XT_Model->mTable = $this->_order_bill_tb;
        $res = $this->CI->XT_Model->insert_string($data);
        return $res;
    }

    /**
     * 方法 ali_pay_serv,支付宝支付方法
     *
     * @param string $pay_way 支付方式
     * @param array $params 参数数组
     *
     */
    private function ali_pay_serv($pay_way, $params){
        //判断支付方式,拼装发起支付的参数数组
        $data = [
            'out_trade_no' => $params['order_no'],
            'total_amount' => round($params['order_money']/100, 2),
            'subject'      => $params['order_name'],
            // 'http_method'  => 'GET' // 如果想在 wap 支付时使用 GET 方式提交,请加上此参数。默认使用 POST 方式提交
        ];
        //5.发起支付
        switch($pay_way){
            case 'web'://电脑支付
                $pay_res = $this->alipay->web($data)->send();
                output_data(['html_str'=>$pay_res->getContent()]);
                break;
            case 'wap'://手机网站支付
                $pay_res = $this->alipay->wap($data)->send();
                break;
            case 'app'://app支付
                $pay_res = $this->alipay->app($data)->send();
                break;
            case 'pos'://刷卡支付
                $data['auth_code'] = $params['auth_code'];
                $pay_res = $this->alipay->pos($data);
                break;
            case 'scan'://扫码支付
                $pay_res = $this->alipay->scan($data);
                break;
            case 'transfer'://账户转账
                $order = [
                    'out_biz_no' => time(),
                    'payee_type' => 'ALIPAY_LOGONID',
                    'payee_account' => 'ghdhjw7124@sandbox.com',
                    'amount' => '0.01',
                ];
                $pay_res = $this->alipay->transfer($order);
                break;
            case 'mini'://小程序支付
                $data['buyer_id'] = $params['buyer_id'];
                $pay_res = $this->alipay->mini($data);
                break;
            default:
                output_error(-1, '未知的支付方式,请确认!');
        }
        return $pay_res;
    }

    /**
     * 方法 wechat_pay_serv,微信支付方法
     *
     * @param string $pay_way 支付方式
     * @param array $params 参数数组
     *
     */
    private function wechat_pay_serv($pay_way, $params){
        //判断支付方式,拼装发起支付的参数数组
        $data = [

        ];
        //判断支付方式,拼装发起支付的参数数组
        switch($pay_way){
            case 'mp'://公众号支付
                break;
            case 'miniapp'://小程序支付
                break;
            case 'wap'://H5支付
                break;
            case 'scan'://扫码支付
                break;
            case 'pos'://刷卡支付
                break;
            case 'app'://app只发
                break;
            case 'transfer'://企业付款
                break;
            case 'redpack'://普通红包
                break;
            case 'groupRedpack'://分类红包
                break;
            default:
                output_error(-1, '未知的支付方式,请确认!');

        }
        //5.发起支付
        $pay = Pay::wechat($this->wechat_pay_cfg)->mp($data);
    }
}

同步通知跳转页面文件ali_pay_return.php:

<!DOCTYPE HTML>
<html>
    <head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <title>支付宝电脑网站支付return_url</title>
	</head>
    <body>
    <?php
        if($res == 'success'){
            echo sprintf($message, $trade_no);
        }else{
            echo $message;
        }
    ?>
    </body>
</html>

以上是支付宝PC网站支付的业务代码,从支付到异步回调通知,再到同步回调通知,仅供参考,欢迎交流。

开发接入注意事项

insufficient-isv-permissions,错误原因: ISV权限不足

问题原因:
应用未上线或支付服务未签约,参考:https://openclub.alipay.com/club/history/read/13201
解决方案参考:

同步通知验签失败

问题原因:
配置文件中ali_public_key使用的是支付宝公钥,而不是应用公钥
解决方案:
去支付宝开发者平台查看支付宝公钥,或到最开始使用秘钥生成工具生成的公钥文件中复制公钥内容,注意公钥中不需要带回车换行符,使用时应去掉,且不包含-----BEGIN PUBLIC KEY-----和-----END PUBLIC KEY-----
在这里插入图片描述

异步通知验签失败

问题原因:
可能是由于支付宝post请求返回的参数编码市GBK,导致中文乱码,致使验签失败,在我使用的这个SDK中,由于支付宝网关设置成了常量,且不能在SDK中直接修改(因为修改过后,每次执行composer都会更新掉,如果不更新代码,可以在网关后面加上?charset=utf-8,指定编码格式解决),所以使用字符编码转换处理。
解决方案:
使用php://input流接收参数,处理中文字符编码问题。
在这里插入图片描述
完整代码参考上面代码块文件。

结语

从支付开始开发,到支付功能开发完成,深有体会的是,可能代码的编写、业务逻辑处理并不是最难的,最难的是对于支付账号信息,你摸不到、碰不了,可能本来给你的信息就是错的,你以为是对的(就像支付宝公钥给成了应用公钥),这是最痛苦的事情,所以,开发之前或者测试出问题的时候,一定要先确认配置信息的正确性,否则可能永远都找不到问题。

********************只要思想不滑坡,办法总比困难多********************
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值