| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 | <?phpnamespace App\Service;use Illuminate\Support\Facades\Redis;class DrbService extends Service{    const RedisKey = 'DRBACCESSTOKENKEY';    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($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 = "";        }elseif ($type == 2){            $code = "";        }else{            $code = "";        }        return $code;    }    private function getFormData($data){        $model = [];        return $model;    }    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;    }}
 |