self::$appID, 'seqNO' => $seqNO, 'random' => strtoupper(md5($seqNO)), 'sm2EncryptData' => self::SM2Encrypt($key, $gf_k), //sm2加密key 'sm2Sign' => self::SM2Sign($key, $k2, $k1), //sm2加密key ]; dump($data); exit; //拼接签名参数,md5转大写 $data['sign'] = self::SM3Crypt($data['random'] . $data['seqNO'] . self::$appSecretKey . $key); dump($data); exit; //发送post接口请求 $res = self::https_post(self::$tokenUrl, $data); dump($res); exit; //解密返回token数据 // $token = self::SM2Decrypt(base64_decode($res['sm2EncryptData']), $k1); self::$token = $token; //返回token return $token; } //业务请求数据 public static function postJry() { //创建模拟请求数据,必须包含head,body $data = [ 'head' => [ 'id' => 8989 ], 'body' => [ 'code' => "000000", 'msg' => "测试请求" ] ]; $res = self::scanPaymentCode($data); dump("返回结果"); halt($res); } //业务请求封装 public static function scanPaymentCode($array = []) { //初始化转换密钥信息 php_HextoAsc(self::string2hex(base64_decode(self::PRIVATE_KEY)), $k1); php_HextoAsc(self::string2hex(base64_decode(self::PUBLIC_KEY)), $k2); php_HextoAsc(self::string2hex(base64_decode(self::CGB_PUBLIC_KEY)), $gf_k); //数据转json $json = json_encode($array, JSON_UNESCAPED_UNICODE); //获取随机6位字符串数字 $seqNO = (string)rand(100000, 999999); //获取随机字符串秘钥,md5 并转大写 $key = strtoupper(md5(self::getKey())); //拼接请求数据 $data = [ 'appID' => self::$appID, 'seqNO' => $seqNO, 'signMethod' => "SM3", 'encryptMethod' => "SM4", 'appAccessToken' => self::getToken(),//获取token 'sm2EncryptData' => self::SM2Encrypt($key, $gf_k), //sm2加密key 'sm2Sign' => self::SM2Sign($key, $k2, $k1), //sm2加密key ]; //拼接签名参数,md5转大写 $data['sign'] = self::SM3Crypt($json . $data['seqNO'] . self::$appSecretKey . $key); //AES加密业务数据 $data['reqData'] = self::SM4Encrypt($json, $data['seqNO'] . $data['appAccessToken'] . self::$appSecretKey . $key); dump("业务数据json"); dump($json); dump("请求数据"); dump($data); $res = self::https_post("https://mouldai.com/apiSIT/tzyj/scanPaymentCode", $data); //解密sm2密钥 $sm2Key = self::SM2Decrypt(base64_decode($res['sm2EncryptData']), $k1); dump("sm2解密数据:" . $sm2Key); //SM4解密数据 $rspData = self::SM4Decrypt($res['rspData'], $res['seqNO'] . $data['appAccessToken'] . self::$appSecretKey . $sm2Key); dump("sm4解密报文数据:" . $rspData); //sm3验签数据校验 $sm3SignData = self::SM3Crypt($rspData . $res['seqNO'] . self::$appSecretKey . $sm2Key); dump("sm3响应报文拼接加签:" . $sm3SignData); $signData = $res['sign']; dump("sm3响应报文签名:" . $signData); if ($sm3SignData == $signData) { dump("验签成功!"); } dump($res); return $res; } //获取post数据并解密解签获得业务数据 public static 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 self::runJson("1000001", "缺少参数"); } dump("获取到的post数据"); dump($arr); //rsa解密秘钥字段rsaEncryptData $rasKey = self::decryptByPublicKey($arr['rsaEncryptData']); dump("解密后的秘钥"); dump($rasKey); //拼接秘钥 $key = $arr['seqNO'] . self::$token . self::$appSecretKey . $rasKey; //秘钥转md5 转大写 $key = strtoupper(md5($key)); //aes解密 $res = $this->decrypt($arr['reqData'], $key); $res = json_decode($res, true); dump("数据结果"); halt($res); } //SM2Encrypt public static function SM2Encrypt($data, $pubkey) { //sm2加密 $recode = php_SM2Encrypt($data, $cipher, $pubkey); //php_SM2Encrypt接口返回的密文值是c1c3c2格式,以下示例转DER编码 $recode = php_SM2FormatConvert(102, $cipher, $der); //SM2加密字符串转base64编码 $sm2encrypted = base64_encode($der); return $sm2encrypted; } //SM2Decrypt public static function SM2Decrypt($data, $privkey) { //php_SM2Decrypt 接收密文值是c1c3c2格式,若对方给的密文值是DER格式 则通过如下方式转换,然后再传入接口解密 $recode = php_SM2FormatConvert(101, $data, $c1c3c2); //解密 $recode = php_SM2Decrypt($c1c3c2, $plain, $privkey); return $plain; } //SM2Sign public static function SM2Sign($data, $pubkey, $privkey) { //签名 $recode = php_SM2Sign($data, $redata, $privkey, $pubkey); //php_SM2Sign接口返回的签名值是RS格式,以下示例转DER编码 $php_func = 'php_SM2FormatConvert'; $recode = $php_func(202, $redata, $der); //加签数据base64返回 $sm2SignData = base64_encode($der); return $sm2SignData; } //SM3Crypt public static function SM3Crypt($data) { $recode = php_SM3Crypt($data, $sm3hash); // echo "
recode:$recode \n"; //加签数据base64返回 return strtoupper(self::string2hex($sm3hash)); } //16进制转换为二进制 public static function hex2String($hexdata) { $bindata = ""; for ($i = 0; $i < strlen($hexdata); $i += 2) { $bindata .= chr(hexdec(substr($hexdata, $i, 2))); } return $bindata; } //SM4Encrypt public static 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, self::$iv); echo "
recode:$recode \n"; echo "
redata: " . base64_encode($redata) . " \n"; $SM4Encryptdata = base64_encode($redata); return $SM4Encryptdata; } //SM4Encrypt public static 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, self::$iv); echo "
sm4[解密]recode:$recode \n"; return $dedata; } /** * 公钥解密 * @param mixed $data 密文数据 * @return string 原文结果 */ private static function decryptByPublicKey($data) { $data = base64_decode($data); openssl_public_decrypt($data, $decrypted, self::PUBLIC_KEY, OPENSSL_PKCS1_PADDING);//公钥解密 return $decrypted; } /** * 私钥加密 * @param mixed $data 原始数据 * @return string 密文结果 */ private static function encryptByPrivateKey($data) { openssl_private_encrypt($data, $encrypted, self::PRIVATE_KEY, OPENSSL_PKCS1_PADDING);//私钥加密 //加密后的内容通常含有特殊字符,需要编码转换下,在网络间通过url传输时要注意base64编码是否是url安全的 return base64_encode($encrypted); } //封装返回数据 private static 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 static 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); return json_decode($tmpInfo, true); } /** * 获得随机字符串 **/ private static function getKey($length = 16) { // 密码字符集,可任意添加你需要的字符 $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ2345678'; $key = ''; for ($i = 0; $i < $length; $i++) { $key .= $chars[mt_rand(0, strlen($chars) - 1)]; } return $key; } }