事情经过是这样的,这段时间在开发一个二维码美化小程序,昨天中午修复了一个bug后提交给微信审核,晚上收到审核结果后惊呆了,居然没有通过,毕竟自己只是增加了一个setTimeout方法,看到驳回原因后觉得还是挺有意思的:

小程序驳回原因截图

看完之后理解了,小程序审核人员在小程序里面上传了张18禁图片,然后告诉我,你这样不行啊,怎么能不进行图片鉴黄呢,万一带坏了小盆友该怎么办。那为什么之前的审核你都给通过了?第一次做图片工具类的小程序,还真是没想到审核会有这波操作。行吧行吧,看在你是腾讯的份上(其实是鉴黄接口不收费,虽然云函数超过免费额度后会收费,但是价格还能接受),你要加就给你加呗。

马化腾

1、准备工作

security.imgSecCheck文档:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/sec-check/security.imgSecCheck.html

看了一下security.imgSecCheck文档,发现调用图片内容安全识别接口有两种方式,第一种是通过HTTPS 调用,第二种是云调用。虽然第一种可以通过直接请求接口调用,但是需要使用access_token,个人感觉还是比较麻烦的,所以选择了云调用。

使用云调用第一步就是需要开通云开发功能,具体开通流程这里就不进行描述了,选择免费的就行(顺带吐槽一下云开发开始割韭菜啦,具体可以参考别人写的文章:小程序云开发新版套餐解读)。

2. 配置云开发

由于这个小程序之前在创建的时候没有勾选云开发,所以需要自己配置一下。

首先是在根目录下的project.config.json中设置云函数目录:

"cloudfunctionRoot": "cloud/"

然后在根目录下创建cloud文件夹,创建完成后,这个文件夹右下角会带有一个云图标:

创建云函数文件夹

3、创建云函数

在微信开发者工具中右击刚才创建的文件夹,点击新建Node.js云函数,创建一个新的云函数,我这边创建的云函数名称是imgSecCheck,然后在这个云函数目录下的config.json中配置api权限:

{
  "permissions": {
    "openapi": [
      "security.imgSecCheck"
    ]
  }
}

4、编写云函数

由于这个小程序中的图片是在本地进行编辑和保存,不需要上传到服务器,所以直接将图片直接传给接口就行了,在imgSecCheck目录下的index.js文件中编写云函数:

// 云函数入口文件
const cloud = require('wx-server-sdk')

cloud.init({
  env: 'your env'
})

// 云函数入口函数
exports.main = async (event, context) => {
  try {
    const res = await cloud.openapi.security.imgSecCheck({
      media: {
        contentType: 'image/png',
        value: Buffer.from(event.value)
      }
    })
    return res
  } catch (error) {
    return error
  }
}

其中env的值可以在开发者工具-云开发-设置-环境ID中拿到,然后将这个云函数进行上传:

上传云函数

5、小程序端调用

上传完成后即可在小程序端调用,下方为从相册选取图片后进行图片内容安全识别的一个demo:

wx.chooseImage({
    count: 1, // 默认9
    sizeType: ['compressed'], // 可以指定是原图还是压缩图,默认二者都有
    sourceType: ['album'], // 可以指定来源是相册还是相机,默认二者都有
    success(res) {
        const src = res.tempFilePaths[0]
        wx.getFileSystemManager().readFile({
            filePath: src,
            success: buffer => {
                wx.showLoading({
                    title: '图片合规性检查中', 
                    mask: true
                })
                wx.cloud.callFunction({
                    name: 'imgSecCheck', // 之前创建的云函数名称
                    data: {
                        value: buffer.data // 传入的值
                    }
                }).then(res => {
                    wx.hideLoading()
                    if (res.result.errCode === 87014) {
                        wx.showToast({
                            title: '图片违规,请重新上传其他图片',
                            icon: 'none'
                        })
                    } else if (res.result.errCode === 0) {
                        // 图片内容正常 TODO
                    } else {
                        wx.showToast({
                            title: '检测出错,错误码为:' + res.result.errCode,
                            icon: 'none'
                        })
                    }
                }).catch(error => {
                    wx.hideLoading()
                    console.log(error)
                    wx.showToast({
                        title: `检测出错,请重试`,
                        icon: 'none'
                    })
                })
            }
        })
    }
})  

