初始化项目
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
// app/common/crypto/Crypto.php
|
||||
namespace app\common\crypto;
|
||||
|
||||
class Crypto
|
||||
{
|
||||
protected $privateKey;
|
||||
protected $platformPublicKey;
|
||||
|
||||
public function __construct($company)
|
||||
{
|
||||
$this->orgNo = $company['orgNo'];
|
||||
$this->appKey = $company['appKey'];
|
||||
$this->privateKey = $this->loadPrivateKey($company['privateKey']);
|
||||
$this->publicKey = $this->loadPublicKey($company['publicKey']);
|
||||
$this->platformPublicKey = $this->loadPublicKey($company['platformPublicKey']);
|
||||
}
|
||||
|
||||
protected function loadPrivateKey($base64PrivateKey)
|
||||
{
|
||||
$privateKey = "-----BEGIN PRIVATE KEY-----\n" .
|
||||
chunk_split($base64PrivateKey, 64, "\n") .
|
||||
"-----END PRIVATE KEY-----\n";
|
||||
$key = openssl_pkey_get_private($privateKey);
|
||||
if ($key === false) {
|
||||
throw new \Exception('Invalid private key: ' . openssl_error_string());
|
||||
}
|
||||
return $key;
|
||||
}
|
||||
|
||||
protected function loadPublicKey($base64PublicKey)
|
||||
{
|
||||
$publicKey = "-----BEGIN PUBLIC KEY-----\n" .
|
||||
chunk_split($base64PublicKey, 64, "\n") .
|
||||
"-----END PUBLIC KEY-----\n";
|
||||
$key = openssl_pkey_get_public($publicKey);
|
||||
if ($key === false) {
|
||||
throw new \Exception('Invalid public key: ' . openssl_error_string());
|
||||
}
|
||||
return $key;
|
||||
}
|
||||
|
||||
public function sign($data)
|
||||
{
|
||||
openssl_sign($data, $signature, $this->privateKey, OPENSSL_ALGO_SHA256);
|
||||
return base64_encode($signature);
|
||||
}
|
||||
|
||||
public function verifySign($data, $signature)
|
||||
{
|
||||
$decodedSignature = base64_decode($signature);
|
||||
return openssl_verify($data, $decodedSignature, $this->platformPublicKey, OPENSSL_ALGO_SHA256);
|
||||
}
|
||||
|
||||
public function encryptData($data, $key)
|
||||
{
|
||||
$encryptedData = openssl_encrypt($data, 'AES-256-ECB', $key, OPENSSL_PKCS1_PADDING);
|
||||
return base64_encode($encryptedData);
|
||||
}
|
||||
|
||||
public function decryptData($data, $key)
|
||||
{
|
||||
$decodedData = base64_decode($data);
|
||||
return openssl_decrypt($decodedData, 'AES-256-ECB', $key, OPENSSL_PKCS1_PADDING);
|
||||
}
|
||||
|
||||
public function encryptKey($key)
|
||||
{
|
||||
openssl_public_encrypt($key, $encryptedKey, $this->platformPublicKey, OPENSSL_PKCS1_PADDING);
|
||||
return base64_encode($encryptedKey);
|
||||
}
|
||||
|
||||
public function decryptKey($encryptedKey)
|
||||
{
|
||||
$decodedKey = base64_decode($encryptedKey);
|
||||
if ($decodedKey === false) {
|
||||
throw new \Exception('Base64 decoding failed.');
|
||||
}
|
||||
|
||||
$decrypted = '';
|
||||
$result = openssl_public_decrypt($decodedKey, $decrypted, $this->platformPublicKey, OPENSSL_PKCS1_PADDING);
|
||||
if ($result === false) {
|
||||
throw new \Exception('Decryption failed: ' . openssl_error_string());
|
||||
}
|
||||
|
||||
return $decrypted;
|
||||
}
|
||||
|
||||
public function generateKey()
|
||||
{
|
||||
return openssl_random_pseudo_bytes(32);
|
||||
}
|
||||
|
||||
public function prepareRequest($header, $body)
|
||||
{
|
||||
$header = [
|
||||
'version' => config('crypto.app_version'),
|
||||
'appKey' => $this->appKey,
|
||||
'method' => $header['method'] ?? '',
|
||||
'requestId' => $this->appKey.$this->generateUniqueString(30),
|
||||
];
|
||||
$bodyJson = json_encode($body);
|
||||
$signData = "version={$header['version']}&appKey={$header['appKey']}&method={$header['method']}&requestId={$header['requestId']}&body={$bodyJson}";
|
||||
|
||||
$signature = $this->sign($signData);
|
||||
|
||||
$header['sign'] = $signature;
|
||||
|
||||
$key = $this->generateKey();
|
||||
$encryptedBody = $this->encryptData($bodyJson, $key);
|
||||
$encryptedKey = $this->encryptKey($key);
|
||||
|
||||
return [
|
||||
'header' => $header,
|
||||
'encryptData' => [
|
||||
'key' => $encryptedKey,
|
||||
'data' => $encryptedBody,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function processResponse($response)
|
||||
{
|
||||
if(!isset($response['encryptData']['key'])){
|
||||
return '';
|
||||
}
|
||||
$encryptedKey = $response['encryptData']['key'];
|
||||
$encryptedData = $response['encryptData']['data'];
|
||||
$header = $response['header'];
|
||||
|
||||
$key = $this->decryptKey($encryptedKey);
|
||||
$data = $this->decryptData($encryptedData, $key);
|
||||
|
||||
$body = json_decode($data, true);
|
||||
return $body;
|
||||
// 判断响应中是否有签名
|
||||
if(empty($header['sign']??'')){
|
||||
return $body;
|
||||
}
|
||||
$header['appKey'] = $header['appkey'] ?? $header['appKey'];
|
||||
$header['requestId'] = $header['requestid'] ?? $header['requestId'];
|
||||
$signData = "version={$header['version']}&appKey={$header['appKey']}&method={$header['method']}&requestId={$header['requestId']}&body=" . json_encode($body);
|
||||
$isValid = $this->verifySign($signData, $header['sign']);
|
||||
if ($isValid) {
|
||||
return $body;
|
||||
} else {
|
||||
throw new \Exception("Invalid signature");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成唯一字符串
|
||||
*
|
||||
* @param int $length 字符串长度,不能超过128
|
||||
* @return string 生成的唯一字符串
|
||||
*/
|
||||
public function generateUniqueString($length = 100)
|
||||
{
|
||||
// 确保长度不超过100
|
||||
if ($length > 100) {
|
||||
$length = 100;
|
||||
}
|
||||
|
||||
// 生成基于时间的唯一ID
|
||||
$uniqueId = uniqid('', true);
|
||||
|
||||
// 可选字符集,可以根据需要修改
|
||||
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
$charactersLength = strlen($characters);
|
||||
$randomString = '';
|
||||
|
||||
// 使用时间戳的微秒部分增加随机性
|
||||
$microtime = microtime();
|
||||
$randomSeed = substr($microtime, strpos($microtime, ' ') + 1);
|
||||
|
||||
// 将随机种子转换为整数
|
||||
$seed = crc32($randomSeed);
|
||||
|
||||
// 设置随机种子
|
||||
srand($seed);
|
||||
|
||||
// 生成随机字符串
|
||||
for ($i = 0; $i < $length - strlen($uniqueId); $i++) {
|
||||
$randomString .= $characters[rand(0, $charactersLength - 1)];
|
||||
}
|
||||
|
||||
// 结合唯一ID和随机字符串
|
||||
$result = substr($uniqueId, 0, $length - strlen($randomString)) . $randomString;
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
// app/common/crypto/Idingju.php
|
||||
namespace app\common\crypto;
|
||||
|
||||
class Idingju
|
||||
{
|
||||
public $orgNo;
|
||||
public $appKey;
|
||||
public $prefixUrl;
|
||||
|
||||
public function __construct($company)
|
||||
{
|
||||
$this->orgNo = $company['orgNo'];
|
||||
$this->appKey = $company['appKey'];
|
||||
$this->prefixUrl = $company['url'];
|
||||
}
|
||||
|
||||
/**
|
||||
获取Token
|
||||
*/
|
||||
public function getToken($orgNo){
|
||||
$filePath = public_path().'temp/'.$orgNo.'.txt';
|
||||
$data = [];
|
||||
$accessToken = '';
|
||||
if(file_exists($filePath)){
|
||||
$content = file_get_contents($filePath);
|
||||
$data = $content ? json_decode($content,true) : [];
|
||||
}
|
||||
|
||||
if(!empty($data) && $data['expires_time'] > time()){
|
||||
$accessToken = $data['access_token'];
|
||||
}else{
|
||||
$url = $this->prefixUrl.'/api/open/getToken';
|
||||
$timestamp = time();
|
||||
$params = [
|
||||
'appid' => $this->orgNo,
|
||||
'appsecret' => $this->appKey,
|
||||
];
|
||||
$header = [
|
||||
'Content-Type: application/json',
|
||||
];
|
||||
$ret = $this->request($url,json_encode($params),'post',$header);
|
||||
$respone = json_decode($ret,true);
|
||||
if(isset($respone['code']) && $respone['code'] == 1){
|
||||
$data = json_encode($respone['data']);
|
||||
$accessToken = $respone['data']['access_token'];
|
||||
file_put_contents($filePath,$data);
|
||||
}else{
|
||||
print_r($url);
|
||||
print_r('<br/>');
|
||||
print_r($params);
|
||||
print_r('<br/>');
|
||||
print_r($respone);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
if($accessToken == ''){
|
||||
echo '获取Token失败';
|
||||
return false;
|
||||
}
|
||||
return $accessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
生成签名
|
||||
$params : 请求参数数组
|
||||
$token : access_token
|
||||
$timestamp : 时间戳
|
||||
$api : 当前请求接口除去域名的部分,如:/api/gasoline/recharge
|
||||
*/
|
||||
public function signature($params,$token,$timestamp,$api){
|
||||
$params['token'] = $token;
|
||||
sort($params, SORT_STRING);
|
||||
// $tmpStr = implode($params);
|
||||
$tmpStr = implode($params);
|
||||
|
||||
$str = $api.$token.$tmpStr.$timestamp;
|
||||
$sign = sha1($str);
|
||||
|
||||
return $sign;
|
||||
}
|
||||
|
||||
/**
|
||||
网络请求方法
|
||||
*/
|
||||
public function request($url,$params,$method,$header = [],$gzip = false,$httpcode = false){
|
||||
if(!$url) return;
|
||||
$ch = curl_init();
|
||||
if($method == 'get'){
|
||||
$paramsUrl = http_build_query($params);
|
||||
if(strpos($url,'?')){
|
||||
$url .= '&'.$paramsUrl;
|
||||
}else{
|
||||
$url .= '?'.$paramsUrl;
|
||||
}
|
||||
}else{
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
|
||||
}
|
||||
|
||||
if($header){
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER , $header);
|
||||
}
|
||||
|
||||
|
||||
if($gzip) curl_setopt($ch, CURLOPT_ENCODING, "gzip");
|
||||
|
||||
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_URL , $url);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER , 0);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST , 0);
|
||||
|
||||
$cEncode = curl_exec($ch);
|
||||
if($httpcode){
|
||||
$cEncode = [
|
||||
'cEncode'=>$cEncode,
|
||||
'httpCode'=>curl_getinfo($ch,CURLINFO_HTTP_CODE)
|
||||
];
|
||||
}
|
||||
curl_close($ch);
|
||||
|
||||
return $cEncode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,242 @@
|
||||
<?php
|
||||
// app/common/crypto/Crypto.php
|
||||
namespace app\common\crypto;
|
||||
|
||||
class RsaUtil
|
||||
{
|
||||
protected $orgNo;
|
||||
protected $appKey;
|
||||
protected $publicKey;
|
||||
protected $platformPrivateKey;
|
||||
|
||||
public function __construct($partners)
|
||||
{
|
||||
$this->orgNo = $partners['orgNo'];
|
||||
$this->appKey = $partners['appKey'];
|
||||
$this->publicKey = $this->loadPublicKey($partners['publicKey']);
|
||||
$this->platformPrivateKey = $this->loadPlatformPrivateKey();
|
||||
}
|
||||
|
||||
protected function loadPlatformPrivateKey()
|
||||
{
|
||||
$config = config('rsa');
|
||||
$privateKey = file_get_contents($config['private_key_path']);
|
||||
$key = openssl_pkey_get_private($privateKey);
|
||||
if ($key === false) {
|
||||
throw new \Exception('Invalid private key: ' . openssl_error_string());
|
||||
}
|
||||
return $key;
|
||||
}
|
||||
|
||||
protected function loadPublicKey($publicKey)
|
||||
{
|
||||
$key = openssl_pkey_get_public($publicKey);
|
||||
if ($key === false) {
|
||||
throw new \Exception('Invalid public key: ' . openssl_error_string());
|
||||
}
|
||||
return $key;
|
||||
}
|
||||
|
||||
public function sign($data)
|
||||
{
|
||||
openssl_sign($data, $signature, $this->platformPrivateKey, OPENSSL_ALGO_SHA256);
|
||||
return base64_encode($signature);
|
||||
}
|
||||
|
||||
public function verifySign($data, $signature)
|
||||
{
|
||||
$decodedSignature = base64_decode($signature);
|
||||
return openssl_verify($data, $decodedSignature, $this->publicKey, OPENSSL_ALGO_SHA256);
|
||||
}
|
||||
|
||||
public function encryptData($data, $key)
|
||||
{
|
||||
$encryptedData = openssl_encrypt($data, 'AES-256-ECB', $key, OPENSSL_PKCS1_PADDING);
|
||||
return base64_encode($encryptedData);
|
||||
}
|
||||
|
||||
public function decryptData($data, $key)
|
||||
{
|
||||
$decodedData = base64_decode($data);
|
||||
return openssl_decrypt($decodedData, 'AES-256-ECB', $key, OPENSSL_PKCS1_PADDING);
|
||||
}
|
||||
|
||||
public function encryptKey($key)
|
||||
{
|
||||
openssl_public_encrypt($key, $encryptedKey, $this->publicKey, OPENSSL_PKCS1_PADDING);
|
||||
return base64_encode($encryptedKey);
|
||||
}
|
||||
|
||||
public function decryptKey($encryptedKey)
|
||||
{
|
||||
$decodedKey = base64_decode($encryptedKey);
|
||||
if ($decodedKey === false) {
|
||||
throw new \Exception('Base64 decoding failed.');
|
||||
}
|
||||
|
||||
$decrypted = '';
|
||||
$result = openssl_private_decrypt($decodedKey, $decrypted, $this->platformPrivateKey, OPENSSL_PKCS1_PADDING);
|
||||
if ($result === false) {
|
||||
throw new \Exception('Decryption failed: ' . openssl_error_string());
|
||||
}
|
||||
|
||||
return $decrypted;
|
||||
}
|
||||
|
||||
public function generateKey()
|
||||
{
|
||||
return openssl_random_pseudo_bytes(32);
|
||||
}
|
||||
|
||||
public function prepareRequest($header, $body)
|
||||
{
|
||||
$header = [
|
||||
'version' => config('rsa.app_version'),
|
||||
'appKey' => $this->appKey,
|
||||
'method' => $header['method'] ?? '',
|
||||
'requestId' => $this->appKey.$this->generateUniqueString(30),
|
||||
];
|
||||
$bodyJson = json_encode($body);
|
||||
$signData = "version={$header['version']}&appKey={$header['appKey']}&method={$header['method']}&requestId={$header['requestId']}&body={$bodyJson}";
|
||||
|
||||
$signature = $this->sign($signData);
|
||||
|
||||
$header['sign'] = $signature;
|
||||
|
||||
$key = $this->generateKey();
|
||||
$encryptedBody = $this->encryptData($bodyJson, $key);
|
||||
$encryptedKey = $this->encryptKey($key);
|
||||
|
||||
return [
|
||||
'header' => $header,
|
||||
'encryptData' => [
|
||||
'key' => $encryptedKey,
|
||||
'data' => $encryptedBody,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function processResponse(array $response, bool $checkSign = true): array
|
||||
{
|
||||
// 1. 检查加密数据是否存在
|
||||
if (empty($response['encryptData']['key'] ?? '') || empty($response['encryptData']['data'] ?? '')) {
|
||||
return [
|
||||
'code' => '04',
|
||||
'errCode' => '0002',
|
||||
];
|
||||
}
|
||||
|
||||
try {
|
||||
// 2. 解密密钥和数据
|
||||
$encryptedKey = $response['encryptData']['key'];
|
||||
$encryptedData = $response['encryptData']['data'];
|
||||
|
||||
$key = $this->decryptKey($encryptedKey);
|
||||
$data = $this->decryptData($encryptedData, $key);
|
||||
$body = json_decode($data, true);
|
||||
|
||||
if ($body === null) {
|
||||
return [
|
||||
'code' => '03',
|
||||
'errCode' => '0011',
|
||||
];
|
||||
}
|
||||
|
||||
// 3. 验签(可选)
|
||||
if ($checkSign) {
|
||||
$header = $response['header'] ?? [];
|
||||
// 请求头version参数不正确
|
||||
if(empty($header['version'] ?? '') || $header['version'] != '1.0.0'){
|
||||
return [
|
||||
'code' => '12',
|
||||
'errCode' => '0003',
|
||||
];
|
||||
}
|
||||
// 请求头APPKEY参数不正确
|
||||
if(empty($header['appkey'] ?? $header['appKey'])){
|
||||
return [
|
||||
'code' => '02',
|
||||
'errCode' => '0004',
|
||||
];
|
||||
}
|
||||
// 请求参数不正确
|
||||
if(empty($header['method'] ?? '') || empty($header['requestid'] ?? $header['requestId'])){
|
||||
return [
|
||||
'code' => '12',
|
||||
'errCode' => '0013',
|
||||
];
|
||||
}
|
||||
$signData = http_build_query([
|
||||
'version' => $header['version'],
|
||||
'appKey' => $header['appkey'] ?? $header['appKey'],
|
||||
'method' => $header['method'],
|
||||
'requestId' => $header['requestid'] ?? $header['requestId'],
|
||||
'body' => json_encode($body, JSON_UNESCAPED_UNICODE)
|
||||
]);
|
||||
|
||||
if (empty($header['sign']) || !$this->verifySign($signData, $header['sign'])) {
|
||||
return [
|
||||
'code' => '05',
|
||||
'errCode' => '0006',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 成功返回
|
||||
return [
|
||||
'code' => '00',
|
||||
'data' => $body
|
||||
];
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
return [
|
||||
'code' => '99',
|
||||
'errCode' => '0007',
|
||||
'errMessage' => $e->getMessage() ?: '',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成唯一字符串
|
||||
*
|
||||
* @param int $length 字符串长度,不能超过128
|
||||
* @return string 生成的唯一字符串
|
||||
*/
|
||||
public function generateUniqueString($length = 100)
|
||||
{
|
||||
// 确保长度不超过100
|
||||
if ($length > 100) {
|
||||
$length = 100;
|
||||
}
|
||||
|
||||
// 生成基于时间的唯一ID
|
||||
$uniqueId = uniqid('', true);
|
||||
|
||||
// 可选字符集,可以根据需要修改
|
||||
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
$charactersLength = strlen($characters);
|
||||
$randomString = '';
|
||||
|
||||
// 使用时间戳的微秒部分增加随机性
|
||||
$microtime = microtime();
|
||||
$randomSeed = substr($microtime, strpos($microtime, ' ') + 1);
|
||||
|
||||
// 将随机种子转换为整数
|
||||
$seed = crc32($randomSeed);
|
||||
|
||||
// 设置随机种子
|
||||
srand($seed);
|
||||
|
||||
// 生成随机字符串
|
||||
for ($i = 0; $i < $length - strlen($uniqueId); $i++) {
|
||||
$randomString .= $characters[rand(0, $charactersLength - 1)];
|
||||
}
|
||||
|
||||
// 结合唯一ID和随机字符串
|
||||
$result = substr($uniqueId, 0, $length - strlen($randomString)) . $randomString;
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user