# uniapp H5 调用微信扫一扫配置文档

## 一、微信 JSSDK 加载

**方式：通过 CDN 加载微信官方 JSSDK**

在 `index.html` 的 `<head>` 中添加：

```html
<script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
```

> **注意：** 不要使用 `import wx from 'jweixin-module'` 或 npm 包方式导入，uni-app 会错误解析导致构建失败。

---

## 二、wxsdk.js 封装

创建 `utils/wxsdk.js`：

```javascript
// utils/wxsdk.js
import { wechatApi } from '@/api/index.js'

// 注意：是 jWeixin，不是 wx
// window.wx 会被 uni-app 框架占用为 Vue 模块
const wx = window.jWeixin

/**
 * 初始化微信 JS-SDK
 */
export async function initWxConfig() {
    const url = window.location.href.split('#')[0]
    try {
        const data = await wechatApi.getJssdkConfig(url)
        const { app_id, timestamp, nonce_str, signature } = data

        return new Promise((resolve, reject) => {
            wx.config({
                debug: true,
                appId: app_id,
                timestamp: timestamp,
                nonceStr: nonce_str,
                signature: signature,
                jsApiList: ['scanQRCode']
            })
            wx.ready(() => {
                console.log('微信 SDK 就绪')
                resolve()
            })
            wx.error((err) => {
                reject(err)
            })
        })
    } catch (e) {
        throw e
    }
}

/**
 * 调起微信扫一扫
 * @returns {Promise<string>} 扫码结果字符串
 */
export function wxScan() {
    return new Promise((resolve, reject) => {
        wx.scanQRCode({
            needResult: 1,
            scanType: ['qrCode', 'barCode'],
            success(res) {
                resolve(res.resultStr)
            },
            fail(err) {
                reject(new Error(err?.errMsg || '扫码失败'))
            }
        })
    })
}

/**
 * 检查是否在微信环境中
 */
export function isInWechat() {
    return /micromessenger/i.test(navigator.userAgent)
}
```

---

## 三、后端接口要求

后端需提供 `/api/c/v1/wechat/jssdk-config` 接口，返回格式：

```json
{
    "app_id": "wx1234567890",
    "timestamp": 1234567890,
    "nonce_str": "randomstring",
    "signature": "xxxxx"
}
```

> **注意：** `nonce_str` 必须与生成 signature 时使用的一致

---

## 四、前端调用示例

```javascript
import { initWxConfig, wxScan, isInWechat } from '@/utils/wxsdk.js'

async function handleScan() {
    if (!isInWechat()) {
        uni.showToast({ title: '请在微信环境中使用', icon: 'none' })
        return
    }

    try {
        // 1. 初始化微信 SDK 配置
        await initWxConfig()

        // 2. 调起扫一扫
        const result = await wxScan()
        console.log('扫码结果:', result)
        // 在此处理扫码结果
    } catch (err) {
        console.error('扫码错误:', err)
        uni.showToast({ title: err.message || JSON.stringify(err), icon: 'none' })
    }
}
```

---

## 五、注意事项

| 问题 | 原因 | 解决方案 |
|------|------|----------|
| `window.wx` 输出 `Module {$emit...}` | `window.wx` 被 uni-app 框架占用为 Vue 事件模块 | 使用 `window.jWeixin` |
| `jweixin-module` 打包报 `"default" is not exported` | uni 构建系统错误解析无 default export 的 UMD 模块 | 使用 CDN 加载，不走 npm |
| `wx.scanQRCode is not a function` | 微信 SDK 未正确加载 | 确认 `window.jWeixin` 有值 |
| 扫码提示 `{}` | `catch` 捕获空错误对象 | 需将错误信息转换为 `Error` 对象返回 |

---

## 六、调试建议

在微信开发者工具中打开控制台，检查以下变量：

```javascript
// 错误情况：被 uni-app 框架占用为 Vue 模块
window.wx
// 输出：Module {$emit: ƒ, $off: ƒ, $on: ƒ, $once: ƒ, ...}

// 正确情况：微信 JSSDK
window.jWeixin
// 输出：{config: ƒ, ready: ƒ, error: ƒ, checkJsApi: ƒ, ...}
```

---

## 七、完整文件路径

```
project/
├── index.html              # 引入微信 JSSDK CDN
├── utils/
│   └── wxsdk.js           # 微信扫一扫封装
└── api/
    └── modules/
        └── wechat.js      # 后端接口封装
```

`api/modules/wechat.js` 示例：

```javascript
import request from '@/utils/request.js'

export const wechatApi = {
    getJssdkConfig(url) {
        return request({
            url: '/api/c/v1/wechat/jssdk-config',
            method: 'GET',
            data: { url }
        })
    }
}
```
