前几天微信弹了一个通知,说是可以一块钱买一个小票机,都一块钱了那也就没有不要的道理,于是买回来了。

到货之后才发现,这玩意儿是有内置联通卡的,除了微信小票,其他啥也不能打,那我买回来干〇毛啊,整整5卷纸我又不是真的商户什么时候才能用完。
搜了一下,唯一一个有记载的就是N站的一个帖子 1元买了台微信收款小票机4G版P5 ,但是也并没有什么用,里面没有任何有用的消息。在多方询问下,得知,后台小程序里有一个可以给小票自定义推广位的页面,在那里设置完推广位之后,选择打印,就能打印推广位了。
如果你这个时候不小心打开了抓包软件,就能在里面找到
https://xxxxxxxxxx/smartqr/printerad/printad从api名称就能看到,这个接口确实是留给打印广告的,里面的内容大致为
{
"device_sn": "",
"ad_content": {
"user_define_template": {
"root": [
{
"text": {
"column": [
{
"value": "123"
}
],
"column_align": [
{}
]
}
}
]
}
},
"account_type": ,
"sid": ""
}聪明的你一定就知道下一步该做什么了,随后,你就可以用这个小票机打印你想打印的东西了。
但还没完,只知道能打印文字那也太无聊了,这个小票机能做到的上限是什么呢,在和gpt一起捣鼓了两天之后,也算是把目前能做到摸了个大概了。
如果你懒得看下面的内容的话,可以直接下载WeChat Printer进行使用

