feat(iit-manager): Add WeChat Official Account integration for patient notifications

Features:
- PatientWechatCallbackController for URL verification and message handling
- PatientWechatService for template and customer messages
- Support for secure mode (message encryption/decryption)
- Simplified route /wechat/patient/callback for WeChat config
- Event handlers for subscribe/unsubscribe/text messages
- Template message for visit reminders

Technical details:
- Reuse @wecom/crypto for encryption (compatible with Official Account)
- Relaxed Fastify schema validation to prevent early request blocking
- Access token caching (7000s with 5min pre-refresh)
- Comprehensive logging for debugging

Testing: Local URL verification passed, ready for SAE deployment

Status: Code complete, waiting for WeChat platform configuration
This commit is contained in:
2026-01-04 22:53:42 +08:00
parent dfc472810b
commit b31255031e
167 changed files with 3055 additions and 2 deletions

View File

@@ -0,0 +1,135 @@
# 微信服务号URL验证本地测试脚本
# 模拟微信服务器发送GET请求
Write-Host "🧪 微信服务号URL验证本地测试" -ForegroundColor Cyan
Write-Host "=" * 60
Write-Host ""
# 配置参数
$BASE_URL = "https://devlocal.xunzhengyixue.com/wechat/patient/callback"
$TOKEN = "IitPatientWechat2026JanToken"
# 生成测试参数
$timestamp = [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds().ToString()
$nonce = -join ((65..90) + (97..122) | Get-Random -Count 10 | ForEach-Object {[char]$_})
$echostr = "test_echo_" + (-join ((65..90) + (97..122) + (48..57) | Get-Random -Count 10 | ForEach-Object {[char]$_}))
Write-Host "📝 测试参数:" -ForegroundColor Yellow
Write-Host " timestamp: $timestamp"
Write-Host " nonce: $nonce"
Write-Host " echostr: $echostr"
Write-Host ""
# 生成签名
Write-Host "🔐 生成签名..." -ForegroundColor Yellow
$sortedArray = @($TOKEN, $timestamp, $nonce) | Sort-Object
$stringToHash = $sortedArray -join ''
$sha1 = [System.Security.Cryptography.SHA1]::Create()
$hashBytes = $sha1.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($stringToHash))
$signature = ($hashBytes | ForEach-Object { $_.ToString("x2") }) -join ''
Write-Host " 排序后拼接: $($stringToHash.Substring(0, [Math]::Min(50, $stringToHash.Length)))..."
Write-Host " SHA1哈希: $signature"
Write-Host ""
# 构建完整URL
$fullUrl = "$BASE_URL`?signature=$signature&timestamp=$timestamp&nonce=$nonce&echostr=$echostr"
Write-Host "📤 发送GET请求..." -ForegroundColor Yellow
Write-Host " URL: $fullUrl" -ForegroundColor Gray
Write-Host ""
# 发送请求忽略SSL证书警告
try {
# 忽略SSL证书错误仅用于测试
add-type @"
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class TrustAllCertsPolicy : ICertificatePolicy {
public bool CheckValidationResult(
ServicePoint srvPoint, X509Certificate certificate,
WebRequest request, int certificateProblem) {
return true;
}
}
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
$response = Invoke-WebRequest -Uri $fullUrl -Method Get -UseBasicParsing
Write-Host "=" * 60
Write-Host ""
Write-Host "✅ 请求成功!" -ForegroundColor Green
Write-Host ""
Write-Host "HTTP状态码: $($response.StatusCode)" -ForegroundColor Green
Write-Host "返回内容类型: $($response.Headers['Content-Type'])" -ForegroundColor Green
Write-Host "返回内容: $($response.Content)" -ForegroundColor Green
Write-Host ""
if ($response.Content -eq $echostr) {
Write-Host "✅ 返回的echostr正确验证通过" -ForegroundColor Green
Write-Host ""
Write-Host "=" * 60
Write-Host ""
Write-Host "🎉 测试成功!服务端配置正确" -ForegroundColor Green
Write-Host ""
Write-Host "📝 这说明:" -ForegroundColor Cyan
Write-Host " 1. ✅ natapp映射正常"
Write-Host " 2. ✅ 后端路由正确"
Write-Host " 3. ✅ 签名验证正确"
Write-Host " 4. ✅ 返回格式正确"
Write-Host ""
Write-Host "⚠️ 但微信配置失败的原因可能是:" -ForegroundColor Yellow
Write-Host " 1. 域名devlocal.xunzhengyixue.com未在微信公众平台配置"
Write-Host " 2. 微信服务器无法访问这个域名"
Write-Host " 3. 建议使用生产域名iit.xunzhengyixue.com"
Write-Host ""
} else {
Write-Host "❌ 返回的echostr不正确" -ForegroundColor Red
Write-Host " 期望: $echostr" -ForegroundColor Red
Write-Host " 实际: $($response.Content)" -ForegroundColor Red
}
} catch {
Write-Host "=" * 60
Write-Host ""
Write-Host "❌ 请求失败" -ForegroundColor Red
Write-Host ""
Write-Host "错误信息: $($_.Exception.Message)" -ForegroundColor Red
Write-Host ""
if ($_.Exception.Response) {
$statusCode = $_.Exception.Response.StatusCode.value__
Write-Host "HTTP状态码: $statusCode" -ForegroundColor Red
if ($statusCode -eq 400) {
Write-Host ""
Write-Host "可能原因:" -ForegroundColor Yellow
Write-Host " 1. Schema验证失败需要检查路由配置"
Write-Host " 2. 参数格式不正确"
} elseif ($statusCode -eq 403) {
Write-Host ""
Write-Host "可能原因:" -ForegroundColor Yellow
Write-Host " 1. 签名验证失败"
Write-Host " 2. Token配置不匹配"
} elseif ($statusCode -eq 404) {
Write-Host ""
Write-Host "可能原因:" -ForegroundColor Yellow
Write-Host " 1. 路由未注册"
Write-Host " 2. URL路径不正确"
}
}
Write-Host ""
Write-Host "排查建议:" -ForegroundColor Cyan
Write-Host " 1. 确认后端服务正在运行"
Write-Host " 2. 确认natapp正在运行"
Write-Host " 3. 访问健康检查接口:"
Write-Host " https://devlocal.xunzhengyixue.com/api/v1/iit/health"
Write-Host " 4. 查看后端服务日志"
Write-Host ""
}
Write-Host ""