Skip to content

Instantly share code, notes, and snippets.

@matthodan
Created July 21, 2010 16:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save matthodan/484715 to your computer and use it in GitHub Desktop.
Save matthodan/484715 to your computer and use it in GitHub Desktop.
module ActiveMerchant #:nodoc:
module Billing #:nodoc:
class PaypalGateway < Gateway
RECURRING_ACTIONS = Set.new([:add, :cancel, :inquiry, :suspend])
@@API_VERSION = '50.0'
def recurring(money, credit_card, options = {})
options[:name] = credit_card.name if options[:name].blank? && credit_card
request = build_recurring_request(options[:profile_id] ? :modify : :add, money, options) do |xml|
add_credit_card(xml, credit_card, options[:billing_address], options) if credit_card
end
commit('CreateRecurringPaymentsProfile', request)
end
# cancels an existing recurring profile
def cancel_recurring(profile_id)
request = build_recurring_request(:cancel, 0, :profile_id => profile_id) {}
commit('ManageRecurringPaymentsProfileStatus', request)
end
# retrieves information about a recurring profile
def recurring_inquiry(profile_id, options = {})
request = build_recurring_request(:inquiry, nil, options.update( :profile_id => profile_id ))
commit('GetRecurringPaymentsProfileDetails', request)
end
# suspends a recurring profile
def suspend_recurring(profile_id)
request = build_recurring_request(:suspend, 0, :profile_id => profile_id) {}
commit('ManageRecurringPaymentsProfileStatus', request)
end
private
def build_recurring_request(action, money, options)
unless RECURRING_ACTIONS.include?(action)
raise StandardError, "Invalid Recurring Profile Action: #{action}"
end
xml = Builder::XmlMarkup.new :indent => 2
ns2 = 'n2:'
if [:add].include?(action)
xml.tag! 'CreateRecurringPaymentsProfileReq', 'xmlns' => PAYPAL_NAMESPACE do
xml.tag! 'CreateRecurringPaymentsProfileRequest' do
xml.tag! 'Version', @@API_VERSION, 'xmlns' => EBAY_NAMESPACE
# NOTE: namespace prefix here is critical!
xml.tag! ns2 + 'CreateRecurringPaymentsProfileRequestDetails ', 'xmlns:n2' => EBAY_NAMESPACE do
# credit card and other information goes here
yield xml
xml.tag! ns2 + 'RecurringPaymentsProfileDetails' do
xml.tag! ns2 + 'BillingStartDate', options[:starting_at]
end
xml.tag! ns2 + 'ScheduleDetails' do
xml.tag! ns2 + 'Description', options[:comment]
unless options[:trial_payment].nil?
xml.tag! ns2 + 'TrialPeriod' do
xml.tag! ns2 + 'BillingPeriod', 'Month'
xml.tag! ns2 + 'BillingFrequency', 1
xml.tag! ns2 + 'TotalBillingCycles', 1
xml.tag! ns2 + 'Amount', amount(options[:trial_payment]), 'currencyID' => options[:currency] || currency(options[:trial_payment])
end
end
unless options[:one_time_payment].nil?
xml.tag! ns2 + 'ActivationDetails' do
xml.tag! ns2 + 'InitialAmount', amount(options[:one_time_payment]), 'currencyID' => options[:currency] || currency(options[:one_time_payment])
end
end
frequency, period = get_pay_period(options)
xml.tag! ns2 + 'PaymentPeriod' do
xml.tag! ns2 + 'BillingPeriod', period
xml.tag! ns2 + 'BillingFrequency', frequency.to_s
xml.tag! ns2 + 'TotalBillingCycles', options[:payments] unless options[:payments].nil? || options[:payments] == 0
xml.tag! ns2 + 'Amount', amount(money), 'currencyID' => options[:currency] || currency(money)
end
xml.tag! ns2 + 'AutoBillOutstandingAmount', 'AddToNextBilling'
end
end
end
end
elsif [:cancel, :suspend].include?(action)
xml.tag! 'ManageRecurringPaymentsProfileStatusReq', 'xmlns' => PAYPAL_NAMESPACE do
xml.tag! 'ManageRecurringPaymentsProfileStatusRequest', 'xmlns:n2' => EBAY_NAMESPACE do
xml.tag! ns2 + 'Version', @@API_VERSION
xml.tag! ns2 + 'ManageRecurringPaymentsProfileStatusRequestDetails' do
xml.tag! 'ProfileID', options[:profile_id]
xml.tag! ns2 + 'Action', action == :cancel ? 'Cancel' : 'Suspend'
xml.tag! ns2 + 'Note', 'Canceling the action, no real comment here'
end
end
end
elsif [:inquiry].include?(action)
xml.tag! 'GetRecurringPaymentsProfileDetailsReq', 'xmlns' => PAYPAL_NAMESPACE do
xml.tag! 'GetRecurringPaymentsProfileDetailsRequest', 'xmlns:n2' => EBAY_NAMESPACE do
xml.tag! ns2 + 'Version', @@API_VERSION
xml.tag! 'ProfileID', options[:profile_id]
end
end
end
end
def get_pay_period(options)
requires!(options, [:periodicity, :bimonthly, :monthly, :biweekly, :weekly, :yearly, :daily, :semimonthly, :quadweekly, :quarterly, :semiyearly])
case options[:periodicity]
when :weekly then [1, 'Week']
when :biweekly then [2, 'Week']
when :semimonthly then [1, 'SemiMonth']
when :quadweekly then [4, 'Week']
when :monthly then [1, 'Month']
when :quarterly then [3, 'Month']
when :semiyearly then [6, 'Month'] # broken! i think
when :yearly then [1, 'Year']
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment