150 lines
6.7 KiB
Ruby
150 lines
6.7 KiB
Ruby
module JamRuby
|
|
class RecurlyTransactionWebHook < ActiveRecord::Base
|
|
|
|
attr_accessible :admin_description, :jam_track_id, as: :admin
|
|
|
|
belongs_to :user, class_name: 'JamRuby::User'
|
|
belongs_to :sale_line_item, class_name: 'JamRuby::SaleLineItem', foreign_key: 'subscription_id', primary_key: 'recurly_subscription_uuid', inverse_of: :recurly_transactions
|
|
belongs_to :sale, class_name: 'JamRuby::Sale', foreign_key: 'invoice_id', primary_key: 'recurly_invoice_id', inverse_of: :recurly_transactions
|
|
|
|
# when we know what JamTrack this refund is related to, we set this value
|
|
belongs_to :jam_track, class_name: 'JamRuby::JamTrack'
|
|
|
|
validates :recurly_transaction_id, presence: true
|
|
validates :action, presence: true
|
|
validates :status, presence: true
|
|
validates :amount_in_cents, numericality: {only_integer: true}
|
|
validates :user, presence: true
|
|
|
|
|
|
SUCCESSFUL_PAYMENT = 'payment'
|
|
FAILED_PAYMENT = 'failed_payment'
|
|
REFUND = 'refund'
|
|
VOID = 'void'
|
|
|
|
|
|
HOOK_TYPES = [SUCCESSFUL_PAYMENT, FAILED_PAYMENT, REFUND, VOID]
|
|
|
|
def is_credit_type?
|
|
transaction_type == REFUND || transaction_type == VOID
|
|
end
|
|
|
|
def is_voided?
|
|
transaction_type == VOID
|
|
end
|
|
|
|
def is_refund?
|
|
transaction_type == REFUND
|
|
end
|
|
|
|
def self.is_transaction_web_hook?(document)
|
|
|
|
return false if document.root.nil?
|
|
case document.root.name
|
|
when 'successful_payment_notification'
|
|
true
|
|
when 'successful_refund_notification'
|
|
true
|
|
when 'failed_payment_notification'
|
|
true
|
|
when 'void_payment_notification'
|
|
true
|
|
else
|
|
false
|
|
end
|
|
end
|
|
|
|
def admin_url
|
|
APP_CONFIG.admin_root_url + "/admin/recurly_hooks/" + id
|
|
end
|
|
|
|
# see spec for examples of XML
|
|
def self.create_from_xml(document)
|
|
|
|
transaction = RecurlyTransactionWebHook.new
|
|
|
|
case document.root.name
|
|
when 'successful_payment_notification'
|
|
transaction.transaction_type = SUCCESSFUL_PAYMENT
|
|
when 'successful_refund_notification'
|
|
transaction.transaction_type = REFUND
|
|
when 'failed_payment_notification'
|
|
transaction.transaction_type = FAILED_PAYMENT
|
|
when 'void_payment_notification'
|
|
transaction.transaction_type = VOID
|
|
else
|
|
raise 'unknown document type ' + document.root.name
|
|
end
|
|
|
|
transaction.recurly_transaction_id = document.at_css('transaction id').content
|
|
transaction.user_id = document.at_css('account account_code').content
|
|
transaction.subscription_id = document.at_css('subscription_id').content
|
|
transaction.invoice_id = document.at_css('invoice_id').content
|
|
transaction.invoice_number_prefix = document.at_css('invoice_number_prefix').content
|
|
transaction.invoice_number = document.at_css('invoice_number').content
|
|
transaction.action = document.at_css('action').content
|
|
transaction.status = document.at_css('status').content
|
|
transaction.transaction_at = Time.parse(document.at_css('date').content)
|
|
transaction.amount_in_cents = document.at_css('amount_in_cents').content
|
|
transaction.reference = document.at_css('reference').content
|
|
transaction.message = document.at_css('message').content
|
|
|
|
transaction.save!
|
|
|
|
# now that we have the transaction saved, we also need to delete the jam_track_right if this is a refund, or voided
|
|
|
|
|
|
if transaction.transaction_type == 'refund' || transaction.transaction_type == 'void'
|
|
sale = Sale.find_by_recurly_invoice_id(transaction.invoice_id)
|
|
|
|
if sale && sale.is_jam_track_sale?
|
|
if sale.sale_line_items.length == 1
|
|
if sale.recurly_total_in_cents == transaction.amount_in_cents
|
|
jam_track = sale.sale_line_items[0].product
|
|
jam_track_right = jam_track.right_for_user(transaction.user) if jam_track
|
|
if jam_track_right
|
|
jam_track_right.destroy
|
|
|
|
# associate which JamTrack we assume this is related to in this one success case
|
|
transaction.jam_track = jam_track
|
|
transaction.save!
|
|
|
|
AdminMailer.recurly_alerts(transaction.user, {
|
|
subject: "NOTICE: #{transaction.user.email} has had JamTrack: #{jam_track.name} revoked",
|
|
body: "A #{transaction.transaction_type} event came from Recurly for sale with Recurly invoice ID #{sale.recurly_invoice_id}. We deleted their right to the track in our own database as a result."
|
|
}).deliver
|
|
else
|
|
AdminMailer.recurly_alerts(transaction.user, {
|
|
subject: "NOTICE: #{transaction.user.email} got a refund, but unable to find JamTrackRight to delete",
|
|
body: "This should just mean the user already has no rights to the JamTrackRight when the refund came in. Not a big deal, but sort of weird..."
|
|
}).deliver
|
|
end
|
|
|
|
else
|
|
AdminMailer.recurly_alerts(transaction.user, {
|
|
subject: "ACTION REQUIRED: #{transaction.user.email} got a refund it was not for total value of a JamTrack sale",
|
|
body: "We received a #{transaction.transaction_type} notice for an amount that was not the same as the original sale. So, no action was taken in the database. sale total: #{sale.recurly_total_in_cents}, refund amount: #{transaction.amount_in_cents}"
|
|
}).deliver
|
|
end
|
|
|
|
|
|
else
|
|
AdminMailer.recurly_alerts(transaction.user, {
|
|
subject: "ACTION REQUIRED: #{transaction.user.email} has refund on invoice with multiple JamTracks",
|
|
body: "You will have to manually revoke any JamTrackRights in our database for the appropriate JamTracks"
|
|
}).deliver
|
|
end
|
|
else
|
|
AdminMailer.recurly_alerts(transaction.user, {
|
|
subject: "ACTION REQUIRED: #{transaction.user.email} has refund with no correlator to sales",
|
|
body: "You will have to manually revoke any JamTrackRights in our database for the appropriate JamTracks"
|
|
}).deliver
|
|
end
|
|
|
|
|
|
end
|
|
transaction
|
|
end
|
|
end
|
|
end
|