spree_emerchantpay_genesis 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/README.md +109 -10
  4. data/app/assets/javascripts/spree/frontend/card.min.js +3 -3
  5. data/app/controllers/spree/api/v2/storefront/checkout_controller_decorator.rb +45 -16
  6. data/app/controllers/spree/api/v2/storefront/emerchantpay_notification_controller.rb +5 -3
  7. data/app/helpers/spree/admin/payment_methods_helper.rb +20 -13
  8. data/app/helpers/spree_emerchantpay_genesis/mappers/genesis.rb +51 -163
  9. data/app/helpers/spree_emerchantpay_genesis/mappers/threeds_attributes.rb +227 -0
  10. data/app/helpers/spree_emerchantpay_genesis/payment_method_helper.rb +34 -0
  11. data/app/helpers/spree_emerchantpay_genesis/threeds_helper.rb +2 -1
  12. data/app/helpers/spree_emerchantpay_genesis/transaction_helper.rb +9 -5
  13. data/app/models/spree/emerchantpay_checkout_source.rb +37 -0
  14. data/app/models/spree/gateway/emerchantpay_checkout.rb +52 -0
  15. data/app/models/spree/gateway/emerchantpay_direct.rb +4 -19
  16. data/app/models/spree/payment_decorator.rb +31 -0
  17. data/app/models/spree_emerchantpay_genesis/base/gateway.rb +18 -1
  18. data/app/models/spree_emerchantpay_genesis/genesis_provider.rb +74 -18
  19. data/app/repositories/spree_emerchantpay_genesis/emerchantpay_payments_repository.rb +6 -5
  20. data/app/repositories/spree_emerchantpay_genesis/spree_payments_repository.rb +4 -8
  21. data/app/serializers/spree/api/v2/platform/emerchantpay_checkout_source_serializer.rb +17 -0
  22. data/app/services/spree/payments/create_decorator.rb +13 -1
  23. data/app/services/spree_emerchantpay_genesis/base/payment_service.rb +28 -2
  24. data/app/services/spree_emerchantpay_genesis/sources/create_checkout.rb +40 -0
  25. data/app/views/partials/_gateway_messages.html.erb +21 -0
  26. data/app/views/partials/_transaction_table.html.erb +34 -0
  27. data/app/views/spree/admin/payments/source_views/_emerchantpay_checkout.html.erb +23 -0
  28. data/app/views/spree/admin/payments/source_views/_emerchantpay_direct.html.erb +2 -55
  29. data/app/views/spree/checkout/payment/_emerchantpay_checkout.html.erb +3 -0
  30. data/config/initializers/extend_spree_permitted_checkout_attributes.rb +13 -0
  31. data/config/locales/en.yml +67 -0
  32. data/db/migrate/20240306152438_add_checkout_source.rb +22 -0
  33. data/lib/spree_emerchantpay_genesis/engine.rb +3 -1
  34. data/lib/spree_emerchantpay_genesis/version.rb +1 -1
  35. metadata +18 -6
@@ -5,12 +5,31 @@ module Spree
5
5
  # Decorate Create Payment action
6
6
  module CheckoutControllerDecorator
7
7
 
8
+ def complete
9
+ spree_authorize! :update, spree_current_order, order_token
10
+
11
+ result = complete_service.call(order: spree_current_order)
12
+
13
+ return emerchantpay_checkout_handler if result.success? && emerchantpay_checkout_method?
14
+
15
+ render_order(result)
16
+ end
17
+
18
+ def next
19
+ spree_authorize! :update, spree_current_order, order_token
20
+
21
+ result = next_service.call(order: spree_current_order)
22
+
23
+ return emerchantpay_checkout_handler if result.success? && emerchantpay_checkout_method?
24
+
25
+ render_order(result)
26
+ end
27
+
8
28
  def create_payment
9
29
  result = create_payment_service.call(order: spree_current_order, params: params)
10
30
 
11
31
  if result.success?
12
- return emerchantpay_direct_payment_handler if
13
- result.value.payment_method.type == Spree::Gateway::EmerchantpayDirect.name
32
+ return emerchantpay_direct_payment_handler if emerchantpay_direct_method?
14
33
 
15
34
  render_serialized_payload(201) { serialize_resource(spree_current_order.reload) }
16
35
  else
