前言

最近在调试微信相关的接口,但是由于微信官方出于安全的考虑,对于调用接口的域名有限制。微信授权与微信支付统一下单接口在本地可以通过更改 host 的方式来调试,微信服务器也能跳转回来,但是微信支付异步通知这里;微信官方强制让设置支付授权目录,且是通过 ICP 备案的域名,因此不采取特殊手段,本地是无法接收到微信的异步通知回调请求的,只能部署到线上环境测试

前置条件

为了解决这个问题,折腾了好几天,才搞出来了,究其根本原因,还是对于 Nginx 不太熟悉。所以在此记录一下。

内网转发

如果想本地进行调试,并且想让微信服务器请求回调回来,则本地必须要有一个外网域名,这里我们是用 Ngrok内网转发 来实现;Ngrok 的配置就是将本地项目的端口映射到分配的外网域名,具体配置参考官网教程文档,此处不再赘述。

我的配置是:

1
http://vcmq.free.ngrok.cc -> 127.0.0.1:8080

配置测试支付目录

前面提到了,微信支付异步通知会对支付域名目录有要求,因此,支付时的域名必须要在设置的支付域名目录下。

首先需要在 微信商户平台 中配置 商户秘钥,支付授权目录。

mark

这里支付授权目录配置的是以后线上的支付授权目录

1
http://pay.domain.com/wechat/public/

然后再加一条本地测试支付的临时授权目录,这个目录最好在本地测试完成后,进行删除。

1
http://pay.domain.com/testpay/

必知的 Nginx 语法

proxy_pass 后的 url 加不加 / 的区别

这里列举 nginx 的 proxy_pass 语法,是为了下一步针对 nginx 的配置进行修改。

这里访问 http://127.0.0.1/proxy/test.html 测试 proxy_pass 后面的 url 加与不加 / 的区别

1
2
3
4
5
6
7
8
server {
listen 80;
server_name 127.0.0.1;

location /proxy/ {
proxy_pass http://192.168.0.100/;
}
}

以上 location 会代理到 http://192.168.0.100/test.html 即相当于是绝对根路径,则 Nginx 不会把 location 中的路径部分代理走。

1
2
3
4
5
6
7
8
server {
listen 80;
server_name 127.0.0.1;

location /proxy/ {
proxy_pass http://192.168.0.100;
}
}

以上 location 会代理到 http://192.168.0.100/proxy/test.html 即相当于相对路径。


代理支付域名到第三方域名

知道上一步 proxy_pass 后 / 的作用后,就开始来配置支付域名指向的服务器上的 nginx 的配置文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
server {
listen 80;
server_name pay.domain.com;

location /testpay/ {
proxy_set_header Host vcmq.free.ngrok.cc;
proxy_pass http://vcmq.free.ngrok.cc/wide/;
}

location / {
proxy_pass http://payServer;
}
}

配置中的 wide 是我项目的名称;
注意:这里的 proxy_set_header Host 必须配置,否则进入 location 块后,会提示 tunnel pay.domain.com not found

当访问 pay.domain.com/testpay/create 微信统一下单接口时, 会代理到 http://vcmq.free.ngrok.cc/wide/create

需要注意的是,在统一下单接口,设置 notify_url 的值要为配置的支付授权目录,比如我的 http://pay.domain.com/testpay/notify,这个异步通知回调 URL 限定是 POST 请求,可以在异步回调方法打断点,然后通过 postman 工具发送 post 请求到 http://pay.domain.com/testpay/notify,看是否可以正常进入断点,如果正常进入断点,恭喜你配置好了 Nginx 回调这一块。

注意: 统一下单接口参数中提交的参数 notify_url ,如果链接无法访问,商户将无法接收到微信通知。
通知 url 必须为直接可访问的 url ,不能携带参数。示例:notify_url:“https://pay.weixin.qq.com/wxpay/pay.action”

另外要注意,如果支付目录中配置的是 https 的,那么 notify_url 也一定要保持一致是 https 的。

统一下单并完成支付完成后,微信服务器会请求统一下单接口中的 notify_url,经过服务器 nginx 进行代理后,会代理到 本地的内网转发域名异步通知回调接口 http://vcmq.free.ngrok.cc/wide/notify, 从而达到了本地接收微信支付异步通知回调请求的目的。

如果地址不在支付授权目录下,会提示当前 Url 未注册。因为是代理过去,因此地址栏的地址不会改变,这也是不能简单使用 nginx 的 rewrite 的原因。

如有疑问,可以联系我。

参考