passkit 0.5.4 → 0.6.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/CHANGELOG.md +4 -0
- data/app/models/passkit/pass.rb +32 -16
- data/docs/passkit_environment_variables.md +8 -6
- data/docs/step5.png +0 -0
- data/lib/passkit/base_pass.rb +103 -5
- data/lib/passkit/example_store_card.rb +30 -6
- data/lib/passkit/generator.rb +36 -11
- data/lib/passkit/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7f0014535dcee793bfad66fd1424eb76f7b93bd5125585c65a2fbbd0ed48e145
|
4
|
+
data.tar.gz: e96bd5782db486f9cdec37721094ed11307e7fda581aa21223c7300c1757cc2a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e1d58e15fff676e4dc197676d5d71d8814a21669086f90e9f19c8e136f64d47205c69b71ffd612efd3411f51d3f6014736571f4e64caab992fa308d737872cff
|
7
|
+
data.tar.gz: 5327cad119f6060ace0e4fe2d485d3df18c412d1e6d4cc652eeded28e77108f91b8a7a6b322caebd87581846ee2fc4c268cd6f5b93fe980d2e1e5d12b1339ba8
|
data/CHANGELOG.md
CHANGED
data/app/models/passkit/pass.rb
CHANGED
@@ -7,30 +7,46 @@ module Passkit
|
|
7
7
|
has_many :registrations, foreign_key: :passkit_pass_id
|
8
8
|
has_many :devices, through: :registrations
|
9
9
|
|
10
|
-
delegate :
|
11
|
-
:
|
12
|
-
:
|
13
|
-
:
|
14
|
-
:
|
15
|
-
:foreground_color,
|
10
|
+
delegate :apple_team_identifier,
|
11
|
+
:app_launch_url,
|
12
|
+
:associated_store_identifiers,
|
13
|
+
:auxiliary_fields,
|
14
|
+
:back_fields,
|
16
15
|
:background_color,
|
17
|
-
:label_color,
|
18
|
-
:web_service_url,
|
19
16
|
:barcode,
|
20
|
-
:
|
21
|
-
:
|
17
|
+
:barcodes,
|
18
|
+
:beacons,
|
19
|
+
:boarding_pass,
|
20
|
+
:coupon,
|
22
21
|
:description,
|
23
|
-
:
|
22
|
+
:event_ticket,
|
23
|
+
:expiration_date,
|
24
|
+
:file_name,
|
25
|
+
:foreground_color,
|
26
|
+
:format_version,
|
27
|
+
:generic,
|
28
|
+
:grouping_identifier,
|
29
|
+
:header_fields,
|
30
|
+
:label_color,
|
31
|
+
:language,
|
24
32
|
:locations,
|
25
|
-
:
|
33
|
+
:logo_text,
|
34
|
+
:max_distance,
|
35
|
+
:nfc,
|
36
|
+
:organization_name,
|
37
|
+
:pass_path,
|
26
38
|
:pass_type,
|
27
|
-
:
|
39
|
+
:pass_type_identifier,
|
28
40
|
:primary_fields,
|
41
|
+
:relevant_date,
|
29
42
|
:secondary_fields,
|
30
|
-
:
|
31
|
-
:back_fields,
|
43
|
+
:semantics,
|
32
44
|
:sharing_prohibited,
|
33
|
-
:
|
45
|
+
:store_card,
|
46
|
+
:suppress_strip_shine,
|
47
|
+
:user_info,
|
48
|
+
:voided,
|
49
|
+
:web_service_url,
|
34
50
|
to: :instance
|
35
51
|
|
36
52
|
before_validation on: :create do
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Setup Passkit Environment variables
|
2
2
|
|
3
|
-
|
3
|
+
### `PASSKIT_WEB_SERVICE_HOST`
|
4
4
|
|
5
5
|
This is the host where your Rails app is running. It is used to generate the URLs for the passes.
|
6
6
|
When the device wants to update the Pass, it will invoke services on this host.
|
@@ -8,19 +8,19 @@ In production, it will simply be your domain name, but in development you can us
|
|
8
8
|
|
9
9
|
**Remember that it must always start with `https://`.**
|
10
10
|
|
11
|
-
|
11
|
+
### `PASSKIT_APPLE_INTERMEDIATE_CERTIFICATE`
|
12
12
|
|
13
13
|
This is the easy one.
|
14
14
|
Head to https://www.apple.com/certificateauthority/ and download the latest Apple Intermediate Certificate Worldwide Developer Relations.
|
15
|
+
You might want to choose the one with the longest expiration date.
|
15
16
|
|
16
|
-
|
17
|
-
## `PASSKIT_APPLE_TEAM_IDENTIFIER`
|
17
|
+
### `PASSKIT_APPLE_TEAM_IDENTIFIER`
|
18
18
|
|
19
19
|
You find this in your Apple Developer dashboard, under Membership.
|
20
20
|
|
21
21
|

