PHP档案馆我们就爱程序媛

探索:CodeIgniter集成微信扫码支付方案

2016-07-06  本文已影响995人  三天大愚

微信扫码支付API文档下载地址:微信扫码支付API文档下载

1. 集成微信扫码支付的CI目录结构

├─config 配置文件目录
│ ├─wxpay.php 微信支付配置文件
│ └─...
├─...
├─libraries 扩展类库目录
│ ├─MY_WxPay.php 微信支付
│ ├─MY_WxPayNotify.php 微信支付通知回调
│ ├─Payment 各种支付类库目录
│ │ ├─Wxpaylib 微信支付类库包目录
│ │ │ ├─WxPay.Api.php
│ │ │ ├─WxPay.Config.php
│ │ │ ├─WxPay.Data.php
│ │ │ ├─WxPay.Exception.php
│ │ │ ├─WxPay.Notify.php
│ │ │ ├─apiclient_cert.pem
│ │ │ └─apiclient_key.pem
│ │ └─... 更多支付类库目录
│ └─... 更多第三方类库目录
└─...

2. wxpay.php 微信支付配置文件
<?php defined('BASEPATH') OR exit('No direct script access allowed');
//=======【基本信息设置】=====================================
/**
 * TODO: 修改这里配置为您自己申请的商户信息
 * 微信公众号信息配置
 * 
 * APPID:绑定支付的APPID(必须配置,开户邮件中可查看)
 * 
 * MCHID:商户号(必须配置,开户邮件中可查看)
 * 
 * KEY:商户支付密钥,参考开户邮件设置(必须配置,登录商户平台自行设置)
 * 设置地址:https://pay.weixin.qq.com/index.php/account/api_cert
 * 
 * APPSECRET:公众帐号secert(仅JSAPI支付的时候需要配置, 登录公众平台,进入开发者中心可设置),
 * 获取地址:https://mp.weixin.qq.com/advanced/advanced?action=dev&t=advanced/dev&token=2005451881&lang=zh_CN
 * @var string
 */
$config['APPID'] = '';
$config['MCHID'] = '';
$config['KEY'] = '';
$config['APPSECRET'] = '';

//=======【证书路径设置】=====================================
/**
 * TODO:设置商户证书路径
 * 证书路径,注意应该填写绝对路径(仅退款、撤销订单时需要,可登录商户平台下载,
 * API证书下载地址:https://pay.weixin.qq.com/index.php/account/api_cert,下载之前需要安装商户操作证书)
 * @var path
 */
$config['SSLCERT_PATH'] = './apiclient_cert.pem';
$config['SSLKEY_PATH'] = './apiclient_key.pem';

//=======【curl代理设置】===================================
/**
 * TODO:这里设置代理机器,只有需要代理的时候才设置,不需要代理,请设置为0.0.0.0和0
 * 本例程通过curl使用HTTP POST方法,此处可修改代理服务器,
 * 默认CURL_PROXY_HOST=0.0.0.0和CURL_PROXY_PORT=0,此时不开启代理(如有需要才设置)
 * @var unknown_type
 */
$config['CURL_PROXY_HOST'] = "0.0.0.0";//"10.152.18.220";
$config['CURL_PROXY_PORT'] = 0;//8080;

//=======【上报信息配置】===================================
/**
 * TODO:接口调用上报等级,默认紧错误上报(注意:上报超时间为【1s】,上报无论成败【永不抛出异常】,
 * 不会影响接口调用流程),开启上报之后,方便微信监控请求调用的质量,建议至少
 * 开启错误上报。
 * 上报等级,0.关闭上报; 1.仅错误出错上报; 2.全量上报
 * @var int
 */
$config['REPORT_LEVENL'] = 1;


// 服务器异步通知页面路径  需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
$config['NOTIFY_URL'] = site_url('pay/wxpaynotify');
3. 修改 WxPay.Data.php

当然你也可以直接将这些参数写在这里,而不需要wxpay.php配置文件

