Module: Pay::Braintree::Billable

Extended by:
ActiveSupport::Concern
Defined in:
lib/pay/braintree/billable.rb

Instance Method Summary collapse

Instance Method Details

#braintree_customerObject

Handles Billable#customer

Returns Braintree::Customer



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/pay/braintree/billable.rb', line 13

def braintree_customer
  if processor_id?
    gateway.customer.find(processor_id)
  else
    result = gateway.customer.create(
      email: email,
      first_name: try(:first_name),
      last_name: try(:last_name),
      payment_method_nonce: card_token
    )
    raise Pay::Braintree::Error, result unless result.success?

    update(processor: "braintree", processor_id: result.customer.id)

    if card_token.present?
      update_braintree_card_on_file result.customer.payment_methods.last
    end

    result.customer
  end
rescue ::Braintree::AuthorizationError
  raise BraintreeAuthorizationError
rescue ::Braintree::BraintreeError => e
  raise Pay::Braintree::Error, e
end

#braintree_invoice!(options = {}) ⇒ Object



135
136
137
# File 'lib/pay/braintree/billable.rb', line 135

def braintree_invoice!(options = {})
  # pass
end

#braintree_subscription(subscription_id, options = {}) ⇒ Object



131
132
133
# File 'lib/pay/braintree/billable.rb', line 131

def braintree_subscription(subscription_id, options = {})
  gateway.subscription.find(subscription_id)
end

#braintree_trial_end_date(subscription) ⇒ Object



117
118
119
120
121
# File 'lib/pay/braintree/billable.rb', line 117

def braintree_trial_end_date(subscription)
  return unless subscription.trial_period
  # Braintree returns dates without time zones, so we'll assume they're UTC
  subscription.first_billing_date.end_of_day
end

#braintree_upcoming_invoiceObject



139
140
141
# File 'lib/pay/braintree/billable.rb', line 139

def braintree_upcoming_invoice
  # pass
end

#create_braintree_charge(amount, options = {}) ⇒ Object

Handles Billable#charge

Returns a Pay::Charge



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/pay/braintree/billable.rb', line 42

def create_braintree_charge(amount, options = {})
  args = {
    amount: amount.to_i / 100.0,
    customer_id: customer.id,
    options: {submit_for_settlement: true}
  }.merge(options)

  result = gateway.transaction.sale(args)
  raise Pay::Braintree::Error, result unless result.success?

  save_braintree_transaction(result.transaction)
rescue ::Braintree::AuthorizationError
  raise Pay::Braintree::AuthorizationError
rescue ::Braintree::BraintreeError => e
  raise Pay::Braintree::Error, e
end

#create_braintree_subscription(name, plan, options = {}) ⇒ Object

Handles Billable#subscribe

Returns Pay::Subscription



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/pay/braintree/billable.rb', line 62

def create_braintree_subscription(name, plan, options = {})
  token = customer.payment_methods.find(&:default?).try(:token)
  raise Pay::Error, "Customer has no default payment method" if token.nil?

  # Standardize the trial period options
  if (trial_period_days = options.delete(:trial_period_days)) && trial_period_days > 0
    options.merge!(trial_period: true, trial_duration: trial_period_days, trial_duration_unit: :day)
  end

  subscription_options = options.merge(
    payment_method_token: token,
    plan_id: plan
  )

  result = gateway.subscription.create(subscription_options)
  raise Pay::Braintree::Error, result unless result.success?

  create_subscription(result.subscription, "braintree", name, plan, status: :active)
rescue ::Braintree::AuthorizationError
  raise Pay::Braintree::AuthorizationError
rescue ::Braintree::BraintreeError => e
  raise Pay::Braintree::Error, e
end

#save_braintree_transaction(transaction) ⇒ Object



143
144
145
146
147
148
149
150
151
152
153
# File 'lib/pay/braintree/billable.rb', line 143

def save_braintree_transaction(transaction)
  attrs = card_details_for_braintree_transaction(transaction)
  attrs[:amount] = transaction.amount.to_f * 100

  charge = charges.find_or_initialize_by(
    processor: :braintree,
    processor_id: transaction.id
  )
  charge.update(attrs)
  charge
end

#update_braintree_card(token) ⇒ Object

Handles Billable#update_card

Returns true if successful



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/pay/braintree/billable.rb', line 89

def update_braintree_card(token)
  result = gateway.payment_method.create(
    customer_id: processor_id,
    payment_method_nonce: token,
    options: {
      make_default: true,
      verify_card: true
    }
  )
  raise Pay::Braintree::Error, result unless result.success?

  update_braintree_card_on_file result.payment_method
  update_subscriptions_to_payment_method(result.payment_method.token)
  true
rescue ::Braintree::AuthorizationError
  raise Pay::Braintree::AuthorizationError
rescue ::Braintree::BraintreeError => e
  raise Pay::Braintree::Error, e
end

#update_braintree_email!Object



109
110
111
112
113
114
115
# File 'lib/pay/braintree/billable.rb', line 109

def update_braintree_email!
  braintree_customer.update(
    email: email,
    first_name: try(:first_name),
    last_name: try(:last_name)
  )
end

#update_subscriptions_to_payment_method(token) ⇒ Object



123
124
125
126
127
128
129
# File 'lib/pay/braintree/billable.rb', line 123

def update_subscriptions_to_payment_method(token)
  subscriptions.braintree.each do |subscription|
    if subscription.active?
      gateway.subscription.update(subscription.processor_id, {payment_method_token: token})
    end
  end
end