先说下项目结构:前端vue,后端laravel。
其中前端用vue-wxlogin这个组件来显示微信登录的二维码。
这个组件中的appid填写微信开放平台中的网站应用的appid,redirect_uri填写微信开放平台中的网站应用登记的授权回调域。
这个授权回调域可以和网站应用的应用官网相同,也可以不同。
只要appid和redirect_uri与网站应用中的一致,二维码就可以显示。
为了调试方便,我在本地调试时把网站应用登记的授权回调域临时修改为另一个域名(该域名做了反向隧道,不知道是否必要)。
当二维码能正常显示时说明前端没有问题了。微信扫码确认后前端页面会跳转到redirect_uri(网址赋值需要用encodeURIComponent来编码一下,否则path可能会出错,比如hash模式时path跑到问号后面去了),跳转后的url会带上code参数。
接下来我们需要用这个code来换取openid和access_token。那么这就涉及到redirect_uri应该用前端域名还是后端域名呢?
我设置的是前端域名,也就是前端的login页显示二维码,然后扫码后跳转到weixin页,读取code并向后端接口发起获取openid的请求。这样,一则前端跳转时是本域跳转,不用重新加载页面,二则,也比较符合前后端分离的模式设计。
后端在code获取openid和access_token这里,我陷入了极大的困惑。后端我引入的是overtrue/laravel-wechat,其中有open_platform的接口,我以为可以像公众号和小程序的接口那样直接调用,比如
$this->app->handleAuthorize($input['code']);
就可以搞定了,但就在这一个方法上,我浪费了一个下午的时间。
具体不展开说了,可以参考https://blog.csdn.net/qq_39859060/article/details/83512563,但其实就算有这篇文章,我还是没搞清楚到底怎么回事,这个component_verify_ticket到底有什么用呢?
最后,是按https://learnku.com/laravel/t/36118#reply164754里面提到的第一种方法实现的。简单的一个file_get_contents就搞定了。
$url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" . config('wechat.open_platform.default.app_id') .
"&secret=" . config('wechat.open_platform.default.secret') . "&code=" . $input['code'] . "&grant_type=authorization_code";
$jsonResult = file_get_contents($url);
$data = json_decode($jsonResult, true);
再次吐槽微信难道从上到下都是跟张小龙一样的狗屎脑子吗?起名字和写文档都一样乱。
为了方便调试,网站应用应该默认给一个测试网站,就像微信公众号的测试号一样。当然啊,用户可以自己申请一个当测试网站来用。可是这给开发者带来新的麻烦。