106 lines
3.7 KiB
PHP
106 lines
3.7 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace app\api\controller;
|
|
|
|
use app\adminapi\logic\qywx\CustomerLogic;
|
|
use EasyWeChat\Kernel\Exceptions\BadRequestException;
|
|
use EasyWeChat\Work\Application;
|
|
use EasyWeChat\Work\Message;
|
|
use think\facade\Log;
|
|
|
|
/**
|
|
* 企业微信「客户联系」事件回调(接收事件服务器)
|
|
*
|
|
* @see https://developer.work.weixin.qq.com/document/path/92130
|
|
*/
|
|
class QywxExternalContactCallbackController extends BaseApiController
|
|
{
|
|
/** 免登录:企微服务器回调 */
|
|
public array $notNeedLogin = ['notify'];
|
|
|
|
public function notify()
|
|
{
|
|
$corpId = (string) config('pay.wechat_work.corp_id', '');
|
|
$secret = (string) config('pay.wechat_work.external_pay_secret', '');
|
|
$token = (string) config('pay.wechat_work.contact_callback_token', '');
|
|
$aesKey = (string) config('pay.wechat_work.contact_callback_aes_key', '');
|
|
|
|
if ($corpId === '' || $secret === '' || $token === '' || $aesKey === '') {
|
|
Log::error('qywx external contact callback: 缺少配置 corp_id / external_pay_secret / contact_callback_token / contact_callback_aes_key');
|
|
|
|
return response('config error', 503, ['Content-Type' => 'text/plain; charset=utf-8']);
|
|
}
|
|
|
|
try {
|
|
$app = new Application([
|
|
'corp_id' => $corpId,
|
|
'secret' => $secret,
|
|
'token' => $token,
|
|
'aes_key' => $aesKey,
|
|
]);
|
|
$server = $app->getServer();
|
|
|
|
$server->addEventListener('change_external_contact', function (Message $message, \Closure $next) {
|
|
try {
|
|
$this->handleChangeExternalContact($message);
|
|
} catch (\Throwable $e) {
|
|
Log::error('qywx external contact callback: ' . $e->getMessage(), [
|
|
'exception' => $e,
|
|
]);
|
|
}
|
|
|
|
return $next($message);
|
|
});
|
|
|
|
$psr = $server->serve();
|
|
$body = $psr->getBody();
|
|
$body->rewind();
|
|
$content = $body->getContents();
|
|
|
|
$headers = [];
|
|
$contentType = $psr->getHeaderLine('Content-Type');
|
|
if ($contentType !== '') {
|
|
$headers['Content-Type'] = $contentType;
|
|
}
|
|
|
|
return response($content, 200, $headers);
|
|
} catch (BadRequestException $e) {
|
|
Log::warning('qywx external contact callback: bad request ' . $e->getMessage());
|
|
|
|
return response('bad request', 400, ['Content-Type' => 'text/plain; charset=utf-8']);
|
|
} catch (\Throwable $e) {
|
|
Log::error('qywx external contact callback: serve failed ' . $e->getMessage(), ['exception' => $e]);
|
|
|
|
return response('error', 500, ['Content-Type' => 'text/plain; charset=utf-8']);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param Message $message
|
|
*/
|
|
private function handleChangeExternalContact($message): void
|
|
{
|
|
$changeType = (string) ($message['ChangeType'] ?? '');
|
|
$extId = trim((string) ($message['ExternalUserID'] ?? $message['ExternalUserId'] ?? ''));
|
|
|
|
if ($extId === '') {
|
|
Log::info('qywx external contact callback: 无 ExternalUserID', ['ChangeType' => $changeType]);
|
|
|
|
return;
|
|
}
|
|
|
|
Log::info('qywx external contact callback', ['ChangeType' => $changeType, 'ExternalUserID' => $extId]);
|
|
|
|
if ($changeType === 'del_external_contact') {
|
|
CustomerLogic::softDeleteExternalContactRow($extId);
|
|
|
|
return;
|
|
}
|
|
|
|
// 其余变更(添加/编辑/删跟进人等):以 get 详情为准 UPSERT,避免遗漏未枚举的 ChangeType
|
|
CustomerLogic::upsertSingleExternalContactFromApi($extId);
|
|
}
|
|
}
|