<?php defined('BASEPATH') OR exit('No direct script access allowed');
$_CI = & get_instance();
$_CI->load->config('wxpay');
define('WX_APPID', $_CI->config->item('APPID'));
define('WX_MCHID', $_CI->config->item('MCHID'));
define('WX_KEY', $_CI->config->item('KEY'));
define('WX_APPSECRET', $_CI->config->item('APPSECRET'));
define('WX_SSLCERT_PATH', $_CI->config->item('SSLCERT_PATH'));
define('WX_SSLKEY_PATH', $_CI->config->item('SSLKEY_PATH'));
define('WX_NOTIFY_URL', $_CI->config->item('NOTIFY_URL'));
unset($_CI);

/**
 *  配置账号信息
 */
class WxPayConfig {

    //=======【基本信息设置】=====================================
    //
    /**
     * TODO: 修改这里配置为您自己申请的商户信息
     * 微信公众号信息配置
     * 
     * APPID:绑定支付的APPID(必须配置,开户邮件中可查看)
     * 
     * MCHID:商户号(必须配置,开户邮件中可查看)
     * 
     * KEY:商户支付密钥,参考开户邮件设置(必须配置,登录商户平台自行设置)
     * 设置地址:https://pay.weixin.qq.com/index.php/account/api_cert
     * 
     * APPSECRET:公众帐号secert(仅JSAPI支付的时候需要配置, 登录公众平台,进入开发者中心可设置),
     * 获取地址:https://mp.weixin.qq.com/advanced/advanced?action=dev&t=advanced/dev&token=2005451881&lang=zh_CN
     * @var string
     */
    const APPID = WX_APPID;
    const MCHID = WX_MCHID;
    const KEY = WX_KEY;
    const APPSECRET = WX_APPSECRET;
    
    //=======【证书路径设置】=====================================
    /**
     * TODO:设置商户证书路径
     * 证书路径,注意应该填写绝对路径(仅退款、撤销订单时需要,可登录商户平台下载,
     * API证书下载地址:https://pay.weixin.qq.com/index.php/account/api_cert,下载之前需要安装商户操作证书)
     * @var path
     */
    const SSLCERT_PATH = WX_SSLCERT_PATH;
    const SSLKEY_PATH = WX_SSLKEY_PATH;
    
    //=======【curl代理设置】===================================
    /**
     * TODO:这里设置代理机器,只有需要代理的时候才设置,不需要代理,请设置为0.0.0.0和0
     * 本例程通过curl使用HTTP POST方法,此处可修改代理服务器,
     * 默认CURL_PROXY_HOST=0.0.0.0和CURL_PROXY_PORT=0,此时不开启代理(如有需要才设置)
     * @var unknown_type
     */
    const CURL_PROXY_HOST = "0.0.0.0";//"10.152.18.220";
    const CURL_PROXY_PORT = 0;//8080;
    
    //=======【上报信息配置】===================================
    /**
     * TODO:接口调用上报等级,默认紧错误上报(注意:上报超时间为【1s】,上报无论成败【永不抛出异常】,
     * 不会影响接口调用流程),开启上报之后,方便微信监控请求调用的质量,建议至少
     * 开启错误上报。
     * 上报等级,0.关闭上报; 1.仅错误出错上报; 2.全量上报
     * @var int
     */
    const REPORT_LEVENL = 1;

    const NOTIFY_URL = WX_NOTIFY_URL;
}
4. MY_WxPay.php 自定义微信支付类
<?php defined('BASEPATH') OR exit('No direct script access allowed');

// 加载微信支付接口类
require_once APPPATH.'libraries/Payment/Wxpaylib/WxPay.Api.php';

/**
 * MY_WxPay 自定义微信支付类
 * @author Mike Lee
 */
class MY_WxPay {

    private $_CI;

    public function  __construct(){
        // 获得 CI 超级对象 使得自定义类可以使用Controller类的方法
        $this->_CI = & get_instance();
    }

