aliquot 2.3.1 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e752bf7cf311e4fe611e3c868ed08510c54d9e1b05b327d5dfa390b3eeb8cee7
4
- data.tar.gz: 5c7df397cabccc5009c712546838c67329f4e2c835935ba56e62f71b6c368920
3
+ metadata.gz: f8e2a9a7e324874ed68aeaacd8a072ea00dedfce4e6022494f7333c94b55ec1d
4
+ data.tar.gz: 5bfc71f786436d227100470dc37a0d8715196b59d474d0b39b6dd3afa730ff61
5
5
  SHA512:
6
- metadata.gz: 648c2bb459b2a09b602c13dab8c8221fc726c886e047789c84ebf51d1436a3f5fece61255905744cf817dcf114d9833f3f0281d5c7ed18a6eb1c44a60b770521
7
- data.tar.gz: eb060ab6212f664bf3545a306dee4eaac7f63a6388921faf70cc28393e7bc606731d408edb3224ce737c3bc9ef8be8efa16942df717e157a1f3e0f746ad467f6
6
+ metadata.gz: c95f8f7f99e9bbb9dfa7685927521e135b480e8a9e098c265771d592e1ebbd9c16e75be9b11b03cb369d0290e6fbb5c860be7cfad2252543b84950448011e13b
7
+ data.tar.gz: 9983ede008609ae095ce8dc863e361c7f3c46e449efe59c7d0422331284b9e18ec8b1182d14da9a71b5361266435c68d6fb125750165968d82ea755365ec9ff3
@@ -66,6 +66,9 @@ module Aliquot
66
66
 
67
67
  begin
68
68
  @message = JSON.parse(decrypt(aes_key, @signed_message[:encryptedMessage]))
69
+ @message['paymentMethodDetails'].merge!(
70
+ 'threedsCryptogram' => @message['paymentMethodDetails']
71
+ .delete('3dsCryptogram')) if @message['paymentMethodDetails']['3dsCryptogram']
69
72
  rescue JSON::JSONError => e
70
73
  raise InputError, "encryptedMessage JSON is invalid, #{e.message}"
71
74
  rescue => e
@@ -221,7 +224,20 @@ module Aliquot
221
224
  validator.validate
222
225
 
223
226
  # Output is hashed with symbolized keys.
224
- validator.output
227
+ message_hash = validator.output
228
+
229
+ payment_method_details_message = message_hash[:paymentMethodDetails]
230
+ message_details_validator =
231
+ if message_hash[:paymentMethod] == 'TOKENIZED_CARD' ||
232
+ message_hash[:paymentMethodDetails]['authMethod'] == 'CRYPTOGRAM_3DS'
233
+ Aliquot::Validator::PaymentMethodDetailsValidator.new(payment_method_details_message, protocol_version, true)
234
+ else
235
+ Aliquot::Validator::PaymentMethodDetailsValidator.new(payment_method_details_message, protocol_version, false)
236
+ end
237
+ message_details_validator.validate
238
+ message_hash[:paymentMethodDetails] = message_details_validator.output
239
+
240
+ message_hash
225
241
  end
226
242
 
227
243
  ##
@@ -21,8 +21,8 @@ module Aliquot
21
21
  base64_asn1?: 'must be base64-encoded ANS.1 value',
22
22
  json?: 'must be valid JSON',
23
23
 
24
- is_authMethodCryptogram3DS: 'authMethod CRYPTOGRAM_3DS requires eciIndicator',
25
- is_authMethodCard: 'eciIndicator/cryptogram must be omitted when PAN_ONLY',
24
+ is_authMethodCryptogram3DS: 'authMethod CRYPTOGRAM_3DS or 3DS requires eciIndicator',
25
+ is_authMethodCard: 'eciIndicator/cryptogram/3dsCryptogram must be omitted when PAN_ONLY',
26
26
  }.freeze
27
27
 
28
28
  def self.base64_check(value)
@@ -118,8 +118,6 @@ module Aliquot
118
118
  rule(:keyValue).validate(:ec_public_key?)
119
119
  end
120
120
 
121
- SignedKeySchema = SignedKeyContract.new
122
-
123
121
  # Schema used for the 'intermediateSigningKey' hash included in ECv2.
124
122
  class IntermediateSigningKeyContract < Dry::Validation::Contract
125
123
  json do
@@ -129,12 +127,10 @@ module Aliquot
129
127
  rule(:signedKey).validate(:json?)
130
128
  rule(:signatures).each do
131
129
  key.failure('must be Base64') unless Aliquot::Validator.base64_check(value) &&
132
- Aliquot::Validator.ans1_check(value)
130
+ Aliquot::Validator.ans1_check(value)
133
131
  end
134
132
  end
135
133
 
136
- IntermediateSigningKeySchema = IntermediateSigningKeyContract.new
137
-
138
134
  # DRY-Validation schema for Google Pay token
