accessMid = $accessMid; $this->privateKeyPwd = $privateKeyPwd; if(file_exists(PLUGIN_ROOT.'sandpay/cert/'.$accessMid.'.pfx')){ $this->privateKeyPath = PLUGIN_ROOT.'sandpay/cert/'.$accessMid.'.pfx'; } if($isTest == 1){ $this->apiUrl = 'https://openapi-uat01.sand.com.cn'; } $this->publicKey = $this->getPublicKey(); $this->privateKey = $this->getPrivateKey(); } //执行请求 public function execute($path, $params){ $aesKey = random(16); ksort($params); $data = json_encode($params, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); $this->request_body = $data; $bizData = $this->aesEncrypt($data, $aesKey); $encryptKey = $this->rsaPublicEncrypt($aesKey); $publicParams = [ 'accessMid' => $this->accessMid, 'timestamp' => date('Y-m-d H:i:s'), 'version' => $this->version, 'signType' => $this->signType, 'encryptType' => $this->encryptType, 'encryptKey' => $encryptKey, 'bizData' => $bizData, ]; $publicParams['sign'] = $this->rsaPrivateSign($publicParams['bizData']); $json = json_encode($publicParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); $response = get_curl($this->apiUrl.$path, $json, 0, 0, 0, 0, 0, ['Content-Type: application/json; charset=utf-8']); $result = json_decode($response, true); if($result['respCode']=='success'){ if(!$this->rsaPubilcVerify($result['bizData'], $result['sign'])){ throw new \Exception('返回数据验签失败'); } $decryptAesKey = $this->rsaPrivateDecrypt($result['encryptKey']); if(!$decryptAesKey){ throw new \Exception('AES密钥解密失败'); } $decryptPlainText = $this->aesDecrypt($result['bizData'], $decryptAesKey); if(!$decryptPlainText){ throw new \Exception('AES解密失败'); } $this->response_body = $decryptPlainText; $arr = json_decode($decryptPlainText, true); if(!$arr){ throw new \Exception('bizData解析失败'); } if($arr['resultStatus'] == 'fail'){ throw new \Exception('['.$arr['errorCode'].']'.$arr['errorDesc']); } return $arr; }elseif($result['respCode']=='fail'){ throw new \Exception($result['respDesc']); }else{ throw new \Exception('返回数据解析失败'); } } public function verify($data, $sign){ if(empty($sign)) return false; return $this->rsaPubilcVerify($data, $sign); } //AES加密 private function aesEncrypt($data, $key){ return openssl_encrypt($data, 'AES-128-ECB', $key); } //AES解密 private function aesDecrypt($data, $key){ return openssl_decrypt($data, 'AES-128-ECB', $key); } //杉德公钥 private function getPublicKey() { $file = file_get_contents($this->publicKeyPath); $cert = chunk_split(base64_encode($file), 64, "\n"); $cert = "-----BEGIN CERTIFICATE-----\n" . $cert . "-----END CERTIFICATE-----\n"; $res = openssl_pkey_get_public($cert); if (!$res) { throw new \Exception('从杉德公钥证书获取公钥失败'); } return $res; } //商户私钥 private function getPrivateKey() { $file = file_get_contents($this->privateKeyPath); if (!openssl_pkcs12_read($file, $cert, $this->privateKeyPwd)) { throw new \Exception('商户私钥证书解析失败'); } return openssl_pkey_get_private($cert['pkey']); } //私钥加签 private function rsaPrivateSign($data) { $result = openssl_sign($data, $sign, $this->privateKey, OPENSSL_ALGO_SHA256); if (!$result) throw new \Exception('sign error'); return base64_encode($sign); } //公钥验签 public function rsaPubilcVerify($data, $sign) { $result = openssl_verify($data, base64_decode($sign), $this->publicKey, OPENSSL_ALGO_SHA256); return $result === 1; } //公钥加密 public function rsaPublicEncrypt($data) { $encrypted = ''; openssl_public_encrypt($data, $encrypted, $this->publicKey, OPENSSL_PKCS1_PADDING); return base64_encode($encrypted); } //私钥解密 public function rsaPrivateDecrypt($data) { $decrypted = ''; openssl_private_decrypt(base64_decode($data), $decrypted, $this->privateKey, OPENSSL_PKCS1_PADDING); return $decrypted; } }