利用nginx变通的解决跨域问题
背景 Link to heading
支付宝商家会员卡业务有两种开卡方式(此处不考虑最新的spi方式)
- 支付宝app扫投放链接获取会员卡
- 支付宝小程序通过会员卡参数直接拉起小程序开卡组件
这两个方式在用户填写表单之后都会向指定回调地址中发送一个get请求,并等待成功返回
如果为了兼容上面两种开卡方式,最优选择应该是后端接收到支付宝的get请求后,通过out_string判断是由什么渠道发起的
- 若浏览器发起,在开卡业务完成后,返回
301/302重定向应答,让支付宝app重定向到一个前端页面进行展示 - 若小程序发起,则返回应答成功的业务报文即可
可是目前我们后端框架暂时无法支持向前端返回301/302这种重定向应答,于是我们暂时只支持了小程序开卡方式
一天支付宝业务人员突然说,他们需要h5扫码方式开会员卡,印刷并张贴在商户门店中,做一些运营活动,很突然,并且当天就要,还要app端跳转到卡包中,于是有了后面的一些操作
解决方案 Link to heading
难点 Link to heading
如上文所说,我们后端并不支持返回301/302应答码,同时也不能导致支付宝小程序发卡失败,那么我们就只有一个方法解决问题,分成两个步骤:
- 写一个中转页面,在h5模式下,支付宝app会解析html页面,于是中转页面中不需要有任何的界面,业务也比较简单
- 获取
get请求中的query参数 - 将参数作为
get参数发送给后端 - 获取请求结果
- 若应答成功,
herf到指定scheme_url中
- 由于紧急,并且公司内部的一些原因,要在公司主域名下发这个中转页面变得不太现实,于是引发了另外一个问题,跨域
解决 Link to heading
- 解决第一个问题非常方便,找了个前端,花几分钟完成了核心代码,一个html文件解决
- 第二个问题曾一度陷入死胡同,最后一句闲聊启发了我,为了避免跨域,html只能向自己域发起请求,那么我只需要找个东西在html的域下把
get请求转发到后端就可以了,查阅了文档后,直接使用nginx即可做到location /ali { #判断$query_string中是否有web标识 if ( $query_string ~* ".*ali_web_redirect.*" ) { #有web标识,则跳转到中转页面 return 301 https://$http_host/redirect/redirect.html?$query_string; } #没有则直接向后端发送请求 proxy_pass https://www.host.com/api/member/open/alipay/opencard; } location /redirect/ { root /opt/www/ali-redirect; index index.html index.htm; } #这个是中转页面发起的请求,此域名收到后,会转发到公司后端 location ^~ /api/ { proxy_pass https://www.host.com; }