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,提交小程序。然后到小程序的论坛上,直接提单,让客服介入就可以了。