johnreitano-activemerchant 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +508 -0
- data/CONTRIBUTORS +134 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +136 -0
- data/gem-public_cert.pem +20 -0
- data/lib/active_merchant/billing/avs_result.rb +98 -0
- data/lib/active_merchant/billing/base.rb +57 -0
- data/lib/active_merchant/billing/check.rb +68 -0
- data/lib/active_merchant/billing/credit_card.rb +159 -0
- data/lib/active_merchant/billing/credit_card_formatting.rb +21 -0
- data/lib/active_merchant/billing/credit_card_methods.rb +125 -0
- data/lib/active_merchant/billing/cvv_result.rb +38 -0
- data/lib/active_merchant/billing/expiry_date.rb +34 -0
- data/lib/active_merchant/billing/gateway.rb +163 -0
- data/lib/active_merchant/billing/gateways/authorize_net.rb +654 -0
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +736 -0
- data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +244 -0
- data/lib/active_merchant/billing/gateways/beanstream.rb +102 -0
- data/lib/active_merchant/billing/gateways/beanstream_interac.rb +54 -0
- data/lib/active_merchant/billing/gateways/bogus.rb +98 -0
- data/lib/active_merchant/billing/gateways/braintree.rb +17 -0
- data/lib/active_merchant/billing/gateways/card_stream.rb +230 -0
- data/lib/active_merchant/billing/gateways/cyber_source.rb +594 -0
- data/lib/active_merchant/billing/gateways/data_cash.rb +593 -0
- data/lib/active_merchant/billing/gateways/efsnet.rb +229 -0
- data/lib/active_merchant/billing/gateways/elavon.rb +134 -0
- data/lib/active_merchant/billing/gateways/eway.rb +277 -0
- data/lib/active_merchant/billing/gateways/exact.rb +222 -0
- data/lib/active_merchant/billing/gateways/first_pay.rb +172 -0
- data/lib/active_merchant/billing/gateways/instapay.rb +164 -0
- data/lib/active_merchant/billing/gateways/jetpay.rb +270 -0
- data/lib/active_merchant/billing/gateways/linkpoint.rb +449 -0
- data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +154 -0
- data/lib/active_merchant/billing/gateways/merchant_ware.rb +283 -0
- data/lib/active_merchant/billing/gateways/modern_payments.rb +36 -0
- data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +220 -0
- data/lib/active_merchant/billing/gateways/moneris.rb +205 -0
- data/lib/active_merchant/billing/gateways/net_registry.rb +189 -0
- data/lib/active_merchant/billing/gateways/netbilling.rb +168 -0
- data/lib/active_merchant/billing/gateways/ogone.rb +279 -0
- data/lib/active_merchant/billing/gateways/pay_junction.rb +392 -0
- data/lib/active_merchant/billing/gateways/pay_secure.rb +120 -0
- data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +207 -0
- data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +39 -0
- data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +13 -0
- data/lib/active_merchant/billing/gateways/payflow.rb +236 -0
- data/lib/active_merchant/billing/gateways/payflow_express.rb +138 -0
- data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +15 -0
- data/lib/active_merchant/billing/gateways/payflow_uk.rb +21 -0
- data/lib/active_merchant/billing/gateways/payment_express.rb +230 -0
- data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +326 -0
- data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +38 -0
- data/lib/active_merchant/billing/gateways/paypal.rb +121 -0
- data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
- data/lib/active_merchant/billing/gateways/paypal_express.rb +130 -0
- data/lib/active_merchant/billing/gateways/paypal_express_common.rb +20 -0
- data/lib/active_merchant/billing/gateways/plugnpay.rb +292 -0
- data/lib/active_merchant/billing/gateways/psigate.rb +214 -0
- data/lib/active_merchant/billing/gateways/psl_card.rb +304 -0
- data/lib/active_merchant/billing/gateways/quickpay.rb +213 -0
- data/lib/active_merchant/billing/gateways/realex.rb +200 -0
- data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +88 -0
- data/lib/active_merchant/billing/gateways/sage/sage_core.rb +116 -0
- data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +97 -0
- data/lib/active_merchant/billing/gateways/sage.rb +146 -0
- data/lib/active_merchant/billing/gateways/sage_pay.rb +309 -0
- data/lib/active_merchant/billing/gateways/sallie_mae.rb +144 -0
- data/lib/active_merchant/billing/gateways/secure_pay.rb +31 -0
- data/lib/active_merchant/billing/gateways/secure_pay_au.rb +157 -0
- data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +113 -0
- data/lib/active_merchant/billing/gateways/skip_jack.rb +453 -0
- data/lib/active_merchant/billing/gateways/smart_ps.rb +265 -0
- data/lib/active_merchant/billing/gateways/trans_first.rb +127 -0
- data/lib/active_merchant/billing/gateways/transax.rb +25 -0
- data/lib/active_merchant/billing/gateways/trust_commerce.rb +418 -0
- data/lib/active_merchant/billing/gateways/usa_epay.rb +194 -0
- data/lib/active_merchant/billing/gateways/verifi.rb +228 -0
- data/lib/active_merchant/billing/gateways/viaklix.rb +189 -0
- data/lib/active_merchant/billing/gateways/wirecard.rb +318 -0
- data/lib/active_merchant/billing/gateways.rb +18 -0
- data/lib/active_merchant/billing/integrations/action_view_helper.rb +79 -0
- data/lib/active_merchant/billing/integrations/bogus/helper.rb +17 -0
- data/lib/active_merchant/billing/integrations/bogus/notification.rb +11 -0
- data/lib/active_merchant/billing/integrations/bogus/return.rb +10 -0
- data/lib/active_merchant/billing/integrations/bogus.rb +23 -0
- data/lib/active_merchant/billing/integrations/chronopay/helper.rb +120 -0
- data/lib/active_merchant/billing/integrations/chronopay/notification.rb +158 -0
- data/lib/active_merchant/billing/integrations/chronopay/return.rb +10 -0
- data/lib/active_merchant/billing/integrations/chronopay.rb +23 -0
- data/lib/active_merchant/billing/integrations/gestpay/common.rb +42 -0
- data/lib/active_merchant/billing/integrations/gestpay/helper.rb +70 -0
- data/lib/active_merchant/billing/integrations/gestpay/notification.rb +85 -0
- data/lib/active_merchant/billing/integrations/gestpay/return.rb +10 -0
- data/lib/active_merchant/billing/integrations/gestpay.rb +25 -0
- data/lib/active_merchant/billing/integrations/helper.rb +93 -0
- data/lib/active_merchant/billing/integrations/hi_trust/helper.rb +58 -0
- data/lib/active_merchant/billing/integrations/hi_trust/notification.rb +59 -0
- data/lib/active_merchant/billing/integrations/hi_trust/return.rb +67 -0
- data/lib/active_merchant/billing/integrations/hi_trust.rb +27 -0
- data/lib/active_merchant/billing/integrations/nochex/helper.rb +68 -0
- data/lib/active_merchant/billing/integrations/nochex/notification.rb +94 -0
- data/lib/active_merchant/billing/integrations/nochex/return.rb +10 -0
- data/lib/active_merchant/billing/integrations/nochex.rb +88 -0
- data/lib/active_merchant/billing/integrations/notification.rb +62 -0
- data/lib/active_merchant/billing/integrations/paypal/helper.rb +119 -0
- data/lib/active_merchant/billing/integrations/paypal/notification.rb +154 -0
- data/lib/active_merchant/billing/integrations/paypal/return.rb +10 -0
- data/lib/active_merchant/billing/integrations/paypal.rb +39 -0
- data/lib/active_merchant/billing/integrations/quickpay/helper.rb +72 -0
- data/lib/active_merchant/billing/integrations/quickpay/notification.rb +74 -0
- data/lib/active_merchant/billing/integrations/quickpay.rb +17 -0
- data/lib/active_merchant/billing/integrations/return.rb +35 -0
- data/lib/active_merchant/billing/integrations/two_checkout/helper.rb +59 -0
- data/lib/active_merchant/billing/integrations/two_checkout/notification.rb +114 -0
- data/lib/active_merchant/billing/integrations/two_checkout/return.rb +17 -0
- data/lib/active_merchant/billing/integrations/two_checkout.rb +23 -0
- data/lib/active_merchant/billing/integrations.rb +29 -0
- data/lib/active_merchant/billing/response.rb +32 -0
- data/lib/active_merchant/billing.rb +9 -0
- data/lib/active_merchant/lib/connection.rb +170 -0
- data/lib/active_merchant/lib/country.rb +319 -0
- data/lib/active_merchant/lib/error.rb +4 -0
- data/lib/active_merchant/lib/post_data.rb +22 -0
- data/lib/active_merchant/lib/posts_data.rb +47 -0
- data/lib/active_merchant/lib/requires_parameters.rb +16 -0
- data/lib/active_merchant/lib/utils.rb +18 -0
- data/lib/active_merchant/lib/validateable.rb +76 -0
- data/lib/active_merchant.rb +46 -0
- data/lib/certs/cacert.pem +7815 -0
- data/lib/support/gateway_support.rb +58 -0
- metadata +218 -0
@@ -0,0 +1,229 @@
|
|
1
|
+
require 'rexml/document'
|
2
|
+
|
3
|
+
module ActiveMerchant #:nodoc:
|
4
|
+
module Billing #:nodoc:
|
5
|
+
|
6
|
+
class EfsnetGateway < Gateway
|
7
|
+
self.supported_countries = ['US']
|
8
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :discover]
|
9
|
+
self.homepage_url = 'http://www.concordefsnet.com/'
|
10
|
+
self.display_name = 'Efsnet'
|
11
|
+
|
12
|
+
TEST_URL = 'https://testefsnet.concordebiz.com/efsnet.dll'
|
13
|
+
LIVE_URL = 'https://efsnet.concordebiz.com/efsnet.dll'
|
14
|
+
|
15
|
+
# login is your Store ID
|
16
|
+
# password is your Store Key
|
17
|
+
def initialize(options = {})
|
18
|
+
requires!(options, :login, :password)
|
19
|
+
@options = options
|
20
|
+
super
|
21
|
+
end
|
22
|
+
|
23
|
+
def test?
|
24
|
+
@options[:test] || super
|
25
|
+
end
|
26
|
+
|
27
|
+
def authorize(money, creditcard, options = {})
|
28
|
+
request = build_credit_card_request(money, creditcard, options)
|
29
|
+
commit(:credit_card_authorize, request)
|
30
|
+
end
|
31
|
+
|
32
|
+
def purchase(money, creditcard, options = {})
|
33
|
+
request = build_credit_card_request(money, creditcard, options)
|
34
|
+
commit(:credit_card_charge, request)
|
35
|
+
end
|
36
|
+
|
37
|
+
def capture(money, identification, options = {})
|
38
|
+
request = build_refund_or_settle_request(money, identification, options)
|
39
|
+
commit(:credit_card_settle, request)
|
40
|
+
end
|
41
|
+
|
42
|
+
def credit(money, identification_or_credit_card, options = {})
|
43
|
+
if identification_or_credit_card.is_a?(String)
|
44
|
+
# Perform authorization reversal
|
45
|
+
request = build_refund_or_settle_request(money, identification_or_credit_card, options)
|
46
|
+
commit(:credit_card_refund, request)
|
47
|
+
else
|
48
|
+
# Perform credit
|
49
|
+
request = build_credit_card_request(money, identification_or_credit_card, options)
|
50
|
+
commit(:credit_card_credit, request)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def void(identification, options = {})
|
55
|
+
requires!(options, :order_id)
|
56
|
+
original_transaction_id, original_transaction_amount = identification.split(";")
|
57
|
+
commit(:void_transaction, {:reference_number => format_reference_number(options[:order_id]), :transaction_ID => original_transaction_id})
|
58
|
+
end
|
59
|
+
|
60
|
+
def voice_authorize(money, authorization_code, creditcard, options = {})
|
61
|
+
options[:authorization_number] = authorization_code
|
62
|
+
request = build_credit_card_request(money, creditcard, options)
|
63
|
+
commit(:credit_card_voice_authorize, request)
|
64
|
+
end
|
65
|
+
|
66
|
+
def force(money, authorization_code, creditcard, options = {})
|
67
|
+
options[:authorization_number] = authorization_code
|
68
|
+
request = build_credit_card_request(money, creditcard, options)
|
69
|
+
commit(:credit_card_capture, request)
|
70
|
+
end
|
71
|
+
|
72
|
+
def system_check
|
73
|
+
commit(:system_check, {})
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def build_refund_or_settle_request(money, identification, options = {})
|
79
|
+
original_transaction_id, original_transaction_amount = identification.split(";")
|
80
|
+
|
81
|
+
requires!(options, :order_id)
|
82
|
+
|
83
|
+
post = {
|
84
|
+
:reference_number => format_reference_number(options[:order_id]),
|
85
|
+
:transaction_amount => amount(money),
|
86
|
+
:original_transaction_amount => original_transaction_amount,
|
87
|
+
:original_transaction_ID => original_transaction_id,
|
88
|
+
:client_ip_address => options[:ip]
|
89
|
+
}
|
90
|
+
end
|
91
|
+
|
92
|
+
def build_credit_card_request(money, creditcard, options = {})
|
93
|
+
requires!(options, :order_id)
|
94
|
+
|
95
|
+
post = {
|
96
|
+
:reference_number => format_reference_number(options[:order_id]),
|
97
|
+
:authorization_number => options[:authorization_number],
|
98
|
+
:transaction_amount => amount(money),
|
99
|
+
:client_ip_address => options[:ip]
|
100
|
+
|
101
|
+
}
|
102
|
+
add_creditcard(post,creditcard)
|
103
|
+
add_address(post,options)
|
104
|
+
post
|
105
|
+
end
|
106
|
+
|
107
|
+
def format_reference_number(number)
|
108
|
+
number.to_s.slice(0,12)
|
109
|
+
end
|
110
|
+
|
111
|
+
def add_address(post,options)
|
112
|
+
if address = options[:billing_address] || options[:address]
|
113
|
+
if address[:address2]
|
114
|
+
post[:billing_address] = address[:address1].to_s << ' ' << address[:address2].to_s
|
115
|
+
else
|
116
|
+
post[:billing_address] = address[:address1].to_s
|
117
|
+
end
|
118
|
+
post[:billing_city] = address[:city].to_s
|
119
|
+
post[:billing_state] = address[:state].blank? ? 'n/a' : address[:state]
|
120
|
+
post[:billing_postal_code] = address[:zip].to_s
|
121
|
+
post[:billing_country] = address[:country].to_s
|
122
|
+
end
|
123
|
+
|
124
|
+
if address = options[:shipping_address]
|
125
|
+
if address[:address2]
|
126
|
+
post[:shipping_address] = address[:address1].to_s << ' ' << address[:address2].to_s
|
127
|
+
else
|
128
|
+
post[:shipping_address] = address[:address1].to_s
|
129
|
+
end
|
130
|
+
post[:shipping_city] = address[:city].to_s
|
131
|
+
post[:shipping_state] = address[:state].blank? ? 'n/a' : address[:state]
|
132
|
+
post[:shipping_postal_code] = address[:zip].to_s
|
133
|
+
post[:shipping_country] = address[:country].to_s
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def add_creditcard(post, creditcard)
|
138
|
+
post[:billing_name] = creditcard.name if creditcard.name
|
139
|
+
post[:account_number] = creditcard.number
|
140
|
+
post[:card_verification_value] = creditcard.verification_value if creditcard.verification_value?
|
141
|
+
post[:expiration_month] = sprintf("%.2i", creditcard.month)
|
142
|
+
post[:expiration_year] = sprintf("%.4i", creditcard.year)[-2..-1]
|
143
|
+
end
|
144
|
+
|
145
|
+
|
146
|
+
def commit(action, parameters)
|
147
|
+
response = parse(ssl_post(test? ? TEST_URL : LIVE_URL, post_data(action, parameters), 'Content-Type' => 'text/xml'))
|
148
|
+
|
149
|
+
Response.new(success?(response), message_from(response[:result_message]), response,
|
150
|
+
:test => test?,
|
151
|
+
:authorization => authorization_from(response, parameters),
|
152
|
+
:avs_result => { :code => response[:avs_response_code] },
|
153
|
+
:cvv_result => response[:cvv_response_code]
|
154
|
+
)
|
155
|
+
end
|
156
|
+
|
157
|
+
def success?(response)
|
158
|
+
response[:response_code] == '0'
|
159
|
+
end
|
160
|
+
|
161
|
+
def authorization_from(response, params)
|
162
|
+
[ response[:transaction_id], params[:transaction_amount] ].compact.join(';')
|
163
|
+
end
|
164
|
+
|
165
|
+
def parse(xml)
|
166
|
+
response = {}
|
167
|
+
|
168
|
+
xml = REXML::Document.new(xml)
|
169
|
+
|
170
|
+
xml.elements.each('//Reply//TransactionReply/*') do |node|
|
171
|
+
|
172
|
+
response[node.name.underscore.to_sym] = normalize(node.text)
|
173
|
+
|
174
|
+
end unless xml.root.nil?
|
175
|
+
|
176
|
+
response
|
177
|
+
end
|
178
|
+
|
179
|
+
def post_data(action, parameters = {})
|
180
|
+
xml = REXML::Document.new("<?xml version='1.0' encoding='UTF-8'?>")
|
181
|
+
root = xml.add_element("Request")
|
182
|
+
root.attributes["StoreID"] = options[:login]
|
183
|
+
root.attributes["StoreKey"] = options[:password]
|
184
|
+
root.attributes["ApplicationID"] = 'ot 1.0'
|
185
|
+
transaction = root.add_element(action.to_s.camelize)
|
186
|
+
|
187
|
+
actions[action].each do |key|
|
188
|
+
transaction.add_element(key.to_s.camelize).text = parameters[key] unless parameters[key].blank?
|
189
|
+
end
|
190
|
+
|
191
|
+
xml.to_s
|
192
|
+
end
|
193
|
+
|
194
|
+
def message_from(message)
|
195
|
+
return 'Unspecified error' if message.blank?
|
196
|
+
message.gsub(/[^\w]/, ' ').split.join(" ").capitalize
|
197
|
+
end
|
198
|
+
|
199
|
+
# Make a ruby type out of the response string
|
200
|
+
def normalize(field)
|
201
|
+
case field
|
202
|
+
when "true" then true
|
203
|
+
when "false" then false
|
204
|
+
when "" then nil
|
205
|
+
when "null" then nil
|
206
|
+
else field
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def actions
|
211
|
+
ACTIONS
|
212
|
+
end
|
213
|
+
|
214
|
+
CREDIT_CARD_FIELDS = [:authorization_number, :client_ip_address, :billing_address, :billing_city, :billing_state, :billing_postal_code, :billing_country, :billing_name, :card_verification_value, :expiration_month, :expiration_year, :reference_number, :transaction_amount, :account_number ]
|
215
|
+
|
216
|
+
ACTIONS = {
|
217
|
+
:credit_card_authorize => CREDIT_CARD_FIELDS,
|
218
|
+
:credit_card_charge => CREDIT_CARD_FIELDS,
|
219
|
+
:credit_card_voice_authorize => CREDIT_CARD_FIELDS,
|
220
|
+
:credit_card_capture => CREDIT_CARD_FIELDS,
|
221
|
+
:credit_card_credit => CREDIT_CARD_FIELDS << :original_transaction_amount,
|
222
|
+
:credit_card_refund => [:reference_number, :transaction_amount, :original_transaction_amount, :original_transaction_ID, :client_ip_address],
|
223
|
+
:void_transaction => [:reference_number, :transaction_ID],
|
224
|
+
:credit_card_settle => [:reference_number, :transaction_amount, :original_transaction_amount, :original_transaction_ID, :client_ip_address],
|
225
|
+
:system_check => [:system_check],
|
226
|
+
}
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/viaklix'
|
2
|
+
|
3
|
+
module ActiveMerchant #:nodoc:
|
4
|
+
module Billing #:nodoc:
|
5
|
+
# = Elavon Virtual Merchant Gateway
|
6
|
+
#
|
7
|
+
# == Example use:
|
8
|
+
#
|
9
|
+
# gateway = ActiveMerchant::Billing::ElavonGateway.new(
|
10
|
+
# :login => "my_virtual_merchant_id",
|
11
|
+
# :password => "my_virtual_merchant_pin",
|
12
|
+
# :user => "my_virtual_merchant_user_id" # optional
|
13
|
+
# )
|
14
|
+
#
|
15
|
+
# # set up credit card obj as in main ActiveMerchant example
|
16
|
+
# creditcard = ActiveMerchant::Billing::CreditCard.new(
|
17
|
+
# :type => 'visa',
|
18
|
+
# :number => '41111111111111111',
|
19
|
+
# :month => 10,
|
20
|
+
# :year => 2011,
|
21
|
+
# :first_name => 'Bob',
|
22
|
+
# :last_name => 'Bobsen'
|
23
|
+
# )
|
24
|
+
#
|
25
|
+
# # run request
|
26
|
+
# response = gateway.purchase(1000, creditcard) # authorize and capture 10 USD
|
27
|
+
#
|
28
|
+
# puts response.success? # Check whether the transaction was successful
|
29
|
+
# puts response.message # Retrieve the message returned by Elavon
|
30
|
+
# puts response.authorization # Retrieve the unique transaction ID returned by Elavon
|
31
|
+
#
|
32
|
+
class ElavonGateway < ViaklixGateway
|
33
|
+
self.test_url = self.live_url = 'https://www.myvirtualmerchant.com/VirtualMerchant/process.do'
|
34
|
+
|
35
|
+
self.display_name = 'Elavon MyVirtualMerchant'
|
36
|
+
self.supported_countries = ['US', 'CA']
|
37
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :discover]
|
38
|
+
self.homepage_url = 'http://www.elavon.com/'
|
39
|
+
|
40
|
+
self.delimiter = "\n"
|
41
|
+
self.actions = {
|
42
|
+
:purchase => 'CCSALE',
|
43
|
+
:credit => 'CCCREDIT',
|
44
|
+
:authorize => 'CCAUTHONLY',
|
45
|
+
:capture => 'CCFORCE'
|
46
|
+
}
|
47
|
+
|
48
|
+
# Authorize a credit card for a given amount.
|
49
|
+
#
|
50
|
+
# ==== Parameters
|
51
|
+
# * <tt>money</tt> - The amount to be authorized as an Integer value in cents.
|
52
|
+
# * <tt>credit_card</tt> - The CreditCard details for the transaction.
|
53
|
+
# * <tt>options</tt>
|
54
|
+
# * <tt>:billing_address</tt> - The billing address for the cardholder.
|
55
|
+
def authorize(money, creditcard, options = {})
|
56
|
+
form = {}
|
57
|
+
add_invoice(form, options)
|
58
|
+
add_creditcard(form, creditcard)
|
59
|
+
add_address(form, options)
|
60
|
+
add_customer_data(form, options)
|
61
|
+
commit(:authorize, money, form)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Capture authorized funds from a credit card.
|
65
|
+
#
|
66
|
+
# ==== Parameters
|
67
|
+
# * <tt>money</tt> - The amount to be captured as an Integer value in cents.
|
68
|
+
# * <tt>authorization</tt> - The approval code returned from the initial authorization.
|
69
|
+
# * <tt>options</tt>
|
70
|
+
# * <tt>:credit_card</tt> - The CreditCard details from the initial transaction (required).
|
71
|
+
def capture(money, authorization, options = {})
|
72
|
+
requires!(options, :credit_card)
|
73
|
+
|
74
|
+
form = {}
|
75
|
+
add_reference(form, authorization)
|
76
|
+
add_invoice(form, options)
|
77
|
+
add_creditcard(form, options[:credit_card])
|
78
|
+
add_customer_data(form, options)
|
79
|
+
commit(:capture, money, form)
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
def add_reference(form, authorization)
|
84
|
+
form[:approval_code] = authorization
|
85
|
+
end
|
86
|
+
|
87
|
+
def authorization_from(response)
|
88
|
+
response['approval_code']
|
89
|
+
end
|
90
|
+
|
91
|
+
def add_verification_value(form, creditcard)
|
92
|
+
form[:cvv2cvc2] = creditcard.verification_value
|
93
|
+
form[:cvv2cvc2_indicator] = '1'
|
94
|
+
end
|
95
|
+
|
96
|
+
def add_address(form,options)
|
97
|
+
billing_address = options[:billing_address] || options[:address]
|
98
|
+
|
99
|
+
if billing_address
|
100
|
+
form[:avs_address] = billing_address[:address1].to_s.slice(0, 30)
|
101
|
+
form[:address2] = billing_address[:address2].to_s.slice(0, 30)
|
102
|
+
form[:avs_zip] = billing_address[:zip].to_s.slice(0, 10)
|
103
|
+
form[:city] = billing_address[:city].to_s.slice(0, 30)
|
104
|
+
form[:state] = billing_address[:state].to_s.slice(0, 10)
|
105
|
+
form[:company] = billing_address[:company].to_s.slice(0, 50)
|
106
|
+
form[:phone] = billing_address[:phone].to_s.slice(0, 20)
|
107
|
+
form[:country] = billing_address[:country].to_s.slice(0, 50)
|
108
|
+
end
|
109
|
+
|
110
|
+
if shipping_address = options[:shipping_address]
|
111
|
+
first_name, last_name = parse_first_and_last_name(shipping_address[:name])
|
112
|
+
form[:ship_to_first_name] = first_name.to_s.slice(0, 20)
|
113
|
+
form[:ship_to_last_name] = last_name.to_s.slice(0, 30)
|
114
|
+
form[:ship_to_address1] = shipping_address[:address1].to_s.slice(0, 30)
|
115
|
+
form[:ship_to_address2] = shipping_address[:address2].to_s.slice(0, 30)
|
116
|
+
form[:ship_to_city] = shipping_address[:city].to_s.slice(0, 30)
|
117
|
+
form[:ship_to_state] = shipping_address[:state].to_s.slice(0, 10)
|
118
|
+
form[:ship_to_company] = shipping_address[:company].to_s.slice(0, 50)
|
119
|
+
form[:ship_to_country] = shipping_address[:country].to_s.slice(0, 50)
|
120
|
+
form[:ship_to_zip] = shipping_address[:zip].to_s.slice(0, 10)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def message_from(response)
|
125
|
+
success?(response) ? response['result_message'] : response['errorMessage']
|
126
|
+
end
|
127
|
+
|
128
|
+
def success?(response)
|
129
|
+
!response.has_key?('errorMessage')
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
@@ -0,0 +1,277 @@
|
|
1
|
+
require 'rexml/document'
|
2
|
+
|
3
|
+
module ActiveMerchant #:nodoc:
|
4
|
+
module Billing #:nodoc:
|
5
|
+
# First, make sure you have everything setup correctly and all of your dependencies in place with:
|
6
|
+
#
|
7
|
+
# require 'rubygems'
|
8
|
+
# require 'active_merchant'
|
9
|
+
#
|
10
|
+
# ActiveMerchant expects the amounts to be given as an Integer in cents. In this case, $10 US becomes 1000.
|
11
|
+
#
|
12
|
+
# tendollar = 1000
|
13
|
+
#
|
14
|
+
# Next, create a credit card object using a TC approved test card.
|
15
|
+
#
|
16
|
+
# creditcard = ActiveMerchant::Billing::CreditCard.new(
|
17
|
+
# :number => '4111111111111111',
|
18
|
+
# :month => 8,
|
19
|
+
# :year => 2006,
|
20
|
+
# :first_name => 'Longbob',
|
21
|
+
# :last_name => 'Longsen'
|
22
|
+
# )
|
23
|
+
# options = {
|
24
|
+
# :order_id => '1230123',
|
25
|
+
# :email => 'bob@testbob.com',
|
26
|
+
# :address => { :address1 => '47 Bobway',
|
27
|
+
# :city => 'Bobville',
|
28
|
+
# :state => 'WA',
|
29
|
+
# :country => 'Australia',
|
30
|
+
# :zip => '2000'
|
31
|
+
# }
|
32
|
+
# :description => 'purchased items'
|
33
|
+
# }
|
34
|
+
#
|
35
|
+
# To finish setting up, create the active_merchant object you will be using, with the eWay gateway. If you have a
|
36
|
+
# functional eWay account, replace :login with your account info.
|
37
|
+
#
|
38
|
+
# gateway = ActiveMerchant::Billing::Base.gateway(:eway).new(:login => '87654321')
|
39
|
+
#
|
40
|
+
# Now we are ready to process our transaction
|
41
|
+
#
|
42
|
+
# response = gateway.purchase(tendollar, creditcard, options)
|
43
|
+
#
|
44
|
+
# Sending a transaction to TrustCommerce with active_merchant returns a Response object, which consistently allows you to:
|
45
|
+
#
|
46
|
+
# 1) Check whether the transaction was successful
|
47
|
+
#
|
48
|
+
# response.success?
|
49
|
+
#
|
50
|
+
# 2) Retrieve any message returned by eWay, either a "transaction was successful" note or an explanation of why the
|
51
|
+
# transaction was rejected.
|
52
|
+
#
|
53
|
+
# response.message
|
54
|
+
#
|
55
|
+
# 3) Retrieve and store the unique transaction ID returned by eWway, for use in referencing the transaction in the future.
|
56
|
+
#
|
57
|
+
# response.authorization
|
58
|
+
#
|
59
|
+
# This should be enough to get you started with eWay and active_merchant. For further information, review the methods
|
60
|
+
# below and the rest of active_merchant's documentation.
|
61
|
+
|
62
|
+
class EwayGateway < Gateway
|
63
|
+
TEST_URL = 'https://www.eway.com.au/gateway/xmltest/testpage.asp'
|
64
|
+
LIVE_URL = 'https://www.eway.com.au/gateway/xmlpayment.asp'
|
65
|
+
|
66
|
+
TEST_CVN_URL = 'https://www.eway.com.au/gateway_cvn/xmltest/testpage.asp'
|
67
|
+
LIVE_CVN_URL = 'https://www.eway.com.au/gateway_cvn/xmlpayment.asp'
|
68
|
+
|
69
|
+
MESSAGES = {
|
70
|
+
"00" => "Transaction Approved",
|
71
|
+
"01" => "Refer to Issuer",
|
72
|
+
"02" => "Refer to Issuer, special",
|
73
|
+
"03" => "No Merchant",
|
74
|
+
"04" => "Pick Up Card",
|
75
|
+
"05" => "Do Not Honour",
|
76
|
+
"06" => "Error",
|
77
|
+
"07" => "Pick Up Card, Special",
|
78
|
+
"08" => "Honour With Identification",
|
79
|
+
"09" => "Request In Progress",
|
80
|
+
"10" => "Approved For Partial Amount",
|
81
|
+
"11" => "Approved, VIP",
|
82
|
+
"12" => "Invalid Transaction",
|
83
|
+
"13" => "Invalid Amount",
|
84
|
+
"14" => "Invalid Card Number",
|
85
|
+
"15" => "No Issuer",
|
86
|
+
"16" => "Approved, Update Track 3",
|
87
|
+
"19" => "Re-enter Last Transaction",
|
88
|
+
"21" => "No Action Taken",
|
89
|
+
"22" => "Suspected Malfunction",
|
90
|
+
"23" => "Unacceptable Transaction Fee",
|
91
|
+
"25" => "Unable to Locate Record On File",
|
92
|
+
"30" => "Format Error",
|
93
|
+
"31" => "Bank Not Supported By Switch",
|
94
|
+
"33" => "Expired Card, Capture",
|
95
|
+
"34" => "Suspected Fraud, Retain Card",
|
96
|
+
"35" => "Card Acceptor, Contact Acquirer, Retain Card",
|
97
|
+
"36" => "Restricted Card, Retain Card",
|
98
|
+
"37" => "Contact Acquirer Security Department, Retain Card",
|
99
|
+
"38" => "PIN Tries Exceeded, Capture",
|
100
|
+
"39" => "No Credit Account",
|
101
|
+
"40" => "Function Not Supported",
|
102
|
+
"41" => "Lost Card",
|
103
|
+
"42" => "No Universal Account",
|
104
|
+
"43" => "Stolen Card",
|
105
|
+
"44" => "No Investment Account",
|
106
|
+
"51" => "Insufficient Funds",
|
107
|
+
"52" => "No Cheque Account",
|
108
|
+
"53" => "No Savings Account",
|
109
|
+
"54" => "Expired Card",
|
110
|
+
"55" => "Incorrect PIN",
|
111
|
+
"56" => "No Card Record",
|
112
|
+
"57" => "Function Not Permitted to Cardholder",
|
113
|
+
"58" => "Function Not Permitted to Terminal",
|
114
|
+
"59" => "Suspected Fraud",
|
115
|
+
"60" => "Acceptor Contact Acquirer",
|
116
|
+
"61" => "Exceeds Withdrawal Limit",
|
117
|
+
"62" => "Restricted Card",
|
118
|
+
"63" => "Security Violation",
|
119
|
+
"64" => "Original Amount Incorrect",
|
120
|
+
"66" => "Acceptor Contact Acquirer, Security",
|
121
|
+
"67" => "Capture Card",
|
122
|
+
"75" => "PIN Tries Exceeded",
|
123
|
+
"82" => "CVV Validation Error",
|
124
|
+
"90" => "Cutoff In Progress",
|
125
|
+
"91" => "Card Issuer Unavailable",
|
126
|
+
"92" => "Unable To Route Transaction",
|
127
|
+
"93" => "Cannot Complete, Violation Of The Law",
|
128
|
+
"94" => "Duplicate Transaction",
|
129
|
+
"96" => "System Error"
|
130
|
+
}
|
131
|
+
|
132
|
+
self.money_format = :cents
|
133
|
+
self.supported_countries = ['AU']
|
134
|
+
self.supported_cardtypes = [:visa, :master, :american_express]
|
135
|
+
self.homepage_url = 'http://www.eway.com.au/'
|
136
|
+
self.display_name = 'eWAY'
|
137
|
+
|
138
|
+
def initialize(options = {})
|
139
|
+
requires!(options, :login)
|
140
|
+
@options = options
|
141
|
+
super
|
142
|
+
end
|
143
|
+
|
144
|
+
# ewayCustomerEmail, ewayCustomerAddress, ewayCustomerPostcode
|
145
|
+
def purchase(money, creditcard, options = {})
|
146
|
+
requires!(options, :order_id)
|
147
|
+
|
148
|
+
post = {}
|
149
|
+
add_creditcard(post, creditcard)
|
150
|
+
add_address(post, options)
|
151
|
+
add_customer_data(post, options)
|
152
|
+
add_invoice_data(post, options)
|
153
|
+
# The request fails if all of the fields aren't present
|
154
|
+
add_optional_data(post)
|
155
|
+
|
156
|
+
commit(money, post)
|
157
|
+
end
|
158
|
+
|
159
|
+
def test?
|
160
|
+
@options[:test] || super
|
161
|
+
end
|
162
|
+
|
163
|
+
private
|
164
|
+
def add_creditcard(post, creditcard)
|
165
|
+
post[:CardNumber] = creditcard.number
|
166
|
+
post[:CardExpiryMonth] = sprintf("%.2i", creditcard.month)
|
167
|
+
post[:CardExpiryYear] = sprintf("%.4i", creditcard.year)[-2..-1]
|
168
|
+
post[:CustomerFirstName] = creditcard.first_name
|
169
|
+
post[:CustomerLastName] = creditcard.last_name
|
170
|
+
post[:CardHoldersName] = creditcard.name
|
171
|
+
|
172
|
+
post[:CVN] = creditcard.verification_value if creditcard.verification_value?
|
173
|
+
end
|
174
|
+
|
175
|
+
def add_address(post, options)
|
176
|
+
if address = options[:billing_address] || options[:address]
|
177
|
+
post[:CustomerAddress] = [ address[:address1], address[:address2], address[:city], address[:state], address[:country] ].compact.join(', ')
|
178
|
+
post[:CustomerPostcode] = address[:zip]
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def add_customer_data(post, options)
|
183
|
+
post[:CustomerEmail] = options[:email]
|
184
|
+
end
|
185
|
+
|
186
|
+
def add_invoice_data(post, options)
|
187
|
+
post[:CustomerInvoiceRef] = options[:order_id]
|
188
|
+
post[:CustomerInvoiceDescription] = options[:description]
|
189
|
+
end
|
190
|
+
|
191
|
+
def add_optional_data(post)
|
192
|
+
post[:TrxnNumber] = nil
|
193
|
+
post[:Option1] = nil
|
194
|
+
post[:Option2] = nil
|
195
|
+
post[:Option3] = nil
|
196
|
+
end
|
197
|
+
|
198
|
+
def commit(money, parameters)
|
199
|
+
parameters[:TotalAmount] = amount(money)
|
200
|
+
|
201
|
+
response = parse( ssl_post(gateway_url(parameters[:CVN], test?), post_data(parameters)) )
|
202
|
+
|
203
|
+
Response.new(success?(response), message_from(response[:ewaytrxnerror]), response,
|
204
|
+
:authorization => response[:ewayauthcode],
|
205
|
+
:test => /\(Test( CVN)? Gateway\)/ === response[:ewaytrxnerror]
|
206
|
+
)
|
207
|
+
end
|
208
|
+
|
209
|
+
def success?(response)
|
210
|
+
response[:ewaytrxnstatus] == "True"
|
211
|
+
end
|
212
|
+
|
213
|
+
# Parse eway response xml into a convinient hash
|
214
|
+
def parse(xml)
|
215
|
+
# "<?xml version=\"1.0\"?>".
|
216
|
+
# <ewayResponse>
|
217
|
+
# <ewayTrxnError></ewayTrxnError>
|
218
|
+
# <ewayTrxnStatus>True</ewayTrxnStatus>
|
219
|
+
# <ewayTrxnNumber>10002</ewayTrxnNumber>
|
220
|
+
# <ewayTrxnOption1></ewayTrxnOption1>
|
221
|
+
# <ewayTrxnOption2></ewayTrxnOption2>
|
222
|
+
# <ewayTrxnOption3></ewayTrxnOption3>
|
223
|
+
# <ewayReturnAmount>10</ewayReturnAmount>
|
224
|
+
# <ewayAuthCode>123456</ewayAuthCode>
|
225
|
+
# <ewayTrxnReference>987654321</ewayTrxnReference>
|
226
|
+
# </ewayResponse>
|
227
|
+
|
228
|
+
response = {}
|
229
|
+
xml = REXML::Document.new(xml)
|
230
|
+
xml.elements.each('//ewayResponse/*') do |node|
|
231
|
+
|
232
|
+
response[node.name.downcase.to_sym] = normalize(node.text)
|
233
|
+
|
234
|
+
end unless xml.root.nil?
|
235
|
+
|
236
|
+
response
|
237
|
+
end
|
238
|
+
|
239
|
+
def post_data(parameters = {})
|
240
|
+
parameters[:CustomerID] = @options[:login]
|
241
|
+
|
242
|
+
xml = REXML::Document.new
|
243
|
+
root = xml.add_element("ewaygateway")
|
244
|
+
|
245
|
+
parameters.each do |key, value|
|
246
|
+
root.add_element("eway#{key}").text = value
|
247
|
+
end
|
248
|
+
xml.to_s
|
249
|
+
end
|
250
|
+
|
251
|
+
def message_from(message)
|
252
|
+
return '' if message.blank?
|
253
|
+
MESSAGES[message[0,2]] || message
|
254
|
+
end
|
255
|
+
|
256
|
+
# Make a ruby type out of the response string
|
257
|
+
def normalize(field)
|
258
|
+
case field
|
259
|
+
when "true" then true
|
260
|
+
when "false" then false
|
261
|
+
when "" then nil
|
262
|
+
when "null" then nil
|
263
|
+
else field
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
def gateway_url(cvn, test)
|
268
|
+
if cvn
|
269
|
+
test ? TEST_CVN_URL : LIVE_CVN_URL
|
270
|
+
else
|
271
|
+
test ? TEST_URL : LIVE_URL
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|