1. 前言(直接看步骤请翻到第4)

最近公司有个新的需求,就是把之前通过H5开发的功能,通过web-view移到小程序上,其中涉及到了调用微信的相机,相册等功能,需要使用JSSDK,网上看了许多帖子,踩过不少坑,最后才成功的,下面以通过nestjs,复述一下步骤以及注意点

2. 前期准备

  1. 微信公众号(是的你没有看错),要有管理员权限
  2. 小程序(废话),要有管理员权限
  3. 微信官方文档
  4. 编写加密算法的后台
  5. 一个在小程序业务域名以内的网页

3. 疑惑点

  1. 为什么明明是小程序中引用jssdk,却需要微信公众号?
    其实很多人(包括我),几乎所有步骤都是照着文档走的,包括加密算法,通过测试也是对的,
    但是最终就是不出效果,其实问题很可能出现在这里。
    让我们先打开JSSDK说明文档
    仔细阅读一下,会发现JSSDK本身其实就是公众号的功能,所以他的参数自然是需要公众号的参数了
  2. 那我用公众号怎么保证我的小程序是可以用的呢
    公众号有个关联小程序的功能,而小程序的web-view的设置就是可以打开关联公众号的内容
  3. 如果我不是原生微信开发,使用会有什么不同吗
    我是用的是uniapp开发的小程序,因为没有考虑到其他平台的兼容性,在web-view内嵌的页面中完全是用的原生的api,如果要兼容其他平台我只能说,对不起我也不知道了。。。

4. 具体步骤

  1. 打开微信公众号的开发者后台,拿到公众号的APPID 和 AppSecret,在开发管理下的基本配置中,需要注意的是 AppSecret生成后是不会在页面展示的,需要用户自己保存,如果遗忘了,需要重置。
  2. 为公众号添加关联小程序,需要小程序管理员扫码
  3. 为公众号添加ip白名单和JS域名白名单


注意域名白名单不要加上https之类的东西,他需要的是域名

  1. 编写获取加密签名的后台代码。
    这里使用了nestjs,nodejs其实是一个思路,只留下了主要代码。

wehcat-mini.service.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import { Injectable } from '@nestjs/common';
import axios from 'axios'
import * as c from 'crypto'
// 加密的库
import NodeCache = require('node-cache');
// 需要用node-cache做缓存,因为微信接口对调用次数有限制的

@Injectable()
export class WechatMiniService {
private App_Id = '这里是appid'
//公众号的APPID,隐私起见改掉了
private App_Scret = '这里是App_Scret '
//公众号的App_Scret ,隐私起见改掉了
private noncestr = 'abac'
// 随机字符串,其实随便写也可以不过要保证,前端和后台一致,所以这里写死了
nodeCache = new NodeCache()
TIME = 7000

// 获取AssessToken
async GetAssessToken() {
const Time = 7000
// 缓存事件
let access_token = this.nodeCache.get('access_token');
if(!access_token){
const { data } = await axios.get(`https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${this.App_Id}&secret=${this.App_Scret}`);
this.nodeCache.set('access_token',data.access_token,this.TIME)
access_token = data.access_token
}
return access_token
}

// 获取ticket
async GetJSApiTicket() {
const access_token = await this.GetAssessToken()
let ticket = this.nodeCache.get('ticket')
if(!ticket){
const { data } = await axios.get(`https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=${access_token}&type=jsapi`);
this.nodeCache.set('ticket',data.access_token,this.TIME)
ticket = data.ticket
}
return ticket
}

// 前端访问接口时调用的方法,
async GetSignature(url) {
/* 根据微信的文档,访问对应接口取到对应参数,将所有参数,包括随机字符串,
时间戳等拼接成键值对的字符串,随后进行sha1加密*/
const ticket = await this.GetJSApiTicket()
const { noncestr } = this
let timestamp = parseInt((Date.now() / 1000).toString())

let Str = `jsapi_ticket=${ticket}&noncestr=${noncestr}&timestamp=${timestamp}&url=${url}`
let hash = c.createHash('sha1')
hash.update(Str)
// 这里保险起见,我将所有后台调微信api等相关的参数都传给后台了,保证前后端的一致
return { ticket, url, timestamp, md5: hash.digest('hex'), noncestr, app_id: this.App_Id, Str }
}
}
  1. 小程序的准备
  • 将需要嵌入到web-view的页面添加到接口安全域名内
  • 将后台接口域名添加到request合法域名中
  1. 嵌入页面的使用
    主要代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    <!DOCTYPE html>
    <html lang="en">

    <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
    <script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.3.2.js">
    <!-- 引入js文件 -->
    </script>
    <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
    </head>

    <body>
    <h2>NPS-ADMIN</h2>
    <button onclick="chooseImage()">wechatMini Test</button>
    <script>
    init()
    async function init() {
    let { data } = await axios.get('https://njphzh.com:3001/wechatmini/getUser')
    console.log(data)
    const { timestamp, noncestr, md5 ,app_id} = data
    wx.config({
    debug: false,//是否开启调试
    // 开发者工具中测试可以将其设置为true判断参数哪里出错了
    appId: app_id,//小程序appid
    timestamp,//时间戳,单位秒
    nonceStr: noncestr,//随机字符串
    signature: md5,//签名md5
    jsApiList: ['startRecord', 'stopRecord', 'playVoice', 'uploadVoice', 'dowmloadVoice', 'onVoiceRecordEnd', 'translateVoice', 'downloadVoice', 'onMenuShareTimeline', 'onMenuShareAppMessage', 'scanQRCode', 'getLocation', 'chooseImage', 'getLocalImgData', 'uploadImage']//当前html需要用到的接口,可在公众号文档中查看
    });
    }
    function chooseImage(){
    wx.chooseImage({
    count: 1,
    sizeType: ['original', 'compressed'],
    sourceType: ['album', 'camera'],
    success(res) {
    // const tempFilePaths = res.tempFilePaths
    console.log(res);
    }
    })
    }
    </script>
    </body>

    </html>
    在小程序web-view中内嵌该页面
    在这里插入图片描述
    如果在debug开的时候,输出该消息时,说明配置是正确的,可以使用微信的api了

有点晚了,后面写的稍微敷衍了,以后再详细的说下吧在(~ ̄▽ ̄)~