request('POST', $url, [ 'headers' => $headers, 'json' => $data, ]); } catch (YiDongException $e) { throw $e; } } protected function request(string $method, string $url, array $options = []): array { $data = []; if (array_key_exists('json', $options)) { $data = $options['json']; } $headers = array_merge([ 'Content-Type' => 'application/json', 'appid' => $this->appid, 'md5' => md5($data ? json_encode($data) : "{}"), 'timestamp' => (string) now()->getTimestampMs(), 'version' => static::ENDPOINT_VERSION, ], $options['headers'] ?? []); if (Str::start($url, '/') === '/v3/open/api/token') { unset($headers['token']); } else { $headers['token'] = isset($headers['token']) ? $headers['token'] : $this->token(); } ksort($headers); $headers['signature'] = $this->sign(json_encode( Arr::only($headers, ['appid', 'md5', 'timestamp', 'token', 'version']) )); $options['headers'] = $headers; /** @var \Illuminate\Http\Client\Response */ $response = Http::baseUrl(static::ENDPOINT_URL)->send($method, $url, $options); $result = $response->throw()->json(); $resultCode = data_get($result, 'resultCode', '-1'); if ($resultCode === '000000') { return $result; } throw new QlyException( data_get($result, 'resultMsg', '请求失败').', 错误码: '.$resultCode, ); } protected function token(bool $refresh = false): string { $key = "ydqly_tokens:{$this->appid}"; if (! $refresh && $this->token ??= Cache::get($key)) { return $this->token; } $result = $this->post( '/v3/open/api/token', array_merge([ 'sig' => md5($this->appid.$this->secret), 'operatorType' => 1, ]), ); $this->token = data_get($result, 'data.token'); $ttl = (int) data_get($result, 'data.expires_in', 0) - 120; if ($ttl > 0) { Cache::put($key, $this->token, $ttl); } return $this->token; } /** * 生成签名 */ protected function sign(string $message): string { // rsa 私钥 $pem = "-----BEGIN PRIVATE KEY-----\n" . wordwrap($this->rsa, 64, "\n", true) . "\n-----END PRIVATE KEY-----"; openssl_sign($message, $signature, $pem); return base64_encode($signature); } }