Wxapp.php 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. <?php
  2. namespace app\data\controller\api;
  3. use app\data\service\UserAdminService;
  4. use think\admin\Controller;
  5. use think\exception\HttpResponseException;
  6. use think\Response;
  7. use WeMini\Crypt;
  8. use WeMini\Live;
  9. use WeMini\Qrcode;
  10. /**
  11. * 微信小程序入口
  12. * Class Wxapp
  13. * @package app\data\controller\api
  14. */
  15. class Wxapp extends Controller
  16. {
  17. /**
  18. * 接口认证类型
  19. * @var string
  20. */
  21. private $type = UserAdminService::API_TYPE_WXAPP;
  22. /**
  23. * 唯一绑定字段
  24. * @var string
  25. */
  26. private $field;
  27. /**
  28. * 小程序配置参数
  29. * @var array
  30. */
  31. private $cfg;
  32. /**
  33. * 接口服务初始化
  34. * @throws \think\db\exception\DataNotFoundException
  35. * @throws \think\db\exception\DbException
  36. * @throws \think\db\exception\ModelNotFoundException
  37. */
  38. protected function initialize()
  39. {
  40. $opt = sysdata('wxapp');
  41. $this->cfg = [
  42. 'appid' => $opt['appid'] ?? '',
  43. 'appsecret' => $opt['appkey'] ?? '',
  44. 'cache_path' => $this->app->getRootPath() . 'runtime' . DIRECTORY_SEPARATOR . 'wechat',
  45. ];
  46. if (empty(UserAdminService::TYPES[$this->type]['auth'])) {
  47. $this->error("接口类型[{$this->type}]没有定义规则");
  48. } else {
  49. $this->field = UserAdminService::TYPES[$this->type]['auth'];
  50. }
  51. }
  52. /**
  53. * 授权Code换取会话信息
  54. * @throws \think\admin\Exception
  55. * @throws \think\db\exception\DbException
  56. */
  57. public function session()
  58. {
  59. $input = $this->_vali(['code.require' => '登录凭证CODE不能为空!']);
  60. [$openid, $unionid, $session] = $this->applySessionKey($input['code']);
  61. $map = UserAdminService::getUserUniMap($this->field, $openid, $unionid);
  62. $data = [$this->field => $openid, 'session_key' => $session];
  63. if (!empty($unionid)) $data['unionid'] = $unionid;
  64. $this->success('授权换取成功!', UserAdminService::set($map, $data, $this->type, true));
  65. }
  66. /**
  67. * 小程序数据解密
  68. */
  69. public function decode()
  70. {
  71. try {
  72. $input = $this->_vali([
  73. 'iv.require' => '解密向量不能为空!',
  74. 'code.require' => '授权CODE不能为空!',
  75. 'encrypted.require' => '加密内容不能为空!',
  76. ]);
  77. [$openid, $unionid, $input['session_key']] = $this->applySessionKey($input['code']);
  78. $result = Crypt::instance($this->cfg)->decode($input['iv'], $input['session_key'], $input['encrypted']);
  79. if (is_array($result) && isset($result['avatarUrl']) && isset($result['nickName'])) {
  80. $data = [$this->field => $openid, 'nickname' => $result['nickName'], 'headimg' => $result['avatarUrl']];
  81. $data['base_sex'] = ['-', '男', '女'][$result['gender']] ?? '-';
  82. if (!empty($unionid)) $data['unionid'] = $unionid;
  83. $map = UserAdminService::getUserUniMap($this->field, $openid, $unionid);
  84. $this->success('数据解密成功!', UserAdminService::set($map, $data, $this->type, true));
  85. } elseif (is_array($result)) {
  86. $this->success('数据解密成功!', $result);
  87. } else {
  88. $this->error('数据处理失败,请稍候再试!');
  89. }
  90. } catch (HttpResponseException $exception) {
  91. throw $exception;
  92. } catch (\Exception $exception) {
  93. trace_file($exception);
  94. $this->error("数据处理失败,{$exception->getMessage()}");
  95. }
  96. }
  97. /**
  98. * 授权CODE换取会话信息
  99. * @param string $code 换取授权CODE
  100. * @return array [openid, sessionkey]
  101. */
  102. private function applySessionKey(string $code): array
  103. {
  104. try {
  105. $cache = $this->app->cache->get($code, []);
  106. if (isset($cache['openid']) && isset($cache['session_key'])) {
  107. return [$cache['openid'], $cache['unionid'] ?? '', $cache['session_key']];
  108. }
  109. $result = Crypt::instance($this->cfg)->session($code);
  110. if (isset($result['openid']) && isset($result['session_key'])) {
  111. $this->app->cache->set($code, $result, 60);
  112. return [$result['openid'], $result['unionid'] ?? '', $result['session_key']];
  113. } elseif (isset($result['errmsg'])) {
  114. $this->error($result['errmsg']);
  115. } else {
  116. $this->error("授权换取失败,请稍候再试!");
  117. }
  118. } catch (HttpResponseException $exception) {
  119. throw $exception;
  120. } catch (\Exception $exception) {
  121. trace_file($exception);
  122. $this->error("授权换取失败,{$exception->getMessage()}");
  123. }
  124. }
  125. /**
  126. * 获取小程序码
  127. */
  128. public function qrcode(): Response
  129. {
  130. try {
  131. $data = $this->_vali([
  132. 'size.default' => 430,
  133. 'type.default' => 'base64',
  134. 'path.require' => '跳转路径不能为空!',
  135. ]);
  136. $result = Qrcode::instance($this->cfg)->createMiniPath($data['path'], $data['size']);
  137. if ($data['type'] === 'base64') {
  138. $this->success('生成小程序码成功!', [
  139. 'base64' => 'data:image/png;base64,' . base64_encode($result),
  140. ]);
  141. } else {
  142. return response($result)->contentType('image/png');
  143. }
  144. } catch (HttpResponseException $exception) {
  145. throw $exception;
  146. } catch (\Exception $exception) {
  147. trace_file($exception);
  148. $this->error($exception->getMessage());
  149. }
  150. }
  151. /**
  152. * 获取直播列表
  153. */
  154. public function getLiveList()
  155. {
  156. try {
  157. $data = $this->_vali(['start.default' => 0, 'limit.default' => 10]);
  158. $list = Live::instance($this->cfg)->getLiveList($data['start'], $data['limit']);
  159. $this->success('获取直播列表成功!', $list);
  160. } catch (HttpResponseException $exception) {
  161. throw $exception;
  162. } catch (\Exception $exception) {
  163. trace_file($exception);
  164. $this->error($exception->getMessage());
  165. }
  166. }
  167. /**
  168. * 获取回放源视频
  169. */
  170. public function getLiveInfo()
  171. {
  172. try {
  173. $data = $this->_vali([
  174. 'start.default' => 0,
  175. 'limit.default' => 10,
  176. 'action.default' => 'get_replay',
  177. 'room_id.require' => '直播间不能为空',
  178. ]);
  179. $result = Live::instance($this->cfg)->getLiveInfo($data);
  180. $this->success('获取回放视频成功!', $result);
  181. } catch (HttpResponseException $exception) {
  182. throw $exception;
  183. } catch (\Exception $exception) {
  184. trace_file($exception);
  185. $this->error($exception->getMessage());
  186. }
  187. }
  188. }