6、遇到问题

编写完小程序端代码后,使用起来很顺利,看官方描述图片大小限制为1m,然后用PS生成了一张5M左右的图片上传识别,本来准备看一下超过大小限制后的报错信息,没想到云函数正确返回了数据,完美,提交代码。

提交后使用真机测试体验版,发现怎么上传都没有用,然后使用真机调试看了一下报错信息:

云函数调用报错

看了一会云开发错误码后没有得到有效的信息,以为是图片大小超过了1M,便多尝试了几张图片,发现结果都是一样的,直到上传了一张几乎为纯白色的图片接口才返回数据。计算了一下这些图片的大小,发现只有几十k大小的图片才有几率能被接口识别,超过100k大小的图片都是报错。文档中说好的图片大小限制为1m呢?

7、更换实现方法

在经历了一系列百度搜索后,自己依旧没有找到问题的解决办法(有知道问题所在原因的小伙伴还希望在评论区指导一下),便决定更换一种实现方法,先将图片上传到云端,然后然云函数在云端下载上传后的图片进行识别。

8、开通存储功能

在微信开发者工具-云开发-存储中开通云存储功能,然后新建一个temp文件夹:

开通云存储功能

9、修改小程序端代码

先将图片上传,获取到文件id后传给云函数:

wx.chooseImage({
    count: 1, // 默认9
    sizeType: ['compressed'], // 可以指定是原图还是压缩图,默认二者都有
    sourceType: ['album'], // 可以指定来源是相册还是相机,默认二者都有
    success(res) {
        const src = res.tempFilePaths[0]
        wx.showLoading({
            title: '上传中',
            mask: true
        })
        wx.cloud.uploadFile({
            // 指定上传到的云路径
            cloudPath: 'temp/' + new Date().getTime() + "-" + Math.floor(Math.random() * 1000),
            // 指定要上传的文件的小程序临时文件路径
            filePath: src,
            // 成功回调
            success: res => {
                wx.hideLoading()
                const fileID = res.fileID
                wx.showLoading({
                    title: '图片合规性检查中',
                    mask: true
                })
                wx.cloud.callFunction({
                    name: 'imgSecCheck', // 之前创建的云函数名称
                    data: {
                        value: fileID // 传入的值
                    }
                }).then(res => {
                    wx.hideLoading()
                    if (res.result.errCode === 87014) {
                        wx.showToast({
                            title: '图片违规,请重新上传其他图片',
                            icon: 'none'
                        })
                    } else if (res.result.errCode === 0) {
                        // 图片内容正常 TODO
                    } else {
                        wx.showToast({
                            title: '检测出错,错误码为:' + res.result.errCode,
                            icon: 'none'
                        })
                    }
                }).catch(error => {
                    wx.hideLoading()
                    console.log(error)
                    wx.showToast({
                        title: `检测出错,请重试`,
                        icon: 'none'
                    })
                })
            },
            fail: error => {
                wx.hideLoading()
                console.log(error)
                wx.showToast({
                    title: '图片上传出错,请重试',
                    icon: 'none'
                })
            }
        })
    }
})

10、修改云函数

云函数首先拿到文件id下载文件,然后再进行图片内容识别。由于我这边图片用完后不需要保存,所以在识别完成后将图片删除,以免占用过多的免费存储空间:

// 云函数入口文件
const cloud = require('wx-server-sdk')

cloud.init({
  env: 'your env'
})

// 云函数入口函数
exports.main = async (event, context) => {
  const file = await cloud.downloadFile({
    fileID: event.value
  })

  try {
    const res = await cloud.openapi.security.imgSecCheck({
      media: {
        contentType: 'image/png',
        value: file.fileContent
      }
    })

    cloud.deleteFile({
      fileList: [event.value]
    })

    return res
  } catch (error) {
    return error
  }
}

11、体验

最终效果可以扫描下方小程序码,然后在自定义二维码-自定义背景图-生成图片中体验。

二维码美化扫码体验

最后修改:2021 年 01 月 31 日 02 : 29 PM
如果觉得我的文章对你有用,请随意赞赏