chargebee_rails 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +470 -0
- data/Rakefile +10 -0
- data/app/controllers/chargebee_rails/webhooks_controller.rb +40 -0
- data/config/routes.rb +9 -0
- data/lib/chargebee_rails.rb +119 -0
- data/lib/chargebee_rails/configuration.rb +47 -0
- data/lib/chargebee_rails/customer.rb +85 -0
- data/lib/chargebee_rails/engine.rb +6 -0
- data/lib/chargebee_rails/errors.rb +26 -0
- data/lib/chargebee_rails/hosted_page_subscription_manager.rb +134 -0
- data/lib/chargebee_rails/metered_billing.rb +56 -0
- data/lib/chargebee_rails/subscription.rb +163 -0
- data/lib/chargebee_rails/subscription_builder.rb +162 -0
- data/lib/chargebee_rails/version.rb +4 -0
- data/lib/chargebee_rails/webhook_handler.rb +175 -0
- data/lib/generators/chargebee_rails/install_generator.rb +58 -0
- data/lib/generators/chargebee_rails/templates/app/models/payment_method.rb +3 -0
- data/lib/generators/chargebee_rails/templates/app/models/plan.rb +4 -0
- data/lib/generators/chargebee_rails/templates/app/models/subscription.rb +7 -0
- data/lib/generators/chargebee_rails/templates/config/initializers/chargebee_rails.rb +38 -0
- data/lib/generators/chargebee_rails/templates/event_sync_log_migration.rb +8 -0
- data/lib/generators/chargebee_rails/templates/new_subscription_migration.rb +16 -0
- data/lib/tasks/chargebee_rails_tasks.rake +7 -0
- data/lib/tasks/sync_failed_events.rake +72 -0
- data/lib/tasks/sync_plans.rake +82 -0
- metadata +206 -0
data/Rakefile
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
|
4
|
+
# Default directory to look in is `/specs`
|
5
|
+
# Run with `rake spec`
|
6
|
+
RSpec::Core::RakeTask.new(:spec) do |task|
|
7
|
+
task.rspec_opts = ['--color', '--format', 'nested']
|
8
|
+
end
|
9
|
+
|
10
|
+
task :default => :spec
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module ChargebeeRails
|
2
|
+
class WebhooksController < ActionController::Base
|
3
|
+
include WebhookHandler
|
4
|
+
before_filter :authenticate, if: "ChargebeeRails.configuration.secure_webhook_api"
|
5
|
+
|
6
|
+
# Handle ChargeBee webhook events
|
7
|
+
# From the post request received from chargebee, the event for which the
|
8
|
+
# webhook is triggered is found from the id parameter sent.
|
9
|
+
# The event is then handled by the WebhookHandler module.
|
10
|
+
# * *Raises* :
|
11
|
+
# - +ChargebeeRails::Error+ -> If event is not valid or if event unprocessable
|
12
|
+
def handle_event
|
13
|
+
event = ChargeBee::Event.retrieve(params[:id]).event
|
14
|
+
handle(event)
|
15
|
+
head :ok
|
16
|
+
rescue ChargebeeRails::Error => e
|
17
|
+
log_errors(e)
|
18
|
+
head :internal_server_error
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def log_errors(e)
|
24
|
+
logger.error e.message
|
25
|
+
e.backtrace.each { |line| logger.error " #{line}" }
|
26
|
+
end
|
27
|
+
|
28
|
+
# Basic http authentication for ChargeBee webhook apis
|
29
|
+
# The username and password used to secure the webhook at chargebee
|
30
|
+
# is compared with the configured webhook_authentication user and
|
31
|
+
# secret in the application.
|
32
|
+
def authenticate
|
33
|
+
authenticate_or_request_with_http_basic do |user, password|
|
34
|
+
user == ChargebeeRails.configuration.webhook_authentication[:user] &&
|
35
|
+
password == ChargebeeRails.configuration.webhook_authentication[:secret]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
data/config/routes.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
Rails.application.routes.draw do #:nodoc:
|
2
|
+
# ChargeBee webhook route
|
3
|
+
# This is the default route that the chargebee's webhooks reach the application
|
4
|
+
# and can be configured.
|
5
|
+
# The default webhook_api_path is +chargebee_rails_event+ - can be configured;
|
6
|
+
# and the default webhook_handler (webhook handling controller) is
|
7
|
+
# +chargebee_rails/webhooks+ - can be configured as well.
|
8
|
+
post ChargebeeRails.configuration.webhook_api_path => "#{ChargebeeRails.configuration.webhook_handler}#handle_event"
|
9
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require "chargebee_rails/version"
|
2
|
+
require "chargebee"
|
3
|
+
require "rails"
|
4
|
+
require "chargebee_rails/engine"
|
5
|
+
require "chargebee_rails/webhook_handler"
|
6
|
+
require "chargebee_rails/configuration"
|
7
|
+
require "chargebee_rails/errors"
|
8
|
+
require "generators/chargebee_rails/install_generator"
|
9
|
+
require "chargebee_rails/subscription"
|
10
|
+
require "chargebee_rails/subscription_builder"
|
11
|
+
require "chargebee_rails/hosted_page_subscription_manager"
|
12
|
+
require "chargebee_rails/customer"
|
13
|
+
require "chargebee_rails/metered_billing"
|
14
|
+
|
15
|
+
module ChargebeeRails
|
16
|
+
# This method is used to update the chargebee customer and also reflects the
|
17
|
+
# changes to the subscription owner in the application.
|
18
|
+
# * *Args* :
|
19
|
+
# - +customer+ -> the subscription owner
|
20
|
+
# - +options+ -> the options hash allowed for customer update in chargebee
|
21
|
+
# For more details on the options hash, refer the input parameters for
|
22
|
+
# https://apidocs.chargebee.com/docs/api/customers?lang=ruby#update_a_customer
|
23
|
+
# * *Returns* :
|
24
|
+
# - the updated subscription owner
|
25
|
+
# * *Raises* :
|
26
|
+
# - +ChargeBee::InvalidRequestError+ -> If customer or options is invalid
|
27
|
+
#
|
28
|
+
def self.update_customer(customer, options={})
|
29
|
+
chargebee_customer = ChargeBee::Customer.update(customer.chargebee_id, options).customer
|
30
|
+
customer.update(chargebee_id: chargebee_customer.id, chargebee_data: chargebee_customer_data(chargebee_customer))
|
31
|
+
customer
|
32
|
+
end
|
33
|
+
|
34
|
+
# Update the billing information of the chargebee customer. The changes in the
|
35
|
+
# billing details are also reflected in the subscription owner's
|
36
|
+
# +chargebee_customer_data+
|
37
|
+
# * *Args* :
|
38
|
+
# - +customer+ -> the subscription owner
|
39
|
+
# - +options+ -> the options hash allowed for updating customer billing info in chargebee
|
40
|
+
# For more details on the options hash, refer the input parameters for
|
41
|
+
# https://apidocs.chargebee.com/docs/api/customers?lang=ruby#update_billing_info_for_a_customer
|
42
|
+
# * *Returns* :
|
43
|
+
# - the updated subscription owner
|
44
|
+
# * *Raises* :
|
45
|
+
# - +ChargeBee::InvalidRequestError+ -> If customer or options is invalid
|
46
|
+
#
|
47
|
+
def self.update_billing_info(customer, options={})
|
48
|
+
chargebee_customer = ChargeBee::Customer.update_billing_info(customer.chargebee_id, options).customer
|
49
|
+
customer.update(chargebee_id: chargebee_customer.id, chargebee_data: chargebee_customer_data(chargebee_customer))
|
50
|
+
customer
|
51
|
+
end
|
52
|
+
|
53
|
+
# Add contacts to a chargebee customer, the subscription owner
|
54
|
+
# and the contact details hash is given as options.
|
55
|
+
# * *Args* :
|
56
|
+
# - +customer+ -> the subscription owner
|
57
|
+
# - +options+ -> the options hash allowed for adding contacts to customer in chargebee
|
58
|
+
# For more details on the options hash, refer the input parameters for
|
59
|
+
# https://apidocs.chargebee.com/docs/api/customers?lang=ruby#add_contacts_to_a_customer
|
60
|
+
# * *Returns* :
|
61
|
+
# - the updated chargebee customer
|
62
|
+
# * *Raises* :
|
63
|
+
# - +ChargeBee::InvalidRequestError+ -> If customer or options is invalid
|
64
|
+
#
|
65
|
+
def self.add_customer_contacts(customer, options={})
|
66
|
+
ChargeBee::Customer.add_contact(customer.chargebee_id, options).customer
|
67
|
+
end
|
68
|
+
|
69
|
+
# Update the contacts for a chargebee customer - the chargebee contact id
|
70
|
+
# must be passed in the options to update the existing contact for the
|
71
|
+
# subscription owner
|
72
|
+
# * *Args* :
|
73
|
+
# - +customer+ -> the subscription owner
|
74
|
+
# - +options+ -> the options hash allowed for updating customer contacts in chargebee
|
75
|
+
# For more details on the options hash, refer the input parameters for
|
76
|
+
# https://apidocs.chargebee.com/docs/api/customers?lang=ruby#update_contacts_for_a_customer
|
77
|
+
# * *Returns* :
|
78
|
+
# - the updated chargebee customer
|
79
|
+
# * *Raises* :
|
80
|
+
# - +ChargeBee::InvalidRequestError+ -> If customer or options is invalid
|
81
|
+
#
|
82
|
+
def self.update_customer_contacts(customer, options={})
|
83
|
+
ChargeBee::Customer.update_contact(customer.chargebee_id, options).customer
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
def chargebee_customer_data customer
|
89
|
+
{
|
90
|
+
customer_details: customer_details(customer),
|
91
|
+
billing_address: billing_address(customer.billing_address)
|
92
|
+
}
|
93
|
+
end
|
94
|
+
|
95
|
+
def customer_details customer
|
96
|
+
{
|
97
|
+
first_name: customer.first_name,
|
98
|
+
last_name: customer.last_name,
|
99
|
+
email: customer.email,
|
100
|
+
company: customer.company,
|
101
|
+
vat_number: customer.vat_number
|
102
|
+
}
|
103
|
+
end
|
104
|
+
|
105
|
+
def billing_address customer_billing_address
|
106
|
+
{
|
107
|
+
first_name: customer_billing_address.first_name,
|
108
|
+
last_name: customer_billing_address.last_name,
|
109
|
+
company: customer_billing_address.company,
|
110
|
+
address_line1: customer_billing_address.line1,
|
111
|
+
address_line2: customer_billing_address.line2,
|
112
|
+
address_line3: customer_billing_address.line3,
|
113
|
+
city: customer_billing_address.city,
|
114
|
+
state: customer_billing_address.state,
|
115
|
+
country: customer_billing_address.country,
|
116
|
+
zip: customer_billing_address.zip
|
117
|
+
} if customer_billing_address.present?
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# :nodoc: all
|
2
|
+
module ChargebeeRails
|
3
|
+
|
4
|
+
def self.configuration
|
5
|
+
@configuration ||= Configuration.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.setup
|
9
|
+
::ChargeBee.configure(
|
10
|
+
site: configuration.chargebee_site,
|
11
|
+
api_key: configuration.chargebee_api_key
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.configure
|
16
|
+
yield configuration
|
17
|
+
setup
|
18
|
+
end
|
19
|
+
|
20
|
+
class Configuration
|
21
|
+
attr_accessor :default_plan_id
|
22
|
+
attr_accessor :end_of_term
|
23
|
+
attr_accessor :proration
|
24
|
+
attr_accessor :include_delayed_charges
|
25
|
+
attr_accessor :chargebee_site
|
26
|
+
attr_accessor :chargebee_api_key
|
27
|
+
attr_accessor :currency
|
28
|
+
attr_accessor :webhook_handler
|
29
|
+
attr_accessor :webhook_api_path
|
30
|
+
attr_accessor :secure_webhook_api
|
31
|
+
attr_accessor :webhook_authentication
|
32
|
+
|
33
|
+
def initialize
|
34
|
+
@default_plan_id = nil
|
35
|
+
@end_of_term = false
|
36
|
+
@proration = true
|
37
|
+
@include_delayed_charges = {changes_estimate: false, renewal_estimate: true}
|
38
|
+
@webhook_handler = 'chargebee_rails/webhooks'
|
39
|
+
@webhook_api_path = 'chargebee_rails_event'
|
40
|
+
@secure_webhook_api = false
|
41
|
+
@webhook_authentication = {user: nil, secret: nil}
|
42
|
+
@chargebee_site = nil
|
43
|
+
@chargebee_api_key = nil
|
44
|
+
@currency = "US Dollars [USD]"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module ChargebeeRails
|
2
|
+
module Customer
|
3
|
+
|
4
|
+
# Subscribe customer to a new subscription in chargebee.
|
5
|
+
# * *Args* :
|
6
|
+
# - +options+ -> the options hash allowed for subscription update in chargebee
|
7
|
+
# For more details on the options hash, refer the input parameters for
|
8
|
+
# https://apidocs.chargebee.com/docs/api/subscriptions?lang=ruby#create_a_subscription
|
9
|
+
# * *Returns* :
|
10
|
+
# - the subscription
|
11
|
+
# * *Raises* :
|
12
|
+
# - +ChargeBee::InvalidRequestError+ -> If subscription options is invalid
|
13
|
+
#
|
14
|
+
def subscribe(options={})
|
15
|
+
SubscriptionBuilder.new(self, options).create
|
16
|
+
end
|
17
|
+
|
18
|
+
# Subscribe customer to a new subscription in chargebee via chargebee's hosted page.
|
19
|
+
# * *Args* :
|
20
|
+
# - +hosted_page+ -> the +hosted_page+ returned by chargebee
|
21
|
+
# The subscription for the customer is created from the +hosted_page+
|
22
|
+
# returned by chargebee. This +hosted_page+ object contains the details
|
23
|
+
# about the subscription in chargebee for the customer. For more on +hosted_page+
|
24
|
+
# https://apidocs.chargebee.com/docs/api/hosted_pages?lang=ruby#checkout_new_subscription
|
25
|
+
# * *Returns* :
|
26
|
+
# - the subscription
|
27
|
+
# * *Raises* :
|
28
|
+
# - +ChargeBee::InvalidRequestError+ -> If +hosted_page+ is invalid
|
29
|
+
#
|
30
|
+
def subscribe_via_hosted_page(hosted_page)
|
31
|
+
HostedPageSubscriptionManager.new(self, hosted_page).create
|
32
|
+
end
|
33
|
+
|
34
|
+
# Subscribe customer to a new subscription in chargebee via chargebee's hosted page.
|
35
|
+
# * *Args* :
|
36
|
+
# - +hosted_page+ -> the +hosted_page+ returned by chargebee
|
37
|
+
# The subscription for the customer is updated from the +hosted_page+
|
38
|
+
# returned by chargebee. This +hosted_page+ object contains the details
|
39
|
+
# about the updated subscription in chargebee for the customer.
|
40
|
+
# * *Returns* :
|
41
|
+
# - the subscription
|
42
|
+
# * *Raises* :
|
43
|
+
# - +ChargeBee::InvalidRequestError+ -> If +hosted_page+ is invalid
|
44
|
+
#
|
45
|
+
def update_subscription_via_hosted_page(hosted_page)
|
46
|
+
HostedPageSubscriptionManager.new(self, hosted_page).update
|
47
|
+
end
|
48
|
+
|
49
|
+
# Update the customer's subscription
|
50
|
+
# * *Args* :
|
51
|
+
# - +options+ -> the options hash allowed for subscription update in chargebee
|
52
|
+
# For more details on the options hash, refer the input parameters for
|
53
|
+
# https://apidocs.chargebee.com/docs/api/subscriptions?lang=ruby#update_a_subscription
|
54
|
+
# * *Returns* :
|
55
|
+
# - the updated subscription
|
56
|
+
# * *Raises* :
|
57
|
+
# - +ChargeBee::InvalidRequestError+ -> If subscription or options is invalid
|
58
|
+
#
|
59
|
+
def update_subscription(options={})
|
60
|
+
SubscriptionBuilder.new(self, options).update
|
61
|
+
end
|
62
|
+
|
63
|
+
# Retrieve the chargebee customer of the subscription owner -
|
64
|
+
# i.e subscription owner as chargebee customer
|
65
|
+
# * *Returns* :
|
66
|
+
# - the chargebee customer
|
67
|
+
# * *Raises* :
|
68
|
+
# - +ChargeBee::InvalidRequestError+ -> If subscription owner is invalid
|
69
|
+
#
|
70
|
+
def as_chargebee_customer
|
71
|
+
ChargeBee::Customer.retrieve(chargebee_id).customer
|
72
|
+
end
|
73
|
+
|
74
|
+
# List all invoices for the subscription owner (customer).
|
75
|
+
# * *Returns* :
|
76
|
+
# - the list of invoices for the customer in chargebee
|
77
|
+
# * *Raises* :
|
78
|
+
# - +ChargeBee::InvalidRequestError+ -> If customer is invalid
|
79
|
+
#
|
80
|
+
def invoices
|
81
|
+
ChargeBee::Invoice.invoices_for_customer(chargebee_id).map(&:invoice)
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# :nodoc: all
|
2
|
+
module ChargebeeRails
|
3
|
+
|
4
|
+
class Error < StandardError
|
5
|
+
attr_reader :original_error
|
6
|
+
|
7
|
+
def initialize(message=nil, original_error=nil)
|
8
|
+
super message
|
9
|
+
@original_error = original_error
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class PlanError < Error
|
14
|
+
# Raise this error when the plan is not present in active_record
|
15
|
+
def plan_not_found
|
16
|
+
"Plan Not Found"
|
17
|
+
end
|
18
|
+
|
19
|
+
# Raise this error when the plan is not setup in ChargeBee
|
20
|
+
def plan_not_configured
|
21
|
+
"Plan Not Configured"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class UnauthorizedError < Error; end
|
26
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
module ChargebeeRails
|
2
|
+
class HostedPageSubscriptionManager
|
3
|
+
|
4
|
+
def initialize(customer, hosted_page)
|
5
|
+
@customer = customer
|
6
|
+
@hosted_page = hosted_page
|
7
|
+
end
|
8
|
+
|
9
|
+
# Create a subscription for the customer in application,
|
10
|
+
# from the subscription details got from chargebee's hosted page
|
11
|
+
def create
|
12
|
+
@customer.update(
|
13
|
+
chargebee_id: hosted_customer.id,
|
14
|
+
chargebee_data: chargebee_customer_data
|
15
|
+
)
|
16
|
+
@subscription = @customer.create_subscription(subscription_attrs)
|
17
|
+
manage_payment_method if hosted_payment_method.present?
|
18
|
+
@subscription
|
19
|
+
end
|
20
|
+
|
21
|
+
# Update the subscription for the customer in application,
|
22
|
+
# from the subscription details got from chargebee's hosted page
|
23
|
+
def update
|
24
|
+
@subscription = @customer.subscription
|
25
|
+
@subscription.update(subscription_attrs)
|
26
|
+
manage_payment_method if hosted_payment_method.present?
|
27
|
+
@subscription
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
# Update payment method for subscrption if one exists or create new one
|
33
|
+
def manage_payment_method
|
34
|
+
@subscription.payment_method.present? &&
|
35
|
+
@subscription.payment_method.update(payment_method_attrs) ||
|
36
|
+
create_payment_method
|
37
|
+
end
|
38
|
+
|
39
|
+
# Create the payment method for the subscription
|
40
|
+
def create_payment_method
|
41
|
+
@subscription.create_payment_method(payment_method_attrs)
|
42
|
+
end
|
43
|
+
|
44
|
+
def hosted_subscription
|
45
|
+
@hosted_subscription ||= @hosted_page.content.subscription
|
46
|
+
end
|
47
|
+
|
48
|
+
def hosted_customer
|
49
|
+
@hosted_customer ||= @hosted_page.content.customer
|
50
|
+
end
|
51
|
+
|
52
|
+
def hosted_payment_method
|
53
|
+
@hosted_payment_method ||= hosted_customer.payment_method
|
54
|
+
end
|
55
|
+
|
56
|
+
def hosted_card
|
57
|
+
@hosted_card ||= @hosted_page.content.card
|
58
|
+
end
|
59
|
+
|
60
|
+
def hosted_billing_address
|
61
|
+
@hosted_billing_address ||= @hosted_customer.billing_address
|
62
|
+
end
|
63
|
+
|
64
|
+
def subscription_attrs
|
65
|
+
{
|
66
|
+
chargebee_id: hosted_subscription.id,
|
67
|
+
status: hosted_subscription.status,
|
68
|
+
plan_quantity: hosted_subscription.plan_quantity,
|
69
|
+
chargebee_data: chargebee_subscription_data,
|
70
|
+
plan: Plan.find_by(plan_id: hosted_subscription.plan_id)
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
def chargebee_subscription_data
|
75
|
+
{
|
76
|
+
trial_ends_at: hosted_subscription.trial_end,
|
77
|
+
next_renewal_at: hosted_subscription.current_term_end,
|
78
|
+
cancelled_at: hosted_subscription.cancelled_at,
|
79
|
+
is_scheduled_for_cancel: (hosted_subscription.status == 'non-renewing' ? true : false),
|
80
|
+
has_scheduled_changes: hosted_subscription.has_scheduled_changes
|
81
|
+
}
|
82
|
+
end
|
83
|
+
|
84
|
+
def chargebee_customer_data
|
85
|
+
{
|
86
|
+
customer_details: customer_details(hosted_customer),
|
87
|
+
billing_address: billing_address(hosted_customer.billing_address)
|
88
|
+
}
|
89
|
+
end
|
90
|
+
|
91
|
+
def customer_details customer
|
92
|
+
{
|
93
|
+
first_name: customer.first_name,
|
94
|
+
last_name: customer.last_name,
|
95
|
+
email: customer.email,
|
96
|
+
company: customer.company,
|
97
|
+
vat_number: customer.vat_number
|
98
|
+
}
|
99
|
+
end
|
100
|
+
|
101
|
+
def billing_address customer_billing_address
|
102
|
+
{
|
103
|
+
first_name: customer_billing_address.first_name,
|
104
|
+
last_name: customer_billing_address.last_name,
|
105
|
+
company: customer_billing_address.company,
|
106
|
+
address_line1: customer_billing_address.line1,
|
107
|
+
address_line2: customer_billing_address.line2,
|
108
|
+
address_line3: customer_billing_address.line3,
|
109
|
+
city: customer_billing_address.city,
|
110
|
+
state: customer_billing_address.state,
|
111
|
+
country: customer_billing_address.country,
|
112
|
+
zip: customer_billing_address.zip
|
113
|
+
} if customer_billing_address.present?
|
114
|
+
end
|
115
|
+
|
116
|
+
def payment_method_attrs
|
117
|
+
if hosted_payment_method.type == 'card'
|
118
|
+
card_last4, card_type = hosted_card.last4, hosted_card.card_type
|
119
|
+
else
|
120
|
+
card_last4, card_type = nil, nil
|
121
|
+
end
|
122
|
+
{
|
123
|
+
cb_customer_id: hosted_customer.id,
|
124
|
+
auto_collection: hosted_customer.auto_collection,
|
125
|
+
payment_type: hosted_payment_method.type,
|
126
|
+
reference_id: hosted_payment_method.reference_id,
|
127
|
+
card_last4: card_last4,
|
128
|
+
card_type: card_type,
|
129
|
+
status: hosted_payment_method.status
|
130
|
+
}
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
end
|