整合第三方支付问题

浏览:3425 发布日期:2017/03/24 分类:求助交流
求助 怎么把这个借口对接到thinkphp上呢 不会弄求大神帮忙解答 万分感谢

req.php#    商户扩展信息
##商户可以任意填写1K 的字符串,支付成功时将原样返回.                                                
$pa_MP                        = '';

#    支付通道编码
##默认为"",到101卡网关.若不需显示普讯101卡的页面,直接跳转到各银行、神州行支付、骏网一卡通等支付页面,该字段可依照附录:银行列表设置参数值.            
$pd_FrpId                    = $_REQUEST['pd_FrpId'];

#    应答机制
##默认为"1": 需要应答机制;
$pr_NeedResponse    = "1";

#调用签名函数生成签名串
$hmac = getReqHmacString($p2_Order,$p3_Amt,$p4_Cur,$p5_Pid,$p6_Pcat,$p7_Pdesc,$p8_Url,$pa_MP,$pd_FrpId,$pr_NeedResponse);
     
?> 
<html>
<head>
<title>101卡</title>
</head>
<body onLoad="document.diy.submit();">
<form name='diy' id="diy" action='<?php echo $reqURL_onLine; ?>' method='post'>
<input type='hidden' name='p0_Cmd'                    value='<?php echo $p0_Cmd; ?>'>
<input type='hidden' name='p1_MerId'                value='<?php echo $p1_MerId; ?>'>
<input type='hidden' name='p2_Order'                value='<?php echo $p2_Order; ?>'>
<input type='hidden' name='p3_Amt'                    value='<?php echo $p3_Amt; ?>'>
<input type='hidden' name='p4_Cur'                    value='<?php echo $p4_Cur; ?>'>
<input type='hidden' name='p5_Pid'                    value='<?php echo $p5_Pid; ?>'>
<input type='hidden' name='p6_Pcat'                    value='<?php echo $p6_Pcat; ?>'>
<input type='hidden' name='p7_Pdesc'                value='<?php echo $p7_Pdesc; ?>'>
<input type='hidden' name='p8_Url'                    value='<?php echo $p8_Url; ?>'>
<input type='hidden' name='p9_SAF'                    value='<?php echo $p9_SAF; ?>'>
<input type='hidden' name='pa_MP'                        value='<?php echo $pa_MP; ?>'>
<input type='hidden' name='pd_FrpId'                value='<?php echo $pd_FrpId; ?>'>
<input type='hidden' name='pr_NeedResponse'    value='<?php echo $pr_NeedResponse; ?>'>
<input type='hidden' name='hmac'                        value='<?php echo $hmac; ?>'>
</form>
</body>
</html>
Properties.php<?php

/*
 * @Description 普讯科技产品通用接口范例 
 * @V3.0
 * @Author rui.xin
 */

#    商户编号p1_MerId,以及密钥merchantKey 需要从普讯科技101卡平台获得
$p1_MerId            = "8880004";                                                                                                        #测试使用
$merchantKey    = "6dcc3a7a2a854569846062c206d2ff3e";        #测试使用

$logName    = "BANK_HTML.log";

?> 
HttpClient.class.php/* Version 0.9, 6th April 2003 - Simon Willison ( http://simon.incutio.com/ )
   Manual: http://scripts.incutio.com/httpclient/
*/

