class SpookAndPay::Providers::Spreedly
Constants
- CARD_FIELDS
A mapping from the names used by
Spreedly
to the namesSpookAndPay
uses internally.- ERRORS
Maps the error types from Spreedly's to the names used internally.
- FORM_FIELD_NAMES
The map of generic field names to what is specifically required by
Spreedly
.
Attributes
Currency code. Spreedly
defaults to USD, but we default to AUD.
@attr_reader String
The which refers to a specific gateway.
@attr_reader String
An instance of the spreedly spreedly.
@attr_reader Spreedly::Environment
Public Class Methods
Generate a new instance of the Spreedly
provider.
@param Hash config @option config String :environment_key @option config String :access_secret @option config String :gateway_token @option config String :currency_code
SpookAndPay::Providers::Base::new
# File lib/spook_and_pay/providers/spreedly.rb, line 36 def initialize(env, config) @gateway_token = config[:gateway_token] @currency_code = config[:currency_code] || 'AUD' @spreedly = ::Spreedly::Environment.new( config[:environment_key], config[:access_secret], :currency_code => currency_code ) super(env, config) end
Public Instance Methods
# File lib/spook_and_pay/providers/spreedly.rb, line 102 def capture_transaction(id) result = spreedly.capture_transaction(transaction_id(id)) coerce_result(result) end
Confirms the submission of payment details to Spreedly
Core.
@param String query_string @param Hash opts @option opts [String, Numeric] :amount @option opts [:purchase, :authorize, :store] :execute @return SpookAndPay::Result
# File lib/spook_and_pay/providers/spreedly.rb, line 72 def confirm_payment_submission(query_string, opts) token = Rack::Utils.parse_nested_query(query_string)["token"] card = credit_card(token) if card.valid? case opts[:execute] when :authorize then card.authorize!(opts[:amount]) when :purchase then card.purchase!(opts[:amount]) else SpookAndPay::Result.new(true, nil, :credit_card => card) end else SpookAndPay::Result.new(false, nil, :credit_card => card, :errors => extract_card_errors(card.raw)) end end
# File lib/spook_and_pay/providers/spreedly.rb, line 87 def credit_card(id) result = spreedly.find_payment_method(id) coerce_credit_card(result) end
# File lib/spook_and_pay/providers/spreedly.rb, line 92 def credit_card_from_transaction(id) result = spreedly.find_transaction(transaction_id(id)) coerce_credit_card(result.payment_method) end
# File lib/spook_and_pay/providers/spreedly.rb, line 165 def delete_credit_card(id) result = spreedly.redact_payment_method(credit_card_id(id)) coerce_result(result) end
# File lib/spook_and_pay/providers/spreedly.rb, line 112 def partially_refund_transaction(id, amount) result = spreedly.refund_transaction(transaction_id(id), :amount => (amount.to_f * 100).to_i) coerce_result(result) end
@param String redirect_url @param Hash opts @return Hash
# File lib/spook_and_pay/providers/spreedly.rb, line 51 def prepare_payment_submission(redirect_url, opts = {}) config = { :url => spreedly.transparent_redirect_form_action, :field_names => self.class::FORM_FIELD_NAMES, :hidden_fields => {:redirect_url => redirect_url, :environment_key => spreedly.key} } if opts[:token] config[:hidden_fields][:payment_method_token] = opts[:token] end config end
# File lib/spook_and_pay/providers/spreedly.rb, line 160 def purchase_via_credit_card(id, amount) result = spreedly.purchase_on_gateway(gateway_token, credit_card_id(id), (amount.to_f * 100).to_i) coerce_result(result) end
# File lib/spook_and_pay/providers/spreedly.rb, line 107 def refund_transaction(id) result = spreedly.refund_transaction(transaction_id(id)) coerce_result(result) end
Calls the retain action on the provider's vault.
@param [SpookAndPay::CreditCard, Integer, String] id @return SpookAndPay::Result
@api private
# File lib/spook_and_pay/providers/spreedly.rb, line 175 def retain_credit_card(id) result = spreedly.retain_payment_method(credit_card_id(id)) coerce_result(result) end
# File lib/spook_and_pay/providers/spreedly.rb, line 141 def supports_capture? check_support_for('supports_capture') end
# File lib/spook_and_pay/providers/spreedly.rb, line 137 def supports_credit? false end
# File lib/spook_and_pay/providers/spreedly.rb, line 149 def supports_delete? # This does not check the gateway, since the redaction is specific to # Spreedly's store, not the gateway. true end
# File lib/spook_and_pay/providers/spreedly.rb, line 129 def supports_purchase? check_support_for('supports_purchase') end
# File lib/spook_and_pay/providers/spreedly.rb, line 133 def supports_void? check_support_for('supports_void') end
# File lib/spook_and_pay/providers/spreedly.rb, line 97 def transaction(id) result = spreedly.find_transaction(id) coerce_transaction(result) end
# File lib/spook_and_pay/providers/spreedly.rb, line 117 def void_transaction(id) result = spreedly.void_transaction(transaction_id(id)) coerce_result(result) end
Private Instance Methods
Retrieves the gateway from Spreedly
and then inspects the response to see what features it supports. This is a helper for the supports_*? predicates.
@param String path @return [true, false]
# File lib/spook_and_pay/providers/spreedly.rb, line 188 def check_support_for(path) gateway = spreedly.find_gateway(gateway_token) node = Nokogiri::XML::DocumentFragment.parse(gateway.characteristics) node.xpath(".//#{path}").inner_html.strip == 'true' end
Takes the response generated by the Spreedly
lib and coerces it into a SpookAndPay::CreditCard
@param Spreedly::CreditCard @return SpookAndPay::CreditCard
# File lib/spook_and_pay/providers/spreedly.rb, line 280 def coerce_credit_card(card) expired = !card.errors.select {|e| e[:key] == 'errors.expired'}.empty? fields = { :card_type => card.card_type, :number => card.number, :name => card.full_name, :expiration_month => card.month, :expiration_year => card.year, :valid => card.valid?, :expired => expired } SpookAndPay::CreditCard.new(self, card.token, fields, card) end
Takes the result of running a transaction against a Spreedly
gateway and coerces it into a SpookAndPay::Result
@param Spreedly::Transaction result @return SpookAndPay::Result
# File lib/spook_and_pay/providers/spreedly.rb, line 199 def coerce_result(result) opts = { :transaction => coerce_transaction(result), :errors => extract_transaction_errors(result) } if result.respond_to?(:payment_method) opts[:credit_card] = coerce_credit_card(result.payment_method) end SpookAndPay::Result.new(result.succeeded, result, opts) end
Takes a transaction generated by the Spreedly
lib and coerces it into a SpookAndPay::Transaction
@param Spreedly::Transaction transaction @return SpookAndPay::Transaction
@todo extract created_at and status from the transaction.response
# File lib/spook_and_pay/providers/spreedly.rb, line 302 def coerce_transaction(transaction) fields = {} fields[:type], status = case transaction when ::Spreedly::Authorization then [:authorize, :authorized] when ::Spreedly::Purchase then [:purchase, :settled] when ::Spreedly::Capture then [:capture, :settled] when ::Spreedly::Refund then [:credit, :refunded] when ::Spreedly::Void then [:void, :voided] when ::Spreedly::RetainPaymentMethod then [:retain, :retained] end if transaction.respond_to?(:amount) fields[:amount] = transaction.amount end SpookAndPay::Transaction.new(self, transaction.token, status, transaction, fields) end
Extracts/coerces errors from a Spreedly
response into SubmissionError
instances.
@param Spreedly::CreditCard result @return Array<SpookAndPay::SubmissionError> @todo If the Spreedly
API behaves later, the check for first/last
name might not be needed anymore.
# File lib/spook_and_pay/providers/spreedly.rb, line 236 def extract_card_errors(result) # This gnarly bit of code transforms errors on the first_name or # last_name attributes into an error on full_name. This is because # Spreedly accepts input for full_name, but propogates errors to the # separate attributes. errors = result.errors.map do |e| case e[:attribute] when 'first_name' then e.merge(:attribute => "full_name") when 'last_name' then nil else e end end.compact errors.map do |e| name = CARD_FIELDS[e[:attribute]] error = ERRORS[e[:key]] if name and error SubmissionError.new(:credit_card, error, name, e) else SubmissionError.new(:unknown, :unknown, :unknown, e) end end end
Extracts/coerces errors from a Spreedly
transaction into SubmissionError
instances.
@param Spreedly::Transaction result @return Array<SpookAndPay::SubmissionError> @todo Expand this to handle different errors
# File lib/spook_and_pay/providers/spreedly.rb, line 267 def extract_transaction_errors(result) if result.succeeded [] else [SubmissionError.new(:transaction, :card_declined, :transaction, result.message)] end end