139
135
  class TokenContract < Dry::Validation::Contract
140
136
  json do
@@ -147,13 +143,11 @@ module Aliquot
147
143
  rule(:signedMessage).validate(:json?)
148
144
 
149
145
  rule(:intermediateSigningKey) do
150
- key.failure('is missing') if 'ECv2'.eql?(values[:protocolVersion]) &&
151
- values[:intermediateSigningKey].nil?
146
+ key.failure('is missing') if values[:protocolVersion] == 'ECv2' &&
147
+ values[:intermediateSigningKey].nil?
152
148
  end
153
149
  end
154
150
 
155
- TokenSchema = TokenContract.new
156
-
157
151
  # DRY-Validation schema for signedMessage component Google Pay token
158
152
  class SignedMessageContract < Dry::Validation::Contract
159
153
  json do
@@ -166,41 +160,55 @@ module Aliquot
166
160
  rule(:tag).validate(:base64?)
167
161
  end
168
162
 
169
- SignedMessageSchema = SignedMessageContract.new
170
-
171
- # DRY-Validation schema for paymentMethodDetails component Google Pay token
172
- class PaymentMethodDetailsContract < Dry::Validation::Contract
163
+ class CommonPaymentMethodDetailsContract < Dry::Validation::Contract
173
164
  json do
174
- required(:pan).filled(:str?)
175
165
  required(:expirationMonth).filled(:int?)
176
166
  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
167
  end
182
- rule(:pan).validate(:integer_string?, :pan?)
183
168
  rule(:expirationMonth).validate(:month?)
184
169
  rule(:expirationYear).validate(:year?)
185
- rule(:eciIndicator).validate(:eci?)
170
+ end
186
171
 
187
- rule(:cryptogram) do
188
- key.failure('is missing') if 'CRYPTOGRAM_3DS'.eql?(values[:authMethod]) &&
189
- values[:cryptogram].nil?
172
+ class ECv1_PaymentMethodDetailsContract < CommonPaymentMethodDetailsContract
173
+ json(CommonPaymentMethodDetailsContract.schema) do
174
+ required(:pan).filled(:str?)
190
175
  end
191
176
 
192
- rule(:cryptogram) do
193
- key.failure('cannot be defined') if 'PAN_ONLY'.eql?(values[:authMethod]) &&
194
- !values[:cryptogram].nil?
177
+ rule(:pan).validate(:integer_string?, :pan?)
178
+ end
179
+
180
+ class ECv1_TokenizedPaymentMethodDetailsContract < CommonPaymentMethodDetailsContract
181
+ json(CommonPaymentMethodDetailsContract.schema) do
182
+ required(:dpan).filled(:str?)
183
+ required(:threedsCryptogram).filled(:str?)
184
+ required(:eciIndicator).filled(:str?)
185
+ required(:authMethod).filled(:str?, included_in?: %w[3DS])
195
186
  end
196
187
 
197
- rule(:eciIndicator) do
198
- key.failure('cannot be defined') if 'PAN_ONLY'.eql?(values[:authMethod]) &&
199
- !values[:eciIndicator].nil?
188
+ rule(:dpan).validate(:integer_string?, :pan?)
189
+ rule(:eciIndicator).validate(:eci?)
190
+ end
191
+
192
+ class ECv2_PaymentMethodDetailsContract < CommonPaymentMethodDetailsContract
193
+ json(CommonPaymentMethodDetailsContract.schema) do
194
+ required(:pan).filled(:str?)
195
+ required(:authMethod).filled(:str?, included_in?: %w[PAN_ONLY])
200
196
  end
197
+
198
+ rule(:pan).validate(:integer_string?, :pan?)
201
199
  end
202
200
 
203
- PaymentMethodDetailsSchema = PaymentMethodDetailsContract.new
201
+ class ECv2_TokenizedPaymentMethodDetailsContract < CommonPaymentMethodDetailsContract
202
+ json(CommonPaymentMethodDetailsContract.schema) do
203
+ required(:pan).filled(:str?)
204
+ required(:cryptogram).filled(:str?)
205
+ required(:eciIndicator).filled(:str?)
206
+ required(:authMethod).filled(:str?, included_in?: %w[CRYPTOGRAM_3DS])
207
+ end
208
+
209
+ rule(:pan).validate(:integer_string?, :pan?)
210
+ rule(:eciIndicator).validate(:eci?)
211
+ end
204
212
 
205
213
  # DRY-Validation schema for encryptedMessage component Google Pay token
206
214
  class EncryptedMessageContract < Dry::Validation::Contract
@@ -208,17 +216,40 @@ module Aliquot
208
216
  required(:messageExpiration).filled(:str?)
209
217
  required(:messageId).filled(:str?)
210
218
  required(:paymentMethod).filled(:str?)
