系列目錄
支付寶集成:http://www.cnblogs.com/nerve/p/3437879.html
系列說明
最近在幫朋友的系統安裝支付模塊(兌換網站積分),現在總結一些開發心得,希望對大家有用。這個系列會講以下第三方支付平臺的集成:
- 支付寶 https://www.alipay.com/
- 匯潮支付 http://www.ecpss.cn/new/index.htm
- 智付支付 http://www.dinpay.com/
- 環迅支付 http://www.ips.com/Default.aspx
以後有更新其他平臺也會寫出來。
這次的支付系統是用來網站的積分充值。爲了簡化,這裏採用的是1元RMB=1個網站積分的兌換。
這裏,不會描述怎麼申請支付平臺的收款帳號。
開發環境
ThinkPHP 3.1.2 (我用的是標準版)
win7 + Apache2
mysql 5.1
匯潮支付有自己的接口文檔:http://download.csdn.net/detail/ssrc0604hx/6635299
爲了方便使用,我將此支付接口封裝成Ecpss.php, 放在 ThinkPhp 的Vendor目錄下:
在此類中,填寫相應的商戶號跟MD5Key(這些在申請了 匯潮支付後,都可以從匯潮網站得到的)。
然後在Ecpss類中,封裝了html form 的生成,可以直接跳轉到支付頁面,下面是Ecpss.php的代碼:
<?php
/**
* Ecpss.php
*==============================
*匯潮支付時用的庫
*==============================
* by:0604hx [email protected]
* Nov 20, 2013 9:02:58 PM
*/
class Ecpss{
/*
* 支付請求的配置
*/
var $config;
var $MD5Key = "";
var $pay_url = "https://pay.ecpss.cn/sslpayment";
/**
* 構造函數
* 參數中應該包括:
* BillNo 訂單號
* Amount 交易金額
* ReturnURL 返回路徑
* products 商品信息
*
* @param unknown_type $c
*/
public function __construct($c=array()){
$this->config['MerNo'] = ""; //商戶號,必須
$this->config['orderTime'] = date("YmdHis"); //請求時間,格式爲 YYYYMMDDHHMMSS
$this->config['AdviceURL'] = "";
$this->config['defaultBankNumber'] = "";
$this->config['Remark'] = "";
//合併兩個數組
$this->config = array_merge($this->config, $c);
}
/**
* 生成支付html
*
* 默認使用post方式提交
*/
public function buildSubmitHtml(){
$this->config['SignInfo'] = $this->createSignInfo();
//生成表單
$sHtml = "<form id='ecpssForm' name='ecpssForm' action='".$this->pay_url."' method='post'>";
foreach ($this->config as $key => $val) {
$sHtml.= "<input type='hidden' name='".$key."' value='".$val."'/>";
}
//submit按鈕控件請不要含有name屬性
$sHtml = $sHtml."<input type='submit' value='去支付'></form>";
$sHtml = $sHtml."<script>document.forms['ecpssForm'].submit();</script>";
return $sHtml;
}
/**
* 生成簽名
* 方式:
* MerNo&BillNo&Amount&ReturnURL&MD5key
* 連接起來進行 MD5 加密後字符串,並進行大寫轉換
*
* 參數之間必須添加&符號,比如:16885&B00001&1.00&http://ecpss.cn&keyvalue,各參數之間添加&符號進行連接
*/
private function createSignInfo(){
$sign = $this->config['MerNo']."&".$this->config['BillNo']
."&".$this->config['Amount']."&".$this->config['ReturnURL']."&".$this->MD5Key;
$sign = md5($sign);
//轉換成大寫
return strtoupper($sign);
}
/**
* 對服務器返回的數據進行驗證
* 參數的 md5校驗串, BillNo & Amount & Succeed & MD5key
*/
public function verify(){
//$sign = $_REQUEST['BillNo']."&".$_REQUEST['Amount']."&".$_REQUEST['Succeed']."&".$this->MD5Key;
//return md5($sign) == $_REQUEST['MD5info'];
return $_REQUEST['Succeed'] == 88;
}
}
?>
注意:
Ecpss中的 verify方法是對匯潮服務器返回數據的校對,我按照接口文檔的說明進行驗證,結果一直無法驗證通過,問了技術客服,也得不到答案。
後來我直接判斷返回的數據中‘Succeed’一欄是否==88(88就是支付成功)
請大家慎重使用。
然後要使用這個類也比較方便, 下面列出使用方法:
/*
* ------------------------------------------------------------------------------------------------
* Start 匯潮支付
* ------------------------------------------------------------------------------------------------
*/
private function payWithEcpss($order){
vendor("Ecpss.Ecpss");
$e['BillNo'] = $order['tradeNo'];
$e['Amount'] = $order['price'];
$e['ReturnURL'] = C("HOST")."index.php/Order/backOnEcpss";
$e['AdviceURL'] = C("HOST")."index.php/Order/notifyOnEcpss";
$e['products'] = $order['subject'];
$ecpss = new Ecpss($e);
echo $ecpss->buildSubmitHtml();
}
/**
* 匯潮支付成功後返回的處理action
*/
public function backOnEcpss(){
$this->dealWithEcpssBack(true);
}
/**
* 從ecpss得到的notify通知
*/
public function notifyOnEcpss(){
$this->dealWithEcpssBack(false);
}
/**
* 處理匯潮的返回值
*
* @param unknown_type $isReturn true爲return,false 爲notify返回
*/
private function dealWithEcpssBack($isReturn=true){
vendor("Ecpss.Ecpss");
$orderLogDao = new OrderLogModel();
$ecpss = new Ecpss();
$orderLog['addDate'] = sqlDate();
$log = "notify from Ecpss,";
/**
* 通過驗證
*/
if($ecpss->verify()){
//根據訂單號獲取訂單
$DAO = new OrderModel();
$order = $DAO->where("tradeNo='".$_REQUEST['BillNo']."'")->find();
/*
* 如果status不爲0,那麼就不需要處理,防止重複處理
*/
if(isset($order)){
$orderLog['order_id'] = $order['id'];
if($order['status'] == 0){
$resultInfo = $this->doAfterPaySuccess($DAO, $order);
$log.= $resultInfo;
}else{
$log.= "但是訂單已經被處理過了,無需重複處理!";
}
}else{
$orderLog['order_id'] = -1;
$log.= "但是訂單號在本地數據庫不存在!";
}
}else{
//驗證不通過時,也記錄下來
$log.= "但是驗證不通過";
$orderLog['order_id'] = -1;
}
$orderLog['log'] = $log." [返回值爲:sign=".$_REQUEST['MD5info']." ".$this->buildEcpssInfo()." ]";
$orderLogDao->add($orderLog);
if($isReturn)
redirect(__APP__."/Order/payResult?orderId=".$orderLog['order_id'], 0);
else
echo "ok";
}
private function buildEcpssInfo(){
return '訂單號='.$_REQUEST['BillNo']." 金額=".$_REQUEST['Amount']." 結果代碼=".$_REQUEST['Succeed']." result code=".$_REQUEST['Result'];
}
/*
* ------------------------------------------------------------------------------------------------
* End 匯潮支付
* ------------------------------------------------------------------------------------------------
*/
(關於Order的字段,在“支付寶集成”中有相關說明)