class HttpClient {
    // Request vars
    var $host;
    var $port;
    var $path;
    var $method;
    var $postdata = '';
    var $cookies = array();
    var $referer;
    var $accept = 'text/xml,application/xml,application/xhtml+xml,text/html,text/plain,image/png,image/jpeg,image/gif,*/*';
    var $accept_encoding = 'gzip';
    var $accept_language = 'en-us';
    var $user_agent = 'Incutio HttpClient v0.9';
    // Options
    var $timeout = 20;
    var $use_gzip = true;
    var $persist_cookies = true;  // If true, received cookies are placed in the $this->cookies array ready for the next request
                                  // Note: This currently ignores the cookie path (and time) completely. Time is not important, 
                                  //       but path could possibly lead to security problems.
    var $persist_referers = true; // For each request, sends path of last request as referer
    var $debug = false;
    var $handle_redirects = true; // Auaomtically redirect if Location or URI header is found
    var $max_redirects = 5;
    var $headers_only = false;    // If true, stops receiving once headers have been read.
    // Basic authorization variables
    var $username;
    var $password;
    // Response vars
    var $status;
    var $headers = array();
    var $content = '';
    var $errormsg;
    // Tracker variables
    var $redirect_count = 0;
    var $cookie_host = '';
    function HttpClient($host, $port=80) {
        $this->host = $host;
        $this->port = $port;
    }
    function get($path, $data = false) {
        $this->path = $path;
        $this->method = 'GET';
        if ($data) {
            $this->path .= '?'.$this->buildQueryString($data);
        }
        return $this->doRequest();
    }
    function post($path, $data) {
        $this->path = $path;
        $this->method = 'POST';
        $this->postdata = $this->buildQueryString($data);
        return $this->doRequest();
    }
    function buildQueryString($data) {
        $querystring = '';
        if (is_array($data)) {
            // Change data in to postable data
            foreach ($data as $key => $val) {
                if (is_array($val)) {
                    foreach ($val as $val2) {
                        $querystring .= urlencode($key).'='.urlencode($val2).'&';
                    }
                } else {
                    $querystring .= urlencode($key).'='.urlencode($val).'&';
                }
            }
            $querystring = substr($querystring, 0, -1); // Eliminate unnecessary &
        } else {
            $querystring = $data;
        }
        return $querystring;
    }
    function doRequest() {
        // Performs the actual HTTP request, returning true or false depending on outcome
        if (!$fp = @fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout)) {
            // Set error message
            switch($errno) {
                case -3:
                    $this->errormsg = 'Socket creation failed (-3)';
                case -4:
                    $this->errormsg = 'DNS lookup failure (-4)';
                case -5:
                    $this->errormsg = 'Connection refused or timed out (-5)';
                default:
                    $this->errormsg = 'Connection failed ('.$errno.')';
                $this->errormsg .= ' '.$errstr;
                $this->debug($this->errormsg);
            }
            return false;
        }
        socket_set_timeout($fp, $this->timeout);
        $request = $this->buildRequest();
        $this->debug('Request', $request);
        fwrite($fp, $request);
        // Reset all the variables that should not persist between requests
        $this->headers = array();
        $this->content = '';
        $this->errormsg = '';
        // Set a couple of flags
        $inHeaders = true;
        $atStart = true;
        // Now start reading back the response
        while (!feof($fp)) {
            $line = fgets($fp, 4096);
            if ($atStart) {
                // Deal with first line of returned data
                $atStart = false;
                if (!preg_match('/HTTP\/(\\d\\.\\d)\\s*(\\d+)\\s*(.*)/', $line, $m)) {
                    $this->errormsg = "Status code line invalid: ".htmlentities($line);
                    $this->debug($this->errormsg);
                    return false;
                }
                $http_version = $m[1]; // not used
                $this->status = $m[2];
                $status_string = $m[3]; // not used
                $this->debug(trim($line));
                continue;
            }
            if ($inHeaders) {
                if (trim($line) == '') {
                    $inHeaders = false;
                    $this->debug('Received Headers', $this->headers);
                    if ($this->headers_only) {
                        break; // Skip the rest of the input
                    }
                    continue;
                }
                if (!preg_match('/([^:]+):\\s*(.*)/', $line, $m)) {
                    // Skip to the next header
                    continue;
                }
                $key = strtolower(trim($m[1]));
                $val = trim($m[2]);
                // Deal with the possibility of multiple headers of same name
                if (isset($this->headers[$key])) {
                    if (is_array($this->headers[$key])) {
                        $this->headers[$key][] = $val;
                    } else {
                        $this->headers[$key] = array($this->headers[$key], $val);
                    }
                } else {
                    $this->headers[$key] = $val;
                }
                continue;
            }
            // We're not in the headers, so append the line to the contents
            $this->content .= $line;
        }
        fclose($fp);
        // If data is compressed, uncompress it
        if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] == 'gzip') {
            $this->debug('Content is gzip encoded, unzipping it');
            $this->content = substr($this->content, 10); // See http://www.php.net/manual/en/function.gzencode.php
            $this->content = gzinflate($this->content);
        }
        // If $persist_cookies, deal with any cookies
        if ($this->persist_cookies && isset($this->headers['set-cookie']) && $this->host == $this->cookie_host) {
            $cookies = $this->headers['set-cookie'];
            if (!is_array($cookies)) {
                $cookies = array($cookies);
            }
            foreach ($cookies as $cookie) {
                if (preg_match('/([^=]+)=([^;]+);/', $cookie, $m)) {
                    $this->cookies[$m[1]] = $m[2];
                }
            }
            // Record domain of cookies for security reasons
            $this->cookie_host = $this->host;
        }
        // If $persist_referers, set the referer ready for the next request
        if ($this->persist_referers) {
            $this->debug('Persisting referer: '.$this->getRequestURL());
            $this->referer = $this->getRequestURL();
        }
        // Finally, if handle_redirects and a redirect is sent, do that
        if ($this->handle_redirects) {
            if (++$this->redirect_count >= $this->max_redirects) {
                $this->errormsg = 'Number of redirects exceeded maximum ('.$this->max_redirects.')';
                $this->debug($this->errormsg);
                $this->redirect_count = 0;
                return false;
            }
            $location = isset($this->headers['location']) ? $this->headers['location'] : '';
            $uri = isset($this->headers['uri']) ? $this->headers['uri'] : '';
            if ($location || $uri) {
                $url = parse_url($location.$uri);
                // This will FAIL if redirect is to a different site
                return $this->get($url['path']);
            }
        }
        return true;
    }
    function buildRequest() {
        $headers = array();
        $headers[] = "{$this->method} {$this->path} HTTP/1.0"; // Using 1.1 leads to all manner of problems, such as "chunked" encoding
        $headers[] = "Host: {$this->host}";
        $headers[] = "User-Agent: {$this->user_agent}";
        $headers[] = "Accept: {$this->accept}";
        if ($this->use_gzip) {
            $headers[] = "Accept-encoding: {$this->accept_encoding}";
        }
        $headers[] = "Accept-language: {$this->accept_language}";
        if ($this->referer) {
            $headers[] = "Referer: {$this->referer}";
        }
        // Cookies
        if ($this->cookies) {
            $cookie = 'Cookie: ';
            foreach ($this->cookies as $key => $value) {
                $cookie .= "$key=$value; ";
            }
            $headers[] = $cookie;
        }
        // Basic authentication
        if ($this->username && $this->password) {
            $headers[] = 'Authorization: BASIC '.base64_encode($this->username.':'.$this->password);
        }
        // If this is a POST, set the content type and length
        if ($this->postdata) {
            $headers[] = 'Content-Type: application/x-www-form-urlencoded';
            $headers[] = 'Content-Length: '.strlen($this->postdata);
        }
        $request = implode("\r\n", $headers)."\r\n\r\n".$this->postdata;
        return $request;
    }
    function getStatus() {
        return $this->status;
    }
    function getContent() {
        return $this->content;
    }
    function getHeaders() {
        return $this->headers;
    }
    function getHeader($header) {
        $header = strtolower($header);
        if (isset($this->headers[$header])) {
            return $this->headers[$header];
        } else {
            return false;
        }
    }
    function getError() {
        return $this->errormsg;
    }
    function getCookies() {
        return $this->cookies;
    }
    function getRequestURL() {
        $url = 'http://'.$this->host;
        if ($this->port != 80) {
            $url .= ':'.$this->port;
        }            
        $url .= $this->path;
        return $url;
    }
    // Setter methods
    function setUserAgent($string) {
        $this->user_agent = $string;
    }
    function setAuthorization($username, $password) {
        $this->username = $username;
        $this->password = $password;
    }
    function setCookies($array) {
        $this->cookies = $array;
    }
    // Option setting methods
    function useGzip($boolean) {
        $this->use_gzip = $boolean;
    }
    function setPersistCookies($boolean) {
        $this->persist_cookies = $boolean;
    }
    function setPersistReferers($boolean) {
        $this->persist_referers = $boolean;
    }
    function setHandleRedirects($boolean) {
        $this->handle_redirects = $boolean;
    }
    function setMaxRedirects($num) {
        $this->max_redirects = $num;
    }
    function setHeadersOnly($boolean) {
        $this->headers_only = $boolean;
    }
    function setDebug($boolean) {
        $this->debug = $boolean;
    }
    // "Quick" static methods
    function quickGet($url) {
        $bits = parse_url($url);
        $host = $bits['host'];
        $port = isset($bits['port']) ? $bits['port'] : 80;
        $path = isset($bits['path']) ? $bits['path'] : '/';
        if (isset($bits['query'])) {
            $path .= '?'.$bits['query'];
        }
        $client = new HttpClient($host, $port);
        if (!$client->get($path)) {
            return false;
        } else {
            return $client->getContent();
        }
    }
    function quickPost($url, $data) {
        $bits = parse_url($url);
        $host = $bits['host'];
        $port = isset($bits['port']) ? $bits['port'] : 80;
        $path = isset($bits['path']) ? $bits['path'] : '/';
        $client = new HttpClient($host, $port);
        if (!$client->post($path, $data)) {
            return false;
        } else {
            return $client->getContent();
        }
    }
    function debug($msg, $object = false) {
        if ($this->debug) {
            print '<div style="border: 1px solid red; padding: 0.5em; margin: 0.5em;"><strong>HttpClient Debug:</strong> '.$msg;
            if ($object) {
                ob_start();
                print_r($object);
                $content = htmlentities(ob_get_contents());
                ob_end_clean();
                print '<pre>'.$content.'</pre>';
            }
            print '</div>';
        }
    }   
}

