sys_id = $config['sys_id']; $this->product_id = $config['product_id']; $this->merchant_private_key = $this->loadPrivateKey($config['merchant_private_key']); $this->huifu_public_key = $this->loadPublicKey($config['huifu_public_key']); } /** * 请求API接口并解析返回数据 */ public function requestApi($path, $data) { $url = self::BASE_API_URL . $path; $body = [ 'sys_id' => $this->sys_id, 'product_id' => $this->product_id, 'data' => $data ]; $body['sign'] = $this->makeSign($data); $response = $this->curlPost($url, $body); $result = json_decode($response, true); if (!$result || empty($result['data']) || empty($result['sign'])) { throw new \Exception("接口返回数据解析失败"); } //print_r($result); if (!$this->checkResponseSign($result['data'], $result['sign'])) { throw new \Exception("接口返回数据验签失败"); } return $result['data']; } /** * 上传文件 */ public function upload($path, $data, $file_path, $file_name) { $url = self::BASE_API_URL . $path; $body = [ 'sys_id' => $this->sys_id, 'product_id' => $this->product_id, 'data' => $data ]; $file = new \CURLFile($file_path, '', $file_name); $body['sign'] = $this->makeSign($data); $response = $this->curlPost($url, $body, $file); $result = json_decode($response, true); if (!$result || empty($result['data'])) { throw new \Exception("接口返回数据解析失败"); } return $result['data']; } /** * 发起POST请求 * @param string $url 请求URL * @param array $body POST数据 * @param \CURLFile $file 上传文件 * @return string */ private function curlPost($url, $body, $file = null) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_TIMEOUT, 10); curl_setopt($ch, CURLOPT_FAILONERROR, false); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_POST, true); if ($file) { $body['data'] = json_encode($body['data'], JSON_UNESCAPED_UNICODE); $body['file'] = $file; curl_setopt($ch, CURLOPT_POSTFIELDS, $body); } else { curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json; charset=utf-8']); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body)); } $response = curl_exec($ch); if (curl_errno($ch) > 0) { $errmsg = curl_error($ch); curl_close($ch); throw new \Exception($errmsg, 0); } $httpStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); if ($httpStatusCode != 200) { curl_close($ch); throw new \Exception($response ? $response : 'http_code=' . $httpStatusCode, $httpStatusCode); } curl_close($ch); return $response; } /** * 生成请求签名 * @param array $params * @return string */ private function makeSign($params) { $params = array_filter($params, function ($value) { return $value !== null; }); ksort($params); $content = json_encode($params, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); return $this->rsaPrivateSign($content); } /** * 校验通知数据签名 * @param string $data * @param string $sign * @return bool */ public function checkNotifySign($data, $sign) { if (empty($sign)) return false; return $this->rsaPublicVerify($data, $sign); } /** * 校验返回数据签名 * @param array $params * @param string $sign * @return bool */ private function checkResponseSign($params, $sign) { if (empty($sign)) return false; ksort($params); $content = json_encode($params, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); return $this->rsaPublicVerify($content, $sign); } /** * 商户私钥签名 * @param string $data 待签名字符串 * @return string */ private function rsaPrivateSign($data) { openssl_sign($data, $signature, $this->merchant_private_key, OPENSSL_ALGO_SHA256); return base64_encode($signature); } /** * 平台公钥验签 * @param string $data 待验签字符串 * @return bool */ private function rsaPublicVerify($data, $signature) { $result = openssl_verify($data, base64_decode($signature), $this->huifu_public_key, OPENSSL_ALGO_SHA256); return $result === 1; } /** * 平台公钥加密 * @param string $data 待加密字符串 * @return string */ private function rsaPublicEncrypt($data) { openssl_public_encrypt($data, $encryptResult, $this->huifu_public_key, OPENSSL_PKCS1_PADDING); return base64_encode($encryptResult); } /** * 加载汇付公钥 */ private function loadPublicKey($public_key) { $res = "-----BEGIN PUBLIC KEY-----\n" . wordwrap($public_key, 64, "\n", true) . "\n-----END PUBLIC KEY-----"; $pubkeyid = openssl_get_publickey($res); if (!$pubkeyid) { throw new Exception('汇付公钥不正确'); } return $pubkeyid; } /** * 加载商户私钥 */ private function loadPrivateKey($private_key) { $res = "-----BEGIN PRIVATE KEY-----\n" . wordwrap($private_key, 64, "\n", true) . "\n-----END PRIVATE KEY-----"; $prikeyid = openssl_get_privatekey($res); if (!$prikeyid) { throw new Exception('商户私钥不正确'); } return $prikeyid; } }