Class: Spree::Payment

Inherits:
Object
  • Object
show all
Extended by:
DisplayMoney
Includes:
Metadata, Metafields, NumberAsParam, NumberIdentifier, CustomEvents, Processing, Webhooks, Security::Payments
Defined in:
app/models/spree/payment.rb,
app/models/spree/payment/webhooks.rb,
app/models/spree/payment/processing.rb,
app/models/spree/payment/custom_events.rb,
app/models/spree/payment/gateway_options.rb

Defined Under Namespace

Modules: CustomEvents, Processing, Webhooks Classes: GatewayOptions

Constant Summary collapse

NON_RISKY_AVS_CODES =
['B', 'D', 'H', 'J', 'M', 'Q', 'T', 'V', 'X', 'Y'].freeze
RISKY_AVS_CODES =
['A', 'C', 'E', 'F', 'G', 'I', 'K', 'L', 'N', 'O', 'P', 'R', 'S', 'U', 'W', 'Z'].freeze
INVALID_STATES =
%w(failed invalid void).freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from DisplayMoney

money_methods

Methods included from Webhooks

#send_payment_completed_webhook, #send_payment_voided_webhook

Methods included from Processing

#authorize!, #cancel!, #capture!, #confirm!, #gateway_options, #process!, #purchase!, #void_transaction!

Instance Attribute Details

#capture_on_dispatchObject

Returns the value of attribute capture_on_dispatch.



56
57
58
# File 'app/models/spree/payment.rb', line 56

def capture_on_dispatch
  @capture_on_dispatch
end

#request_envObject

Returns the value of attribute request_env.



56
57
58
# File 'app/models/spree/payment.rb', line 56

def request_env
  @request_env
end

#source_attributesObject

Returns the value of attribute source_attributes.



56
57
58
# File 'app/models/spree/payment.rb', line 56

def source_attributes
  @source_attributes
end

Instance Method Details

#actionsObject



207
208
209
210
211
# File 'app/models/spree/payment.rb', line 207

def actions
  return [] unless payment_source&.respond_to?(:actions)

  payment_source.actions.select { |action| !payment_source.respond_to?("can_#{action}?") || payment_source.send("can_#{action}?", self) }
end

#add_gateway_processing_error(error_message) ⇒ Object



261
262
263
264
265
266
267
268
269
270
# File 'app/models/spree/payment.rb', line 261

def add_gateway_processing_error(error_message)
  if has_metafield?('gateway.processing_errors')
    errors = JSON.parse(get_metafield('gateway.processing_errors').value)
    errors << { message: error_message }

    set_metafield('gateway.processing_errors', errors.to_json)
  else
    set_metafield('gateway.processing_errors', [{ message: error_message }].to_json)
  end
end

#amount=(amount) ⇒ Object



159
160
161
162
163
164
165
166
167
# File 'app/models/spree/payment.rb', line 159

def amount=(amount)
  self[:amount] =
    case amount
    when String
      separator = I18n.t('number.currency.format.separator')
      number    = amount.delete("^0-9-#{separator}\.").tr(separator, '.')
      number.to_d if number.present?
    end || amount
end

#build_sourceObject



187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'app/models/spree/payment.rb', line 187

def build_source
  return unless new_record?

  if source_attributes.present? && source.blank? && payment_method.try(:payment_source_class)
    self.source = if source_attributes[:id].present? && source_attributes[:id] != :new
                    payment_method.payment_source_class.find(source_attributes[:id])
                  else
                    payment_method.payment_source_class.new(source_attributes)
                  end

    if source.user_id.present? && source.user_id != order.user_id
      self.source = nil
      return
    end

    source.payment_method_id = payment_method.id if source.respond_to?(:payment_method_id)
    source.user_id = order.user_id if order
  end
end

#can_be_deleted?Boolean

we shouldn’t allow deleting payments via admin interface

Returns:



182
183
184
# File 'app/models/spree/payment.rb', line 182

def can_be_deleted?
  false
end

#can_credit?Boolean

Returns:



177
178
179
# File 'app/models/spree/payment.rb', line 177

def can_credit?
  credit_allowed > 0
end

#captured_amountObject



236
237
238
# File 'app/models/spree/payment.rb', line 236

def captured_amount
  capture_events.sum(:amount)
end

#credit_allowedObject



173
174
175
# File 'app/models/spree/payment.rb', line 173

def credit_allowed
  amount - (offsets_total.abs + refunds.sum(:amount))
end

#display_source_nameObject



248
249
250
251
252
253
# File 'app/models/spree/payment.rb', line 248

def display_source_name
  return if source.blank?

  source_class = source.class
  source_class.respond_to?(:display_name) ? source_class.display_name : source_class.name.demodulize.split(/(?=[A-Z])/).join(' ')
end

#editable?Boolean

Returns:



244
245
246
# File 'app/models/spree/payment.rb', line 244

def editable?
  checkout? || pending?
end

#gateway_dashboard_payment_urlObject



232
233
234
# File 'app/models/spree/payment.rb', line 232

def gateway_dashboard_payment_url
  payment_method.try(:gateway_dashboard_payment_url, self)
end

#gateway_processing_error_messagesObject



272
273
274
275
276
277
278
279
# File 'app/models/spree/payment.rb', line 272

def gateway_processing_error_messages
  @gateway_processing_error_messages ||= begin
    errors = JSON.parse(get_metafield('gateway.processing_errors')&.value || '[]')
    errors.map { |error| error['message'] }
  rescue JSON::ParserError
    []
  end
end

#has_invalid_state?Boolean

Returns:



281
282
283
# File 'app/models/spree/payment.rb', line 281

def has_invalid_state?
  INVALID_STATES.include?(state)
end

#is_avs_risky?Boolean

Returns:



218
219
220
221
222
# File 'app/models/spree/payment.rb', line 218

def is_avs_risky?
  return false if avs_response.blank? || NON_RISKY_AVS_CODES.include?(avs_response)

  true
end

#is_cvv_risky?Boolean

Returns:



224
225
226
227
228
229
230
# File 'app/models/spree/payment.rb', line 224

def is_cvv_risky?
  return false if cvv_response_code == 'M'
  return false if cvv_response_code.nil?
  return false if cvv_response_message.present?

  true
end

#max_amountObject



146
147
148
149
150
151
152
153
154
155
156
157
# File 'app/models/spree/payment.rb', line 146

def max_amount
  return amount if order.nil?

  amount_from_order = order.total - order.payment_total

  if payment_method&.store_credit?
    store_credits = order.available_store_credits
    store_credits.any? ? [store_credits.first.amount_remaining, amount_from_order].min : amount_from_order
  else
    amount_from_order
  end
end

#offsets_totalObject



169
170
171
# File 'app/models/spree/payment.rb', line 169

def offsets_total
  offsets.sum(:amount)
end

#payment_sourceObject



213
214
215
216
# File 'app/models/spree/payment.rb', line 213

def payment_source
  res = source.is_a?(Payment) ? source.source : source
  res || payment_method
end

#sourceObject



139
140
141
142
143
144
# File 'app/models/spree/payment.rb', line 139

def source
  return super if payment_method.nil?
  return super unless payment_method.source_required?

  payment_method.payment_source_class.unscoped { super }
end

#source_required?Boolean

Returns:



255
256
257
258
259
# File 'app/models/spree/payment.rb', line 255

def source_required?
  return false if skip_source_requirement

  payment_method&.source_required?
end

#uncaptured_amountObject



240
241
242
# File 'app/models/spree/payment.rb', line 240

def uncaptured_amount
  amount - captured_amount
end