$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($data) { $code = $data['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 换取用户信息(v2 接口) $url = "https://oapi.dingtalk.com/topapi/v2/user/getuserinfo?access_token={$accessToken}"; $resp = $this->curlOpen1($url, [ 'request' => 'post', 'header' => [ "Content-Type: application/json", ], 'json' => [ "code" => $code ] ]); $res = json_decode($resp, true); if (!isset($res['errcode'])) { return [false, '接口返回异常: ' . $resp]; } if ($res['errcode'] !== 0) { return [false, '获取用户信息失败: ' . $res['errmsg']]; } return [true, $res]; } private function getManDetail($user){ // 1. 获取 access_token [$success, $tokenData] = $this->getAccessToken(); if (! $success) return [false, $tokenData]; // tokenData 是错误信息 $accessToken = $tokenData['access_token']; // 3. 根据 userid 获取详细用户信息(包括部门) $urlDetail = "https://oapi.dingtalk.com/topapi/v2/user/get?access_token={$accessToken}"; $respDetail = $this->curlOpen1($urlDetail, [ 'request' => 'post', 'header' => ["Content-Type: application/json"], 'json' => ["userid" => $user['userId']] ]); $detail = json_decode($respDetail, true); if (!isset($detail['errcode'])) return [false, '获取用户详情接口异常: ' . $respDetail]; if ($detail['errcode'] !== 0) return [false, '获取用户详情失败: ' . $detail['errmsg']]; if (empty($detail['result'])) return [false, '获取用户详情失败,结果为空']; // 返回完整用户信息 return [true, $detail['result']]; } public function createProcessInstance($data, $user) { if(empty($data['type'])) return [false, '单据类型不能为空']; $type = $data['type']; $userId = $user['userId']; [$success, $userDetail] = $this->getManDetail($user); if(!$success) return [false, $userDetail]; // 1. 获取 access_token [$success, $tokenData] = $this->getAccessToken(); if (!$success) return [false, $tokenData]; $accessToken = $tokenData['access_token']; //获取模板id $code = $this->getModelCode($type); //获取模板数据 $formData = $this->getFormData($data); //创建审批 [$success, $msg] = $this->createFlow($accessToken, $code, $userId, $userDetail, $formData); if(! $success) return [false, $msg]; //记录信息 return [true, '']; } private function createFlow($accessToken, $code, $userId, $userDetail, $formData){ // 2. 请求 URL $url = "https://oapi.dingtalk.com/topapi/processinstance/create?access_token={$accessToken}"; // 3. 请求体 $payload = [ "process_code" => $code, // 审批模板编码 "originator_user_id" => $userId, // 发起人 userId "dept_id" => $userDetail['dept_id_list'], // 发起人部门 ID "form_component_values" => $formData, // 表单数据 ]; // 4. 发送请求 $resp = $this->curlOpen1($url, [ 'request' => 'post', 'header' => [ "Content-Type: application/json", ], 'json' => $payload ]); $res = json_decode($resp, true); if (!isset($res['errcode'])) { return [false, "接口返回异常: " . $resp]; } if ($res['errcode'] !== 0) { return [false, "创建审批实例失败: " . $res['errmsg']]; } return [true, $res['process_instance_id']]; } private function getModelCode($type){ if($type == 1){ // 采购单 $code = "PROC-61E1D916-C7BE-4DE2-9D25-63505D8573B1"; }elseif ($type == 2){ // 请购单 $code = "PROC-4FECC44D-993C-48E3-8623-CDC75B467622"; }else{ // 付款单 $code = "PROC-F6D0C212-D8C6-4662-9AFD-EA9DE85A1F14"; } return $code; } private function getFormData($data){ $model = []; $formData = [ [ "name" => "订单日期", "value" => "2025-09-23" // 日期型字段,字符串 yyyy-MM-dd ], [ "name" => "订单编号", "value" => "PO20250923001" ], [ "name" => "业务类型", "value" => "标准采购" ], [ "name" => "供应商", "value" => "XX供应商有限公司" ], [ "name" => "制单人", "value" => "陈庆鹏" ], [ "name" => "表格", "value" => json_encode([ [ [ "name" => "存货名称", "value" => "打印机" ], [ "name" => "数量", "value" => "2" ], [ "name" => "主计量单位", "value" => "台" ], [ "name" => "原币价税合计", "value" => "3000" ] ], [ [ "name" => "存货名称", "value" => "显示器" ], [ "name" => "数量", "value" => "5" ], [ "name" => "主计量单位", "value" => "个" ], [ "name" => "原币价税合计", "value" => "5000" ] ] ], JSON_UNESCAPED_UNICODE) // 表格必须是字符串化的 JSON 数组 ] ]; return $model; } private function recordDatabase($data, $user, $process_instance_id){ } public function getTemplateFields($data) { $processCode = $data['code'] ?? ""; if (empty($processCode)) { return [false, '模板编号 process_code 不能为空']; } [$ok, $tokenData] = $this->getAccessToken(); if (! $ok) return [false, $tokenData]; $accessToken = $tokenData['access_token']; // 注意这里是 GET,并且 processCode 是 query 参数 $url = "https://api.dingtalk.com/v1.0/workflow/forms/schemas/processCodes?processCode={$processCode}"; $resp = $this->curlOpen1($url, [ 'request' => 'get', 'header' => [ "Content-Type: application/json", "x-acs-dingtalk-access-token: {$accessToken}" ], ]); $res = json_decode($resp, true); if (isset($res['schemas'])) { return [true, $res['schemas']]; } else { return [false, $res]; } } 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; } }