tracking_number 0.10.5 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. checksums.yaml +5 -5
  2. data/.github/FUNDING.yml +2 -0
  3. data/.github/dependabot.yml +22 -0
  4. data/.github/workflows/release.yml +36 -0
  5. data/.github/workflows/ruby.yml +35 -0
  6. data/.gitmodules +3 -0
  7. data/.tool-versions +1 -0
  8. data/CHANGELOG.md +318 -0
  9. data/Gemfile +4 -2
  10. data/README.md +112 -15
  11. data/Rakefile +4 -1
  12. data/bin/console +14 -0
  13. data/lib/data/couriers/amazon.json +45 -0
  14. data/lib/data/couriers/canadapost.json +33 -0
  15. data/lib/data/couriers/canpar.json +29 -0
  16. data/lib/data/couriers/dhl.json +97 -0
  17. data/lib/data/couriers/dpd.json +345 -0
  18. data/lib/data/couriers/fedex.json +291 -0
  19. data/lib/data/couriers/gofo.json +24 -0
  20. data/lib/data/couriers/landmark.json +26 -0
  21. data/lib/data/couriers/lasership.json +105 -0
  22. data/lib/data/couriers/old_dominion.json +65 -0
  23. data/lib/data/couriers/ontrac.json +74 -0
  24. data/lib/data/couriers/purolator.json +50 -0
  25. data/lib/data/couriers/s10.json +1443 -0
  26. data/lib/data/couriers/speedee.json +26 -0
  27. data/lib/data/couriers/ups.json +197 -0
  28. data/lib/data/couriers/usps.json +272 -0
  29. data/lib/data/couriers/yodel.json +29 -0
  30. data/lib/data/couriers/yunexpress.json +25 -0
  31. data/lib/tracking_number/active_model_validator.rb +1 -1
  32. data/lib/tracking_number/base.rb +291 -22
  33. data/lib/tracking_number/checksum_validations.rb +119 -0
  34. data/lib/tracking_number/info.rb +26 -0
  35. data/lib/tracking_number/loader.rb +82 -0
  36. data/lib/tracking_number/partnership.rb +7 -0
  37. data/lib/tracking_number/unknown.rb +45 -0
  38. data/lib/tracking_number/version.rb +1 -1
  39. data/lib/tracking_number.rb +69 -17
  40. data/package.json +77 -0
  41. data/test/partnership_test.rb +71 -0
  42. data/test/renamed_types_test.rb +44 -0
  43. data/test/test_helper.rb +14 -7
  44. data/test/tracking_number_meta_test.rb +145 -0
  45. data/test/tracking_number_test.rb +191 -0
  46. data/tracking_number.gemspec +53 -22
  47. data/yarn.lock +3425 -0
  48. metadata +131 -46
  49. data/.travis.yml +0 -12
  50. data/VERSION +0 -1
  51. data/lib/tracking_number/dhl.rb +0 -34
  52. data/lib/tracking_number/fedex.rb +0 -156
  53. data/lib/tracking_number/ontrac.rb +0 -34
  54. data/lib/tracking_number/ups.rb +0 -108
  55. data/lib/tracking_number/usps.rb +0 -166
  56. data/test/dhl_tracking_number_test.rb +0 -35
  57. data/test/fedex_tracking_number_test.rb +0 -75
  58. data/test/ontrac_tracking_number_test.rb +0 -24
  59. data/test/ups_tracking_number_test.rb +0 -36
  60. data/test/usps_tracking_number_test.rb +0 -73
