aktivemerchant 2.0.0
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.
- checksums.yaml +7 -0
- data/CHANGELOG +1596 -0
- data/CONTRIBUTORS +511 -0
- data/MIT-LICENSE +20 -0
- data/README.md +18 -0
- data/lib/active_merchant.rb +108 -0
- data/lib/active_merchant/billing.rb +13 -0
- data/lib/active_merchant/billing/apple_pay_payment_token.rb +22 -0
- data/lib/active_merchant/billing/avs_result.rb +98 -0
- data/lib/active_merchant/billing/base.rb +72 -0
- data/lib/active_merchant/billing/check.rb +76 -0
- data/lib/active_merchant/billing/compatibility.rb +120 -0
- data/lib/active_merchant/billing/credit_card.rb +352 -0
- data/lib/active_merchant/billing/credit_card_formatting.rb +24 -0
- data/lib/active_merchant/billing/credit_card_methods.rb +160 -0
- data/lib/active_merchant/billing/cvv_result.rb +38 -0
- data/lib/active_merchant/billing/gateway.rb +268 -0
- data/lib/active_merchant/billing/gateways.rb +17 -0
- data/lib/active_merchant/billing/gateways/adyen.rb +209 -0
- data/lib/active_merchant/billing/gateways/alfabank.rb +117 -0
- data/lib/active_merchant/billing/gateways/app55.rb +176 -0
- data/lib/active_merchant/billing/gateways/authorize_net.rb +419 -0
- data/lib/active_merchant/billing/gateways/authorize_net_arb.rb +417 -0
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +976 -0
- data/lib/active_merchant/billing/gateways/balanced.rb +256 -0
- data/lib/active_merchant/billing/gateways/bank_frick.rb +225 -0
- data/lib/active_merchant/billing/gateways/banwire.rb +105 -0
- data/lib/active_merchant/billing/gateways/barclays_epdq.rb +314 -0
- data/lib/active_merchant/billing/gateways/barclays_epdq_extra_plus.rb +15 -0
- data/lib/active_merchant/billing/gateways/be2bill.rb +131 -0
- data/lib/active_merchant/billing/gateways/beanstream.rb +188 -0
- data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +393 -0
- data/lib/active_merchant/billing/gateways/beanstream_interac.rb +54 -0
- data/lib/active_merchant/billing/gateways/blue_pay.rb +506 -0
- data/lib/active_merchant/billing/gateways/bogus.rb +140 -0
- data/lib/active_merchant/billing/gateways/borgun.rb +210 -0
- data/lib/active_merchant/billing/gateways/braintree.rb +19 -0
- data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +9 -0
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +515 -0
- data/lib/active_merchant/billing/gateways/braintree_orange.rb +20 -0
- data/lib/active_merchant/billing/gateways/bridge_pay.rb +189 -0
- data/lib/active_merchant/billing/gateways/card_save.rb +23 -0
- data/lib/active_merchant/billing/gateways/card_stream.rb +220 -0
- data/lib/active_merchant/billing/gateways/cashnet.rb +191 -0
- data/lib/active_merchant/billing/gateways/cc5.rb +201 -0
- data/lib/active_merchant/billing/gateways/cecabank.rb +229 -0
- data/lib/active_merchant/billing/gateways/certo_direct.rb +278 -0
- data/lib/active_merchant/billing/gateways/checkout.rb +213 -0
- data/lib/active_merchant/billing/gateways/commercegate.rb +143 -0
- data/lib/active_merchant/billing/gateways/conekta.rb +209 -0
- data/lib/active_merchant/billing/gateways/cyber_source.rb +709 -0
- data/lib/active_merchant/billing/gateways/data_cash.rb +600 -0
- data/lib/active_merchant/billing/gateways/efsnet.rb +219 -0
- data/lib/active_merchant/billing/gateways/elavon.rb +348 -0
- data/lib/active_merchant/billing/gateways/epay.rb +275 -0
- data/lib/active_merchant/billing/gateways/evo_ca.rb +308 -0
- data/lib/active_merchant/billing/gateways/eway.rb +214 -0
- data/lib/active_merchant/billing/gateways/eway_managed.rb +291 -0
- data/lib/active_merchant/billing/gateways/eway_rapid.rb +524 -0
- data/lib/active_merchant/billing/gateways/exact.rb +218 -0
- data/lib/active_merchant/billing/gateways/fat_zebra.rb +173 -0
- data/lib/active_merchant/billing/gateways/federated_canada.rb +160 -0
- data/lib/active_merchant/billing/gateways/finansbank.rb +23 -0
- data/lib/active_merchant/billing/gateways/first_giving.rb +143 -0
- data/lib/active_merchant/billing/gateways/first_pay.rb +160 -0
- data/lib/active_merchant/billing/gateways/firstdata_e4.rb +355 -0
- data/lib/active_merchant/billing/gateways/garanti.rb +257 -0
- data/lib/active_merchant/billing/gateways/global_transport.rb +183 -0
- data/lib/active_merchant/billing/gateways/hdfc.rb +207 -0
- data/lib/active_merchant/billing/gateways/hps.rb +288 -0
- data/lib/active_merchant/billing/gateways/iats_payments.rb +251 -0
- data/lib/active_merchant/billing/gateways/ideal/ideal_base.rb +246 -0
- data/lib/active_merchant/billing/gateways/ideal/ideal_rabobank.pem +13 -0
- data/lib/active_merchant/billing/gateways/ideal/ideal_response.rb +29 -0
- data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +66 -0
- data/lib/active_merchant/billing/gateways/inspire.rb +213 -0
- data/lib/active_merchant/billing/gateways/instapay.rb +163 -0
- data/lib/active_merchant/billing/gateways/iridium.rb +457 -0
- data/lib/active_merchant/billing/gateways/itransact.rb +448 -0
- data/lib/active_merchant/billing/gateways/jetpay.rb +275 -0
- data/lib/active_merchant/billing/gateways/linkpoint.rb +438 -0
- data/lib/active_merchant/billing/gateways/litle.rb +346 -0
- data/lib/active_merchant/billing/gateways/maxipago.rb +197 -0
- data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +170 -0
- data/lib/active_merchant/billing/gateways/merchant_one.rb +114 -0
- data/lib/active_merchant/billing/gateways/merchant_ware.rb +319 -0
- data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +268 -0
- data/lib/active_merchant/billing/gateways/merchant_warrior.rb +195 -0
- data/lib/active_merchant/billing/gateways/mercury.rb +333 -0
- data/lib/active_merchant/billing/gateways/metrics_global.rb +303 -0
- data/lib/active_merchant/billing/gateways/migs.rb +265 -0
- data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +100 -0
- data/lib/active_merchant/billing/gateways/modern_payments.rb +37 -0
- data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +219 -0
- data/lib/active_merchant/billing/gateways/moneris.rb +309 -0
- data/lib/active_merchant/billing/gateways/moneris_us.rb +291 -0
- data/lib/active_merchant/billing/gateways/money_movers.rb +152 -0
- data/lib/active_merchant/billing/gateways/nab_transact.rb +280 -0
- data/lib/active_merchant/billing/gateways/net_registry.rb +198 -0
- data/lib/active_merchant/billing/gateways/netaxept.rb +181 -0
- data/lib/active_merchant/billing/gateways/netbilling.rb +190 -0
- data/lib/active_merchant/billing/gateways/netpay.rb +223 -0
- data/lib/active_merchant/billing/gateways/network_merchants.rb +242 -0
- data/lib/active_merchant/billing/gateways/nmi.rb +256 -0
- data/lib/active_merchant/billing/gateways/ogone.rb +435 -0
- data/lib/active_merchant/billing/gateways/openpay.rb +194 -0
- data/lib/active_merchant/billing/gateways/optimal_payment.rb +313 -0
- data/lib/active_merchant/billing/gateways/orbital.rb +803 -0
- data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +47 -0
- data/lib/active_merchant/billing/gateways/pac_net_raven.rb +207 -0
- data/lib/active_merchant/billing/gateways/pago_facil.rb +122 -0
- data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +261 -0
- data/lib/active_merchant/billing/gateways/pay_junction.rb +390 -0
- data/lib/active_merchant/billing/gateways/pay_secure.rb +112 -0
- data/lib/active_merchant/billing/gateways/pay_u_latam.rb +462 -0
- data/lib/active_merchant/billing/gateways/paybox_direct.rb +188 -0
- data/lib/active_merchant/billing/gateways/payex.rb +412 -0
- data/lib/active_merchant/billing/gateways/payflow.rb +304 -0
- data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +209 -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_express.rb +224 -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 +353 -0
- data/lib/active_merchant/billing/gateways/paymill.rb +281 -0
- data/lib/active_merchant/billing/gateways/paypal.rb +117 -0
- data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +670 -0
- data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +65 -0
- data/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb +262 -0
- data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
- data/lib/active_merchant/billing/gateways/paypal_digital_goods.rb +44 -0
- data/lib/active_merchant/billing/gateways/paypal_express.rb +264 -0
- data/lib/active_merchant/billing/gateways/paypal_express_common.rb +30 -0
- data/lib/active_merchant/billing/gateways/payscout.rb +162 -0
- data/lib/active_merchant/billing/gateways/paystation.rb +199 -0
- data/lib/active_merchant/billing/gateways/payway.rb +207 -0
- data/lib/active_merchant/billing/gateways/pin.rb +197 -0
- data/lib/active_merchant/billing/gateways/plugnpay.rb +283 -0
- data/lib/active_merchant/billing/gateways/psigate.rb +216 -0
- data/lib/active_merchant/billing/gateways/psl_card.rb +303 -0
- data/lib/active_merchant/billing/gateways/qbms.rb +292 -0
- data/lib/active_merchant/billing/gateways/quantum.rb +276 -0
- data/lib/active_merchant/billing/gateways/quickpay.rb +367 -0
- data/lib/active_merchant/billing/gateways/realex.rb +298 -0
- data/lib/active_merchant/billing/gateways/redsys.rb +391 -0
- data/lib/active_merchant/billing/gateways/sage.rb +175 -0
- data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +87 -0
- data/lib/active_merchant/billing/gateways/sage/sage_core.rb +114 -0
- data/lib/active_merchant/billing/gateways/sage/sage_vault.rb +149 -0
- data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +102 -0
- data/lib/active_merchant/billing/gateways/sage_pay.rb +398 -0
- data/lib/active_merchant/billing/gateways/sallie_mae.rb +143 -0
- data/lib/active_merchant/billing/gateways/secure_net.rb +252 -0
- data/lib/active_merchant/billing/gateways/secure_pay.rb +201 -0
- data/lib/active_merchant/billing/gateways/secure_pay_au.rb +281 -0
- data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +105 -0
- data/lib/active_merchant/billing/gateways/skip_jack.rb +452 -0
- data/lib/active_merchant/billing/gateways/smart_ps.rb +283 -0
- data/lib/active_merchant/billing/gateways/so_easy_pay.rb +194 -0
- data/lib/active_merchant/billing/gateways/spreedly_core.rb +247 -0
- data/lib/active_merchant/billing/gateways/stripe.rb +411 -0
- data/lib/active_merchant/billing/gateways/swipe_checkout.rb +157 -0
- data/lib/active_merchant/billing/gateways/tns.rb +227 -0
- data/lib/active_merchant/billing/gateways/trans_first.rb +126 -0
- data/lib/active_merchant/billing/gateways/transax.rb +23 -0
- data/lib/active_merchant/billing/gateways/transnational.rb +10 -0
- data/lib/active_merchant/billing/gateways/trust_commerce.rb +416 -0
- data/lib/active_merchant/billing/gateways/usa_epay.rb +25 -0
- data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +1516 -0
- data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +254 -0
- data/lib/active_merchant/billing/gateways/verifi.rb +225 -0
- data/lib/active_merchant/billing/gateways/viaklix.rb +183 -0
- data/lib/active_merchant/billing/gateways/vindicia.rb +385 -0
- data/lib/active_merchant/billing/gateways/webpay.rb +97 -0
- data/lib/active_merchant/billing/gateways/wepay.rb +189 -0
- data/lib/active_merchant/billing/gateways/wirecard.rb +421 -0
- data/lib/active_merchant/billing/gateways/worldpay.rb +331 -0
- data/lib/active_merchant/billing/gateways/worldpay_us.rb +181 -0
- data/lib/active_merchant/billing/model.rb +30 -0
- data/lib/active_merchant/billing/payment_token.rb +21 -0
- data/lib/active_merchant/billing/rails.rb +3 -0
- data/lib/active_merchant/billing/response.rb +91 -0
- data/lib/active_merchant/country.rb +332 -0
- data/lib/active_merchant/empty.rb +20 -0
- data/lib/active_merchant/errors.rb +29 -0
- data/lib/active_merchant/offsite_payments_shim.rb +19 -0
- data/lib/active_merchant/version.rb +3 -0
- data/lib/activemerchant.rb +1 -0
- data/lib/support/gateway_support.rb +71 -0
- data/lib/support/outbound_hosts.rb +25 -0
- data/lib/support/ssl_verify.rb +93 -0
- metadata +400 -0
@@ -0,0 +1,183 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
class ViaklixGateway < Gateway
|
4
|
+
class_attribute :test_url, :live_url, :delimiter, :actions
|
5
|
+
|
6
|
+
self.test_url = 'https://demo.viaklix.com/process.asp'
|
7
|
+
self.live_url = 'https://www.viaklix.com/process.asp'
|
8
|
+
self.delimiter = "\r\n"
|
9
|
+
|
10
|
+
self.actions = {
|
11
|
+
:purchase => 'SALE',
|
12
|
+
:credit => 'CREDIT'
|
13
|
+
}
|
14
|
+
|
15
|
+
APPROVED = '0'
|
16
|
+
|
17
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :discover]
|
18
|
+
self.supported_countries = ['US']
|
19
|
+
self.display_name = 'ViaKLIX'
|
20
|
+
self.homepage_url = 'http://viaklix.com'
|
21
|
+
|
22
|
+
# Initialize the Gateway
|
23
|
+
#
|
24
|
+
# The gateway requires that a valid login and password be passed
|
25
|
+
# in the +options+ hash.
|
26
|
+
#
|
27
|
+
# ==== Options
|
28
|
+
#
|
29
|
+
# * <tt>:login</tt> -- Merchant ID
|
30
|
+
# * <tt>:password</tt> -- PIN
|
31
|
+
# * <tt>:user</tt> -- Specify a subuser of the account (optional)
|
32
|
+
# * <tt>:test => +true+ or +false+</tt> -- Force test transactions
|
33
|
+
def initialize(options = {})
|
34
|
+
requires!(options, :login, :password)
|
35
|
+
super
|
36
|
+
end
|
37
|
+
|
38
|
+
# Make a purchase
|
39
|
+
def purchase(money, creditcard, options = {})
|
40
|
+
form = {}
|
41
|
+
add_invoice(form, options)
|
42
|
+
add_creditcard(form, creditcard)
|
43
|
+
add_address(form, options)
|
44
|
+
add_customer_data(form, options)
|
45
|
+
add_test_mode(form, options)
|
46
|
+
commit(:purchase, money, form)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Make a credit to a card (Void can only be done from the virtual terminal)
|
50
|
+
# Viaklix does not support credits by reference. You must pass in the credit card
|
51
|
+
def credit(money, creditcard, options = {})
|
52
|
+
if creditcard.is_a?(String)
|
53
|
+
raise ArgumentError, "Reference credits are not supported. Please supply the original credit card"
|
54
|
+
end
|
55
|
+
|
56
|
+
form = {}
|
57
|
+
add_invoice(form, options)
|
58
|
+
add_creditcard(form, creditcard)
|
59
|
+
add_address(form, options)
|
60
|
+
add_customer_data(form, options)
|
61
|
+
add_test_mode(form, options)
|
62
|
+
commit(:credit, money, form)
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
def add_test_mode(form, options)
|
67
|
+
form[:test_mode] = 'TRUE' if options[:test_mode]
|
68
|
+
end
|
69
|
+
|
70
|
+
def add_customer_data(form, options)
|
71
|
+
form[:email] = options[:email].to_s.slice(0, 100) unless options[:email].blank?
|
72
|
+
form[:customer_code] = options[:customer].to_s.slice(0, 10) unless options[:customer].blank?
|
73
|
+
end
|
74
|
+
|
75
|
+
def add_invoice(form,options)
|
76
|
+
form[:invoice_number] = (options[:order_id] || options[:invoice]).to_s.slice(0, 10)
|
77
|
+
form[:description] = options[:description].to_s.slice(0, 255)
|
78
|
+
end
|
79
|
+
|
80
|
+
def add_address(form,options)
|
81
|
+
billing_address = options[:billing_address] || options[:address]
|
82
|
+
|
83
|
+
if billing_address
|
84
|
+
form[:avs_address] = billing_address[:address1].to_s.slice(0, 30)
|
85
|
+
form[:address2] = billing_address[:address2].to_s.slice(0, 30)
|
86
|
+
form[:avs_zip] = billing_address[:zip].to_s.slice(0, 10)
|
87
|
+
form[:city] = billing_address[:city].to_s.slice(0, 30)
|
88
|
+
form[:state] = billing_address[:state].to_s.slice(0, 10)
|
89
|
+
form[:company] = billing_address[:company].to_s.slice(0, 50)
|
90
|
+
form[:phone] = billing_address[:phone].to_s.slice(0, 20)
|
91
|
+
form[:country] = billing_address[:country].to_s.slice(0, 50)
|
92
|
+
end
|
93
|
+
|
94
|
+
if shipping_address = options[:shipping_address]
|
95
|
+
first_name, last_name = parse_first_and_last_name(shipping_address[:name])
|
96
|
+
form[:ship_to_first_name] = first_name.to_s.slice(0, 20)
|
97
|
+
form[:ship_to_last_name] = last_name.to_s.slice(0, 30)
|
98
|
+
form[:ship_to_address] = shipping_address[:address1].to_s.slice(0, 30)
|
99
|
+
form[:ship_to_city] = shipping_address[:city].to_s.slice(0, 30)
|
100
|
+
form[:ship_to_state] = shipping_address[:state].to_s.slice(0, 10)
|
101
|
+
form[:ship_to_company] = shipping_address[:company].to_s.slice(0, 50)
|
102
|
+
form[:ship_to_country] = shipping_address[:country].to_s.slice(0, 50)
|
103
|
+
form[:ship_to_zip] = shipping_address[:zip].to_s.slice(0, 10)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def parse_first_and_last_name(value)
|
108
|
+
name = value.to_s.split(' ')
|
109
|
+
|
110
|
+
last_name = name.pop || ''
|
111
|
+
first_name = name.join(' ')
|
112
|
+
[ first_name, last_name ]
|
113
|
+
end
|
114
|
+
|
115
|
+
def add_creditcard(form, creditcard)
|
116
|
+
form[:card_number] = creditcard.number
|
117
|
+
form[:exp_date] = expdate(creditcard)
|
118
|
+
|
119
|
+
if creditcard.verification_value?
|
120
|
+
add_verification_value(form, creditcard)
|
121
|
+
end
|
122
|
+
|
123
|
+
form[:first_name] = creditcard.first_name.to_s.slice(0, 20)
|
124
|
+
form[:last_name] = creditcard.last_name.to_s.slice(0, 30)
|
125
|
+
end
|
126
|
+
|
127
|
+
def add_verification_value(form, creditcard)
|
128
|
+
form[:cvv2cvc2] = creditcard.verification_value
|
129
|
+
form[:cvv2] = 'present'
|
130
|
+
end
|
131
|
+
|
132
|
+
def preamble
|
133
|
+
result = {
|
134
|
+
'merchant_id' => @options[:login],
|
135
|
+
'pin' => @options[:password],
|
136
|
+
'show_form' => 'false',
|
137
|
+
'result_format' => 'ASCII'
|
138
|
+
}
|
139
|
+
|
140
|
+
result['user_id'] = @options[:user] unless @options[:user].blank?
|
141
|
+
result
|
142
|
+
end
|
143
|
+
|
144
|
+
def commit(action, money, parameters)
|
145
|
+
parameters[:amount] = amount(money)
|
146
|
+
parameters[:transaction_type] = self.actions[action]
|
147
|
+
|
148
|
+
response = parse( ssl_post(test? ? self.test_url : self.live_url, post_data(parameters)) )
|
149
|
+
|
150
|
+
Response.new(response['result'] == APPROVED, message_from(response), response,
|
151
|
+
:test => @options[:test] || test?,
|
152
|
+
:authorization => authorization_from(response),
|
153
|
+
:avs_result => { :code => response['avs_response'] },
|
154
|
+
:cvv_result => response['cvv2_response']
|
155
|
+
)
|
156
|
+
end
|
157
|
+
|
158
|
+
def authorization_from(response)
|
159
|
+
response['txn_id']
|
160
|
+
end
|
161
|
+
|
162
|
+
def message_from(response)
|
163
|
+
response['result_message']
|
164
|
+
end
|
165
|
+
|
166
|
+
def post_data(parameters)
|
167
|
+
result = preamble
|
168
|
+
result.merge!(parameters)
|
169
|
+
result.collect { |key, value| "ssl_#{key}=#{CGI.escape(value.to_s)}" }.join("&")
|
170
|
+
end
|
171
|
+
|
172
|
+
# Parse the response message
|
173
|
+
def parse(msg)
|
174
|
+
resp = {}
|
175
|
+
msg.split(self.delimiter).collect{|li|
|
176
|
+
key, value = li.split("=")
|
177
|
+
resp[key.strip.gsub(/^ssl_/, '')] = value.to_s.strip
|
178
|
+
}
|
179
|
+
resp
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
@@ -0,0 +1,385 @@
|
|
1
|
+
require 'i18n/core_ext/string/interpolate'
|
2
|
+
|
3
|
+
module ActiveMerchant #:nodoc:
|
4
|
+
module Billing #:nodoc:
|
5
|
+
|
6
|
+
# For more information on the Vindicia Gateway please visit their {website}[http://vindicia.com/]
|
7
|
+
#
|
8
|
+
# The login and password are not the username and password you use to
|
9
|
+
# login to the Vindicia Merchant Portal.
|
10
|
+
#
|
11
|
+
# ==== Recurring Billing
|
12
|
+
#
|
13
|
+
# AutoBills are an feature of Vindicia's API that allows for creating and managing subscriptions.
|
14
|
+
#
|
15
|
+
# For more information about Vindicia's API and various other services visit their {Resource Center}[http://www.vindicia.com/resources/index.html]
|
16
|
+
class VindiciaGateway < Gateway
|
17
|
+
self.supported_countries = %w{US CA GB AU MX BR DE KR CN HK}
|
18
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :discover]
|
19
|
+
self.homepage_url = 'http://www.vindicia.com/'
|
20
|
+
self.display_name = 'Vindicia'
|
21
|
+
|
22
|
+
class_attribute :test_url, :live_url
|
23
|
+
|
24
|
+
self.test_url = "https://soap.prodtest.sj.vindicia.com/soap.pl"
|
25
|
+
self.live_url = "http://soap.vindicia.com/soap.pl"
|
26
|
+
|
27
|
+
# Creates a new VindiciaGateway
|
28
|
+
#
|
29
|
+
# The gateway requires that a valid login and password be passed
|
30
|
+
# in the +options+ hash.
|
31
|
+
#
|
32
|
+
# ==== Options
|
33
|
+
#
|
34
|
+
# * <tt>:login</tt> -- Vindicia SOAP login (REQUIRED)
|
35
|
+
# * <tt>:password</tt> -- Vindicia SOAP password (REQUIRED)
|
36
|
+
# * <tt>:api_version</tt> -- Vindicia API Version - defaults to 3.6 (OPTIONAL)
|
37
|
+
# * <tt>:account_id</tt> -- Account Id which all transactions will be run against. (REQUIRED)
|
38
|
+
# * <tt>:transaction_prefix</tt> -- Prefix to order id for one-time transactions - defaults to 'X' (OPTIONAL
|
39
|
+
# * <tt>:min_chargeback_probability</tt> -- Minimum score for chargebacks - defaults to 65 (OPTIONAL)
|
40
|
+
# * <tt>:cvn_success</tt> -- Array of valid CVN Check return values - defaults to [M, P] (OPTIONAL)
|
41
|
+
# * <tt>:avs_success</tt> -- Array of valid AVS Check return values - defaults to [X, Y, A, W, Z] (OPTIONAL)
|
42
|
+
def initialize(options = {})
|
43
|
+
requires!(options, :login, :password, :account_id)
|
44
|
+
super
|
45
|
+
|
46
|
+
@account_id = options[:account_id]
|
47
|
+
|
48
|
+
@transaction_prefix = options[:transaction_prefix] || "X"
|
49
|
+
|
50
|
+
@min_chargeback_probability = options[:min_chargeback_probability] || 65
|
51
|
+
@cvn_success = options[:cvn_success] || %w{M P}
|
52
|
+
@avs_success = options[:avs_success] || %w{X Y A W Z}
|
53
|
+
|
54
|
+
@allowed_authorization_statuses = %w{Authorized}
|
55
|
+
end
|
56
|
+
|
57
|
+
# Perform a purchase, which is essentially an authorization and capture in a single operation.
|
58
|
+
#
|
59
|
+
# ==== Parameters
|
60
|
+
#
|
61
|
+
# * <tt>money</tt> -- The amount to be purchased as an Integer value in cents.
|
62
|
+
# * <tt>creditcard</tt> -- The CreditCard details for the transaction.
|
63
|
+
# * <tt>options</tt> -- A hash of optional parameters.
|
64
|
+
def purchase(money, creditcard, options = {})
|
65
|
+
response = authorize(money, creditcard, options)
|
66
|
+
return response if !response.success? || response.fraud_review?
|
67
|
+
|
68
|
+
capture(money, response.authorization, options)
|
69
|
+
end
|
70
|
+
|
71
|
+
# Performs an authorization, which reserves the funds on the customer's credit card, but does not
|
72
|
+
# charge the card.
|
73
|
+
#
|
74
|
+
# ==== Parameters
|
75
|
+
#
|
76
|
+
# * <tt>money</tt> -- The amount to be authorized as an Integer value in cents.
|
77
|
+
# * <tt>creditcard</tt> -- The CreditCard details for the transaction.
|
78
|
+
# * <tt>options</tt> -- A hash of optional parameters.
|
79
|
+
def authorize(money, creditcard, options = {})
|
80
|
+
vindicia_transaction = authorize_transaction(money, creditcard, options)
|
81
|
+
response = check_transaction(vindicia_transaction)
|
82
|
+
|
83
|
+
# if this response is under fraud review because of our AVS/CVV checks void the transaction
|
84
|
+
if !response.success? && response.fraud_review? && !response.authorization.blank?
|
85
|
+
void_response = void([vindicia_transaction[:transaction][:merchantTransactionId]], options)
|
86
|
+
if void_response.success?
|
87
|
+
return response
|
88
|
+
else
|
89
|
+
return void_response
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
response
|
94
|
+
end
|
95
|
+
|
96
|
+
# Captures the funds from an authorized transaction.
|
97
|
+
#
|
98
|
+
# ==== Parameters
|
99
|
+
#
|
100
|
+
# * <tt>money</tt> -- The amount to be captured as an Integer value in cents.
|
101
|
+
# * <tt>identification</tt> -- The authorization returned from the previous authorize request.
|
102
|
+
def capture(money, identification, options = {})
|
103
|
+
response = post(:capture) do |xml|
|
104
|
+
add_hash(xml, transactions: [{ merchantTransactionId: identification }])
|
105
|
+
end
|
106
|
+
|
107
|
+
if response[:return][:returnCode] != '200' || response[:qtyFail].to_i > 0
|
108
|
+
return fail(response)
|
109
|
+
end
|
110
|
+
|
111
|
+
success(response, identification)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Void a previous transaction
|
115
|
+
#
|
116
|
+
# ==== Parameters
|
117
|
+
#
|
118
|
+
# * <tt>identification</tt> - The authorization returned from the previous authorize request.
|
119
|
+
# * <tt>options</tt> - Extra options (currently only :ip used)
|
120
|
+
def void(identification, options = {})
|
121
|
+
response = post(:cancel) do |xml|
|
122
|
+
add_hash(xml, transactions: [{
|
123
|
+
account: {merchantAccountId: @account_id},
|
124
|
+
merchantTransactionId: identification,
|
125
|
+
sourceIp: options[:ip]
|
126
|
+
}])
|
127
|
+
end
|
128
|
+
|
129
|
+
if response[:return][:returnCode] == '200' && response[:qtyFail].to_i == 0
|
130
|
+
success(response, identification)
|
131
|
+
else
|
132
|
+
fail(response)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# Perform a recurring billing, which is essentially a purchase and autobill setup in a single operation.
|
137
|
+
#
|
138
|
+
# ==== Parameters
|
139
|
+
#
|
140
|
+
# * <tt>money</tt> -- The amount to be purchased as an Integer value in cents.
|
141
|
+
# * <tt>creditcard</tt> -- The CreditCard details for the transaction.
|
142
|
+
# * <tt>options</tt> -- A hash of parameters.
|
143
|
+
#
|
144
|
+
# ==== Options
|
145
|
+
#
|
146
|
+
# * <tt>:product_sku</tt> -- The subscription product's sku
|
147
|
+
# * <tt>:autobill_prefix</tt> -- Prefix to order id for subscriptions - defaults to 'A' (OPTIONAL)
|
148
|
+
def recurring(money, creditcard, options={})
|
149
|
+
ActiveMerchant.deprecated RECURRING_DEPRECATION_MESSAGE
|
150
|
+
|
151
|
+
options[:recurring] = true
|
152
|
+
@autobill_prefix = options[:autobill_prefix] || "A"
|
153
|
+
|
154
|
+
response = authorize(money, creditcard, options)
|
155
|
+
return response if !response.success? || response.fraud_review?
|
156
|
+
|
157
|
+
capture_resp = capture(money, response.authorization, options)
|
158
|
+
return capture_resp if !response.success?
|
159
|
+
|
160
|
+
# Setting up a recurring AutoBill requires an associated product
|
161
|
+
requires!(options, :product_sku)
|
162
|
+
autobill_response = check_subscription(authorize_subscription(options.merge(:product_sku => options[:product_sku])))
|
163
|
+
|
164
|
+
if autobill_response.success?
|
165
|
+
autobill_response
|
166
|
+
else
|
167
|
+
# If the AutoBill fails to set-up, void the transaction and return it as the response
|
168
|
+
void_response = void(capture_resp.authorization, options)
|
169
|
+
if void_response.success?
|
170
|
+
return autobill_response
|
171
|
+
else
|
172
|
+
return void_response
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
private
|
178
|
+
|
179
|
+
def add_hash(xml, hash)
|
180
|
+
hash.each do |k,v|
|
181
|
+
add_element(xml, k, v)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def add_array(xml, elem, val)
|
186
|
+
val.each do |v|
|
187
|
+
add_element(xml, elem, v)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def add_element(xml, elem, val)
|
192
|
+
if val.is_a?(Hash)
|
193
|
+
xml.tag!(elem.to_s.camelize(:lower)) do |env|
|
194
|
+
add_hash(env, val)
|
195
|
+
end
|
196
|
+
elsif val.is_a?(Array)
|
197
|
+
add_array(xml, elem, val)
|
198
|
+
else
|
199
|
+
xml.tag!(elem.to_s.camelize(:lower), val.to_s)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def post(action, kind="Transaction")
|
204
|
+
xml = Builder::XmlMarkup.new
|
205
|
+
xml.instruct!(:xml, :encoding => "UTF-8")
|
206
|
+
xml.env :Envelope,
|
207
|
+
"xmlns:xsd" => "http://www.w3.org/2001/XMLSchema",
|
208
|
+
"xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",
|
209
|
+
"xmlns:tns" => "http://soap.vindicia.com/v3_6/#{kind}",
|
210
|
+
"xmlns:env" => "http://schemas.xmlsoap.org/soap/envelope/" do
|
211
|
+
|
212
|
+
xml.env :Body do
|
213
|
+
xml.tns action.to_sym do
|
214
|
+
xml.auth do
|
215
|
+
xml.tag! :login, @options[:login]
|
216
|
+
xml.tag! :password, @options[:password]
|
217
|
+
xml.tag! :version, "3.6"
|
218
|
+
end
|
219
|
+
|
220
|
+
yield(xml)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
url = (test? ? self.test_url : self.live_url)
|
226
|
+
parse(ssl_post(url, xml.target!, "Content-Type" => "text/xml"))
|
227
|
+
end
|
228
|
+
|
229
|
+
def parse(response)
|
230
|
+
# Vindicia always returns in the form of request_type_response => { actual_response }
|
231
|
+
Hash.from_xml(response)["Envelope"]["Body"].values.first.with_indifferent_access
|
232
|
+
end
|
233
|
+
|
234
|
+
def check_transaction(vindicia_transaction)
|
235
|
+
if vindicia_transaction[:return][:returnCode] == '200'
|
236
|
+
status_log = vindicia_transaction[:transaction][:statusLog].first
|
237
|
+
if status_log[:creditCardStatus]
|
238
|
+
avs = status_log[:creditCardStatus][:avsCode]
|
239
|
+
cvn = status_log[:creditCardStatus][:cvnCode]
|
240
|
+
end
|
241
|
+
|
242
|
+
if @allowed_authorization_statuses.include?(status_log[:status]) &&
|
243
|
+
check_cvn(cvn) && check_avs(avs)
|
244
|
+
|
245
|
+
success(vindicia_transaction,
|
246
|
+
vindicia_transaction[:transaction][:merchantTransactionId],
|
247
|
+
avs, cvn)
|
248
|
+
else
|
249
|
+
# If the transaction is authorized, but it didn't pass our AVS/CVV checks send the authorization along so
|
250
|
+
# that is gets voided. Otherwise, send no authorization.
|
251
|
+
fail(vindicia_transaction, avs, cvn, false,
|
252
|
+
@allowed_authorization_statuses.include?(status_log[:status]) ? vindicia_transaction[:transaction][:merchantTransactionId] : "")
|
253
|
+
end
|
254
|
+
else
|
255
|
+
# 406 = Chargeback risk score is higher than minChargebackProbability, transaction not authorized.
|
256
|
+
fail(vindicia_transaction, nil, nil, vindicia_transaction[:return][:return_code] == '406')
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
def authorize_transaction(money, creditcard, options)
|
261
|
+
parameters = {
|
262
|
+
:amount => amount(money),
|
263
|
+
:currency => options[:currency] || currency(money)
|
264
|
+
}
|
265
|
+
|
266
|
+
add_account_data(parameters, options)
|
267
|
+
add_customer_data(parameters, options)
|
268
|
+
add_payment_source(parameters, creditcard, options)
|
269
|
+
|
270
|
+
post(:auth) do |xml|
|
271
|
+
add_hash(xml, transaction: parameters, minChargebackProbability: @min_chargeback_probability)
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
def add_account_data(parameters, options)
|
276
|
+
parameters[:account] = { :merchantAccountId => @account_id }
|
277
|
+
parameters[:sourceIp] = options[:ip] if options[:ip]
|
278
|
+
end
|
279
|
+
|
280
|
+
def add_customer_data(parameters, options)
|
281
|
+
parameters[:merchantTransactionId] = transaction_id(options[:order_id])
|
282
|
+
parameters[:shippingAddress] = convert_am_address_to_vindicia(options[:shipping_address])
|
283
|
+
|
284
|
+
# Transaction items must be provided for tax purposes
|
285
|
+
requires!(options, :line_items)
|
286
|
+
parameters[:transactionItems] = options[:line_items]
|
287
|
+
|
288
|
+
if options[:recurring]
|
289
|
+
parameters[:nameValues] = [{:name => 'merchantAutoBillIdentifier', :value => autobill_id(options[:order_id])}]
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
def add_payment_source(parameters, creditcard, options)
|
294
|
+
parameters[:sourcePaymentMethod] = {
|
295
|
+
:type => 'CreditCard',
|
296
|
+
:creditCard => { :account => creditcard.number, :expirationDate => "%4d%02d" % [creditcard.year, creditcard.month] },
|
297
|
+
:accountHolderName => creditcard.name,
|
298
|
+
:nameValues => [{ :name => 'CVN', :value => creditcard.verification_value }],
|
299
|
+
:billingAddress => convert_am_address_to_vindicia(options[:billing_address] || options[:address]),
|
300
|
+
:customerSpecifiedType => creditcard.brand.capitalize,
|
301
|
+
:active => !!options[:recurring]
|
302
|
+
}
|
303
|
+
end
|
304
|
+
|
305
|
+
def authorize_subscription(options)
|
306
|
+
parameters = {}
|
307
|
+
|
308
|
+
add_account_data(parameters, options)
|
309
|
+
add_subscription_information(parameters, options)
|
310
|
+
|
311
|
+
post(:update, "AutoBill") do |xml|
|
312
|
+
add_hash(xml, autobill: parameters, validatePaymentMethod: false, minChargebackProbability: 100)
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
def check_subscription(vindicia_transaction)
|
317
|
+
if vindicia_transaction[:return][:returnCode] == '200'
|
318
|
+
if vindicia_transaction[:autobill] && vindicia_transaction[:autobill][:status] == "Active"
|
319
|
+
success(vindicia_transaction,
|
320
|
+
vindicia_transaction[:autobill][:merchantAutoBillId])
|
321
|
+
else
|
322
|
+
fail(vindicia_transaction)
|
323
|
+
end
|
324
|
+
else
|
325
|
+
fail(vindicia_transaction)
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
def add_subscription_information(parameters, options)
|
330
|
+
requires!(options, :product_sku)
|
331
|
+
|
332
|
+
if options[:shipping_address]
|
333
|
+
parameters[:account][:shipping_address] = options[:shipping_address]
|
334
|
+
end
|
335
|
+
|
336
|
+
parameters[:merchantAutoBillId] = autobill_id(options[:order_id])
|
337
|
+
parameters[:product] = { :merchantProductId => options[:product_sku] }
|
338
|
+
end
|
339
|
+
|
340
|
+
def check_avs(avs)
|
341
|
+
avs.blank? || @avs_success.include?(avs)
|
342
|
+
end
|
343
|
+
|
344
|
+
def check_cvn(cvn)
|
345
|
+
cvn.blank? || @cvn_success.include?(cvn)
|
346
|
+
end
|
347
|
+
|
348
|
+
def success(response, authorization, avs_code = nil, cvn_code = nil)
|
349
|
+
ActiveMerchant::Billing::Response.new(true, response[:return][:returnString], response,
|
350
|
+
{ :fraud_review => false, :authorization => authorization, :test => test?,
|
351
|
+
:avs_result => { :code => avs_code }, :cvv_result => cvn_code })
|
352
|
+
end
|
353
|
+
|
354
|
+
def fail(response, avs_code = nil, cvn_code = nil, fraud_review = false, authorization = "")
|
355
|
+
ActiveMerchant::Billing::Response.new(false, response[:return][:returnString], response,
|
356
|
+
{ :fraud_review => fraud_review || !authorization.blank?,
|
357
|
+
:authorization => authorization, :test => test?,
|
358
|
+
:avs_result => { :code => avs_code }, :cvv_result => cvn_code })
|
359
|
+
|
360
|
+
end
|
361
|
+
|
362
|
+
def autobill_id(order_id)
|
363
|
+
"#{@autobill_prefix}#{order_id}"
|
364
|
+
end
|
365
|
+
|
366
|
+
def transaction_id(order_id)
|
367
|
+
"#{@transaction_prefix}#{order_id}"
|
368
|
+
end
|
369
|
+
|
370
|
+
# Converts valid ActiveMerchant address hash to proper Vindicia format
|
371
|
+
def convert_am_address_to_vindicia(address)
|
372
|
+
return if address.nil?
|
373
|
+
|
374
|
+
convs = { :address1 => :addr1, :address2 => :addr2,
|
375
|
+
:state => :district, :zip => :postalCode }
|
376
|
+
|
377
|
+
vindicia_address = {}
|
378
|
+
address.each do |key, val|
|
379
|
+
vindicia_address[convs[key] || key] = val
|
380
|
+
end
|
381
|
+
vindicia_address
|
382
|
+
end
|
383
|
+
end
|
384
|
+
end
|
385
|
+
end
|