@@ -22,32 +41,42 @@ module Spree
22
41
 
23
42
  # Handle EmerchantpayDirect Payment Method Create Payment API Call
24
43
  def emerchantpay_direct_payment_handler
25
- return render_error_payload('You must authenticate in order to create Emerchanptpay payment') if
26
- order_token.empty?
27
-
28
44
  spree_authorize! :update, spree_current_order, order_token
29
45
 
30
46
  # Complete the order. This will call the purchase method with source containing credit card number
31
47
  loop { break unless spree_current_order.next }
32
48
 
49
+ return handle_order_state 201 if spree_current_order.completed?
50
+
51
+ render_error_payload(spree_current_order.errors[:base].join('|'))
52
+ end
53
+
54
+ # Handle Emerchantpay Checkout Payment Method Next and Complete API Calls
55
+ def emerchantpay_checkout_handler
33
56
  handle_order_state
34
57
  end
35
58
 
36
- # Generate Spree Response
37
- def handle_order_state
38
- # spree_current_order.payments.last.source
59
+ # Check if the payment is made via emerchantpay direct method
60
+ def emerchantpay_direct_method?
61
+ spree_current_order&.payments &&
62
+ spree_current_order.payments.last.payment_method.type == Spree::Gateway::EmerchantpayDirect.name
63
+ end
64
+
65
+ # Check if the payment is made via emerchantpay checkout method
66
+ def emerchantpay_checkout_method?
67
+ spree_current_order&.completed? && spree_current_order&.payments &&
68
+ spree_current_order.payments.last.payment_method.type == Spree::Gateway::EmerchantpayCheckout.name
69
+ end
39
70
 
40
- if spree_current_order.completed?
41
- return render_serialized_payload(201) do
42
- response = serialize_resource(spree_current_order.reload)
71
+ # Generate Spree Response
72
+ def handle_order_state(status = 200)
73
+ render_serialized_payload(status) do
74
+ response = serialize_resource(spree_current_order.reload)
43
75
 
44
- response[:data].merge!(build_genesis_response_parameters)
76
+ response[:data].merge!(build_genesis_response_parameters)
45
77
 
46
- response
47
- end
78
+ response
48
79
  end
49
-
50
- render_error_payload(spree_current_order.errors[:base].join('|'))
51
80
  end
52
81
 
53
82
  # Build additional response parameters
@@ -24,11 +24,11 @@ module Spree
24
24
 
25
25
  # Validate params
26
26
  def validate_params
27
- params.require [:unique_id, :signature]
27
+ params.require [:signature]
28
28
  end
29
29
 
30
30
  # Permit params
31
- def process_params
31
+ def process_params # rubocop:disable Metrics/MethodLength
32
32
  @permitted_params = params.permit(
33
33
  :transaction_id, :terminal_token, :unique_id, :transaction_type, :status, :signature, :amount,
34
34
  :eci, :cvv_result_code, :retrieval_reference_number, :authorization_code, :scheme_transaction_identifier,
@@ -36,7 +36,9 @@ module Spree
36
36
  :threeds_concrete_protocol_version, :threeds_method_status, :scheme_response_code, :avs_response_code,
37
37
  :avs_response_text, :reference_transaction_unique_id, :threeds_authentication_status_reason_code,
38
38
  :card_brand, :card_number, :card_type, :card_subtype, :card_issuing_bank, :card_holder, :expiration_year,
39
- :expiration_month
39
+ :expiration_month, :wpf_unique_id, :payment_transaction_terminal_token, :payment_transaction_unique_id,
40
+ :payment_transaction_transaction_type, :payment_transaction_amount, :wpf_status, :wpf_transaction_id,
41
+ :notification_type
40
42
  )
41
43
  end
42
44
 
@@ -17,21 +17,16 @@ module Spree
17
17
  label_tag(field, Spree.t(field))
18
18
  form.select(field, { Spree.t(:enabled) => true, Spree.t(:disabled) => false }, {}, class: 'select2')
19
19
  when :select
20
+ add_select_preference(form, field, options, { class: 'select2' })
21
+ when :multi_select
20
22
  label_tag(field, Spree.t(field))
