Wechat.php 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. <?php
  2. namespace app\data\controller\api;
  3. use app\data\service\UserAdminService;
  4. use app\wechat\service\WechatService;
  5. use think\admin\Controller;
  6. use think\Response;
  7. /**
  8. * 微信服务号入口
  9. * Class Wechat
  10. * @package app\data\controller\api
  11. * @example 域名请修改为自己的地址,放到网页代码合适位置
  12. * <meta name="referrer" content="always">
  13. * <script referrerpolicy="unsafe-url" src="https://your.domain.com/data/api.wechat/oauth?mode=1"></script>
  14. *
  15. * 授权模式支持两种模块,参数 mode=0 时为静默授权,mode=1 时为完整授权
  16. * 注意:回跳地址默认从 Header 中的 http_referer 获取,也可以传 source 参数
  17. */
  18. class Wechat extends Controller
  19. {
  20. /**
  21. * 接口认证类型
  22. * @var string
  23. */
  24. private $type = UserAdminService::API_TYPE_WECHAT;
  25. /**
  26. * 唯一绑定字段
  27. * @var string
  28. */
  29. private $field;
  30. /**
  31. * 控制器初始化
  32. * @return $this
  33. */
  34. protected function initialize(): Wechat
  35. {
  36. if (empty(UserAdminService::TYPES[$this->type]['auth'])) {
  37. $this->error("接口类型[{$this->type}]没有定义规则");
  38. } else {
  39. $this->field = UserAdminService::TYPES[$this->type]['auth'];
  40. }
  41. return $this;
  42. }
  43. /**
  44. * 获取 JSSDK 签名
  45. * @throws \WeChat\Exceptions\InvalidResponseException
  46. * @throws \WeChat\Exceptions\LocalCacheException
  47. * @throws \think\admin\Exception
  48. * @throws \think\db\exception\DataNotFoundException
  49. * @throws \think\db\exception\DbException
  50. * @throws \think\db\exception\ModelNotFoundException
  51. */
  52. public function jssdk()
  53. {
  54. $url = input('source') ?: $this->request->server('http_referer');
  55. $this->success('获取签名参数', WechatService::instance()->getWebJssdkSign($url));
  56. }
  57. /**
  58. * 加载网页授权数据
  59. * @return \think\Response
  60. * @throws \think\admin\Exception
  61. * @throws \think\db\exception\DbException
  62. */
  63. public function oauth(): Response
  64. {
  65. $source = input('source') ?: $this->request->server('http_referer');
  66. [$mode, $script, $wechat] = [input('mode', 1), [], WechatService::instance()];
  67. $result = $wechat->getWebOauthInfo($source ?: $this->request->url(true), $mode, false);
  68. if (empty($result['openid'])) {
  69. $script[] = 'alert("Wechat WebOauth failed.")';
  70. } else {
  71. $data = $result['fansinfo'] ?? [];
  72. $data['openid2'] = $data['openid'];
  73. $data['base_sex'] = ['未知', '男', '女'][$data['sex']] ?? '未知';
  74. if (isset($data['headimgurl'])) $data['headimg'] = $data['headimgurl'];
  75. $map = isset($data['unionid']) ? ['unionid' => $data['unionid']] : [$this->field => $result['openid']];
  76. $result['userinfo'] = UserAdminService::instance()->set($map, array_merge($map, $data), $this->type, true);
  77. $script[] = "window.WeChatOpenid='{$result['openid']}'";
  78. $script[] = 'window.WeChatFansInfo=' . json_encode($result['fansinfo'], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
  79. $script[] = 'window.WeChatUserInfo=' . json_encode($result['userinfo'], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
  80. }
  81. $script[] = '';
  82. return Response::create(join(";\n", $script))->contentType('application/x-javascript');
  83. }
  84. /**
  85. * 网页授权测试
  86. * 使用网页直接访问此链接
  87. * @return string
  88. */
  89. public function otest(): string
  90. {
  91. return <<<EOL
  92. <html lang="zh">
  93. <head>
  94. <meta charset="utf-8">
  95. <title>微信网页授权测试</title>
  96. <meta name="referrer" content="always">
  97. <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0">
  98. <style>pre{padding:20px;overflow:auto;margin-top:10px;background:#ccc;border-radius:6px;}</style>
  99. </head>
  100. <body>
  101. <div>当前链接</div>
  102. <pre>{$this->request->scheme()}://{$this->request->host()}/data/api.wechat/oauth?mode=1</pre>
  103. <div style="margin-top:30px">粉丝数据</div>
  104. <pre id="fansdata">待网页授权,加载粉丝数据...</pre>
  105. <div style="margin-top:30px">用户数据</div>
  106. <pre id="userdata">待网页授权,加载用户数据...</pre>
  107. <script referrerpolicy="unsafe-url" src="//{$this->request->host()}/data/api.wechat/oauth?mode=1"></script>
  108. <script>
  109. if(typeof window.WeChatFansInfo === 'object'){
  110. document.getElementById('fansdata').innerText = JSON.stringify(window.WeChatFansInfo, null, 2);
  111. }
  112. if(typeof window.WeChatUserInfo === 'object'){
  113. document.getElementById('userdata').innerText = JSON.stringify(window.WeChatUserInfo, null, 2);
  114. }
  115. </script>
  116. </body>
  117. </html>
  118. EOL;
  119. }
  120. }