Skip to content

Commit

Permalink
Added support for Elavon gateway.
Browse files Browse the repository at this point in the history
  • Loading branch information
Jesse Storimer authored and jamesmacaulay committed Aug 20, 2009
1 parent 2c5832f commit 90f5bbd
Show file tree
Hide file tree
Showing 7 changed files with 357 additions and 13 deletions.
1 change: 1 addition & 0 deletions CHANGELOG
@@ -1,6 +1,7 @@
= ActiveMerchant CHANGELOG

* Fix typo preventing OgoneGateway from working in production [Nicolas Jacobeus]
* Add support for the Elavon MyVirtualMerchant gateway [jstorimer]
* Fix recurring transactions in Ogone gateway [cody]
* Fix money formatting for Ogone gateway [cody]
* Tweak Ogone gateway to use ActiveMerchant conventions for reference transactions [cody, jstorimer]
Expand Down
4 changes: 4 additions & 0 deletions CONTRIBUTERS
Expand Up @@ -112,3 +112,7 @@ FirstPay (July 24, 2009)
Ogone (July 20, 2009)

* Nicolas Jacobeus

Elavon (August 09, 2009)

* Jesse Storimer
106 changes: 106 additions & 0 deletions lib/active_merchant/billing/gateways/elavon.rb
@@ -0,0 +1,106 @@
require File.dirname(__FILE__) + '/viaklix'

module ActiveMerchant #:nodoc:
module Billing #:nodoc:
# = Elavon Virtual Merchant Gateway
#
# == Example use:
#
# gateway = ActiveMerchant::Billing::ElavonGateway.new(
# :login => "my_virtual_merchant_id",
# :password => "my_virtual_merchant_pin",
# :user => "my_virtual_merchant_user_id" # optional
# )
#
# # set up credit card obj as in main ActiveMerchant example
# creditcard = ActiveMerchant::Billing::CreditCard.new(
# :type => 'visa',
# :number => '41111111111111111',
# :month => 10,
# :year => 2011,
# :first_name => 'Bob',
# :last_name => 'Bobsen'
# )
#
# # run request
# response = gateway.purchase(1000, creditcard) # authorize and capture 10 USD
#
# puts response.success? # Check whether the transaction was successful
# puts response.message # Retrieve the message returned by Elavon
# puts response.authorization # Retrieve the unique transaction ID returned by Elavon
#
class ElavonGateway < ViaklixGateway
self.test_url = self.live_url = 'https://www.myvirtualmerchant.com/VirtualMerchant/process.do'

self.display_name = 'Elavon MyVirtualMerchant'
self.supported_countries = ['US', 'CA']
self.supported_cardtypes = [:visa, :master, :american_express, :discover]
self.homepage_url = 'http://www.elavon.com/'

self.delimiter = "\n"
self.actions = {
:purchase => 'CCSALE',
:credit => 'CCCREDIT',
:authorize => 'CCAUTHONLY',
:capture => 'CCFORCE'
}

# Authorize a credit card for a given amount.
#
# ==== Parameters
# * <tt>money</tt> - The amount to be authorized. Either an Integer value in cents or a Money object.
# * <tt>credit_card</tt> - The CreditCard details for the transaction.
# * <tt>options</tt>
# * <tt>:billing_address</tt> - The billing address for the cardholder.
def authorize(money, creditcard, options = {})
form = {}
add_invoice(form, options)
add_creditcard(form, creditcard)
add_address(form, options)
add_customer_data(form, options)
commit(:authorize, money, form)
end

# Capture authorized funds from a credit card.
#
# ==== Parameters
# * <tt>money</tt> - The amount to be captured. Either an Integer value in cents or a Money object.
# * <tt>authorization</tt> - The approval code returned from the initial authorization.
# * <tt>options</tt>
# * <tt>:credit_card</tt> - The CreditCard details from the initial transaction (required).
def capture(money, authorization, options = {})
requires!(options, :credit_card)

form = {}
add_reference(form, authorization)
add_invoice(form, options)
add_creditcard(form, options[:credit_card])
add_customer_data(form, options)
commit(:capture, money, form)
end

private
def add_reference(form, authorization)
form[:approval_code] = authorization
end

def authorization_from(response)
response['approval_code']
end

def add_verification_value(form, creditcard)
form[:cvv2cvc2] = creditcard.verification_value
form[:cvv2cvc2_indicator] = '1'
end

def message_from(response)
success?(response) ? response['result_message'] : response['errorMessage']
end

def success?(response)
!response.has_key?('errorMessage')
end
end
end
end

50 changes: 37 additions & 13 deletions lib/active_merchant/billing/gateways/viaklix.rb
@@ -1,8 +1,16 @@
module ActiveMerchant #:nodoc:
module Billing #:nodoc:
class ViaklixGateway < Gateway
TEST_URL = 'https://demo.viaklix.com/process.asp'
LIVE_URL = 'https://www.viaklix.com/process.asp'
class_inheritable_accessor :test_url, :live_url, :delimiter, :actions

self.test_url = 'https://demo.viaklix.com/process.asp'
self.live_url = 'https://www.viaklix.com/process.asp'
self.delimiter = "\r\n"

self.actions = {
:purchase => 'SALE',
:credit => 'CREDIT'
}

APPROVED = '0'

