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;
}
}