chargebee_rails 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|