OfficialNotify.php 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. <?php
  2. namespace App\Http\Controllers\Api\Wechat;
  3. use App\Http\Controllers\Controller;
  4. use App\Models\Api\Personnel\EmployeeOpenid as EmployeeOpenidModel;
  5. use App\Facades\Servers\Logs\Log;
  6. use App\Servers\Wechat\Official;
  7. class OfficialNotify extends Controller
  8. {
  9. /**
  10. * 公众号关注回调 - 自动绑定用户公众号OpenID
  11. * @author 唐远望
  12. * @version 1.0
  13. * @date 2026-03-10
  14. */
  15. public function callback(EmployeeOpenidModel $EmployeeOpenidModel)
  16. {
  17. // 验证签名
  18. $signature = $this->checkSignature();
  19. if ($signature) return $signature;
  20. // 获取微信推送的原始数据
  21. $xmlData = file_get_contents('php://input');
  22. $xml = simplexml_load_string($xmlData, 'SimpleXMLElement', LIBXML_NOCDATA);
  23. $Official = new Official();
  24. if (!$xml) return true;
  25. // 提取关键信息
  26. $fromUsername = (string)$xml->FromUserName; // 用户的公众号OpenID
  27. $toUsername = (string)$xml->ToUserName; // 公众号原始ID
  28. $event = (string)$xml->Event; // 事件类型
  29. $eventKey = (string)$xml->EventKey; // 事件KEY值(扫码关注时会有)
  30. // 记录日志,方便调试
  31. Log::info('wechat_subscribe_info', '微信关注事件', ['FromUserName' => $fromUsername, 'ToUserName' => $toUsername, 'event' => $event, 'eventKey' => $eventKey]);
  32. // 处理关注事件
  33. if ($event == 'subscribe') {
  34. // 尝试获取用户UnionID
  35. $official_user_info = $Official->getApp()->user->get($fromUsername);
  36. $unionid = isset($official_user_info['unionid']) ? $official_user_info['unionid'] : '';
  37. if ($unionid) {
  38. // 1. 有UnionID,直接绑定公众号OpenID
  39. $user_open_data = $EmployeeOpenidModel->where(['unionid' => $unionid])->first();
  40. if ($user_open_data) {
  41. $user_open_data->official_openid = $fromUsername;
  42. $user_open_data->save();
  43. }
  44. } else {
  45. Log::info('wechat_subscribe_error', '获取UnionID失败', ['data' => $fromUsername, 'request_data' => $official_user_info]);
  46. }
  47. }
  48. // 默认返回成功(微信要求必须返回)
  49. return true;
  50. }
  51. private function checkSignature()
  52. {
  53. $signature = $_GET["signature"];
  54. $timestamp = $_GET["timestamp"];
  55. $nonce = $_GET["nonce"];
  56. if (!$signature || !$timestamp || !$nonce) return false;
  57. $token = config('wechat.openplat.token', '');
  58. $tmpArr = array($token, $timestamp, $nonce);
  59. sort($tmpArr, SORT_STRING);
  60. $tmpStr = implode($tmpArr);
  61. $tmpStr = sha1($tmpStr);
  62. if ($tmpStr == $signature) {
  63. return $tmpStr;
  64. } else {
  65. return false;
  66. }
  67. }
  68. }