>>>>>> 386b37d33e5ba817cba00df29efaefbd692e4dd1 class Gmdemo extends Controller{ //以下参数都需要金融云提供 //AES偏移量 protected $iv = 'abcdefghABCDEFGH'; <<<<<<< HEAD protected $appID = "93f1a51c1-39d4-48e1-8119-a37b63c0ed8c"; protected $appSecretKey = "66a81e7a-dea3-4870-9c63-58712e13aa9b"; protected $tokenUrl = "https://mouldai.com/apiSIT/tzyj/approveDev";//回归环境 protected $token; //合作机构自有公钥 const PUBLIC_KEY = "MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE6mJz31IQpqtv42a67pfUe6q6UKUa/Lxf2rzJC4iAK0p3dOooG/d+N2fs6qmzK+7smovqcP7VhA8D+OIvaVjMsw=="; ======= protected $appID = "96c8268e-cfa4-497f-9329-a5e3417f0825"; protected $appSecretKey = "921b3c06-eaed-7b1c-e053-010000717745"; protected $tokenUrl = "https://mouldai.com/apiSIT/tzyj/approveDev";//回归环境 protected $token; //合作机构自有公钥 const PUBLIC_KEY = "DE3w4DgjV+np0oHQzSDUgvlxGKPhi/gHBRp8dtjun+z6uqrRJE6B1qswZpaSCs3tp0tm98ZjjL9RTuNh4dyUuA=="; >>>>>>> 386b37d33e5ba817cba00df29efaefbd692e4dd1 //合作机构自有私钥 const PRIVATE_KEY = "778NKKZgdS9IGm/crvajNPoq5CHJNEKXptciF/1SU3I="; //泰隆银行公钥 const CGB_PUBLIC_KEY = "kZYtvaa+HIImu0xhONxte8wyXmMBe7HKKf1i1fqU7Wf8PrsmvAguPNClPXfOoxqW8gmy5qrFK9oX3tvmrq4r0A=="; public function _initialize() { // 初始化加密扩展 echo "--------php_crypto_init 初始化开始--------\n"; <<<<<<< HEAD $path = "/www/wwwroot/hgd.liuniu946.com/public/opt/php/libcryptAPIsm_lnx64.so";//国密动态库路径 ======= $path = "/opt/php/libcryptAPIsm_lnx64.so"; >>>>>>> 386b37d33e5ba817cba00df29efaefbd692e4dd1 php_crypto_init($path); echo "--------php_crypto_init 初始化结束-------\n"; } function string2hex($string){ $hex = ''; for($i = 0;$i < strlen($string); $i++){ $ch = dechex(ord($string[$i])); if(strlen($ch)==1){ $ch = "0".$ch; } $hex .=$ch; } return $hex; } //获取token public function getToken(){ //获取6位数字符串 $seqNO = (string)rand(100000,999999); //获取16位随机字符串并md5 转大写 得到 $key = strtoupper(md5($this->getKey())); //echo $this->string2hex(base64_decode(self::PRIVATE_KEY)); echo $this->string2hex(base64_decode(self::PUBLIC_KEY)); //初始化转换密钥信息 <<<<<<< HEAD // php_HextoAsc($this->string2hex(base64_decode(self::PRIVATE_KEY)),$k1); // php_HextoAsc($this->string2hex(base64_decode(self::PUBLIC_KEY)),$k2); // php_HextoAsc($this->string2hex(base64_decode(self::CGB_PUBLIC_KEY)),$gf_k); $this->string2hex(base64_decode(self::PRIVATE_KEY)); $this->string2hex(base64_decode(self::PUBLIC_KEY)); $this->string2hex(base64_decode(self::CGB_PUBLIC_KEY)); ======= php_HextoAsc($this->string2hex(base64_decode(self::PRIVATE_KEY)),$k1); php_HextoAsc($this->string2hex(base64_decode(self::PUBLIC_KEY)),$k2); php_HextoAsc($this->string2hex(base64_decode(self::CGB_PUBLIC_KEY)),$gf_k); >>>>>>> 386b37d33e5ba817cba00df29efaefbd692e4dd1 //拼接参数数组 $data = [ 'appID' => $this->appID, 'seqNO' => $seqNO, 'random'=> strtoupper(md5($seqNO)), 'sm2EncryptData' => $this->SM2Encrypt($key,$gf_k), //sm2加密key 'sm2Sign' => $this->SM2Sign($key,$k2,$k1), //sm2加密key ]; //拼接签名参数,md5转大写 $data['sign'] = $this->SM3Crypt($data['random'] . $data['seqNO'] . $this->appSecretKey . $key); //发送post接口请求 $res = $this->https_post($this->tokenUrl,$data); //解密返回token数据 $token = $this->SM2Decrypt(base64_decode($res['sm2EncryptData']),$k1); $this->token = $token; //返回token return $token; } //业务请求数据 public function postJry() { //创建模拟请求数据,必须包含head,body $data = [ 'head' => [ 'id' => 8989 ], 'body' => [ 'code'=>"000000", 'msg'=>"测试请求" ] ]; $res = $this->scanPaymentCode($data); dump("返回结果"); halt($res); } //业务请求封装 public function scanPaymentCode($array=[]) { <<<<<<< HEAD $k1 = self::PUBLIC_KEY; $k2 = self::PRIVATE_KEY; $gf_k = self::CGB_PUBLIC_KEY; //初始化转换密钥信息 // php_HextoAsc($this->string2hex(base64_decode(self::PRIVATE_KEY)),$k1); // php_HextoAsc($this->string2hex(base64_decode(self::PUBLIC_KEY)),$k2); // php_HextoAsc($this->string2hex(base64_decode(self::CGB_PUBLIC_KEY)),$gf_k); $this->string2hex(base64_decode(self::PRIVATE_KEY)); $this->string2hex(base64_decode(self::PUBLIC_KEY)); $this->string2hex(base64_decode(self::CGB_PUBLIC_KEY)); //数据转json ======= //初始化转换密钥信息 php_HextoAsc($this->string2hex(base64_decode(self::PRIVATE_KEY)),$k1); php_HextoAsc($this->string2hex(base64_decode(self::PUBLIC_KEY)),$k2); php_HextoAsc($this->string2hex(base64_decode(self::CGB_PUBLIC_KEY)),$gf_k); // $this->string2hex(base64_decode(self::PRIVATE_KEY)); // $this->string2hex(base64_decode(self::PUBLIC_KEY)); // $this->string2hex(base64_decode(self::CGB_PUBLIC_KEY)); //数据转json >>>>>>> 386b37d33e5ba817cba00df29efaefbd692e4dd1 $json = json_encode($array, JSON_UNESCAPED_UNICODE); //获取随机6位字符串数字 $seqNO = (string)rand(100000,999999); //获取随机字符串秘钥,md5 并转大写 $key = strtoupper(md5($this->getKey())); //拼接请求数据 $data = [ 'appID' => $this->appID, 'seqNO' => $seqNO, 'signMethod' => "SM3", 'encryptMethod' => "SM4", 'appAccessToken'=> $this->getToken(),//获取token <<<<<<< HEAD 'sm2EncryptData' => $this->SM2Encrypt($key,self::PUBLIC_KEY), //sm2加密key 'sm2Sign' => $this->SM2Sign($key,$k2,$k1), //sm2加密key ]; ======= 'sm2EncryptData' => $this->SM2Encrypt($key,$gf_k), //sm2加密key 'sm2Sign' => $this->SM2Sign($key,$k2,$k1), //sm2加密key ]; >>>>>>> 386b37d33e5ba817cba00df29efaefbd692e4dd1 //拼接签名参数,md5转大写 $data['sign'] = $this->SM3Crypt($json . $data['seqNO'] . $this->appSecretKey . $key); //AES加密业务数据 $data['reqData'] = $this->SM4Encrypt($json,$data['seqNO'] . $data['appAccessToken'] . $this->appSecretKey . $key); dump("业务数据json"); dump($json); dump("请求数据"); dump($data); $res = $this->https_post("https://mouldai.com/apiSIT/tzyj/scanPaymentCode",$data); //解密sm2密钥 $sm2Key = $this->SM2Decrypt(base64_decode($res['sm2EncryptData']),$k1); dump("sm2解密数据:".$sm2Key); //SM4解密数据 $rspData = $this->SM4Decrypt($res['rspData'],$res['seqNO'] .$data['appAccessToken']. $this->appSecretKey. $sm2Key); dump("sm4解密报文数据:".$rspData); //sm3验签数据校验 $sm3SignData = $this->SM3Crypt($rspData . $res['seqNO'] .$this->appSecretKey . $sm2Key); dump("sm3响应报文拼接加签:".$sm3SignData); $signData = $res['sign']; dump("sm3响应报文签名:".$signData); if ($sm3SignData == $signData) { dump("验签成功!"); } dump($res); return $res; } //获取post数据并解密解签获得业务数据 public function getPostData() { //获取post数据 $arr = input("post."); //模拟post获取数据 $arr = '{"sign":"1CA0926A5C8BC2E2347E57016650E731","signMethod":"MD5","rsaEncryptData":"xs8lNVCj4ZCsAbXoJHI+AmRPqDJk01dlt3q7Jb9Vox4SNvvx6F+DclM2v1FdnDxAsNgXBERLXCc3SOFnqtrcMdYxc2GKyF+YTLJKjX0NmlGkXlO2oipIzhIL94la\/NGEzlT+JL4I8KF5vZvE+4gudkg0mZ+jC6jPWc+qyM6RROdwbgYPCiOpVTaQ+jtIxwz4rCY\/a2z\/fAFazzApUbyRxsCTVRESJ+3dU8V9zYxE7VzrV+IlOCwJdAIAfGPcwjq5wd3p\/3yEeFDBbZz0N6jnIEIlkCH99NsNFWIYY2mH0K2z+ccpJlBejoNq+FaxusS2DvZfJhp8xa3dav8itVyiSw==","encryptMethod":"AES","reqData":"QbYx9PwqKwy30K1SSgiorq9Sg9taSxImEw6qwY93N0QhsRb1UHqBghS+WmbBRZxrBTCMYNGBsG1GFvUdJxIrdXaQ4qBU\/PTpIjLlD+bvRyE27OYgHrSpQ6umylxWXSTYUIO0qbdTjNTR8UwRKPlHjuUJ149E5eH+s\/oyE6zZi9KNzx8BwjeZ\/Qeo\/CQF7fMuu3uJF7XOOIDqLidXvevQEr8hHLUyT40a\/NZsOAoqQSoNppazy+tDuttATH7gFWjFKNzRtt89wDdbjWNtK95tc\/uUBojfjg5HKcctSmqQ7jW6HvA2J5k3WnC6mxsTdaU9WPjtKbnqGUTkoM9YbJs1VghcnnQLSH49wAY7kB5SwWwTaPkHZy5kvytfMvLjwgjUioW0qYSpZyaBww4dSXJ0bQ1Mb+TArunrCpIzl2T4ZkzWT3\/j0m4bJoq7le4l03NVAn8iA3ju2asrBbrySTWzQ9vXDQbq1q+S5uh9YTXrVq0dM6CMNV8KquOCEC0UyaTKxCK2+cAS9LDQD4APXRTuNhkR57LKox2CfvN+CTDlWw8QfFfYKdNpmt\/OHklrUez0LcfMluc08ce1fvoDCuOqMN51y5qhV+d3utWa5rBjvzhE8de5qi54l3qW4EV03sQRdvN7R433fxOVt33N1mZ3NOwx1xjnJ4ivdVuhZ1XbGHd\/B7NGGafQbx3RChEIT250Kl3vih\/P2yF1ozQC8MY6sAHgOxAufmos8DoOwwWy9L59lNqN2sAnVpPalvjM4UCa8pkSrToDaoU4Sc44JOBghQ==","appAccessToken":"","seqNO":"127600","appID":"a539d3d7-3d4b-454b-9c49-7fb83fb8b611"}';//正式获取数据删除这里 $arr = json_decode($arr, true); //正式获取数据删除这里 //检验字段是否缺失 if (!isset($arr['rsaEncryptData']) || !isset($arr['seqNO']) || !isset($arr['signMethod']) || !isset($arr['sign']) || !isset($arr['encryptMethod']) || !isset($arr['reqData']) || !isset($arr['appID'])) { return $this->runJson("1000001", "缺少参数"); } dump("获取到的post数据"); dump($arr); //rsa解密秘钥字段rsaEncryptData $rasKey = $this->decryptByPublicKey($arr['rsaEncryptData']); dump("解密后的秘钥"); dump($rasKey); //拼接秘钥 $key = $arr['seqNO'] . $this->token . $this->appSecretKey . $rasKey; //秘钥转md5 转大写 $key = strtoupper(md5($key)); //aes解密 $res = $this->decrypt($arr['reqData'], $key); $res = json_decode($res, true); dump("数据结果"); halt($res); } //SM2Encrypt function SM2Encrypt($data,$pubkey){ //sm2加密 $recode = php_SM2Encrypt($data, $cipher, $pubkey); echo "
recode:$recode \n"; //php_SM2Encrypt接口返回的密文值是c1c3c2格式,以下示例转DER编码 $recode = php_SM2FormatConvert(102,$cipher, $der); echo "
recode:$recode \n"; //SM2加密字符串转base64编码 $sm2encrypted = base64_encode($der); echo "
sm2加密字符串base64:$sm2encrypted \n"; return $sm2encrypted; } //SM2Decrypt function SM2Decrypt($data,$privkey){ //php_SM2Decrypt 接收密文值是c1c3c2格式,若对方给的密文值是DER格式 则通过如下方式转换,然后再传入接口解密 $recode = php_SM2FormatConvert(101,$data,$c1c3c2); echo "
recode:$recode \n"; //解密 $recode = php_SM2Decrypt($c1c3c2,$plain,$privkey); echo "
recode:$recode \n"; echo "
解密数据plain: $plain\n"; return $plain; } //SM2Sign function SM2Sign($data,$pubkey,$privkey){ //签名 $recode = php_SM2Sign($data, $redata,$privkey,$pubkey); echo "
recode:$recode \n"; //php_SM2Sign接口返回的签名值是RS格式,以下示例转DER编码 $php_func = 'php_SM2FormatConvert'; $recode = $php_func(202,$redata, $der); echo "
recode:$recode \n"; echo "
data: ".$data." len:".strlen($data)." \n"; echo "
signValue DER: ".base64_encode($der)." len:".strlen($der)." \n"; //加签数据base64返回 $sm2SignData = base64_encode($der); return $sm2SignData; } //SM3Crypt function SM3Crypt($data){ $recode = php_SM3Crypt($data,$sm3hash); echo "
recode:$recode \n"; //加签数据base64返回 return strtoupper($this->string2hex($sm3hash)); } //16进制转换为二进制 function hex2String($hexdata){ $bindata=""; for ($i=0;$i < strlen($hexdata);$i+=2) { $bindata.=chr(hexdec(substr($hexdata,$i,2))); } return $bindata; } //SM4Encrypt function SM4Encrypt($data,$password){ //加密密码做特殊处理 先MD5转换大写 从第8位开始截取16个字符串 $password = substr(strtoupper(md5($password)),8,16); echo "
【SM4】MD5加密密码=======".$password; //接口是密文key,将明文key加密后再传入php_SM4CBCCrypt进行数据加密 //不必要每次都加密key,建议手工加密一次,将key密文保存使用,key明文保存至安全的地方 //若是会话级别的key则自行定策略 $recode = php_CryptKey(0, $password,$key); echo "
recode:$recode \n"; //加密 $recode = php_SM4CBCCrypt(0,$data,$redata,$key,$this->iv); echo "
recode:$recode \n"; echo "
redata: ".base64_encode($redata)." \n"; $SM4Encryptdata = base64_encode($redata); return $SM4Encryptdata; } //SM4Encrypt function SM4Decrypt($data,$password){ echo "
SM4解密数据=======".$data; //加密密码做特殊处理 $password = substr(strtoupper(md5($password)),8,16); echo "
MD5密码=======".$password; //接口是密文key,将明文key加密后再传入php_SM4CBCCrypt进行数据加密 //不必要每次都加密key,建议手工加密一次,将key密文保存使用,key明文保存至安全的地方 //若是会话级别的key则自行定策略 $recode = php_CryptKey(0, $password,$key); echo "
recode:$recode \n"; //解密 $recode = php_SM4CBCCrypt(1,base64_decode($data),$dedata,$key,$this->iv); echo "
sm4[解密]recode:$recode \n"; return $dedata; } /** * 公钥解密 * @param 密文数据 $data * @return 原文结果 string */ private function decryptByPublicKey($data) { $data = base64_decode($data); openssl_public_decrypt($data,$decrypted,$this->publicKey,OPENSSL_PKCS1_PADDING);//公钥解密 return $decrypted; } /** * 私钥加密 * @param 原始数据 $data * @return 密文结果 string */ private function encryptByPrivateKey($data) { openssl_private_encrypt($data,$encrypted,$this->privateKey,OPENSSL_PKCS1_PADDING);//私钥加密 $encrypted = base64_encode($encrypted);//加密后的内容通常含有特殊字符,需要编码转换下,在网络间通过url传输时要注意base64编码是否是url安全的 return $encrypted; } //封装返回数据 private function runJson($code="000000",$msg="完成"){ return json(['code'=>$code,'message'=>$msg]); //以下加密信息返回,暂时不用使用 // $data = [ // 'signMethod' => 'MD5', // 'encryptMethod' => 'AES', // 'appID' => $this->appID, // 'seqNO' => (string)rand(100000,999999), // 'appAccessToken' => '' // ]; // $json = json_encode(['code'=>$code, 'message'=>$msg]); // $key = strtoupper(md5(getKey()));//随机秘钥 // $data['rsaEncryptData'] = $this->encryptByPrivateKey($key); // $data['reqData'] = $this->encrypt($json, $key); // $data['sign'] = strtoupper(md5($data['reqData'] . $data['seqNO'] . $this->appSecretKey . $key )); // return json($data); } // curl post请求 private function https_post($url, $data = null) { $data = json_encode($data, JSON_UNESCAPED_SLASHES); $header [] = 'Content-Type:application/x-www-form-urlencoded'; $ch = curl_init(); curl_setopt ( $ch, CURLOPT_HTTPHEADER, $header ); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)'); @curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_setopt($ch, CURLOPT_AUTOREFERER, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $tmpInfo = curl_exec($ch); curl_close($ch); $tmpInfo1 = json_decode($tmpInfo, true); return $tmpInfo1; } /** * 获得随机字符串 **/ private function getKey($length = 16) { // 密码字符集,可任意添加你需要的字符 $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ2345678'; $key = ''; for ($i = 0; $i < $length; $i++) { // 这里提供两种字符获取方式 // 第一种是使用 substr 截取$chars中的任意一位字符; // 第二种是取字符数组 $chars 的任意元素 // $key .= substr($chars, mt_rand(0, strlen($chars) – 1), 1); $key .= $chars[mt_rand(0, strlen($chars) - 1)]; } return $key; } }