211
- required(:paymentMethodDetails).filled(:hash).schema(PaymentMethodDetailsContract.schema)
219
+ required(:paymentMethodDetails).filled(:hash)
212
220
  optional(:gatewayMerchantId).filled(:str?)
213
221
  end
214
222
  rule(:messageExpiration).validate(:integer_string?)
223
+
224
+ rule(:paymentMethodDetails).validate do
225
+ contract =
226
+ if values[:protocolVersion] == 'ECv1'
227
+ if values[:paymentMethod] == 'TOKENIZED_CARD'
228
+ ECv1_TokenizedPaymentMethodDetailsContract.new
229
+ else
230
+ ECv1_PaymentMethodDetailsContract.new
231
+ end
232
+ else
233
+ if values[:authMethod] == 'CRYPTOGRAM_3DS'
234
+ ECv2_TokenizedPaymentMethodDetailsContract.new
235
+ else
236
+ ECv2_PaymentMethodDetailsContract.new
237
+ end
238
+ end
239
+ contract.call(values[:paymentMethodDetails])
240
+ end
241
+
215
242
  rule(:paymentMethod) do
216
- key.failure('must be equal to CARD') unless 'CARD'.eql?(value)
243
+ if values[:paymentMethodDetails].is_a?(Hash)
244
+ if '3DS'.eql?(values[:paymentMethodDetails]['authMethod']) # Tokenized ECv1
245
+ key.failure('must be equal to TOKENIZED_CARD') unless value == 'TOKENIZED_CARD'
246
+ else
247
+ key.failure('must be equal to CARD') unless value == 'CARD'
248
+ end
249
+ end
217
250
  end
218
251
  end
219
252
 
220
- EncryptedMessageSchema = EncryptedMessageContract.new
221
-
222
253
  module InstanceMethods
223
254
  attr_reader :output
224
255
 
@@ -259,7 +290,7 @@ module Aliquot
259
290
 
260
291
  def initialize(input)
261
292
  @input = input
262
- @schema = TokenSchema
293
+ @schema = TokenContract.new
263
294
  end
264
295
  end
265
296
 
@@ -271,7 +302,7 @@ module Aliquot
271
302
 
272
303
  def initialize(input)
273
304
  @input = input
274
- @schema = SignedMessageSchema
305
+ @schema = SignedMessageContract.new
275
306
  end
276
307
  end
277
308
 
@@ -283,7 +314,32 @@ module Aliquot
283
314
 
284
315
  def initialize(input)
285
316
  @input = input
286
- @schema = EncryptedMessageSchema
317
+ @schema = EncryptedMessageContract.new
318
+ end
319
+ end
320
+
321
+ # Class for validating the encryptedMessage component of a Google Pay token
322
+ class PaymentMethodDetailsValidator
323
+ include InstanceMethods
324
+
325
+ class Error < ::Aliquot::Error; end
326
+
327
+ def initialize(input, version, tokenized)
328
+ @input = input
329
+ @schema =
330
+ if version == 'ECv1'
331
+ if tokenized
332
+ Aliquot::Validator::ECv1_TokenizedPaymentMethodDetailsContract.new
333
+ else
334
+ Aliquot::Validator::ECv1_PaymentMethodDetailsContract.new
335
+ end
336
+ else
337
+ if tokenized
338
+ Aliquot::Validator::ECv2_TokenizedPaymentMethodDetailsContract.new
339
+ else
340
+ Aliquot::Validator::ECv2_PaymentMethodDetailsContract.new
341
+ end
342
+ end
287
343
  end
288
344
  end
289
345
 
@@ -294,7 +350,7 @@ module Aliquot
294
350
 
295
351
  def initialize(input)
296
352
  @input = input
297
- @schema = SignedKeySchema
353
+ @schema = SignedKeyContract.new
298
354
  end
299
355
  end
300
356
  end
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: 2.3.1
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Clearhaus
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-09-29 00:00:00.000000000 Z
11
+ date: 2024-02-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dry-validation
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '3.0'
61
+ version: '4.0'
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: '3.0'
68
+ version: '4.0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -94,7 +94,7 @@ dependencies:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: 0.14.1
97
- description:
97
+ description:
98
98
  email: hello@clearhaus.com
99
99
  executables: []
100
100
  extensions: []
@@ -108,7 +108,7 @@ homepage: https://github.com/clearhaus/aliquot
108
108
  licenses:
109
109
  - MIT
110
110
  metadata: {}
111
- post_install_message:
111
+ post_install_message:
112
112
  rdoc_options: []
113
113
  require_paths:
114
114
  - lib
@@ -123,8 +123,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
125
  requirements: []
126
- rubygems_version: 3.3.5
127
- signing_key:
126
+ rubygems_version: 3.1.6
127
+ signing_key:
128
128
  specification_version: 4
129
129
  summary: Validates Google Pay tokens
130
130
  test_files: []