21
- form.select(
22
- field,
23
- options_for_select(
24
- options[:values].map { |key| [I18n.t(key, scope: 'emerchantpay.preferences'), key] }, options[:selected]
25
- ),
26
- {},
27
- class: 'select2'
28
- )
23
+ add_select_preference(form, field, options, { class: 'select2', multiple: true })
29
24
  else
30
25
  form.text_field(field, preference_field_options(options))
31
26
  end
32
27
  end
33
28
 
34
- def preference_field_tag(name, value, options) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
29
+ def preference_field_tag(name, value, options) # rubocop:disable Metrics/MethodLength
35
30
  case options[:type]
36
31
  when :integer, :string
37
32
  text_field_tag(name, value, preference_field_options(options))
@@ -42,9 +37,7 @@ module Spree
42
37
  password_field_tag(name, value, preference_field_options(options))
43
38
  when :text
44
39
  text_area_tag(name, value, preference_field_options(options))
45
- when :boolean_select
46
- select_tag(name, value, preference_field_options(options))
47
- when :select
40
+ when :boolean_select, :select
48
41
  select_tag(name, value, preference_field_options(options))
49
42
  else
50
43
  text_field_tag(name, value, preference_field_options(options))
@@ -95,9 +88,23 @@ module Spree
95
88
  end
96
89
  end
97
90
 
91
+ def add_select_preference(form, field, options, html_options)
92
+ form.select(
93
+ field,
94
+ options_for_select(
95
+ options[:values].map { |key| [I18n.t(key, scope: 'emerchantpay.preferences'), key] }, options[:selected]
96
+ ),
97
+ {},
98
+ html_options
99
+ )
100
+ end
101
+
98
102
  def default_preference_support?(object, preference)
99
103
  unsupported_default_preferences.include?(preference.to_s) &&
100
- object.instance_of?(Spree::Gateway::EmerchantpayDirect)
104
+ (
105
+ object.instance_of?(Spree::Gateway::EmerchantpayDirect) ||
106
+ object.instance_of?(Spree::Gateway::EmerchantpayCheckout)
107
+ )
101
108
  end
102
109
 
103
110
  # Not Supported preferences from Emerchantpay Gateway
@@ -39,10 +39,18 @@ module SpreeEmerchantpayGenesis
39
39
  this.map_method_continue emerchantpay_payment
40
40
  end
41
41
 
42
+ def self.for_wpf(genesis, order, source, options)
43
+ this = new genesis
44
+
45
+ this.map_wpf order, source, options
46
+ end
47
+
42
48
  # Replace URL patterns
43
49
  def self.for_urls!(options, order_number)
44
50
  options[:return_success_url]&.sub! ORDER_REPLACE_PATTERN, order_number
45
51
  options[:return_failure_url]&.sub! ORDER_REPLACE_PATTERN, order_number
52
+ options[:return_cancel_url]&.sub! ORDER_REPLACE_PATTERN, order_number
53
+ options[:return_pending_url]&.sub! ORDER_REPLACE_PATTERN, order_number
46
54
 
47
55
  options
48
56
  end
@@ -57,14 +65,30 @@ module SpreeEmerchantpayGenesis
57
65
  credit_card_attributes source
58
66
  billing_attributes order
59
67
  shipping_attributes order
60
- if TransactionHelper.asyn? @context
61
- asyn_attributes options
62
- threeds_attributes order, source, options if ActiveModel::Type::Boolean.new.cast options[:threeds_allowed]
68
+ asyn_attributes options if TransactionHelper.asyn? @context
69
+
70
+ if TransactionHelper.asyn?(@context) && ActiveModel::Type::Boolean.new.cast(options[:threeds_allowed])
71
+ threeds_processing_attributes order, source, options
63
72
  end
64
73
 
65
74
  self
66
75
  end
67
76
 
77
+ # Map WPF request
78
+ def map_wpf(order, _source, options)
79
+ common_attributes order, support_ip: false
80
+ billing_attributes order
81
+ shipping_attributes order
82
+ asyn_attributes options
83
+ transaction_types_attributes options
84
+ threeds_wpf_attributes order, options if ActiveModel::Type::Boolean.new.cast options[:threeds_allowed]
85
+
86
+ @context.return_cancel_url = options[:return_cancel_url]
87
+ @context.return_pending_url = options[:return_pending_url]
88
+
89
+ self
90
+ end
91
+
68
92
  # Map Reference transaction
