以下基于
wxLogin.js
在React
应用中使用案例
实验环境
- antd:
^5.14.1
- next:
14.1.0
- react:
^18
组件调用示例
"use client";
import { useEffect, useState } from "react";
import { WechatChannel } from "./channel";
export default function ThirdForm() {
function handleWeChatLoad(){
console.log("载入完成")
}
return (
<>
<WechatChannel
appid={"xxxxx"}
redirectUri="https%3A%2F%2Fblog.csdn.net%2Fu011159821"
onLoad={handleWeChatLoad}
/>
</>
);
}
由于是基于
ts
开发,下面根据《网站应用微信登录开发指南》中的参数说明,编写简易声明文件
// file: type.d.ts
export type WeChatSdkParam = {
self_redirect?: boolean;
id: string;
appid: string;
scope: string | "snsapi_login";
redirect_uri: string;
state?: string | "";
style?: "black" | "white";
href?: string;
stylelite?: "1";
fast_login?: "1" | "0";
};
export type WeChatSDK = (param: WeChatSdkParam) => void;
参数 | 是否必须 | 说明 |
---|---|---|
self_redirect | 否 | true :手机点击确认登录后可以在 iframe 内跳转到 redirect_uri,false :手机点击确认登录后可以在 top window 跳转到 redirect_uri。默认为 false 。 |
id | 是 | 第三方页面显示二维码的容器id |
appid | 是 | 应用唯一标识 ,在微信开放平台提交应用审核通过后获得 |
scope | 是 | 应用授权作用域,拥有多个作用域用逗号(,)分隔, 网页应用目前仅填写 snsapi_login 即可 |
redirect_uri | 是 | 重定向地址,需要进行UrlEncode |
state | 否 | 用于保持请求和回调的状态,授权请求后原样带回给第三方。 该参数可用于 防止csrf攻击(跨站请求伪造攻击) ,建议第三方带上该参数 ,可设置为简单的随机数加session进行校验 |
style | 否 | 提供"black "、"white "可选,默认为黑色文字描述 |
href | 否 | 自定义样式链接,第三方可根据实际需求覆盖默认样式,stylelite不为1时有效 。(此处传入css样式文件的url路径) |
stylelite | 否 | 切换二维码登录样式,值为1时二维码登录将切换到新样式。 |
fast_login | 否 | 启用或禁用快速登录功能,值为0时将禁用快速登录。 |
组件封装代码
Ps:
fetchResource
是异步文件载入的封装处理方法,可以上网搜,不在本章内容里
// channel/WeChatLogin/index.tsx
import type { WeChatSDK, WeChatSdkParam } from "./type.d";
import { useCallback, useEffect, useState } from "react";
import { QRCode } from "antd";
import FetchResource from "@/utils/network/fetchResource";
type ChannelProps = {
appid: string;
redirectUri: string;
disabled?: boolean;
onLoad?: () => void;
onLoadError?: (e: any) => void;
};
const elIdName = "login_container";
const FResource = FetchResource.getInstance();
const channel = function (props: ChannelProps) {
const [disabled, setDisabled] = useState<boolean>(false);
// 资源初始化
const initWeChatSDK = useCallback(
(param: WeChatSdkParam) => {
return new Promise((resolve, reject) => {
FResource.load({
url: "https://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js",
}).then(() => {
// @ts-ignore
const wxLogin: WeChatSDK | undefined = window?.WxLogin || undefined;
if (wxLogin) {
resolve(wxLogin(param));
} else {
reject("WeChat SDK Not Found");
}
});
});
},
[elIdName]
);
useEffect(() => {
const _disabled =
typeof props.disabled === "boolean" ? props.disabled : false;
setDisabled(_disabled);
if (_disabled === false) {
// 初始化WeChat网页版的SDK
initWeChatSDK({
id: elIdName,
appid: props.appid,
scope: "snsapi_login",
state: "xxxxxx",
href: "https://xxx.xxx.com/assets/css/wx.css",
redirect_uri: props.redirectUri
self_redirect: false,
})
.then(() => {
// 初始化完成
props.onLoad && props.onLoad();
})
.catch((err) => {
// 初始化失败或异常
props.onLoadError && props.onLoadError(err);
});
}
return () => {
setDisabled(true);
};
}, [props]);
return (
<>
{!disabled && <div id={elIdName}></div>}
{disabled && (
<>
<QRCode
type={"canvas"}
value={"https://ant.design"}
status="expired"
size={350}
bordered={false}
/>
</>
)}
</>
);
};
export const WechatChannel = channel;
export default channel;