|
22
22
|
|
23
|
-
|
23
|
+
### `PASSKIT_PASS_TYPE_IDENTIFIER`, `PASSKIT_PRIVATE_P12_CERTIFICATE` and `PASSKIT_CERTIFICATE_KEY`
|
24
24
|
|
25
25
|
Head to your Apple Developers console and generate a new certificate.
|
26
26
|
|
@@ -40,9 +40,11 @@ And create the certificate:
|
|
40
40
|
|
41
41
|
At the end, you'll have a `pass.cer` file.
|
42
42
|
|
43
|
-
Open it in the Keychain Access tool and export it:
|
43
|
+
Open it in the Keychain Access tool and export it (you must be in the My Certificates tab):
|
44
44
|
|
45
45
|

|
46
46
|
|
47
47
|
Set a password and get your p12 file. The path to this file is the `PASSKIT_PRIVATE_P12_CERTIFICATE` variable.
|
48
48
|
Save the password. This is the `PASSKIT_CERTIFICATE_KEY` variable.
|
49
|
+
|
50
|
+
`PKCS12_parse: unsupported`: you might encounter this issue: https://help.heroku.com/88GYDTB2/how-do-i-configure-openssl-to-allow-the-use-of-legacy-cryptographic-algorithms
|
data/docs/step5.png
CHANGED
Binary file
|
data/lib/passkit/base_pass.rb
CHANGED
@@ -37,6 +37,9 @@ module Passkit
|
|
37
37
|
def pass_type
|
38
38
|
:storeCard
|
39
39
|
# :coupon
|
40
|
+
# :eventTicket
|
41
|
+
# :generic
|
42
|
+
# :boardingPass
|
40
43
|
end
|
41
44
|
|
42
45
|
def web_service_url
|
@@ -83,16 +86,111 @@ module Passkit
|
|
83
86
|
def max_distance
|
84
87
|
end
|
85
88
|
|
89
|
+
# URL to launch the associated app (nil by default)
|
90
|
+
# Returns a String
|
91
|
+
def app_launch_url
|
92
|
+
end
|
93
|
+
|
94
|
+
# A list of Apple App Store identifiers for apps associated
|
95
|
+
# with the pass. The first one that is compatible with the
|
96
|
+
# device is picked.
|
97
|
+
# Returns an array of numbers
|
98
|
+
def associated_store_identifiers
|
99
|
+
[]
|
100
|
+
end
|
101
|
+
|
102
|
+
# An array of barcodes, the first one that can
|
103
|
+
# be displayed on the device is picked.
|
104
|
+
# Returns an array of hashes representing Pass.Barcodes
|
105
|
+
def barcodes
|
106
|
+
[]
|
107
|
+
end
|
108
|
+
|
109
|
+
# List of iBeacon identifiers to identify when the
|
110
|
+
# pass should be displayed.
|
111
|
+
# Returns an array of hashes representing Pass.Beacons
|
112
|
+
def beacons
|
113
|
+
[]
|
114
|
+
end
|
115
|
+
|
116
|
+
# Information specific to a boarding pass
|
117
|
+
# Returns a hash representing Pass.BoardingPass
|
118
|
+
def boarding_pass
|
119
|
+
end
|
120
|
+
|
121
|
+
# Information specific to a coupon
|
122
|
+
# Returns a hash representing Pass.Coupon
|
123
|
+
def coupon
|
124
|
+
end
|
125
|
+
|
126
|
+
# Information specific to an event ticket
|
127
|
+
# Returns a hash representing Pass.EventTicket
|
128
|
+
def event_ticket
|
129
|
+
end
|
130
|
+
|
131
|
+
# Date and time the pass expires, must include
|
132
|
+
# days, hours and minutes (seconds are optional)
|
133
|
+
# Returns a String representing the date and time in W3C format
|
134
|
+
def expiration_date
|
135
|
+
end
|
136
|
+
|
137
|
+
# Information specific to a generic pass
|
138
|
+
# Returns a hash representing Pass.Generic
|
139
|
+
def generic
|
140
|
+
end
|
141
|
+
|
142
|
+
# A key to identify group multiple passes together
|
143
|
+
# (e.g. a number of boarding passes for the same trip)
|
144
|
+
# Returns a String
|
145
|
+
def grouping_identifier
|
146
|
+
end
|
147
|
+
|
148
|
+
# Information specific to Value Added Service Protocol
|
149
|
+
# transactions
|
150
|
+
# Returns a hash representing Pass.NFC
|
151
|
+
def nfc
|
152
|
+
end
|
153
|
+
|
154
|
+
# Date and time when the pass becomes relevant and should be
|
155
|
+
# displayed, must include days, hours and minutes
|
156
|
+
# (seconds are optional)
|
157
|
+
# Returns a String representing the date and time in W3C format
|
158
|
+
def relevant_date
|
159
|
+
end
|
160
|
+
|
161
|
+
# Machine readable metadata that the device can use
|
162
|
+
# to suggest actions
|
163
|
+
# Returns a hash representing SemanticTags
|
164
|
+
def semantics
|
165
|
+
end
|
166
|
+
|
167
|
+
# Information specific to a store card
|
168
|
+
# Returns a hash representing Pass.StoreCard
|
169
|
+
def store_card
|
170
|
+
end
|
171
|
+
|
172
|
+
# Display the strip image without a shine effect
|
173
|
+
# Returns a boolean
|
174
|
+
def suppress_strip_shine
|
175
|
+
true
|
176
|
+
end
|
177
|
+
|
178
|
+
# JSON dictionary to display custom information for
|
179
|
+
# companion apps. Data isn't displayed to the user. e.g.
|
180
|
+
# a machine readable version of the user's favourite coffee
|
181
|
+
def user_info
|
182
|
+
end
|
183
|
+
|
86
184
|
def file_name
|
87
185
|
@file_name ||= SecureRandom.uuid
|
88
186
|
end
|
89
187
|
|
90
188
|
# QRCode by default
|
91
189
|
def barcode
|
92
|
-
{messageEncoding: "iso-8859-1",
|
93
|
-
|
94
|
-
|
95
|
-
|
190
|
+
{ messageEncoding: "iso-8859-1",
|
191
|
+
format: "PKBarcodeFormatQR",
|
192
|
+
message: "https://github.com/coorasse/passkit",
|
193
|
+
altText: "https://github.com/coorasse/passkit" }
|
96
194
|
end
|
97
195
|
|
98
196
|
# Barcode example
|
@@ -131,7 +229,7 @@ module Passkit
|
|
131
229
|
false
|
132
230
|
end
|
133
231
|
|
134
|
-
|
232
|
+
private
|
135
233
|
|
136
234
|
def folder_name
|
137
235
|
self.class.name.demodulize.underscore
|
@@ -37,11 +37,13 @@ module Passkit
|
|
37
37
|
end
|
38
38
|
|
39
39
|
# QRCode by default
|
40
|
-
def
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
40
|
+
def barcodes
|
41
|
+
[
|
42
|
+
{ messageEncoding: "iso-8859-1",
|
43
|
+
format: "PKBarcodeFormatQR",
|
44
|
+
message: "https://github.com/coorasse/passkit",
|
45
|
+
altText: "https://github.com/coorasse/passkit" }
|
46
|
+
]
|
45
47
|
end
|
46
48
|
|
47
49
|
# Barcode example
|
@@ -56,6 +58,28 @@ module Passkit
|
|
56
58
|
"Loyalty Card"
|
57
59
|
end
|
58
60
|
|
61
|
+
def app_launch_url
|
62
|
+
"https://github.com/coorasse/passkit"
|
63
|
+
end
|
64
|
+
|
65
|
+
def relevant_date
|
66
|
+
Time.current.strftime("%Y-%m-%dT%H:%M:%S%z")
|
67
|
+
end
|
68
|
+
|
69
|
+
def expiration_date
|
70
|
+
# Expire the pass tomorrow
|
71
|
+
(Time.current + 60*60*24).strftime("%Y-%m-%dT%H:%M:%S%z")
|
72
|
+
end
|
73
|
+
|
74
|
+
def semantics
|
75
|
+
{
|
76
|
+
balance: {
|
77
|
+
amount: "100",
|
78
|
+
currencyCode: "USD"
|
79
|
+
}
|
80
|
+
}
|
81
|
+
end
|
82
|
+
|
59
83
|
def header_fields
|
60
84
|
[{
|
61
85
|
key: "balance",
|
@@ -101,7 +125,7 @@ module Passkit
|
|
101
125
|
}]
|
102
126
|
end
|
103
127
|
|
104
|
-
|
128
|
+
private
|
105
129
|
|
106
130
|
def folder_name
|
107
131
|
self.class.name.demodulize.underscore
|
data/lib/passkit/generator.rb
CHANGED
@@ -23,7 +23,7 @@ module Passkit
|
|
23
23
|
compress_pass_file
|
24
24
|
end
|
25
25
|
|
26
|
-
|
26
|
+
private
|
27
27
|
|
28
28
|
def check_necessary_files
|
29
29
|
raise "icon.png is not present in #{@pass.pass_path}" unless File.exist?(File.join(@pass.pass_path, "icon.png"))
|
@@ -48,24 +48,49 @@ module Passkit
|
|
48
48
|
pass = {
|
49
49
|
formatVersion: @pass.format_version,
|
50
50
|
teamIdentifier: @pass.apple_team_identifier,
|
51
|
-
|
51
|
+
authenticationToken: @pass.authentication_token,
|
52
52
|
backgroundColor: @pass.background_color,
|
53
|
-
webServiceURL: @pass.web_service_url,
|
54
|
-
barcode: @pass.barcode,
|
55
|
-
voided: @pass.voided,
|
56
|
-
organizationName: @pass.organization_name,
|
57
53
|
description: @pass.description,
|
58
|
-
|
59
|
-
locations: @pass.locations,
|
54
|
+
foregroundColor: @pass.foreground_color,
|
60
55
|
labelColor: @pass.label_color,
|
61
|
-
|
62
|
-
|
56
|
+
locations: @pass.locations,
|
57
|
+
logoText: @pass.logo_text,
|
58
|
+
organizationName: @pass.organization_name,
|
63
59
|
passTypeIdentifier: @pass.pass_type_identifier,
|
64
|
-
|
60
|
+
serialNumber: @pass.serial_number,
|
61
|
+
sharingProhibited: @pass.sharing_prohibited,
|
62
|
+
suppressStripShine: @pass.suppress_strip_shine,
|
63
|
+
voided: @pass.voided,
|
64
|
+
webServiceURL: @pass.web_service_url
|
65
65
|
}
|
66
66
|
|
67
67
|
pass[:maxDistance] = @pass.max_distance if @pass.max_distance
|
68
68
|
|
69
|
+
# If the newer barcodes attribute has been used, then
|
70
|
+
# include the list of barcodes, otherwise fall back to
|
71
|
+
# the original barcode attribute
|
72
|
+
barcodes = @pass.barcodes || []
|
73
|
+
if barcodes.empty?
|
74
|
+
pass[:barcode] = @pass.barcode
|
75
|
+
else
|
76
|
+
pass[:barcodes] = @pass.barcodes
|
77
|
+
end
|
78
|
+
|
79
|
+
pass[:appLaunchURL] = @pass.app_launch_url if @pass.app_launch_url
|
80
|
+
pass[:associatedStoreIdentifiers] = @pass.associated_store_identifiers unless @pass.associated_store_identifiers.empty?
|
81
|
+
pass[:beacons] = @pass.beacons unless @pass.beacons.empty?
|
82
|
+
pass[:boardingPass] = @pass.boarding_pass if @pass.boarding_pass
|
83
|
+
pass[:coupon] = @pass.coupon if @pass.coupon
|
84
|
+
pass[:eventTicket] = @pass.event_ticket if @pass.event_ticket
|
85
|
+
pass[:expirationDate] = @pass.expiration_date if @pass.expiration_date
|
86
|
+
pass[:generic] = @pass.generic if @pass.generic
|
87
|
+
pass[:groupingIdentifier] = @pass.grouping_identifier if @pass.grouping_identifier
|
88
|
+
pass[:nfc] = @pass.nfc if @pass.nfc
|
89
|
+
pass[:relevantDate] = @pass.relevant_date if @pass.relevant_date
|
90
|
+
pass[:semantics] = @pass.semantics if @pass.semantics
|
91
|
+
pass[:store_card] = @pass.store_card if @pass.store_card
|
92
|
+
pass[:userInfo] = @pass.user_info if @pass.user_info
|
93
|
+
|
69
94
|
pass[@pass.pass_type] = {
|
70
95
|
headerFields: @pass.header_fields,
|
71
96
|
primaryFields: @pass.primary_fields,
|
data/lib/passkit/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: passkit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alessandro Rodi
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-01-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|