69
93
  def map_reference(amount, transaction, order)
70
94
  @context.transaction_id = TransactionHelper.generate_transaction_id
@@ -82,7 +106,7 @@ module SpreeEmerchantpayGenesis
82
106
  def map_config(options)
83
107
  @context.username = options[:username]
84
108
  @context.password = options[:password]
85
- @context.token = options[:token]
109
+ @context.token = options[:token] || nil
86
110
  @context.environment = fetch_genesis_environment ActiveModel::Type::Boolean.new.cast(options[:test_mode])
87
111
  @context.endpoint = GenesisRuby::Api::Constants::Endpoints::EMERCHANTPAY
88
112
 
@@ -101,14 +125,16 @@ module SpreeEmerchantpayGenesis
101
125
  private
102
126
 
103
127
  # Common Genesis Attributes
104
- def common_attributes(provider) # rubocop:disable Metrics/AbcSize
128
+ def common_attributes(provider, support_ip: true) # rubocop:disable Metrics/AbcSize
105
129
  @context.transaction_id = TransactionHelper.generate_transaction_id
106
130
  @context.amount = provider.total.to_s
107
131
  @context.currency = provider.currency
108
132
  @context.usage = I18n.t 'usage', scope: 'emerchantpay.payment'
109
133
  @context.customer_email = provider.email
110
134
  @context.customer_phone = provider.billing_address&.phone
111
- @context.remote_ip = provider.ip
135
+ @context.remote_ip = provider.ip if support_ip
136
+
137
+ nil
112
138
  end
113
139
 
114
140
  # Credit Card Attributes
@@ -118,6 +144,8 @@ module SpreeEmerchantpayGenesis
118
144
  @context.expiration_month = source.month
119
145
  @context.expiration_year = source.year
120
146
  @context.cvv = source.verification_value
147
+
148
+ nil
121
149
  end
122
150
 
123
151
  # Billing Attributes
@@ -132,6 +160,8 @@ module SpreeEmerchantpayGenesis
132
160
  @context.billing_city = provider.billing_address.city
133
161
  @context.billing_state = provider.billing_address.state
134
162
  @context.billing_country = provider.billing_address.country
163
+
164
+ nil
135
165
  end
136
166
 
137
167
  # Shipping Attributes
@@ -146,12 +176,17 @@ module SpreeEmerchantpayGenesis
146
176
  @context.shipping_city = provider.shipping_address.city
147
177
  @context.shipping_state = provider.shipping_address.state
148
178
  @context.shipping_country = provider.shipping_address.country
179
+
180
+ nil
149
181
  end
150
182
 
183
+ # Asynchronous attributes
151
184
  def asyn_attributes(options)
152
185
  @context.notification_url = "#{options[:hostname]}#{api_v2_storefront_emerchantpay_notification_path}"
153
186
  @context.return_success_url = options[:return_success_url]
154
187
  @context.return_failure_url = options[:return_failure_url]
188
+
189
+ nil
155
190
  end
156
191
 
157
192
  # Fetch Genesis Environments
@@ -163,168 +198,21 @@ module SpreeEmerchantpayGenesis
163
198
  end
164
199
  end
165
200
 
