0x00 问题描述
微信支付完成之后,回调修改数据状态一直没有修改成功,因为只有生产环境才能有支付回调所以只能查看日志;通过wathDog发现响应体一直是"付款通知签名验证失败";将请求包复制,直接打本地开发环境打请求;
0x01 项目环境包配置
<PackageReference Include="Senparc.Weixin.MP.MVC" Version="7.12.13" />
<PackageReference Include="Senparc.Weixin.Open" Version="4.15.0" />
<PackageReference Include="Senparc.Weixin.Work" Version="3.16.4" />
<PackageReference Include="Senparc.Weixin.WxOpen" Version="3.16.4" />
<PackageReference Include="Senparc.Weixin.TenPay" Version="1.12.14" />
<PackageReference Include="Senparc.Weixin.TenPayV3" Version="0.7.10.4" />
0x02 回调接口代码
[AllowAnonymous]
[HttpPost]
[Route("pay-notify/{appId}/{mchId}")]
public async Task<string> PayNotifyAsync(string appId, string mchId)
{
ResponseHandler resHandler = new ResponseHandler(HttpContext);
var notifyXml = resHandler.ParseXML();
Logger.LogInformation("支付回调:" + notifyXml);
var profileId = $"{appId}.{mchId}";
var tenPayV3Info = Config.SenparcWeixinSetting.Items[profileId];
resHandler.SetKey(tenPayV3Info.TenPayV3_Key);
if (!resHandler.IsTenpaySign()) return FailResponse($"付款通知签名验证失败");
return SuccessResponse();
}
0x03 发送给微信支付的回调url
var queryString = QueryString.Create("__tenant", CurrentTenant.Id.ToString());
var payNotifyUrl = tenPayV3Info.TenPayV3_TenpayNotify + $"/{request.AppId}/{request.MchId}" + queryString.ToUriComponent();
var xmlDataInfo = new TenPayV3UnifiedorderRequestData(tenPayV3Info.TenPayV3_AppId, tenPayV3Info.TenPayV3_MchId, tenPayV3Info.TenPayV3_SubAppId, tenPayV3Info.TenPayV3_SubMchId, body, request.OutTradeNo,
price, _webClientInfoProvider.ClientIpAddress, payNotifyUrl, TenPayV3Type.JSAPI, payerOpenId.OpenId, payerOpenId.SubOpenId, tenPayV3Info.TenPayV3_Key, nonceStr,
timeExpire: request.Expiration?.DateTime, attach: request.Attach);
0x04 问题原因
1.通知url拼接了租户ID,将租户ID放到了请求头QueryString中
2.盛派SDK中的ResponseHandler传入了请求上下文;内部读取了Query头,导致租户id参与编码校验
3.此处的appid与mch_id因为在Route参数中,不参与编码校验;所以不会冲突
0x05 解决方案
如需传参请修改为路由传参或者重写ResponseHandler类,在验证签名之前将参数移除;