Class: Pay::Braintree::Billable

Inherits:
Object
  • Object
show all
Defined in:
lib/pay/braintree/billable.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(billable) ⇒ Billable

Returns a new instance of Billable.



13
14
15
# File 'lib/pay/braintree/billable.rb', line 13

def initialize(billable)
  @billable = billable
end

Instance Attribute Details

#billableObject (readonly)

Returns the value of attribute billable.



4
5
6
# File 'lib/pay/braintree/billable.rb', line 4

def billable
  @billable
end

Instance Method Details

#braintree_invoice!(options = {}) ⇒ Object



142
143
144
# File 'lib/pay/braintree/billable.rb', line 142

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

#braintree_upcoming_invoiceObject



146
147
148
# File 'lib/pay/braintree/billable.rb', line 146

def braintree_upcoming_invoice
  # pass
end

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

Handles Billable#charge

Returns a Pay::Charge



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/pay/braintree/billable.rb', line 51

def 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_transaction(result.transaction)
rescue ::Braintree::AuthorizationError => e
  raise Pay::Braintree::AuthorizationError, e
rescue ::Braintree::BraintreeError => e
  raise Pay::Braintree::Error, e
end

#customerObject

Handles Billable#customer

Returns Braintree::Customer



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/pay/braintree/billable.rb', line 20

def customer
  if processor_id?
    customer = gateway.customer.find(processor_id)
    update_card card_token if card_token.present?
    customer
  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?

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

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

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

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



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

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

#save_transaction(transaction) ⇒ Object



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/pay/braintree/billable.rb', line 150

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

  # Associate charge with subscription if we can
  if transaction.subscription_id
    attrs[:subscription] = Pay::Subscription.find_by(processor: :braintree, processor_id: transaction.subscription_id)
  end

  charge = billable.charges.find_or_initialize_by(
    processor: :braintree,
    processor_id: transaction.id,
    currency: transaction.currency_iso_code,
    application_fee_amount: transaction.service_fee_amount
  )
  charge.update(attrs)
  charge
end

#subscribe(name: Pay.default_product_name, plan: Pay.default_plan_name, **options) ⇒ Object

Handles Billable#subscribe

Returns Pay::Subscription



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/pay/braintree/billable.rb', line 71

def subscribe(name: Pay.default_product_name, plan: Pay.default_plan_name, **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?

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

#trial_end_date(subscription) ⇒ Object



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

def 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

#update_card(token) ⇒ Object

Handles Billable#update_card

Returns true if successful



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/pay/braintree/billable.rb', line 98

def update_card(token)
  customer unless processor_id?

  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_card_on_file result.payment_method
  update_subscriptions_to_payment_method(result.payment_method.token)
  true
rescue ::Braintree::AuthorizationError => e
  raise Pay::Braintree::AuthorizationError, e
rescue ::Braintree::BraintreeError => e
  raise Pay::Braintree::Error, e
end

#update_email!Object



120
121
122
# File 'lib/pay/braintree/billable.rb', line 120

def update_email!
  gateway.customer.update(processor_id, email: email, first_name: try(:first_name), last_name: try(:last_name))
end

#update_subscriptions_to_payment_method(token) ⇒ Object



130
131
132
133
134
135
136
# File 'lib/pay/braintree/billable.rb', line 130

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