166
- # 3DSv2 attributes
167
- def threeds_attributes(order, source, options) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
168
- user_orders = []
169
- @context.threeds_v2_purchase_category = fetch_threeds_category order
170
- @context.threeds_v2_method_callback_url =
171
- "#{options[:hostname]}#{api_v2_storefront_emerchantpay_threeds_callback_handler_path}"
172
- threeds_control_attributes options
173
- @context.threeds_v2_merchant_risk_shipping_indicator = fetch_shipping_indicator order
174
- @context.threeds_v2_merchant_risk_delivery_timeframe = fetch_delivery_timeframe order
175
- threeds_browser_attributes source
176
-
177
- user_orders = SpreeOrderRepository.orders_by_user order.user_id if order.user_id
178
- @context.threeds_v2_merchant_risk_reorder_items_indicator = fetch_reorder_items_indicator order, user_orders
179
-
180
- if order.user.empty?
181
- @context.threeds_v2_card_holder_account_registration_indicator = GenesisRuby::Api::Constants::Transactions::
182
- Parameters::Threeds::Version2::CardHolderAccount::RegistrationIndicators::GUEST_CHECKOUT
183
- end
184
-
185
- threeds_card_holder_attributes order, user_orders unless order.user.empty?
186
- end
187
-
188
- # 3DSv2 Control attributes
189
- def threeds_control_attributes(options)
190
- @context.threeds_v2_control_device_type = GenesisRuby::Api::Constants::Transactions::Parameters::
191
- Threeds::Version2::Control::DeviceTypes::BROWSER
192
- @context.threeds_v2_control_challenge_window_size =
193
- GenesisRuby::Api::Constants::Transactions::Parameters::Threeds::Version2::Control::ChallengeWindowSizes::
194
- FULLSCREEN
195
- @context.threeds_v2_control_challenge_indicator = options[:challenge_indicator]
196
- end
197
-
198
- # 3DSv2 Browser attributes
199
- def threeds_browser_attributes(source) # rubocop:disable Metrics/AbcSize
200
- @context.threeds_v2_browser_accept_header = source.public_metadata[:accept_header]
201
- @context.threeds_v2_browser_java_enabled = ActiveModel::Type::Boolean.new.cast(
202
- source.public_metadata[:java_enabled]
203
- )
204
- @context.threeds_v2_browser_language = source.public_metadata[:language]
205
- @context.threeds_v2_browser_color_depth = source.public_metadata[:color_depth]
206
- @context.threeds_v2_browser_screen_height = source.public_metadata[:screen_height]
207
- @context.threeds_v2_browser_screen_width = source.public_metadata[:screen_width]
208
- @context.threeds_v2_browser_time_zone_offset = source.public_metadata[:time_zone_offset]
209
- @context.threeds_v2_browser_user_agent = source.public_metadata[:user_agent]
210
- end
211
-
212
- # Fetch 3DSv2 Purchase Category
213
- def fetch_threeds_category(order)
214
- if order.digital
215
- return GenesisRuby::Api::Constants::Transactions::Parameters::Threeds::Version2::Purchase::Categories::SERVICE
216
- end
217
-
218
- GenesisRuby::Api::Constants::Transactions::Parameters::Threeds::Version2::Purchase::Categories::GOODS
219
- end
220
-
221
- # Fetch 3DSv2 Merchant Risk Shipping Indicator
222
- def fetch_shipping_indicator(order) # rubocop:disable Metrics/MethodLength
223
- if order.digital
224
- return GenesisRuby::Api::Constants::Transactions::Parameters::Threeds::Version2::MerchantRisk::
225
- ShippingIndicators::DIGITAL_GOODS
226
- end
227
-
228
- if order.shipping_address&.to_s == order.billing_address&.to_s
229
- return GenesisRuby::Api::Constants::Transactions::Parameters::Threeds::Version2::MerchantRisk::
230
- ShippingIndicators::SAME_AS_BILLING
231
- end
232
-
233
- if order.user_id
234
- return GenesisRuby::Api::Constants::Transactions::Parameters::Threeds::Version2::MerchantRisk::
235
- ShippingIndicators::STORED_ADDRESS
236
- end
237
-
238
- GenesisRuby::Api::Constants::Transactions::Parameters::Threeds::Version2::MerchantRisk::
239
- ShippingIndicators::OTHER
201
+ # 3DSv2 Processing attributes
202
+ def threeds_processing_attributes(order, source, options)
203
+ ThreedsAttributes.for_payment @context, order, source, options
240
204
  end
241
205
 
242
- # Fetch 3DSv2 Merchant Risk Delivery Timeframe
243
- def fetch_delivery_timeframe(order)
244
- if order.digital
245
- return GenesisRuby::Api::Constants::Transactions::Parameters::Threeds::Version2::MerchantRisk::
246
- DeliveryTimeframes::ELECTRONICS
247
- end
248
-
249
- GenesisRuby::Api::Constants::Transactions::Parameters::Threeds::Version2::MerchantRisk::DeliveryTimeframes::
250
- ANOTHER_DAY
206
+ # 3DSv2 WPF attributes
207
+ def threeds_wpf_attributes(order, options)
208
+ ThreedsAttributes.for_wpf @context, order, options
251
209
  end
252
210
 
