本文使用的支付寶即時到賬業(yè)務(wù)接口,API文檔下載地址:支付寶即時到賬接口文檔
1. 集成支付寶的CI目錄結(jié)構(gòu)
├─config 配置文件目錄
│ ├─alipay.php 支付寶配置文件
│ └─...
├─...
├─libraries 擴展類庫目錄
│ ├─MY_AlipayNotify.php 支付寶返回通知
│ ├─MY_AlipaySubmit.php 支付提交
│ ├─Payment 各種支付類庫目錄
│ │ ├─Alipaylib 支付寶類庫包目錄
│ │ │ ├─alipay_core.function.php
│ │ │ ├─alipay_md5.function.php
│ │ │ ├─alipay_submit.class.php
│ │ │ ├─alipay_notify.class.php
│ │ │ └─cacert.pem
│ │ ├─Wechatpay 微信支付類庫目錄
│ │ └─... 更多支付類庫目錄
│ └─... 更多第三方類庫目錄
└─...
2. alipay.php 支付寶配置文件
<?php defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Alipay 配置文件
*/
//↓↓↓↓↓↓↓↓↓↓請在這里配置您的基本信息↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
//合作身份者ID,簽約賬號渺鹦,以2088開頭由16位純數(shù)字組成的字符串赁酝,查看地址:https://b.alipay.com/order/pidAndKey.htm
$config['partner'] = '';
//收款支付寶賬號路星,以2088開頭由16位純數(shù)字組成的字符串并蝗,一般情況下收款賬號就是簽約賬號
$config['seller_id'] = $config['partner'];
// MD5密鑰卧檐,安全檢驗碼克懊,由數(shù)字和字母組成的32位字符串忱辅,查看地址:https://b.alipay.com/order/pidAndKey.htm
$config['key'] = '';
// 服務(wù)器異步通知頁面路徑 需http://格式的完整路徑七蜘,不能加?id=123這類自定義參數(shù),必須外網(wǎng)可以正常訪問
$config['notify_url'] = site_url('pay/alipaynotify');
// 頁面跳轉(zhuǎn)同步通知頁面路徑 需http://格式的完整路徑墙懂,不能加?id=123這類自定義參數(shù)橡卤,必須外網(wǎng)可以正常訪問
$config['return_url'] = site_url('pay/alipayreturn');
//簽名方式
$config['sign_type'] = strtoupper('MD5');
//字符編碼格式 目前支持 gbk 或 utf-8
$config['input_charset']= strtolower('utf-8');
//ca證書路徑地址,用于curl中ssl校驗
//請保證cacert.pem文件在當前文件夾目錄中
$config['cacert'] = getcwd().'\\cacert.pem';
//訪問模式,根據(jù)自己的服務(wù)器是否支持ssl訪問损搬,若支持請選擇https碧库;若不支持請選擇http
$config['transport'] = 'http';
// 支付類型 ,無需修改
$config['payment_type'] = "1";
// 產(chǎn)品類型巧勤,無需修改
$config['service'] = "create_direct_pay_by_user";
//↑↑↑↑↑↑↑↑↑↑請在這里配置您的基本信息↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
//↓↓↓↓↓↓↓↓↓↓ 請在這里配置防釣魚信息嵌灰,如果沒開通防釣魚功能,為空即可 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
// 防釣魚時間戳 若要使用請調(diào)用類文件submit中的query_timestamp函數(shù)
$config['anti_phishing_key'] = "";
// 客戶端的IP地址 非局域網(wǎng)的外網(wǎng)IP地址颅悉,如:221.0.0.1
$config['exter_invoke_ip'] = "";
//↑↑↑↑↑↑↑↑↑↑請在這里配置防釣魚信息沽瞭,如果沒開通防釣魚功能,為空即可 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
?>
3. MY_AlipaySubmit.php 支付寶支付
<?php defined('BASEPATH') OR exit('No direct script access allowed');
// 加載支付寶支付提交類
require_once APPPATH.'libraries/Payment/Alipaylib/alipay_submit.class.php';
/**
* MY_AlipaySubmit
* @author Mike Lee
*/
class MY_AlipaySubmit extends AlipaySubmit {
protected $_CI;
public function __construct($config = array()){
// 獲得 _CI 超級對象
$this->_CI = & get_instance();
// 判斷是否存在配置文件
if (empty($config)) {
// 加載 Alipay 配置文件
$this->_CI->load->config('alipay', TRUE);
$config = $this->_CI->config->item('alipay');
}
parent::__construct($config);
}
/**
* submit 支付提交
* @access public
* @param string $out_trade_no 商戶訂單號 商戶網(wǎng)站訂單系統(tǒng)中唯一訂單號
* @param string $subject 訂單名稱
* @param float $total_fee 付款金額
* @param string $body 商品描述 可空
* @return void
* @author Mike Lee
*/
public function submit($order_code){
$this->_CI->load->model('order_model');
$order_info = $this->_CI->order_model->getOrderByID($order_code, true);
if ( ! is_array($order_info) || ! $order_info) return false;
$subject = 'XXXX訂單';
$total_fee = $order_info['order_amount'];
$body = 'XXXX網(wǎng)站商品購買';
// 構(gòu)造要請求的參數(shù)數(shù)組
$parameter = array(
"service" => $this->alipay_config['service'],
"partner" => $this->alipay_config['partner'],
"seller_id" => $this->alipay_config['seller_id'],
"payment_type" => $this->alipay_config['payment_type'],
"notify_url" => $this->alipay_config['notify_url'],
"return_url" => $this->alipay_config['return_url'],
"anti_phishing_key" => $this->alipay_config['anti_phishing_key'],
"exter_invoke_ip" => $this->alipay_config['exter_invoke_ip'],
"out_trade_no" => $order_code,
"subject" => $subject,
"total_fee" => $total_fee,
"body" => $body,
"_input_charset" => trim(strtolower($this->alipay_config['input_charset']))
);
$html_text = $this->buildRequestForm($parameter, 'get', '確認');
return $html_text;
}
}
/* End of file MY_AlipaySubmit.php */
/* Location: ./application/libraries/MY_AlipaySubmit.php */
?>
4. MY_AlipayReturn.php 支付寶返回通知
<?php defined('BASEPATH') OR exit('No direct script access allowed');
// 加載支付寶通知類
require_once APPPATH.'libraries/Payment/Alipaylib/alipay_notify.class.php';
/**
* MY_AlipayNotify
* @author Mike Lee
*/
class MY_AlipayNotify extends AlipayNotify {
protected $_CI;
public function __construct($config = array()){
// 獲得 CI 超級對象 使得自定義類可以使用Controller類的方法
$this->_CI = & get_instance();
// 判斷是否存在配置文件
if (empty($config)) {
// 加載 Alipay 配置文件
$this->_CI->load->config('alipay', TRUE);
$config = $this->_CI->config->item('alipay');
}
parent::__construct($config);
}
/**
* asynNotify 異步通知
* @access public
* @param void
* @return void
* @author Mike Lee
*/
public function asynNotify(){
$verify_result = $this->verifyNotify();
if($verify_result) { //驗證成功
$notify_data = $this->_CI->input->post(null, true);
//交易狀態(tài)
$trade_status = $notify_data['trade_status'];
// 根據(jù)交易狀態(tài)處理訂單支付狀態(tài)
if($trade_status == 'TRADE_FINISHED' || $trade_status == 'TRADE_SUCCESS') {
// 更新訂單支付信息
$this->updateOrderPay($notify_data);
}
echo 'success'; //請不要修改或刪除
} else { //驗證失敗
echo 'fail'; //請不要修改或刪除
}
}
/**
* syncReturn 頁面跳轉(zhuǎn)同步通知
* @access public
* @param void
* @return void
* @author Mike Lee
*/
public function syncReturn(){
$verify_result = $this->verifyReturn();
if($verify_result) { // 驗證成功
$return_data = $this->_CI->input->get(null, true);
// 交易狀態(tài)
$trade_status = $return_data['trade_status'];
if($trade_status == 'TRADE_FINISHED' || $trade_status == 'TRADE_SUCCESS') {
// 更新訂單支付信息
$this->updateOrderPay($return_data);
return true;
} else {
return false;
}
return true;
} else {
// 驗證失敗
return false;
}
}
/**
* updateOrderPay 更新訂單支付信息
* @access private
* @param string $order_code
* @return mixed
* @author Mike Lee
*/
public function updateOrderPay($alipay_data){
$this->_CI->load->model('order_model');
// 根據(jù)訂單號獲取訂單信息
$order_code = $alipay_data['out_trade_no'];
$order_info = $this->_CI->order_model->getOrderByID($order_code, true);
// 判斷訂單狀態(tài)以及是否已經(jīng)支付
if ($order_info['order_status'] == 0 && $order_info['pay_status'] != '1') {
// 更新訂單的支付狀態(tài)及支付方式
// pay_status => 1 表示支付成功
// pay_method => 3 表示支付方式為支付寶支付
$pay_info = array('pay_status' => '1', 'pay_method' => 3);
$pay_result = $this->_CI->order_model->updateOrderPayStatus($order_code, $pay_info, true);
// 添加訂單支付信息
// user_id 用戶ID
// order_id 訂單ID
// total_fee 支付總額
// openid 用戶支付寶ID buyer_id
$order_pay_info = array(
'user_id' => $order_info['user_id'],
'order_id' => $order_info['id'],
'total_fee' => $alipay_data['total_fee'],
#'total_fee' => $alipay_data['price'],
'buyer_id' => $alipay_data['buyer_id'],
'time' => time()
);
$this->_CI->order_model->addOrderPayLog($order_pay_info);
// 添加用戶收支日志
// correlation_id 關(guān)聯(lián)ID 這里為訂單ID
// action_type => 1 表示為XXXX商品購買事件
// point_type => 5 表示為支付寶支付
$payment_log = array(
'user_id' => $order_info['user_id'],
'correlation_id' => $order_info['id'],
'action_type' => 1,
'pay_type' => 5,
'total_fee' => $alipay_data['total_fee'],
'remark' => 'XXX網(wǎng)站商品購買:支付寶支付'.$alipay_data['total_fee'],
'action_ip' => $_SERVER['REMOTE_ADDR'],
'add_time' => time()
);
$this->_CI->order_model->addUserPayLog($payment_log);
}
return true;
}
}
/* End of file MY_AlipayNotify.php */
/* Location: ./application/libraries/MY_AlipayNotify.php */
5. 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();
}
/**
* submitPaymentToAlipay 提交支付寶支付
* @access public
* @param string $order_code
* @return void
* @author Mike Lee
*/
public function submitPaymentToAlipay($order_code){
$this->load->library('MY_AlipaySubmit');
$result = $this->my_alipaysubmit->submit($order_code);
if ($result === false) {
// 無效訂單跳轉(zhuǎn)
// 請注意這里的跳轉(zhuǎn)方法是自己寫的
$this->jumpNoticePage('無訂單信息剩瓶!', $_SERVER['HTTP_REFERER'], 'ERROR');
}
$this->assign('html_text', $result);
$this->display('order/alipay.html');
}
/**
* aliPayNotify 支付寶異步回調(diào)
* notify_url http://www.xxxx.com/index.php/pay/alipaynotify
* @access public
* @param void
* @return void
* @author Mike Lee
*/
public function aliPayNotify(){
$this->load->library('MY_AlipayNotify');
$this->my_alipaynotify->asynNotify();
}
/**
* aliPayReturn 支付寶同步通知
* return_url http://www.xxxx.com/index.php/pay/alipayreturn
* @access public
* @param void
* @return void
* @author Mike Lee
*/
public function aliPayReturn(){
$this->load->library('MY_AlipayNotify');
if ($this->my_alipaynotify->syncReturn()) {
// 驗證成功 這里可以執(zhí)行你想要的跳轉(zhuǎn)
$this->jumpNoticePage('訂單支付成功驹溃!', site_url('order'));
} else {
// 驗證失敗跳轉(zhuǎn)
$this->jumpNoticePage('訂單支付失敗儒搭!', site_url('order'), 'ERROR');
}
}
6. 小結(jié)
總體來說吠架,支付寶支付的使用還是很簡單的,目前支付寶即時到賬有密退款DEMO還沒有去研究搂鲫,有時間肯定會繼續(xù)更新的。另外我覺得支付寶即時到賬DEMO中庫文件太多磺平,后期準備將這些庫文件整理成一個文件一個類魂仍,這樣可以讓整個集成結(jié)構(gòu)更加清晰。
在調(diào)用支付寶支付成功后支付寶的同步跳轉(zhuǎn)中出現(xiàn)了一個不明原因的驗證錯誤拣挪,經(jīng)過調(diào)試發(fā)現(xiàn)擦酌,在執(zhí)行verifyReturn驗證方法的過程中有個去除空值及簽名參數(shù)的函數(shù)paraFilter執(zhí)行后會使得$_GET中的第一個參數(shù)丟失,比如$para_temp['body']為第一個參數(shù)且不為空菠劝,執(zhí)行paraFilter($para_temp)后body丟失了赊舶,但這個函數(shù)本身是沒有問題的,這就導致我至今還沒有找到造成參數(shù)丟失的原因赶诊,只好按照支付寶技術(shù)支持的方法在丟失參數(shù)的地方手動加上這個參數(shù)笼平,這才驗證通過。