    /**
     * createPayQRcode2
     * 生成直接支付url 支付url有效期为2小时 模式二
     * @param array $params 统一下单参数组
     * @return void
     * @author Mike Lee
     */
    public function createPayQRcode2($params){
        $input = $this->getUnifiedOrderInput($params);
        if ($input->GetTrade_type() == 'NATIVE') {
            $result = WxPayApi::unifiedOrder($input);
            // 这里也可以直接返回code_url 然后直接使用demo中生成二维码的方式
            // return urlencode($result['code_url']);
            $this->_CI->load->library('MY_QRcode');
            $this->_CI->my_qrcode->createQRcode($result['code_url']);
        }
    }

    /**
     * getUnifiedOrderInput 获取统一下单输入对象
     * @access public
     * @param array $params
     * @return UnifiedOrderInput $input
     * @author Mike Lee
     */
    public function getUnifiedOrderInput($params){
        $input = new WxPayUnifiedOrder();
        $input->SetOut_trade_no($params['out_trade_no']);
        $input->SetBody($params['body']);
        // $input->SetAttach("test");
        // $input->SetOut_trade_no(WxPayConfig::MCHID.date("YmdHis"));
        $input->SetTotal_fee($params['total_fee']);
        $input->SetTime_start(date("YmdHis"));
        $input->SetTime_expire(date("YmdHis", time() + 600));
        // $input->SetGoods_tag("test");
        // $input->SetNotify_url("http://paysdk.weixin.qq.com/example/notify.php");
        $input->SetTrade_type($params['trade_type']);
        $input->SetProduct_id($params['product_id']);
        // $input->SetSpbill_create_ip($params['spbill_create_ip']);
        return $input;
    }

    /**
     * wxPayOrderQuery 微信支付订单查询
     * @access public
     * @param string $order_code
     * @param bool $mode
     * @return array
     * @author Mike Lee
     */
    public function getWxPayOrderInfo($order_code, $mode = false){
        if ( ! $order_code) return false;
        $input = new WxPayOrderQuery();
        if ($mode) {
            // 微信订单号
            $input->SetTransaction_id($order_code);
        } else {
            // 商户订单号
            $input->SetOut_trade_no($order_code);
        }
        
        return WxPayApi::orderQuery($input);
    }

}


/* End of file MY_Wxpay.php */
/* Location: ./application/libraries/MY_WxPay.php */
5. MY_WxPayNotify.php 自定义微信支付通知类
<?php defined('BASEPATH') OR exit('No direct script access allowed');

// 加载微信支付接口类
require_once APPPATH.'libraries/Payment/Wxpaylib/WxPay.Api.php';
require_once APPPATH.'libraries/Payment/Wxpaylib/WxPay.Notify.php';

/**
 * MY_WxPayNotify 自定义微信支付类
 * @author Mike Lee
 */
class MY_WxPayNotify extends WxPayNotify {

    private $_CI;

    public function  __construct(){
        // 获得 CI 超级对象 使得自定义类可以使用Controller类的方法
        $this->_CI = & get_instance();
    }

    /**
     * NotifyProcess 微信回调处理
     * @access public
     */
    public function NotifyProcess($data, &$msg){
        //echo "处理回调";
        log_message('error', json_encode($data));

        if ($data['return_code'] == 'SUCCESS' && $data['result_code'] == 'SUCCESS') {
            $this->updateOrderPay($data);
            return true;
        }

        return false;
    }

