晨旭的博客
你想干什么!
晨旭的博客~
简单解析微信、支付宝,付款码的条形码生成原理

最近做了一个项目,其中用到了条形码的生成,为了避免时间太长自己忘记相关的知识点,同时也为了方便给后来人减少一些坑,所以就先用这篇文章做一个简单的记录。
by chenxublog.com

付款码用的条形码编码规则

条形码编码规则有不少,付款码现在用的是Code128编码规则。

Code128编码的特性

  • 具有A、B、C三种不同的编码类型,可提供标准ASCII中128个字元的编码使用

  • 允许双向扫描(正着反着都能扫)

  • 可自行决定是否加上检验位(但付款码必须要校验位)

  • 条码长度可调,但包括开始位和结束位在内,不可超过232个字元(付款码也就十几二十位数字)

  • 同一个128码,可以由A、B、C三种不同编码规则互换,既可扩大字元选择的范围,也可缩短编码的长度(这点十分重要,后面会讲到)

优先选用的编码规则

由于编码规则越复杂,二维码就越复杂,所以条形码编码优先使用的是Code128C这个编码规则。

Code128C将数字两个两个组合在一起,大大减小了条码的复杂度。

code128的编码规则

为了方便表达,我们用b代表一条黑色像素宽度的线,s代表一条白色像素宽度的线,当bs组合时,中间不留任何缝隙

ABC三种编码的编码表如下,后面会用到这张表:

