aliquot 0.15.0 → 2.1.1
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/lib/aliquot/error.rb +2 -1
- data/lib/aliquot/payment.rb +18 -17
- data/lib/aliquot/validator.rb +179 -93
- metadata +55 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 340c8e93be8733d7b403356c5d7b85f0f1b69466e8492f6750875f7d1b4b0332
|
4
|
+
data.tar.gz: 27bb764e594448851ddceaaf0e65afd0a8c7916b82cf65514f077ad67d65ac56
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 70e3dfd919b5b2dde76eb7025a6627b46f2462096a7a9ce747764315c8b612104be97a38c7c4e8f7b2d5927e807adf992dc4bd7c145d5e091c6a699c5fae4830
|
7
|
+
data.tar.gz: 58c0275b221f378289d417131eb3e84039be05183b09e0e00cdb0b5ad8450d59c28d859ec5242544ce6eedbd0b0a933b6ad82e4e3bd0fb3ae0d62041e9e44a8d
|
data/lib/aliquot/error.rb
CHANGED
data/lib/aliquot/payment.rb
CHANGED
@@ -10,29 +10,29 @@ module Aliquot
|
|
10
10
|
##
|
11
11
|
# A Payment represents a single payment using Google Pay.
|
12
12
|
# It is used to verify/decrypt the supplied token by using the shared secret,
|
13
|
-
# thus avoiding having knowledge of
|
13
|
+
# thus avoiding having knowledge of any private keys involved.
|
14
14
|
class Payment
|
15
15
|
SUPPORTED_PROTOCOL_VERSIONS = %w[ECv1 ECv2].freeze
|
16
16
|
##
|
17
17
|
# Parameters:
|
18
18
|
# token_string:: Google Pay token (JSON string)
|
19
19
|
# shared_secret:: Base64 encoded shared secret
|
20
|
-
#
|
20
|
+
# recipient_id:: Google Pay recipient ID
|
21
21
|
# signing_keys:: Signing keys fetched from Google
|
22
|
-
def initialize(token_string, shared_secret,
|
22
|
+
def initialize(token_string, shared_secret, recipient_id,
|
23
23
|
signing_keys: ENV['GOOGLE_SIGNING_KEYS'])
|
24
24
|
|
25
25
|
begin
|
26
26
|
validation = Aliquot::Validator::Token.new(JSON.parse(token_string))
|
27
27
|
validation.validate
|
28
28
|
rescue JSON::JSONError => e
|
29
|
-
raise InputError, "
|
29
|
+
raise InputError, "token JSON is invalid, #{e.message}"
|
30
30
|
end
|
31
31
|
|
32
32
|
@token = validation.output
|
33
33
|
|
34
34
|
@shared_secret = shared_secret
|
35
|
-
@
|
35
|
+
@recipient_id = recipient_id
|
36
36
|
@signing_keys = signing_keys
|
37
37
|
end
|
38
38
|
|
@@ -43,13 +43,13 @@ module Aliquot
|
|
43
43
|
raise Error, "supported protocol versions are #{SUPPORTED_PROTOCOL_VERSIONS.join(', ')}"
|
44
44
|
end
|
45
45
|
|
46
|
-
@recipient_id =
|
46
|
+
@recipient_id = validate_recipient_id
|
47
47
|
|
48
48
|
check_shared_secret
|
49
49
|
|
50
50
|
if protocol_version == 'ECv2'
|
51
51
|
@intermediate_key = validate_intermediate_key
|
52
|
-
raise InvalidSignatureError, 'intermediate certificate
|
52
|
+
raise InvalidSignatureError, 'intermediate certificate is expired' if intermediate_key_expired?
|
53
53
|
end
|
54
54
|
|
55
55
|
check_signature
|
@@ -59,22 +59,22 @@ module Aliquot
|
|
59
59
|
begin
|
60
60
|
aes_key, mac_key = derive_keys(@signed_message[:ephemeralPublicKey], @shared_secret, 'Google')
|
61
61
|
rescue => e
|
62
|
-
raise KeyDerivationError, "
|
62
|
+
raise KeyDerivationError, "cannot derive keys, #{e.message}"
|
63
63
|
end
|
64
64
|
|
65
|
-
raise InvalidMacError, 'MAC
|
65
|
+
raise InvalidMacError, 'MAC does not match' unless valid_mac?(mac_key)
|
66
66
|
|
67
67
|
begin
|
68
68
|
@message = JSON.parse(decrypt(aes_key, @signed_message[:encryptedMessage]))
|
69
69
|
rescue JSON::JSONError => e
|
70
|
-
raise InputError, "
|
70
|
+
raise InputError, "encryptedMessage JSON is invalid, #{e.message}"
|
71
71
|
rescue => e
|
72
72
|
raise DecryptionError, "decryption failed, #{e.message}"
|
73
73
|
end
|
74
74
|
|
75
75
|
@message = validate_message
|
76
76
|
|
77
|
-
raise TokenExpiredError, 'token
|
77
|
+
raise TokenExpiredError, 'token is expired' if expired?
|
78
78
|
|
79
79
|
@message
|
80
80
|
end
|
@@ -102,9 +102,10 @@ module Aliquot
|
|
102
102
|
@intermediate_key[:keyExpiration].to_i < cur_millis
|
103
103
|
end
|
104
104
|
|
105
|
-
def
|
106
|
-
raise
|
107
|
-
|
105
|
+
def validate_recipient_id
|
106
|
+
raise InvalidRecipientIDError, 'recipient_id must be alphanumeric and punctuation' unless /\A[[:graph:]]+\z/ =~ @recipient_id
|
107
|
+
|
108
|
+
@recipient_id
|
108
109
|
end
|
109
110
|
|
110
111
|
def check_shared_secret
|
@@ -133,7 +134,7 @@ module Aliquot
|
|
133
134
|
key.verify(new_digest, message_signature, signed_string_message)
|
134
135
|
end.any?
|
135
136
|
|
136
|
-
raise InvalidSignatureError, 'signature of signedMessage
|
137
|
+
raise InvalidSignatureError, 'signature of signedMessage does not match' unless success
|
137
138
|
when 'ECv2'
|
138
139
|
signed_key_signature = ['Google', 'ECv2', @token[:intermediateSigningKey][:signedKey]].map do |str|
|
139
140
|
[str.length].pack('V') + str
|
@@ -141,7 +142,7 @@ module Aliquot
|
|
141
142
|
|
142
143
|
# Check that the intermediate key signed the message
|
143
144
|
pkey = OpenSSL::PKey::EC.new(Base64.strict_decode64(@intermediate_key[:keyValue]))
|
144
|
-
raise InvalidSignatureError, 'signature of signedMessage
|
145
|
+
raise InvalidSignatureError, 'signature of signedMessage does not match' unless pkey.verify(new_digest, message_signature, signed_string_message)
|
145
146
|
|
146
147
|
intermediate_signatures = @token[:intermediateSigningKey][:signatures]
|
147
148
|
|
@@ -152,7 +153,7 @@ module Aliquot
|
|
152
153
|
signed_key_signature
|
153
154
|
)
|
154
155
|
|
155
|
-
raise InvalidSignatureError, 'no valid signature of intermediate key
|
156
|
+
raise InvalidSignatureError, 'no valid signature of intermediate key' unless success
|
156
157
|
end
|
157
158
|
rescue OpenSSL::PKey::PKeyError => e
|
158
159
|
# Catches problems with verifying signature. Can be caused by signature
|
data/lib/aliquot/validator.rb
CHANGED
@@ -9,143 +9,221 @@ module Aliquot
|
|
9
9
|
module Validator
|
10
10
|
# Verified according to:
|
11
11
|
# https://developers.google.com/pay/api/web/guides/resources/payment-data-cryptography#payment-method-token-structure
|
12
|
-
module Predicates
|
13
|
-
include Dry::Logic::Predicates
|
14
|
-
|
15
|
-
CUSTOM_PREDICATE_ERRORS = {
|
16
|
-
base64?: 'must be Base64',
|
17
|
-
pan?: 'must be a pan',
|
18
|
-
ec_public_key?: 'must be an EC public key',
|
19
|
-
eci?: 'must be an ECI',
|
20
|
-
json_string?: 'must be valid JSON',
|
21
|
-
integer_string?: 'must be string encoded integer',
|
22
|
-
month?: 'must be a month (1..12)',
|
23
|
-
year?: 'must be a year (2000..3000)',
|
24
|
-
base64_asn1?: 'must be base64 encoded asn1 value',
|
25
|
-
|
26
|
-
authMethodCryptogram3DS: 'authMethod CRYPTOGRAM_3DS requires eciIndicator',
|
27
|
-
authMethodCard: 'eciIndicator/cryptogram must be omitted when PAN_ONLY',
|
28
|
-
}.freeze
|
29
|
-
|
30
|
-
# Support Ruby 2.3, but use the faster #match? when available.
|
31
|
-
match_b = ''.respond_to?(:match?) ? ->(s, re) { s.match?(re) } : ->(s, re) { !!(s =~ re) }
|
32
|
-
|
33
|
-
def self.to_bool(lbd)
|
34
|
-
lbd.call
|
35
|
-
true
|
36
|
-
rescue
|
37
|
-
false
|
38
|
-
end
|
39
12
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
13
|
+
CUSTOM_ERRORS = {
|
14
|
+
base64?: 'must be Base64',
|
15
|
+
pan?: 'must be a PAN',
|
16
|
+
ec_public_key?: 'must be an EC public key',
|
17
|
+
eci?: 'must be an ECI',
|
18
|
+
integer_string?: 'must be string encoded integer',
|
19
|
+
month?: 'must be a month (1..12)',
|
20
|
+
year?: 'must be a year (2000..3000)',
|
21
|
+
base64_asn1?: 'must be base64-encoded ANS.1 value',
|
22
|
+
json?: 'must be valid JSON',
|
23
|
+
|
24
|
+
is_authMethodCryptogram3DS: 'authMethod CRYPTOGRAM_3DS requires eciIndicator',
|
25
|
+
is_authMethodCard: 'eciIndicator/cryptogram must be omitted when PAN_ONLY',
|
26
|
+
}.freeze
|
27
|
+
|
28
|
+
def self.base64_check(value)
|
29
|
+
/\A[=A-Za-z0-9+\/]*\z/.match?(value) && # allowable chars
|
30
|
+
value.length.remainder(4).zero? && # multiple of 4
|
31
|
+
!/=[^$=]/.match?(value) && # may only end with ='s
|
32
|
+
!/===/.match?(value) # at most 2 ='s
|
33
|
+
end
|
34
|
+
|
35
|
+
Dry::Validation.register_macro(:base64?) do
|
36
|
+
if key?
|
37
|
+
unless Aliquot::Validator.base64_check(value)
|
38
|
+
key.failure(CUSTOM_ERRORS[:base64?])
|
39
|
+
end
|
46
40
|
end
|
41
|
+
end
|
47
42
|
|
48
|
-
|
49
|
-
|
50
|
-
|
43
|
+
def self.ans1_check(value)
|
44
|
+
OpenSSL::ASN1.decode(Base64.strict_decode64(value)) rescue false
|
45
|
+
end
|
51
46
|
|
52
|
-
|
47
|
+
Dry::Validation.register_macro(:base64_asn1?) do
|
48
|
+
if key?
|
49
|
+
unless Aliquot::Validator.ans1_check(value)
|
50
|
+
key.failure(CUSTOM_ERRORS[:base64_asn1?])
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
53
54
|
|
54
|
-
|
55
|
+
Dry::Validation.register_macro(:pan?) do
|
56
|
+
if key?
|
57
|
+
unless /\A[1-9][0-9]{11,18}\z/.match?(value)
|
58
|
+
key.failure(CUSTOM_ERRORS[:pan?])
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
55
62
|
|
56
|
-
|
63
|
+
Dry::Validation.register_macro(:ec_public_key?) do
|
64
|
+
if key?
|
65
|
+
begin
|
66
|
+
OpenSSL::PKey::EC.new(Base64.decode64(value)).check_key
|
67
|
+
rescue
|
68
|
+
key.failure(CUSTOM_ERRORS[:ec_public_key?])
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
57
72
|
|
58
|
-
|
73
|
+
Dry::Validation.register_macro(:eci?) do
|
74
|
+
if key?
|
75
|
+
unless /\A\d{1,2}\z/.match?(value)
|
76
|
+
key.failure(CUSTOM_ERRORS[:eci?])
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
59
80
|
|
60
|
-
|
81
|
+
Dry::Validation.register_macro(:integer_string?) do
|
82
|
+
if key?
|
83
|
+
unless /\A\d+\z/.match?(value)
|
84
|
+
key.failure(CUSTOM_ERRORS[:integer_string?])
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
61
88
|
|
62
|
-
|
89
|
+
Dry::Validation.register_macro(:json?) do
|
90
|
+
if key?
|
91
|
+
json = JSON.parse(value) rescue false
|
92
|
+
key.failure(CUSTOM_ERRORS[:json?]) unless json
|
93
|
+
end
|
94
|
+
end
|
63
95
|
|
64
|
-
|
96
|
+
Dry::Validation.register_macro(:month?) do
|
97
|
+
if key?
|
98
|
+
unless value.between?(1, 12)
|
99
|
+
key.failure(CUSTOM_ERRORS[:month?])
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
65
103
|
|
66
|
-
|
104
|
+
Dry::Validation.register_macro(:year?) do
|
105
|
+
if key?
|
106
|
+
unless value.between?(2000, 3000)
|
107
|
+
key.failure(CUSTOM_ERRORS[:year?])
|
108
|
+
end
|
109
|
+
end
|
67
110
|
end
|
68
111
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
super.merge(en: { errors: Predicates::CUSTOM_PREDICATE_ERRORS })
|
112
|
+
class SignedKeyContract < Dry::Validation::Contract
|
113
|
+
json do
|
114
|
+
required(:keyExpiration).filled(:str?)
|
115
|
+
required(:keyValue).filled(:str?)
|
74
116
|
end
|
117
|
+
rule(:keyExpiration).validate(:integer_string?)
|
118
|
+
rule(:keyValue).validate(:ec_public_key?)
|
75
119
|
end
|
76
120
|
|
77
|
-
|
78
|
-
IntermediateSigningKeySchema = Dry::Validation.Schema(BaseSchema) do
|
79
|
-
required(:signedKey).filled(:str?, :json_string?)
|
121
|
+
SignedKeySchema = SignedKeyContract.new
|
80
122
|
|
81
|
-
|
82
|
-
|
123
|
+
# Schema used for the 'intermediateSigningKey' hash included in ECv2.
|
124
|
+
class IntermediateSigningKeyContract < Dry::Validation::Contract
|
125
|
+
json do
|
126
|
+
required(:signedKey).filled(:str?)
|
127
|
+
required(:signatures).array(:str?)
|
128
|
+
end
|
129
|
+
rule(:signedKey).validate(:json?)
|
130
|
+
rule(:signatures).each do
|
131
|
+
key.failure('must be Base64') unless Aliquot::Validator.base64_check(value) &&
|
132
|
+
Aliquot::Validator.ans1_check(value)
|
133
|
+
end
|
83
134
|
end
|
84
135
|
|
85
|
-
|
86
|
-
required(:keyExpiration).filled(:integer_string?)
|
87
|
-
required(:keyValue).filled(:ec_public_key?)
|
88
|
-
end
|
136
|
+
IntermediateSigningKeySchema = IntermediateSigningKeyContract.new
|
89
137
|
|
90
138
|
# DRY-Validation schema for Google Pay token
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
139
|
+
class TokenContract < Dry::Validation::Contract
|
140
|
+
json do
|
141
|
+
required(:signature).filled(:str?)
|
142
|
+
required(:signedMessage).filled(:str?)
|
143
|
+
required(:protocolVersion).filled(:str?)
|
144
|
+
optional(:intermediateSigningKey).hash(IntermediateSigningKeyContract.new.schema)
|
145
|
+
end
|
146
|
+
rule(:signature).validate(:base64?, :base64_asn1?)
|
147
|
+
rule(:signedMessage).validate(:json?)
|
99
148
|
|
100
|
-
rule(
|
101
|
-
|
149
|
+
rule(:intermediateSigningKey) do
|
150
|
+
key.failure('is missing') if 'ECv2'.eql?(values[:protocolVersion]) &&
|
151
|
+
values[:intermediateSigningKey].nil?
|
102
152
|
end
|
103
153
|
end
|
104
154
|
|
155
|
+
TokenSchema = TokenContract.new
|
156
|
+
|
105
157
|
# DRY-Validation schema for signedMessage component Google Pay token
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
158
|
+
class SignedMessageContract < Dry::Validation::Contract
|
159
|
+
json do
|
160
|
+
required(:encryptedMessage).filled(:str?)
|
161
|
+
required(:ephemeralPublicKey).filled(:str?)
|
162
|
+
required(:tag).filled(:str?)
|
163
|
+
end
|
164
|
+
rule(:encryptedMessage).validate(:base64?)
|
165
|
+
rule(:ephemeralPublicKey).validate(:base64?)
|
166
|
+
rule(:tag).validate(:base64?)
|
110
167
|
end
|
111
168
|
|
112
|
-
|
113
|
-
PaymentMethodDetailsSchema = Dry::Validation.Schema(BaseSchema) do
|
114
|
-
required(:pan).filled(:integer_string?, :pan?)
|
115
|
-
required(:expirationMonth).filled(:int?, :month?)
|
116
|
-
required(:expirationYear).filled(:int?, :year?)
|
117
|
-
required(:authMethod).filled(:str?, included_in?: %w[PAN_ONLY CRYPTOGRAM_3DS])
|
118
|
-
|
119
|
-
optional(:cryptogram).filled(:str?)
|
120
|
-
optional(:eciIndicator).filled(:str?, :eci?)
|
169
|
+
SignedMessageSchema = SignedMessageContract.new
|
121
170
|
|
122
|
-
|
123
|
-
|
171
|
+
# DRY-Validation schema for paymentMethodDetails component Google Pay token
|
172
|
+
class PaymentMethodDetailsContract < Dry::Validation::Contract
|
173
|
+
json do
|
174
|
+
required(:pan).filled(:str?)
|
175
|
+
required(:expirationMonth).filled(:int?)
|
176
|
+
required(:expirationYear).filled(:int?)
|
177
|
+
required(:authMethod).filled(:str?, included_in?: %w[PAN_ONLY CRYPTOGRAM_3DS])
|
178
|
+
|
179
|
+
optional(:cryptogram).filled(:str?)
|
180
|
+
optional(:eciIndicator).filled(:str?)
|
181
|
+
end
|
182
|
+
rule(:pan).validate(:integer_string?, :pan?)
|
183
|
+
rule(:expirationMonth).validate(:month?)
|
184
|
+
rule(:expirationYear).validate(:year?)
|
185
|
+
rule(:eciIndicator).validate(:eci?)
|
186
|
+
|
187
|
+
rule(:cryptogram) do
|
188
|
+
key.failure('is missing') if 'CRYPTOGRAM_3DS'.eql?(values[:authMethod]) &&
|
189
|
+
values[:cryptogram].nil?
|
124
190
|
end
|
125
191
|
|
126
|
-
rule(
|
127
|
-
|
192
|
+
rule(:cryptogram) do
|
193
|
+
key.failure('cannot be defined') if 'PAN_ONLY'.eql?(values[:authMethod]) &&
|
194
|
+
!values[:cryptogram].nil?
|
128
195
|
end
|
129
196
|
|
130
|
-
rule(
|
131
|
-
|
197
|
+
rule(:eciIndicator) do
|
198
|
+
key.failure('cannot be defined') if 'PAN_ONLY'.eql?(values[:authMethod]) &&
|
199
|
+
!values[:eciIndicator].nil?
|
132
200
|
end
|
133
201
|
end
|
134
202
|
|
203
|
+
PaymentMethodDetailsSchema = PaymentMethodDetailsContract.new
|
204
|
+
|
135
205
|
# DRY-Validation schema for encryptedMessage component Google Pay token
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
206
|
+
class EncryptedMessageContract < Dry::Validation::Contract
|
207
|
+
json do
|
208
|
+
required(:messageExpiration).filled(:str?)
|
209
|
+
required(:messageId).filled(:str?)
|
210
|
+
required(:paymentMethod).filled(:str?)
|
211
|
+
required(:paymentMethodDetails).filled(:hash).schema(PaymentMethodDetailsContract.schema)
|
212
|
+
end
|
213
|
+
rule(:messageExpiration).validate(:integer_string?)
|
214
|
+
rule(:paymentMethod) do
|
215
|
+
key.failure('must be equal to CARD') unless 'CARD'.eql?(value)
|
216
|
+
end
|
141
217
|
end
|
142
218
|
|
219
|
+
EncryptedMessageSchema = EncryptedMessageContract.new
|
220
|
+
|
143
221
|
module InstanceMethods
|
144
222
|
attr_reader :output
|
145
223
|
|
146
224
|
def validate
|
147
225
|
@validation ||= @schema.call(@input)
|
148
|
-
@output = @validation.
|
226
|
+
@output = @validation.to_h
|
149
227
|
return true if @validation.success?
|
150
228
|
raise Aliquot::ValidationError, "validation error(s), #{errors_formatted}"
|
151
229
|
end
|
@@ -176,7 +254,9 @@ module Aliquot
|
|
176
254
|
# Class for validating a Google Pay token
|
177
255
|
class Token
|
178
256
|
include InstanceMethods
|
257
|
+
|
179
258
|
class Error < ::Aliquot::Error; end
|
259
|
+
|
180
260
|
def initialize(input)
|
181
261
|
@input = input
|
182
262
|
@schema = TokenSchema
|
@@ -186,7 +266,9 @@ module Aliquot
|
|
186
266
|
# Class for validating the SignedMessage component of a Google Pay token
|
187
267
|
class SignedMessage
|
188
268
|
include InstanceMethods
|
269
|
+
|
189
270
|
class Error < ::Aliquot::Error; end
|
271
|
+
|
190
272
|
def initialize(input)
|
191
273
|
@input = input
|
192
274
|
@schema = SignedMessageSchema
|
@@ -196,7 +278,9 @@ module Aliquot
|
|
196
278
|
# Class for validating the encryptedMessage component of a Google Pay token
|
197
279
|
class EncryptedMessageValidator
|
198
280
|
include InstanceMethods
|
281
|
+
|
199
282
|
class Error < ::Aliquot::Error; end
|
283
|
+
|
200
284
|
def initialize(input)
|
201
285
|
@input = input
|
202
286
|
@schema = EncryptedMessageSchema
|
@@ -205,7 +289,9 @@ module Aliquot
|
|
205
289
|
|
206
290
|
class SignedKeyValidator
|
207
291
|
include InstanceMethods
|
292
|
+
|
208
293
|
class Error < ::Aliquot::Error; end
|
294
|
+
|
209
295
|
def initialize(input)
|
210
296
|
@input = input
|
211
297
|
@schema = SignedKeySchema
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aliquot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Clearhaus
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-09-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dry-validation
|
@@ -16,56 +16,84 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '1.8'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '1.8'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: excon
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 0.71.0
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 0.71.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: hkdf
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
47
|
+
version: '0.3'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
54
|
+
version: '0.3'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: aliquot-pay
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
61
|
+
version: 2.1.1
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
68
|
+
version: 2.1.1
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: bundler
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '2.3'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '2.3'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '13.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '13.0'
|
69
97
|
- !ruby/object:Gem::Dependency
|
70
98
|
name: rspec
|
71
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,6 +108,20 @@ dependencies:
|
|
80
108
|
- - "~>"
|
81
109
|
- !ruby/object:Gem::Version
|
82
110
|
version: '3'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: pry
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
83
125
|
description:
|
84
126
|
email: hello@clearhaus.com
|
85
127
|
executables: []
|
@@ -100,16 +142,16 @@ require_paths:
|
|
100
142
|
- lib
|
101
143
|
required_ruby_version: !ruby/object:Gem::Requirement
|
102
144
|
requirements:
|
103
|
-
- - "
|
145
|
+
- - "~>"
|
104
146
|
- !ruby/object:Gem::Version
|
105
|
-
version: '
|
147
|
+
version: '2.7'
|
106
148
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
149
|
requirements:
|
108
150
|
- - ">="
|
109
151
|
- !ruby/object:Gem::Version
|
110
152
|
version: '0'
|
111
153
|
requirements: []
|
112
|
-
rubygems_version: 3.
|
154
|
+
rubygems_version: 3.1.6
|
113
155
|
signing_key:
|
114
156
|
specification_version: 4
|
115
157
|
summary: Validates Google Pay tokens
|