@@ -0,0 +1,291 @@
1
+ {
2
+ "name": "FedEx",
3
+ "courier_code": "fedex",
4
+ "tracking_numbers": [
5
+ {
6
+ "name": "FedEx Express (12)",
7
+ "id": "fedex_12",
8
+ "regex": "\\s*(?<SerialNumber>([0-9]\\s*){11})(?<CheckDigit>[0-9]\\s*)",
9
+ "validation": {
10
+ "checksum": {
11
+ "name": "sum_product_with_weightings_and_modulo",
12
+ "weightings": [
13
+ 3,
14
+ 1,
15
+ 7,
16
+ 3,
17
+ 1,
18
+ 7,
19
+ 3,
20
+ 1,
21
+ 7,
22
+ 3,
23
+ 1
24
+ ],
25
+ "modulo1": 11,
26
+ "modulo2": 10
27
+ }
28
+ },
29
+ "tracking_url": "https://www.fedex.com/apps/fedextrack/?tracknumbers=%s",
30
+ "test_numbers": {
31
+ "valid": [
32
+ "986578788855",
33
+ "477179081230",
34
+ "799531274483",
35
+ "790535312317",
36
+ " 7 9 0 5 3 5 3 1 2 3 1 7 ",
37
+ "974367662710"
38
+ ],
39
+ "invalid": [
40
+ "996578788855"
41
+ ]
42
+ }
43
+ },
44
+ {
45
+ "name": "FedEx Express (34)",
46
+ "id": "fedex_34",
47
+ "regex": [
48
+ "\\s*[0-8]\\s*([0-9]\\s*){14}",
49
+ "(?<DestinationZip>([0-9]\\s*){5})",
50
+ "(?<SerialNumber>([0-9]\\s*){13})",
51
+ "(?<CheckDigit>[0-9]\\s*)"
52
+ ],
53
+ "validation": {
54
+ "checksum": {
55
+ "name": "sum_product_with_weightings_and_modulo",
56
+ "weightings": [
57
+ 1,
58
+ 7,
59
+ 3,
60
+ 1,
61
+ 7,
62
+ 3,
63
+ 1,
64
+ 7,
65
+ 3,
66
+ 1,
67
+ 7,
68
+ 3,
69
+ 1
70
+ ],
71
+ "modulo1": 11,
72
+ "modulo2": 10
73
+ }
74
+ },
75
+ "tracking_url": "https://www.fedex.com/apps/fedextrack/?tracknumbers=%s",
76
+ "test_numbers": {
77
+ "valid": [
78
+ "1001921334250001000300779017972697",
79
+ "1001921380360001000300639585804382",
80
+ "1001901781990001000300617767839437",
81
+ " 1 0 0 1 9 0 1 7 8 1 9 9 0 0 0 1 0 0 0 3 0 0 6 1 7 7 6 7 8 3 9 4 3 7 ",
82
+ "1002297871540001000300790695517286",
83
+ "1027590111820004833500785458233610",
84
+ "1195266473930007521100871079919940",
85
+ "1 1 9 52 6 64739 3000 75211 00 8710 799 199 40",
86
+ "1195271874060007521100871140316925",
87
+ "1195583874210007521100871140316936"
88
+ ],
89
+ "invalid": [
90
+ "1001901781990001000300617767839438"
91
+ ]
92
+ }
93
+ },
94
+ {
95
+ "name": "FedEx ASTRA (32)",
96
+ "id": "fedex_astra_32",
97
+ "description": "The legacy ASTRA barcode. Positions 17 through 28 hold a FedEx Express tracking number, and its check digit is the only one the barcode carries. What the other fields mean is not yet known.",
98
+ "regex": [
99
+ "\\s*3\\s*",
100
+ "(?:[0-9]\\s*){5}",
101
+ "(?:[0-9]\\s*){3}",
102
+ "(?:[0-9]\\s*){7}",
103
+ "(?<SerialNumber>(?:[0-9]\\s*){11})",
104
+ "(?<CheckDigit>[0-9]\\s*)",
105
+ "(?:[0-9]\\s*){4}"
106
+ ],
107
+ "validation": {
108
+ "checksum": {
109
+ "name": "sum_product_with_weightings_and_modulo",
110
+ "weightings": [3, 1, 7, 3, 1, 7, 3, 1, 7, 3, 1],
111
+ "modulo1": 11,
112
+ "modulo2": 10
113
+ }
114
+ },
115
+ "test_numbers": {
116
+ "valid": [
117
+ "32971514560102447849175802862014",
118
+ "32971510360102447848540980802018",
119
+ "32971508360102447847941133172013",
120
+ "33810799560000004380417923803212",
121
+ "3 29715 145 6010244 784917580286 2014"
122
+ ],
123
+ "invalid": [
124
+ "32971514560102447849175802852014",
125
+ "3297151456010244784917580286201"
126
+ ]
127
+ }
128
+ },
129
+ {
130
+ "name": "FedEx Ground",
131
+ "id": "fedex_ground",
132
+ "regex": "\\s*(?<SerialNumber>([0-9]\\s*){14})(?<CheckDigit>([0-9]\\s*))",
133
+ "validation": {
134
+ "checksum": {
135
+ "name": "mod10",
136
+ "modulo": 10,
137
+ "evens_multiplier": 1,
138
+ "odds_multiplier": 3,
139
+ "reverse": false
140
+ }
141
+ },
142
+ "tracking_url": "https://www.fedex.com/apps/fedextrack/?tracknumbers=%s",
143
+ "test_numbers": {
144
+ "valid": [
145
+ "0414 4176 0228 964",
146
+ "5682 8361 0012 000",
147
+ " 5 6 8 2 8 3 6 1 0 0 1 2 0 0 0 ",
148
+ "5682 8361 0012 734"
149
+ ],
150
+ "invalid": [
151
+ "5682 8361 0012 732"
152
+ ]
153
+ }
154
+ },
155
+ {
156
+ "name": "FedEx Ground (SSCC-18)",
157
+ "id": "fedex_ground_sscc_18",
158
+ "regex": "\\s*(?<ShippingContainerType>([0-9]\\s*){2})(?<SerialNumber>([0-9]\\s*){15})(?<CheckDigit>[0-9]\\s*)",
159
+ "tracking_url": "https://www.fedex.com/apps/fedextrack/?tracknumbers=%s",
160
+ "validation": {
161
+ "checksum": {
162
+ "name": "mod10",
163
+ "modulo": 10,
164
+ "evens_multiplier": 3,
165
+ "odds_multiplier": 1,
166
+ "reverse": false
167
+ }
168
+ },
169
+ "test_numbers": {
170
+ "valid": [
171
+ "00 0123 4500 0000 0027",
172
+ " 0 0 0 1 2 3 4 5 0 0 0 0 0 0 0 0 2 7 "
173
+ ],
174
+ "invalid": [
175
+ "000000000000000001"
176
+ ]
177
+ },
178
+ "additional": [
179
+ {
180
+ "name": "Container Type",
181
+ "regex_group_name": "ShippingContainerType",
182
+ "lookup": [
183
+ {
184
+ "matches": "00",
185
+ "name": "case/carton"
186
+ },
187
+ {
188
+ "matches": "01",
189
+ "name": "pallet"
190
+ },
191
+ {
192
+ "matches": "02",
193
+ "name": "larger than a pallet"
194
+ },
195
+ {
196
+ "matches": "04",
197
+ "name": "internally defined for intra-company use"
198
+ }
199
+ ]
200
+ }
201
+ ]
202
+ },
203
+ {
204
+ "name": "FedEx Ground 96 (22)",
205
+ "id": "fedex_ground_96",
206
+ "glossary": {
207
+ "ApplicationIdentifier": { "description": "Always 96, marking a ground shipping label." }
208
+ },
209
+ "regex": [
210
+ "\\s*(?<ApplicationIdentifier>9\\s*6\\s*)",
211
+ "(?<SCNC>([0-9]\\s*){2})",
212
+ "(?<ServiceType>([0-9]\\s*){3})",
213
+ "(?<SerialNumber>(?<ShipperId>([0-9]\\s*){7})(?<PackageId>([0-9]\\s*){7}))",
214
+ "(?<CheckDigit>[0-9]\\s*)"
215
+ ],
216
+ "validation": {
217
+ "checksum": {
218
+ "name": "mod10",
219
+ "modulo": 10,
220
+ "evens_multiplier": 1,
221
+ "odds_multiplier": 3,
222
+ "reverse": false
223
+ }
224
+ },
225
+ "tracking_url": "https://www.fedex.com/apps/fedextrack/?tracknumbers=%s",
226
+ "test_numbers": {
227
+ "valid": [
228
+ "9611020987654312345672",
229
+ " 9 6 1 1 0 2 0 9 8 7 6 5 4 3 1 2 3 4 5 6 7 2 "
230
+ ],
231
+ "invalid": [
232
+ "9600000000000000000001"
233
+ ]
234
+ }
235
+ },
236
+ {
237
+ "name": "FedEx Ground GSN",
238
+ "id": "fedex_ground_gsn",
239
+ "description": "Ground's 34 digit barcode, carrying the Ground shipper number and the tracking number in the last twelve digits",
240
+ "glossary": {
241
+ "ApplicationIdentifier": { "description": "Always 96, marking a ground shipping label." },
242
+ "SCNC": { "description": "22, or 32 where the shipper number is nine digits." }
243
+ },
244
+ "regex": [
245
+ "\\s*(?<ApplicationIdentifier>9\\s*6\\s*)",
246
+ "(?<SCNC>([0-9]\\s*){2})",
247
+ "([0-9]\\s*){5}",
248
+ "(?<GSN>([0-9]\\s*){10})",
249
+ "[0-9]\\s*",
250
+ "(?<SerialNumber>([0-9]\\s*){13})",
251
+ "(?<CheckDigit>[0-9]\\s*)"
252
+ ],
253
+ "validation": {
254
+ "checksum": {
255
+ "name": "sum_product_with_weightings_and_modulo",
256
+ "weightings": [
257
+ 1,
258
+ 7,
259
+ 3,
260
+ 1,
261
+ 7,
262
+ 3,
263
+ 1,
264
+ 7,
265
+ 3,
266
+ 1,
267
+ 7,
268
+ 3,
269
+ 1
270
+ ],
271
+ "modulo1": 11,
272
+ "modulo2": 10
273
+ }
274
+ },
275
+ "tracking_url": "https://www.fedex.com/apps/fedextrack/?tracknumbers=%s",
276
+ "test_numbers": {
277
+ "valid": [
278
+ "9622001900000000000000776632517510",
279
+ "9622001560000000000000794808390594",
280
+ "9622001560001234567100794808390594",
281
+ " 9 6 2 2 0 0 1 5 6 0 0 0 1 2 3 4 5 6 7 1 0 0 7 9 4 8 0 8 3 9 0 5 9 4 ",
282
+ "9632001560123456789900794808390594"
283
+ ],
284
+ "invalid": [
285
+ "9622001560001234567100794808390595",
286
+ "9622001560001234567100794808390597"
287
+ ]
288
+ }
289
+ }
290
+ ]
291
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "GOFO Express",
3
+ "courier_code": "gofo",
4
+ "tracking_numbers": [
5
+ {
6
+ "name": "GOFO Express (US)",
7
+ "id": "gofo_us",
8
+ "regex": [
9
+ "\\s*G\\s*F\\s*U\\s*S\\s*(?<SerialNumber>([0-9]\\s*){14})\\s*"
10
+ ],
11
+ "tracking_url": "https://www.gofoexpress.com/tracking.html?searchID=%s",
12
+ "validation": {},
13
+ "test_numbers": {
14
+ "valid": [
15
+ "GFUS01011884214464",
16
+ "GFUS01011884214272"
17
+ ],
18
+ "invalid": [
19
+ "GFUS0101188421446"
20
+ ]
21
+ }
22
+ }
23
+ ]
24
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "Landmark Global LTN",
3
+ "courier_code": "landmark",
4
+ "tracking_numbers": [
5
+ {
6
+ "name": "Landmark Global LTN",
7
+ "id": "landmark_global",
8
+ "regex": [
9
+ "\\s*L\\s*T\\s*N\\s*(?<SerialNumber>([0-9]\\s*){8})\\s*N\\s*1"
10
+ ],
11
+ "tracking_url": "https://track.landmarkglobal.com/?search=%s",
12
+ "validation": {},
13
+ "test_numbers": {
14
+ "valid": [
15
+ "LTN74207623N1",
16
+ "LTN74209518N1",
17
+ "LTN74224021N1"
18
+ ],
19
+ "invalid": [
20
+ "LSN74209518N2",
21
+ "LSN74209518N1"
22
+ ]
23
+ }
24
+ }
25
+ ]
26
+ }
@@ -0,0 +1,105 @@
1
+ {
2
+ "name": "LaserShip",
3
+ "courier_code": "lasership",
4
+ "tracking_numbers": [
5
+ {
6
+ "name": "LaserShip LX",
7
+ "id": "lasership_lx",
8
+ "regex": [
9
+ "\\s*L\\s*[AIEHNX]\\s*[1-3]\\s*(?<SerialNumber>([0-9]\\s*){7,7})\\s*"
10
+ ],
11
+ "validation": {},
12
+ "test_numbers": {
13
+ "valid": [
14
+ "LX17635036",
15
+ "LX 176 35035",
16
+ "LX17635034",
17
+ "LI 129 79072",
18
+ "LI12976442",
19
+ "LA28376237",
20
+ "LA28372694",
21
+ "LH13830790",
22
+ "LH13816137",
23
+ "LH13820469",
24
+ "LH13831034",
25
+ "LH13821737",
26
+ "LH13820881",
27
+ "LH13820881",
28
+ "LH13812209",
29
+ "LH13800911",
30
+ "LH13795254",
31
+ "LE10917377",
32
+ "LE10913900",
33
+ "LE10913753",
34
+ "LN30083672"
35
+ ],
36
+ "invalid": [
37
+ "LX9763503N",
38
+ "LH9176350N6",
39
+ "XA17635036",
40
+ "L A 9 7 6 3 5 0 3 6 "
41
+ ]
42
+ }
43
+ },
44
+ {
45
+ "name": "LaserShip 1LS7 (15)",
46
+ "id": "lasership_1ls7",
47
+ "regex": [
48
+ "\\s*1\\s*L\\s*S\\s*7\\s*[12]\\s*([0-9]\\s*){4,4}",
49
+ "(?<SerialNumber>([0-9]\\s*){6,6})\\s*"
50
+ ],
51
+ "validation": {},
52
+ "test_numbers": {
53
+ "valid": [
54
+ "1LS717793482164",
55
+ "1LS724505321754",
56
+ "1LS720000000000",
57
+ " 1 L S 7 2 0 0 0 0 0 0 0 0 0 0 "
58
+ ],
59
+ "invalid": [
60
+ "1LX734505321754"
61
+ ]
62
+ }
63
+ },
64
+ {
65
+ "name": "LaserShip 1LS7 (18)",
66
+ "regex": [
67
+ "\\s*1\\s*L\\s*S\\s*7\\s*",
68
+ "[12]\\s*([0-9]\\s*){2,2}\\s*0\\s*1\\s*[1234]\\s*",
69
+ "\\s*(?<SerialNumber>([0-9]\\s*){6,6})",
70
+ "-\\s*1\\s*"
71
+ ],
72
+ "validation": {},
73
+ "test_numbers": {
74
+ "valid": [
75
+ "1LS7119013618127-1",
76
+ " 1 L S 7 1 1 9 0 1 3 6 1 8 1 2 7 - 1 "
77
+ ],
78
+ "invalid": [
79
+ "1LS7119013618127-2"
80
+ ]
81
+ }
82
+ },
83
+ {
84
+ "name": "LaserShip 1LSCX (15)",
85
+ "id": "lasership_1lscx",
86
+ "regex": [
87
+ "\\s*1\\s*L\\s*S\\s*",
88
+ "\\s*C\\s*X\\s*",
89
+ "(?<SerialNumber>",
90
+ "([0-9A-Z]\\s*){10}",
91
+ ")"
92
+ ],
93
+ "validation": {},
94
+ "test_numbers": {
95
+ "valid": [
96
+ "1LS CX VE00 58631Y",
97
+ "1LSCXVE005BUEFX"
98
+ ],
99
+ "invalid": [
100
+ "1LSCZVE0058631Y"
101
+ ]
102
+ }
103
+ }
104
+ ]
105
+ }
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "Old Dominion Freight Line",
3
+ "courier_code": "old_dominion",
4
+ "tracking_numbers": [
5
+ {
6
+ "name": "Old Dominion",
7
+ "regex": [
8
+ "\\s*(?<SerialNumber>",
9
+ "(7\\s*7\\s*[78]\\s*|0\\s*7\\s*2\\s*|7\\s*8\\s*0\\s*)",
10
+ "([0-9]\\s*){7}",
11
+ ")",
12
+ "(?<CheckDigit>[0-9]\\s*)"
13
+ ],
14
+ "validation": {
15
+ "checksum": {
16
+ "name": "luhn",
17
+ "modulo": 10
18
+ }
19
+ },
20
+ "tracking_url": "https://www.odfl.com/us/en/tools/trace-track-ltl-freight/trace.html?proNumbers=%s",
21
+ "test_numbers": {
22
+ "valid": [
23
+ "07209562763",
24
+ " 0 7 2 0 9 5 6 2 7 6 3 ",
25
+ "77767553207",
26
+ "77806528897",
27
+ "78045768393"
28
+ ],
29
+ "invalid": [
30
+ "07209562773",
31
+ "79927398713",
32
+ "10000000000"
33
+ ]
34
+ }
35
+ },
36
+ {
37
+ "name": "Old Dominion Guaranteed Shipment",
38
+ "regex": [
39
+ "\\s*(?<SerialNumber>",
40
+ "8\\s*0\\s*",
41
+ "([0-9]\\s*){8}",
42
+ ")",
43
+ "(?<CheckDigit>[0-9]\\s*)"
44
+ ],
45
+ "validation": {
46
+ "checksum": {
47
+ "name": "luhn",
48
+ "modulo": 10
49
+ }
50
+ },
51
+ "tracking_url": "https://www.odfl.com/us/en/tools/trace-track-ltl-freight/trace.html?proNumbers=%s",
52
+ "test_numbers": {
53
+ "valid": [
54
+ "80003280379",
55
+ " 8 0 0 0 3 2 8 0 3 7 9 ",
56
+ "80993847369"
57
+ ],
58
+ "invalid": [
59
+ "80003280389",
60
+ "10000000000"
61
+ ]
62
+ }
63
+ }
64
+ ]
65
+ }
@@ -0,0 +1,74 @@
1
+ {
2
+ "name": "OnTrac",
3
+ "courier_code": "ontrac",
4
+ "tracking_numbers": [
5
+ {
6
+ "name": "OnTrac",
7
+ "id": "ontrac_c",
8
+ "regex": "\\s*C\\s*(?<SerialNumber>([0-9]\\s*){13})(?<CheckDigit>[0-9]\\s*)",
9
+ "validation": {
10
+ "checksum": {
11
+ "name": "mod10",
12
+ "modulo": 10,
13
+ "evens_multiplier": 1,
14
+ "odds_multiplier": 2,
15
+ "reverse": false
16
+ },
17
+ "serial_number_format": {
18
+ "prepend_if": {
19
+ "matches_regex": "^(?!4).+$",
20
+ "content": "4"
21
+ }
22
+ }
23
+ },
24
+ "tracking_url": "http://www.ontrac.com/tracking/?number=%s",
25
+ "test_numbers": {
26
+ "valid": [
27
+ "C11031500001879",
28
+ "C 110 31 500 00187 9",
29
+ "C10999911320231",
30
+ "C11121552953069",
31
+ "C11121553156000",
32
+ "C11121552829468"
33
+ ],
34
+ "invalid": [
35
+ "C10000000000000",
36
+ "C11031500001889"
37
+ ]
38
+ }
39
+ },
40
+ {
41
+ "name": "OnTrac D",
42
+ "id": "ontrac_d",
43
+ "regex": "\\s*D\\s*(?<SerialNumber>([0-9]\\s*){13})(?<CheckDigit>[0-9]\\s*)",
44
+ "validation": {
45
+ "checksum": {
46
+ "name": "mod10",
47
+ "modulo": 10,
48
+ "evens_multiplier": 1,
49
+ "odds_multiplier": 2,
50
+ "reverse": false
51
+ },
52
+ "serial_number_format": {
53
+ "prepend_if": {
54
+ "matches_regex": "^(?!5).+$",
55
+ "content": "5"
56
+ }
57
+ }
58
+ },
59
+ "tracking_url": "http://www.ontrac.com/tracking/?number=%s",
60
+ "test_numbers": {
61
+ "valid": [
62
+ "D10011354453707",
63
+ "D10011345983010",
64
+ "D 100 113 459 830 10",
65
+ "D10011342332145"
66
+ ],
67
+ "invalid": [
68
+ "D10011345983012",
69
+ "D10011342332144"
70
+ ]
71
+ }
72
+ }
73
+ ]
74
+ }
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "Purolator",
3
+ "courier_code": "purolator",
4
+ "tracking_numbers": [
5
+ {
6
+ "name": "Purolator (12)",
7
+ "id": "purolator_numeric",
8
+ "regex": "\\s*(?<SerialNumber>[0-5]\\s*([0-9]\\s*){10})(?<CheckDigit>[0-9])\\s*",
9
+ "validation": {
10
+ "checksum": {
11
+ "name": "luhn"
12
+ }
13
+ },
14
+ "tracking_url": "https://www.purolator.com/en/shipping/tracker?searchValue=%s",
15
+ "test_numbers": {
16
+ "valid": [
17
+ "320595463938",
18
+ "320606146993",
19
+ "287809468872",
20
+ "320610804900",
21
+ "331426749957",
22
+ "331434972567"
23
+ ],
24
+ "invalid": [
25
+ "320595463939",
26
+ "287809468875"
27
+ ]
28
+ }
29
+ },
30
+ {
31
+ "name": "Purolator (alpha + 9)",
32
+ "id": "purolator_alpha",
33
+ "regex": "\\s*(?<SerialNumber>([A-Z]\\s*){3}([0-9]\\s*){9})\\s*",
34
+ "validation": {},
35
+ "tracking_url": "https://www.purolator.com/en/shipping/tracker?searchValue=%s",
36
+ "test_numbers": {
37
+ "valid": [
38
+ "KYV009956937",
39
+ "CGK002986959",
40
+ "JFV247545960",
41
+ "TLR000083964"
42
+ ],
43
+ "invalid": [
44
+ "KY009956937",
45
+ "331426749957"
46
+ ]
47
+ }
48
+ }
49
+ ]
50
+ }