更新
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use app\adminapi\logic\firstvisit\WecomAcquisitionCustomerLogic;
|
||||
use app\common\service\qywx\QywxCustomerAcquisitionApiService;
|
||||
use app\common\service\qywx\QywxCustomerAcquisitionCustomerService;
|
||||
use think\facade\Db;
|
||||
|
||||
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||
|
||||
$app = new think\App();
|
||||
$app->initialize();
|
||||
|
||||
$assert = static function (bool $condition, string $message): void {
|
||||
if (!$condition) {
|
||||
throw new RuntimeException($message);
|
||||
}
|
||||
};
|
||||
$admin = Db::name('admin')->where('root', 1)->whereNull('delete_time')->find();
|
||||
if (!$admin) {
|
||||
throw new RuntimeException('未找到 root 管理员,无法执行获客客户统计冒烟测试');
|
||||
}
|
||||
$assert(
|
||||
Db::name('dev_crontab')
|
||||
->where('command', 'qywx:retry-customer-acquisition-events')
|
||||
->whereNull('delete_time')
|
||||
->count() === 1,
|
||||
'获客回调每分钟重试任务未写入数据库'
|
||||
);
|
||||
|
||||
$suffix = bin2hex(random_bytes(5));
|
||||
$linkId = '__smoke_link_' . $suffix;
|
||||
$externalUserId = '__smoke_external_' . $suffix;
|
||||
$userId = '__smoke_user_' . $suffix;
|
||||
$eventTime = time();
|
||||
$api = new class($linkId, $externalUserId, $userId) extends QywxCustomerAcquisitionApiService {
|
||||
public function __construct(
|
||||
private string $testLinkId,
|
||||
private string $testExternalUserId,
|
||||
private string $testUserId
|
||||
) {
|
||||
}
|
||||
|
||||
public function listCustomers(string $linkId, string $cursor = '', int $limit = 1000): array
|
||||
{
|
||||
return [
|
||||
'customer_list' => [[
|
||||
'external_userid' => $this->testExternalUserId,
|
||||
'userid' => $this->testUserId,
|
||||
'chat_status' => 2,
|
||||
'state' => 'smoke-sync',
|
||||
]],
|
||||
'next_cursor' => '',
|
||||
];
|
||||
}
|
||||
|
||||
public function getChatInfo(string $chatKey): array
|
||||
{
|
||||
return [
|
||||
'external_userid' => $this->testExternalUserId,
|
||||
'userid' => $this->testUserId,
|
||||
'chat_info' => [
|
||||
'link_id' => $this->testLinkId,
|
||||
'state' => 'smoke-chat',
|
||||
'recv_msg_cnt' => 5,
|
||||
],
|
||||
];
|
||||
}
|
||||
};
|
||||
$service = new QywxCustomerAcquisitionCustomerService($api);
|
||||
|
||||
Db::startTrans();
|
||||
try {
|
||||
$startMessage = [
|
||||
'MsgId' => 'smoke-start-' . $suffix,
|
||||
'ChangeType' => 'customer_start_chat',
|
||||
'CreateTime' => $eventTime,
|
||||
'LinkID' => $linkId,
|
||||
'ExternalUserID' => $externalUserId,
|
||||
'UserID' => $userId,
|
||||
'State' => 'smoke-start',
|
||||
];
|
||||
$service->handleCallback($startMessage);
|
||||
|
||||
$chatMessage = [
|
||||
'MsgId' => 'smoke-chat-' . $suffix,
|
||||
'ChangeType' => 'message_from_customer',
|
||||
'CreateTime' => $eventTime + 1,
|
||||
'ChatKey' => 'smoke-chat-key-' . $suffix,
|
||||
];
|
||||
$service->handleCallback($chatMessage);
|
||||
$duplicate = $service->handleCallback($chatMessage);
|
||||
$assert(($duplicate['duplicate'] ?? false) === true, '相同 message_from_customer 回调必须幂等');
|
||||
|
||||
// 远端客户列表中的 chat_status=2 是“未知”,不能把已由回调确认的状态 1 回退。
|
||||
$service->syncLink($linkId);
|
||||
|
||||
$customer = Db::name('qywx_customer_acquisition_customer')
|
||||
->where('link_id', $linkId)
|
||||
->where('external_userid', $externalUserId)
|
||||
->where('userid', $userId)
|
||||
->find();
|
||||
$assert((int) ($customer['chat_status'] ?? -1) === 1, '列表同步错误回退了已确认的聊天状态');
|
||||
$assert((int) ($customer['recv_msg_cnt'] ?? -1) === 5, '累计接收消息数不正确或被重复累加');
|
||||
$assert((int) ($customer['message_count_known'] ?? 0) === 1, '精确消息次数标识未保存');
|
||||
|
||||
$stats = WecomAcquisitionCustomerLogic::statistics(
|
||||
['keyword' => $externalUserId, 'page_size' => 20],
|
||||
(int) $admin['id'],
|
||||
$admin
|
||||
);
|
||||
$summary = $stats['summary'] ?? [];
|
||||
$assert((int) ($summary['customer_count'] ?? 0) === 1, '获客客户汇总数量不正确');
|
||||
$assert((int) ($summary['started_chat_count'] ?? 0) === 1, '已发消息客户数不正确');
|
||||
$assert((int) ($summary['received_message_count'] ?? 0) === 5, '接收消息汇总不正确');
|
||||
$assert((int) ($summary['message_count_known_count'] ?? 0) === 1, '精确消息统计覆盖数不正确');
|
||||
$row = $stats['lists'][0] ?? [];
|
||||
$assert(!array_key_exists('external_userid', $row), '接口不应返回原始客户 ExternalUserID');
|
||||
$assert(str_contains((string) ($row['external_userid_masked'] ?? ''), '*'), '客户标识没有脱敏');
|
||||
|
||||
$eventKeys = [
|
||||
QywxCustomerAcquisitionCustomerService::eventKey($startMessage, 'customer_start_chat', '', $eventTime),
|
||||
QywxCustomerAcquisitionCustomerService::eventKey(
|
||||
$chatMessage,
|
||||
'message_from_customer',
|
||||
(string) $chatMessage['ChatKey'],
|
||||
$eventTime + 1
|
||||
),
|
||||
];
|
||||
$events = Db::name('qywx_customer_acquisition_event')
|
||||
->whereIn('event_key', $eventKeys)
|
||||
->select()->toArray();
|
||||
$assert(count($events) === 2, '回调事件审计数量不正确');
|
||||
foreach ($events as $event) {
|
||||
$assert((int) ($event['status'] ?? 0) === 1, '成功回调未进入成功终态');
|
||||
$assert((string) ($event['chat_key'] ?? '') === '', '成功后仍保存了敏感 ChatKey');
|
||||
$assert(($event['raw_json'] ?? null) === null, '成功后仍保存了原始回调');
|
||||
}
|
||||
|
||||
echo "WECOM_ACQUISITION_CUSTOMER_STATISTICS_SMOKE_OK messages=5\n";
|
||||
} finally {
|
||||
Db::rollback();
|
||||
}
|
||||
Reference in New Issue
Block a user