React Native Expo版本的微信SDK。基本实现了所有的微信官方SDK的功能,包括支付、登录、分享、客服、跳转小程序等。支持安卓和iOS。 本框架旨在让你所有原生代码配置都在RN侧以及json文件中进行,真正做到0原生代码配置,充分利用expo的优势来做到简单好用。
npx expo install expo-wechat
# 不带支付版本
# npx expo install expo-wechat-no-payiOS需要配置通用链接和URL Scheme。
什么是URL Scheme和通用链接?简单来说这就是iOS上微信授权完成后,跳回你的app的两种途径。 URL Scheme用于给你的应用注册一个独一无二的链接,使别的软件可以通过这个链接直接唤起你的App。 是微信回调起你的App的保底方案,当通用链接唤起失败后,微信会尝试使用URL Scheme来唤起你的App。这个URL Scheme就是微信开放平台给你的微信id,类似于
wx1234567890这种格式的。通用链接是微信首推的唤起微信和你的App的方案,当通用链接没有配置好的时候,才会回退到URL Scheme方案。 通用链接允许你向苹果注册一个URL地址,当访问这个地址的时候,系统优先唤起你的App,而不是网页。简单来说,它是一种比URL Scheme更好的唤起App的解决方案。
使用Expo官方提供的方式来添加URL Scheme,以及配置通用链接。在app.json或app.config.js中添加以下字段:
"ios": {
"scheme": [
"wx1234567890"
],
"associatedDomains": [
"applinks:example.com"
]
}这里的通用链接如何生成,以及如何向苹果注册,也许你需要参照一下苹果官方文档。
URL Scheme白名单,也就是
LSApplicationQueriesSchemes字段,因为是固定不变的,插件已经自动帮你配置好了。
在安卓上,你需要配置微信的混淆规则,以免打包时将微信的框架代码排除在外而报错。 微信所需的proguard混淆规则内容如下:
-keep class com.tencent.mm.opensdk.** {
*;
}
-keep class com.tencent.wxop.** {
*;
}
-keep class com.tencent.mm.sdk.** {
*;
}
需要利用Expo BuildProperties,在app.json或app.config.js中添加以下内容:
"plugins": [
[
"expo-build-properties",
{
"android": {
"extraProguardRules": "把以上规则内容放到这里",
},
}
]配置部分,iOS需要配置URL Scheme和通用链接,安卓需要配置混淆规则。最后需要添加expo-wechat的config plugin:
"plugins": [
"expo-wechat"
]注意这里的plugins对象跟上面的expo-build-properties的是同一个对象。
这些是全部的配置项了,都可以通过expo的app.json或app.config.js来完成,配置部分完成后,就可以正常使用微信SDK了。
请注意,由于包含了自定义的原生代码,无法在expo go中直接使用。你应该使用npx expo run:android或者npx expo run:ios,编译原生app。详情参见官方DevClient文档。
import ExpoWeChat from 'expo-wechat'
/// 初始化微信SDK。一般都在用户接受了隐私政策后,调用此方法。
const result = await ExpoWeChat.registerApp(wechatAppId, universalLink);| 属性名 | 类型 | 说明 |
|---|---|---|
isRegistered |
boolean |
是否已经成功调用registerApp方法 |
registerApp(appId: string, universalLink: string): Promise<boolean>初始化微信SDK。返回初始化结果。
参数:
appId: 微信App IDuniversalLink: 通用链接地址(iOS必需)
返回值: Promise<boolean> - 初始化是否成功
isWXAppInstalled(): Promise<boolean>检查用户是否已安装微信客户端。
返回值: Promise<boolean> - 是否已安装微信
getApiVersion(): Promise<string>获取微信SDK的版本号。
返回值: Promise<string> - SDK版本号
getWXAppInstallUrl(): Promise<string | null>获取微信安装的URL。
返回值: Promise<string | null> - 安装URL或null
openWXApp(): Promise<boolean>打开微信App。
返回值: Promise<boolean> - 打开是否成功
checkUniversalLinkReady(): Promise<void>启动微信自检流程,打印自检日志。
注意: iOS Only
sendAuthRequest(
scope: "snsapi_userinfo" | string,
state: string
): Promise<boolean>发送微信授权登录请求。
参数:
scope: 微信scope字段,如snsapi_userinfostate: 微信state字段,用于维持请求和回调的状态
返回值: Promise<boolean> - 请求是否发送成功
注意: 此方法返回的是请求发送结果,不是授权结果。授权结果需通过监听onAuthResult事件获取。
sendAuthByQRRequest(options: AuthByQROptions): Promise<string>发送微信扫码登录请求。
参数:
interface AuthByQROptions {
appId: string; // 微信App ID
appSecret: string; // 微信App Secret
scope: "snsapi_userinfo" | string; // 授权范围
schemeData?: string; // 可选的scheme数据
}返回值: Promise<string> - 二维码base64编码的图片数据
shareText(text: string, scene: ShareScene): Promise<boolean>分享文字到微信。
参数:
text: 要分享的文字内容scene: 分享目标场景 ('session' | 'timeline' | 'favorite' | 'status' | 'specifiedContact')
返回值: Promise<boolean> - 分享请求是否发送成功
shareImage(options: ShareImageOptions): Promise<boolean>分享图片到微信。
参数:
interface ShareImageOptions {
base64OrImageUri: string; // 图片内容(本地URI或base64)
scene: ShareScene; // 分享场景
thumbBase64OrImageUri?: string; // 缩略图内容(可选)
imageDataHash?: string | null; // 图片哈希值(可选)
miniProgramId?: string | null; // 小程序原始id(可选)
miniProgramPath?: string | null; // 小程序路径(可选)
}返回值: Promise<boolean> - 分享请求是否发送成功
shareFile(
base64OrFileUri: string,
title: string,
scene: ShareScene
): Promise<boolean>分享文件到微信。
参数:
base64OrFileUri: 文件内容(本地URI或base64)title: 文件标题scene: 分享目标场景
返回值: Promise<boolean> - 分享请求是否发送成功
shareMusic(options: ShareMusicOptions): Promise<boolean>分享音乐到微信。
参数:
interface ShareMusicOptions {
musicWebpageUrl: string; // 音乐网页URL
musicFileUri: string; // 音乐文件URI
singerName: string; // 歌手名称
duration: number; // 音乐时长(秒)
scene: ShareScene; // 分享场景
songLyric?: string; // 歌词(可选)
hdAlbumThumbFilePath?: string; // 高清专辑缩略图文件路径(安卓)
hdAlbumThumbBase64OrImageUri?: string; // 高清专辑缩略图(iOS)
hdAlbumThumbFileHash?: string; // 高清专辑缩略图文件哈希值
albumName?: string; // 专辑名称
title?: string; // 标题(可选)
description?: string; // 描述(可选)
thumbBase64OrImageUri?: string; // 缩略图(可选)
}返回值: Promise<boolean> - 分享请求是否发送成功
shareVideo(options: ShareVideoOptions): Promise<boolean>分享视频到微信。
参数:
interface ShareVideoOptions {
videoUri: string; // 视频文件URI
scene: ShareScene; // 分享场景
lowQualityVideoUri?: string; // 低质量视频URI(可选)
thumbBase64OrImageUri?: string; // 缩略图(可选)
title?: string; // 标题(可选)
description?: string; // 描述(可选)
}返回值: Promise<boolean> - 分享请求是否发送成功
shareWebpage(options: ShareWebpageOptions): Promise<boolean>分享网页到微信。
参数:
interface ShareWebpageOptions {
url: string; // 网页URL
scene: ShareScene; // 分享场景
title?: string; // 标题(可选)
description?: string; // 描述(可选)
thumbBase64OrImageUri?: string; // 缩略图(可选)
extraInfo?: string; // 额外信息(可选)
}返回值: Promise<boolean> - 分享请求是否发送成功
shareMiniProgram(options: ShareMiniProgramOptions): Promise<boolean>分享小程序到微信。
参数:
interface ShareMiniProgramOptions {
id: string; // 小程序原始id
type: WeChatMiniProgramType; // 小程序类型 ('release' | 'test' | 'preview')
path?: string; // 小程序路径(可选)
scene: ShareScene; // 分享场景
webpageUrl?: string; // 网页URL(可选)
title?: string; // 标题(可选)
description?: string; // 描述(可选)
thumbBase64OrImageUri?: string; // 缩略图(可选)
withShareTicket?: boolean; // 是否携带shareTicket(可选)
}返回值: Promise<boolean> - 分享请求是否发送成功
launchMiniProgram(options: LaunchMiniProgramOptions): Promise<boolean>打开微信小程序。
参数:
interface LaunchMiniProgramOptions {
id: string; // 小程序原始id
type: WeChatMiniProgramType; // 小程序类型
path?: string; // 小程序路径(可选)
extraData?: string; // 额外数据(可选)
}返回值: Promise<boolean> - 打开请求是否发送成功
pay(options: PayOptions): Promise<boolean>发起微信支付。
参数:
interface PayOptions {
partnerId: string; // 商户号
prepayId: string; // 预支付交易会话ID
nonceStr: string; // 随机字符串
timeStamp: number; // 时间戳
sign: string; // 签名
package: string; // 扩展字段
extraData: string; // 额外数据
}返回值: Promise<boolean> - 支付请求是否发送成功
openWeChatCustomerServiceChat(cropId: string, url: string): Promise<boolean>打开微信客服聊天。
参数:
cropId: 企业IDurl: 客服URL
返回值: Promise<boolean> - 打开请求是否发送成功
sendSubscribeMessage(
scene: number,
templateId: string,
reserved: string
): Promise<boolean>发送订阅消息。
参数:
scene: 场景templateId: 模板IDreserved: 保留字段
返回值: Promise<boolean> - 发送请求是否成功
调用API返回的Promise仅仅代表调用的成功与否,不代表最终的微信返回结果。对于需要观测结果的API,应当使用事件监听的方式来实现:
| 事件名 | 说明 | 回调参数类型 |
|---|---|---|
onQRCodeAuthGotQRCode |
二维码登录时,得到二维码图片 | { image: string } |
onQRCodeAuthUserScanned |
二维码登录时,用户成功扫描二维码 | void |
onQRCodeAuthResult |
二维码登录结果 | { errorCode: number; authCode: string } |
onShowMessageFromWeChat |
从微信打开应用时收到的消息 | ShowMessageFromWeChatPayload |
onAuthResult |
授权登录结果 | AuthResultPayload |
onPayResult |
支付结果 | PayResultPayload |
onLaunchMiniProgramResult |
打开小程序结果 | { extraInfo?: string } |
export type AuthResultPayload = {
code: string; // 授权码
state: string; // 状态值
url: string; // 完整URL
authResult: boolean; // 授权是否成功
lang: string; // 语言
country: string; // 国家
errorCode: number; // 错误码
errorMessage: string; // 错误信息
openId: string; // 开放ID
transaction: string; // 事务ID
};export type PayResultPayload = {
prepayId?: string; // 预支付ID
returnKey?: string; // 返回键
extraInfo?: string; // 额外信息
errorCode: number; // 错误码
errorMessage: string; // 错误信息
openId: string; // 开放ID
transaction: string; // 事务ID
};export enum ResultErrorCode {
ok = 0, // 成功
common = -1, // 普通错误
userCancel = -2, // 用户取消
sentFailed = -3, // 发送失败
authDenied = -4, // 授权被拒绝
unsupported = -5, // 不支持的操作
ban = -6, // 被禁止
}import ExpoWeChat from 'expo-wechat'
import { useEvent, useEffect } from 'expo'
// 初始化
const initializeWeChat = async () => {
const result = await ExpoWeChat.registerApp('wx1234567890', 'https://example.com/');
console.log('微信SDK初始化结果:', result);
};
// 使用useEvent监听授权结果
const authResult = useEvent(ExpoWeChat, 'onAuthResult');
useEffect(() => {
if (authResult) {
if (authResult.errorCode === 0) {
console.log('授权成功!');
console.log('授权码:', authResult.code);
console.log('状态:', authResult.state);
// 在这里使用code向服务器换取token
} else {
console.log('授权失败:', authResult.errorMessage);
}
}
}, [authResult]);
// 发送授权请求
const handleWeChatLogin = async () => {
// 检查微信是否安装
const isInstalled = await ExpoWeChat.isWXAppInstalled();
if (!isInstalled) {
alert('请先安装微信');
return;
}
// 发送授权请求
const requestResult = await ExpoWeChat.sendAuthRequest('snsapi_userinfo', 'state123');
console.log('授权请求发送结果:', requestResult);
};import ExpoWeChat from 'expo-wechat'
import { useEvent, useEffect } from 'expo'
// 监听二维码相关事件
const qrCodeResult = useEvent(ExpoWeChat, 'onQRCodeAuthGotQRCode');
const qrCodeScanResult = useEvent(ExpoWeChat, 'onQRCodeAuthUserScanned');
const qrCodeLoginResult = useEvent(ExpoWeChat, 'onQRCodeAuthResult');
useEffect(() => {
if (qrCodeResult) {
console.log('二维码生成成功,可以显示了');
// 这里可以使用qrCodeResult.image来渲染二维码
}
}, [qrCodeResult]);
useEffect(() => {
if (qrCodeScanResult) {
console.log('用户已扫描二维码,请确认');
}
}, [qrCodeScanResult]);
useEffect(() => {
if (qrCodeLoginResult) {
if (qrCodeLoginResult.errorCode === 0) {
console.log('二维码登录成功!');
console.log('授权码:', qrCodeLoginResult.authCode);
// 在这里使用authCode向服务器换取token
} else {
console.log('二维码登录失败:', qrCodeLoginResult.errorCode);
}
}
}, [qrCodeLoginResult]);
// 生成登录二维码
const generateLoginQRCode = async () => {
try {
const qrCode = await ExpoWeChat.sendAuthByQRRequest({
appId: 'wx1234567890',
appSecret: 'your_app_secret',
scope: 'snsapi_userinfo'
});
console.log('二维码生成成功');
} catch (error) {
console.error('二维码生成失败:', error);
}
};import ExpoWeChat from 'expo-wechat'
import { useEvent, useEffect } from 'expo'
// 监听支付结果
const payResult = useEvent(ExpoWeChat, 'onPayResult');
useEffect(() => {
if (payResult) {
if (payResult.errorCode === 0) {
console.log('支付成功!');
// 支付成功后的处理逻辑
} else {
console.log('支付失败:', payResult.errorMessage);
// 支付失败后的处理逻辑
}
}
}, [payResult]);
// 发起支付
const handlePay = async () => {
try {
// 从服务器获取支付参数
const payParams = await getPayParamsFromServer();
const result = await ExpoWeChat.pay({
partnerId: payParams.partnerId,
prepayId: payParams.prepayId,
nonceStr: payParams.nonceStr,
timeStamp: payParams.timeStamp,
sign: payParams.sign,
package: payParams.package,
extraData: payParams.extraData
});
console.log('支付请求发送结果:', result);
} catch (error) {
console.error('支付失败:', error);
}
};import ExpoWeChat from 'expo-wechat'
// 分享网页到微信会话
const shareToWeChat = async () => {
try {
const result = await ExpoWeChat.shareWebpage({
url: 'https://example.com',
title: '分享标题',
description: '分享描述内容',
thumbBase64OrImageUri: 'base64编码的图片或本地图片URI',
scene: 'session'
});
console.log('分享请求发送结果:', result);
} catch (error) {
console.error('分享失败:', error);
}
};注意: 所有API返回的Promise仅表示调用是否成功发送,不代表最终操作结果。需要通过相应的事件监听获取实际操作结果。
useEvent是expo提供的一个模块事件监听的工具,你完全可以使用ExpoWeChat.addEventListener('onAuthResult', (result) => {})这种语法来监听事件结果,但千万不要忘记在组件卸载时移除事件监听,否则会导致内存泄漏。
克隆本仓库,并启动Example示例项目的步骤如下
- 克隆本仓库后,在根目录执行
npm i - 在根目录执行
npm run build plugin,然后按下ctrl + c退出命令即可。 - 进入example文件夹,执行
npm i安装依赖。 - 启动之前,请在
.env文件内配置微信AppId和Key,以及通用链接。
本框架参考了许多react-native-wechat-lib的代码,实现了基本上所有的API的功能,在此基础上,极大的简化了配置流程,并使用了最新的微信SDK,感谢前人!
本框架积极维护,如有任何问题,欢迎提交issue或者PR。 QQ 群:682911244
- 实现选择发票功能
- 发布不带支付功能的SDK
- 完善文档
报错 could not find module ExpoModulesCore for target '86_64-apple-ios-simulator'; found: arm64-apple-ios-simulator
以下方案是我们的一些经验,你可以都试一下:
- 启动Rosetta模拟器。
- 使用真机运行项目。
- 升级Xcode到16.4以及以后。
- 使用expo-fix-ios-simulator-arch插件来自动帮你解决这个问题。