jam-cloud/ruby/lib/jam_ruby/recurly_client.rb

751 lines
29 KiB
Ruby
Raw Normal View History

require 'recurly'
module JamRuby
class RecurlyClient
def initialize()
@log = Logging.logger[self]
end
2015-03-20 13:48:00 +00:00
def create_account(current_user, billing_info)
options = account_hash(current_user, billing_info)
account = nil
begin
#puts "Recurly.api_key: #{Recurly.api_key}"
account = Recurly::Account.create(options)
2020-11-21 22:14:37 +00:00
if account.errors.any?
puts "Errors encountered while creating account: #{account.errors}"
raise RecurlyClientError.new(account.errors) if account.errors.any?
end
rescue Recurly::Error, NoMethodError => x
raise RecurlyClientError, x.to_s
else
if account
current_user.update_attribute(:recurly_code, account.account_code)
end
end
account
end
def has_account?(current_user)
account = get_account(current_user)
!!account
end
def delete_account(current_user)
account = get_account(current_user)
2020-11-21 22:14:37 +00:00
if account
begin
account.destroy
rescue Recurly::Error, NoMethodError => x
raise RecurlyClientError, x.to_s
end
else
raise RecurlyClientError, "Could not find account to delete."
end
account
end
2020-11-30 00:24:28 +00:00
def update_desired_subscription(current_user, plan_code)
subscription = nil
account = nil
current_user.desired_plan_code = plan_code
current_user.desired_plan_code_set_at = DateTime.now
current_user.save(validate: false)
puts "updating desired subscription for #{current_user.email} to #{plan_code}"
account = get_account(current_user)
if account
if plan_code.nil? || plan_code == ''
begin
# user wants a free subscription. If they have a subscription, let's cancel it.
subscription, account = find_subscription(current_user, account)
if subscription
puts "Canceling user's #{current_user.email} subscription"
subscription.cancel
# upon cancelation, take the user's current monthly payment plan
subscription = Recurly::Subscription.find(subscription.uuid)
current_user.subscription_plan_code = get_highest_plan(subscription)
current_user.subscription_plan_code_set_at = DateTime.now
current_user.save(validate: false)
2020-11-30 00:24:28 +00:00
# do not delete the recurly_subscription_id ; we'll use that to try and reactivate later if they user re-activates their account
else
# if no subscription and past trial, you goin down -- because there must have never been payment??
if current_user.subscription_trial_ended?
current_user.subscription_plan_code = nil
current_user.subscription_plan_code_set_at = DateTime.now
current_user.save(validate: false)
end
end
# do not set the subscription _plan_code either; because the user has paid through the month; they still
# get their old plan
#current_user.subscription_plan_code = nil
#current_user.save(validate: false)
rescue => e
puts "Could not cancel subscription for user #{current_user.email}. #{e}"
return false, subscription, account
end
else
# user wants to pay. let's get it goin
return handle_create_subscription(current_user, plan_code, account)
end
end
return true, subscription, account
end
def get_account(current_user)
2021-01-04 13:40:49 +00:00
begin
account = current_user && current_user.recurly_code ? Recurly::Account.find(current_user.recurly_code) : nil
rescue Recurly::Error => x
puts "Swallow find acct for user #{current_user.email} error initial #{x}"
end
2020-11-21 22:14:37 +00:00
# check again, assuming account_code is the user ID (can happen in error scenarios where we create the account
# on recurly, but couldn't save the account_code to the user.recurly_code field)
2020-11-30 00:24:28 +00:00
puts "get_account for #{current_user.email} found #{account}"
2020-11-21 22:14:37 +00:00
if !account
2020-11-30 00:24:28 +00:00
begin
account = Recurly::Account.find(current_user.id)
rescue Recurly::Error => x
2021-01-04 13:40:49 +00:00
puts "Swallow find acct for user #{current_user.email} error #{x}"
2020-11-30 00:24:28 +00:00
end
2020-11-21 22:14:37 +00:00
# repair user local account info
if !account.nil?
current_user.update_attribute(:recurly_code, account.account_code)
end
end
account
2015-03-20 21:15:13 +00:00
rescue Recurly::Error => x
raise RecurlyClientError, x.to_s
end
2020-11-21 22:14:37 +00:00
def update_account(current_user, billing_info=nil)
account = get_account(current_user)
if(account.present?)
options = account_hash(current_user, billing_info)
begin
account.update_attributes(options)
rescue Recurly::Error, NoMethodError => x
raise RecurlyClientError, x.to_s
end
end
account
end
2020-11-30 00:24:28 +00:00
def list_invoices(account)
invoices = []
count = 0
account.invoices.find_each do |invoice|
count = count + 1
invoices << invoice
if count == 50
break
end
end
invoices
end
def payment_history(current_user, params ={})
limit = params[:limit]
limit ||= 20
limit = limit.to_i
2020-11-30 00:24:28 +00:00
cursor = params[:cursor]
payments = []
account = get_account(current_user)
if(account.present?)
begin
2020-11-30 00:24:28 +00:00
account.transactions.paginate(per_page:limit, cursor:cursor).each do |transaction|
# XXX this isn't correct because we create 0 dollar transactions too (for free stuff)
#if transaction.amount_in_cents > 0 # Account creation adds a transaction record
payments << {
:created_at => transaction.created_at,
:amount_in_cents => transaction.amount_in_cents,
2020-11-30 00:24:28 +00:00
:tax_in_cents=> transaction.tax_in_cents,
:status => transaction.status,
2020-11-30 00:24:28 +00:00
:action => transaction.action,
:payment_method => transaction.payment_method,
:reference => transaction.reference,
2020-11-30 00:24:28 +00:00
:currency => transaction.currency
}
#end
end
rescue Recurly::Error, NoMethodError => x
2020-11-30 00:24:28 +00:00
puts "Recurly error #{current_user.email} #{x}"
raise RecurlyClientError, x.to_s
end
end
payments
end
2020-11-30 00:24:28 +00:00
def invoice_history(current_user, params ={})
limit = params[:limit]
limit ||= 20
limit = limit.to_i
cursor = params[:cursor]
payments = []
account = get_account(current_user)
if(account.present?)
begin
account.invoices.paginate(per_page:limit, cursor:cursor).each do |invoice|
# XXX this isn't correct because we create 0 dollar transactions too (for free stuff)
#if transaction.amount_in_cents > 0 # Account creation adds a transaction record
payments << {
:created_at => invoice.created_at,
:subtotal_in_cents => invoice.subtotal_in_cents,
:tax_in_cents=> invoice.tax_in_cents,
:total_in_cents => invoice.total_in_cents,
:state => invoice.state,
:description => invoice.line_items.map(&:description).join(", "),
:currency => invoice.currency
}
#end
end
rescue Recurly::Error, NoMethodError => x
puts "Recurly error #{current_user.email} #{x}"
raise RecurlyClientError, x.to_s
end
end
return payments, account
end
2020-11-21 22:14:37 +00:00
def update_billing_info(current_user, billing_info=nil, account = nil)
account = get_account(current_user) if account.nil?
if account.present?
begin
2015-03-20 13:48:00 +00:00
account.billing_info = billing_info
account.billing_info.save
rescue Recurly::Error, NoMethodError => x
raise RecurlyClientError, x.to_s
end
raise RecurlyClientError.new(account.errors) if account.errors.any?
else
raise RecurlyClientError, "Could not find account to update billing info."
end
account
end
2020-11-21 22:14:37 +00:00
# token was created in the web ui. we can tell recurly to update the billing info on the account with just the token
def update_billing_info_from_token(current_user, account, recurly_token)
account.billing_info = {
token_id: recurly_token
}
account.billing_info.save!
end
def refund_user_subscription(current_user, jam_track)
jam_track_right=JamRuby::JamTrackRight.where("user_id=? AND jam_track_id=?", current_user.id, jam_track.id).first
if jam_track_right
refund_subscription(jam_track_right)
else
raise RecurlyClientError, "The user #{current_user} does not have a subscription to #{jam_track}"
end
end
def refund_subscription(jam_track_right)
account = get_account(jam_track_right.user)
if (account.present?)
terminated = false
begin
jam_track = jam_track_right.jam_track
account.subscriptions.find_each do |subscription|
2015-03-04 22:31:03 +00:00
#puts "subscription.plan.plan_code: #{subscription.plan.plan_code} / #{jam_track.plan_code} / #{subscription.plan.plan_code == jam_track.plan_code}"
if(subscription.plan.plan_code == jam_track.plan_code)
subscription.terminate(:full)
raise RecurlyClientError.new(subscription.errors) if subscription.errors.any?
terminated = true
end
end
if terminated
jam_track_right.destroy()
else
raise RecurlyClientError, "Subscription '#{jam_track.plan_code}' not found for this user; could not issue refund."
end
rescue Recurly::Error, NoMethodError => x
raise RecurlyClientError, x.to_s
end
else
raise RecurlyClientError, "Could not find account to refund order."
end
account
end
2015-03-09 14:44:12 +00:00
def find_jam_track_plan(jam_track)
plan = nil
begin
plan = Recurly::Plan.find(jam_track.plan_code)
rescue Recurly::Resource::NotFound
end
plan
end
def create_jam_track_plan(jam_track)
plan = Recurly::Plan.create(accounting_code: "",
bypass_hosted_confirmation: false,
cancel_url: nil,
description: jam_track.description,
display_donation_amounts: false,
display_phone_number: false,
display_quantity: false,
name: "JamTrack: #{jam_track.name}",
payment_page_css: nil,
payment_page_tos_link: nil,
plan_code: jam_track.plan_code,
plan_interval_length: 1,
plan_interval_unit: "months",
setup_fee_in_cents: Recurly::Money.new(:USD => 0), # <Recurly::Money USD: 0_00>
success_url: "",
tax_exempt: false,
total_billing_cycles: 1,
trial_interval_length: 0,
trial_interval_unit: "days",
unit_amount_in_cents: Recurly::Money.new(:USD => 1_99),
unit_name: "unit"
)
raise RecurlyClientError.new(plan.errors) if plan.errors.any?
end
def get_pending_plan_code(subscription)
if subscription && subscription.pending_subscription
return subscription.pending_subscription.plan.plan_code
else
return nil
end
end
def get_highest_plan(subscription)
SubscriptionDefinitions.higher_plan(subscription.plan.plan_code, get_pending_plan_code(subscription))
end
2020-11-30 00:24:28 +00:00
def handle_create_subscription(current_user, plan_code, account)
begin
subscription = create_subscription(current_user, plan_code, account, current_user.subscription_trial_ended? ? nil : current_user.subscription_trial_ends_at)
current_user.recurly_subscription_id = subscription.uuid
current_user.first_subscribed_at = Time.now if current_user.first_subscribed_at.nil?
current_user.first_subscribed_plan_code = plan_code if current_user.first_subscribed_plan_code.nil?
2020-11-30 00:24:28 +00:00
if current_user.subscription_trial_ended?
current_user.subscription_plan_code = get_highest_plan(subscription)
2020-11-30 00:24:28 +00:00
current_user.subscription_plan_code_set_at = DateTime.now
else
# we could force a platinum plan since the user has put forward payment already, even in trial
puts "user #{current_user.email} is in trial"
if plan_code == SubscriptionDefinitions::JAM_PLATINUM || plan_code == SubscriptionDefinitions::JAM_PLATINUM_YEARLY
puts "user #{current_user.email} is in trial and buying platinum ; upgrade them already"
current_user.subscription_plan_code = plan_code
current_user.subscription_plan_code_set_at = DateTime.now
else
current_user.subscription_plan_code = SubscriptionDefinitions::JAM_GOLD
current_user.subscription_plan_code_set_at = DateTime.now
end
end
2021-02-21 21:07:31 +00:00
current_user.reset_playtime
2020-11-30 00:24:28 +00:00
current_user.save(validate: false)
rescue => e
puts "Could not create subscription for user #{current_user.email}. #{e}"
return false, subscription, account
end
return true, subscription, account
end
2020-10-09 22:22:20 +00:00
# https://dev.recurly.com/docs/create-subscription
2020-11-30 00:24:28 +00:00
def create_subscription(user, plan_code, account, starts_at = nil)
old_subscription_id = user.recurly_subscription_id
if old_subscription_id
# first, let's try to reactivate it
old_subscription = Recurly::Subscription.find(old_subscription_id)
begin
old_subscription.reactivate
puts "reactivated plan! Let's check if it needs changing"
#if plan_code != old_subscription.plan.plan_code
2020-11-30 00:24:28 +00:00
result = old_subscription.update_attributes(
:plan_code => plan_code,
:timeframe => starts_at.nil? ? 'bill_date' : 'now'
)
# end
# fetch it again. because it's got staleness after update_attributes operation
return Recurly::Subscription.find(old_subscription_id)
2020-11-30 00:24:28 +00:00
rescue => e
puts "Unable to reactivate/update old plan #{e}"
user.update_attribute(:recurly_subscription_id, nil)
end
end
if account.billing_info
puts "Creating subscription for #{user.email} with plan_code #{plan_code}"
subscription = Recurly::Subscription.create(
:plan_code => plan_code,
:currency => 'USD',
:customer_notes => 'Thank you for your business!',
:account => {
:account_code => account.account_code
},
:starts_at => starts_at,
:auto_renew => true
)
subscription
else
puts "User has no billing info; not trying to create a subscription #{user.email}"
end
2020-10-09 22:22:20 +00:00
subscription
end
2020-11-30 00:24:28 +00:00
def find_subscription(user, fed_account = nil)
2020-11-21 22:14:37 +00:00
subscription = nil
2020-11-30 00:24:28 +00:00
account = nil
if fed_account.nil?
account = get_account(user)
else
account = fed_account
end
2020-11-21 22:14:37 +00:00
2021-01-06 03:45:35 +00:00
# first try to find the current subscription. If it's gone, delete our state. If expired, delete our state.
if user.recurly_subscription_id
begin
subscription = Recurly::Subscription.find(user.recurly_subscription_id)
rescue Recurly::Resource::NotFound
puts "subscription is gone. delete it!"
user.update_attribute(:recurly_subscription_id, nil)
user.recurly_subscription_id = nil
subscription = nil
end
puts "Subscription state: #{subscription.state}"
if subscription.state == 'expired'
puts "subscription is expired. stop tracking it!"
user.update_attribute(:recurly_subscription_id, nil)
user.recurly_subscription_id = nil
subscription = nil
end
end
2020-10-09 22:22:20 +00:00
if user.recurly_subscription_id.nil?
2020-11-21 22:14:37 +00:00
if account
2020-11-30 00:24:28 +00:00
active_subscription = nil
2020-11-21 22:14:37 +00:00
account.subscriptions.find_each do |subscription|
2020-11-30 00:24:28 +00:00
puts "Subscription: #{subscription.inspect} #{subscription.state}"
2021-01-06 03:45:35 +00:00
if subscription.state == "active" || subscription.state == "future"
2020-11-30 00:24:28 +00:00
active_subscription = subscription
break
end
2020-11-21 22:14:37 +00:00
end
2020-11-30 00:24:28 +00:00
subscription = active_subscription
2020-11-21 22:14:37 +00:00
else
puts "can't find subscription for account #{account}"
end
end
2020-11-30 00:24:28 +00:00
if subscription && user.recurly_subscription_id.nil?
2020-11-21 22:14:37 +00:00
puts "Repairing subscription ID on account"
2021-01-06 03:45:35 +00:00
user.update_attribute(:recurly_subscription_id, subscription.uuid)
user.update_attribute(:first_subscribed_plan_code, subscription.plan.plan_code)
2021-01-06 03:45:35 +00:00
user.recurly_subscription_id = subscription.uuid
user.first_subscribed_at = Time.now if user.first_subscribed_at.nil?
2020-10-09 22:22:20 +00:00
end
2020-11-21 22:14:37 +00:00
2020-11-30 00:24:28 +00:00
return [subscription, account]
2020-10-09 22:22:20 +00:00
end
2020-11-21 22:14:37 +00:00
def change_subscription_plan(current_user, plan_code)
2020-11-30 00:24:28 +00:00
subscription, account = find_subscription(current_user)
2020-11-21 22:14:37 +00:00
if subscription.nil?
puts "no subscription found for user #{current_user.email}"
return false
end
puts "subscription.plan #{subscription.plan}"
if subscription.plan.plan_code == plan_code
puts "plan code was the same as requested: #{plan_code}"
return false
end
result = subscription.update_attributes(
:plan_code => plan_code,
:timeframe => 'bill_date'
)
puts "change subscription plan #{result}"
return result
end
2020-10-09 22:22:20 +00:00
def sync_subscription(user)
2020-11-30 00:24:28 +00:00
begin
# edge case: admin controlled
if user.admin_override_plan_code
2020-12-05 18:16:38 +00:00
# check if it's expired first...
if Time.now > user.admin_override_ends_at.to_time
puts "admin control expired. clear override and set Free plan"
user.admin_override_plan_code = nil
# logic below will catch this
#user.subscription_plan_code = nil
user.admin_override_ends_at = nil
user.subscription_sync_code = 'undo_admin_control'
user.subscription_sync_msg = "admin control expired. clear override and set Free plan"
user.subscription_last_checked_at = Time.now
user.save(validate: false)
# don't return; let this fall through to next states
else
puts "admin controlled plan #{user.email}"
user.subscription_plan_code = user.admin_override_plan_code
user.subscription_plan_code_set_at = Time.now
user.subscription_last_checked_at = Time.now
user.subscription_sync_code = 'admin_control'
user.subscription_sync_msg = "admin override - plan_code set to #{user.admin_override_plan_code}"
user.save(validate: false)
return
end
2020-11-30 00:24:28 +00:00
end
# edge case: user is in a licensed school
if user.has_active_license?
puts "user has school license #{user.email}"
user.subscription_plan_code = SubscriptionDefinitions::JAM_PLATINUM
user.subscription_plan_code_set_at = DateTime.now
user.subscription_last_checked_at = DateTime.now
user.subscription_sync_code = 'school_license'
user.subscription_sync_msg = "has school license - plan_code set to #{SubscriptionDefinitions::JAM_PLATINUM}"
user.save(validate: false)
return
end
# if user is in trial still, not much book-keeping
if !user.subscription_trial_ended?
puts "user has a trial still #{user.email}"
# there is actually nothing to do, because we don't start billing for any plan until trial is over.
user.subscription_last_checked_at = DateTime.now
user.subscription_sync_code = 'in_trial'
user.subscription_sync_msg = "trial still active - plan_code not altered"
user.save(validate: false)
return
end
# if there is no recurly action here, then they must be coming off of a trial and we have to mark them down
if user.recurly_code.nil? && !user.subscription_plan_code.nil?
puts "new user #{user.email} has no payment info and is ending their trial"
# TODO: send email
2020-10-09 22:22:20 +00:00
user.subscription_plan_code = nil
2020-11-30 00:24:28 +00:00
user.subscription_plan_code_set_at = DateTime.now
user.subscription_last_checked_at = DateTime.now
user.subscription_sync_code = 'trial_ended'
user.subscription_sync_msg = "trial ended and no subscription set - plan_code set to Free"
user.save(validate: false)
return
end
account = get_account(user)
if account.nil?
2020-12-05 18:16:38 +00:00
puts "Account is nil? #{user.email}. Strange. Could happen in some weird admin messing around scenarios"
2020-11-30 00:24:28 +00:00
user.subscription_last_checked_at = DateTime.now
user.save(validate: false)
user.subscription_sync_code = 'no_recurly_account'
user.subscription_sync_msg = "user has no recurly account - plan_code not altered"
2020-12-05 18:16:38 +00:00
user.save(validate: false)
2020-11-30 00:24:28 +00:00
return
end
user.is_past_due = account.has_past_due_invoice
subscription, account = find_subscription(user, account)
if subscription
user.recurly_subscription_state = subscription.state
else
2020-10-09 22:22:20 +00:00
user.recurly_subscription_state = nil
end
2020-11-30 00:24:28 +00:00
if subscription.nil? || subscription.state == 'expired'
puts "user has expired or no plan"
user.subscription_plan_code = nil
user.subscription_plan_code_set_at = DateTime.now
user.subscription_sync_code = 'no_subscription_or_expired'
user.subscription_sync_msg = "user has no or expired subscription - plan_code set to Free"
else
if user.is_past_due
if !user.subscription_plan_code.nil?
puts "user #{user.email} has a past due plan. We gotta bring them down"
user.subscription_plan_code = nil
user.subscription_plan_code_set_at = DateTime.now
user.subscription_sync_code = 'is_past_due_changed'
user.subscription_sync_msg = "payment has gone past due - plan_code set to Free"
else
puts "user is past due and #{user.email} had no changes"
user.subscription_sync_code = 'is_past_due_unchanged'
user.subscription_sync_msg = "payment has gone past due, plan_code not altered because already set to free"
end
else
2021-01-08 04:39:09 +00:00
if user.subscription_plan_code != user.desired_plan_code
2020-11-30 00:24:28 +00:00
puts "they are back! get them back into their desired plan #{user.email}"
2021-01-11 18:15:15 +00:00
if !SubscriptionDefinitions.is_downgrade(user.desired_plan_code, user.subscription_plan_code)
2021-02-21 21:07:31 +00:00
user.reset_playtime
2021-01-11 18:15:15 +00:00
user.subscription_plan_code = user.desired_plan_code
user.subscription_plan_code_set_at = DateTime.now
user.subscription_sync_code = 'good_standing_repaired'
user.subscription_sync_msg = "user is in good standing but desired != effective; plan_code set to #{user.desired_plan_code}"
else
#user.subscription_plan_code = user.desired_plan_code
#user.subscription_plan_code_set_at = DateTime.now
user.subscription_sync_code = 'good_standing_ignored'
user.subscription_sync_msg = "user is in good standing but the desired plan is less than subscription plan; plan_code not touched"
end
2020-11-30 00:24:28 +00:00
else
puts "good standing user #{user.email} had no changes"
user.subscription_sync_code = 'good_standing_unchanged'
user.subscription_sync_msg = "user is in good standing but already set correctly; plan_code not altered"
end
end
2020-10-09 22:22:20 +00:00
end
2020-11-30 00:24:28 +00:00
user.subscription_last_checked_at = DateTime.now
user.save(validate: false)
rescue => e
puts "Unexpected error in sync_subscription for user #{user.email}"
puts e.message
user.subscription_last_checked_at = DateTime.now
user.subscription_sync_code = 'failed_sync'
user.subscription_sync_msg = e.message
user.save(validate: false)
2020-10-09 22:22:20 +00:00
end
2020-11-30 00:24:28 +00:00
2020-10-09 22:22:20 +00:00
end
def sync_transactions(options = {})
ActiveRecord::Base.transaction do
2021-03-14 21:23:43 +00:00
options.merge!({ sort: :updated_at, state: :successful, per_page: 200 })
latest_seen = nil
Recurly::Transaction.find_each(options) do |transaction |
if AffiliateDistribution.find_by_external_id(transaction.uuid)
2021-03-16 20:23:56 +00:00
# this is now a normal path, because we will pick up the last transaction we saw, since we use
# the last transaction time to feed `latest_seen`.
#begin
# Bugsnag.notify("ActiveRecord::RecordNotUnique: duplicate affiliate_distribution for Recurly transaction uuid #{transaction.uuid} was prevented from been added.")
#rescue => exception
# Rails.logger.error(exception) unless Rails.env.test?
#end
next
end
2021-03-16 13:35:47 +00:00
# advance the time last seen in the transactions.
if latest_seen.nil? || latest_seen < transaction.created_at.to_time
latest_seen = transaction.created_at.to_time
end
# these next lines try to ascertain that the transaction we've hit describes a true subscription
# jamtrack transactions are handled entirely separately, so this should avoid those, and perhaps other 'odd'
# transactions in Recurly
2021-03-16 18:34:50 +00:00
next if transaction.action != 'purchase' || transaction.status != 'success' || transaction.source != 'subscription'
next if transaction.subscriptions.length == 0
subscription = transaction.subscriptions.first
next if subscription.plan == nil || subscription.plan.plan_code == nil
account = transaction.details["account"]
user = User.find(account.account_code)
affiliate_partner = user.affiliate_referral
if !affiliate_partner.nil? && affiliate_partner.created_within_affiliate_window(user, transaction.created_at.to_time)
affiliate_distribution = AffiliateDistribution.new
affiliate_distribution.product_type = "Subscription"
affiliate_distribution.affiliate_referral = affiliate_partner
2021-03-16 15:09:55 +00:00
fee_in_cents = (transaction.amount_in_cents - transaction.tax_in_cents) * affiliate_partner.rate
affiliate_distribution.affiliate_referral_fee_in_cents = fee_in_cents
affiliate_distribution.created_at = transaction.created_at.to_time
affiliate_distribution.product_code = subscription.plan.plan_code
affiliate_distribution.external_id = transaction.uuid #external_id is a unique column. should raises error if duplicates
affiliate_distribution.save!
end
end
2021-03-14 21:23:43 +00:00
# only grab the latest time as seen in the data; that way, we should never skip really recent entries if
if !latest_seen.nil?
GenericState.singleton.update_attribute(:recurly_transactions_last_sync_at, latest_seen)
end
end
end
2020-11-21 22:14:37 +00:00
def find_or_create_account(current_user, billing_info, recurly_token = nil)
account = get_account(current_user)
2020-11-21 22:14:37 +00:00
if !account
account = create_account(current_user, billing_info)
2020-11-21 22:14:37 +00:00
elsif !billing_info.nil?
update_billing_info(current_user, billing_info, account)
end
if !recurly_token.nil?
update_billing_info_from_token(current_user, account, recurly_token)
end
account
end
private
def account_hash(current_user, billing_info)
options = {
account_code: current_user.id,
email: current_user.email,
first_name: current_user.first_name,
last_name: current_user.last_name,
address: {
city: current_user.city,
state: current_user.state,
country: current_user.country
}
}
options[:billing_info] = billing_info if billing_info
options
end
end # class
class RecurlyClientError < Exception
attr_accessor :errors
def initialize(data)
if data.respond_to?('has_key?')
self.errors = data
else
self.errors = {:message=>data.to_s}
end
end # initialize
def to_s
s=super
s << ", errors: #{errors.inspect}" if self.errors.any?
s
end
end # RecurlyClientError
end # module