DrbService.php 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. <?php
  2. namespace App\Service;
  3. use Illuminate\Support\Facades\Redis;
  4. class DrbService extends Service
  5. {
  6. const RedisKey = 'DRBACCESSTOKENKEY';
  7. public function getAccessToken()
  8. {
  9. $token = Redis::get(self::RedisKey);
  10. if(! empty($token)) return [true, ['access_token' => $token]];
  11. $appKey = config('dingtalk.app_key');
  12. $appSecret = config('dingtalk.app_secret');
  13. $url = "https://api.dingtalk.com/v1.0/oauth2/accessToken";
  14. $resp = $this->curlOpen1($url, [
  15. 'request' => 'post',
  16. 'header' => ['Content-Type: application/json'],
  17. 'json' => [
  18. "appKey" => $appKey,
  19. "appSecret" => $appSecret
  20. ]
  21. ]);
  22. $res = json_decode($resp, true);
  23. $accessToken = $res['accessToken'] ?? "";
  24. $expires_in = $res['expires_in'] ?? 0;
  25. if(empty($accessToken)) return [false, 'AccessToken获取失败'];
  26. Redis::setex(self::RedisKey, $expires_in, $accessToken);
  27. return [true, ['access_token' => $accessToken]];
  28. }
  29. /**
  30. * 根据前端传来的免登 code 获取用户信息
  31. * @param string $code 前端 dd.getAuthCode 获取的 code
  32. * @return array [bool, data] bool 表示成功与否,data 成功返回用户信息,失败返回错误信息
  33. */
  34. public function getUserByCode($data)
  35. {
  36. $code = $data['code'] ?? "";
  37. if (empty($code)) return [false, '钉钉授权code不能为空'];
  38. // 1. 获取 access_token
  39. [$success, $tokenData] = $this->getAccessToken();
  40. if (! $success) return [false, $tokenData]; // tokenData 是错误信息
  41. $accessToken = $tokenData['access_token'];
  42. // 2. 用 code 换取用户信息(v2 接口)
  43. $url = "https://oapi.dingtalk.com/topapi/v2/user/getuserinfo?access_token={$accessToken}";
  44. $resp = $this->curlOpen1($url, [
  45. 'request' => 'post',
  46. 'header' => [
  47. "Content-Type: application/json",
  48. ],
  49. 'json' => [
  50. "code" => $code
  51. ]
  52. ]);
  53. $res = json_decode($resp, true);
  54. if (!isset($res['errcode'])) {
  55. return [false, '接口返回异常: ' . $resp];
  56. }
  57. if ($res['errcode'] !== 0) {
  58. return [false, '获取用户信息失败: ' . $res['errmsg']];
  59. }
  60. return [true, $res];
  61. }
  62. private function getManDetail($user){
  63. // 1. 获取 access_token
  64. [$success, $tokenData] = $this->getAccessToken();
  65. if (! $success) return [false, $tokenData]; // tokenData 是错误信息
  66. $accessToken = $tokenData['access_token'];
  67. // 3. 根据 userid 获取详细用户信息(包括部门)
  68. $urlDetail = "https://oapi.dingtalk.com/topapi/v2/user/get?access_token={$accessToken}";
  69. $respDetail = $this->curlOpen1($urlDetail, [
  70. 'request' => 'post',
  71. 'header' => ["Content-Type: application/json"],
  72. 'json' => ["userid" => $user['userId']]
  73. ]);
  74. $detail = json_decode($respDetail, true);
  75. if (!isset($detail['errcode'])) return [false, '获取用户详情接口异常: ' . $respDetail];
  76. if ($detail['errcode'] !== 0) return [false, '获取用户详情失败: ' . $detail['errmsg']];
  77. if (empty($detail['result'])) return [false, '获取用户详情失败,结果为空'];
  78. // 返回完整用户信息
  79. return [true, $detail['result']];
  80. }
  81. public function createProcessInstance($data, $user)
  82. {
  83. if(empty($data['type'])) return [false, '单据类型不能为空'];
  84. $type = $data['type'];
  85. $userId = $user['userId'];
  86. [$success, $userDetail] = $this->getManDetail($user);
  87. if(!$success) return [false, $userDetail];
  88. // 1. 获取 access_token
  89. [$success, $tokenData] = $this->getAccessToken();
  90. if (!$success) return [false, $tokenData];
  91. $accessToken = $tokenData['access_token'];
  92. //获取模板id
  93. $code = $this->getModelCode($type);
  94. //获取模板数据
  95. $formData = $this->getFormData($data);
  96. //创建审批
  97. [$success, $msg] = $this->createFlow($accessToken, $code, $userId, $userDetail, $formData);
  98. if(! $success) return [false, $msg];
  99. return [true, ''];
  100. }
  101. private function createFlow($accessToken, $code, $userId, $userDetail, $formData){
  102. // 2. 请求 URL
  103. $url = "https://oapi.dingtalk.com/topapi/processinstance/create?access_token={$accessToken}";
  104. // 3. 请求体
  105. $payload = [
  106. "process_code" => $code, // 审批模板编码
  107. "originator_user_id" => $userId, // 发起人 userId
  108. "dept_id" => $userDetail['dept_id_list'], // 发起人部门 ID
  109. "form_component_values" => $formData, // 表单数据
  110. ];
  111. // 4. 发送请求
  112. $resp = $this->curlOpen1($url, [
  113. 'request' => 'post',
  114. 'header' => [
  115. "Content-Type: application/json",
  116. ],
  117. 'json' => $payload
  118. ]);
  119. $res = json_decode($resp, true);
  120. if (!isset($res['errcode'])) {
  121. return [false, "接口返回异常: " . $resp];
  122. }
  123. if ($res['errcode'] !== 0) {
  124. return [false, "创建审批实例失败: " . $res['errmsg']];
  125. }
  126. return [true, $res['process_instance_id']];
  127. }
  128. private function getModelCode($type){
  129. if($type == 1){
  130. $code = "";
  131. }elseif ($type == 2){
  132. $code = "";
  133. }else{
  134. $code = "";
  135. }
  136. return $code;
  137. }
  138. private function getFormData($data){
  139. $model = [];
  140. return $model;
  141. }
  142. protected function curlOpen1($url, $config = [])
  143. {
  144. $default = [
  145. 'post' => false,
  146. 'request' => 'get',
  147. 'header' => [],
  148. 'json' => null,
  149. 'timeout' => 30
  150. ];
  151. $arr = array_merge($default, $config);
  152. $ch = curl_init();
  153. curl_setopt($ch, CURLOPT_URL, $url);
  154. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  155. curl_setopt($ch, CURLOPT_TIMEOUT, $arr['timeout']);
  156. curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
  157. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  158. if (!empty($arr['header'])) {
  159. curl_setopt($ch, CURLOPT_HTTPHEADER, $arr['header']);
  160. }
  161. if ($arr['post'] || $arr['request'] !== 'get') {
  162. curl_setopt($ch, CURLOPT_CUSTOMREQUEST, strtoupper($arr['request']));
  163. if ($arr['json'] !== null) {
  164. curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($arr['json'], JSON_UNESCAPED_UNICODE));
  165. }
  166. }
  167. $result = curl_exec($ch);
  168. if ($result === false) {
  169. $err = curl_error($ch);
  170. curl_close($ch);
  171. return json_encode(['error' => $err]);
  172. }
  173. curl_close($ch);
  174. return $result;
  175. }
  176. }