BaseController.Class.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. <?php
  2. namespace JinDouYun\Controller;
  3. use AlibabaCloud\SDK\Dingtalk\Vworkflow_1_0\Models\GetProcessConfigResponseBody\result\handSignConf;
  4. use JinDouYun\Cache\ShopCache;
  5. use JinDouYun\Cache\SupplierCache;
  6. use JinDouYun\Dao\Enterprise\DEnterprise;
  7. use JinDouYun\Dao\Shop\DShopKey;
  8. use JinDouYun\Model\Enterprise\MEnterprise;
  9. use JinDouYun\Model\System\MBasicSetup;
  10. use JinDouYun\Model\System\MModule;
  11. use JinDouYun\Model\Shop\MShop;
  12. use Mall\Framework\Core\StatusCode;
  13. use Mall\Framework\Factory;
  14. use Mall\Framework\Core\Jwt;
  15. use Mall\Framework\Core\ErrorCode;
  16. use JinDouYun\Cache\EnterpriseCache;
  17. use JinDouYun\Cache\RoleAclCache;
  18. use JinDouYun\Cache\SysAreaChinaCache;
  19. use JinDouYun\Model\SysAreaChina\MSysAreaChina;
  20. class BaseController
  21. {
  22. /** @var \Mall\Framework\Core\Request $request */
  23. protected $request;
  24. /** @var \Mall\Framework\Core\Cache $cache */
  25. protected $cache;
  26. /**
  27. * @var int
  28. */
  29. protected $onlineUserId;
  30. /**
  31. * @var int
  32. */
  33. protected $onlineEnterpriseId;
  34. /**
  35. * @var string
  36. */
  37. protected $authorization;
  38. /**
  39. * @var string
  40. */
  41. protected $token;
  42. /**
  43. * @var string
  44. */
  45. protected $areaCode;
  46. /**
  47. * @var string 店铺token
  48. */
  49. private $shopToken = '';
  50. /**
  51. * @var int 供应商id
  52. */
  53. protected $supplierId = null;//TODO
  54. /**
  55. * @var string
  56. */
  57. protected $supplierToken = '';
  58. /**
  59. * @var int
  60. */
  61. protected $shopId = 0;
  62. /**
  63. * BaseController constructor.
  64. * @param bool $isCheckAcl
  65. * @param false $isMustLogin
  66. * @param bool $checkToken
  67. * @param false $getAreaCode
  68. * @param bool $checkShopToken
  69. * @param bool $checkSupplierToken
  70. */
  71. public function __construct(
  72. $isCheckAcl = true,
  73. $isMustLogin = false,
  74. $checkToken = true,
  75. $getAreaCode=false,
  76. $checkShopToken = true,
  77. $checkSupplierToken = true
  78. ){
  79. $this->request = Factory::request();
  80. //$this->cache = Factory::cache();
  81. if($isMustLogin){
  82. self::getUserIdByAuthorization();
  83. }
  84. if($checkToken){
  85. self::getEnterpriseIdByToken();
  86. }
  87. if($isCheckAcl){
  88. // self::checkAcl();
  89. }
  90. if ($getAreaCode) {
  91. self::getAreaCode();
  92. }
  93. if ($checkShopToken){
  94. self::getShopIdByShopToken();
  95. }
  96. if ($checkSupplierToken){
  97. self::getSupplierIdBySupplierToken();
  98. }
  99. }
  100. /**
  101. * #777每请求一次接口刷新一次Authorization 没有请求接口2小时 Authorization过期 需要重新登录
  102. * 根据Authorization获取userCenterId
  103. *
  104. * return int
  105. */
  106. public function getUserIdByAuthorization()
  107. {
  108. $authorization = $this->request->getServerParam('HTTP_AUTHORIZATION');
  109. if(empty($authorization)) {
  110. $this->sendOutput('未登录', ErrorCode::$notAllowToken);
  111. }
  112. try {
  113. $jwt_data = JWT::decode($authorization, SITE_SECRET, array('HS256'));
  114. if (empty($jwt_data) || $jwt_data->expireTime < time()) {
  115. // $this->sendOutput('登陆用户过期', ErrorCode::$loginedexpire);
  116. /*
  117. $referurl = $this->request->getServerParam('REQUEST_URI');
  118. $loginUrl = '?m=member&c=login&a=login&referurl=' . DOMAIN_PROJECT . $referurl;
  119. header('Location:' . $loginUrl);
  120. */
  121. }
  122. $this->onlineUserId = intval($jwt_data->uid);
  123. $this->authorization = $authorization;
  124. } catch (\Exception $e) {
  125. $this->sendOutput('无效的Authorization', ErrorCode::$notAllowToken);
  126. }
  127. }
  128. /**
  129. * Doc: (des="根据SHOP_TOKEN获取店铺id")
  130. * User: XMing
  131. * Date: 2020/12/2
  132. * Time: 10:03 上午
  133. */
  134. public function getShopIdByShopToken($Token = '')
  135. {
  136. $shopToken = $this->request->getServerParam('HTTP_SHOP_TOKEN');
  137. if (empty($shopToken)){
  138. $shopToken = $Token;
  139. if (empty($shopToken)){
  140. return;
  141. }
  142. }
  143. $this->shopToken = $shopToken;
  144. $objShopCache = new ShopCache();
  145. if (empty($this->onlineEnterpriseId)){
  146. $token = $this->request->getServerParam('HTTP_TOKEN');
  147. $this->token = $token;
  148. if (!empty($this->token)){
  149. $objEnterpriseCache = new EnterpriseCache();
  150. $this->onlineEnterpriseId = intval($objEnterpriseCache->getEnterpriseIdByToken($token));
  151. }
  152. }
  153. $objMShop=new MShop($this->onlineEnterpriseId);
  154. $this->shopId=$objMShop->getShopid($this->onlineEnterpriseId,$this->shopToken)[0]['id'];
  155. ;
  156. // $this->shopId = intval($objShopCache->getShopToken(10,$this->shopToken));
  157. if (empty($this->shopId)){
  158. $this->sendOutput('店铺不存在',ErrorCode::$notAllowAccess);
  159. }
  160. }
  161. public function getSupplierIdBySupplierToken()
  162. {
  163. $supplierToken = $this->request->getServerParam('HTTP_SUPPLIER_TOKEN');
  164. if (empty($supplierToken)){
  165. return;
  166. }
  167. $this->supplierToken = $supplierToken;
  168. $objSupplierCache = new SupplierCache();
  169. $this->supplierId = intval($objSupplierCache->getSupplierToken($this->onlineEnterpriseId,$this->supplierToken));
  170. if (empty($this->supplierId)){
  171. $this->sendOutput('供应商不存在',ErrorCode::$notAllowAccess);
  172. }
  173. }
  174. /**
  175. * 根据企业token获取企业id enterpriseId
  176. * return int
  177. * @param bool $checkExists
  178. */
  179. public function getEnterpriseIdByToken($checkExists = true)
  180. {
  181. $token = $this->request->getServerParam('HTTP_TOKEN');
  182. $this->token = $token;
  183. if(!$this->token && $checkExists) {
  184. $this->sendOutput('token为空', ErrorCode::$notAllowToken);
  185. }
  186. // 先从Cache中根据token找id
  187. $objEnterpriseCache = new EnterpriseCache();
  188. $this->onlineEnterpriseId = intval($objEnterpriseCache->getEnterpriseIdByToken($token));
  189. // 如果没有就从数据库中找id
  190. if(empty($this->onlineEnterpriseId)){
  191. $objMEnterprise = new MEnterprise();
  192. $enterpriseId = $objMEnterprise->getEnterpriseIdByToken($token);
  193. if(!$enterpriseId->isSuccess()){
  194. $this->sendOutput($enterpriseId->getData(), $enterpriseId->getErrorCode());
  195. }
  196. $enterpriseId = $enterpriseId->getData();
  197. $this->onlineEnterpriseId = intval($enterpriseId);
  198. }
  199. // 以上都没有则企业不存在
  200. if( empty($this->onlineEnterpriseId) && $checkExists){
  201. $this->sendOutput('当前企业不存在', ErrorCode::$notAllowAccess);
  202. }
  203. $objEnterpriseCache->enterpriseIdAndTokenCache($this->onlineEnterpriseId, $token);
  204. }
  205. public function getAreaCode() {
  206. $location = $this->request->getServerParam('HTTP_LOCATION');
  207. if (empty($location)) {
  208. $this->areaCode = '';
  209. return;
  210. }
  211. $areaArr = json_decode(base64_decode($location),true);
  212. if (is_string($areaArr)) {
  213. $areaArr = json_decode($areaArr,true);
  214. }
  215. if(empty($areaArr)){
  216. $areaArr = [
  217. 'provinceName' => '陕西省',
  218. 'cityName' => '西安市',
  219. 'districtName' => '莲湖区'
  220. ];
  221. }
  222. foreach($areaArr as &$value){
  223. if(empty($value)){
  224. $value = '';
  225. }
  226. }
  227. switch($areaArr['cityName']){
  228. case '北京市':
  229. $areaArr['provinceName'] = '北京市';
  230. break;
  231. case '重庆市':
  232. $areaArr['provinceName'] = '重庆市';
  233. break;
  234. case '天津市':
  235. $areaArr['provinceName'] = '天津市';
  236. break;
  237. case '上海市':
  238. $areaArr['provinceName'] = '上海市';
  239. break;
  240. }
  241. // V($areaArr);
  242. $this->areaCode = '';
  243. $objMSysAreaChina = new MSysAreaChina();
  244. $modelResult = $objMSysAreaChina->getCodeByName($areaArr);
  245. if(!$modelResult->isSuccess()){
  246. $this->sendOutput($modelResult->getData(), $modelResult->getErrorCode());
  247. }
  248. $areaData = $modelResult->getData();
  249. foreach($areaData as $value){
  250. $this->areaCode = !empty($this->areaCode) ? $this->areaCode.'-'.$value : $this->areaCode.$value;
  251. }
  252. }
  253. /**
  254. * 校验权限,当前登录用户是否可操作当前企业
  255. */
  256. public function checkAcl() {
  257. if(!$this->onlineUserId) {
  258. $this->sendOutput('请登录', ErrorCode::$notAllowToken);
  259. }
  260. if(!$this->onlineEnterpriseId) {
  261. $this->sendOutput('请选择企业', ErrorCode::$notAllowToken);
  262. }
  263. //获取用户与企业的关联关系
  264. $objEnterpriseCache = new EnterpriseCache();
  265. $enterpriseIds = $objEnterpriseCache->getUserCenterIdAndEnterpriseIds($this->onlineUserId);
  266. //用户与企业不存在关联,则无权限
  267. if(!isset($enterpriseIds[$this->onlineEnterpriseId])){
  268. $this->sendOutput('没有权限操作', ErrorCode::$notAllowAccess);
  269. }
  270. //如果是创建者,则超级管理员,无限权限
  271. if($enterpriseIds[$this->onlineEnterpriseId] == StatusCode::$roleType['admin']) {
  272. return true;
  273. }
  274. //员工,获取其在企业所属的角色组id
  275. $objRoleAclCache = new RoleAclCache();
  276. $roleId = $objRoleAclCache->getRoleIdOfStaff($this->onlineEnterpriseId, $this->onlineUserId);
  277. if(!$roleId){
  278. $this->sendOutput('请联系管理员获取角色', ErrorCode::$notAllowAccess);
  279. }
  280. //查询是否为超级管理员
  281. $cacheResult = $objRoleAclCache->getAdministrator($this->onlineEnterpriseId, $roleId);
  282. if($cacheResult){
  283. //是超级管理员
  284. return true;
  285. }
  286. self::accessCheck($roleId);
  287. }
  288. /**
  289. * 系统核心权限控制部分
  290. * @param array $aclList
  291. * @return bool
  292. */
  293. public function accessCheck($roleId)
  294. {
  295. $moduleName = strtolower($this->request->getModule());
  296. $controllerName = strtolower($this->request->param('c'));
  297. $actionName = strtolower($this->request->getAction());
  298. if (!$moduleName || !$controllerName || !$actionName) {
  299. self::sendOutput('非法的请求', ErrorCode::$notAllowAccess);
  300. }
  301. $accessUrl = $moduleName . DS . $controllerName . DS . $actionName;
  302. //过滤是否验证权限
  303. $objRoleAclCache = new RoleAclCache();
  304. $result = $objRoleAclCache->getAuthority($accessUrl);
  305. if(!$result){
  306. return true;
  307. }
  308. //搜索的直接放行
  309. if(strpos($actionName,'search') !== false) {
  310. return true;
  311. }
  312. $cacheResult = $objRoleAclCache->getAuthorityBindRole($this->onlineEnterpriseId, $roleId, $accessUrl);
  313. if(!$cacheResult){
  314. $objMModule = new MModule();
  315. $moduleName =(string) $objMModule->getModuleNameByUri($accessUrl);
  316. self::sendOutput('没有权限操作,'.$moduleName, ErrorCode::$notHaveAclAccess);
  317. }
  318. return true;
  319. }
  320. /**
  321. * 项目全局返回json格式
  322. * @param $data
  323. * @param int $errorcode
  324. * @param array $pageData
  325. */
  326. public function sendOutput($data, $errorcode = 0, $pageData = [])
  327. {
  328. $errorcode = intval($errorcode);
  329. if ($errorcode) {
  330. $sendMessage = [
  331. 'state' => false,
  332. 'data' => $data,
  333. 'errorcode' => $errorcode
  334. ];
  335. } else {
  336. $sendMessage = [
  337. 'state' => true,
  338. 'data' => $data,
  339. 'errorcode' => $errorcode
  340. ];
  341. }
  342. $sendMessage = array_merge($sendMessage, $pageData);
  343. if($sendMessage['errorcode'] == ErrorCode::$dberror){
  344. $moduleName = strtolower($this->request->getModule());
  345. $controllerName = strtolower($this->request->param('c'));
  346. $actionName = strtolower($this->request->getAction());
  347. $accessUrl = $moduleName . DS . $controllerName . DS . $actionName;
  348. // file_put_contents('../apps/logs/sqlerror.log', date('Y-m-d H:i:s').'-'.$accessUrl.'-'.var_export($sendMessage['data'], true) . PHP_EOL, FILE_APPEND);
  349. }
  350. if(empty($sendMessage['data']) && !isset($sendMessage['pageTotal'])){
  351. exit(json_encode($sendMessage, JSON_UNESCAPED_UNICODE|JSON_FORCE_OBJECT));
  352. }
  353. exit(json_encode($sendMessage, JSON_UNESCAPED_UNICODE));
  354. }
  355. /**
  356. * 检查手机号格式
  357. * @param $mobile
  358. */
  359. public function checkMobile($mobile){
  360. $checkMobile = isMobile($mobile);
  361. if(!$checkMobile){
  362. self::sendOutput('手机格式不正确', ErrorCode::$paramError);
  363. }
  364. }
  365. public function pr($var, $int = '')
  366. {
  367. $template = PHP_SAPI !== 'cli' ? '<pre>%s</pre>' : "\n%s\n";
  368. printf($template, print_r($var, true));
  369. exit($int);
  370. }
  371. /**
  372. *获取AccessToken
  373. * @return bool|string
  374. */
  375. public function AccessToken()
  376. {
  377. $this->shopKey = new DShopKey('default');
  378. $this->shopKey->setTable($this->shopKey->get_Table().'_'.$this->onlineEnterpriseId);
  379. $data = $this->shopKey->get(['shop_id' => $this->shopId]);
  380. $data = [
  381. 'corpid' => $data['corpid'],
  382. 'ssoSecret' => $data['ssoSecred']
  383. ];
  384. $res = $this->post_json('https://api.dingtalk.com/v1.0/oauth2/ssoAccessToken', json_encode($data));
  385. $res = json_decode($res);
  386. return $res->access_token;
  387. }
  388. /**
  389. * 获取免登入凭证
  390. * @return bool|string
  391. */
  392. public function voucher($shopId = '', $EnterpriseId = '')
  393. {
  394. $this->shopKey = new DShopKey('default');
  395. $onlineEnterpriseId = $this->onlineEnterpriseId ? $this->onlineEnterpriseId : $EnterpriseId;
  396. $shopId = $this->shopId ? $this->shopId : $shopId;
  397. $basic = new MBasicSetup($onlineEnterpriseId);
  398. $data = $basic->getBasicSetup($onlineEnterpriseId)->getData();
  399. // $data = $this->shopKey->get(['enterprise_id' => $onlineEnterpriseId]);
  400. if (isset($data['basicData']['appKey']) and isset($data['basicData']['appSecret'])){
  401. if (empty($data['basicData']['appKey']) || empty($data['basicData']['appSecret'])){
  402. self::sendOutput('请完善配置钉钉apikey', ErrorCode::$paramError);
  403. }
  404. }else{
  405. self::sendOutput('请配置钉钉apikey', ErrorCode::$paramError);
  406. }
  407. $res = $this->curl_get('https://oapi.dingtalk.com/gettoken?appkey='.$data['basicData']['appKey'].'&appsecret='.$data['basicData']['appSecret']);
  408. $res = json_decode($res);
  409. return $res->access_token;
  410. }
  411. /**
  412. * group_key
  413. * @return mixed
  414. */
  415. public function group_key($id)
  416. {
  417. $group_key = $this->post_json('https://oapi.dingtalk.com/topapi/attendance/groups/idtokey?access_token='.$this->voucher(),json_encode(['group_id' => $id]));
  418. $group_key = json_decode($group_key);
  419. if ($group_key->errcode > 0){
  420. parent::sendOutput($group_key->errmsg, 1);
  421. }
  422. return $group_key->result;
  423. }
  424. public function curl_get($url, &$httpCode = 0)
  425. {
  426. $ch = curl_init();
  427. curl_setopt($ch, CURLOPT_URL, $url);
  428. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  429. //不做证书校验,部署在linux环境下请改为true
  430. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  431. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
  432. $file_contents = curl_exec($ch);
  433. $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  434. curl_close($ch);
  435. return $file_contents;
  436. }
  437. public function post_json($url , $params = array()){
  438. //$data_string = json_encode($params,JSON_UNESCAPED_UNICODE);
  439. $ch = curl_init();
  440. curl_setopt($ch, CURLOPT_URL, $url);
  441. curl_setopt($ch, CURLOPT_HEADER, 0);
  442. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  443. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
  444. curl_setopt($ch, CURLOPT_POST, 1);
  445. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  446. curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
  447. curl_setopt(
  448. $ch, CURLOPT_HTTPHEADER,
  449. array(
  450. 'Content-Type: application/json'
  451. )
  452. );
  453. $data = curl_exec($ch);
  454. curl_close($ch);
  455. return ($data);
  456. }
  457. public function getRandPass($length = 8)
  458. {
  459. $password = '';
  460. $chars = "0123456789";
  461. $char_len = strlen($chars);
  462. for ($i = 0; $i <= $length; $i++) {
  463. $loop = mt_rand(0, ($char_len - 1));
  464. $password .= $chars[$loop];
  465. }
  466. return $password;
  467. }
  468. }