# 微信JS-SDK集成API文档 ## 📋 文档概述 **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集成模块为移动端应用提供完整的微信浏览器原生功能调用能力,包括分享、扫码、支付、地理位置、图片处理等功能。 ### 核心功能 - ✅ 微信环境检测和SDK初始化 - ✅ 分享功能(朋友圈/朋友) - ✅ 扫码功能(二维码/条形码) - ✅ 图片处理(选择/预览/上传) - ✅ **微信多媒体文件永久保存**(解决3天有效期限制) - ✅ 地理位置(获取/打开地图) - ✅ 设备信息查询 - ✅ 微信支付调用 - ✅ 接口支持检查 ## 🔧 技术架构 ### 前端架构 ``` mobile/ ├── src/ │ ├── utils/ │ │ └── wechat.js # 微信JS-SDK工具类 │ ├── api/ │ │ └── wechat.ts # 微信API接口定义 │ └── components/ │ └── WeChatDemo.vue # 功能演示组件 └── public/ └── index.html # JS-SDK脚本引用 ``` ### 依赖关系 - **微信JS-SDK**: 1.6.0 (CDN引入) - **请求工具**: 基于项目统一的request.js - **加密工具**: 使用现有的crypto.js - **UI组件**: uview-ui 2.0.38 ## 📚 前端API文档 ### 微信工具类 (wechat.js) #### 1. 初始化相关 ##### `init(options)` 初始化微信JS-SDK配置 **方法签名:** ```javascript async init(options = {}) ``` **参数说明:** ```typescript interface InitOptions { url?: string; // 当前页面URL,默认自动获取 jsApiList?: string[]; // 需要使用的API列表,默认使用全部 debug?: boolean; // 是否开启调试模式,默认根据环境 } ``` **返回值:** ```typescript Promise ``` **使用示例:** ```javascript import weChatSDK from '@/utils/wechat.js'; // 基础初始化 await weChatSDK.init(); // 自定义配置 await weChatSDK.init({ debug: true, jsApiList: ['chooseImage', 'scanQRCode', 'getLocation'] }); ``` ##### `isWeChatBrowser()` 检查是否在微信浏览器中 **方法签名:** ```javascript isWeChatBrowser() ``` **返回值:** ```typescript boolean ``` **使用示例:** ```javascript if (weChatSDK.isWeChatBrowser()) { console.log('在微信浏览器中'); } else { console.log('不在微信浏览器中'); } ``` #### 2. 分享功能 ##### `shareTimeline(shareData)` 分享到朋友圈 **方法签名:** ```javascript async shareTimeline(shareData) ``` **参数说明:** ```typescript interface ShareTimelineData { title: string; // 分享标题 link: string; // 分享链接 imgUrl: string; // 分享图标URL } ``` **使用示例:** ```javascript await weChatSDK.shareTimeline({ title: '智慧校园移动应用', link: 'https://example.com/app', imgUrl: 'https://example.com/logo.png' }); ``` ##### `shareAppMessage(shareData)` 分享给朋友 **方法签名:** ```javascript async shareAppMessage(shareData) ``` **参数说明:** ```typescript interface ShareAppMessageData { title: string; // 分享标题 desc: string; // 分享描述 link: string; // 分享链接 imgUrl: string; // 分享图标URL } ``` **使用示例:** ```javascript await weChatSDK.shareAppMessage({ title: '智慧校园', desc: '基于uni-app的校园管理系统', link: 'https://example.com/app', imgUrl: 'https://example.com/logo.png' }); ``` #### 3. 扫码功能 ##### `scanQRCode(options)` 微信扫一扫 **方法签名:** ```javascript async scanQRCode(options = {}) ``` **参数说明:** ```typescript interface ScanOptions { needResult?: number; // 是否返回扫描结果,0不返回,1返回,默认1 scanType?: string[]; // 扫码类型,默认['qrCode', 'barCode'] } ``` **返回值:** ```typescript Promise<{ resultStr: string; // 扫描结果 }> ``` **使用示例:** ```javascript // 扫描二维码和条形码 const result = await weChatSDK.scanQRCode(); console.log('扫码结果:', result.resultStr); // 只扫描二维码 const qrResult = await weChatSDK.scanQRCode({ scanType: ['qrCode'] }); ``` #### 4. 图片功能 ##### `chooseImage(options)` 选择图片 **方法签名:** ```javascript async chooseImage(options = {}) ``` **参数说明:** ```typescript interface ChooseImageOptions { count?: number; // 图片数量,默认1,最多9张 sizeType?: string[]; // 图片尺寸,默认['original', 'compressed'] sourceType?: string[]; // 图片来源,默认['album', 'camera'] } ``` **返回值:** ```typescript Promise<{ localIds: string[]; // 图片本地ID列表 }> ``` **使用示例:** ```javascript // 选择1张压缩图片 const result = await weChatSDK.chooseImage({ count: 1, sizeType: ['compressed'], sourceType: ['album', 'camera'] }); console.log('选中图片:', result.localIds); ``` ##### `previewImage(options)` 预览图片 **方法签名:** ```javascript async previewImage(options) ``` **参数说明:** ```typescript interface PreviewImageOptions { current: string; // 当前显示图片的链接 urls: string[]; // 需要预览的图片链接列表 } ``` **使用示例:** ```javascript await weChatSDK.previewImage({ current: 'https://example.com/image1.jpg', urls: [ 'https://example.com/image1.jpg', 'https://example.com/image2.jpg' ] }); ``` #### 5. 地理位置 ##### `getLocation(options)` 获取地理位置 **方法签名:** ```javascript async getLocation(options = {}) ``` **参数说明:** ```typescript interface LocationOptions { type?: string; // 坐标类型,'wgs84'或'gcj02',默认'gcj02' } ``` **返回值:** ```typescript Promise<{ latitude: number; // 纬度 longitude: number; // 经度 speed: number; // 速度(米/秒) accuracy: number; // 精度(米) }> ``` **使用示例:** ```javascript const location = await weChatSDK.getLocation({ type: 'gcj02' }); console.log(`位置: ${location.latitude}, ${location.longitude}`); console.log(`精度: ${location.accuracy}米`); ``` ##### `openLocation(location)` 打开地图 **方法签名:** ```javascript async openLocation(location) ``` **参数说明:** ```typescript interface OpenLocationData { latitude: number; // 纬度 longitude: number; // 经度 name?: string; // 位置名称 address?: string; // 地址详情 scale?: number; // 地图缩放级别,默认14 } ``` **使用示例:** ```javascript await weChatSDK.openLocation({ latitude: 39.908692, longitude: 116.397477, name: '天安门', address: '北京市东城区天安门广场', scale: 16 }); ``` #### 6. 设备信息 ##### `getNetworkType()` 获取网络状态 **方法签名:** ```javascript async getNetworkType() ``` **返回值:** ```typescript Promise<{ networkType: string; // 网络类型:wifi/2g/3g/4g/5g/unknown/none }> ``` **使用示例:** ```javascript const network = await weChatSDK.getNetworkType(); console.log('网络类型:', network.networkType); ``` #### 7. 支付功能 ##### `chooseWXPay(payInfo)` 微信支付 **方法签名:** ```javascript async chooseWXPay(payInfo) ``` **参数说明:** ```typescript interface PayInfo { timestamp: string; // 时间戳 nonceStr: string; // 随机字符串 package: string; // 订单详情扩展字符串 signType?: string; // 签名方式,默认'MD5' paySign: string; // 签名 } ``` **使用示例:** ```javascript await weChatSDK.chooseWXPay({ timestamp: '1640995200', nonceStr: 'Wm3WZYTPz0wzccnW', package: 'prepay_id=wx1234567890abcdef', signType: 'MD5', paySign: '0f9de62fce790f9a083d5c99e95740ceb90c27ed' }); ``` #### 8. 工具方法 ##### `checkJsApi(jsApiList)` 检查接口支持 **方法签名:** ```javascript async checkJsApi(jsApiList) ``` **参数说明:** ```typescript jsApiList: string[] // 需要检查的接口列表 ``` **返回值:** ```typescript Promise<{ checkResult: { [apiName: string]: boolean; // 接口名称和支持状态的映射 } }> ``` **使用示例:** ```javascript const result = await weChatSDK.checkJsApi([ 'chooseImage', 'scanQRCode', 'getLocation' ]); console.log('chooseImage支持:', result.checkResult.chooseImage); console.log('scanQRCode支持:', result.checkResult.scanQRCode); ``` ##### `closeWindow()` 关闭当前网页窗口 **方法签名:** ```javascript closeWindow() ``` **使用示例:** ```javascript weChatSDK.closeWindow(); ``` ## 🌐 后端API接口 ### 基础信息 **接口基础路径**: `/system/wechat` **认证方式**: Bearer Token **请求格式**: application/json **响应格式**: application/json ### 接口列表 #### 1. 获取微信JS-SDK配置 **接口描述**: 获取微信JS-SDK初始化所需的配置信息 **接口地址**: `POST /system/wechat/config` **请求参数**: ```json { "url": "https://example.com/app" // 当前页面URL } ``` **响应示例**: ```json { "code": 200, "msg": "操作成功", "data": { "appId": "wx1234567890abcdef", "timestamp": 1640995200, "nonceStr": "Wm3WZYTPz0wzccnW", "signature": "0f9de62fce790f9a083d5c99e95740ceb90c27ed" } } ``` #### 2. 保存微信媒体文件到服务器 **接口描述**: 将微信临时媒体文件下载并保存到自己的OSS服务器,解决微信媒体文件3天有效期限制 **背景说明**: - 微信JS-SDK的`wx.uploadImage`只是将图片上传到微信临时服务器,获得serverId(也就是media_id) - 这个serverId有效期只有3天,过期后无法访问 - 本接口通过微信多媒体API将文件从微信服务器下载到我们的OSS存储,实现永久保存 **接口地址**: `POST /system/wechat/upload` **请求参数**: ```json { "mediaId": "wx_media_123456", // 微信媒体文件ID(wx.uploadImage返回的serverId) "type": "image" // 媒体类型:image/voice/video/thumb } ``` **处理流程**: 1. 使用微信access_token从微信多媒体接口下载文件 2. 根据Content-Type自动识别文件类型和扩展名 3. 将文件上传到项目的OSS存储服务 4. 返回文件在我们服务器上的访问信息 **响应示例**: ```json { "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" } } ``` **错误响应示例**: ```json { "code": 500, "msg": "处理微信媒体文件失败: 微信媒体文件下载失败: media_id invalid", "data": null } ``` #### 3. 测试微信媒体文件下载 **接口描述**: 测试从微信服务器下载媒体文件(与上传接口功能相同,用于直接测试下载功能) **接口地址**: `GET /system/wechat/download` **请求参数**: ``` ?mediaId=wx_media_123456 ``` **响应格式**: JSON(与上传接口返回格式相同) **使用场景**: - 测试微信媒体文件下载功能 - 单独下载特定的微信媒体文件 - 开发调试和接口验证 #### 4. 获取微信用户信息 **接口描述**: 通过微信授权码获取用户信息 **接口地址**: `GET /system/wechat/userinfo` **请求参数**: ``` ?code=wx_auth_code_123456 ``` **响应示例**: ```json { "code": 200, "msg": "获取成功", "data": { "openid": "o6_bmjrPTlm6_2sgVt7hMZOPfL2M", "nickname": "用户昵称", "headimgurl": "https://example.com/avatar.jpg", "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL" } } ``` #### 5. 创建微信支付订单 **接口描述**: 创建微信支付订单并返回支付参数 **接口地址**: `POST /system/wechat/pay/create` **请求参数**: ```json { "body": "商品描述", "total_fee": 100, // 金额(分) "trade_type": "JSAPI", "openid": "用户openid" } ``` **响应示例**: ```json { "code": 200, "msg": "创建成功", "data": { "timestamp": "1640995200", "nonceStr": "Wm3WZYTPz0wzccnW", "package": "prepay_id=wx1234567890abcdef", "signType": "MD5", "paySign": "0f9de62fce790f9a083d5c99e95740ceb90c27ed" } } ``` #### 6. 查询支付状态 **接口描述**: 查询微信支付订单状态 **接口地址**: `GET /system/wechat/pay/query` **请求参数**: ``` ?order_id=ORDER_123456 ``` **响应示例**: ```json { "code": 200, "msg": "查询成功", "data": { "order_id": "ORDER_123456", "trade_state": "SUCCESS", "transaction_id": "wx_trans_123456", "total_fee": 100 } } ``` ## 🎨 使用示例 ### 完整使用流程 ```vue ``` ## 🔧 配置说明 ### 微信公众平台配置 1. **JS接口安全域名配置** - 登录微信公众平台 - 进入"设置" → "公众号设置" → "功能设置" - 配置"JS接口安全域名" - 填入网站域名(不包含http://) 2. **接口权限获取** - 确保服务号已认证 - 开通所需的接口权限 - 获取AppID和AppSecret ### 后端配置要求 1. **微信配置** ```javascript const wechatConfig = { appId: 'wx1234567890abcdef', appSecret: '你的AppSecret', token: '你的Token', encodingAESKey: '你的EncodingAESKey' }; ``` 2. **签名算法** ```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访问地址 <------------ | ``` ### 核心微信API接口 #### 1. 获取access_token ```http GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET ``` #### 2. 下载多媒体文件 ```http GET https://api.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID ``` ### 前端集成示例 ```javascript // 完整的图片上传并保存流程 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); } } ``` ### 后端实现关键点 #### 1. 文件类型识别 ```java 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"; } } ``` #### 2. 错误处理 ```java // 检查微信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")); } ``` ## 🚨 注意事项 ### 1. 安全考虑 - ⚠️ AppSecret等敏感信息只能在服务端使用 - ⚠️ 签名计算必须在服务端完成 - ⚠️ 分享图标等资源使用HTTPS地址 - ⚠️ access_token需要缓存,避免频繁获取 - ⚠️ 微信媒体文件有3天有效期,需及时下载保存 ### 2. 调试技巧 - 📱 使用微信开发者工具进行调试 - 🐛 开启debug模式查看详细错误信息 - 🔍 检查JS接口安全域名配置 - 🔍 检查access_token是否有效 - 🔍 验证media_id是否在3天有效期内 ### 3. 常见问题 - **invalid signature**: 检查签名算法和URL参数 - **permission denied**: 确认接口权限和jsApiList配置 - **config:fail**: 检查配置参数完整性 - **media_id invalid**: 媒体文件已过期或不存在 - **access_token invalid**: Token已过期,需要重新获取 - **下载失败**: 检查网络连接和微信服务器状态 ### 4. 性能优化 - 🚀 access_token缓存7200秒(提前300秒刷新) - 🚀 支持多种文件格式自动识别 - 🚀 集成OSS存储,支持CDN加速 - 🚀 异步处理大文件上传 ## 📱 兼容性 ### 支持的微信版本 - iOS微信: 6.0.2+ - Android微信: 6.0.2+ ### 支持的功能 - ✅ 基础分享功能(所有认证服务号) - ✅ 图像和音频处理 - ✅ 地理位置服务 - ✅ 设备信息查询 - ✅ 扫一扫功能 - ✅ 微信支付(需开通) ## 🔗 相关资源 - [微信JS-SDK官方文档](https://developers.weixin.qq.com/doc/service/guide/h5/jssdk.html) - [微信公众平台](https://mp.weixin.qq.com/) - [移动端开发规范](../../.cursor/cursorrules-mobile.md) - [API开发最佳实践](../API开发最佳实践总结.md) --- **文档维护**: 开发团队 **最后更新**: 2025-01-03 **API版本**: v1.0.0