tracking_number 2.4.0 → 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.
- checksums.yaml +4 -4
- data/.github/FUNDING.yml +2 -0
- data/CHANGELOG.md +19 -0
- data/README.md +3 -35
- data/lib/data/couriers/canadapost.json +3 -1
- data/lib/data/couriers/canpar.json +29 -0
- data/lib/data/couriers/dhl.json +3 -74
- data/lib/data/couriers/dpd.json +6 -2
- data/lib/data/couriers/fedex.json +44 -56
- data/lib/data/couriers/gofo.json +24 -0
- data/lib/data/couriers/lasership.json +21 -0
- data/lib/data/couriers/old_dominion.json +4 -2
- data/lib/data/couriers/ontrac.json +6 -2
- data/lib/data/couriers/purolator.json +50 -0
- data/lib/data/couriers/s10.json +9 -1
- data/lib/data/couriers/speedee.json +26 -0
- data/lib/data/couriers/ups.json +6 -2
- data/lib/data/couriers/usps.json +138 -137
- data/lib/data/couriers/yodel.json +29 -0
- data/lib/data/couriers/yunexpress.json +25 -0
- data/lib/tracking_number/version.rb +1 -1
- data/lib/tracking_number.rb +25 -0
- data/package.json +1 -25
- data/test/partnership_test.rb +71 -0
- data/test/renamed_types_test.rb +44 -0
- data/test/test_helper.rb +4 -3
- data/test/tracking_number_meta_test.rb +1 -1
- data/test/tracking_number_test.rb +15 -18
- data/tracking_number.gemspec +1 -0
- metadata +25 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 71f01e80c118f12c210f3c9a5195edf0c9d257c37ff4ce36529962f4131a57ed
|
|
4
|
+
data.tar.gz: 79519ddef14f7728eb6de46437360a9040368e261ce3dba4cdadf9a9b382891e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 86ef4bdd51d50a76f26b0bc53f17db5518c48973ecc715b90058dc446c1a7ac2558db35a75f9a572837e4aacbf9e6fa33b2c5870dfc21076a50a8c538e156313
|
|
7
|
+
data.tar.gz: f78a9a8b106ce172f87f231c9d59aa6c52a1f76b8a6b471aaa5a17ac92ee605d71cab5d216b3032d3eba8fd0244a406f6358f6be465e1332c1edce32d07c9ad8
|
data/.github/FUNDING.yml
ADDED
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
tracking_number changelog
|
|
2
2
|
|
|
3
|
+
# [3.0.0](https://github.com/jkeen/tracking_number/compare/v2.5.0...v3.0.0) (2026-08-15)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
* feat!: Update to tracking_number_data 2.0, which rebuilds the IMpb USPS definitions from Publication 199 and absorbs the DHL and Fedex definitions that described the same tracking number. ([448e953](https://github.com/jkeen/tracking_number/commit/448e9534b0be8d2f205de5712e3215281922de99))
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### BREAKING CHANGES
|
|
10
|
+
|
|
11
|
+
* `fedex_smartpost`, `dhl_ecommerce_30` and `usps_32V2` are absorbed into `usps_impb_c`, which is the definition they were always describing. `usps_91` and `usps_22` become `usps_impb_c` and `usps_impb_n`, and Application Identifier 91 splits off to `usps_legacy`. Every number these matched still decodes, now as USPS.
|
|
12
|
+
|
|
13
|
+
No active definitions declare `partners` anymore, but it remains valid in our data spec for potential future use.
|
|
14
|
+
|
|
15
|
+
# [2.5.0](https://github.com/jkeen/tracking_number/compare/v2.4.0...v2.5.0) (2026-08-13)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* update to tracking_number_data 1.12, which includes support for Canpar, Purolator, Spee-Dee, YunExpress, and an updated FedEx matcher ([ca67edf](https://github.com/jkeen/tracking_number/commit/ca67edf0eaeab33171008bf115e96bdcf55c0d4b))
|
|
21
|
+
|
|
3
22
|
# [2.4.0](https://github.com/jkeen/tracking_number/compare/v2.3.0...v2.4.0) (2025-08-21)
|
|
4
23
|
|
|
5
24
|
|
data/README.md
CHANGED
|
@@ -2,21 +2,15 @@
|
|
|
2
2
|
[](https://badge.fury.io/rb/tracking_number)
|
|
3
3
|
[]()
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
>
|
|
7
|
-
> <a href="https://www.buymeacoffee.com/jeffkeen" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: auto !important;width: 150px !important;" ></a>
|
|
8
|
-
|
|
9
|
-
## Tracking Number (v1.x)
|
|
5
|
+
## Tracking Number
|
|
10
6
|
|
|
11
7
|
This gem identifies valid tracking numbers and can tell you a little bit about the shipment just from the number—there's quite a bit of info tucked away into those numbers, it turns out.
|
|
12
8
|
|
|
13
|
-
It detects tracking numbers from UPS, FedEx,
|
|
9
|
+
It detects tracking numbers from USPS, UPS, FedEx, Amazon, DHL, OnTrac, LaserShip, Canada Post, DPD, Purolator, Old Dominion Freight Line, Spee-Dee Delivery, Canpar, YunExpress, Landmark Global, GOFO Express, and any carrier using the S10 international standard.
|
|
14
10
|
|
|
15
11
|
This gem does not do tracking. That is left up to you.
|
|
16
12
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
Starting with the 1.0 release the specifications for detecting tracking numbers have been moved into a separate repository ([tracking_number_data](http://github.com/jkeen/tracking_number_data)) that this gem relies on. I did this so a) we can have a single place to document all tracking number types and it can be more of a crowdsourced effort, and b) so clients can be written in other languages easier.
|
|
13
|
+
All the matching data is kept in [tracking_number_data](https://github.com/jkeen/tracking_number_data) and displayed in full on [trackingnumber.fyi](https://trackingnumber.fyi).
|
|
20
14
|
|
|
21
15
|
## Usage
|
|
22
16
|
|
|
@@ -134,32 +128,6 @@ Most tracking numbers have a format where each part of the number has meaning. `
|
|
|
134
128
|
# }
|
|
135
129
|
```
|
|
136
130
|
|
|
137
|
-
#### Multiple shippers / Partnerships
|
|
138
|
-
Some tracking numbers match multiple carriers, because they belong to multiple carriers. Some shipments like Fedex Smartpost contract the "last mile" out to USPS.
|
|
139
|
-
|
|
140
|
-
```ruby
|
|
141
|
-
# Search defaults to only showing numbers that fulfill the carrier side of the relationship
|
|
142
|
-
# (if a partnership exists at all), as this is the end a consumer would most likely be interested in.
|
|
143
|
-
|
|
144
|
-
results = TrackingNumber.search('420112139261290983497923666238')
|
|
145
|
-
=> [#<TrackingNumber::USPS91:0x26ac0 420112139261290983497923666238>]
|
|
146
|
-
|
|
147
|
-
all_results = TrackingNumber.search('420112139261290983497923666238', match: :all)
|
|
148
|
-
=> [#<TrackingNumber::FedExSmartPost:0x30624 420112139261290983497923666238>, #<TrackingNumber::USPS91:0x26ac0 420112139261290983497923666238>]
|
|
149
|
-
|
|
150
|
-
tn = results.first
|
|
151
|
-
tn.shipper? #=> false
|
|
152
|
-
tn.carrier? #=> true
|
|
153
|
-
tn.partnership? #=> true
|
|
154
|
-
tn.partners
|
|
155
|
-
#=> <struct TrackingNumber::Base::PartnerStruct
|
|
156
|
-
# shipper=#<TrackingNumber::FedExSmartPost:0x30624 420112139261290983497923666238>,
|
|
157
|
-
# carrier=#<TrackingNumber::USPS91:0x2f1fc 420112139261290983497923666238>>
|
|
158
|
-
|
|
159
|
-
tn.partners.shipper #=> #<TrackingNumber::FedExSmartPost:0x30624 420112139261290983497923666238>
|
|
160
|
-
tn.partners.carrier == tn #=> true
|
|
161
|
-
```
|
|
162
|
-
|
|
163
131
|
## ActiveModel validation
|
|
164
132
|
|
|
165
133
|
For Rails 3 (or any ActiveModel client), validate your fields as a tracking number:
|
|
@@ -9,8 +9,10 @@
|
|
|
9
9
|
"validation": {
|
|
10
10
|
"checksum": {
|
|
11
11
|
"name": "mod10",
|
|
12
|
+
"modulo": 10,
|
|
12
13
|
"evens_multiplier": 3,
|
|
13
|
-
"odds_multiplier": 1
|
|
14
|
+
"odds_multiplier": 1,
|
|
15
|
+
"reverse": false
|
|
14
16
|
}
|
|
15
17
|
},
|
|
16
18
|
"tracking_url": "https://www.canadapost-postescanada.ca/track-reperage/en#/search?searchFor=%s",
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Canpar",
|
|
3
|
+
"courier_code": "canpar",
|
|
4
|
+
"tracking_numbers": [
|
|
5
|
+
{
|
|
6
|
+
"name": "Canpar (22)",
|
|
7
|
+
"id": "canpar_22",
|
|
8
|
+
"regex": "\\s*(?<SerialNumber>[CDKLSUXZ]\\s*([0-9]\\s*){21})\\s*",
|
|
9
|
+
"validation": {},
|
|
10
|
+
"tracking_url": "https://www.canpar.com/en/track/tracking.jsp?reference=%s&locale=en",
|
|
11
|
+
"test_numbers": {
|
|
12
|
+
"valid": [
|
|
13
|
+
"D576002440000001718010",
|
|
14
|
+
"D576002440000001428004",
|
|
15
|
+
"D576002440000002496001",
|
|
16
|
+
"L576002440000000001004",
|
|
17
|
+
"L576002440000000004001",
|
|
18
|
+
"S576002440000000004001",
|
|
19
|
+
"S576002440000000025001"
|
|
20
|
+
],
|
|
21
|
+
"invalid": [
|
|
22
|
+
"1576002440000002510003",
|
|
23
|
+
"D57600244000000251000",
|
|
24
|
+
"M576002440000002510003"
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
}
|
data/lib/data/couriers/dhl.json
CHANGED
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
"regex": "\\s*(?<SerialNumber>([0-9]\\s*){9,10})(?<CheckDigit>([0-9]\\s*))",
|
|
9
9
|
"validation": {
|
|
10
10
|
"checksum": {
|
|
11
|
-
"name": "mod7"
|
|
11
|
+
"name": "mod7",
|
|
12
|
+
"modulo": 7
|
|
12
13
|
}
|
|
13
14
|
},
|
|
14
15
|
"tracking_url": "http://www.dhl.com/en/express/tracking.html?brand=DHL&AWB=%s",
|
|
@@ -89,80 +90,8 @@
|
|
|
89
90
|
"GR295117494011169045"
|
|
90
91
|
]
|
|
91
92
|
}
|
|
92
|
-
},
|
|
93
|
-
{
|
|
94
|
-
"name": "DHL E-Commerce (30)",
|
|
95
|
-
"id": "dhl_ecommerce_30",
|
|
96
|
-
"regex": [
|
|
97
|
-
"\\s*(?<RoutingApplicationId>4\\s*2\\s*0\\s*)(?<DestinationZip>([0-9]\\s*){5})",
|
|
98
|
-
"(?!\\s*9\\s*[1-5]\\b)",
|
|
99
|
-
"(?<SerialNumber>",
|
|
100
|
-
"(?<ServiceType>(9[2-5]\\s*))",
|
|
101
|
-
"(?<ShipperId>([0-9]\\s*){9})",
|
|
102
|
-
"(?<PackageId>([0-9]\\s*){10})",
|
|
103
|
-
")",
|
|
104
|
-
"(?<CheckDigit>[0-9]\\s*)"
|
|
105
|
-
],
|
|
106
|
-
"validation": {
|
|
107
|
-
"checksum": {
|
|
108
|
-
"name": "mod10",
|
|
109
|
-
"evens_multiplier": 3,
|
|
110
|
-
"odds_multiplier": 1,
|
|
111
|
-
"reverse": true
|
|
112
|
-
}
|
|
113
|
-
},
|
|
114
|
-
"tracking_url": "https://ecommerceportal.dhl.com/track?trackingnumber=%s",
|
|
115
|
-
"partners": [{
|
|
116
|
-
"description": "DHL eCommerce hands off to USPS for the last mile",
|
|
117
|
-
"partner_type": "carrier",
|
|
118
|
-
"partner_id": "usps_22",
|
|
119
|
-
"validation": {
|
|
120
|
-
"matches_all": [
|
|
121
|
-
{ "regex_group_name": "RoutingApplicationId", "matches": "420" },
|
|
122
|
-
{ "regex_group_name": "ServiceType", "matches_regex": "9[2345]" }
|
|
123
|
-
]
|
|
124
|
-
}
|
|
125
|
-
},
|
|
126
|
-
{
|
|
127
|
-
"description": "DHL eCommerce hands off to USPS for the last mile",
|
|
128
|
-
"partner_type": "carrier",
|
|
129
|
-
"partner_id": "usps_91",
|
|
130
|
-
"validation": {
|
|
131
|
-
"matches_all": [
|
|
132
|
-
{ "regex_group_name": "RoutingApplicationId", "matches": "420" },
|
|
133
|
-
{ "regex_group_name": "ServiceType", "matches_regex": "9[2345]" }
|
|
134
|
-
]
|
|
135
|
-
}
|
|
136
|
-
}],
|
|
137
|
-
"additional": [
|
|
138
|
-
{
|
|
139
|
-
"name": "Service Type",
|
|
140
|
-
"regex_group_name": "ServiceType",
|
|
141
|
-
"lookup": [
|
|
142
|
-
{ "matches": "92", "name": "USPS Tracking (Commercial)" },
|
|
143
|
-
{ "matches": "93", "name": "Collect on Delivery (COD)" },
|
|
144
|
-
{ "matches": "94", "name": "USPS Tracking" },
|
|
145
|
-
{ "matches": "95", "name": "Certified Mail" }
|
|
146
|
-
]
|
|
147
|
-
}
|
|
148
|
-
],
|
|
149
|
-
"test_numbers": {
|
|
150
|
-
"valid": [
|
|
151
|
-
"420902459261290336128704042634",
|
|
152
|
-
"420941179261290336128704062441",
|
|
153
|
-
"420926029261290336128704067248",
|
|
154
|
-
"420902729261290336128704124163",
|
|
155
|
-
"420950549261290336128704133837",
|
|
156
|
-
"420193809261290336128704280838",
|
|
157
|
-
"420900469261290336128704216936"
|
|
158
|
-
],
|
|
159
|
-
"invalid": [
|
|
160
|
-
"420941179261290336128704062442",
|
|
161
|
-
"420941179261290336128704062400",
|
|
162
|
-
"420941179261290336128704062422"
|
|
163
|
-
]
|
|
164
|
-
}
|
|
165
93
|
}
|
|
166
94
|
|
|
95
|
+
|
|
167
96
|
]
|
|
168
97
|
}
|
data/lib/data/couriers/dpd.json
CHANGED
|
@@ -17,7 +17,9 @@
|
|
|
17
17
|
],
|
|
18
18
|
"validation": {
|
|
19
19
|
"checksum": {
|
|
20
|
-
"name": "mod_37_36"
|
|
20
|
+
"name": "mod_37_36",
|
|
21
|
+
"modulo": 36,
|
|
22
|
+
"alphabet": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
21
23
|
}
|
|
22
24
|
},
|
|
23
25
|
"tracking_url": "https://www.dpdgroup.com/nl/mydpd/my-parcels/track?lang=en&parcelNumber=%s",
|
|
@@ -323,7 +325,9 @@
|
|
|
323
325
|
],
|
|
324
326
|
"validation": {
|
|
325
327
|
"checksum": {
|
|
326
|
-
"name": "mod_37_36"
|
|
328
|
+
"name": "mod_37_36",
|
|
329
|
+
"modulo": 36,
|
|
330
|
+
"alphabet": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
327
331
|
}
|
|
328
332
|
},
|
|
329
333
|
"tracking_url": "https://www.dpdgroup.com/nl/mydpd/my-parcels/track?lang=en&parcelNumber=%s",
|
|
@@ -45,8 +45,7 @@
|
|
|
45
45
|
"name": "FedEx Express (34)",
|
|
46
46
|
"id": "fedex_34",
|
|
47
47
|
"regex": [
|
|
48
|
-
"\\s*
|
|
49
|
-
"([0-9]\\s*){10}",
|
|
48
|
+
"\\s*[0-8]\\s*([0-9]\\s*){14}",
|
|
50
49
|
"(?<DestinationZip>([0-9]\\s*){5})",
|
|
51
50
|
"(?<SerialNumber>([0-9]\\s*){13})",
|
|
52
51
|
"(?<CheckDigit>[0-9]\\s*)"
|
|
@@ -81,7 +80,11 @@
|
|
|
81
80
|
"1001901781990001000300617767839437",
|
|
82
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 ",
|
|
83
82
|
"1002297871540001000300790695517286",
|
|
84
|
-
"1027590111820004833500785458233610"
|
|
83
|
+
"1027590111820004833500785458233610",
|
|
84
|
+
"1195266473930007521100871079919940",
|
|
85
|
+
"1 1 9 52 6 64739 3000 75211 00 8710 799 199 40",
|
|
86
|
+
"1195271874060007521100871140316925",
|
|
87
|
+
"1195583874210007521100871140316936"
|
|
85
88
|
],
|
|
86
89
|
"invalid": [
|
|
87
90
|
"1001901781990001000300617767839438"
|
|
@@ -89,66 +92,37 @@
|
|
|
89
92
|
}
|
|
90
93
|
},
|
|
91
94
|
{
|
|
92
|
-
"name": "FedEx
|
|
93
|
-
"id": "
|
|
94
|
-
"description": "
|
|
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.",
|
|
95
98
|
"regex": [
|
|
96
|
-
"\\s*
|
|
97
|
-
"(?:
|
|
98
|
-
"(
|
|
99
|
-
")
|
|
100
|
-
"(?<SerialNumber>",
|
|
101
|
-
"(?<
|
|
102
|
-
"(
|
|
103
|
-
"(?<ShipperId>([0-9]\\s*){8})",
|
|
104
|
-
"(?<PackageId>([0-9]\\s*){11}|([0-9]\\s*){7})",
|
|
105
|
-
")",
|
|
106
|
-
"(?<CheckDigit>([0-9]\\s*))"
|
|
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}"
|
|
107
106
|
],
|
|
108
|
-
"additional": [
|
|
109
|
-
{
|
|
110
|
-
"name": "Service Type",
|
|
111
|
-
"regex_group_name": "ServiceType",
|
|
112
|
-
"lookup": [
|
|
113
|
-
{
|
|
114
|
-
"matches_regex": ".",
|
|
115
|
-
"name": "Delivered by USPS"
|
|
116
|
-
}
|
|
117
|
-
]
|
|
118
|
-
}
|
|
119
|
-
],
|
|
120
|
-
"partners": [{
|
|
121
|
-
"partner_id": "usps_91",
|
|
122
|
-
"partner_type": "carrier",
|
|
123
|
-
"description": "FedEx SmartPost is a shipping service that utilizes FedEx for the initial transport and the United States Postal Service for final delivery."
|
|
124
|
-
}],
|
|
125
107
|
"validation": {
|
|
126
108
|
"checksum": {
|
|
127
|
-
"name": "
|
|
128
|
-
"
|
|
129
|
-
"
|
|
130
|
-
|
|
131
|
-
"serial_number_format": {
|
|
132
|
-
"prepend_if": {
|
|
133
|
-
"matches_regex": "^(?!92).+",
|
|
134
|
-
"content": "92"
|
|
135
|
-
}
|
|
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
|
|
136
113
|
}
|
|
137
114
|
},
|
|
138
|
-
"tracking_url": "https://www.fedex.com/apps/fedextrack/?tracknumbers=%s",
|
|
139
115
|
"test_numbers": {
|
|
140
116
|
"valid": [
|
|
141
|
-
"
|
|
142
|
-
"
|
|
143
|
-
"
|
|
117
|
+
"32971514560102447849175802862014",
|
|
118
|
+
"32971510360102447848540980802018",
|
|
119
|
+
"32971508360102447847941133172013",
|
|
120
|
+
"33810799560000004380417923803212",
|
|
121
|
+
"3 29715 145 6010244 784917580286 2014"
|
|
144
122
|
],
|
|
145
123
|
"invalid": [
|
|
146
|
-
"
|
|
147
|
-
"
|
|
148
|
-
"420 11213 61290983497923666231",
|
|
149
|
-
"92 6129098349792366623 5",
|
|
150
|
-
"9400 1112 0108 0805 4830 16",
|
|
151
|
-
"9361 2898 7870 0317 6337 95"
|
|
124
|
+
"32971514560102447849175802852014",
|
|
125
|
+
"3297151456010244784917580286201"
|
|
152
126
|
]
|
|
153
127
|
}
|
|
154
128
|
},
|
|
@@ -159,8 +133,10 @@
|
|
|
159
133
|
"validation": {
|
|
160
134
|
"checksum": {
|
|
161
135
|
"name": "mod10",
|
|
136
|
+
"modulo": 10,
|
|
162
137
|
"evens_multiplier": 1,
|
|
163
|
-
"odds_multiplier": 3
|
|
138
|
+
"odds_multiplier": 3,
|
|
139
|
+
"reverse": false
|
|
164
140
|
}
|
|
165
141
|
},
|
|
166
142
|
"tracking_url": "https://www.fedex.com/apps/fedextrack/?tracknumbers=%s",
|
|
@@ -184,8 +160,10 @@
|
|
|
184
160
|
"validation": {
|
|
185
161
|
"checksum": {
|
|
186
162
|
"name": "mod10",
|
|
163
|
+
"modulo": 10,
|
|
187
164
|
"evens_multiplier": 3,
|
|
188
|
-
"odds_multiplier": 1
|
|
165
|
+
"odds_multiplier": 1,
|
|
166
|
+
"reverse": false
|
|
189
167
|
}
|
|
190
168
|
},
|
|
191
169
|
"test_numbers": {
|
|
@@ -225,6 +203,9 @@
|
|
|
225
203
|
{
|
|
226
204
|
"name": "FedEx Ground 96 (22)",
|
|
227
205
|
"id": "fedex_ground_96",
|
|
206
|
+
"glossary": {
|
|
207
|
+
"ApplicationIdentifier": { "description": "Always 96, marking a ground shipping label." }
|
|
208
|
+
},
|
|
228
209
|
"regex": [
|
|
229
210
|
"\\s*(?<ApplicationIdentifier>9\\s*6\\s*)",
|
|
230
211
|
"(?<SCNC>([0-9]\\s*){2})",
|
|
@@ -235,8 +216,10 @@
|
|
|
235
216
|
"validation": {
|
|
236
217
|
"checksum": {
|
|
237
218
|
"name": "mod10",
|
|
219
|
+
"modulo": 10,
|
|
238
220
|
"evens_multiplier": 1,
|
|
239
|
-
"odds_multiplier": 3
|
|
221
|
+
"odds_multiplier": 3,
|
|
222
|
+
"reverse": false
|
|
240
223
|
}
|
|
241
224
|
},
|
|
242
225
|
"tracking_url": "https://www.fedex.com/apps/fedextrack/?tracknumbers=%s",
|
|
@@ -253,6 +236,11 @@
|
|
|
253
236
|
{
|
|
254
237
|
"name": "FedEx Ground GSN",
|
|
255
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
|
+
},
|
|
256
244
|
"regex": [
|
|
257
245
|
"\\s*(?<ApplicationIdentifier>9\\s*6\\s*)",
|
|
258
246
|
"(?<SCNC>([0-9]\\s*){2})",
|
|
@@ -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
|
+
}
|
|
@@ -79,6 +79,27 @@
|
|
|
79
79
|
"1LS7119013618127-2"
|
|
80
80
|
]
|
|
81
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
|
+
}
|
|
82
103
|
}
|
|
83
104
|
]
|
|
84
105
|
}
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
],
|
|
14
14
|
"validation": {
|
|
15
15
|
"checksum": {
|
|
16
|
-
"name": "luhn"
|
|
16
|
+
"name": "luhn",
|
|
17
|
+
"modulo": 10
|
|
17
18
|
}
|
|
18
19
|
},
|
|
19
20
|
"tracking_url": "https://www.odfl.com/us/en/tools/trace-track-ltl-freight/trace.html?proNumbers=%s",
|
|
@@ -43,7 +44,8 @@
|
|
|
43
44
|
],
|
|
44
45
|
"validation": {
|
|
45
46
|
"checksum": {
|
|
46
|
-
"name": "luhn"
|
|
47
|
+
"name": "luhn",
|
|
48
|
+
"modulo": 10
|
|
47
49
|
}
|
|
48
50
|
},
|
|
49
51
|
"tracking_url": "https://www.odfl.com/us/en/tools/trace-track-ltl-freight/trace.html?proNumbers=%s",
|
|
@@ -9,8 +9,10 @@
|
|
|
9
9
|
"validation": {
|
|
10
10
|
"checksum": {
|
|
11
11
|
"name": "mod10",
|
|
12
|
+
"modulo": 10,
|
|
12
13
|
"evens_multiplier": 1,
|
|
13
|
-
"odds_multiplier": 2
|
|
14
|
+
"odds_multiplier": 2,
|
|
15
|
+
"reverse": false
|
|
14
16
|
},
|
|
15
17
|
"serial_number_format": {
|
|
16
18
|
"prepend_if": {
|
|
@@ -42,8 +44,10 @@
|
|
|
42
44
|
"validation": {
|
|
43
45
|
"checksum": {
|
|
44
46
|
"name": "mod10",
|
|
47
|
+
"modulo": 10,
|
|
45
48
|
"evens_multiplier": 1,
|
|
46
|
-
"odds_multiplier": 2
|
|
49
|
+
"odds_multiplier": 2,
|
|
50
|
+
"reverse": false
|
|
47
51
|
},
|
|
48
52
|
"serial_number_format": {
|
|
49
53
|
"prepend_if": {
|
|
@@ -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
|
+
}
|
data/lib/data/couriers/s10.json
CHANGED
|
@@ -4,10 +4,13 @@
|
|
|
4
4
|
"tracking_numbers": [
|
|
5
5
|
{
|
|
6
6
|
"id": "s10",
|
|
7
|
+
"description": "The UPU format every postal service uses for international items",
|
|
7
8
|
"name": "S10",
|
|
8
9
|
"validation": {
|
|
9
10
|
"checksum": {
|
|
10
|
-
"name": "s10"
|
|
11
|
+
"name": "s10",
|
|
12
|
+
"weightings": [8, 6, 4, 2, 3, 5, 9, 7],
|
|
13
|
+
"modulo": 11
|
|
11
14
|
},
|
|
12
15
|
"additional": {
|
|
13
16
|
"exists": [
|
|
@@ -17,6 +20,11 @@
|
|
|
17
20
|
},
|
|
18
21
|
"regex": "\\s*(?<ServiceType>([A-Z]\\s*){2})(?<SerialNumber>([0-9]\\s*){8})(?<CheckDigit>([0-9]\\s*))(?<CountryCode>([A-Z]\\s*){2})",
|
|
19
22
|
"tracking_url": null,
|
|
23
|
+
"glossary": {
|
|
24
|
+
"ServiceType": { "description": "Two letters for the class of postal service, the first of which identifies the service and the second the variant." },
|
|
25
|
+
"SerialNumber": { "description": "Eight digits assigned by the issuing postal service." },
|
|
26
|
+
"CountryCode": { "description": "Two letters for the country whose postal service issued the number, following ISO 3166." }
|
|
27
|
+
},
|
|
20
28
|
"test_numbers": {
|
|
21
29
|
"valid": [
|
|
22
30
|
"RB123456785GB",
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Spee-Dee Delivery",
|
|
3
|
+
"courier_code": "speedee",
|
|
4
|
+
"tracking_numbers": [
|
|
5
|
+
{
|
|
6
|
+
"name": "Spee-Dee (20)",
|
|
7
|
+
"id": "speedee",
|
|
8
|
+
"regex": "\\s*S\\s*P\\s*(?<SerialNumber>([0-9]\\s*){18})\\s*",
|
|
9
|
+
"validation": {},
|
|
10
|
+
"tracking_url": "https://www.speedeedelivery.com/track/?tracking=%s",
|
|
11
|
+
"test_numbers": {
|
|
12
|
+
"valid": [
|
|
13
|
+
"SP029692510000920746",
|
|
14
|
+
"SP029692510000901479",
|
|
15
|
+
"SP029692510000688332",
|
|
16
|
+
"SP029692510000279301",
|
|
17
|
+
"SP029692450001607639"
|
|
18
|
+
],
|
|
19
|
+
"invalid": [
|
|
20
|
+
"029692510000920746",
|
|
21
|
+
"SX029692510000920746"
|
|
22
|
+
]
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
}
|
data/lib/data/couriers/ups.json
CHANGED
|
@@ -15,8 +15,10 @@
|
|
|
15
15
|
"validation": {
|
|
16
16
|
"checksum": {
|
|
17
17
|
"name": "mod10",
|
|
18
|
+
"modulo": 10,
|
|
18
19
|
"evens_multiplier": 1,
|
|
19
|
-
"odds_multiplier": 2
|
|
20
|
+
"odds_multiplier": 2,
|
|
21
|
+
"reverse": false
|
|
20
22
|
}
|
|
21
23
|
},
|
|
22
24
|
"tracking_url": "https://wwwapps.ups.com/WebTracking/track?track=yes&trackNums=%s",
|
|
@@ -146,8 +148,10 @@
|
|
|
146
148
|
"validation": {
|
|
147
149
|
"checksum": {
|
|
148
150
|
"name": "mod10",
|
|
151
|
+
"modulo": 10,
|
|
149
152
|
"evens_multiplier": 1,
|
|
150
|
-
"odds_multiplier": 2
|
|
153
|
+
"odds_multiplier": 2,
|
|
154
|
+
"reverse": false
|
|
151
155
|
}
|
|
152
156
|
},
|
|
153
157
|
"additional": [
|