    /**
     * updateOrderPay 更新订单支付信息
     * @access private
     * @param string $order_code
     * @return mixed
     * @author Mike Lee
     */
    public function updateOrderPay($wxpay_data){
        $this->_CI->load->model('order_model');
        // 根据订单号获取订单信息
        $order_code = $wxpay_data['out_trade_no'];
        $order_info = $this->_CI->order_model->getOrderByID($order_code, true);
        if ($order_info['order_status'] == 0 && $order_info['pay_status'] != '1') {
            // 更新订单的支付状态及支付方式
            // pay_status => 1 表示支付成功
            // pay_method => 2 表示支付方式为微信支付
            $pay_info = array('pay_status' => '1', 'pay_method' => 2);
            $pay_result = $this->_CI->order_model->updateOrderPayStatus($order_code, $pay_info, true);
            // 添加订单支付信息
            // user_id 用户ID
            // order_id 订单ID
            // total_fee 支付总额
            // openid 用户微信唯一ID
            $order_pay_info = array(
                'user_id'   => $order_info['user_id'],
                'order_id'  => $order_info['id'],
                'total_fee' => $wxpay_data['cash_fee'] / 100,
                'openid'    => $wxpay_data['openid'],
                'time'      => time()
            );
            $this->_CI->order_model->addOrderWxPayLog($order_pay_info);
            // 添加用户收支日志
            // correlation_id 关联ID 这里为订单ID
            // action_type => 1 表示为商品购买事件
            // point_type => 4 表示为微信支付
            $payment_log = array(
                'user_id'        => $order_info['user_id'],
                'correlation_id' => $order_info['id'],
                'action_type'    => 1,
                'pay_type'     => 4,
                'total_fee'  => $wxpay_data['cash_fee'] / 100,
                'remark'         => 'XXXX商品购买:微信支付'.$wxpay_data['cash_fee'] / 100,
                'action_ip'      => $_SERVER['REMOTE_ADDR'],
                'add_time'       => time()
            );
            $this->_CI->order_model->addUserPayLog($payment_log);
        }
        return true;
    }


}


/* End of file MY_WxPayNotify.php */
/* Location: ./application/libraries/MY_WxPayNotify.php */
6. pay.php 支付控制器
<?php defined('BASEPATH') OR exit('No direct script access allowed');
/**
 * pay 支付控制器
 */
class Pay extends MY_Controller {

    public function __construct(){
        $this->isNeedLogin = FALSE;
        parent::__construct();
    }

    /**
     * generateQRcode 生成微信支付二维码
     * @access public
     * @param void
     * @return void
     * @author Mike Lee
     */
    public function generateWxPayQRcode($order_code = false){
        if ( ! $order_code) {
            $order_code = $this->uri->segment(3, false);
            if ( ! $order_code)  return false;
        }

        $this->load->model('order_model');
        $order_info = $this->order_model->getOrderByID($order_code, true);
        if ( ! is_array($order_info) || ! $order_info) {
            return false;
        }
        // 准备微信支付参数数组
        $params = array(
            'out_trade_no'  => $order_code,
            'body'          => 'XXXX网商品购买',
            'total_fee'     => $order_info['order_amount'] * 100,
            'trade_type'    => 'NATIVE',
            'spbill_create_ip'  => $_SERVER['REMOTE_ADDR'],
            'product_id'    => 1
        );
        $this->load->library('MY_WxPay');
        $this->my_wxpay->createPayQRcode2($params);
    }

    /**
     * wxPayNotify 微信回调
     * @access public
     * @param void
     * @return void
     * @author Mike Lee
     */
    public function wxPayNotify(){
        $this->load->library('MY_WxPayNotify');
        $result = $this->my_wxpaynotify->Handle(true);
    }

    /**
     * wxPayResult 微信支付结果查询
     * @access public
     * @param void
     * @return void
     * @author Mike Lee
     */
    public function wxPayResult(){
        $order_code = $this->input->post('order_code', true);
        $pay_method = $this->input->post('pay_method', true);
        $this->load->model('order_model');
        $order_info = $this->order_model->getOrderByID($order_code, true);
        if ($order_info['is_pay'] == '1') {
            $this->ajaxReturn('SUCCESS');
        } else {
            $this->ajaxReturn('WAITING');
        }
        // sleep(1);
    }

}


/* End of file pay.php */
/* Location: ./application/controllers/pay.php */
上一篇下一篇

猜你喜欢

热点阅读