corpId = (string)($config['corp_id'] ?? ''); $this->secret = (string)($config['external_pay_secret'] ?? $config['secret'] ?? ''); } /** * 获取 access_token(对外收款应用) */ public function getAccessToken(): ?string { if (empty($this->corpId) || empty($this->secret)) { Log::error('企业微信对外收款:corp_id 或 external_pay_secret 未配置'); return null; } $cacheKey = 'work_wechat_external_pay_token_' . md5($this->corpId . $this->secret); $cached = Cache::get($cacheKey); if ($cached) { return $cached; } $url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={$this->corpId}&corpsecret={$this->secret}"; $response = $this->httpGet($url); if (!$response || ($response['errcode'] ?? -1) != 0) { Log::error('企业微信对外收款获取access_token失败: ' . json_encode($response)); return null; } $accessToken = $response['access_token']; Cache::set($cacheKey, $accessToken, ($response['expires_in'] ?? 7200) - 200); return $accessToken; } /** * 获取对外收款记录 * @param int $beginTime 开始时间戳(秒) * @param int $endTime 结束时间戳(秒) * @param string $payeeUserid 收款人userid,空则查全部 * @param string $cursor 分页游标 * @param int $limit 最大记录数,最大1000 * @return array */ public function getBillList(int $beginTime, int $endTime, string $payeeUserid = '', string $cursor = '', int $limit = 100): array { $accessToken = $this->getAccessToken(); if (!$accessToken) { return ['errcode' => -1, 'errmsg' => '获取access_token失败', 'bill_list' => []]; } $url = "https://qyapi.weixin.qq.com/cgi-bin/externalpay/get_bill_list?access_token={$accessToken}"; $data = [ 'begin_time' => $beginTime, 'end_time' => $endTime, 'limit' => $limit, ]; if ($payeeUserid) { $data['payee_userid'] = $payeeUserid; } if ($cursor) { $data['cursor'] = $cursor; } $response = $this->httpPost($url, $data); if (!$response) { return ['errcode' => -1, 'errmsg' => '请求失败', 'bill_list' => []]; } $billList = $response['bill_list'] ?? []; return [ 'errcode' => $response['errcode'] ?? 0, 'errmsg' => $response['errmsg'] ?? '', 'bill_list' => is_array($billList) ? $billList : [], 'next_cursor' => $response['next_cursor'] ?? '', ]; } private function httpGet(string $url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_TIMEOUT, 10); $result = curl_exec($ch); curl_close($ch); return $result ? json_decode($result, true) : null; } private function httpPost(string $url, array $data) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']); curl_setopt($ch, CURLOPT_TIMEOUT, 10); $result = curl_exec($ch); curl_close($ch); return $result ? json_decode($result, true) : null; } }