API模块: 微信JS-SDK集成
适用平台: 移动端 (H5)
技术架构: uni-app 2.x + Vue 2.6.14 + 微信JS-SDK 1.6.0
更新日期: 2025-01-03
文档版本: v1.1.0 (新增微信多媒体文件处理功能)
微信JS-SDK集成模块为移动端应用提供完整的微信浏览器原生功能调用能力,包括分享、扫码、支付、地理位置、图片处理等功能。
mobile/
├── src/
│ ├── utils/
│ │ └── wechat.js # 微信JS-SDK工具类
│ ├── api/
│ │ └── wechat.ts # 微信API接口定义
│ └── components/
│ └── WeChatDemo.vue # 功能演示组件
└── public/
└── index.html # JS-SDK脚本引用
init(options)初始化微信JS-SDK配置
方法签名:
async init(options = {})
参数说明:
interface InitOptions {
url?: string; // 当前页面URL,默认自动获取
jsApiList?: string[]; // 需要使用的API列表,默认使用全部
debug?: boolean; // 是否开启调试模式,默认根据环境
}
返回值:
Promise<WeChatConfig>
使用示例:
import weChatSDK from '@/utils/wechat.js';
// 基础初始化
await weChatSDK.init();
// 自定义配置
await weChatSDK.init({
debug: true,
jsApiList: ['chooseImage', 'scanQRCode', 'getLocation']
});
isWeChatBrowser()检查是否在微信浏览器中
方法签名:
isWeChatBrowser()
返回值:
boolean
使用示例:
if (weChatSDK.isWeChatBrowser()) {
console.log('在微信浏览器中');
} else {
console.log('不在微信浏览器中');
}
shareTimeline(shareData)分享到朋友圈
方法签名:
async shareTimeline(shareData)
参数说明:
interface ShareTimelineData {
title: string; // 分享标题
link: string; // 分享链接
imgUrl: string; // 分享图标URL
}
使用示例:
await weChatSDK.shareTimeline({
title: '智慧校园移动应用',
link: 'https://example.com/app',
imgUrl: 'https://example.com/logo.png'
});
shareAppMessage(shareData)分享给朋友
方法签名:
async shareAppMessage(shareData)
参数说明:
interface ShareAppMessageData {
title: string; // 分享标题
desc: string; // 分享描述
link: string; // 分享链接
imgUrl: string; // 分享图标URL
}
使用示例:
await weChatSDK.shareAppMessage({
title: '智慧校园',
desc: '基于uni-app的校园管理系统',
link: 'https://example.com/app',
imgUrl: 'https://example.com/logo.png'
});
scanQRCode(options)微信扫一扫
方法签名:
async scanQRCode(options = {})
参数说明:
interface ScanOptions {
needResult?: number; // 是否返回扫描结果,0不返回,1返回,默认1
scanType?: string[]; // 扫码类型,默认['qrCode', 'barCode']
}
返回值:
Promise<{
resultStr: string; // 扫描结果
}>
使用示例:
// 扫描二维码和条形码
const result = await weChatSDK.scanQRCode();
console.log('扫码结果:', result.resultStr);
// 只扫描二维码
const qrResult = await weChatSDK.scanQRCode({
scanType: ['qrCode']
});
chooseImage(options)选择图片
方法签名:
async chooseImage(options = {})
参数说明:
interface ChooseImageOptions {
count?: number; // 图片数量,默认1,最多9张
sizeType?: string[]; // 图片尺寸,默认['original', 'compressed']
sourceType?: string[]; // 图片来源,默认['album', 'camera']
}
返回值:
Promise<{
localIds: string[]; // 图片本地ID列表
}>
使用示例:
// 选择1张压缩图片
const result = await weChatSDK.chooseImage({
count: 1,
sizeType: ['compressed'],
sourceType: ['album', 'camera']
});
console.log('选中图片:', result.localIds);
previewImage(options)预览图片
方法签名:
async previewImage(options)
参数说明:
interface PreviewImageOptions {
current: string; // 当前显示图片的链接
urls: string[]; // 需要预览的图片链接列表
}
使用示例:
await weChatSDK.previewImage({
current: 'https://example.com/image1.jpg',
urls: [
'https://example.com/image1.jpg',
'https://example.com/image2.jpg'
]
});
getLocation(options)获取地理位置
方法签名:
async getLocation(options = {})
参数说明:
interface LocationOptions {
type?: string; // 坐标类型,'wgs84'或'gcj02',默认'gcj02'
}
返回值:
Promise<{
latitude: number; // 纬度
longitude: number; // 经度
speed: number; // 速度(米/秒)
accuracy: number; // 精度(米)
}>
使用示例:
const location = await weChatSDK.getLocation({
type: 'gcj02'
});
console.log(`位置: ${location.latitude}, ${location.longitude}`);
console.log(`精度: ${location.accuracy}米`);
openLocation(location)打开地图
方法签名:
async openLocation(location)
参数说明:
interface OpenLocationData {
latitude: number; // 纬度
longitude: number; // 经度
name?: string; // 位置名称
address?: string; // 地址详情
scale?: number; // 地图缩放级别,默认14
}
使用示例:
await weChatSDK.openLocation({
latitude: 39.908692,
longitude: 116.397477,
name: '天安门',
address: '北京市东城区天安门广场',
scale: 16
});
getNetworkType()获取网络状态
方法签名:
async getNetworkType()
返回值:
Promise<{
networkType: string; // 网络类型:wifi/2g/3g/4g/5g/unknown/none
}>
使用示例:
const network = await weChatSDK.getNetworkType();
console.log('网络类型:', network.networkType);
chooseWXPay(payInfo)微信支付
方法签名:
async chooseWXPay(payInfo)
参数说明:
interface PayInfo {
timestamp: string; // 时间戳
nonceStr: string; // 随机字符串
package: string; // 订单详情扩展字符串
signType?: string; // 签名方式,默认'MD5'
paySign: string; // 签名
}
使用示例:
await weChatSDK.chooseWXPay({
timestamp: '1640995200',
nonceStr: 'Wm3WZYTPz0wzccnW',
package: 'prepay_id=wx1234567890abcdef',
signType: 'MD5',
paySign: '0f9de62fce790f9a083d5c99e95740ceb90c27ed'
});
checkJsApi(jsApiList)检查接口支持
方法签名:
async checkJsApi(jsApiList)
参数说明:
jsApiList: string[] // 需要检查的接口列表
返回值:
Promise<{
checkResult: {
[apiName: string]: boolean; // 接口名称和支持状态的映射
}
}>
使用示例:
const result = await weChatSDK.checkJsApi([
'chooseImage',
'scanQRCode',
'getLocation'
]);
console.log('chooseImage支持:', result.checkResult.chooseImage);
console.log('scanQRCode支持:', result.checkResult.scanQRCode);
closeWindow()关闭当前网页窗口
方法签名:
closeWindow()
使用示例:
weChatSDK.closeWindow();
接口基础路径: /system/wechat
认证方式: Bearer Token
请求格式: application/json
响应格式: application/json
接口描述: 获取微信JS-SDK初始化所需的配置信息
接口地址: POST /system/wechat/config
请求参数:
{
"url": "https://example.com/app" // 当前页面URL
}
响应示例:
{
"code": 200,
"msg": "操作成功",
"data": {
"appId": "wx1234567890abcdef",
"timestamp": 1640995200,
"nonceStr": "Wm3WZYTPz0wzccnW",
"signature": "0f9de62fce790f9a083d5c99e95740ceb90c27ed"
}
}
接口描述: 将微信临时媒体文件下载并保存到自己的OSS服务器,解决微信媒体文件3天有效期限制
背景说明:
wx.uploadImage只是将图片上传到微信临时服务器,获得serverId(也就是media_id)接口地址: POST /system/wechat/upload
请求参数:
{
"mediaId": "wx_media_123456", // 微信媒体文件ID(wx.uploadImage返回的serverId)
"type": "image" // 媒体类型:image/voice/video/thumb
}
处理流程:
响应示例:
{
"code": 200,
"msg": "上传成功",
"data": {
"mediaId": "wx_media_123456",
"ossId": 12345,
"fileName": "20250103/wechat_media_wx_media_123456_a1b2c3.jpg",
"originalName": "wechat_media_wx_media_123456.jpg",
"url": "https://oss.example.com/files/20250103/wechat_media_wx_media_123456_a1b2c3.jpg",
"fileSuffix": ".jpg",
"fileSize": 256789,
"contentType": "image/jpeg",
"downloadTime": 1640995200000,
"status": "success"
}
}
错误响应示例:
{
"code": 500,
"msg": "处理微信媒体文件失败: 微信媒体文件下载失败: media_id invalid",
"data": null
}
接口描述: 测试从微信服务器下载媒体文件(与上传接口功能相同,用于直接测试下载功能)
接口地址: GET /system/wechat/download
请求参数:
?mediaId=wx_media_123456
响应格式: JSON(与上传接口返回格式相同)
使用场景:
接口描述: 通过微信授权码获取用户信息
接口地址: GET /system/wechat/userinfo
请求参数:
?code=wx_auth_code_123456
响应示例:
{
"code": 200,
"msg": "获取成功",
"data": {
"openid": "o6_bmjrPTlm6_2sgVt7hMZOPfL2M",
"nickname": "用户昵称",
"headimgurl": "https://example.com/avatar.jpg",
"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
}
}
接口描述: 创建微信支付订单并返回支付参数
接口地址: POST /system/wechat/pay/create
请求参数:
{
"body": "商品描述",
"total_fee": 100, // 金额(分)
"trade_type": "JSAPI",
"openid": "用户openid"
}
响应示例:
{
"code": 200,
"msg": "创建成功",
"data": {
"timestamp": "1640995200",
"nonceStr": "Wm3WZYTPz0wzccnW",
"package": "prepay_id=wx1234567890abcdef",
"signType": "MD5",
"paySign": "0f9de62fce790f9a083d5c99e95740ceb90c27ed"
}
}
接口描述: 查询微信支付订单状态
接口地址: GET /system/wechat/pay/query
请求参数:
?order_id=ORDER_123456
响应示例:
{
"code": 200,
"msg": "查询成功",
"data": {
"order_id": "ORDER_123456",
"trade_state": "SUCCESS",
"transaction_id": "wx_trans_123456",
"total_fee": 100
}
}
<template>
<view class="wechat-page">
<!-- 初始化按钮 -->
<button @click="initWeChatSDK" :disabled="isInitialized">
{{ isInitialized ? '已初始化' : '初始化微信SDK' }}
</button>
<!-- 功能按钮 -->
<button @click="scanQRCode" :disabled="!isInitialized">扫一扫</button>
<button @click="chooseAndPreviewImage" :disabled="!isInitialized">选择图片</button>
<button @click="shareToFriends" :disabled="!isInitialized">分享给朋友</button>
<button @click="getLocationAndOpen" :disabled="!isInitialized">获取位置</button>
</view>
</template>
<script>
import weChatSDK from '@/utils/wechat.js';
export default {
data() {
return {
isInitialized: false
};
},
mounted() {
this.checkWeChatEnvironment();
},
methods: {
// 检查微信环境
checkWeChatEnvironment() {
if (!weChatSDK.isWeChatBrowser()) {
uni.showModal({
title: '提示',
content: '请在微信中打开',
showCancel: false
});
}
},
// 初始化微信SDK
async initWeChatSDK() {
try {
await weChatSDK.init({
debug: process.env.NODE_ENV === 'development'
});
this.isInitialized = true;
uni.showToast({ title: '初始化成功', icon: 'success' });
} catch (error) {
console.error('初始化失败:', error);
uni.showToast({ title: '初始化失败', icon: 'none' });
}
},
// 扫码功能
async scanQRCode() {
try {
const result = await weChatSDK.scanQRCode();
uni.showModal({
title: '扫码结果',
content: result.resultStr,
showCancel: false
});
} catch (error) {
uni.showToast({ title: '扫码失败', icon: 'none' });
}
},
// 选择和预览图片
async chooseAndPreviewImage() {
try {
const result = await weChatSDK.chooseImage({
count: 3,
sizeType: ['compressed']
});
if (result.localIds.length > 0) {
await weChatSDK.previewImage({
current: result.localIds[0],
urls: result.localIds
});
}
} catch (error) {
uni.showToast({ title: '操作失败', icon: 'none' });
}
},
// 分享给朋友
async shareToFriends() {
try {
await weChatSDK.shareAppMessage({
title: '智慧校园',
desc: '基于uni-app的校园管理系统',
link: window.location.href,
imgUrl: 'https://example.com/logo.png'
});
uni.showToast({ title: '分享配置成功', icon: 'success' });
} catch (error) {
uni.showToast({ title: '分享配置失败', icon: 'none' });
}
},
// 获取位置并打开地图
async getLocationAndOpen() {
try {
const location = await weChatSDK.getLocation();
await weChatSDK.openLocation({
latitude: location.latitude,
longitude: location.longitude,
name: '当前位置',
address: '通过微信JS-SDK获取',
scale: 16
});
} catch (error) {
uni.showToast({ title: '定位失败', icon: 'none' });
}
}
}
};
</script>
JS接口安全域名配置
接口权限获取
微信配置
const wechatConfig = {
appId: 'wx1234567890abcdef',
appSecret: '你的AppSecret',
token: '你的Token',
encodingAESKey: '你的EncodingAESKey'
};
javascript
// 签名算法实现(示例)
function generateSignature(jsapi_ticket, noncestr, timestamp, url) {
const string1 = `jsapi_ticket=${jsapi_ticket}&noncestr=${noncestr}×tamp=${timestamp}&url=${url}`;
return sha1(string1);
}
微信多媒体接口是微信公众平台后端API,用于处理通过微信JS-SDK上传的临时媒体文件。
用户操作 微信前端 微信服务器 项目后端 项目OSS
| | | | |
1. 选择图片 -----> | | | |
| | | | |
2. 调用wx.uploadImage -----------> | 临时存储3天 | |
| | | (获得serverId) | |
| | <------------ | | |
| | | | |
3. 调用后端接口 -----> POST /system/wechat/upload | |
| | | | |
| | 4. 使用access_token | |
| | 下载文件 <--------- | |
| | | | |
| | | 返回文件数据 --> | |
| | | | |
| | | 5. 上传OSS ----------> | 永久存储
| | | | |
| | <------------ | 返回OSS访问地址 <------------ |
GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
GET https://api.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID
// 完整的图片上传并保存流程
async uploadAndSaveImage() {
try {
// 1. 选择图片
const chooseResult = await wx.chooseImage({
count: 1,
sizeType: ['compressed'],
sourceType: ['album', 'camera']
});
const localId = chooseResult.localIds[0];
// 2. 上传到微信服务器
const uploadResult = await wx.uploadImage({
localId: localId,
isShowProgressTips: 1
});
const serverId = uploadResult.serverId;
console.log('微信服务器ID:', serverId);
// 3. 调用后端接口保存到自己的服务器
const saveResponse = await uni.request({
url: '/system/wechat/upload',
method: 'POST',
header: {
'Content-Type': 'application/json',
'Authorization': 'Bearer your-token'
},
data: {
mediaId: serverId,
type: 'image'
}
});
if (saveResponse.data.code === 200) {
const savedFile = saveResponse.data.data;
console.log('文件已保存:', savedFile.url);
console.log('OSS ID:', savedFile.ossId);
// 现在可以长期使用这个URL了
this.showImage(savedFile.url);
}
} catch (error) {
console.error('处理失败:', error);
}
}
private String getFileExtensionByContentType(String contentType) {
switch (contentType.toLowerCase()) {
case "image/jpeg": return ".jpg";
case "image/png": return ".png";
case "image/gif": return ".gif";
// ... 更多类型
default: return ".unknown";
}
}
// 检查微信API返回的错误
String contentType = response.header("Content-Type");
if (contentType != null && contentType.contains("application/json")) {
// 返回的是JSON错误信息
JSONObject errorJson = JSONUtil.parseObj(response.body());
throw new ServiceException("微信媒体文件下载失败: " + errorJson.getStr("errmsg"));
}
文档维护: 开发团队
最后更新: 2025-01-03
API版本: v1.0.0