?>
Common.php<?php
include 'Properties.php';
/*
 * @Description 普讯科技产品通用接口范例 
 * @V3.0
 * @Author rui.xin
 */
     
    #    产品通用接口正式请求地址
     $reqURL_onLine = "http://api.101ka.com/GateWay/Bank/Default.aspx";
        
    # 业务类型
    # 支付请求,固定值"Buy" .    
    $p0_Cmd = "Buy";
        
    #    送货地址
    $p9_SAF = "0";
    
#签名函数生成签名串
function getReqHmacString($p2_Order,$p3_Amt,$p4_Cur,$p5_Pid,$p6_Pcat,$p7_Pdesc,$p8_Url,$pa_MP,$pd_FrpId,$pr_NeedResponse)
{
  global $p0_Cmd;
  global $p9_SAF;
    include 'Properties.php';
        
    #进行签名处理,一定按照文档中标明的签名顺序进行
  $sbOld = "";
  #加入业务类型
  $sbOld = $sbOld.$p0_Cmd;
  #加入商户编号
  $sbOld = $sbOld.$p1_MerId;
  #加入商户订单号
  $sbOld = $sbOld.$p2_Order;     
  #加入支付金额
  $sbOld = $sbOld.$p3_Amt;
  #加入交易币种
  $sbOld = $sbOld.$p4_Cur;
  #加入商品名称
  $sbOld = $sbOld.$p5_Pid;
  #加入商品分类
  $sbOld = $sbOld.$p6_Pcat;
  #加入商品描述
  $sbOld = $sbOld.$p7_Pdesc;
  #加入商户接收支付成功数据的地址
  $sbOld = $sbOld.$p8_Url;
  #加入送货地址标识
  $sbOld = $sbOld.$p9_SAF;
  #加入商户扩展信息
  $sbOld = $sbOld.$pa_MP;
  #加入支付通道编码
  $sbOld = $sbOld.$pd_FrpId;
  #加入是否需要应答机制
  $sbOld = $sbOld.$pr_NeedResponse;
    logstr($p2_Order,$sbOld,HmacMd5($sbOld,$merchantKey));
  return HmacMd5($sbOld,$merchantKey);
  


function getCallbackHmacString($r0_Cmd,$r1_Code,$r2_TrxId,$r3_Amt,$r4_Cur,$r5_Pid,$r6_Order,$r7_Uid,$r8_MP,$r9_BType)
{
  
    include 'Properties.php';
  
    #取得加密前的字符串
    $sbOld = "";
    #加入商家ID
    $sbOld = $sbOld.$p1_MerId;
    #加入消息类型
    $sbOld = $sbOld.$r0_Cmd;
    #加入业务返回码
    $sbOld = $sbOld.$r1_Code;
    #加入交易ID
    $sbOld = $sbOld.$r2_TrxId;
    #加入交易金额
    $sbOld = $sbOld.$r3_Amt;
    #加入货币单位
    $sbOld = $sbOld.$r4_Cur;
    #加入产品Id
    $sbOld = $sbOld.$r5_Pid;
    #加入订单ID
    $sbOld = $sbOld.$r6_Order;
    #加入用户ID
    $sbOld = $sbOld.$r7_Uid;
    #加入商家扩展信息
    $sbOld = $sbOld.$r8_MP;
    #加入交易结果返回类型
    $sbOld = $sbOld.$r9_BType;

    logstr($r6_Order,$sbOld,HmacMd5($sbOld,$merchantKey));
    return HmacMd5($sbOld,$merchantKey);

}


#    取得返回串中的所有参数
function getCallBackValue(&$r0_Cmd,&$r1_Code,&$r2_TrxId,&$r3_Amt,&$r4_Cur,&$r5_Pid,&$r6_Order,&$r7_Uid,&$r8_MP,&$r9_BType,&$hmac)
{  
    $r0_Cmd        = $_REQUEST['r0_Cmd'];
    $r1_Code    = $_REQUEST['r1_Code'];
    $r2_TrxId    = $_REQUEST['r2_TrxId'];
    $r3_Amt        = $_REQUEST['r3_Amt'];
    $r4_Cur        = $_REQUEST['r4_Cur'];
    $r5_Pid        = $_REQUEST['r5_Pid'];
    $r6_Order    = $_REQUEST['r6_Order'];
    $r7_Uid        = $_REQUEST['r7_Uid'];
    $r8_MP        = $_REQUEST['r8_MP'];
    $r9_BType    = $_REQUEST['r9_BType']; 
    $hmac            = $_REQUEST['hmac'];
    
    return null;
}

function CheckHmac($r0_Cmd,$r1_Code,$r2_TrxId,$r3_Amt,$r4_Cur,$r5_Pid,$r6_Order,$r7_Uid,$r8_MP,$r9_BType,$hmac)
{
    if($hmac==getCallbackHmacString($r0_Cmd,$r1_Code,$r2_TrxId,$r3_Amt,$r4_Cur,$r5_Pid,$r6_Order,$r7_Uid,$r8_MP,$r9_BType))
        return true;
    else
        return false;
}
        
  
function HmacMd5($data,$key)
{
// RFC 2104 HMAC implementation for php.
// Creates an md5 HMAC.
// Eliminates the need to install mhash to compute a HMAC
// Hacked by Lance Rushing(NOTE: Hacked means written)

//需要配置环境支持iconv,否则中文参数不能正常处理
$key = iconv("GB2312","UTF-8",$key);
$data = iconv("GB2312","UTF-8",$data);

$b = 64; // byte length for md5
if (strlen($key) > $b) {
$key = pack("H*",md5($key));
}
$key = str_pad($key, $b, chr(0x00));
$ipad = str_pad('', $b, chr(0x36));
$opad = str_pad('', $b, chr(0x5c));
$k_ipad = $key ^ $ipad ;
$k_opad = $key ^ $opad;

return md5($k_opad . pack("H*",md5($k_ipad . $data)));
}

function logstr($orderid,$str,$hmac)
{
include 'Properties.php';
$james=fopen($logName,"a+");
fwrite($james,"\r\n".date("Y-m-d H:i:s")."|orderid[".$orderid."]|str[".$str."]|hmac[".$hmac."]");
fclose($james);
}

?> 
callback.php<?php

/*
 * @Description 普讯科技101卡支付B2C在线支付接口范例 
 * @V3.0
 * @Author rui.xin
 */
 
include 'Common.php';    
    
#    只有支付成功时101卡才会通知商户.
##支付成功回调有两次,都会通知到在线支付请求参数中的p8_Url上:浏览器重定向;服务器点对点通讯.

#    解析返回参数.
$return = getCallBackValue($r0_Cmd,$r1_Code,$r2_TrxId,$r3_Amt,$r4_Cur,$r5_Pid,$r6_Order,$r7_Uid,$r8_MP,$r9_BType,$hmac);

#    判断返回签名是否正确(True/False)
$bRet = CheckHmac($r0_Cmd,$r1_Code,$r2_TrxId,$r3_Amt,$r4_Cur,$r5_Pid,$r6_Order,$r7_Uid,$r8_MP,$r9_BType,$hmac);
#    以上代码和变量不需要修改.
         
#    校验码正确.
if($bRet){
    if($r1_Code=="1"){
        
    #    需要比较返回的金额与商家数据库中订单的金额是否相等,只有相等的情况下才认为是交易成功.
    #    并且需要对返回的处理进行事务控制,进行记录的排它性处理,在接收到支付结果通知后,判断是否进行过业务逻辑处理,不要重复进行业务逻辑处理,防止对同一条交易重复发货的情况发生.                
        
        if($r9_BType=="1"){
            echo "交易成功";
            echo  "<br />在线支付页面返回";
        }elseif($r9_BType=="2"){
            #如果需要应答机制则必须回写流,以success开头,大小写不敏感.
            echo "success";
            echo "<br />交易成功";
            echo  "<br />在线支付服务器返回";                   
        }
    }
    
}else{
    echo "交易信息被篡改";
}
   
?>
<html>
<head>
<title>Return from  Page</title>
</head>
<body>
</body>
</html>
说明:首先欢迎您选择101卡平台提供的支付接入服务。此目录的例子是PHP代码版本的,您可以直接把所有文件放在WEB服务器上应用的目录下,进行测试运行。
1)文件列表说明
|------------------------------Common.php    (共通函数文件,正式请求地址在此文件中修改)
|------------------------------Properties.php    (商家属性文件,商家可以在此文件中修改商家的ID和密钥和支付返回地址等信息)
|------------------------------req.php    (支付请求文件,通过此文件发起支付请求,商家可以在此文件中写入自己的订单信息等,然后把请求提交给101卡平台)
|------------------------------callback.php    (支付结果返回文件,通过此文件商家判断对应订单的支付成功状态,并且根据结果修改自己数据库中的订单状态)
|------------------------------QueryOrder.php   (101卡平台查询接口主程序)
|------------------------------HttpClient.class.php   (共通函数文件,用于服务器通讯)

