Module: Spree::Payment::Processing

Included in:
Spree::Payment
Defined in:
app/models/spree/payment/processing.rb

Instance Method Summary collapse

Instance Method Details

#authorize!Object



25
26
27
28
# File 'app/models/spree/payment/processing.rb', line 25

def authorize!
  started_processing!
  gateway_action(source, :authorize, :pend)
end

#cancel!Object



122
123
124
125
126
127
128
# File 'app/models/spree/payment/processing.rb', line 122

def cancel!
  if payment_method.respond_to?(:cancel)
    payment_method.cancel(response_code)
  else
    credit!(credit_allowed.abs)
  end
end

#capture!(amount = nil) ⇒ Object

Takes the amount in cents to capture. Can be used to capture partial amounts of a payment.



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'app/models/spree/payment/processing.rb', line 40

def capture!(amount=nil)
  amount ||= money.money.cents
  return true if completed?
  started_processing!
  protect_from_connection_error do
    check_environment
    # Standard ActiveMerchant capture usage
    response = payment_method.capture(
      amount,
      response_code,
      gateway_options
    )

    money = ::Money.new(amount, currency)
    capture_events.create!(amount: money.to_f)
    handle_response(response, :complete, :failure)
  end
end

#credit!(credit_amount = nil) ⇒ Object

Raises:



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'app/models/spree/payment/processing.rb', line 83

def credit!(credit_amount=nil)
  raise Core::GatewayError.new(Spree.t(:payment_processing_failed)) if processing?

  # Calculate credit amount before marking as processing since it messes up the order totals not having payment in completed state.
  credit_amount ||= credit_allowed >= order.outstanding_balance.abs ? order.outstanding_balance.abs : credit_allowed.abs
  credit_amount = credit_amount.to_f

  # Mark as processing to avoid race condition that could send multiple credits to the gateway.
  started_processing!
  protect_from_connection_error do
    check_environment

    credit_cents = Spree::Money.new(credit_amount, currency: currency).money.cents

    if payment_method.payment_profiles_supported?
      response = payment_method.credit(credit_cents, source, response_code, gateway_options)
    else
      response = payment_method.credit(credit_cents, response_code, gateway_options)
    end

    record_response(response)
    # Always set back to 'completed' as initial payment record was successful.
    self.update_column(:state, 'completed')

    if response.success?
      self.class.create!(
        :order => order,
        :source => self,
        :payment_method => payment_method,
        :amount => credit_amount.abs * -1,
        :response_code => response.authorization,
        :state => 'completed'
      )
    else
      gateway_error(response)
    end
  end
end

#gateway_optionsObject



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'app/models/spree/payment/processing.rb', line 135

def gateway_options
  order.reload
  options = { :email       => order.email,
              :customer    => order.email,
              :customer_id => order.user_id,
              :ip          => order.last_ip_address,
              # Need to pass in a unique identifier here to make some
              # payment gateways happy.
              #
              # For more information, please see Spree::Payment#set_unique_identifier
              :order_id    => gateway_order_id }

  options.merge!({ :shipping => order.ship_total * 100,
                   :tax      => order.additional_tax_total * 100,
                   :subtotal => order.item_total * 100,
                   :discount => order.promo_total * 100,
                   :currency => currency })

  options.merge!({ :billing_address  => order.bill_address.try(:active_merchant_hash),
                  :shipping_address => order.ship_address.try(:active_merchant_hash) })

  options
end

#partial_credit(amount) ⇒ Object



130
131
132
133
# File 'app/models/spree/payment/processing.rb', line 130

def partial_credit(amount)
  return if amount > credit_allowed
  credit!(amount)
end

#process!Object



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'app/models/spree/payment/processing.rb', line 4

def process!
  if payment_method && payment_method.source_required?
    if source
      if !processing?
        if payment_method.supports?(source) || token_based?
          if payment_method.auto_capture?
            purchase!
          else
            authorize!
          end
        else
          invalidate!
          raise Core::GatewayError.new(Spree.t(:payment_method_not_supported))
        end
      end
    else
      raise Core::GatewayError.new(Spree.t(:payment_processing_failed))
    end
  end
end

#purchase!Object

Captures the entire amount of a payment.



31
32
33
34
35
36
# File 'app/models/spree/payment/processing.rb', line 31

def purchase!
  started_processing!
  result = gateway_action(source, :purchase, :complete)
  # This won't be called if gateway_action raises a GatewayError
  capture_events.create!(amount: amount)
end

#void_transaction!Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'app/models/spree/payment/processing.rb', line 59

def void_transaction!
  return true if void?
  protect_from_connection_error do
    check_environment

    if payment_method.payment_profiles_supported?
      # Gateways supporting payment profiles will need access to credit card object because this stores the payment profile information
      # so supply the authorization itself as well as the credit card, rather than just the authorization code
      response = payment_method.void(self.response_code, source, gateway_options)
    else
      # Standard ActiveMerchant void usage
      response = payment_method.void(self.response_code, gateway_options)
    end
    record_response(response)

    if response.success?
      self.response_code = response.authorization
      self.void
    else
      gateway_error(response)
    end
  end
end