通联支付生态圈支付系统PHP DEMO
·
Pay.php
<?php
namespace TongLianEcosphere;
include "SubmitCommonRequest.php";
header("Content-type:text/html;charset=utf-8");
class TongLianEcosphere
{
private $url;
private $file_url;
private $header;
private $head;
private $private_key;
private $public_key;
private $sn;
private $DESede;
public function __construct()
{
#--初始化:
#交易接口地址
$this->url='http://****/AppStsWeb/service/acquireAction.action';
#私钥
$this->private_key="****";
#公钥
$this->public_key="****";
#公钥SN
$this->sn="*****";
#DEs168位秘钥
$this->DESede=base64_decode('******');
$this->header=[];
#--set head:
$this->head=array(
"processing_code"=>"", //4位接口编码,详见每支接口描述
"inst_id"=>12345678, //通联分配的机构编码
"trans_date"=>date("Ymd"), //YYYYMMDD
"trans_time"=>date("His"), //HHIISS
"ver_num"=>"1.00", //版本号
);
}
/**
* @desc 单笔交易查询
*
* @return array|null
* @author Tao
* @email 804633234@qq.com
* @date 2022-08-16 09:27
*/
public function SelectResult(){
$s=new SubmitCommonRequest();
$this->head['processing_code']="3001";
$data=[
"req_trace_num"=>"202202020202022", //申请方流水号
"org_req_trace_num"=>"202202020202022", //原交易流水号
"org_resp_trace_num"=>"202202020202022", //原交易通联流水号
"org_trans_date"=>"20220816" //原交易日期
];
//通联私钥签名
$this->head['sign_code']=$this->Sign($this->enxml($this->head,$data),$this->private_key);
//对称加密报文
$EncryptedText=$this->EnRsaEcb($this->enxml($this->head,$data));
//通联公钥对对称秘钥加密
$EncryptedKey=$this->EnRsa($this->DESede,$this->public_key);
//转换成通联DATA
$data=$this->EnCastTlData($EncryptedText,$EncryptedKey);
$result=$s->setReqUrl($this->url)->reqPost($data);
return $result;
}
/**
* @desc 数组转xml适配通联格式
*
* @param $header
* @param $body
* @param bool $req
* @return mixed
* @author Tao
* @email 804633234@qq.com
* @date 2022-08-12 14:33
*/
public function enxml($header, $body,$req=false)
{
$request="request";
if($req){
$request="response";
}
$headerxml = "";
foreach ($header as $key => $val) {
if(!$val&&$val!=0){
$val="";
}
if($key=="sign_code"){
$headerxml .= "<$key>$val</$key>";
}else{
$headerxml .= "<$key>$val</$key>"."\n";
}
}
$bodyxml = "";
foreach ($body as $key => $val) {
if(!$val&&$val!=0){
$val="";
}
$bodyxml .= "<$key>$val</$key>"."\n";
}
$xml = '<?xml version="1.0" encoding="GBK"?>'."\n".
'<transaction>'."\n".
'<head>'."\n".
$headerxml.
'</head>'."\n".
'<'.$request.'>'."\n".
$bodyxml.
'</'.$request.'>'."\n".
'</transaction>';
return $xml;
}
/**
* @desc xml转数组
*
* @param $xml
* @return array|mixed
* @author Tao
* @email 804633234@qq.com
* @date 2022-08-12 14:33
*/
public function dexml($xml)
{
try {
$xml = mb_convert_encoding($xml,'GBK','UTF-8');
return json_decode(json_encode(simplexml_load_string($xml)), true);
} catch (\Throwable $exception) {
return [];
}
}
/**
* @desc RSA签名
*
* @param $str
* @param $private_key
* @return string
* @author Tao
* @email 804633234@qq.com
* @date 2022-08-12 15:03
*/
public function Sign($str,$key){
$bufSignSrc =$str;
$private_key = chunk_split($key , 64, "\n");
$key = "-----BEGIN PRIVATE KEY-----\n".wordwrap($private_key)."-----END PRIVATE KEY-----";
if(openssl_sign($bufSignSrc, $signature, $key ,OPENSSL_ALGO_SHA1)){
//echo "success";
}else{
//echo 'sign fail';
}
$sign = base64_encode($signature);
return $sign;
}
/**
* @desc 验签
*
* @param $str
* @return bool
* @author Tao
* @email 804633234@qq.com
* @date 2022-08-13 18:13
*/
public function ValidSign($data){
$old_sign=$data['head']['sign_code'];
unset($data['head']['sign_code']);
$xml=$this->enxml($data['head'],$data['response'],true);
$xml=str_replace("\r","",$xml);
$public_key = chunk_split($this->public_key , 64, "\n");
$public_key = "-----BEGIN PUBLIC KEY-----\n$public_key-----END PUBLIC KEY-----\n";
$result=openssl_verify($xml, base64_decode($old_sign), $public_key,OPENSSL_ALGO_SHA1);
if($result){
return true;
}else{
return false;
}
}
/**
* @desc Rsa加密
*
* @param $str
* @param $public_key
* @return bool|string
* @author Tao
* @email 804633234@qq.com
* @date 2022-08-12 16:56
*/
public function EnRsa($str,$public_key){
//公钥加密
$public_key = chunk_split($public_key , 64, "\n");
$public_key = "-----BEGIN PUBLIC KEY-----\n$public_key-----END PUBLIC KEY-----\n";
$key = openssl_pkey_get_public($public_key);
if (!$key) {
return('公钥不可用');
}
$result='';
$data = str_split($str, 117);
foreach ($data as $block) {
openssl_public_encrypt($block, $dataEncrypt, $public_key, OPENSSL_PKCS1_PADDING);
$result .= $dataEncrypt;
}
return $result ? base64_encode($result) : null;
}
/**
* @desc Rsa解密
*
* @param $str
* @param $public_key
* @return string
* @author Tao
* @email 804633234@qq.com
* @date 2022-08-12 16:57
*/
public function DeRsa($str,$private_key){
$private_key = chunk_split($private_key , 64, "\n");
$private_key = "-----BEGIN PRIVATE KEY-----\n".wordwrap($private_key)."-----END PRIVATE KEY-----";
$private_key = openssl_pkey_get_private($private_key);
if (!$private_key) {
return('私钥不可用');
}
$crypto = '';
foreach (str_split(base64_decode($str), 128) as $chunk) {
openssl_private_decrypt($chunk, $decryptData, $private_key, OPENSSL_PKCS1_PADDING);
$crypto .= $decryptData;
}
return $crypto;
}
/**
* @desc 转换成通联数据
*
* @param $EncryptedText
* @param $EncryptedKey
* @return string
* @author Tao
* @email 804633234@qq.com
* @date 2022-08-13 11:24
*/
public function EnCastTlData($EncryptedText,$EncryptedKey){
return base64_encode('<STSPackage><EncryptedText>'.$EncryptedText.'</EncryptedText><KeyInfo><ReceiverX509CertSN>'.$this->sn.'</ReceiverX509CertSN><EncryptedKey>'.$EncryptedKey.'</EncryptedKey></KeyInfo></STSPackage>');
}
/**
* @desc 解析通联数据
*
* @param $str
* @return string
* @author Tao
* @email 804633234@qq.com
* @date 2022-08-13 17:24
*/
public function DeCastTlData($str){
$data=$this->dexml(base64_decode($str));
//解析对称密钥
$key=$this->DeRsa($data['KeyInfo']['EncryptedKey'],$this->private_key);
//获取报文
$body=$data['EncryptedText'];
//对称解密
$backData= $this->DeRsaEcb($body, $key);
//解析xml
$xmlToArr=$this->dexml($backData);
//验签
$ValidSign= $this->ValidSign($xmlToArr);
if($ValidSign){
return $backData;
}else{
return false;
}
return $backData;
}
/**
* @desc 对称加密
*
* @param $str
* @return string
* @author Tao
* @email 804633234@qq.com
* @date 2022-08-13 11:16
*/
public function EnRsaEcb($str){
return base64_encode(openssl_encrypt($str, 'DES-EDE3', $this->DESede, OPENSSL_RAW_DATA));
}
/**
* @desc 对称解密
*
* @param $str
* @param $key
* @return string
* @author Tao
* @email 804633234@qq.com
* @date 2022-08-13 11:16
*/
public function DeRsaEcb($str,$key){
$decrypted = openssl_decrypt(base64_decode($str), 'DES-EDE3',$key, OPENSSL_RAW_DATA);
return $decrypted;
}
}
?>
SubmitCommonRequest.php
<?php
namespace TongLianEcosphere;
header("Content-type:text/html;charset=utf-8");
class SubmitCommonRequest
{
public $reqConnectTimeOut = 30;
public $reqTimeOut = 30;
public $reqHeader = array(
"Content-Type:multipart/form-data;"
);
public $autoLog = true;
public $backErr = null;
public $JSON_UNESCAPED = false;
// 返回的code码,统一返回及log使用
private $httpCodeErr = array(
"0"=>"链接超时",
"200"=>"请求发送成功",
"201"=>"请求已完成,并一个新的返回资源被创建",
"400"=>"错误请求",
"403"=>"远程服务器拒绝请求",
"404"=>"请求URI错误",
"500"=>"远程服务器阻止请求",
"502"=>"网关错误,远程服务器没有响应",
"702"=>"请求的文件不存在",
"948"=>"请求的文件名格式不正确",
"949"=>"文件解压失败",
"952"=>"格式校验失败",
);
public $postData = null;
public function __construct()
{
}
/*
* 设置 Source (请求之前使用)
*/
public function setUniCode($isUnCode = false){
if(isset($isUnCode) && $isUnCode=== true){
$this->JSON_UNESCAPED = true;
}
}
/*
* 设置 Source (请求之前使用)
*/
public function setSource($Source){
if (!empty($Source) && is_string($Source)){
$this->Source = $Source;
}
return $this;
}
/*
* 设置自动动log (请求之前使用)
*/
public function setAutoLog($autoLog=true){
if(isset($autoLog) && is_bool($autoLog)){
$this->autoLog = $autoLog;
}
return $this;
}
/*
* 设置请求路径 (请求之前使用)
*/
public function setReqUrl($url){
if(!empty($url) && is_string($url)){
$this->reqUrl = $url;
}
return $this;
}
/*
* 设置返回的信息 (请求之前使用)
* @param array $backCodeData 与httpCode码相对应的返回信息
* @param boolean $isMerge 是否merge,默认true
*/
public function setBackData($backCodeData,$isMerge = true){
if(isset($backCodeData) && !empty($backCodeData) && is_array($backCodeData)){
if($isMerge){
$this->httpCodeErr = array_merge($this->httpCodeErr,$backCodeData);
}else{
$this->httpCodeErr = $backCodeData;
}
}
return $this;
}
/*
* 请求发送
* @param array $postData 请求的数据
* @param array $headArr 请求头设置(数组的merge)
*/
public function reqPost($xmlString){
if(!empty($this->backErr)){
if($this->autoLog){
$this->requestLog($this->backErr);
}
return $this->backErr;
}
if (empty($xmlString)){
$this->backErr = array(
"code"=>"-2",
"message"=>"提交的数据是空数据"
);
if($this->autoLog){
$this->requestLog($this->backErr);
}
return $this->backErr;
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$this->reqUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, ["msgPlain"=>$xmlString]);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT , $this->reqConnectTimeOut);
curl_setopt($ch, CURLOPT_TIMEOUT, $this->reqTimeOut);
$result = curl_exec($ch);
$info = curl_getinfo($ch);
if (isset($info['http_code'])){
if($info['http_code']== 200){
$res = array(
"code"=>"200",
"message"=>"请求成功",
"data"=>$result
);
if($this->autoLog){
$this->requestLog($res);
}
return $res;
}else{
$httpCode = $info['http_code']."";
if(isset($this->httpCodeErr[$httpCode])){
$res= array(
"code"=>$httpCode,
"message"=>$this->httpCodeErr[$httpCode]
);
}else{
if (empty($httpCode)){
$httpCode = "-5";
}
$res = array(
"code"=>$httpCode,
"message"=>"请求远程服务器失败,未知错误"
);
}
if($this->autoLog){
$this->requestLog($res);
}
if(!empty($result)){
$res["source"] = $result;
}
$res["reqUrl"] = $this->reqUrl;
$res["reqBody"] = $xmlString;
return $res;
}
}else{
$this->backErr = array(
"code"=>"-4",
"message"=>"请求远程服务器失败,未知错误"
);
if($this->autoLog){
$this->requestLog($this->backErr);
}
return $this->backErr;
}
}
/*
* 统一请求log
*/
private function requestLog($reqBack){
if(is_array($reqBack)){
$reqBack=json_encode($reqBack,JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE);
}
$this->LogTest(date('YmdHis',time()).":".$reqBack);
}
/*
* 请求头配置 (请求之前使用)
*/
public function setReqHeader($headArr=null){
if(!empty($headArr) && is_array($headArr)){
$headerArray = array_merge($this->reqHeader,$headArr);
$this->reqHeader = $headerArray;
}
return $this;
}
private function LogTest($data){
//设置目录时间
$years = date('Y-m');
//设置路径目录信息
$url = 'log/'.$years.'/'.$years.'_request_log.txt';
//取出目录路径中目录(不包括后面的文件)
$dir_name = dirname($url);
//如果目录不存在就创建
if(!file_exists($dir_name)) {
$res = mkdir(iconv("UTF-8","GBK",$dir_name),0777,true);
}
$fp = fopen($url,"a+");//打开文件资源通道 不存在则自动创建
fwrite($fp,$data."\r\n");//写入文件
fclose($fp);//关闭资源通道
}
}
更多推荐



所有评论(0)