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

微信扫码支付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 */
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,880评论 25 707
  • 本文使用的支付宝即时到账业务接口,API文档下载地址:支付宝即时到账接口文档 1. 集成支付宝的CI目录结构 ├─...
    三天大愚阅读 962评论 0 3
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,067评论 4 62
  • 广播分为有序广播和无序广播 有序广播所有与广播中的action匹配的广播接收者都可以收到这条广播,但是是有先后顺序...
    yanghanbin_it阅读 362评论 0 0
  • 总有那么一瞬间不知道何去何从!只是有点累。明天还得继续。早睡只是为了更好的明天,愿都好!安
    工匠21阅读 311评论 0 0