This commit is contained in:
Your Name
2026-08-25 09:35:47 +08:00
parent 1f3e580cf8
commit 01c38d8c5b
13 changed files with 855 additions and 92 deletions
@@ -94,4 +94,23 @@ $assert(($customerPayload['link_id'] ?? '') === 'link_1' && ($customerPayload['l
$chatPayload = json_decode((string) $history[6]['request']->getBody(), true);
$assert(($chatPayload['chat_key'] ?? '') === 'chat_key_1', 'get_chat_info 请求体不正确');
$invalidUserService = new QywxCustomerAcquisitionApiService(new Client([
'base_uri' => 'https://qyapi.weixin.qq.com/',
'handler' => HandlerStack::create(new MockHandler([
$json(['errcode' => 60111, 'errmsg' => "invalid string value `XiongCaiQian`: userid not found"]),
])),
'http_errors' => false,
]), static fn (): string => 'mock_token');
$invalidUserMessage = '';
try {
$invalidUserService->createLink([
'link_name' => '无效成员测试',
'range' => ['user_list' => ['XiongCaiQian']],
]);
} catch (RuntimeException $e) {
$invalidUserMessage = $e->getMessage();
}
$assert(str_contains($invalidUserMessage, 'userid 不存在'), '60111 应返回明确的成员绑定诊断提示');
$assert(str_contains($invalidUserMessage, '应用可见范围'), '60111 应提示检查应用可见范围');
echo "QYWX_CUSTOMER_ACQUISITION_API_TEST_OK\n";
@@ -98,9 +98,10 @@ $encoded = QywxPromotionWidgetService::encode($xssConfig);
widgetAssert(!str_contains($encoded, '<img') && str_contains($encoded, '\\u003Cimg'), '持久化 JSON 未使用 HEX 转义');
$key = str_repeat('a', 32);
$officialUrl = 'https://work.weixin.qq.com/ca/test?customer_channel=zyt_pool:123';
$script = QywxPromotionWidgetService::renderScript(
$key,
'/api/qywx-promotion/go/' . $key,
$officialUrl,
$xssConfig,
true
);
@@ -112,8 +113,9 @@ widgetAssert(str_contains($script, '.wecom-promotion-link[data-pool'), '旧 data
widgetAssert(str_contains($script, 'w.WecomPromotion=w.WecomPromotion||{}'), '全局 WecomPromotion 注册表丢失');
widgetAssert(str_contains($script, 'open:openPromotion'), '全局 open 方法丢失');
widgetAssert(str_contains($script, 'show:show') && str_contains($script, 'hide:hide') && str_contains($script, 'destroy:destroy'), '浮窗生命周期方法不完整');
widgetAssert(str_contains($script, 'location.origin') && str_contains($script, 'location.pathname'), '来源地址未限制为 origin + pathname');
widgetAssert(!str_contains($script, 'location.href'), '公开脚本仍发送完整 location.href');
widgetAssert(str_contains($script, 'location.assign(targetUrl)'), '公开脚本没有直达企业微信官方链接');
widgetAssert(str_contains($script, 'work.weixin.qq.com/ca/test?customer_channel=zyt_pool:123'), '公开脚本缺少官方渠道链接');
widgetAssert(!str_contains($script, '?from='), '公开脚本仍追加本站跳转来源参数');
widgetAssert(str_contains($script, 'attachShadow'), '公开脚本未隔离浮窗样式');
widgetAssert(str_contains($script, 'd.currentScript') && str_contains($script, 'new w.URL(value,node.src)'), '跳转地址未从安装脚本来源解析');
widgetAssert(str_contains($script, "style.setAttribute('nonce',nonce)"), '公开脚本未向动态样式传递 CSP nonce');