ID Code128A Code128B Code128C BandCode 编码值
0 SP  SP 0 212222 bbsbbssbbss
1 ! ! 1 222122 bbssbbsbbss
2 2 222221 bbssbbssbbs
3 # # 3 121223 bssbssbbsss
4 $ $ 4 121322 bssbsssbbss
5 % % 5 131222 bsssbssbbss
6 & & 6 122213 bssbbssbsss
7 7 122312 bssbbsssbss
8 ( ( 8 132212 bsssbbssbss
9 ) ) 9 221213 bbssbssbsss
10 * * 10 221312 bbssbsssbss
11 + + 11 231212 bbsssbssbss
12 , , 12 112232 bsbbssbbbss
13 13 122132 bssbbsbbbss
14 . . 14 122231 bssbbssbbbs
15 / / 15 113222 bsbbbssbbss
16 0 0 16 123122 bssbbbsbbss
17 1 1 17 123221 bssbbbssbbs
18 2 2 18 223211 bbssbbbssbs
19 3 3 19 221132 bbssbsbbbss
20 4 4 20 221231 bbssbssbbbs
21 5 5 21 213212 bbsbbbssbss
22 6 6 22 223112 bbssbbbsbss
23 7 7 23 312131 bbbsbbsbbbs
24 8 8 24 311222 bbbsbssbbss
25 9 9 25 321122 bbbssbsbbss
26 : : 26 321221 bbbssbssbbs
27 ; ; 27 312212 bbbsbbssbss
28 < < 28 322112 bbbssbbsbss
29 = = 29 322211 bbbssbbssbs
30 > > 30 212123 bbsbbsbbsss
31 ? ? 31 212321 bbsbbsssbbs
32 @ @ 32 232121 bbsssbbsbbs
33 A A 33 111323 bsbsssbbsss
34 B B 34 131123 bsssbsbbsss
35 C C 35 131321 bsssbsssbbs
36 D D 36 112313 bsbbsssbsss
37 E E 37 132113 bsssbbsbsss
38 F F 38 132311 bsssbbsssbs
39 G G 39 211313 bbsbsssbsss
40 H H 40 231113 bbsssbsbsss
41 I I 41 231311 bbsssbsssbs
42 J J 42 112133 bsbbsbbbsss
43 K K 43 112331 bsbbsssbbbs
44 L L 44 132131 bsssbbsbbbs
45 M M 45 113123 bsbbbsbbsss
46 N N 46 113321 bsbbbsssbbs
47 O O 47 133121 bsssbbbsbbs
48 P P 48 313121 bbbsbbbsbbs
49 Q Q 49 211331 bbsbsssbbbs
50 R R 50 231131 bbsssbsbbbs
51 S S 51 213113 bbsbbbsbsss
52 T T 52 213311 bbsbbbsssbs
53 U U 53 213131 bbsbbbsbbbs
54 V V 54 311123 bbbsbsbbsss
55 W W 55 311321 bbbsbsssbbs
56 X X 56 331121 bbbsssbsbbs
57 Y Y 57 312113 bbbsbbsbsss
58 Z Z 58 312311 bbbsbbsssbs
59 [ [ 59 332111 bbbsssbbsbs
60 \ \ 60 314111 bbbsbbbbsbs
61 ] ] 61 221411 bbssbssssbs
62 ^ ^ 62 431111 bbbbsssbsbs
63 _ _ 63 111224 bsbssbbssss
64 NUL ` 64 111422 bsbssssbbss
65 SOH a 65 121124 bssbsbbssss
66 STX b 66 121421 bssbssssbbs
67 ETX c 67 141122 bssssbsbbss
68 EOT d 68 141221 bssssbssbbs
69 ENQ e 69 112214 bsbbssbssss
70 ACK f 70 112412 bsbbssssbss
71 BEL g 71 122114 bssbbsbssss
72 BS h 72 122411 bssbbssssbs
73 HT i 73 142112 bssssbbsbss
74 LF j 74 142211 bssssbbssbs
75 VT k 75 241211 bbssssbssbs
76 FF I 76 221114 bbssbsbssss
77 CR m 77 413111 bbbbsbbbsbs
78 SO n 78 241112 bbssssbsbss
79 SI o 79 134111 bsssbbbbsbs
80 DLE p 80 111242 bsbssbbbbss
81 DC1 q 81 121142 bssbsbbbbss
82 DC2 r 82 121241 bssbssbbbbs
83 DC3 s 83 114212 bsbbbbssbss
84 DC4 t 84 124112 bssbbbbsbss
85 NAK u 85 124211 bssbbbbssbs
86 SYN v 86 411212 bbbbsbssbss
87 ETB w 87 421112 bbbbssbsbss
88 CAN x 88 421211 bbbbssbssbs
89 EM y 89 212141 bbsbbsbbbbs
90 SUB z 90 214121 bbsbbbbsbbs
91 ESC { 91 412121 bbbbsbbsbbs
92 FS | 92 111143 bsbsbbbbsss
93 GS } 93 111341 bsbsssbbbbs
94 RS ~ 94 131141 bsssbsbbbbs
95 US DEL 95 114113 bsbbbbsbsss
96 FNC3 FNC3 96 114311 bsbbbbsssbs
97 FNC2 FNC2 97 411113 bbbbsbsbsss
98 SHIFT SHIFT 98 411311 bbbbsbsssbs
99 CODEC CODEC 99 113141 bsbbbsbbbbs
100 CODEB FNC4 CODEB 114131 bsbbbbsbbbs
101 FNC4 CODEA CODEA 311141 bbbsbsbbbbs
102 FNC1 FNC1 FNC1 411131 bbbbsbsbbbs
103 StartA StartA StartA 211412 bbsbssssbss
104 StartB StartB StartB 211214 bbsbssbssss
105 StartC StartC StartC 211232 bbsbssbbbss
106 Stop Stop Stop 2331112 bbsssbbbsbsbb

对于某种条码的编码规则为:

开始位 + 后面所有的数据按顺序拼接 + 校验位 + 结束位

编码的103-106为起始位于结束位,只会在开头或结尾出现

我们首先使用一个简单的例子来解释如何使用三种编码方式进行条形码的编码:

需要编码成条形码的数据:1346

对于Code128A编码:

起始位(StartA:bbsbssssbss)+
数据位(Code128A中的1:bssbbbssbbs)+
数据位(Code128A中的3:bbssbsbbbss)+
数据位(Code128A中的4:bbssbssbbbs)+
数据位(Code128A中的6:bbssbbbsbss)+
校验位((StartA的id + Code128A中的1的id*1 + Code128A中的3的id*2 + Code128A中的4的id*3 + Code128A中的6的id*4) % 103 = (103 + 17*1 + 19*2 + 20*3 + 22*4) % 103 = 自己算去吧:Code128A中对应的id值所表示的编码)
停止位(Stop:bbsssbbbsbsbb)

对于Code128B编码:

B类编码和A几乎完全一样,只有起始位和校验位所使用的开头不一样:

起始位(StartB:bbsbssbssss)+
数据位(Code128B中的1:bssbbbssbbs)+
数据位(Code128B中的3:bbssbsbbbss)+
数据位(Code128B中的4:bbssbssbbbs)+
数据位(Code128B中的6:bbssbbbsbss)+
校验位((StartB的id + Code128B中的1的id*1 + Code128B中的3的id*2 + Code128B中的4的id*3 + Code128B中的6的id*4) % 103 = (104 + 17*1 + 19*2 + 20*3 + 22*4) % 103 = 自己算去吧:Code128B中对应的id值所表示的编码)
停止位(Stop:bbsssbbbsbsbb)

对于Code128C编码:

Code128C编码时,只能编码数字内容,并且在编码前会将偶数个的数字两个两个分为一组,进行编码:

起始位(StartC:bbsbssbbbss)+
数据位(Code128C中的13:bssbbsbbbss)+
数据位(Code128C中的46:bsbbbsssbbs)+
校验位((StartC的id + 数据位1*1 + 数据位2*2) % 103 = (105 + 13*1 + 46*2) % 103 = 自己算去吧:Code128C中对应的值所表示的编码)
停止位(Stop:bbsssbbbsbsbb)

这时候就应该可以明白,为什么付款码优先使用的是Code128C编码了。

实际的例子

95270078用Code128A表示的结果为:

bbsbssssbss开头
bbbssbsbbss数据位
bbsbbbssbss数据位
bbssbbbssbs数据位
bbbsbbsbbbs数据位
bssbbbsbbss数据位
bssbbbsbbss数据位
bbbsbbsbbbs数据位
bbbsbssbbss数据位
bbsbbbssbss校验位
bbsssbbbsbsbb停止位

即:bbsbssssbssbbbssbsbbssbbsbbbssbssbbssbbbssbsbbbsbbsbbbsbssbbbsbbssbssbbbsbbssbbbsbbsbbbsbbbsbssbbssbbsbbbssbssbbsssbbbsbsbb

实际使用

在实际按此方法使用的过程中,也遇到了一个坑,下面就简单讲一下这个坑人的地方

生成偶数位数字的条形码

这个简单,直接用Code128C编码方式编码即可,不再重复说明

生成奇数位数字的条形码

这个需求在一开始听到之后,我是十分疑惑的:完全不可能嘛!Code128C编码怎么可能生成一个奇数位数字的条形码呢?

不过在bing中翻阅过不少资料后,发现这个是可行的,原因在文章开头也讲到了:

同一个128码,可以由A、B、C三种不同编码规则互换,既可扩大字元选择的范围,也可缩短编码的长度

也就是说,我们可以在Code128C的编码中插入Code128A编码,以此来实现奇数位数字的表示,同时保证条形码不会太复杂,具体如下。

首先我们假定一个数字吧:7434012

第一步需要将数字分组:74、34、01、2

两位数的部分就用Code128C表示,一位数的部分就用Code128A表示。那么问题来了,校验位怎么求呢?这里经过查阅资料,校验位是要把Code128A的编码值也算进去,按code128C的校验值计算方法来计算。。。

具体编码结构如下:

Code128C的开始位
数据位74
数据位34
数据位01
Code128C编码中的`CODEA`(id为101)
数据位(Code128A中的2,id为18)
校验位=(StartC的id:105 + 74*1 + 34*2 + 1*3 + CODEA的id:101*4 + Code128A中2的id:18*5) % 103
停止位

其他编码方式开头,中途更换编码方式的算法也可以进行类推。

END

既然条码生成算法讲完了,下一篇文章就可以使用lua来生成条形码,显示到屏幕上面了

如果文章有错误,请在下方留言,谢谢!

赞赏
如非特殊说明,本站所有文章均采用知识共享 署名-非商业性使用-相同方式共享4.0国际许可协议(CC BY-NC-SA 4.0)进行许可。

发表评论

textsms
account_circle
email

晨旭的博客~

简单解析微信、支付宝,付款码的条形码生成原理
最近做了一个项目,其中用到了条形码的生成,为了避免时间太长自己忘记相关的知识点,同时也为了方便给后来人减少一些坑,所以就先用这篇文章做一个简单的记录。 by chenxublog.com …
扫描二维码继续阅读
2018-09-22