passkit 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.example.env +6 -0
- data/README.md +44 -41
- data/app/controllers/passkit/api/v1/passes_controller.rb +9 -6
- data/app/controllers/passkit/api/v1/registrations_controller.rb +1 -1
- data/app/models/passkit/pass.rb +4 -0
- data/docs/membership.png +0 -0
- data/docs/passkit_environment_variables.md +48 -0
- data/docs/step1.png +0 -0
- data/docs/step2.png +0 -0
- data/docs/step3.png +0 -0
- data/docs/step4.png +0 -0
- data/docs/step5.png +0 -0
- data/lib/passkit/base_pass.rb +4 -0
- data/lib/passkit/factory.rb +2 -2
- data/lib/passkit/payload_generator.rb +18 -0
- data/lib/passkit/url_generator.rb +2 -9
- data/lib/passkit/version.rb +1 -1
- data/lib/passkit.rb +2 -1
- data/passkit-0.2.0.gem +0 -0
- data/sig/lib/passkit/factory.rbs +1 -1
- metadata +26 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 37dfbf2ceba4423e2a1eba28d94aa8f5fbf676c011429efb8759af2f7fd8c477
|
4
|
+
data.tar.gz: 5909695a00d94a28da5f4ae1ee318a1d7d7320c8599646457a408b7c2a780af0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 637340fef65ed2655a1e8bedaf9d86a5ece533782bbd6c3c92a26d2e49d5153de1be57e27977994b13b63e1f47a2b39b30e481c57539771b8c06b3f2db4b6691
|
7
|
+
data.tar.gz: 5350a3793c359fbbf00d197541e7b51577c93c46c68068f8e0f7cb852ff46f6c9d1f60e4a3a8c00fc66a52c82c6e95b94b768ff602b1c188bb887f3128214821
|
data/.example.env
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
PASSKIT_WEB_SERVICE_HOST=https://localhost:3000
|
2
|
+
PASSKIT_CERTIFICATE_KEY=path/to/certificate.key
|
3
|
+
PASSKIT_PRIVATE_P12_CERTIFICATE=path/to/certificate.p12
|
4
|
+
PASSKIT_APPLE_INTERMEDIATE_CERTIFICATE=path/to/AppleWWDRCA.cer
|
5
|
+
PASSKIT_APPLE_TEAM_IDENTIFIER=XXXXXXXXXX
|
6
|
+
PASSKIT_PASS_TYPE_IDENTIFIER=pass.com.example.pass
|
data/README.md
CHANGED
@@ -4,24 +4,28 @@ Your out-of-the-box solution to start serving Wallet Passes in your Ruby On Rail
|
|
4
4
|
|
5
5
|
Do you have a QRCode or a Barcode anywhere in your app that you want to distribute as Wallet Pass, compatible for iOS and Android? Look no further!
|
6
6
|
|
7
|
-
This gem provides everything
|
7
|
+
This gem provides everything necessary to distribute Wallet Passes in pkpass format, and gives you all the steps to follow for what we cannot provide.
|
8
8
|
|
9
|
-
We provide
|
9
|
+
**We provide:**
|
10
10
|
|
11
|
-
* A (not yet) fancy dashboard to manage your passes, registered devices and logs
|
11
|
+
* A (not yet) fancy dashboard to manage your passes, registered devices and logs.
|
12
12
|
* All API endpoints to serve your passes: create, register, update, unregister, etc...
|
13
|
-
* All ActiveRecord models
|
14
|
-
* A BasePass model that you can extend to create your own passes
|
15
|
-
* Some helpers to generate the necessary URLs, so that you can include them in the emails
|
16
|
-
* Examples for everything
|
13
|
+
* All necessary ActiveRecord models.
|
14
|
+
* A BasePass model that you can extend to create your own passes.
|
15
|
+
* Some helpers to generate the necessary URLs, so that you can include them in the emails.
|
16
|
+
* Examples for everything.
|
17
17
|
|
18
|
-
We don't provide yet
|
18
|
+
**We don't provide (yet):**
|
19
19
|
|
20
|
-
* Full tests coverage
|
21
|
-
* A fancy dashboard. Pull requests are welcome!
|
22
|
-
* Push notifications. Pull requests are welcome!
|
23
|
-
* Google Wallet
|
20
|
+
* Full tests coverage: we are working on it!
|
21
|
+
* A fancy dashboard: our dashboard is really really simple right now. Pull requests are welcome!
|
22
|
+
* Push notifications: this is the most wanted feature I believe. Pull requests are welcome!
|
23
|
+
* Google Wallet integration: we use https://walletpasses.io/ on Android to read .pkpass format.
|
24
24
|
|
25
|
+
## Apple documentation
|
26
|
+
|
27
|
+
* [Apple Wallet Passes](https://developer.apple.com/documentation/walletpasses)
|
28
|
+
* [Send Push Notifications](https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns)
|
25
29
|
|
26
30
|
## Installation
|
27
31
|
|
@@ -45,18 +49,18 @@ Run the initializer:
|
|
45
49
|
|
46
50
|
that will generate the migrations and the initializer file.
|
47
51
|
|
48
|
-
Mount the engine in your routes.rb
|
52
|
+
Mount the engine in your `config/routes.rb`:
|
49
53
|
|
50
54
|
```ruby
|
51
55
|
mount Passkit::Engine => '/passkit', as: 'passkit'
|
52
56
|
```
|
53
57
|
|
54
|
-
and run `rails db:migrate`.
|
58
|
+
and run `bin/rails db:migrate`.
|
55
59
|
|
56
|
-
|
60
|
+
### Setup environment variables
|
57
61
|
|
58
|
-
If you followed the installation steps, you already saw that Passkit provides
|
59
|
-
you the tables and ActiveRecord models, and also an engine the necessary APIs already implemented.
|
62
|
+
If you followed the installation steps, you already saw that Passkit provides
|
63
|
+
you the tables and ActiveRecord models, and also an engine with the necessary APIs already implemented.
|
60
64
|
|
61
65
|
Now is your turn. Before proceeding, you need to set these ENV variables:
|
62
66
|
* `PASSKIT_WEB_SERVICE_HOST`
|
@@ -67,14 +71,19 @@ Now is your turn. Before proceeding, you need to set these ENV variables:
|
|
67
71
|
* `PASSKIT_PASS_TYPE_IDENTIFIER`
|
68
72
|
|
69
73
|
We have a [specific guide on how to get all these](docs/passkit_environment_variables.md), please follow it.
|
70
|
-
You cannot
|
74
|
+
You cannot start using this library without these variables set, and we cannot do the work for you.
|
71
75
|
|
72
|
-
|
76
|
+
## Usage
|
73
77
|
|
74
78
|
If you followed the installation steps and you have the ENV variables set, we can start looking at what is provided for you.
|
75
79
|
|
76
|
-
|
80
|
+
### Dashboard
|
81
|
+
|
82
|
+
Head to `http://localhost:3000/passkit/previews` and you will see a first `ExampleStoreCard` available for download.
|
77
83
|
You can click on the button and you will obtain a `.pkpass` file that you can simply open or install on your phone.
|
84
|
+
The dashboard has also a view for logs, and a view for emitted passes.
|
85
|
+
|
86
|
+
### Mailer Helpers
|
78
87
|
|
79
88
|
If you use mailer previews, you can create the following file in `spec/mailers/previews/passkit/example_mailer_preview.rb`:
|
80
89
|
|
@@ -89,21 +98,28 @@ end
|
|
89
98
|
```
|
90
99
|
|
91
100
|
and head to `http://localhost:3000/rails/mailers/` to see an example of email with links to download the Wallet Pass.
|
101
|
+
Please check the source code of [ExampleMailer](app/mailers/passkit/example_mailer.rb) to see how to distribute your own Wallet Passes.
|
102
|
+
|
103
|
+
### Example Passes
|
104
|
+
|
105
|
+
Please check the source code of the [ExampleStoreCard](lib/passkit/example_store_card.rb) to see how to create your own Wallet Passes.
|
92
106
|
|
93
|
-
|
94
|
-
Looking at the examples, is the easiest way to get started.
|
107
|
+
Again, looking at these examples, is the easiest way to get started.
|
95
108
|
|
96
109
|
### Create your own Wallet Pass
|
97
110
|
|
98
|
-
You can create your own Wallet Passes by creating a new class that inherits from `Passkit::BasePass` and
|
111
|
+
You can create your own Wallet Passes by creating a new class that inherits from `Passkit::BasePass` and
|
112
|
+
defining the methods that you want to override.
|
113
|
+
|
99
114
|
You can define colors, fields and texts. You can also define the logo and the background image.
|
100
115
|
|
101
|
-
You
|
116
|
+
You should place the images in a 'private/passkit/<your_downcased_passname>' folder.
|
102
117
|
There is a [dummy app in the gem](test/dummy) that you can use to check how to create your own Wallet Passes.
|
103
118
|
|
104
119
|
### Serve your Wallet Pass
|
105
120
|
|
106
|
-
Use the [Passkit::UrlGenerator](lib/passkit/url_generator.rb) to generate the URL to serve your Wallet Pass.
|
121
|
+
Use the [Passkit::UrlGenerator](lib/passkit/url_generator.rb) to generate the URL to serve your Wallet Pass.
|
122
|
+
You can initialize it with:
|
107
123
|
|
108
124
|
```ruby
|
109
125
|
Passkit::UrlGenerator.new(pass_class: Passkit::MyPass, generator: User.find(1))
|
@@ -119,21 +135,6 @@ Again, check the example mailer included in the gem to see how to use it.
|
|
119
135
|
* In case of error "The passTypeIdentifier or teamIdentifier provided may not match your certificate,
|
120
136
|
or the certificate trust chain could not be verified." the certificate (p12) might be expired.
|
121
137
|
|
122
|
-
|
123
|
-
* Setup ngrok and start it
|
124
|
-
* Configure your `HOST: 'https://xxx.ngrok.io'` on `config/application.yml` (make sure is https!)
|
125
|
-
* Set `config.hosts = nil` in `config/environments/development.rb`
|
126
|
-
* Head to the `/rails/mailers/` and preview an email containing a pass
|
127
|
-
* Download the pkpass and open it
|
128
|
-
|
129
|
-
|
130
|
-
Here are the rough steps to generate a new one:
|
131
|
-
* Access https://developer.apple.com/account/resources/identifiers/passTypeId/edit/F578W7LDT9/pass.ch.renuo.loyalty.
|
132
|
-
* Click "Create Certificate".
|
133
|
-
* Follow the guide to generate a new Certificate Signing Request and use operations@renuo.ch as email address and Renuo AG as organization name.
|
134
|
-
* Convert the certificate to p12 using Keychain Access and re-use the same password.
|
135
|
-
* Re-upload the new certificate to the servers.
|
136
|
-
|
137
138
|
## Development
|
138
139
|
|
139
140
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
@@ -154,4 +155,6 @@ Everyone interacting in the Passkit project's codebases, issue trackers, chat ro
|
|
154
155
|
|
155
156
|
## Credits
|
156
157
|
|
157
|
-
<a href="https://www.flaticon.com/free-icons/credit-card" title="credit card icons">Credit card icons created by Iconfromus - Flaticon</a>
|
158
|
+
* <a href="https://www.flaticon.com/free-icons/credit-card" title="credit card icons">Credit card icons created by Iconfromus - Flaticon</a>
|
159
|
+
|
160
|
+
* https://www.sitepoint.com/whats-in-your-wallet-handling-ios-passbook-with-ruby/
|
@@ -12,7 +12,7 @@ module Passkit
|
|
12
12
|
# @return If the request is not authorized, returns HTTP status 401.
|
13
13
|
# @return Otherwise, returns the appropriate standard HTTP status.
|
14
14
|
def show
|
15
|
-
authentication_token = request.headers["Authorization"]&.split(" ")
|
15
|
+
authentication_token = request.headers["Authorization"]&.split(" ")&.last
|
16
16
|
unless authentication_token.present?
|
17
17
|
render json: {}, status: :unauthorized
|
18
18
|
return
|
@@ -26,9 +26,9 @@ module Passkit
|
|
26
26
|
|
27
27
|
pass_output_path = Passkit::Generator.new(pass).generate_and_sign
|
28
28
|
|
29
|
-
response.headers["last-modified"] = pass.
|
29
|
+
response.headers["last-modified"] = pass.last_update.strftime("%Y-%m-%d %H:%M:%S")
|
30
30
|
if request.headers["If-Modified-Since"].nil? ||
|
31
|
-
(pass.
|
31
|
+
(pass.last_update.to_i > Time.zone.parse(request.headers["If-Modified-Since"]).to_i)
|
32
32
|
send_file(pass_output_path)
|
33
33
|
else
|
34
34
|
head :not_modified
|
@@ -45,9 +45,12 @@ module Passkit
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def fetch_pass(payload)
|
48
|
-
|
49
|
-
|
50
|
-
|
48
|
+
generator = nil
|
49
|
+
if payload[:generator_class].present? && payload[:generator_id].present?
|
50
|
+
generator_class = payload[:generator_class].constantize
|
51
|
+
generator = generator_class.find(payload[:generator_id])
|
52
|
+
end
|
53
|
+
Passkit::Factory.create_pass(payload[:pass_class], generator)
|
51
54
|
end
|
52
55
|
end
|
53
56
|
end
|
@@ -61,7 +61,7 @@ module Passkit
|
|
61
61
|
private
|
62
62
|
|
63
63
|
def load_pass
|
64
|
-
authentication_token = request.headers["Authorization"]&.split(" ")
|
64
|
+
authentication_token = request.headers["Authorization"]&.split(" ")&.last
|
65
65
|
unless authentication_token.present?
|
66
66
|
render json: {}, status: :unauthorized
|
67
67
|
return
|
data/app/models/passkit/pass.rb
CHANGED
data/docs/membership.png
ADDED
Binary file
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# Setup Passkit Environment variables
|
2
|
+
|
3
|
+
## `PASSKIT_WEB_SERVICE_HOST`
|
4
|
+
|
5
|
+
This is the host where your Rails app is running. It is used to generate the URLs for the passes.
|
6
|
+
When the device wants to update the Pass, it will invoke services on this host.
|
7
|
+
In production, it will simply be your domain name, but in development you can use [ngrok](https://ngrok.com/) to expose your local server to the internet.
|
8
|
+
|
9
|
+
**Remember that it must always start with `https://`.**
|
10
|
+
|
11
|
+
## `PASSKIT_APPLE_INTERMEDIATE_CERTIFICATE`
|
12
|
+
|
13
|
+
This is the easy one.
|
14
|
+
Head to https://www.apple.com/certificateauthority/ and download the latest Apple Intermediate Certificate Worldwide Developer Relations.
|
15
|
+
|
16
|
+
|
17
|
+
## `PASSKIT_APPLE_TEAM_IDENTIFIER`
|
18
|
+
|
19
|
+
You find this in your Apple Developer dashboard, under Membership.
|
20
|
+
|
21
|
+
![Membership](membership.png)
|
22
|
+
|
23
|
+
## `PASSKIT_PASS_TYPE_IDENTIFIER`, `PASSKIT_PRIVATE_P12_CERTIFICATE` and `PASSKIT_CERTIFICATE_KEY`
|
24
|
+
|
25
|
+
Head to your Apple Developers console and generate a new certificate.
|
26
|
+
|
27
|
+
![Step 1](step1.png)
|
28
|
+
|
29
|
+
![Step 2](step2.png)
|
30
|
+
|
31
|
+
![Step 3](step3.png)
|
32
|
+
|
33
|
+
The identifier is the `PASSKIT_PASS_TYPE_IDENTIFIER` variable.
|
34
|
+
|
35
|
+
Now, create a certificate signing request: https://help.apple.com/developer-account/#/devbfa00fef7
|
36
|
+
|
37
|
+
And create the certificate:
|
38
|
+
|
39
|
+
![Step 4](step4.png)
|
40
|
+
|
41
|
+
At the end, you'll have a `pass.cer` file.
|
42
|
+
|
43
|
+
Open it in the Keychain Access tool and export it:
|
44
|
+
|
45
|
+
![Step 5](step5.png)
|
46
|
+
|
47
|
+
Set a password and get your p12 file. The path to this file is the `PASSKIT_PRIVATE_P12_CERTIFICATE` variable.
|
48
|
+
Save the password. This is the `PASSKIT_CERTIFICATE_KEY` variable.
|
data/docs/step1.png
ADDED
Binary file
|
data/docs/step2.png
ADDED
Binary file
|
data/docs/step3.png
ADDED
Binary file
|
data/docs/step4.png
ADDED
Binary file
|
data/docs/step5.png
ADDED
Binary file
|
data/lib/passkit/base_pass.rb
CHANGED
data/lib/passkit/factory.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
module Passkit
|
2
2
|
class Factory
|
3
3
|
class << self
|
4
|
-
def create_pass(
|
5
|
-
pass = Pass.create!(
|
4
|
+
def create_pass(pass_class, generator = nil)
|
5
|
+
pass = Pass.create!(klass: pass_class, generator: generator)
|
6
6
|
Passkit::Generator.new(pass).generate_and_sign
|
7
7
|
end
|
8
8
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Passkit
|
2
|
+
class PayloadGenerator
|
3
|
+
VALIDITY = 30.days
|
4
|
+
|
5
|
+
def self.encrypted(pass_class, generator = nil)
|
6
|
+
UrlEncrypt.encrypt(hash(pass_class, generator))
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.hash(pass_class, generator = nil)
|
10
|
+
valid_until = VALIDITY.from_now
|
11
|
+
|
12
|
+
{valid_until: valid_until,
|
13
|
+
generator_class: generator&.class&.name,
|
14
|
+
generator_id: generator&.id,
|
15
|
+
pass_class: pass_class.name}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -2,16 +2,9 @@ module Passkit
|
|
2
2
|
class UrlGenerator
|
3
3
|
include Passkit::Engine.routes.url_helpers
|
4
4
|
|
5
|
-
VALIDITY = 30.days
|
6
|
-
|
7
5
|
def initialize(pass_class, generator = nil)
|
8
|
-
|
9
|
-
|
10
|
-
payload = {valid_until: valid_until,
|
11
|
-
generator_class: generator&.class&.name,
|
12
|
-
generator_id: generator&.id,
|
13
|
-
pass_class: pass_class.name}
|
14
|
-
@url = passes_api_url(host: ENV["PASSKIT_WEB_SERVICE_HOST"], payload: UrlEncrypt.encrypt(payload))
|
6
|
+
@url = passes_api_url(host: ENV["PASSKIT_WEB_SERVICE_HOST"],
|
7
|
+
payload: PayloadGenerator.encrypted(pass_class, generator))
|
15
8
|
end
|
16
9
|
|
17
10
|
def ios
|
data/lib/passkit/version.rb
CHANGED
data/lib/passkit.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "rails"
|
3
4
|
require "passkit/engine"
|
4
5
|
|
5
6
|
require "zeitwerk"
|
@@ -31,7 +32,7 @@ module Passkit
|
|
31
32
|
def initialize
|
32
33
|
@available_passes = {"Passkit::ExampleStoreCard" => -> {}}
|
33
34
|
@web_service_host = ENV["PASSKIT_WEB_SERVICE_HOST"] || (raise "Please set PASSKIT_WEB_SERVICE_HOST")
|
34
|
-
raise("PASSKIT_WEB_SERVICE_HOST must start with https://") unless @web_service_host.
|
35
|
+
raise("PASSKIT_WEB_SERVICE_HOST must start with https://") unless @web_service_host.start_with?("https://")
|
35
36
|
@certificate_key = ENV["PASSKIT_CERTIFICATE_KEY"] || (raise "Please set PASSKIT_CERTIFICATE_KEY")
|
36
37
|
@private_p12_certificate = ENV["PASSKIT_PRIVATE_P12_CERTIFICATE"] || (raise "Please set PASSKIT_PRIVATE_P12_CERTIFICATE")
|
37
38
|
@apple_intermediate_certificate = ENV["PASSKIT_APPLE_INTERMEDIATE_CERTIFICATE"] || (raise "Please set PASSKIT_APPLE_INTERMEDIATE_CERTIFICATE")
|
data/passkit-0.2.0.gem
ADDED
Binary file
|
data/sig/lib/passkit/factory.rbs
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.3.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: 2022-
|
11
|
+
date: 2022-10-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '3.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: dotenv
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: standard
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -88,6 +102,7 @@ executables: []
|
|
88
102
|
extensions: []
|
89
103
|
extra_rdoc_files: []
|
90
104
|
files:
|
105
|
+
- ".example.env"
|
91
106
|
- ".standard.yml"
|
92
107
|
- CHANGELOG.md
|
93
108
|
- CODE_OF_CONDUCT.md
|
@@ -123,6 +138,13 @@ files:
|
|
123
138
|
- bin/console
|
124
139
|
- bin/setup
|
125
140
|
- config/routes.rb
|
141
|
+
- docs/membership.png
|
142
|
+
- docs/passkit_environment_variables.md
|
143
|
+
- docs/step1.png
|
144
|
+
- docs/step2.png
|
145
|
+
- docs/step3.png
|
146
|
+
- docs/step4.png
|
147
|
+
- docs/step5.png
|
126
148
|
- docs/wallet.png
|
127
149
|
- lib/generators/passkit/install_generator.rb
|
128
150
|
- lib/generators/templates/create_passkit_tables.rb.tt
|
@@ -137,9 +159,11 @@ files:
|
|
137
159
|
- lib/passkit/example_store_card/logo.png
|
138
160
|
- lib/passkit/factory.rb
|
139
161
|
- lib/passkit/generator.rb
|
162
|
+
- lib/passkit/payload_generator.rb
|
140
163
|
- lib/passkit/url_encrypt.rb
|
141
164
|
- lib/passkit/url_generator.rb
|
142
165
|
- lib/passkit/version.rb
|
166
|
+
- passkit-0.2.0.gem
|
143
167
|
- sig/lib/passkit/encryptable_payload.rbs
|
144
168
|
- sig/lib/passkit/factory.rbs
|
145
169
|
- sig/lib/passkit/generator.rbs
|