$appKey, "appSecret" => $appSecret ]; $tokenResp = $this->curlOpen('https://api.dingtalk.com/v1.0/oauth2/accessToken',[ 'post' => true, 'request' => 'post', 'isupfile' => false, 'header' => ['Content-Type: application/json'], 'post' => json_encode($postData) ]); $tokenResp = json_decode($tokenResp,true); if (empty($tokenResp['accessToken'])) return [false, '获取 access_token 失败']; $accessToken = $tokenResp['accessToken']; // Step2: 用 code 获取用户信息 $userInfoResp = $this->curlOpen('https://oapi.dingtalk.com/topapi/v2/user/getuserinfo', [ 'post' => true, 'request' => 'post', 'isupfile' => false, 'header' => ["x-acs-dingtalk-access-token: {$accessToken}", "Content-Type: application/json"], 'post' => json_encode(['code' => $code]) ]); $userInfoResp = json_decode($userInfoResp, true);dd($userInfoResp); $userId = $userInfoResp['result']['userId'] ?? null; if (!$userId) return ['error' => '获取用户信息失败或 code 已过期']; // 获取用户信息 $userInfoUrl = "https://oapi.dingtalk.com/topapi/v2/user/getuserinfo?access_token={$accessToken}"; $postData = [ 'code' => $code ]; $tokenResp = $this->curlOpen($userInfoUrl,[ 'post' => true, 'request' => 'post', 'isupfile' => false, 'header' => ['Content-Type: application/json'], 'post' => json_encode($postData) ]); $tokenResp = json_decode($tokenResp,true); dd($tokenResp,$userInfoUrl,$postData); // Step 2: 用 code 换取用户信息 $url = "https://oapi.dingtalk.com/user/getuserinfo?access_token={$accessToken}&code={$code}"; $tokenResp = $this->curlOpen($url); dd($tokenResp,$url); if (isset($userResp['errcode']) && $userResp['errcode'] != 0) { return response()->json(['error' => '获取用户失败', 'detail' => $userResp], 500); } // userResp 里有 userid $dingUserId = $userResp['userid']; // Step 3: 你自己系统里维护映射关系 (假设表 user_bindings 记录了 dingtalk_userid ↔ u8_username) $u8User = \DB::table('user_bindings')->where('dingtalk_userid', $dingUserId)->first(); if (!$u8User) { return response()->json(['error' => '该钉钉账号未绑定 U8 用户'], 403); } // Step 4: 返回登录成功信息 return response()->json([ 'dingUserId' => $dingUserId, 'u8User' => $u8User->u8_username, 'message' => '登录成功' ]); } public function getAccessToken() { $token = Redis::get(self::RedisKey); if(! empty($token)) return [true, ['access_token' => $token]]; $appKey = config('dingtalk.app_key'); $appSecret = config('dingtalk.app_secret'); $url = "https://api.dingtalk.com/v1.0/oauth2/accessToken"; $resp = $this->curlOpen1($url, [ 'request' => 'post', 'header' => ['Content-Type: application/json'], 'json' => [ "appKey" => $appKey, "appSecret" => $appSecret ] ]); $res = json_decode($resp, true); $accessToken = $res['accessToken'] ?? ""; $expires_in = $res['expires_in'] ?? 0; if(empty($accessToken)) return [false, 'AccessToken获取失败']; Redis::setex(self::RedisKey, $expires_in, $accessToken); return [true, ['access_token' => $accessToken]]; } /** * 根据前端传来的免登 code 获取用户信息 * @param string $code 前端 dd.getAuthCode 获取的 code * @return array [bool, data] bool 表示成功与否,data 成功返回用户信息,失败返回错误信息 */ public function getUserByCode(string $code) { if (empty($code)) { return [false, 'code不能为空']; } // 1. 获取 access_token [$success, $tokenData] = $this->getAccessToken(); if (!$success) return [false, $tokenData]; // tokenData 是错误信息 $accessToken = $tokenData['access_token']; // 2. 用 code 换取 userid $url = "https://api.dingtalk.com/v1.0/user/getuserinfo"; $resp = $this->curlOpen1($url, [ 'request' => 'post', 'header' => [ "Content-Type: application/json", "x-acs-dingtalk-access-token: {$accessToken}" ], 'json' => [ "code" => $code ] ]); $res = json_decode($resp, true); $userid = $res['result']['userid'] ?? null; if (!$userid) { return [false, '获取userid失败:' . $res['errmsg']]; } return [true, $res]; // // 3. 根据 userid 获取用户详情 // $urlDetail = "https://api.dingtalk.com/v1.0/user/get"; // $respDetail = $this->curlOpen1($urlDetail, [ // 'request' => 'post', // 'header' => [ // "Content-Type: application/json", // "x-acs-dingtalk-access-token: {$accessToken}" // ], // 'json' => [ // "userid" => $userid // ] // ]); // // $detail = json_decode($respDetail, true); // if (empty($detail['result'])) { // return [false, '获取用户详情失败:' . ($detail['msg'] ?? json_encode($detail))]; // } // 返回用户信息 // return [true, $detail['result']]; } protected function curlOpen1($url, $config = []) { $default = [ 'post' => false, 'request' => 'get', 'header' => [], 'json' => null, 'timeout' => 30 ]; $arr = array_merge($default, $config); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, $arr['timeout']); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); if (!empty($arr['header'])) { curl_setopt($ch, CURLOPT_HTTPHEADER, $arr['header']); } if ($arr['post'] || $arr['request'] !== 'get') { curl_setopt($ch, CURLOPT_CUSTOMREQUEST, strtoupper($arr['request'])); if ($arr['json'] !== null) { curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($arr['json'], JSON_UNESCAPED_UNICODE)); } } $result = curl_exec($ch); if ($result === false) { $err = curl_error($ch); curl_close($ch); return json_encode(['error' => $err]); } curl_close($ch); return $result; } }