2)商家测试可以先用101卡平台的测试商家测试成功再在Properties.php文件中修改成自己的商家ID和密钥信息
$p1_MerId = "0000";
$merchantKey = "0000000000000000000";
商家ID和密钥需要同时修改才有效

3)支付成功的返回URL请在pay.html文件中进行修改
接收支付成功数据的地址填写"http://localhost/callback.php"; 
商家正式运行时,必须把自己的服务器部署在公网上的服务器上,这样支付成功后101卡平台的服务器才能将支付结果及时返回给商家

4)共通文件采用服务器包含的方式进行处理
如:
include 'Common.php';
所以如果您修改共通文件请帮助每个文件能够编译通过。

5)101卡平台支持在商家选择银行和在101卡平台网关选择银行的两种方式
可以通过设定req.php中frpId的值来进行调整。银行ID请参考101卡平台的文档说明

6) 请确保iconv函数,这样就可以支持中文商品名称

7)本地的STR,商户编号和KEY的查找位置(在出现“交易签名无效”的错误时需要查找STR)
str:在 虚拟目录下的日志文件中 默认是 _HTML.log
商户编号:在 Properties.php 文件中的 p1_MerId
key:在 Properties.php 文件中的 merchantKey

8)log保存地址配置
Properties.php文件中的logName    

9)在接收到支付结果通知后,判断是否进行过业务逻辑处理,不要重复进行业务逻辑处理
最佳答案
评论( 相关
后面还有条评论,点击查看>>