lib/active_merchant/billing/gateways/first_giving.rb
require 'nokogiri'
module ActiveMerchant #:nodoc:
module Billing #:nodoc:
class FirstGivingGateway < Gateway
self.test_url = 'http://usapisandbox.fgdev.net'
self.live_url = 'https://api.firstgiving.com'
self.supported_countries = ['US']
self.supported_cardtypes = %i[visa master american_express discover]
self.homepage_url = 'http://www.firstgiving.com/'
self.default_currency = 'USD'
self.display_name = 'FirstGiving'
def initialize(options = {})
requires!(options, :application_key, :security_token, :charity_id)
super
end
def purchase(money, creditcard, options = {})
post = {}
add_invoice(post, options)
add_creditcard(post, creditcard)
add_address(post, options)
add_customer_data(post, options)
add_donation_data(post, money, options)
commit('/donation/creditcard', post)
end
def refund(money, identifier, options = {})
get = {}
get[:transactionId] = identifier
get[:tranType] = 'REFUNDREQUEST'
commit('/transaction/refundrequest?' + encode(get))
end
private
def add_donation_data(post, money, options)
post[:amount] = amount(money)
post[:charityId] = @options[:charity_id]
post[:description] = (options[:description] || 'Purchase')
post[:currencyCode] = (options[:currency] || currency(money))
end
def add_customer_data(post, options)
post[:billToEmail] = (options[:email] || 'activemerchant@example.com')
post[:remoteAddr] = (options[:ip] || '127.0.0.1')
end
def add_address(post, options)
if (billing_address = (options[:billing_address] || options[:address]))
post[:billToAddressLine1] = billing_address[:address1]
post[:billToCity] = billing_address[:city]
post[:billToState] = billing_address[:state]
post[:billToZip] = billing_address[:zip]
post[:billToCountry] = billing_address[:country]
end
end
def add_invoice(post, options)
post[:orderId] = options[:order_id]
end
def add_creditcard(post, creditcard)
post[:billToFirstName] = creditcard.first_name
post[:billToLastName] = creditcard.last_name
post[:ccNumber] = creditcard.number
post[:ccType] = creditcard_brand(creditcard.brand)
post[:ccExpDateMonth] = creditcard.month
post[:ccExpDateYear] = creditcard.year
post[:ccCardValidationNum] = creditcard.verification_value
end
def parse(body)
response = {}
xml = Nokogiri::XML(body)
element = xml.xpath('//firstGivingDonationApi/firstGivingResponse').first
element.attributes.each do |name, attribute|
response[name] = attribute.content
end
element.children.each do |child|
next if child.text?
response[child.name] = child.text
end
response
end
def commit(action, post = nil)
url = (test? ? self.test_url : self.live_url) + action
begin
if post
response = parse(ssl_post(url, post_data(post), headers))
else
response = parse(ssl_get(url, headers))
end
rescue ResponseError => e
response = parse(e.response.body)
end
Response.new(
(response['acknowledgement'] == 'Success'),
(response['friendlyErrorMessage'] || response['verboseErrorMessage'] || response['acknowledgement']),
response,
authorization: response['transactionId'],
test: test?
)
end
def post_data(post)
post.collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join('&')
end
def encode(hash)
hash.collect { |(k, v)| "#{CGI.escape(k.to_s)}=#{CGI.escape(v.to_s)}" }.join('&')
end
def creditcard_brand(brand)
case brand
when 'visa' then 'VI'
when 'master' then 'MC'
when 'discover' then 'DI'
when 'american_express' then 'AX'
else
raise "Unhandled credit card brand #{brand}"
end
end
def headers
{
'User-Agent' => "ActiveMerchantBindings/#{ActiveMerchant::VERSION}",
'JG_APPLICATIONKEY' => @options[:application_key].to_s,
'JG_SECURITYTOKEN' => @options[:security_token].to_s
}
end
end
end
end