accessToken(); if ($token === null) { return null; } $response = Http::withHeaders(['x-acs-dingtalk-access-token' => $token]) ->timeout(20) ->post(self::GRANT_DOWNLOAD_URL, [ 'processInstanceId' => $processInstanceId, 'fileId' => $fileId, ]); if (! $response->successful()) { report(new \RuntimeException( 'dingtalk approval attachment grant failed: HTTP ' . $response->status() )); return null; } $uri = (string) $response->json('result.downloadUri'); return $uri !== '' ? $uri : null; } private function accessToken(): ?string { $clientId = (string) config('dingtalk.client_id'); $secret = (string) config('dingtalk.client_secret'); if ($clientId === '' || $secret === '') { return null; } $token = Cache::remember(self::TOKEN_CACHE_KEY, now()->addMinutes(100), function () use ($clientId, $secret): ?string { $response = Http::timeout(15)->get(self::GET_TOKEN_URL, [ 'appkey' => $clientId, 'appsecret' => $secret, ]); $token = (string) $response->json('access_token'); return $token !== '' ? $token : null; }); return is_string($token) && $token !== '' ? $token : null; } }