(转:https://www.cnblogs.com/lyzg/p/6159617.html)php
在作项目集成微信登陆以及微信支付的时候,都须要进行用户受权。这个受权的流程能够简单描述为:
1. 用户从咱们的应用触发须要受权的操做,好比点击微信登陆;
2. 应用收到这种用户请求后,将用户重定向到微信提供的一个受权页面: 或
3. 用户经过微信扫码(PC端受权,上边左图)或者点击确认按钮(移动端受权,上边右图)告知微信,受权应用访问本身的微信帐号信息;
4. 微信收到用户的受权许可后,生成受权码,并把它做为参数回调至应用的某个页面;
5. 应用的回调页面在接收到微信的回调请求后,拿到其中的受权码,并经过微信官方提供的access token api接口获取access token;
6. 最后经过access token以及微信官方提供的另外一个userinfo api接口就能获取到用户的微信帐号信息。html
为了实现这个过程,首先要为应用申请一个微信公众号,并将应用最终部署的域名设置到微信公众号设置里面的受权回调页面域名这个选项里面。微信官方对这个选项的说明以下:git
关于网页受权回调域名的说明github
一、在微信公众号请求用户网页受权以前,开发者须要先到公众平台官网中的“开发 - 接口权限 - 网页服务 - 网页账号 - 网页受权获取用户基本信息”的配置选项中,修改受权回调域名。请注意,这里填写的是域名(是一个字符串),而不是URL,所以请勿加 http:// 等协议头;api
二、受权回调域名配置规范为全域名,好比须要网页受权的域名为:www.qq.com,配置之后此域名下面的页面http://www.qq.com/music.html 、 http://www.qq.com/login.html 均可以进行OAuth2.0鉴权。但http://pay.qq.com 、 http://music.qq.com 、 http://qq.com没法进行OAuth2.0鉴权微信
三、若是公众号登陆受权给了第三方开发者来进行管理,则没必要作任何设置,由第三方代替公众号实现网页受权便可架构
因而可知,这个规则极其严格。若是说咱们的应用最终部署的时候只有一个域名,那么这种规则不会有什么问题;可是考虑到未来应用的复杂性,咱们可能在应用设计之初就会对应用作拆分,而后不一样的业务采用不一样的二级域名来部署。好比一个带有交易的应用,你可能会把登陆注册,交易管理和常规业务都独立出来,而后采用如下的方式来部署它们:
www.your.com 部署常规业务;
trade.your.com 部署交易管理的业务;
passport.your.com 部署登陆注册的业务;
在这种模式下,若是集成微信登陆和微信支付,前面说的受权回调页面域名的规则就会给应用带来问题。在这里:至少能够确认trade.your.com和passport.your.com都须要前面的介绍的用户微信受权,可是它们是两个不一样的子域名,并且咱们只有一个公众号;根据受权回调页面域名的原则,它只能用一个域名,而且只有回调地址的域名与该设置彻底相同,才能成功发起微信受权,不然就会提示rediret_uri参数错误或者引起没法回调的问题。app
那么这种状况该如何处理?测试
当下的解决方案是引入一个新的很是简单的应用来做为微信受权的代理服务,能够这么作:
1. 把公众号的网页受权接口域名设置成另一个子域名,如proxy.your.com;
2. 而后把php_weixin_proxy里面的index.php部署到proxy.your.com微信支付
php_weixin_proxy下的index.php是一个很简单的php文件,你能够直接查看源码了解它的实现方式。由于当前项目的环境,我采用php来完成这个代理服务实现,实际上,你彻底能够用任意平台语言来完成相似的功能。
当其它业务须要发起微信受权时,将受权请求先发到proxy.your.com,而后proxy.your.com会把这个请求转发到微信;
当用户赞成受权后,proxy.your.com会收到微信的受权回调,并把回调结果(code、state参数)原封不动地再返回给最开始发起受权的业务。
惟一的区别在于,在不使用proxy.your.com的时候,你从应用发起微信受权的连接应该是这样的:
https://open.weixin.qq.com/connect/qrconnect?appid=xxxxx&redirect_uri=http%3A%2F%2Fpassport.your.com%2F&response_type=code&scope=snsapi_login&state=584bc87e11ff37492#wechat_redirect
用了proxy.your.com以后,这个受权连接就应该是这样的:
http://proxy.your.com/?appid=xxxxx&redirect_uri=http%3A%2F%2Fpassport.your.com%2Flogin%2Fnotify&response_type=code&scope=snsapi_base&state=584bc87e11ff37492&device=pc
后面这个连接跟上面的比:
1. 后面的连接中的host变成了proxy.your.com,也就是代理的受权回调域名;
2. 后面的多了一个device参数,这个是必要的。由于微信pc端跟移动端的受权地址是不同的,然后面的连接是发送个proxy.your.com的,因此须要多加个参数告诉它在转发给受权申请给微信的时候,是用PC端仍是移动端的受权地址。
总体方案思路:
小结:
这个方案我测试过,是行的通的。虽说引入了代理服务,增长了一次重定向操做,不过因为这个受权请求并非全部请求都须要,因此实际上也不会对用户体验产生多大的影响,可是从架构上来讲,它的好处很明显,可以配合着应用的拆分逻辑,集成同一个公众号的登陆及支付功能,没必要为每一个子应用都单独申请一个公众号来开发了(这种方式从业务上来讲也不合理,一个公司哪须要运营那么多公众号)。