前言
众所周知,初次接触微信相关生态铁定是头疼的,用微信API第一步就得拿到微信code, 官方上说这么操作,实际业务上体现就是:需要code的页面首先得重定向到微信的授权地址上面去,并且要携带上你当前项目的域名(redirect_uri
)和AppId
还有其他同样重要的参数(response_type、scope、#wechat_redirect、state等
),授权成功后会重新重定向回你的域名上并为你的域名拼接上code。 至此一个code就到手了,能完成上面流程的代码和具体参数的意思一搜一大把,我这就不再赘述唠。今天要说的是本地开发环境中如何优雅(奇技淫巧)的获取微信code😆
痛点:痛!太痛了!
不用我说,大伙都知道,微信网页授权的过程中携带的redirect_uri
,也就是你项目的域名必须在微信公众平台里配置为网页授权域名。
实际开发中,我们至少得配置生产域名和测试域名。但真正糟心还是属本地环境下如何调试,如何去获得code, 我所知道市面上常用的法子是配置测试域名, 还有就是内网穿透。这两种方式配置都很麻烦,对于小白不是很有好。尤其后者对于没有网络基础的小白听着就有些劝退。
踩坑后的顿悟
自己刚开始接触到h5项目时,为了得到这个code,每次测试都自己部署到线上去测,只因为线上域名在公众号中配置过,也只有通过线上域名能拿到code。而且这样反复部署过于繁琐又非常不安全,太容易翻车。虽然通过配配置测试域名成功在本地拿到过code, 但后端同样需要配置,鉴定为麻烦,放弃!内网穿透,鉴定为搞不懂,放弃!😂
所以后面擅长放弃的我想了个办法,反正目的只是拿code, 用点下流(愚蠢)的手段又不是不可以:
首先我先在微信开发者工具中打开项目的线上地址,调慢网速,手动去把得到code扣下来,然后我再往我本地地址上面一复制,铛铛!完成!本地环境成功拿到了线上code!🤗
但实际这么操作几次,发现依旧蛋疼,code用一次就废了,新的code还要用上面的方式去获取一次。
所以有没有那么一种方式,不用我再手动去拿code, 再复制?也不去配置那些多余域名?也不用做那我还搞不懂的内网穿透?最好就用框架本身去解决?用js代码去解决?答案是可以的!🤩
以下是下流手段转化为优雅代码的过程
- 首先需要前往微信公众平台配置一个,合法的网页授权域名。(官网如是说)
- 开发一个名为
传送门
的组件,并将该组件挂载到前端路由上,如/portal
,然后项目部署至刚才配置过的合法域名上; - 接着封装一个
useWxCode
的hook, 它可以与传送门
相联动 useWxCode
在任何一个需要code的页面直接调用即可,生产环境下可以正常往微信授权网址跳转,并获取code,然后重定向回来。但在开发环境中,当向微信授权网址重定时,useWxCode
将会带着当前本地Url作为参数往线上的传送门
组件的路由上跳转。当跳到线上的传送门
时code其实已经到手了,而传送门
的唯一一项工作就是,将路径参数里的本地Url与code以及其他参数拼接起来作为重定向的路径并进行跳转。至此大功告成!😎
can can need code
我是在react中实现的,但主要都是以TS为主,其他任何框架稍微改改也能使用,废话少说,上代码:
传送门组件 (PortalComponent)
创建 portalComponent.tsx
,且为其注册路由。对应上面第二个步骤,
该组件的作用是:路径中存在code时,将路径参数里的本地Url与code以及其他参数拼接起来作为重定向的路径并进行跳转。
PortalPath 为传送门组件的 路由名 + ?
,传送门组件与hook都会用到该参数参与路径拼接,所以建议写在公共配置文件中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| const PortalPath = 'portal?'; export default function PortalComponent() { const code = React.useRef<string>(geUrlParam(location.href)?.['code']); React.useEffect(() => { if (code.current) { const hash = '#/';
const originalUrl = decodeURIComponent(location.href.split(PortalPath)[1]); const redirectUrl = originalUrl.split(hash)[0] + `?code=${code.current}` + hash + originalUrl.split(hash)[1]; window.location.href = redirectUrl; } }, []); return <LoadingComponent />; }
|
| { path: '/portal', component: () => import('./portal-component/portal.component'), lazyload: true, exact: true }
|
获取Url中参数的方法
| function geUrlParam(search: string) { const param: Record<string, any> = {}; search.replace(/([^&=?]+)=([^&]+)/g, (m, $1, $2) => (param[$1] = $2)); return param; }
|
useWxCode (hook)
创建 useWxCode.ts
。对应上面第三个步骤
此hook,封装了自动获取微信code的逻辑代码,也暴露了code, wxLoading等状态, 以及刷新code的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| export const PortalPath = 'portal?';
export const WxState = { wxLoading: true };
export interface WxCodeHookOpt { route: string; getCodeAfterFn?: (code: string) => void; isPreGetCode?: boolean; scope?: 'snsapi_userinfo' | 'snsapi_base'; }
export interface WxCodeHookRes { code: string; refreshCode: () => void; wxLoading: boolean; }
export function useWxCode(wxCodeHookOpt: WxCodeHookOpt): WxCodeHookRes { const [state, setState] = useState(WxState); const { wxLoading } = state; const { route, getCodeAfterFn, isPreGetCode = true, scope = 'snsapi_userinfo' } = wxCodeHookOpt; const code = useRef<string>(); useEffect(() => { code.current = geUrlParam(location.href.split('#/')[0])['code']; if (code.current) { setState({ wxLoading: false }); getCodeAfterFn && getCodeAfterFn(code.current); } else { isPreGetCode ? refreshCode() : setState({ wxLoading: false }); } }, []);
function refreshCode() { const noCodeUrl = location.href.split('?code=')[0] + location.hash; const devHref = code.current ? noCodeUrl : location.href; const devGetCodePath = PortalPath + devHref; const routePath = process.env.NODE_ENV === 'development' ? devGetCodePath : route; const str = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${ process.env.appId }&redirect_uri=${encodeURIComponent( process.env.REDIRECT_URL + routePath )}&response_type=code&scope=${scope}&state=123#wechat_redirect`; window.location.href = str; }
return { refreshCode, code: code.current, wxLoading };
|
使用
在任何需要使用微信code的页面,直接调用 useWxCode
即可!暴露的 code, wxLoading, refreshCode
,可以满足你后续代码有关code的任何需求!
| const { code, wxLoading, refreshCode } = useWxCode({ route: 'home' });
|
使用useWxCode后,开发环境会重定向到线上的[传送门]组件中获取code,获取code后再带着code返回源地址; 正式环境则直接跳微信授权网址获取code
效果
从此开发h5页面,只需配置一个公众号授权域名,无论测试环境,还是本地开发环境,只需添加如上代码,获取code,就是这么丝滑~

最后的最后
这里是萌新小把子,这是我第一篇技术文章,期待各位大佬狠狠的指点~!😆