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:
135
backend/src/modules/iit-manager/test-wechat-mp-local.ps1
Normal file
135
backend/src/modules/iit-manager/test-wechat-mp-local.ps1
Normal 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×tamp=$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 ""
|
||||
|
||||
Reference in New Issue
Block a user