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);//关闭资源通道
  }
}

更多推荐