技术饭
微信公众号开发一物一码功能与扫码跳转小程序
需求是要用到微信公众号的一物一码功能,申请一批二维码并进行激活,将这些二维码分发到商品上,用户通过扫描二维码可以跳转到小程序,然后进入到我们自己的业务逻辑存储数据进行后续分析。看了官方的开发文档了,发现一物一码功能也是上线不久,网上并没有太多的开发经验。所以折腾了几个小时,终于大概弄清楚了,也不会特别复杂,说白了就是:公众号的一个插件,用来批量生成商品二维码,扫码之后跳转到小程序的页面。不过开通一码一物的流程可能比较慢。
前期准备、开发
1. 申请一物一码功能
已认证服务号的插件菜单申请一物一码功能,申请通过后会收到邮件得到一串秘钥,这个秘钥要留着用来解密二维码包。
2. 申请及获取二维码
公众号申请一物一码功能通过之后就可以进行二维码的申请及获取了。可以查看微信公众号一物一码接口文档。
1)、业务流程图
2)、扫码业务流程图
3)、申请二维码接口
API:https://api.weixin.qq.com/intp/marketcode/applycode?access_token=ACCESSTOKEN
ACCESSTOKEN参见接口规则说明。
请求参数:
code_count是你要申请码的数量,最少一万个,外部单号是我们自定义的一个字符串,例如我们要申请一个商品的码,就可以用这个商品的名称例如product-01作为外部单号,然后外部单号和商品类型的映射关系自己要记好,因为在后面的步骤中还要用到。这里申请二维码的操作我们可以直接通过postman完成,先去用公众号的AppID和AppSecret调用获取access_token的接口,然后用access_token去调用申请接口就可以了。
调用申请接口成功后,会返回一个application_id:
返回参数:
在这里最好是把外部单号和申请单号(isv_application_id和application_id)这两个参数统一保存好,总之就是能够找到对应商品就行。下一步我们就可以查询二维码申请单的状态了。
4)、查询二维码申请单接口
API:https://api.weixin.qq.com/intp/marketcode/applycodequery?access_token=ACCESSTOKEN ACCESSTOKEN参见接口规则说明。
请求参数:
这里的参数就用到了我们上一步申请时使用的外部单号以及接口得到的申请单号,用这两个参数去进行查询,返回参数如下:
返回参数:
status参数从INIT到FINISH,大概要经过三到五分钟左右,FINISH之后就可以去下载二维码包了。
5)、下载二维码包接口
API:https://api.weixin.qq.com/intp/marketcode/applycodedownload?access_token=ACCESSTOKE ACCESSTOKEN参见接口规则说明。
请求参数:
返回参数:
这里建议用postman来调下载二维码包接口,申请单号依旧来自之前的接口,code_start和code_end文档中没有说明,实践中发现一次最多只能下载1w个,超过了就会报错,所以如果申请了5w个二维码,那么就需要调用五次接口,分五段下载。
在postman中我们选择send选项中的send and download,就可以直接将返回的数据保存到json文件中。如果点击send之后等待数据返回再保存为文件那么有很大的可能会导致卡死,建议使用send and download。
包含1w个二维码的码包数据是5Mb左右,返回的数据中buffer参数是经过base64加密的,如下所示:
拿到返回的数据后我们就可以进行解密处理。官方文档的描述如下:
解密说明
实名数据的加密方式使用AES的CBC模式,iv使用加解密钥,填充使用PKCS7Padding,最后使用base64进行编码。
解密时,先进行base64解码,然后使用密钥及AES/CBC/PKCS7Padding进行解密。 密钥在申请实名接口权限时,会提供到申请方。
解密秘钥就是在申请一物一码功能通过后通过邮件发送到申请人的一串码,我这里用nodejs写了解密的方法,引了crypto解密,解密方法如下:
function jiemi(body) {
var iv = 'YVN+HNPxfJVPxMwS' // 一物一码的秘钥
var clearEncoding = 'utf8'
var cipherEncoding = 'base64'
var key = 'YVN+HNPxfJVPxMwS'
var cipherChunks = []
var decipher = crypto.createDecipheriv('aes-128-cbc', key, iv)
cipherChunks.push(decipher.update(body, cipherEncoding, clearEncoding))
cipherChunks.push(decipher.final(clearEncoding))
var decryption = cipherChunks.join('')
return decryption
}
let bitmap = jsonFile.buffer;
let jie = jiemi(bitmap)
fs.writeFileSync('data.txt', jie);
将buffer的值进行解密,解密后写入文件即可得到二维码的原始数据。二维码包数据如下:
1111111100111111111100000110001100000110111010110010111011011101011101011101101110100100101110110000011010110000011111111110111111111110001100010110001100011011010000011001000110010010111101101110100101101101111000110100101001111111111111000100110100000110011111000110111010101011110111011101010100000001101110100100011011110000011001010110101111111100011000111 043E.NS%E 0 P.URL.CN/0HSHWR.AZKSYOC7UYZG1111111100111111111100000111011100000110111010101010111011011101010001011101101110101110101110110000011101110000011111111110111111111110001100100110001100100111110101111100010100110111101000111100100001011111111000110101101000001111111110101100110100000111001000000010111010011001010011011101000101010100101110101111001001110000011001000111011111111100110000111 043E.NS%F 1 P.URL.CN/0EPQ.X3B$DLKAQLVZ/I
解密后的数据格式为:
a1 b1 c1 d1
a2 b2 c2 d2
即以 /n 换行,每行四个元素以 /t 分隔。
a为361字节的01点阵,用于支持生成19*19的微型码,0为白,1为黑,
b为原始码数据,最长9位,
c为该码在此次申请的索引位置,
d为28位字符,用于支持转为普通二维码。可生成码制2,纠错等级Q的二维码。
在我们处理好所有的二维码包数据后,就可以将文件发给印刷厂进行印刷,那边会有解析程序解析二维码,作为开发只要关心9位的原始码数据即可,也是后面我们进行扫码操作时要用到的数据。
6)、激活二维码
因为申请码、激活码以及开发小程序这几个动作都可以并行,所以我们可以先去申请二维码拿去印刷,在这期间进行小程序的开发,等到二维码要投入应用时再进行激活。
二维码的激活可以多次重复激活,建议在批量印刷前先拿到几个样码单独激活给开发人员测试用,等到投入生产在重新激活。激活二维码接口如下:
激活二维码接口
API:https://api.weixin.qq.com/intp/marketcode/codeactive?access_token=ACCESSTOKEN
请求参数:
返回参数:
申请单号依旧是之前获取到的单号,活动名称、商品品牌、商品标题、商品条码这些都是自定义的参数,应该由产品来确定;appid是我们扫码要跳转的小程序id,path就是要跳进来的小程序路径(例如'pages/index/index'),wxa_type可以设置正式版开发版体验版,想要开发测试就传1或2,最后生产环境再重新激活就可以了。
7)、查询二维码激活状态接口
API:https://api.weixin.qq.com/intp/marketcode/codeactivequery?access_token=ACCESSTOKEN
这里提供两种查询方式:1)传入application_id和code_index;2)传入九位原始码code或28位普通码字符code_url。 返回原始码信息和激活状态,可以在小程序内扫码等场景使用。
请求参数:
返回参数:
8)、小程序扫码
在激活成功后可以进行扫码了,扫码后我们会获得一个参数code_ticket,这个参数在onLoad回调方法中可以拿到:
onLoad: function (options) {
console.log(options.code_ticket)
},
然后再通过wx.login方法以及jscode2session方法拿到扫码用户的openid,用这两个参数调用公众号的tickettocode接口:
code_ticket换code接口
API:https://api.weixin.qq.com/intp/marketcode/tickettocode?access_token=ACCESSTOKEN ACCESSTOKEN参见接口规则说明。
请求参数:
返回参数:
入参示例:
{
"code_ticket":"6cb4bc95e1f1abc97034cbe8fd484989",
"openid":"oiV2luCau8Cx0TMOy9lvZSLqRcKc"
}
返回示例:
{
"errcode": 0,
"errmsg": "ok",
"code": "8",
"code_start": 0,
"code_end": 200,
"activity_name": "test_name",
"product_brand": "test_brand",
"product_title": "test_title",
"product_code": "test_code",
"wxa_appid":"wx3sxjifjwojfsffef",
"wxa_path":"pages/index/index",
"application_id":581865877,
"isv_application_id":"test_id"
}
接口返回的code参数就是二维码的原始码值,我们就可以继续走自己的业务逻辑进行相应的处理了。
这里需要注意的是,要区分好小程序和公众号的接口以及access_token的获取,在我们自己的业务后台应该将两种appId和appSecret区分,获取的access_token不要混淆了,以免在调试过程中浪费时间。
参考:
文明上网理性发言!