Home.php 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. <?php
  2. namespace app\controller\v2;
  3. use app\extra\basic\Base;
  4. use app\extra\dyLife\Crypt;
  5. use app\middleware\AuthMiddleware;
  6. use app\model\saas\SaasGoods;
  7. use app\model\saas\SaasStore;
  8. use LinFly\Annotation\Attributes\Route\Controller;
  9. use LinFly\Annotation\Attributes\Route\GetMapping;
  10. use LinFly\Annotation\Attributes\Route\Middleware;
  11. use LinFly\Annotation\Attributes\Route\PostMapping;
  12. use support\Request;
  13. use support\Response;
  14. #[Controller("/v2/home"),Middleware(AuthMiddleware::class)]
  15. class Home extends Base
  16. {
  17. /**
  18. * @var array|string[]
  19. */
  20. protected array $noNeedLogin = ["getHomeData","getLicense","payBtnMobile","getMoreGoods","getCityJson"];
  21. #[GetMapping("data")]
  22. public function getHomeData(Request $request): Response
  23. {
  24. try {
  25. $param = $this->_valid([
  26. "store.require" => trans("empty.require")
  27. ],$request->method());
  28. if (!is_array($param)) return error($param);
  29. $store = (new SaasStore)->where("poi_id",$param['store'])->field("poi_name,start_at,end_at,longitude,latitude,service_mobile,poi_id,poi_city,poi_address,poi_logo")->findOrEmpty();
  30. if (!$store->isEmpty()) {
  31. $store['poi_logo'] = empty($store['poi_logo']) ? sConf("service.logo") : $store['poi_logo'];
  32. }
  33. $goods = (new SaasGoods)->where("poi_id",$param['store'])->where("status",1)->field("product_id,product_name,image_list,category,price,line_price,sale_stock,id")->limit(10)->order('id','desc')->select()->toArray();
  34. return success("ok",compact('store','goods'));
  35. } catch (\Throwable $th) {
  36. return error($th->getMessage());
  37. }
  38. }
  39. #[GetMapping("goods")]
  40. public function getMoreGoods(Request $request): Response
  41. {
  42. try {
  43. $param = $this->_valid([
  44. "store.require" => trans("empty.require"),
  45. "page.default" => 1,
  46. "size.default" => 10
  47. ],$request->method());
  48. if (!is_array($param)) return error($param);
  49. $goods = (new SaasGoods)->where("poi_id",$param['store'])->where("status",1)->field("product_id,product_name,image_list,category,price,line_price,sale_stock,id,goods_id")->limit(10)->order('id','desc')->paginate([
  50. "list_rows" => $param['size'],
  51. "page" => $param['page']
  52. ]);
  53. return successTrans(100010,pageFormat($goods),200);
  54. } catch (\Throwable $throwable) {
  55. return error($throwable->getMessage());
  56. }
  57. }
  58. #[GetMapping("license")]
  59. public function getLicense(): Response
  60. {
  61. try {
  62. return success("ok",['img' => sConf("service.license")]);
  63. } catch (\Throwable $throwable) {
  64. return error($throwable->getMessage());
  65. }
  66. }
  67. /**
  68. * 三级城市信息
  69. * @param Request $request
  70. * @return Response
  71. */
  72. #[GetMapping("city")]
  73. public function getCityJson(Request $request): Response
  74. {
  75. try {
  76. $data = json_decode(file_get_contents(base_path()."/city.json"),true);
  77. return successTrans("success.data",$data);
  78. } catch (\Throwable $throwable) {
  79. return error($throwable->getMessage());
  80. }
  81. }
  82. /**
  83. * 生服组件解密手机号码
  84. * @param Request $request
  85. * @return Response
  86. */
  87. #[PostMapping("mobile")]
  88. public function payBtnMobile(Request $request): Response
  89. {
  90. try {
  91. $param = $request->all();
  92. $mobile = [];
  93. if (!empty($param['code'])) {
  94. $sessionKey = (new Crypt)->config($this->getDyConfig())->token()->getSessionKey($param['code']);
  95. if (!empty($sessionKey)) {
  96. $mobileStr = $this->decrypt2code($param['encryptedData'], $sessionKey['session_key'],$param['iv']);
  97. if (!empty($mobileStr)) $mobile = json_decode($mobileStr,true);
  98. }
  99. }
  100. if (empty($mobile)) return error("获取失败");
  101. return successTrans("success.data",['mobile' => $mobile['purePhoneNumber']]);
  102. } catch (\Throwable $throwable) {
  103. return error($throwable->getMessage());
  104. }
  105. }
  106. /**
  107. * 解密微信用户手机号等加密数据
  108. *
  109. * @param string $encrypted_data Base64 编码的密文
  110. * @param string $session_key Base64 编码的会话密钥
  111. * @param string $iv Base64 编码的初始向量
  112. * @return string 解密后的原始字符串(通常为 JSON)
  113. * @throws Exception
  114. */
  115. protected function decrypt2code($encrypted_data, $session_key, $iv)
  116. {
  117. // 1. Base64 解码
  118. $data = base64_decode($encrypted_data, true);
  119. $key = base64_decode($session_key, true);
  120. $iv = base64_decode($iv, true);
  121. if ($data === false || $key === false || $iv === false) {
  122. throw new \Exception('Base64 解码失败');
  123. }
  124. // 2. 根据密钥长度选择 AES 算法
  125. $key_len = strlen($key);
  126. switch ($key_len) {
  127. case 16:
  128. $method = 'AES-128-CBC';
  129. break;
  130. case 24:
  131. $method = 'AES-192-CBC';
  132. break;
  133. case 32:
  134. $method = 'AES-256-CBC';
  135. break;
  136. default:
  137. throw new \Exception("无效的密钥长度: {$key_len} 字节");
  138. }
  139. // 3. 解密(OPENSSL_RAW_DATA 表示返回二进制数据,不进行 Base64 编码)
  140. $decrypted = openssl_decrypt($data, $method, $key, OPENSSL_RAW_DATA, $iv);
  141. if ($decrypted === false) {
  142. throw new \Exception('解密失败: ' . openssl_error_string());
  143. }
  144. return $decrypted;
  145. }
  146. }