9月30日晚上,突然收到一条微信,提示 图片水印工具 因涉嫌违规,封禁“被搜索”能力,如下图所示。
第一反应这是个误会。图片水印工具是一个本地小程序,仅在用户的手机本地对图片进行处理。不涉及任何网络传输,没有服务端,用户也不无法把自己的图片分享给他人,不可能存在“内容安全”相关的问题。小程序上线一年半,没有扩展新的功能,最近一次更新是一年前修复一个小 bug。

我郁闷了,看来这次禁封不是误会。
怎么解决呢?在Google的帮助下,知道了真相,原来9月底大量图片处理相关的小程序在毫无征兆的情况下被封禁,看来图片水印工具被封禁不是个例啊。很多网友给出了解决方案:对于图片处理的小程序,都应该接入微信的安全检查 API:imgSecCheck,即所有的图片在处理之前,都应该使用 imgSecCheck 进行检查,连本地运行的小程序也不例外。
改吧,人在屋檐下,不得不低头。
思路
在小程序的内容安全中找到 security.imgSecCheck 函数的说明,这个函数必须在服务端调用,需要给它传 2 个参数,1个是 accessToken,一个是图片的内容。
图片水印工具是一个纯客户端的应用,没有服务端。如果要调用 imgSecCheck,那必须增加一台服务器,做 2 件事情:1. 在服务器端维护好 accessToken,保证每2小时更新一次;2.增加一个 API 供小程序端调用,当小程序调用这个API时,服务端调用 imgSecCheck,并把返回值返回给小程序。
为了增加一个内容安全检查的功能,增加一台服务器,成本有点高。有没有其他的方案呢?
庆幸的是,微信最近引入了云开发的功能。采用云开发作为服务端,应该可以节省不少成本。
实现
那就决定采用云开发。
先在本机搭建云开发环境,云开发的服务端是 nodejs。详细步骤可参见:小程序云开发全套实战教程,本文不再赘述。
接下来,创建云开发(服务端)的API,命名为 imgSecCheck,在index.js文件中加入安全内容检查的代码,代码如下:
// 云函数入口文件
const cloud = require('wx-server-sdk')
// 初始化云开发
cloud.init()
// 云函数入口函数
exports.main = async (event, context) => {
const wxContext = cloud.getWXContext()
var imgType = event.contentType;
var imgContent = event.value;
var buffer = Buffer.from(imgContent);
try {
var result = await cloud.openapi.security.imgSecCheck({
media: {
contentType: imgType,
value: buffer
}
})
return result
} catch (err) {
return err
}
}
我们来读一下这段代码。第 10 行、11行先读取两个参数 contentType、value,其中 contentType 是图片类型,可能值是“image/png”、“image/jpg”等常见的图片类型,第二个值是图片数据,类型为 ArrayBuffer。
由于 腾讯的图片内容检查函数可接受的图片数据为 Buffer,所以需要使用 Buffer.from() 转换成 Buffer。第15行 ~ 第20行是调用腾讯的内容检查函数security.imgSecCheck,获取结果之后再返回给小程序端。
本来在调用 security.imgSecCheck 函数时,需要传入参数 access_token,以确保调用方的可信度。在腾讯看来,云开发环境是天然的可信方,所以云开发在调用时无需 access_token。
以上是服务端的实现,现在我们开发小程序端。
首先,通过 wx.getImageInfo() 获取图片的类型,然后使用 wx.getFileSystemManager().readFile() 读取文件,获取的数据 res.data 即是文件 Buffer,最后调用刚才开发的云函数既可以了。详细代码如下:
var imgType = res.Type;
wx.getFileSystemManager().readFile({
filePath: fileTypeValue,
success: function (res) {
wx.cloud.callFunction({
// 云函数名称
name: 'imgSecCheck',
// 传给云函数的参数
data: {
contentType: 'image/' + imgType,
value: res.data,
},
success: function (res) {
if( res.result && res.result.errCode == 0 )
{
...
}else
{
wx.showToast({
title: '根据腾讯规定,此图片不符合安全规范,不予显示。',
icon: 'none',
duration: 3000
});
}
},
fail: function( res )
{
...
}
});
});
最后,把服务端代码上传到云开发环境,就可以运行了。
总结

使用云开发环境,免去了 access_token 的维护工作,一定程度上也简化了开发,挺好的。
在重新提交代码之后,很快就审批了,我也把它提交上线了。
只是,我心里仍旧有很深的疑虑:一个在用户本地处理图片的小程序,无需上传图片,也没有分享功能,怎么可能存在内容不安全因素呢?加上内容安全检查功能,一方面增加开发者的工作量;另一方面,在浪费用户流量的同时,也影响了小程序的性能;另外,腾讯公司不得不耗费大量的人力物力进行审核工作,对任何一方而言,没有人受益。我不禁要问:这个内容安全检查功能真的这么重要吗?
除了刚才提到的成本损失外,在毫无征兆的情况下,大面积封禁小程序,已有的开发者对小程序的信心恐怕会大打折扣,而正在犹豫是否要开发的小程序的开发者,很有可能会打退堂鼓。
后续
增加“安全内容检查”之后,重新提交上线了。可是“被搜索”功能仍旧被限制。我也找不到任何申诉渠道。也就是说,从今以后,用户无论如何都搜索不到 图片水印工具 这个小程序了。向小程序的客服反馈,也没有回音。
国庆之后的10天,每天的新增用户只有以前的10%。看着断崖式下跌的新增用户数,心里在滴血。
当然,我是幸运的。在尝试各种渠道之后,今天早上恢复了“被搜索”功能。但我心里的石头仍旧悬着,下一次毫无征兆地封禁什么时候到来呢?


我的小程序也被封了,请问怎么解封啊?
—–
[Frank回复] 先修改小程序,接入图片审查的API,提交小程序。然后到小程序的论坛上,直接提单,让客服介入就可以了。