Class: Creditcard
- Inherits:
-
ActiveRecord::Base
- Object
- ActiveRecord::Base
- Creditcard
- Defined in:
- app/models/creditcard.rb
Direct Known Subclasses
Defined Under Namespace
Classes: CardDetector
Instance Attribute Summary collapse
-
#number ⇒ Object
Returns the value of attribute number.
-
#verification_value ⇒ Object
Returns the value of attribute verification_value.
Instance Method Summary collapse
- #actions ⇒ Object
- #authorize(amount, payment) ⇒ Object
-
#brand ⇒ Object
needed for some of the ActiveMerchant gateways (eg. SagePay).
-
#can_capture?(payment) ⇒ Boolean
Indicates whether its possible to capture the payment.
-
#can_credit?(payment) ⇒ Boolean
Indicates whether its possible to credit the payment.
-
#can_void?(payment) ⇒ Boolean
Indicates whether its possible to void the payment.
- #capture(payment) ⇒ Object
-
#check_environment(gateway) ⇒ Object
Saftey check to make sure we’re not accidentally performing operations on a live gateway.
- #credit(payment) ⇒ Object
-
#display_number ⇒ Object
Show the card number, with all but last 4 numbers replace with “X”.
- #first_name? ⇒ Boolean
- #gateway_error(error) ⇒ Object
- #gateway_options(payment) ⇒ Object
-
#generate_address_hash(address) ⇒ Object
Generates an ActiveMerchant compatible address hash from one of Spree’s address objects.
- #has_payment_profile? ⇒ Boolean
- #last_name? ⇒ Boolean
-
#minimal_gateway_options(payment) ⇒ Object
Generates a minimal set of gateway options.
- #name ⇒ Object
- #name? ⇒ Boolean
- #process!(payment) ⇒ Object
- #purchase(amount, payment) ⇒ Object
- #record_log(payment, response) ⇒ Object
-
#set_card_type ⇒ Object
sets self.cc_type while we still have the card number.
- #set_last_digits ⇒ Object
- #spree_cc_type ⇒ Object
- #verification_value? ⇒ Boolean
- #void(payment) ⇒ Object
Instance Attribute Details
#number ⇒ Object
Returns the value of attribute number.
7 8 9 |
# File 'app/models/creditcard.rb', line 7 def number @number end |
#verification_value ⇒ Object
Returns the value of attribute verification_value.
7 8 9 |
# File 'app/models/creditcard.rb', line 7 def verification_value @verification_value end |
Instance Method Details
#actions ⇒ Object
188 189 190 |
# File 'app/models/creditcard.rb', line 188 def actions %w{capture void credit} end |
#authorize(amount, payment) ⇒ Object
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'app/models/creditcard.rb', line 76 def (amount, payment) # ActiveMerchant is configured to use cents so we need to multiply order total by 100 payment_gateway = payment.payment_method check_environment(payment_gateway) response = payment_gateway.((amount * 100).round, self, (payment)) record_log payment, response if response.success? payment.response_code = response. payment.avs_response = response.avs_result['code'] payment.pend else payment.fail gateway_error(response) end rescue ActiveMerchant::ConnectionError gateway_error I18n.t(:unable_to_connect_to_gateway) end |
#brand ⇒ Object
needed for some of the ActiveMerchant gateways (eg. SagePay)
70 71 72 |
# File 'app/models/creditcard.rb', line 70 def brand cc_type end |
#can_capture?(payment) ⇒ Boolean
Indicates whether its possible to capture the payment
193 194 195 |
# File 'app/models/creditcard.rb', line 193 def can_capture?(payment) payment.state == "pending" end |
#can_credit?(payment) ⇒ Boolean
Indicates whether its possible to credit the payment. Note that most gateways require that the payment be settled first which generally happens within 12-24 hours of the transaction.
204 205 206 207 208 |
# File 'app/models/creditcard.rb', line 204 def can_credit?(payment) return false unless payment.state == "completed" return false unless payment.order.payment_state == "credit_owed" payment.credit_allowed > 0 end |
#can_void?(payment) ⇒ Boolean
Indicates whether its possible to void the payment.
198 199 200 |
# File 'app/models/creditcard.rb', line 198 def can_void?(payment) payment.state == "void" ? false : true end |
#capture(payment) ⇒ Object
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'app/models/creditcard.rb', line 116 def capture(payment) return unless payment.pending? payment_gateway = payment.payment_method check_environment(payment_gateway) if payment_gateway.payment_profiles_supported? # Gateways supporting payment profiles will need access to creditcard object because this stores the payment profile information # so supply the authorization itself as well as the creditcard, rather than just the authorization code response = payment_gateway.capture(payment, self, (payment)) else # Standard ActiveMerchant capture usage response = payment_gateway.capture((payment.amount * 100).round, payment.response_code, (payment)) end record_log payment, response if response.success? payment.response_code = response. payment.complete else payment.fail gateway_error(response) end rescue ActiveMerchant::ConnectionError gateway_error I18n.t(:unable_to_connect_to_gateway) end |
#check_environment(gateway) ⇒ Object
Saftey check to make sure we’re not accidentally performing operations on a live gateway. Ex. When testing in staging environment with a copy of production data.
262 263 264 265 266 |
# File 'app/models/creditcard.rb', line 262 def check_environment(gateway) return if gateway.environment == Rails.env = I18n.t(:gateway_config_unavailable) + " - #{Rails.env}" raise Spree::GatewayError.new() end |
#credit(payment) ⇒ Object
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'app/models/creditcard.rb', line 160 def credit(payment) payment_gateway = payment.payment_method check_environment(payment_gateway) amount = payment.credit_allowed >= payment.order.outstanding_balance.abs ? payment.order.outstanding_balance.abs : payment.credit_allowed.abs if payment_gateway.payment_profiles_supported? response = payment_gateway.credit((amount * 100).round, self, payment.response_code, (payment)) else response = payment_gateway.credit((amount * 100).round, payment.response_code, (payment)) end record_log payment, response if response.success? Payment.create(:order => payment.order, :source => payment, :payment_method => payment.payment_method, :amount => amount.abs * -1, :response_code => response., :state => 'completed') else gateway_error(response) end rescue ActiveMerchant::ConnectionError gateway_error I18n.t(:unable_to_connect_to_gateway) end |
#display_number ⇒ Object
Show the card number, with all but last 4 numbers replace with “X”. (XXXX-XXXX-XXXX-4338)
61 62 63 |
# File 'app/models/creditcard.rb', line 61 def display_number "XXXX-XXXX-XXXX-#{last_digits}" end |
#first_name? ⇒ Boolean
44 45 46 |
# File 'app/models/creditcard.rb', line 44 def first_name? first_name.present? end |
#gateway_error(error) ⇒ Object
218 219 220 221 222 223 224 225 226 227 |
# File 'app/models/creditcard.rb', line 218 def gateway_error(error) if error.is_a? ActiveMerchant::Billing::Response text = error.params['message'] || error.params['response_reason_text'] || error. else text = error.to_s end logger.error(I18n.t('gateway_error')) logger.error(" #{error.to_yaml}") raise Spree::GatewayError.new(text) end |
#gateway_options(payment) ⇒ Object
229 230 231 232 233 |
# File 'app/models/creditcard.rb', line 229 def (payment) = {:billing_address => generate_address_hash(payment.order.bill_address), :shipping_address => generate_address_hash(payment.order.ship_address)} .merge (payment) end |
#generate_address_hash(address) ⇒ Object
Generates an ActiveMerchant compatible address hash from one of Spree’s address objects
236 237 238 239 240 |
# File 'app/models/creditcard.rb', line 236 def generate_address_hash(address) return {} if address.nil? {:name => address.full_name, :address1 => address.address1, :address2 => address.address2, :city => address.city, :state => address.state_text, :zip => address.zipcode, :country => address.country.iso, :phone => address.phone} end |
#has_payment_profile? ⇒ Boolean
210 211 212 |
# File 'app/models/creditcard.rb', line 210 def has_payment_profile? gateway_customer_profile_id.present? end |
#last_name? ⇒ Boolean
48 49 50 |
# File 'app/models/creditcard.rb', line 48 def last_name? last_name.present? end |
#minimal_gateway_options(payment) ⇒ Object
Generates a minimal set of gateway options. There appears to be some issues with passing in a billing address when authorizing/voiding a previously captured transaction. So omits these options in this case since they aren’t necessary.
245 246 247 248 249 250 251 252 253 |
# File 'app/models/creditcard.rb', line 245 def (payment) {:email => payment.order.email, :customer => payment.order.email, :ip => payment.order.ip_address, :order_id => payment.order.number, :shipping => payment.order.ship_total * 100, :tax => payment.order.tax_total * 100, :subtotal => payment.order.item_total * 100} end |
#name ⇒ Object
52 53 54 |
# File 'app/models/creditcard.rb', line 52 def name "#{first_name} #{last_name}" end |
#name? ⇒ Boolean
40 41 42 |
# File 'app/models/creditcard.rb', line 40 def name? first_name? && last_name? end |
#process!(payment) ⇒ Object
13 14 15 16 17 18 19 |
# File 'app/models/creditcard.rb', line 13 def process!(payment) if Spree::Config[:auto_capture] purchase(payment.amount.to_f, payment) else (payment.amount.to_f, payment) end end |
#purchase(amount, payment) ⇒ Object
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'app/models/creditcard.rb', line 96 def purchase(amount, payment) #combined Authorize and Capture that gets processed by the ActiveMerchant gateway as one single transaction. payment_gateway = payment.payment_method check_environment(payment_gateway) response = payment_gateway.purchase((amount * 100).round, self, (payment)) record_log payment, response if response.success? payment.response_code = response. payment.avs_response = response.avs_result['code'] payment.complete else payment.fail gateway_error(response) unless response.success? end rescue ActiveMerchant::ConnectionError gateway_error I18n.t(:unable_to_connect_to_gateway) end |
#record_log(payment, response) ⇒ Object
214 215 216 |
# File 'app/models/creditcard.rb', line 214 def record_log(payment, response) payment.log_entries.create(:details => response.to_yaml) end |
#set_card_type ⇒ Object
sets self.cc_type while we still have the card number
36 37 38 |
# File 'app/models/creditcard.rb', line 36 def set_card_type self.cc_type ||= CardDetector.type?(self.number) end |
#set_last_digits ⇒ Object
21 22 23 24 25 |
# File 'app/models/creditcard.rb', line 21 def set_last_digits number.to_s.gsub!(/\s/,'') unless number.nil? verification_value.to_s.gsub!(/\s/,'') unless number.nil? self.last_digits ||= number.to_s.length <= 4 ? number : number.to_s.slice(-4..-1) end |
#spree_cc_type ⇒ Object
255 256 257 258 |
# File 'app/models/creditcard.rb', line 255 def spree_cc_type return "visa" if ::Rails.env == "development" self.cc_type end |
#verification_value? ⇒ Boolean
56 57 58 |
# File 'app/models/creditcard.rb', line 56 def verification_value? verification_value.present? end |
#void(payment) ⇒ Object
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'app/models/creditcard.rb', line 143 def void(payment) payment_gateway = payment.payment_method check_environment(payment_gateway) response = payment_gateway.void(payment.response_code, (payment)) record_log payment, response if response.success? payment.response_code = response. payment.void else gateway_error(response) end rescue ActiveMerchant::ConnectionError gateway_error I18n.t(:unable_to_connect_to_gateway) end |