Expand Down Expand Up @@ -35,7 +43,7 @@ def purchase(money, creditcard, options = {})
add_creditcard(form, creditcard)
add_address(form, options)
add_customer_data(form, options)
commit('SALE', money, form)
commit(:purchase, money, form)
end

# Make a credit to a card (Void can only be done from the virtual terminal)
Expand All @@ -50,7 +58,7 @@ def credit(money, creditcard, options = {})
add_creditcard(form, creditcard)
add_address(form, options)
add_customer_data(form, options)
commit('CREDIT', money, form)
commit(:credit, money, form)
end

private
Expand Down Expand Up @@ -104,41 +112,57 @@ def add_creditcard(form, creditcard)
form[:exp_date] = expdate(creditcard)

if creditcard.verification_value?
form[:cvv2cvc2] = creditcard.verification_value
form[:cvv2] = 'present'
add_verification_value(form, creditcard)
end

form[:first_name] = creditcard.first_name.to_s.slice(0, 20)
form[:last_name] = creditcard.last_name.to_s.slice(0, 30)
end

def add_verification_value(form, creditcard)
form[:cvv2cvc2] = creditcard.verification_value
form[:cvv2] = 'present'
end

def preamble
result = {
'merchant_id' => @options[:login],
'pin' => @options[:password],
'show_form' => 'false',
'test_mode' => @options[:test] ? 'TRUE' : 'FALSE',
'test_mode' => test? ? 'TRUE' : 'FALSE',
'result_format' => 'ASCII',
}

result['user_id'] = @options[:user] unless @options[:user].blank?
result
end

def test?
@options[:test] || super
end

def commit(action, money, parameters)
parameters[:amount] = amount(money)
parameters[:transaction_type] = action
parameters[:transaction_type] = self.actions[action]

response = parse( ssl_post(test? ? TEST_URL : LIVE_URL, post_data(parameters)) )
response = parse( ssl_post(test? ? self.test_url : self.live_url, post_data(parameters)) )

Response.new(response['result'] == APPROVED, response['result_message'], response,
Response.new(response['result'] == APPROVED, message_from(response), response,
:test => @options[:test] || test?,
:authorization => response['txn_id'],
:authorization => authorization_from(response),
:avs_result => { :code => response['avs_response'] },
:cvv_result => response['cvv2_response']
)
end

def authorization_from(response)
response['txn_id']
end

def message_from(response)
response['result_message']
end

def post_data(parameters)
result = preamble
result.merge!(parameters)
Expand All @@ -154,9 +178,9 @@ def expdate(creditcard)
# Parse the response message
def parse(msg)
resp = {}
msg.split("\r\n").collect{|li|
msg.split(self.delimiter).collect{|li|
key, value = li.split("=")
resp[key.gsub(/^ssl_/, '')] = value.to_s.strip
resp[key.strip.gsub(/^ssl_/, '')] = value.to_s.strip
}
resp
end
Expand Down
4 changes: 4 additions & 0 deletions test/fixtures.yml
Expand Up @@ -44,6 +44,10 @@ efsnet:
login: X
password: Y

elavon:
login: LOGIN
password: PASSWORD

# Working credentials, no need to replace
eway:
login: '87654321'
Expand Down
66 changes: 66 additions & 0 deletions test/remote/gateways/remote_elavon_test.rb
@@ -0,0 +1,66 @@
require 'test_helper'

class RemoteElavonTest < Test::Unit::TestCase
def setup
@gateway = ElavonGateway.new(fixtures(:elavon))

@credit_card = credit_card
@bad_credit_card = credit_card('invalid')

@options = {
:email => "paul@domain.com",
:description => 'Test Transaction',
:billing_address => address
}
@amount = 100
end

def test_successful_purchase
assert response = @gateway.purchase(@amount, @credit_card, @options)

assert_success response
assert response.test?
assert_equal 'APPROVED', response.message
assert response.authorization
end

def test_unsuccessful_purchase
assert response = @gateway.purchase(@amount, @bad_credit_card, @options)

assert_failure response
assert response.test?
assert_equal 'The Credit Card Number supplied in the authorization request appears to be invalid.', response.message
end

def test_authorize_and_capture
assert auth = @gateway.authorize(@amount, @credit_card, @options)
assert_success auth
assert_equal 'APPROVED', auth.message
assert auth.authorization
assert capture = @gateway.capture(@amount, auth.authorization, :credit_card => @credit_card)
assert_success capture
end

def test_unsuccessful_capture
assert response = @gateway.capture(@amount, '', :credit_card => @credit_card)
assert_failure response
assert_equal 'The FORCE Approval Code supplied in the authorization request appears to be invalid or blank. The FORCE Approval Code must be 6 or less alphanumeric characters.', response.message
end

def test_unsuccessful_authorization
@credit_card.number = "1234567890123"
assert response = @gateway.authorize(@amount, @credit_card, @options)
assert_failure response
assert_equal 'The Credit Card Number supplied in the authorization request appears to be invalid.', response.message
end

def test_purchase_and_credit
assert purchase = @gateway.purchase(@amount, @credit_card, @options)
assert_success purchase
assert purchase.authorization

assert credit = @gateway.credit(@amount, @credit_card, @options)
assert_success credit
assert credit.authorization
end
end

0 comments on commit 90f5bbd

Please sign in to comment.