From 125ff21b774589746fa0235023abab340c961d9f Mon Sep 17 00:00:00 2001 From: zpc Date: Sun, 29 Mar 2026 21:09:26 +0800 Subject: [PATCH] feat(wechat): Enforce HTTP/1.1 protocol and improve template message request handling - Set HTTP client to use HTTP/1.1 with exact version policy for WeChat API compatibility - Replace PostAsJsonAsync with manual HttpRequestMessage construction for better control - Add User-Agent and Accept headers to template message requests - Use StringContent with explicit UTF-8 encoding for JSON serialization - Update error logging to include request body and remove sensitive app secret from logs - Improve diagnostic information for template message failures --- .../Extensions/InfrastructureExtensions.cs | 2 ++ .../WeChat/WeChatService.cs | 18 +++++++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/server/src/XiangYi.Infrastructure/Extensions/InfrastructureExtensions.cs b/server/src/XiangYi.Infrastructure/Extensions/InfrastructureExtensions.cs index aa1499b..98cd27a 100644 --- a/server/src/XiangYi.Infrastructure/Extensions/InfrastructureExtensions.cs +++ b/server/src/XiangYi.Infrastructure/Extensions/InfrastructureExtensions.cs @@ -24,6 +24,8 @@ public static class InfrastructureExtensions services.AddHttpClient("WeChat", client => { client.Timeout = TimeSpan.FromSeconds(30); + client.DefaultRequestVersion = new Version(1, 1); + client.DefaultVersionPolicy = HttpVersionPolicy.RequestVersionExact; }); services.AddHttpClient("WeChatPay", client => { diff --git a/server/src/XiangYi.Infrastructure/WeChat/WeChatService.cs b/server/src/XiangYi.Infrastructure/WeChat/WeChatService.cs index 5029449..9ca5390 100644 --- a/server/src/XiangYi.Infrastructure/WeChat/WeChatService.cs +++ b/server/src/XiangYi.Infrastructure/WeChat/WeChatService.cs @@ -465,16 +465,24 @@ public class WeChatService : IWeChatService }; } - var response = await _httpClient.PostAsJsonAsync(url, requestBody); + var jsonContent = System.Text.Json.JsonSerializer.Serialize(requestBody); + var httpRequest = new HttpRequestMessage(HttpMethod.Post, url) + { + Content = new StringContent(jsonContent, Encoding.UTF8, "application/json") + }; + httpRequest.Headers.TryAddWithoutValidation("User-Agent", "XiangYi/1.0"); + httpRequest.Headers.TryAddWithoutValidation("Accept", "application/json"); + + var response = await _httpClient.SendAsync(httpRequest); var responseContent = await response.Content.ReadAsStringAsync(); // 非200时打印完整诊断信息,包括响应头 if (!response.IsSuccessStatusCode || string.IsNullOrWhiteSpace(responseContent)) { - var headers = string.Join(", ", response.Headers.Select(h => $"{h.Key}={string.Join(";", h.Value)}")); - _logger.LogWarning("发送服务号模板消息失败: StatusCode={StatusCode}, Headers={Headers}, AppId={AppId}, AppSecret={AppSecret}, ToUser={ToUser}, TemplateId={TemplateId}, AccessToken={AccessToken}, IsRetry={IsRetry}, Response={Response}", - (int)response.StatusCode, headers, _options.ServiceAccount?.AppId, _options.ServiceAccount?.AppSecret, - request.ToUser, request.TemplateId, accessToken, isRetry, responseContent); + var respHeaders = string.Join(", ", response.Headers.Select(h => $"{h.Key}={string.Join(";", h.Value)}")); + _logger.LogWarning("发送服务号模板消息失败: StatusCode={StatusCode}, Headers={Headers}, AppId={AppId}, ToUser={ToUser}, TemplateId={TemplateId}, AccessToken={AccessToken}, IsRetry={IsRetry}, RequestBody={RequestBody}, Response={Response}", + (int)response.StatusCode, respHeaders, _options.ServiceAccount?.AppId, + request.ToUser, request.TemplateId, accessToken, isRetry, jsonContent, responseContent); } // HTTP 412 表示 access_token 失效,强制刷新后重试一次