PS:这里的sid是有有效期的,过期之后得重新抓一次
接口结构
所有打印内容都通过:
{
"ad_content": {
"user_define_template": {
"root": []
}
}
}发送。
其中 root 是一个数组。
数组中的元素会按照顺序从上到下依次打印。
目前确认存在三种组件:
- content(表格/文本)
- icon(二维码/图片)
- text(简单文本)
content:最重要的组件
目前绝大多数排版都是通过 content 完成的。
例如:
{
"content": {
"column_align": [
{
"column_width": 20,
"style": {
"justification": 0
}
},
{
"column_width": 10,
"style": {
"justification": 2
}
}
],
"lines": {
"linelist": [
{
"column": [
"可乐",
"3"
]
}
]
},
"maxcolumn": 2,
"style": {
"height": 0,
"width": 0
}
}
}列数
目前已经验证:
1列
2列
3列
5列都可以正常工作。
五列表格测试结果也完全正常。
例如:
# 项目 单价 数量 小计
1 手冲咖啡超大杯 28 2 56列宽
column_width 不是实际宽度。
而是权重。
例如:
10 : 20和:
20 : 40最终效果完全一致。
因此可以理解为类似 CSS 的 flex 权重。
对齐
{
"style": {
"justification": 0
}
}对应:
0 = 左对齐
1 = 居中
2 = 右对齐无论是整行还是单列都支持,图片/二维码/表格也都支持用这个设置对齐方式。
字体大小
目前确认:
height = 0
width = 0标准字体。
height = 1
width = 1双倍字体。
height = 2
width = 2也能正常使用。你也可以单独设定height和width的值,例如
height = 1
width = 0就可以得到一个窄窄的字,反之则是宽宽的字。在不能换字体的情况下,也算是多了一点可玩性。
自动换行
如果某列文字超出分配宽度:
手冲咖啡超大杯会自动折行,而且不会影响其它列,例如:
手冲咖啡超
大杯右边价格列依旧保持正常对齐,排版逻辑比我想象中完善很多。
content 的一个坑
我原本以为
{
"lines": {
"linelist": [
{...},
{...}
]
}
}可以实现多行表格,结果直接打印空白。这玩意儿还不能和其他的小票机一样content里面塞完整个小票的内容,一个 content 节点只能渲染一行。如果要实现:
商品A
商品B
商品C就只能这样写
{
"root": [
{ "content": {...} },
{ "content": {...} },
{ "content": {...} }
]
}icon:二维码与图片
二维码
在官方小程序中,二维码是这样实现的
{
"icon": {
"type": 1,
"value": "https://example.com"
}
}value的值并不是一个图片链接,而是一个链接,在多次测试后得知
type = 1就是二维码组件,value既可以是 URL,也可以是任意字符串,最后打印的时候会自动转换成二维码打印出来。但是这个小票机的精度很低,这里塞的值太长的话,二维码容易糊在一起,就扫不了了。
图片
依旧是官方小程序,图片就简单多了,是这样实现的
{
"icon": {
"type": 3,
"value": "https://example.com/test.png"
}
}type = 3也就是图片组件了,我刚开始以为图片的url只能用官方的接口,或者只能用腾讯的域名,毕竟那张联通卡很有可能是一个物联卡,可能并不能访问非腾讯的资源,但是我错了,这里的url什么都能填,唯一需要注意的是,url不能太长,太长小票机就会读不到图片了。
以及不管你传入什么尺寸的图片,都只会按照固定大小和固定比例1:1打印出来,而且如果是png图片,透明像素会被填充为黑色。
进阶:灰度图片
这里踩了很久的坑,由于小票机只能打印黑色,所以这里打印图片都会被二值化,根本没法看,唯一的解决办法就是在交给小票机之前,手动将图片抖动处理比如Floyd-Steinberg,Atkinson,Bayer,处理之后,图片中灰色的地方就能用密集度不一样的小点打印出来,视觉上看起来就会有颜色的过渡。
其他 type
其他的type我也试过了,要么打印出来是空白,要么服务器直接拒绝了,摸黑测试过于困难于是就放弃了,交给有缘人吧
text:简单文本组件
除了 content 之外,还存在一个组件
{
"text": {
"value": "Hello World"
}
}不过目前看比较鸡肋,因为它的样式基本不会生效,字体大小也无法调整,除非你懒得写太多东西进json,否则大多数场景下直接用 content 更方便,能自定义的东西也更多。
特殊控制符
目前发现一个有意思的地方。
{
"text": {
"value": "__EOL__"
}
}会输出一个空白行,相当于换行符,但
__LINE__
__CUT__只会被当作普通文字打印出来。
可以打印的特殊字符
特殊符号
∞、。·ˉˇ¨〃々—~‖…‘’“”〔〕〈〉《》「」『』〖〗【】
±×÷∶∧∨∑∏∪∩∈∷√⊥∥∠⌒⊙∫∮≡≌≈∽∝≠≮≯≤≥
∵∴♂♀°′″℃$¤¢£‰§№☆★○●◎◇◆□■△▲※
→←↑↓〓〡〢〣〤〥〦〧〨〩㊣
㎎㎏㎜㎝㎞㎡㏄㏎㏑㏒㏕
︰¬¦℡ˊˋ˙–―‥‵℅℉
↖↗↘↙∕∟∣≒≦≧⊿
═║╒╓╔╕╖╗╘╙╚╛╜╝╞╟╠╡╢╣╤╥╦╧╨╩╪╫╬
╭╮╯╰╱╲╳
▁▂▃▄▅▆▇█▉▊▋▌▍▎▏▓▔▕
▼▽◢◣◤◥☉⊕〒〝〞罗马数字
ⅰⅱⅲⅳⅴⅵⅶⅷⅸⅹ
ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ带圈、带括号数字
⒈⒉⒊⒋⒌⒍⒎⒏⒐⒑⒒⒓⒔⒕⒖⒗⒘⒙⒚⒛
⑴⑵⑶⑷⑸⑹⑺⑻⑼⑽⑾⑿⒀⒁⒂⒃⒄⒅⒆⒇
①②③④⑤⑥⑦⑧⑨⑩
㈠㈡㈢㈣㈤㈥㈦㈧㈨㈩拼音字母
āáǎàēéěèīíǐìōóǒòūúǔùǖǘǚǜü希腊字母
ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ
αβγδεζηθικλμνξοπρστυφχψω已确认可打印的上标样式字符
˙ * ′已知支持的能力
目前已经确认支持:
- 普通文本
- 大字体
- 超大字体
- 自动换行
- 左中右对齐
- 单列表格
- 双列表格
- 三列表格
- 五列表格
- 二维码
- 图片 URL
- 图文混排
- 空白行
目前还没搞清楚的部分
虽然已经能正常打印复杂内容了,但还有几个地方没测试:
root 最大节点数
目前还没测试过上限,理论上应该存在服务端限制,但谁能写那么多东西呢,大不了多打几次嘛
是否存在更多组件
目前只发现:
content
icon
text三个组件,不确定是否存在
barcode
line
table之类隐藏组件。
icon.type 是否还有其它合法值
目前已知
1 = QRCode
3 = Image但理论上应该还有其它枚举值,只是暂时没找到。
type:2的话能被服务器接受,但是打出来是空白
总结
折腾了半天发现这玩意儿也没什么好玩的,所以搓了一个小程序让他可以打印聊天记录,找不到我人的时候就可以飞鸽传书了。但每次打印的时候都有一个巨大的语音播报,所以干脆拆机给喇叭拔了。至于他还能做什么呢,我也就不知道了,等其他有缘人来折腾吧。
5 条评论
撕了一下电源附近的贴纸,发现露出了一个micro usb但是插上好像没有用?不知道作者有做过测试吗(
以及这台设备是不是没有改装成USB打印机的可能性
我在我的p4上确实没找到除了电源意外的其他接口
可以看看拆开之后电源的那个小板
原来还有这个接口吗,我去琢磨琢磨