gonow-activemerchant 1.15.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.
- data/CHANGELOG +690 -0
- data/CONTRIBUTORS +237 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +165 -0
- data/gem-public_cert.pem +20 -0
- data/lib/active_merchant.rb +47 -0
- data/lib/active_merchant/billing.rb +9 -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 +178 -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 +170 -0
- data/lib/active_merchant/billing/gateways.rb +18 -0
- data/lib/active_merchant/billing/gateways/authorize_net.rb +664 -0
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +858 -0
- data/lib/active_merchant/billing/gateways/barclays_epdq.rb +308 -0
- data/lib/active_merchant/billing/gateways/beanstream.rb +139 -0
- data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +282 -0
- data/lib/active_merchant/billing/gateways/beanstream_interac.rb +54 -0
- data/lib/active_merchant/billing/gateways/blue_pay.rb +11 -0
- data/lib/active_merchant/billing/gateways/bogus.rb +132 -0
- data/lib/active_merchant/billing/gateways/braintree.rb +17 -0
- data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +9 -0
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +293 -0
- data/lib/active_merchant/billing/gateways/braintree_orange.rb +17 -0
- data/lib/active_merchant/billing/gateways/braspag.rb +188 -0
- data/lib/active_merchant/billing/gateways/card_stream.rb +230 -0
- data/lib/active_merchant/billing/gateways/cyber_source.rb +430 -0
- data/lib/active_merchant/billing/gateways/data_cash.rb +597 -0
- data/lib/active_merchant/billing/gateways/efsnet.rb +235 -0
- data/lib/active_merchant/billing/gateways/elavon.rb +134 -0
- data/lib/active_merchant/billing/gateways/epay.rb +268 -0
- data/lib/active_merchant/billing/gateways/eway.rb +277 -0
- data/lib/active_merchant/billing/gateways/eway_managed.rb +231 -0
- data/lib/active_merchant/billing/gateways/exact.rb +222 -0
- data/lib/active_merchant/billing/gateways/federated_canada.rb +168 -0
- data/lib/active_merchant/billing/gateways/first_pay.rb +177 -0
- data/lib/active_merchant/billing/gateways/garanti.rb +262 -0
- data/lib/active_merchant/billing/gateways/ideal/ideal_base.rb +250 -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 +55 -0
- data/lib/active_merchant/billing/gateways/inspire.rb +221 -0
- data/lib/active_merchant/billing/gateways/instapay.rb +164 -0
- data/lib/active_merchant/billing/gateways/iridium.rb +258 -0
- data/lib/active_merchant/billing/gateways/jetpay.rb +276 -0
- data/lib/active_merchant/billing/gateways/linkpoint.rb +454 -0
- data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +156 -0
- data/lib/active_merchant/billing/gateways/merchant_ware.rb +289 -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 +209 -0
- data/lib/active_merchant/billing/gateways/net_registry.rb +189 -0
- data/lib/active_merchant/billing/gateways/netaxept.rb +239 -0
- data/lib/active_merchant/billing/gateways/netbilling.rb +168 -0
- data/lib/active_merchant/billing/gateways/nmi.rb +13 -0
- data/lib/active_merchant/billing/gateways/ogone.rb +292 -0
- data/lib/active_merchant/billing/gateways/orbital.rb +321 -0
- data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +46 -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/paybox_direct.rb +207 -0
- data/lib/active_merchant/billing/gateways/payflow.rb +253 -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_express.rb +222 -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 +235 -0
- data/lib/active_merchant/billing/gateways/paypal.rb +121 -0
- data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +351 -0
- data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +49 -0
- data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
- data/lib/active_merchant/billing/gateways/paypal_express.rb +177 -0
- data/lib/active_merchant/billing/gateways/paypal_express_common.rb +25 -0
- data/lib/active_merchant/billing/gateways/plugnpay.rb +298 -0
- data/lib/active_merchant/billing/gateways/psigate.rb +219 -0
- data/lib/active_merchant/billing/gateways/psl_card.rb +304 -0
- data/lib/active_merchant/billing/gateways/qbms.rb +295 -0
- data/lib/active_merchant/billing/gateways/quantum.rb +282 -0
- data/lib/active_merchant/billing/gateways/quickpay.rb +218 -0
- data/lib/active_merchant/billing/gateways/realex.rb +311 -0
- data/lib/active_merchant/billing/gateways/sage.rb +146 -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_pay.rb +320 -0
- data/lib/active_merchant/billing/gateways/sallie_mae.rb +144 -0
- data/lib/active_merchant/billing/gateways/secure_net.rb +330 -0
- data/lib/active_merchant/billing/gateways/secure_pay.rb +31 -0
- data/lib/active_merchant/billing/gateways/secure_pay_au.rb +193 -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 +271 -0
- data/lib/active_merchant/billing/gateways/stripe.rb +212 -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 +423 -0
- data/lib/active_merchant/billing/gateways/usa_epay.rb +194 -0
- data/lib/active_merchant/billing/gateways/verifi.rb +233 -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/worldpay.rb +280 -0
- data/lib/active_merchant/billing/integrations.rb +17 -0
- data/lib/active_merchant/billing/integrations/action_view_helper.rb +68 -0
- data/lib/active_merchant/billing/integrations/bogus.rb +23 -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/chronopay.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/direc_pay.rb +41 -0
- data/lib/active_merchant/billing/integrations/direc_pay/helper.rb +200 -0
- data/lib/active_merchant/billing/integrations/direc_pay/notification.rb +76 -0
- data/lib/active_merchant/billing/integrations/direc_pay/return.rb +32 -0
- data/lib/active_merchant/billing/integrations/direc_pay/status.rb +37 -0
- data/lib/active_merchant/billing/integrations/directebanking.rb +47 -0
- data/lib/active_merchant/billing/integrations/directebanking/helper.rb +90 -0
- data/lib/active_merchant/billing/integrations/directebanking/notification.rb +120 -0
- data/lib/active_merchant/billing/integrations/directebanking/return.rb +11 -0
- data/lib/active_merchant/billing/integrations/e_payment_plans.rb +48 -0
- data/lib/active_merchant/billing/integrations/e_payment_plans/helper.rb +34 -0
- data/lib/active_merchant/billing/integrations/e_payment_plans/notification.rb +84 -0
- data/lib/active_merchant/billing/integrations/gestpay.rb +25 -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/helper.rb +96 -0
- data/lib/active_merchant/billing/integrations/hi_trust.rb +27 -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/moneybookers.rb +26 -0
- data/lib/active_merchant/billing/integrations/moneybookers/helper.rb +59 -0
- data/lib/active_merchant/billing/integrations/moneybookers/notification.rb +129 -0
- data/lib/active_merchant/billing/integrations/nochex.rb +88 -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/notification.rb +62 -0
- data/lib/active_merchant/billing/integrations/paypal.rb +39 -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/quickpay.rb +21 -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/return.rb +42 -0
- data/lib/active_merchant/billing/integrations/sage_pay_form.rb +37 -0
- data/lib/active_merchant/billing/integrations/sage_pay_form/encryption.rb +33 -0
- data/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb +111 -0
- data/lib/active_merchant/billing/integrations/sage_pay_form/notification.rb +210 -0
- data/lib/active_merchant/billing/integrations/sage_pay_form/return.rb +31 -0
- data/lib/active_merchant/billing/integrations/two_checkout.rb +23 -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/valitor.rb +33 -0
- data/lib/active_merchant/billing/integrations/valitor/helper.rb +86 -0
- data/lib/active_merchant/billing/integrations/valitor/notification.rb +13 -0
- data/lib/active_merchant/billing/integrations/valitor/response_fields.rb +97 -0
- data/lib/active_merchant/billing/integrations/valitor/return.rb +13 -0
- data/lib/active_merchant/billing/integrations/world_pay.rb +27 -0
- data/lib/active_merchant/billing/integrations/world_pay/helper.rb +100 -0
- data/lib/active_merchant/billing/integrations/world_pay/notification.rb +160 -0
- data/lib/active_merchant/billing/response.rb +32 -0
- data/lib/active_merchant/common.rb +14 -0
- data/lib/active_merchant/common/connection.rb +177 -0
- data/lib/active_merchant/common/country.rb +328 -0
- data/lib/active_merchant/common/error.rb +26 -0
- data/lib/active_merchant/common/post_data.rb +24 -0
- data/lib/active_merchant/common/posts_data.rb +63 -0
- data/lib/active_merchant/common/requires_parameters.rb +16 -0
- data/lib/active_merchant/common/utils.rb +22 -0
- data/lib/active_merchant/common/validateable.rb +81 -0
- data/lib/active_merchant/version.rb +3 -0
- data/lib/activemerchant.rb +1 -0
- data/lib/certs/cacert.pem +7815 -0
- data/lib/support/gateway_support.rb +58 -0
- data/lib/support/outbound_hosts.rb +25 -0
- metadata +276 -0
@@ -0,0 +1,219 @@
|
|
1
|
+
# This class implements the Psigate gateway for the ActiveMerchant module.
|
2
|
+
# Psigate = http://www.psigate.com/ The class is currently set up to use
|
3
|
+
# the psigate test server while rails is in testing or developement mode.
|
4
|
+
# The real server will be used while in production mode.
|
5
|
+
#
|
6
|
+
# Modifications by Sean O'Hara ( sohara at sohara dot com )
|
7
|
+
#
|
8
|
+
# Usage for a PreAuth (authorize) is as follows:
|
9
|
+
#
|
10
|
+
# twenty = 2000
|
11
|
+
# gateway = PsigateGateway.new(
|
12
|
+
# :login => 'teststore',
|
13
|
+
# :password => 'psigate1234'
|
14
|
+
# )
|
15
|
+
#
|
16
|
+
# creditcard = CreditCard.new(
|
17
|
+
# :number => '4242424242424242',
|
18
|
+
# :month => 8,
|
19
|
+
# :year => 2006,
|
20
|
+
# :first_name => 'Longbob',
|
21
|
+
# :last_name => 'Longsen'
|
22
|
+
# )
|
23
|
+
# response = @gateway.authorize(twenty, creditcard,
|
24
|
+
# :order_id => 1234,
|
25
|
+
# :billing_address => {
|
26
|
+
# :address1 => '123 fairweather Lane',
|
27
|
+
# :address2 => 'Apt B',
|
28
|
+
# :city => 'New York',
|
29
|
+
# :state => 'NY',
|
30
|
+
# :country => 'U.S.A.',
|
31
|
+
# :zip => '10010'
|
32
|
+
# },
|
33
|
+
# :email => 'jack@yahoo.com'
|
34
|
+
# )
|
35
|
+
|
36
|
+
require 'rexml/document'
|
37
|
+
|
38
|
+
module ActiveMerchant #:nodoc:
|
39
|
+
module Billing #:nodoc:
|
40
|
+
|
41
|
+
class PsigateGateway < Gateway
|
42
|
+
TEST_URL = 'https://dev.psigate.com:7989/Messenger/XMLMessenger'
|
43
|
+
LIVE_URL = 'https://secure.psigate.com:7934/Messenger/XMLMessenger'
|
44
|
+
|
45
|
+
self.supported_cardtypes = [:visa, :master, :american_express]
|
46
|
+
self.supported_countries = ['CA']
|
47
|
+
self.homepage_url = 'http://www.psigate.com/'
|
48
|
+
self.display_name = 'Psigate'
|
49
|
+
|
50
|
+
SUCCESS_MESSAGE = 'Success'
|
51
|
+
FAILURE_MESSAGE = 'The transaction was declined'
|
52
|
+
|
53
|
+
def initialize(options = {})
|
54
|
+
requires!(options, :login, :password)
|
55
|
+
@options = options
|
56
|
+
super
|
57
|
+
end
|
58
|
+
|
59
|
+
# Psigate PreAuth
|
60
|
+
def authorize(money, creditcard, options = {})
|
61
|
+
requires!(options, :order_id)
|
62
|
+
options.update({ :CardAction => "1" })
|
63
|
+
commit(money, creditcard, options)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Psigate Sale
|
67
|
+
def purchase(money, creditcard, options = {})
|
68
|
+
requires!(options, :order_id)
|
69
|
+
options.update({ :CardAction => "0" })
|
70
|
+
commit(money, creditcard, options)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Psigate PostAuth
|
74
|
+
def capture(money, authorization, options = {})
|
75
|
+
options.update({ :CardAction => "2", :order_id => authorization })
|
76
|
+
commit(money, nil, options)
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
# Psigate Credit
|
81
|
+
def credit(money, authorization, options = {})
|
82
|
+
deprecated CREDIT_DEPRECATION_MESSAGE
|
83
|
+
refund(money, authorization, options)
|
84
|
+
end
|
85
|
+
|
86
|
+
def refund(money, authorization, options = {})
|
87
|
+
options.update({ :CardAction => "3", :order_id => authorization })
|
88
|
+
commit(money, nil, options)
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def commit(money, creditcard, options = {})
|
94
|
+
response = parse(ssl_post(test? ? TEST_URL : LIVE_URL, post_data(money, creditcard, options)))
|
95
|
+
|
96
|
+
Response.new(successful?(response), message_from(response), response,
|
97
|
+
:test => test?,
|
98
|
+
:authorization => response[:orderid],
|
99
|
+
:avs_result => { :code => response[:avsresult] },
|
100
|
+
:cvv_result => response[:cardidresult]
|
101
|
+
)
|
102
|
+
end
|
103
|
+
|
104
|
+
def successful?(response)
|
105
|
+
response[:approved] == "APPROVED"
|
106
|
+
end
|
107
|
+
|
108
|
+
def parse(xml)
|
109
|
+
response = {:message => "Global Error Receipt", :complete => false}
|
110
|
+
|
111
|
+
xml = REXML::Document.new(xml)
|
112
|
+
xml.elements.each('//Result/*') do |node|
|
113
|
+
|
114
|
+
response[node.name.downcase.to_sym] = normalize(node.text)
|
115
|
+
|
116
|
+
end unless xml.root.nil?
|
117
|
+
|
118
|
+
response
|
119
|
+
end
|
120
|
+
|
121
|
+
def post_data(money, creditcard, options)
|
122
|
+
xml = REXML::Document.new
|
123
|
+
xml << REXML::XMLDecl.new
|
124
|
+
root = xml.add_element("Order")
|
125
|
+
|
126
|
+
for key, value in parameters(money, creditcard, options)
|
127
|
+
root.add_element(key.to_s).text = value if value
|
128
|
+
end
|
129
|
+
|
130
|
+
xml.to_s
|
131
|
+
end
|
132
|
+
|
133
|
+
# Set up the parameters hash just once so we don't have to do it
|
134
|
+
# for every action.
|
135
|
+
def parameters(money, creditcard, options = {})
|
136
|
+
params = {
|
137
|
+
# General order paramters
|
138
|
+
:StoreID => @options[:login],
|
139
|
+
:Passphrase => @options[:password],
|
140
|
+
:TestResult => options[:test_result],
|
141
|
+
:OrderID => options[:order_id],
|
142
|
+
:UserID => options[:user_id],
|
143
|
+
:Phone => options[:phone],
|
144
|
+
:Fax => options[:fax],
|
145
|
+
:Email => options[:email],
|
146
|
+
|
147
|
+
# Credit Card paramaters
|
148
|
+
:PaymentType => "CC",
|
149
|
+
:CardAction => options[:CardAction],
|
150
|
+
|
151
|
+
# Financial paramters
|
152
|
+
:CustomerIP => options[:ip],
|
153
|
+
:SubTotal => amount(money),
|
154
|
+
:Tax1 => options[:tax1],
|
155
|
+
:Tax2 => options[:tax2],
|
156
|
+
:ShippingTotal => options[:shipping_total],
|
157
|
+
}
|
158
|
+
|
159
|
+
if creditcard
|
160
|
+
exp_month = sprintf("%.2i", creditcard.month) unless creditcard.month.blank?
|
161
|
+
exp_year = creditcard.year.to_s[2,2] unless creditcard.year.blank?
|
162
|
+
card_id_code = creditcard.verification_value.blank? ? nil : "1"
|
163
|
+
|
164
|
+
params.update(
|
165
|
+
:CardNumber => creditcard.number,
|
166
|
+
:CardExpMonth => exp_month,
|
167
|
+
:CardExpYear => exp_year,
|
168
|
+
:CardIDCode => card_id_code,
|
169
|
+
:CardIDNumber => creditcard.verification_value
|
170
|
+
)
|
171
|
+
end
|
172
|
+
|
173
|
+
if address = options[:billing_address] || options[:address]
|
174
|
+
params[:Bname] = address[:name] || creditcard.name
|
175
|
+
params[:Baddress1] = address[:address1] unless address[:address1].blank?
|
176
|
+
params[:Baddress2] = address[:address2] unless address[:address2].blank?
|
177
|
+
params[:Bcity] = address[:city] unless address[:city].blank?
|
178
|
+
params[:Bprovince] = address[:state] unless address[:state].blank?
|
179
|
+
params[:Bpostalcode] = address[:zip] unless address[:zip].blank?
|
180
|
+
params[:Bcountry] = address[:country] unless address[:country].blank?
|
181
|
+
params[:Bcompany] = address[:company] unless address[:company].blank?
|
182
|
+
end
|
183
|
+
|
184
|
+
if address = options[:shipping_address]
|
185
|
+
params[:Sname] = address[:name] || creditcard.name
|
186
|
+
params[:Saddress1] = address[:address1] unless address[:address1].blank?
|
187
|
+
params[:Saddress2] = address[:address2] unless address[:address2].blank?
|
188
|
+
params[:Scity] = address[:city] unless address[:city].blank?
|
189
|
+
params[:Sprovince] = address[:state] unless address[:state].blank?
|
190
|
+
params[:Spostalcode] = address[:zip] unless address[:zip].blank?
|
191
|
+
params[:Scountry] = address[:country] unless address[:country].blank?
|
192
|
+
params[:Scompany] = address[:company] unless address[:company].blank?
|
193
|
+
end
|
194
|
+
|
195
|
+
return params
|
196
|
+
end
|
197
|
+
|
198
|
+
def message_from(response)
|
199
|
+
if response[:approved] == "APPROVED"
|
200
|
+
return SUCCESS_MESSAGE
|
201
|
+
else
|
202
|
+
return FAILURE_MESSAGE if response[:errmsg].blank?
|
203
|
+
return response[:errmsg].gsub(/[^\w]/, ' ').split.join(" ").capitalize
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
# Make a ruby type out of the response string
|
208
|
+
def normalize(field)
|
209
|
+
case field
|
210
|
+
when "true" then true
|
211
|
+
when "false" then false
|
212
|
+
when "" then nil
|
213
|
+
when "null" then nil
|
214
|
+
else field
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
@@ -0,0 +1,304 @@
|
|
1
|
+
module ActiveMerchant
|
2
|
+
module Billing
|
3
|
+
#
|
4
|
+
# ActiveMerchant PSL Card Gateway
|
5
|
+
#
|
6
|
+
# Notes:
|
7
|
+
# -To be able to use the capture function, the IP address of the machine must be
|
8
|
+
# registered with PSL
|
9
|
+
# -ESALE_KEYED should only be used in situations where the cardholder perceives the
|
10
|
+
# transaction to be Internet-based, such as purchasing from a web site/on-line store.
|
11
|
+
# If the Internet is used purely for the transport of information from the merchant
|
12
|
+
# directly to the gateway then the appropriate cardholder present or not present message
|
13
|
+
# type should be used rather than the ‘E’ equivalent.
|
14
|
+
# -The CV2 / AVS policies are set up with the account settings when signing up for an account
|
15
|
+
class PslCardGateway < Gateway
|
16
|
+
self.money_format = :cents
|
17
|
+
self.default_currency = 'GBP'
|
18
|
+
|
19
|
+
self.supported_countries = ['GB']
|
20
|
+
# Visa Credit, Visa Debit, Mastercard, Maestro, Solo, Electron,
|
21
|
+
# American Express, Diners Club, JCB, International Maestro,
|
22
|
+
# Style, Clydesdale Financial Services, Other
|
23
|
+
|
24
|
+
self.supported_cardtypes = [ :visa, :master, :american_express, :diners_club, :jcb, :switch, :solo, :maestro ]
|
25
|
+
self.homepage_url = 'http://www.paymentsolutionsltd.com/'
|
26
|
+
self.display_name = 'PSL Payment Solutions'
|
27
|
+
|
28
|
+
# Default ISO 3166 country code (GB)
|
29
|
+
cattr_accessor :location
|
30
|
+
self.location = 826
|
31
|
+
|
32
|
+
# PslCard server URL - The url is the same whether testing or live - use
|
33
|
+
# the test account when testing...
|
34
|
+
URL = 'https://pslcard3.paymentsolutionsltd.com/secure/transact.asp?'
|
35
|
+
|
36
|
+
# eCommerce sale transaction, details keyed by merchant or cardholder
|
37
|
+
MESSAGE_TYPE = 'ESALE_KEYED'
|
38
|
+
|
39
|
+
# The type of response that we want to get from PSL, options are HTML, XML or REDIRECT
|
40
|
+
RESPONSE_ACTION = 'HTML'
|
41
|
+
|
42
|
+
# Currency Codes
|
43
|
+
CURRENCY_CODES = {
|
44
|
+
'AUD' => 036,
|
45
|
+
'GBP' => 826,
|
46
|
+
'USD' => 840
|
47
|
+
}
|
48
|
+
|
49
|
+
#The terminal used - only for swipe transactions, so hard coded to 32 for online
|
50
|
+
EMV_TERMINAL_TYPE = 32
|
51
|
+
|
52
|
+
#Different Dispatch types
|
53
|
+
DISPATCH_LATER = 'LATER'
|
54
|
+
DISPATCH_NOW = 'NOW'
|
55
|
+
|
56
|
+
# Return codes
|
57
|
+
APPROVED = '00'
|
58
|
+
|
59
|
+
#Nominal amount to authorize for a 'dispatch later' type
|
60
|
+
#The nominal amount is held straight away, when the goods are ready
|
61
|
+
#to be dispatched, PSL is informed and the full amount is the
|
62
|
+
#taken.
|
63
|
+
NOMINAL_AMOUNT = 101
|
64
|
+
|
65
|
+
AVS_CODE = {
|
66
|
+
"ALL MATCH" => 'Y',
|
67
|
+
"SECURITY CODE MATCH ONLY" => 'N',
|
68
|
+
"ADDRESS MATCH ONLY" => 'Y',
|
69
|
+
"NO DATA MATCHES" => 'N',
|
70
|
+
"DATA NOT CHECKED" => 'R',
|
71
|
+
"SECURITY CHECKS NOT SUPPORTED" => 'X'
|
72
|
+
}
|
73
|
+
|
74
|
+
CVV_CODE = {
|
75
|
+
"ALL MATCH" => 'M',
|
76
|
+
"SECURITY CODE MATCH ONLY" => 'M',
|
77
|
+
"ADDRESS MATCH ONLY" => 'N',
|
78
|
+
"NO DATA MATCHES" => 'N',
|
79
|
+
"DATA NOT CHECKED" => 'P',
|
80
|
+
"SECURITY CHECKS NOT SUPPORTED" => 'X'
|
81
|
+
}
|
82
|
+
|
83
|
+
# Create a new PslCardGateway
|
84
|
+
#
|
85
|
+
# The gateway requires that a valid :login be passed in the options hash
|
86
|
+
#
|
87
|
+
# Paramaters:
|
88
|
+
# -options:
|
89
|
+
# :login - the PslCard account login (required)
|
90
|
+
def initialize(options = {})
|
91
|
+
requires!(options, :login)
|
92
|
+
|
93
|
+
@options = options
|
94
|
+
super
|
95
|
+
end
|
96
|
+
|
97
|
+
# Purchase the item straight away
|
98
|
+
#
|
99
|
+
# Parameters:
|
100
|
+
# -money: Amount to be charged as an Integer value in cents
|
101
|
+
# -authorization: the PSL cross reference from the previous authorization
|
102
|
+
# -options:
|
103
|
+
#
|
104
|
+
# Returns:
|
105
|
+
# -ActiveRecord::Billing::Response object
|
106
|
+
#
|
107
|
+
def purchase(money, credit_card, options = {})
|
108
|
+
post = {}
|
109
|
+
|
110
|
+
add_amount(post, money, DISPATCH_NOW, options)
|
111
|
+
add_credit_card(post, credit_card)
|
112
|
+
add_address(post, options)
|
113
|
+
add_invoice(post, options)
|
114
|
+
add_purchase_details(post)
|
115
|
+
|
116
|
+
commit(post)
|
117
|
+
end
|
118
|
+
|
119
|
+
# Authorize the transaction
|
120
|
+
#
|
121
|
+
# Reserves the funds on the customer's credit card, but does not
|
122
|
+
# charge the card.
|
123
|
+
#
|
124
|
+
# This implementation does not authorize the full amount, rather it checks that the full amount
|
125
|
+
# is available and only 'reserves' the nominal amount (currently a pound and a penny)
|
126
|
+
#
|
127
|
+
# Parameters:
|
128
|
+
# -money: Amount to be charged as an Integer value in cents
|
129
|
+
# -authorization: the PSL cross reference from the previous authorization
|
130
|
+
# -options:
|
131
|
+
#
|
132
|
+
# Returns:
|
133
|
+
# -ActiveRecord::Billing::Response object
|
134
|
+
#
|
135
|
+
def authorize(money, credit_card, options = {})
|
136
|
+
post = {}
|
137
|
+
|
138
|
+
add_amount(post, money, DISPATCH_LATER, options)
|
139
|
+
add_credit_card(post, credit_card)
|
140
|
+
add_address(post, options)
|
141
|
+
add_invoice(post, options)
|
142
|
+
add_purchase_details(post)
|
143
|
+
|
144
|
+
commit(post)
|
145
|
+
end
|
146
|
+
|
147
|
+
# Post an authorization.
|
148
|
+
#
|
149
|
+
# Captures the funds from an authorized transaction.
|
150
|
+
#
|
151
|
+
# Parameters:
|
152
|
+
# -money: Amount to be charged as an Integer value in cents
|
153
|
+
# -authorization: The PSL Cross Reference
|
154
|
+
# -options:
|
155
|
+
#
|
156
|
+
# Returns:
|
157
|
+
# -ActiveRecord::Billing::Response object
|
158
|
+
#
|
159
|
+
def capture(money, authorization, options = {})
|
160
|
+
post = {}
|
161
|
+
|
162
|
+
add_amount(post, money, DISPATCH_NOW, options)
|
163
|
+
add_reference(post, authorization)
|
164
|
+
add_purchase_details(post)
|
165
|
+
|
166
|
+
commit(post)
|
167
|
+
end
|
168
|
+
|
169
|
+
private
|
170
|
+
|
171
|
+
def add_credit_card(post, credit_card)
|
172
|
+
post[:QAName] = credit_card.name
|
173
|
+
post[:CardNumber] = credit_card.number
|
174
|
+
post[:EMVTerminalType] = EMV_TERMINAL_TYPE
|
175
|
+
post[:ExpMonth] = credit_card.month
|
176
|
+
post[:ExpYear] = credit_card.year
|
177
|
+
|
178
|
+
if requires_start_date_or_issue_number?(credit_card)
|
179
|
+
post[:IssueNumber] = credit_card.issue_number unless credit_card.issue_number.blank?
|
180
|
+
post[:StartMonth] = credit_card.start_month unless credit_card.start_month.blank?
|
181
|
+
post[:StartYear] = credit_card.start_year unless credit_card.start_year.blank?
|
182
|
+
end
|
183
|
+
|
184
|
+
# CV2 check
|
185
|
+
post[:AVSCV2Check] = credit_card.verification_value? ? 'YES' : 'NO'
|
186
|
+
post[:CV2] = credit_card.verification_value if credit_card.verification_value?
|
187
|
+
end
|
188
|
+
|
189
|
+
def add_address(post, options)
|
190
|
+
address = options[:billing_address] || options[:address]
|
191
|
+
return if address.nil?
|
192
|
+
|
193
|
+
post[:QAAddress] = [:address1, :address2, :city, :state].collect{|a| address[a]}.reject{|a| a.blank?}.join(' ')
|
194
|
+
post[:QAPostcode] = address[:zip]
|
195
|
+
end
|
196
|
+
|
197
|
+
def add_invoice(post, options)
|
198
|
+
post[:MerchantName] = options[:merchant] || 'Merchant Name' # May use this as the order_id field
|
199
|
+
post[:OrderID] = options[:order_id] unless options[:order_id].blank?
|
200
|
+
end
|
201
|
+
|
202
|
+
def add_reference(post, authorization)
|
203
|
+
post[:CrossReference] = authorization
|
204
|
+
end
|
205
|
+
|
206
|
+
def add_amount(post, money, dispatch_type, options)
|
207
|
+
post[:CurrencyCode] = currency_code(options[:currency] || currency(money))
|
208
|
+
|
209
|
+
if dispatch_type == DISPATCH_LATER
|
210
|
+
post[:amount] = amount(NOMINAL_AMOUNT)
|
211
|
+
post[:DispatchLaterAmount] = amount(money)
|
212
|
+
else
|
213
|
+
post[:amount] = amount(money)
|
214
|
+
end
|
215
|
+
|
216
|
+
post[:Dispatch] = dispatch_type
|
217
|
+
end
|
218
|
+
|
219
|
+
def add_purchase_details(post)
|
220
|
+
post[:EchoAmount] = 'YES'
|
221
|
+
post[:SCBI] = 'YES' # Return information about the transaction
|
222
|
+
post[:MessageType] = MESSAGE_TYPE
|
223
|
+
end
|
224
|
+
|
225
|
+
# Get the currency code for the passed money object
|
226
|
+
#
|
227
|
+
# The money class stores the currency as an ISO 4217:2001 Alphanumeric,
|
228
|
+
# however PSL requires the ISO 4217:2001 Numeric code.
|
229
|
+
#
|
230
|
+
# Parameters:
|
231
|
+
# -money: Integer value in cents
|
232
|
+
#
|
233
|
+
# Returns:
|
234
|
+
# -the ISO 4217:2001 Numberic currency code
|
235
|
+
#
|
236
|
+
def currency_code(currency)
|
237
|
+
CURRENCY_CODES[currency]
|
238
|
+
end
|
239
|
+
|
240
|
+
# Parse the PSL response and create a Response object
|
241
|
+
#
|
242
|
+
# Parameters:
|
243
|
+
# -body: The response string returned from PSL, Formatted:
|
244
|
+
# Key=value&key=value...
|
245
|
+
#
|
246
|
+
# Returns:
|
247
|
+
# -a hash with all of the values returned in the PSL response
|
248
|
+
#
|
249
|
+
def parse(body)
|
250
|
+
|
251
|
+
fields = {}
|
252
|
+
for line in body.split('&')
|
253
|
+
key, value = *line.scan( %r{^(\w+)\=(.*)$} ).flatten
|
254
|
+
fields[key] = CGI.unescape(value)
|
255
|
+
end
|
256
|
+
fields.symbolize_keys
|
257
|
+
end
|
258
|
+
|
259
|
+
# Send the passed data to PSL for processing
|
260
|
+
#
|
261
|
+
# Parameters:
|
262
|
+
# -request: The data that is to be sent to PSL
|
263
|
+
#
|
264
|
+
# Returns:
|
265
|
+
# - ActiveMerchant::Billing::Response object
|
266
|
+
#
|
267
|
+
def commit(request)
|
268
|
+
response = parse( ssl_post(URL, post_data(request)) )
|
269
|
+
|
270
|
+
Response.new(response[:ResponseCode] == APPROVED, response[:Message], response,
|
271
|
+
:test => test?,
|
272
|
+
:authorization => response[:CrossReference],
|
273
|
+
:cvv_result => CVV_CODE[response[:AVSCV2Check]],
|
274
|
+
:avs_result => { :code => AVS_CODE[response[:AVSCV2Check]] }
|
275
|
+
)
|
276
|
+
end
|
277
|
+
|
278
|
+
# Put the passed data into a format that can be submitted to PSL
|
279
|
+
# Key=Value&Key=Value...
|
280
|
+
#
|
281
|
+
# Any ampersands and equal signs are removed from the data being posted
|
282
|
+
# as PSL puts them back into the response string which then cannot be parsed.
|
283
|
+
# This is after escaping before sending the request to PSL - this is a work
|
284
|
+
# around for the time being
|
285
|
+
#
|
286
|
+
# Parameters:
|
287
|
+
# -post: Hash of all the data to be sent
|
288
|
+
#
|
289
|
+
# Returns:
|
290
|
+
# -String: the data to be sent
|
291
|
+
#
|
292
|
+
def post_data(post)
|
293
|
+
post[:CountryCode] = self.location
|
294
|
+
post[:MerchantID] = @options[:login]
|
295
|
+
post[:ValidityID] = @options[:password]
|
296
|
+
post[:ResponseAction] = RESPONSE_ACTION
|
297
|
+
|
298
|
+
post.collect { |key, value|
|
299
|
+
"#{key}=#{CGI.escape(value.to_s.tr('&=', ' '))}"
|
300
|
+
}.join("&")
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|