lib/active_merchant/billing/gateways/transact_pro.rb
module ActiveMerchant #:nodoc:
module Billing #:nodoc:
# For more information visit {Transact Pro Services}[https://www.transactpro.lv/business/]
#
# This gateway was formerly associated with www.1stpayments.net
#
# Written by Piers Chambers (Varyonic.com)
class TransactProGateway < Gateway
self.test_url = 'https://gw2sandbox.tpro.lv:8443/gw2test/gwprocessor2.php'
self.live_url = 'https://www2.1stpayments.net/gwprocessor2.php'
self.supported_countries = ['US']
self.default_currency = 'USD'
self.money_format = :cents
self.supported_cardtypes = %i[visa master american_express discover]
self.homepage_url = 'https://www.transactpro.lv/business/online-payments-acceptance'
self.display_name = 'Transact Pro'
def initialize(options = {})
requires!(options, :guid, :password, :terminal)
super
end
def purchase(amount, payment, options = {})
post = PostData.new
add_invoice(post, amount, options)
add_payment(post, payment)
add_address(post, payment, options)
add_customer_data(post, options)
add_credentials(post)
post[:rs] = @options[:terminal]
MultiResponse.run do |r|
r.process { commit('init', post) }
r.process do
post = PostData.new
post[:init_transaction_id] = r.authorization
add_payment_cc(post, payment)
post[:f_extended] = '4'
commit('charge', post, amount)
end
end
end
def authorize(amount, payment, options = {})
post = PostData.new
add_invoice(post, amount, options)
add_payment(post, payment)
add_address(post, payment, options)
add_customer_data(post, options)
add_credentials(post)
post[:rs] = @options[:terminal]
MultiResponse.run do |r|
r.process { commit('init_dms', post) }
r.process do
post = PostData.new
post[:init_transaction_id] = r.authorization
add_payment_cc(post, payment)
post[:f_extended] = '4'
commit('make_hold', post, amount)
end
end
end
def capture(amount, authorization, options = {})
identifier, original_amount = split_authorization(authorization)
raise ArgumentError.new("Partial capture is not supported, and #{amount.inspect} != #{original_amount.inspect}") if amount && (amount != original_amount)
post = PostData.new
add_credentials(post)
post[:init_transaction_id] = identifier
post[:f_extended] = '4'
commit('charge_hold', post, original_amount)
end
def refund(amount, authorization, options = {})
identifier, original_amount = split_authorization(authorization)
post = PostData.new
add_credentials(post, :account_guid)
post[:init_transaction_id] = identifier
post[:amount_to_refund] = amount(amount || original_amount)
commit('refund', post)
end
def void(authorization, options = {})
identifier, amount = split_authorization(authorization)
post = PostData.new
add_credentials(post, :account_guid)
post[:init_transaction_id] = identifier
post[:amount_to_refund] = amount(amount)
commit('cancel_dms', post)
end
def verify(credit_card, options = {})
MultiResponse.run(:use_first_response) do |r|
r.process { authorize(100, credit_card, options) }
r.process(:ignore_result) { void(r.authorization, options) }
end
end
private
def add_customer_data(post, options)
post[:email] = (options[:email] || 'noone@example.com')
post[:user_ip] = (options[:ip] || '127.0.0.1')
end
def add_address(post, creditcard, options)
if address = options[:billing_address]
post[:street] = address[:address1].to_s
post[:city] = address[:city].to_s
post[:state] = (address[:state].blank? ? 'NA' : address[:state].to_s)
post[:zip] = address[:zip].to_s
post[:country] = address[:country].to_s
post[:phone] = (address[:phone].to_s.gsub(/[^0-9]/, '') || '0000000')
end
if address = options[:shipping_address]
post[:shipping_name] = "#{address.first_name} #{address.last_name}"
post[:shipping_street] = address[:address1].to_s
post[:shipping_phone] = address[:phone].to_s
post[:shipping_zip] = address[:zip].to_s
post[:shipping_city] = address[:city].to_s
post[:shipping_country] = address[:country].to_s
post[:shipping_state] = (address[:state].blank? ? 'NA' : address[:state].to_s)
post[:shipping_email] = (options[:email] || 'noone@example.com')
end
end
def add_invoice(post, money, options)
post[:merchant_transaction_id] = options[:order_id] if options[:order_id]
post[:amount] = amount(money)
post[:currency] = (options[:currency] || currency(money))
post[:description] = options[:description]
post[:merchant_site_url] = options[:merchant]
end
def add_payment(post, payment)
post[:name_on_card] = "#{payment.first_name} #{payment.last_name}"
post[:card_bin] = payment.first_digits
end
def add_payment_cc(post, credit_card)
post[:cc] = credit_card.number
post[:cvv] = credit_card.verification_value if credit_card.verification_value?
year = sprintf('%.4i', credit_card.year)
month = sprintf('%.2i', credit_card.month)
post[:expire] = "#{month}/#{year[2..3]}"
end
def add_credentials(post, key = :guid)
post[key] = @options[:guid]
post[:pwd] = Digest::SHA1.hexdigest(@options[:password])
end
def parse(body)
if /^ID:/.match?(body)
body.split('~').reduce(Hash.new) { |h, v|
m = v.match('(.*?):(.*)')
h.merge!(m[1].underscore.to_sym => m[2])
}
elsif (m = body.match('(.*?):(.*)'))
m[1] == 'OK' ?
{ status: 'success', id: m[2] } :
{ status: 'failure', message: m[2] }
else
{ status: body }
end
end
def commit(action, parameters, amount = nil)
url = (test? ? test_url : live_url)
response = parse(ssl_post(url, post_data(action, parameters)))
Response.new(
success_from(response),
message_from(response),
response,
authorization: authorization_from(parameters, response, amount),
test: test?
)
end
def authorization_from(parameters, response, amount)
identifier = (response[:id] || parameters[:init_transaction_id])
authorization = [identifier]
authorization << amount if amount
authorization.join('|')
end
def split_authorization(authorization)
if /|/.match?(authorization)
identifier, amount = authorization.split('|')
[identifier, amount.to_i]
else
authorization
end
end
def success_from(response)
(response[:status] =~ /success/i || response[:status] =~ /ok/i)
end
def message_from(response)
(response[:message] || response[:status])
end
def post_data(action, parameters = {})
parameters[:a] = action
parameters.to_s
end
end
end
end