Class: Gateway::BraintreeGateway

Inherits:
Gateway
  • Object
show all
Defined in:
app/models/spree/gateway/braintree_gateway.rb

Constant Summary collapse

CARD_TYPE_MAPPING =
{
  'American Express' => 'american_express',
  'Diners Club' => 'diners_club',
  'Discover' => 'discover',
  'JCB' => 'jcb',
  'Laser' => 'laser',
  'Maestro' => 'maestro',
  'MasterCard' => 'master',
  'Solo' => 'solo',
  'Switch' => 'switch',
  'Visa' => 'visa'
}

Instance Method Summary collapse

Instance Method Details

#authorize(money, creditcard, options = {}) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
49
# File 'app/models/spree/gateway/braintree_gateway.rb', line 38

def authorize(money, creditcard, options = {})
  adjust_options_for_braintree(creditcard, options)

  if creditcard.gateway_payment_profile_id
    payment_method = creditcard.gateway_payment_profile_id
    options[:payment_method_token] = true
  else
    payment_method = creditcard.gateway_customer_profile_id || creditcard
  end

  provider.authorize(money, payment_method, options)
end

#cancel(response_code) ⇒ Object



128
129
130
131
132
133
134
135
136
137
138
139
# File 'app/models/spree/gateway/braintree_gateway.rb', line 128

def cancel(response_code)
  provider
  transaction = ::Braintree::Transaction.find(response_code)
  # From: https://www.braintreepayments.com/docs/ruby/transactions/refund
  # "A transaction can be refunded if its status is settled or settling.
  # If the transaction has not yet begun settlement, it should be voided instead of refunded.
  if transaction.status == Braintree::Transaction::Status::SubmittedForSettlement
    provider.void(response_code)
  else
    provider.refund(response_code)
  end
end

#capture(amount, authorization_code, ignored_options = {}) ⇒ Object



51
52
53
# File 'app/models/spree/gateway/braintree_gateway.rb', line 51

def capture(amount, authorization_code, ignored_options = {})
  provider.capture(amount, authorization_code)
end

#create_profile(payment) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'app/models/spree/gateway/braintree_gateway.rb', line 55

def create_profile(payment)
  if payment.source.gateway_customer_profile_id.nil?
    response = provider.store(payment.source, options_for_payment(payment))

    if response.success?
      payment.source.update_attributes!(:gateway_customer_profile_id => response.params['customer_vault_id'])
      cc = response.params['braintree_customer'].fetch('credit_cards',[]).first
      update_card_number(payment.source, cc) if cc
    else
      payment.send(:gateway_error, response.message)
    end
  end
end

#credit(*args) ⇒ Object



77
78
79
80
81
82
83
84
85
86
87
# File 'app/models/spree/gateway/braintree_gateway.rb', line 77

def credit(*args)
  if args.size == 4
    # enables ability to refund instead of credit
    args.slice!(1,1)
    credit_without_payment_profiles(*args)
  elsif args.size == 3
    credit_without_payment_profiles(*args)
  else
    raise ArgumentError, "Expected 3 or 4 arguments, received #{args.size}"
  end
end

#credit_with_payment_profiles(amount, payment, response_code, option) ⇒ Object

Braintree now disables credits by default, see www.braintreepayments.com/docs/ruby/transactions/credit



90
91
92
# File 'app/models/spree/gateway/braintree_gateway.rb', line 90

def credit_with_payment_profiles(amount, payment, response_code, option)
  provider.credit(amount, payment)
end

#credit_without_payment_profiles(amount, response_code, options) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
# File 'app/models/spree/gateway/braintree_gateway.rb', line 94

def credit_without_payment_profiles(amount, response_code, options)
  provider # braintree provider needs to be called here to properly configure braintree gem.
  transaction = ::Braintree::Transaction.find(response_code)
  if BigDecimal.new(amount.to_s) == (transaction.amount * 100)
    provider.refund(response_code)
  elsif BigDecimal.new(amount.to_s) < (transaction.amount * 100) # support partial refunds
    provider.refund(amount, response_code)
  else
    raise NotImplementedError
  end
end

#optionsObject



118
119
120
121
122
123
124
125
126
# File 'app/models/spree/gateway/braintree_gateway.rb', line 118

def options
  h = super
  # We need to add merchant_account_id only if present when creating BraintreeBlueGateway
  # Remove it since it is always part of the preferences hash.
  if h[:merchant_account_id].blank?
    h.delete(:merchant_account_id)
  end
  h
end

#payment_profiles_supported?Boolean

Returns:

  • (Boolean)


106
107
108
# File 'app/models/spree/gateway/braintree_gateway.rb', line 106

def payment_profiles_supported?
  true
end

#providerObject



23
24
25
26
27
28
29
30
31
32
# File 'app/models/spree/gateway/braintree_gateway.rb', line 23

def provider
  provider_instance = super
  Braintree::Configuration.custom_user_agent = "solidus_gateway #{SolidusGateway::VERSION}"
  Braintree::Configuration.environment = preferred_environment.to_sym
  Braintree::Configuration.merchant_id = preferred_merchant_id
  Braintree::Configuration.public_key = preferred_public_key
  Braintree::Configuration.private_key = preferred_private_key

  provider_instance
end

#provider_classObject



34
35
36
# File 'app/models/spree/gateway/braintree_gateway.rb', line 34

def provider_class
  ActiveMerchant::Billing::BraintreeBlueGateway
end

#purchase(money, creditcard, options = {}) ⇒ Object



110
111
112
# File 'app/models/spree/gateway/braintree_gateway.rb', line 110

def purchase(money, creditcard, options = {})
  authorize(money, creditcard, options.merge(:submit_for_settlement => true))
end

#update_card_number(source, cc) ⇒ Object



69
70
71
72
73
74
75
# File 'app/models/spree/gateway/braintree_gateway.rb', line 69

def update_card_number(source, cc)
  last_4 = cc['last_4']
  source.last_digits = last_4 if last_4
  source.gateway_payment_profile_id = cc['token']
  source.cc_type = CARD_TYPE_MAPPING[cc['card_type']] if cc['card_type']
  source.save!
end

#void(response_code, *ignored_options) ⇒ Object



114
115
116
# File 'app/models/spree/gateway/braintree_gateway.rb', line 114

def void(response_code, *ignored_options)
  provider.void(response_code)
end