| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- <?php
- namespace App\Http\Controllers\Api\Wechat;
- use App\Http\Controllers\Controller;
- use App\Models\Api\Personnel\EmployeeOpenid as EmployeeOpenidModel;
- use App\Facades\Servers\Logs\Log;
- use App\Servers\Wechat\Official;
- class OfficialNotify extends Controller
- {
- /**
- * 公众号关注回调 - 自动绑定用户公众号OpenID
- * @author 唐远望
- * @version 1.0
- * @date 2026-03-10
- */
- public function callback(EmployeeOpenidModel $EmployeeOpenidModel)
- {
- // 1. 处理微信服务器验证(GET请求)
- if ($_SERVER['REQUEST_METHOD'] === 'GET') {
- return $this->checkSignature();
- }
-
- // 2. 处理微信事件推送(POST请求)
- if ($_SERVER['REQUEST_METHOD'] === 'POST') {
- return $this->handleEvent($EmployeeOpenidModel);
- }
-
- return 'success';
- }
-
- /**
- * 处理微信事件
- */
- private function handleEvent($EmployeeOpenidModel)
- {
- // 获取微信推送的原始数据
- $xmlData = file_get_contents('php://input');
- $xml = simplexml_load_string($xmlData, 'SimpleXMLElement', LIBXML_NOCDATA);
-
- if (!$xml) {
- return 'success';
- }
-
- // 提取关键信息
- $fromUsername = (string)$xml->FromUserName; // 用户的公众号OpenID
- $toUsername = (string)$xml->ToUserName; // 公众号原始ID
- $event = (string)$xml->Event; // 事件类型
- $eventKey = (string)$xml->EventKey; // 事件KEY值(扫码关注时会有)
-
- // 记录日志,方便调试
- Log::info('wechat_subscribe_info', '微信关注事件', [
- 'FromUserName' => $fromUsername,
- 'ToUserName' => $toUsername,
- 'event' => $event,
- 'eventKey' => $eventKey
- ]);
-
- // 处理关注事件
- if ($event == 'subscribe') {
- try {
- // 尝试获取用户UnionID
- $Official = new Official();
- $official_user_info = $Official->getApp()->user->get($fromUsername);
- $unionid = isset($official_user_info['unionid']) ? $official_user_info['unionid'] : '';
-
- if ($unionid) {
- // 1. 有UnionID,直接绑定公众号OpenID
- $user_open_data = $EmployeeOpenidModel->where(['unionid' => $unionid])->first();
- if ($user_open_data) {
- $user_open_data->official_openid = $fromUsername;
- $user_open_data->save();
- Log::info('wechat_subscribe_success', '绑定成功', ['unionid' => $unionid, 'openid' => $fromUsername]);
- }
- } else {
- Log::info('wechat_subscribe_error', '获取UnionID失败', [
- 'data' => $fromUsername,
- 'request_data' => $official_user_info
- ]);
- }
- } catch (\Exception $e) {
- Log::error('wechat_subscribe_exception', '处理异常', [
- 'error' => $e->getMessage()
- ]);
- }
- }
-
- // 重要:必须返回success
- return 'success';
- }
- /**
- * 验证服务器地址有效性
- */
- private function checkSignature()
- {
- $signature = $_GET["signature"] ?? '';
- $timestamp = $_GET["timestamp"] ?? '';
- $nonce = $_GET["nonce"] ?? '';
- $echostr = $_GET["echostr"] ?? '';
-
- if (!$signature || !$timestamp || !$nonce) {
- return 'Invalid request';
- }
-
- $token = config('wechat.openplat.token', 'your_token_here');
- $tmpArr = [$token, $timestamp, $nonce];
- sort($tmpArr, SORT_STRING);
- $tmpStr = sha1(implode($tmpArr));
-
- if ($tmpStr == $signature) {
- return $echostr; // 验证成功,返回echostr
- } else {
- return 'Invalid signature';
- }
- }
- }
|