253
- # Fetch 3DSv2 Merchant Risk Reorder Items Indicator
254
- def fetch_reorder_items_indicator(order, user_orders) # rubocop:disable Metrics/MethodLength
255
- unless order.user_id
256
- return GenesisRuby::Api::Constants::Transactions::Parameters::Threeds::Version2::MerchantRisk::
257
- ReorderItemIndicators::FIRST_TIME
211
+ # Map WPF Transaction Types
212
+ def transaction_types_attributes(options)
213
+ options[:transaction_types].each do |type|
214
+ @context.add_transaction_type type unless type.empty?
258
215
  end
259
-
260
- variants = []
261
- order.line_items.each { |line_item| variants.push line_item[:variant_id] }
262
-
263
- reordered = SpreeEmerchantpayGenesis::SpreeOrderRepository.reordered_variant? order.id, variants, user_orders
264
-
265
- if reordered
266
- return GenesisRuby::Api::Constants::Transactions::Parameters::Threeds::Version2::MerchantRisk::
267
- ReorderItemIndicators::REORDERED
268
- end
269
-
270
- GenesisRuby::Api::Constants::Transactions::Parameters::Threeds::Version2::MerchantRisk::
271
- ReorderItemIndicators::FIRST_TIME
272
- end
273
-
274
- # 3DSv2 Card Holder Account attributes
275
- def threeds_card_holder_attributes(order, user_orders) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
276
- @context.threeds_v2_card_holder_account_creation_date = order.user.created_at_formatted
277
-
278
- # Card Holder last changes with the 3DS requester
279
- card_holder_updated_at = ThreedsHelper.fetch_last_change_date(
280
- order.user.billing_address, order.user.shipping_address
281
- )
282
- @context.threeds_v2_card_holder_account_update_indicator = ThreedsHelper.fetch_class_indicator(
283
- 'UpdateIndicators', card_holder_updated_at
284
- )
285
- @context.threeds_v2_card_holder_account_last_change_date = card_holder_updated_at
286
-
287
- # Card Holder Password changes
288
- @context.threeds_v2_card_holder_account_password_change_indicator = ThreedsHelper.fetch_class_indicator(
289
- 'PasswordChangeIndicators', order.user.updated_at_formatted
290
- )
291
- @context.threeds_v2_card_holder_account_password_change_date = order.user.updated_at_formatted
292
-
293
- # Card Holder Shipping Address first time used
294
- shipping_address_first_used = ThreedsHelper.fetch_shipping_address_first_used(order.user.shipping_address)
295
- @context.threeds_v2_card_holder_account_shipping_address_usage_indicator = ThreedsHelper.fetch_class_indicator(
296
- 'ShippingAddressUsageIndicators', shipping_address_first_used
297
- )
298
- @context.threeds_v2_card_holder_account_shipping_address_date_first_used = shipping_address_first_used
299
-
300
- # Card Holder Payments count
301
- activity_last24_hours = ThreedsHelper.filter_transaction_activity_24_hours user_orders
302
- if activity_last24_hours.positive?
303
- @context.threeds_v2_card_holder_account_transactions_activity_last24_hours = activity_last24_hours
304
- end
305
-
306
- previous_year_count = ThreedsHelper.filter_transaction_activity_previous_year user_orders
307
- if previous_year_count.positive?
308
- @context.threeds_v2_card_holder_account_transactions_activity_previous_year = previous_year_count
309
- end
310
-
311
- purchases_last6_months = SpreeEmerchantpayGenesis::ThreedsHelper.filter_purchases_count_last6_months user_orders
312
- if purchases_last6_months.positive?
313
- @context.threeds_v2_card_holder_account_purchases_count_last6_months = purchases_last6_months
314
- end
315
-
316
- # Card Holder registration with the 3D requester
317
- first_completed_payment = ThreedsHelper.filter_first_completed_payment user_orders
318
- unless first_completed_payment.empty?
319
- string_date = DateTime.parse(first_completed_payment['payment_created_at'].to_s)
320
- .strftime(ThreedsHelper::DATE_ISO_FORMAT)
321
- @context.threeds_v2_card_holder_account_registration_indicator = ThreedsHelper.fetch_class_indicator(
322
- 'RegistrationIndicators', string_date
323
- )
324
- @context.threeds_v2_card_holder_account_registration_date = string_date
325
- end
326
-
327
- nil
328
216
  end
329
217
 
330
218
  end