tlconnor-activemerchant 1.20.4 → 1.23.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 +86 -6
- data/CONTRIBUTORS +33 -0
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +2 -0
- data/lib/active_merchant/billing/gateways/barclays_epdq.rb +4 -4
- data/lib/active_merchant/billing/gateways/blue_pay.rb +492 -11
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +46 -19
- data/lib/active_merchant/billing/gateways/certo_direct.rb +1 -1
- data/lib/active_merchant/billing/gateways/elavon.rb +2 -0
- data/lib/active_merchant/billing/gateways/epay.rb +3 -1
- data/lib/active_merchant/billing/gateways/itransact.rb +450 -0
- data/lib/active_merchant/billing/gateways/litle.rb +275 -0
- data/lib/active_merchant/billing/gateways/migs.rb +259 -0
- data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +100 -0
- data/lib/active_merchant/billing/gateways/moneris.rb +4 -30
- data/lib/active_merchant/billing/gateways/moneris_us.rb +211 -0
- data/lib/active_merchant/billing/gateways/nab_transact.rb +1 -1
- data/lib/active_merchant/billing/gateways/ogone.rb +104 -12
- data/lib/active_merchant/billing/gateways/orbital.rb +15 -6
- data/lib/active_merchant/billing/gateways/paybox_direct.rb +1 -4
- data/lib/active_merchant/billing/gateways/payflow.rb +8 -3
- data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +4 -1
- data/lib/active_merchant/billing/gateways/payflow_express.rb +4 -2
- data/lib/active_merchant/billing/gateways/payment_express.rb +60 -13
- data/lib/active_merchant/billing/gateways/paypal.rb +3 -18
- data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +333 -3
- data/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb +245 -0
- data/lib/active_merchant/billing/gateways/paypal_digital_goods.rb +43 -0
- data/lib/active_merchant/billing/gateways/paypal_express.rb +14 -65
- data/lib/active_merchant/billing/gateways/paypal_express_common.rb +8 -3
- data/lib/active_merchant/billing/gateways/realex.rb +5 -7
- data/lib/active_merchant/billing/gateways/secure_pay_au.rb +3 -2
- data/lib/active_merchant/billing/gateways/stripe.rb +1 -9
- data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +2 -2
- data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +1 -5
- data/lib/active_merchant/billing/gateways/viaklix.rb +7 -2
- data/lib/active_merchant/billing/gateways/vindicia.rb +359 -0
- data/lib/active_merchant/billing/integrations/dotpay.rb +22 -0
- data/lib/active_merchant/billing/integrations/dotpay/helper.rb +77 -0
- data/lib/active_merchant/billing/integrations/dotpay/notification.rb +86 -0
- data/lib/active_merchant/billing/integrations/dotpay/return.rb +11 -0
- data/lib/active_merchant/billing/integrations/epay.rb +21 -0
- data/lib/active_merchant/billing/integrations/epay/helper.rb +55 -0
- data/lib/active_merchant/billing/integrations/epay/notification.rb +110 -0
- data/lib/active_merchant/billing/integrations/paypal/notification.rb +2 -1
- data/lib/active_merchant/billing/integrations/quickpay/helper.rb +2 -3
- data/lib/active_merchant/billing/integrations/robokassa.rb +49 -0
- data/lib/active_merchant/billing/integrations/robokassa/common.rb +19 -0
- data/lib/active_merchant/billing/integrations/robokassa/helper.rb +50 -0
- data/lib/active_merchant/billing/integrations/robokassa/notification.rb +55 -0
- data/lib/active_merchant/billing/integrations/robokassa/return.rb +17 -0
- data/lib/active_merchant/billing/integrations/two_checkout.rb +25 -3
- data/lib/active_merchant/billing/integrations/two_checkout/helper.rb +58 -26
- data/lib/active_merchant/billing/integrations/two_checkout/notification.rb +71 -46
- data/lib/active_merchant/billing/integrations/verkkomaksut.rb +20 -0
- data/lib/active_merchant/billing/integrations/verkkomaksut/helper.rb +87 -0
- data/lib/active_merchant/billing/integrations/verkkomaksut/notification.rb +59 -0
- data/lib/active_merchant/version.rb +1 -1
- metadata +28 -5
@@ -0,0 +1,275 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'LitleOnline'
|
3
|
+
|
4
|
+
module ActiveMerchant #:nodoc:
|
5
|
+
module Billing #:nodoc:
|
6
|
+
class LitleGateway < Gateway
|
7
|
+
# Specific to Litle options:
|
8
|
+
# * <tt>:merchant_id</tt> - Merchant Id assigned by Litle
|
9
|
+
# * <tt>:user</tt> - Username assigned by Litle
|
10
|
+
# * <tt>:password</tt> - Password assigned by Litle
|
11
|
+
# * <tt>:version</tt> - The version of the api you are using (eg, '8.10')
|
12
|
+
# * <tt>:proxy_addr</tt> - Proxy address - nil if not needed
|
13
|
+
# * <tt>:proxy_port</tt> - Proxy port - nil if not needed
|
14
|
+
# * <tt>:url</tt> - URL assigned by Litle (for testing, use the sandbox)
|
15
|
+
#
|
16
|
+
# Standard Active Merchant options
|
17
|
+
# * <tt>:order_id</tt> - The order number
|
18
|
+
# * <tt>:ip</tt> - The IP address of the customer making the purchase
|
19
|
+
# * <tt>:customer</tt> - The name, customer number, or other information that identifies the customer
|
20
|
+
# * <tt>:invoice</tt> - The invoice number
|
21
|
+
# * <tt>:merchant</tt> - The name or description of the merchant offering the product
|
22
|
+
# * <tt>:description</tt> - A description of the transaction
|
23
|
+
# * <tt>:email</tt> - The email address of the customer
|
24
|
+
# * <tt>:currency</tt> - The currency of the transaction. Only important when you are using a currency that is not the default with a gateway that supports multiple currencies.
|
25
|
+
# * <tt>:billing_address</tt> - A hash containing the billing address of the customer.
|
26
|
+
# * <tt>:shipping_address</tt> - A hash containing the shipping address of the customer.
|
27
|
+
#
|
28
|
+
# The <tt>:billing_address</tt>, and <tt>:shipping_address</tt> hashes can have the following keys:
|
29
|
+
#
|
30
|
+
# * <tt>:name</tt> - The full name of the customer.
|
31
|
+
# * <tt>:company</tt> - The company name of the customer.
|
32
|
+
# * <tt>:address1</tt> - The primary street address of the customer.
|
33
|
+
# * <tt>:address2</tt> - Additional line of address information.
|
34
|
+
# * <tt>:city</tt> - The city of the customer.
|
35
|
+
# * <tt>:state</tt> - The state of the customer. The 2 digit code for US and Canadian addresses. The full name of the state or province for foreign addresses.
|
36
|
+
# * <tt>:country</tt> - The [ISO 3166-1-alpha-2 code](http://www.iso.org/iso/country_codes/iso_3166_code_lists/english_country_names_and_code_elements.htm) for the customer.
|
37
|
+
# * <tt>:zip</tt> - The zip or postal code of the customer.
|
38
|
+
# * <tt>:phone</tt> - The phone number of the customer.
|
39
|
+
|
40
|
+
TEST_URL = 'https://www.testlitle.com/sandbox/communicator/online'
|
41
|
+
LIVE_URL = 'https://payments.litle.com/vap/communicator/online'
|
42
|
+
|
43
|
+
# The countries the gateway supports merchants from as 2 digit ISO country codes
|
44
|
+
self.supported_countries = ['US']
|
45
|
+
|
46
|
+
# The card types supported by the payment gateway
|
47
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb]
|
48
|
+
|
49
|
+
# The homepage URL of the gateway
|
50
|
+
self.homepage_url = 'http://www.litle.com/'
|
51
|
+
|
52
|
+
# The name of the gateway
|
53
|
+
self.display_name = 'Litle & Co.'
|
54
|
+
|
55
|
+
self.default_currency = 'USD'
|
56
|
+
|
57
|
+
def initialize(options = {})
|
58
|
+
@litle = LitleOnline::LitleOnlineRequest.new
|
59
|
+
requires!(options, :merchant_id, :user, :password, :version, :url)
|
60
|
+
@options = options
|
61
|
+
end
|
62
|
+
|
63
|
+
def authorize(money, creditcard, options = {})
|
64
|
+
to_pass = create_credit_card_hash(money, creditcard, options)
|
65
|
+
build_response(:authorization, @litle.authorization(to_pass))
|
66
|
+
end
|
67
|
+
|
68
|
+
def purchase(money, creditcard, options = {})
|
69
|
+
to_pass = create_credit_card_hash(money, creditcard, options)
|
70
|
+
build_response(:sale, @litle.sale(to_pass))
|
71
|
+
end
|
72
|
+
|
73
|
+
def capture(money, authorization, options = {})
|
74
|
+
to_pass = create_capture_hash(money, authorization, options)
|
75
|
+
build_response(:capture, @litle.capture(to_pass))
|
76
|
+
end
|
77
|
+
|
78
|
+
def void(identification, options = {})
|
79
|
+
to_pass = create_void_hash(identification, options)
|
80
|
+
build_response(:void, @litle.void(to_pass))
|
81
|
+
end
|
82
|
+
|
83
|
+
def credit(money, identification, options = {})
|
84
|
+
to_pass = create_credit_hash(money, identification, options)
|
85
|
+
build_response(:credit, @litle.credit(to_pass))
|
86
|
+
end
|
87
|
+
|
88
|
+
def store(creditcard, options = {})
|
89
|
+
to_pass = create_token_hash(creditcard, options)
|
90
|
+
build_response(:registerToken, @litle.register_token_request(to_pass), %w(801 802))
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
CARD_TYPE = {
|
96
|
+
'visa' => 'VI',
|
97
|
+
'master' => 'MC',
|
98
|
+
'american_express' => 'AX',
|
99
|
+
'discover' => 'DI',
|
100
|
+
'jcb' => 'DI',
|
101
|
+
'diners_club' => 'DI'
|
102
|
+
}
|
103
|
+
|
104
|
+
AVS_RESPONSE_CODE = {
|
105
|
+
'00' => 'Y',
|
106
|
+
'01' => 'X',
|
107
|
+
'02' => 'D',
|
108
|
+
'10' => 'Z',
|
109
|
+
'11' => 'W',
|
110
|
+
'12' => 'A',
|
111
|
+
'13' => 'A',
|
112
|
+
'14' => 'P',
|
113
|
+
'20' => 'N',
|
114
|
+
'30' => 'S',
|
115
|
+
'31' => 'R',
|
116
|
+
'32' => 'U',
|
117
|
+
'33' => 'R',
|
118
|
+
'34' => 'I',
|
119
|
+
'40' => 'E'
|
120
|
+
}
|
121
|
+
|
122
|
+
def build_response(kind, litle_response, valid_responses=%w(000))
|
123
|
+
if litle_response.response == "0"
|
124
|
+
detail = litle_response.send("#{kind}Response")
|
125
|
+
Response.new(
|
126
|
+
(valid_responses.include?(detail.response)),
|
127
|
+
detail.message,
|
128
|
+
{:litleOnlineResponse => litle_response},
|
129
|
+
:authorization => detail.litleTxnId,
|
130
|
+
:avs_result => {:code => fraud_result(detail)['avs']},
|
131
|
+
:cvv_result => fraud_result(detail)['cvv']
|
132
|
+
)
|
133
|
+
else
|
134
|
+
Response.new(false, litle_response.message, :litleOnlineResponse => litle_response)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def create_credit_card_hash(money, creditcard, options)
|
139
|
+
cc_type = CARD_TYPE[creditcard.type]
|
140
|
+
|
141
|
+
exp_date_yr = creditcard.year.to_s()[2..3]
|
142
|
+
|
143
|
+
if( creditcard.month.to_s().length == 1 )
|
144
|
+
exp_date_mo = '0' + creditcard.month.to_s()
|
145
|
+
else
|
146
|
+
exp_date_mo = creditcard.month.to_s()
|
147
|
+
end
|
148
|
+
|
149
|
+
exp_date = exp_date_mo + exp_date_yr
|
150
|
+
|
151
|
+
card_info = {
|
152
|
+
'type' => cc_type,
|
153
|
+
'number' => creditcard.number,
|
154
|
+
'expDate' => exp_date,
|
155
|
+
'cardValidationNum' => creditcard.verification_value
|
156
|
+
}
|
157
|
+
|
158
|
+
hash = create_hash(money, options)
|
159
|
+
hash['card'] = card_info
|
160
|
+
hash
|
161
|
+
end
|
162
|
+
|
163
|
+
def create_capture_hash(money, authorization, options)
|
164
|
+
hash = create_hash(money, options)
|
165
|
+
hash['litleTxnId'] = authorization
|
166
|
+
hash
|
167
|
+
end
|
168
|
+
|
169
|
+
def create_credit_hash(money, identification, options)
|
170
|
+
hash = create_hash(money, options)
|
171
|
+
hash['litleTxnId'] = identification
|
172
|
+
hash['orderSource'] = nil
|
173
|
+
hash['orderId'] = nil
|
174
|
+
hash
|
175
|
+
end
|
176
|
+
|
177
|
+
def create_token_hash(creditcard, options)
|
178
|
+
hash = create_hash(0, options)
|
179
|
+
hash['accountNumber'] = creditcard.number
|
180
|
+
hash
|
181
|
+
end
|
182
|
+
|
183
|
+
def create_void_hash(identification, options)
|
184
|
+
hash = create_hash(nil, options)
|
185
|
+
hash['litleTxnId'] = identification
|
186
|
+
hash
|
187
|
+
end
|
188
|
+
|
189
|
+
def create_hash(money, options)
|
190
|
+
fraud_check_type = {}
|
191
|
+
if options[:ip]
|
192
|
+
fraud_check_type['customerIpAddress'] = options[:ip]
|
193
|
+
end
|
194
|
+
|
195
|
+
enhanced_data = {}
|
196
|
+
if options[:invoice]
|
197
|
+
enhanced_data['invoiceReferenceNumber'] = options[:invoice]
|
198
|
+
end
|
199
|
+
|
200
|
+
if options[:description]
|
201
|
+
enhanced_data['customerReference'] = options[:description]
|
202
|
+
end
|
203
|
+
|
204
|
+
if options[:billing_address]
|
205
|
+
bill_to_address = {
|
206
|
+
'name' => options[:billing_address][:name],
|
207
|
+
'companyName' => options[:billing_address][:company],
|
208
|
+
'addressLine1' => options[:billing_address][:address1],
|
209
|
+
'addressLine2' => options[:billing_address][:address2],
|
210
|
+
'city' => options[:billing_address][:city],
|
211
|
+
'state' => options[:billing_address][:state],
|
212
|
+
'zip' => options[:billing_address][:zip],
|
213
|
+
'country' => options[:billing_address][:country],
|
214
|
+
'email' => options[:email],
|
215
|
+
'phone' => options[:billing_address][:phone]
|
216
|
+
}
|
217
|
+
end
|
218
|
+
if options[:shipping_address]
|
219
|
+
ship_to_address = {
|
220
|
+
'name' => options[:shipping_address][:name],
|
221
|
+
'companyName' => options[:shipping_address][:company],
|
222
|
+
'addressLine1' => options[:shipping_address][:address1],
|
223
|
+
'addressLine2' => options[:shipping_address][:address2],
|
224
|
+
'city' => options[:shipping_address][:city],
|
225
|
+
'state' => options[:shipping_address][:state],
|
226
|
+
'zip' => options[:shipping_address][:zip],
|
227
|
+
'country' => options[:shipping_address][:country],
|
228
|
+
'email' => options[:email],
|
229
|
+
'phone' => options[:shipping_address][:phone]
|
230
|
+
}
|
231
|
+
end
|
232
|
+
|
233
|
+
hash = {
|
234
|
+
'billToAddress' => bill_to_address,
|
235
|
+
'shipToAddress' => ship_to_address,
|
236
|
+
'orderId' => (options[:order_id] or @options[:order_id]),
|
237
|
+
'customerId' => options[:customer],
|
238
|
+
'reportGroup' => (options[:merchant] or @options[:merchant]),
|
239
|
+
'merchantId' => (options[:merchant_id] or @options[:merchant_id]),
|
240
|
+
'orderSource' => 'ecommerce',
|
241
|
+
'enhancedData' => enhanced_data,
|
242
|
+
'fraudCheckType' => fraud_check_type,
|
243
|
+
'user' => (options[:user] or @options[:user]),
|
244
|
+
'password' => (options[:password] or @options[:password]),
|
245
|
+
'version' => (options[:version] or @options[:version]),
|
246
|
+
'url' => (options[:url] or @options[:url]),
|
247
|
+
'proxy_addr' => (options[:proxy_addr] or @options[:proxy_addr]),
|
248
|
+
'proxy_port' => (options[:proxy_port] or @options[:proxy_port]),
|
249
|
+
'id' => (options[:id] or options[:order_id] or @options[:order_id])
|
250
|
+
}
|
251
|
+
|
252
|
+
if( !money.nil? && money.to_s.length > 0 )
|
253
|
+
hash.merge!({'amount' => money})
|
254
|
+
end
|
255
|
+
hash
|
256
|
+
end
|
257
|
+
|
258
|
+
def fraud_result(authorization_response)
|
259
|
+
if authorization_response.respond_to?('fraudResult')
|
260
|
+
fraud_result = authorization_response.fraudResult
|
261
|
+
if fraud_result.respond_to?('cardValidationResult')
|
262
|
+
cvv_to_pass = fraud_result.cardValidationResult
|
263
|
+
if(cvv_to_pass == "")
|
264
|
+
cvv_to_pass = "P"
|
265
|
+
end
|
266
|
+
end
|
267
|
+
if fraud_result.respond_to?('avsResult')
|
268
|
+
avs_to_pass = AVS_RESPONSE_CODE[fraud_result.avsResult]
|
269
|
+
end
|
270
|
+
end
|
271
|
+
{'cvv'=>cvv_to_pass, 'avs'=>avs_to_pass}
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
@@ -0,0 +1,259 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/migs/migs_codes'
|
2
|
+
|
3
|
+
require 'digest/md5' # Used in add_secure_hash
|
4
|
+
|
5
|
+
module ActiveMerchant #:nodoc:
|
6
|
+
module Billing #:nodoc:
|
7
|
+
class MigsGateway < Gateway
|
8
|
+
include MigsCodes
|
9
|
+
|
10
|
+
API_VERSION = 1
|
11
|
+
|
12
|
+
SERVER_HOSTED_URL = 'https://migs.mastercard.com.au/vpcpay'
|
13
|
+
MERCHANT_HOSTED_URL = 'https://migs.mastercard.com.au/vpcdps'
|
14
|
+
|
15
|
+
# MiGS is supported throughout Asia Pacific, Middle East and Africa
|
16
|
+
# MiGS is used in Australia (AU) by ANZ (eGate), CBA (CommWeb) and more
|
17
|
+
# Source of Country List: http://www.scribd.com/doc/17811923
|
18
|
+
self.supported_countries = %w(AU AE BD BN EG HK ID IN JO KW LB LK MU MV MY NZ OM PH QA SA SG TT VN)
|
19
|
+
|
20
|
+
# The card types supported by the payment gateway
|
21
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :jcb]
|
22
|
+
|
23
|
+
self.money_format = :cents
|
24
|
+
|
25
|
+
# The homepage URL of the gateway
|
26
|
+
self.homepage_url = 'http://mastercard.com/mastercardsps'
|
27
|
+
|
28
|
+
# The name of the gateway
|
29
|
+
self.display_name = 'MasterCard Internet Gateway Service (MiGS)'
|
30
|
+
|
31
|
+
# Creates a new MigsGateway
|
32
|
+
# The advanced_login/advanced_password fields are needed for
|
33
|
+
# advanced methods such as the capture, refund and status methods
|
34
|
+
#
|
35
|
+
# ==== Options
|
36
|
+
#
|
37
|
+
# * <tt>:login</tt> -- The MiGS Merchant ID (REQUIRED)
|
38
|
+
# * <tt>:password</tt> -- The MiGS Access Code (REQUIRED)
|
39
|
+
# * <tt>:secure_hash</tt> -- The MiGS Secure Hash
|
40
|
+
# (Required for Server Hosted payments)
|
41
|
+
# * <tt>:advanced_login</tt> -- The MiGS AMA User
|
42
|
+
# * <tt>:advanced_password</tt> -- The MiGS AMA User's password
|
43
|
+
def initialize(options = {})
|
44
|
+
requires!(options, :login, :password)
|
45
|
+
@test = options[:login].start_with?('TEST')
|
46
|
+
@options = options
|
47
|
+
super
|
48
|
+
end
|
49
|
+
|
50
|
+
# ==== Options
|
51
|
+
#
|
52
|
+
# * <tt>:order_id</tt> -- A reference for tracking the order (REQUIRED)
|
53
|
+
# * <tt>:unique_id</tt> -- A unique id for this request (Max 40 chars).
|
54
|
+
# If not supplied one will be generated.
|
55
|
+
def purchase(money, creditcard, options = {})
|
56
|
+
requires!(options, :order_id)
|
57
|
+
|
58
|
+
post = {}
|
59
|
+
post[:Amount] = amount(money)
|
60
|
+
add_invoice(post, options)
|
61
|
+
add_creditcard(post, creditcard)
|
62
|
+
add_standard_parameters('pay', post, options[:unique_id])
|
63
|
+
|
64
|
+
commit(post)
|
65
|
+
end
|
66
|
+
|
67
|
+
# MiGS works by merchants being either purchase only or authorize/capture
|
68
|
+
# So authorize is the same as purchase when in authorize mode
|
69
|
+
alias_method :authorize, :purchase
|
70
|
+
|
71
|
+
# ==== Options
|
72
|
+
#
|
73
|
+
# * <tt>:unique_id</tt> -- A unique id for this request (Max 40 chars).
|
74
|
+
# If not supplied one will be generated.
|
75
|
+
def capture(money, authorization, options = {})
|
76
|
+
requires!(@options, :advanced_login, :advanced_password)
|
77
|
+
|
78
|
+
post = options.merge(:TransNo => authorization)
|
79
|
+
post[:Amount] = amount(money)
|
80
|
+
add_advanced_user(post)
|
81
|
+
add_standard_parameters('capture', post, options[:unique_id])
|
82
|
+
|
83
|
+
commit(post)
|
84
|
+
end
|
85
|
+
|
86
|
+
# ==== Options
|
87
|
+
#
|
88
|
+
# * <tt>:unique_id</tt> -- A unique id for this request (Max 40 chars).
|
89
|
+
# If not supplied one will be generated.
|
90
|
+
def refund(money, authorization, options = {})
|
91
|
+
requires!(@options, :advanced_login, :advanced_password)
|
92
|
+
|
93
|
+
post = options.merge(:TransNo => authorization)
|
94
|
+
post[:Amount] = amount(money)
|
95
|
+
add_advanced_user(post)
|
96
|
+
add_standard_parameters('refund', post, options[:unique_id])
|
97
|
+
|
98
|
+
commit(post)
|
99
|
+
end
|
100
|
+
|
101
|
+
def credit(money, authorization, options = {})
|
102
|
+
deprecated CREDIT_DEPRECATION_MESSAGE
|
103
|
+
refund(money, authorization, options)
|
104
|
+
end
|
105
|
+
|
106
|
+
# Checks the status of a previous transaction
|
107
|
+
# This can be useful when a response is not received due to network issues
|
108
|
+
#
|
109
|
+
# ==== Parameters
|
110
|
+
#
|
111
|
+
# * <tt>unique_id</tt> -- Unique id of transaction to find.
|
112
|
+
# This is the value of the option supplied in other methods or
|
113
|
+
# if not supplied is returned with key :MerchTxnRef
|
114
|
+
def status(unique_id)
|
115
|
+
requires!(@options, :advanced_login, :advanced_password)
|
116
|
+
|
117
|
+
post = {}
|
118
|
+
add_advanced_user(post)
|
119
|
+
add_standard_parameters('queryDR', post, unique_id)
|
120
|
+
|
121
|
+
commit(post)
|
122
|
+
end
|
123
|
+
|
124
|
+
# Generates a URL to redirect user to MiGS to process payment
|
125
|
+
# Once user is finished MiGS will redirect back to specified URL
|
126
|
+
# With a response hash which can be turned into a Response object
|
127
|
+
# with purchase_offsite_response
|
128
|
+
#
|
129
|
+
# ==== Options
|
130
|
+
#
|
131
|
+
# * <tt>:order_id</tt> -- A reference for tracking the order (REQUIRED)
|
132
|
+
# * <tt>:locale</tt> -- Change the language of the redirected page
|
133
|
+
# Values are 2 digit locale, e.g. en, es
|
134
|
+
# * <tt>:return_url</tt> -- the URL to return to once the payment is complete
|
135
|
+
# * <tt>:card_type</tt> -- Providing this skips the card type step.
|
136
|
+
# Values are ActiveMerchant formats: e.g. master, visa, american_express, diners_club
|
137
|
+
# * <tt>:unique_id</tt> -- Unique id of transaction to find.
|
138
|
+
# If not supplied one will be generated.
|
139
|
+
def purchase_offsite_url(money, options = {})
|
140
|
+
requires!(options, :order_id, :return_url)
|
141
|
+
requires!(@options, :secure_hash)
|
142
|
+
|
143
|
+
post = {}
|
144
|
+
post[:Amount] = amount(money)
|
145
|
+
add_invoice(post, options)
|
146
|
+
add_creditcard_type(post, options[:card_type]) if options[:card_type]
|
147
|
+
|
148
|
+
post.merge!(
|
149
|
+
:Locale => options[:locale] || 'en',
|
150
|
+
:ReturnURL => options[:return_url]
|
151
|
+
)
|
152
|
+
|
153
|
+
add_standard_parameters('pay', post, options[:unique_id])
|
154
|
+
|
155
|
+
add_secure_hash(post)
|
156
|
+
|
157
|
+
SERVER_HOSTED_URL + '?' + post_data(post)
|
158
|
+
end
|
159
|
+
|
160
|
+
# Parses a response from purchase_offsite_url once user is redirected back
|
161
|
+
#
|
162
|
+
# ==== Parameters
|
163
|
+
#
|
164
|
+
# * <tt>data</tt> -- All params when offsite payment returns
|
165
|
+
# e.g. returns to http://company.com/return?a=1&b=2, then input "a=1&b=2"
|
166
|
+
def purchase_offsite_response(data)
|
167
|
+
requires!(@options, :secure_hash)
|
168
|
+
|
169
|
+
response_hash = parse(data)
|
170
|
+
|
171
|
+
expected_secure_hash = calculate_secure_hash(response_hash.reject{|k, v| k == :SecureHash}, @options[:secure_hash])
|
172
|
+
unless response_hash[:SecureHash] == expected_secure_hash
|
173
|
+
raise SecurityError, "Secure Hash mismatch, response may be tampered with"
|
174
|
+
end
|
175
|
+
|
176
|
+
response_object(response_hash)
|
177
|
+
end
|
178
|
+
|
179
|
+
private
|
180
|
+
|
181
|
+
def add_advanced_user(post)
|
182
|
+
post[:User] = @options[:advanced_login]
|
183
|
+
post[:Password] = @options[:advanced_password]
|
184
|
+
end
|
185
|
+
|
186
|
+
def add_invoice(post, options)
|
187
|
+
post[:OrderInfo] = options[:order_id]
|
188
|
+
end
|
189
|
+
|
190
|
+
def add_creditcard(post, creditcard)
|
191
|
+
post[:CardNum] = creditcard.number
|
192
|
+
post[:CardSecurityCode] = creditcard.verification_value if creditcard.verification_value?
|
193
|
+
post[:CardExp] = format(creditcard.year, :two_digits) + format(creditcard.month, :two_digits)
|
194
|
+
end
|
195
|
+
|
196
|
+
def add_creditcard_type(post, card_type)
|
197
|
+
post[:Gateway] = 'ssl'
|
198
|
+
post[:card] = CARD_TYPES.detect{|ct| ct.am_code == card_type}.migs_long_code
|
199
|
+
end
|
200
|
+
|
201
|
+
def parse(body)
|
202
|
+
params = CGI::parse(body)
|
203
|
+
hash = {}
|
204
|
+
params.each do |key, value|
|
205
|
+
hash[key.gsub('vpc_', '').to_sym] = value[0]
|
206
|
+
end
|
207
|
+
hash
|
208
|
+
end
|
209
|
+
|
210
|
+
def commit(post)
|
211
|
+
data = ssl_post MERCHANT_HOSTED_URL, post_data(post)
|
212
|
+
response_hash = parse(data)
|
213
|
+
response_object(response_hash)
|
214
|
+
end
|
215
|
+
|
216
|
+
def response_object(response)
|
217
|
+
Response.new(success?(response), response[:Message], response,
|
218
|
+
:test => @test,
|
219
|
+
:authorization => response[:TransactionNo],
|
220
|
+
:fraud_review => fraud_review?(response),
|
221
|
+
:avs_result => { :code => response[:AVSResultCode] },
|
222
|
+
:cvv_result => response[:CSCResultCode]
|
223
|
+
)
|
224
|
+
end
|
225
|
+
|
226
|
+
def success?(response)
|
227
|
+
response[:TxnResponseCode] == '0'
|
228
|
+
end
|
229
|
+
|
230
|
+
def fraud_review?(response)
|
231
|
+
ISSUER_RESPONSE_CODES[response[:AcqResponseCode]] == 'Suspected Fraud'
|
232
|
+
end
|
233
|
+
|
234
|
+
def add_standard_parameters(action, post, unique_id = nil)
|
235
|
+
post.merge!(
|
236
|
+
:Version => API_VERSION,
|
237
|
+
:Merchant => @options[:login],
|
238
|
+
:AccessCode => @options[:password],
|
239
|
+
:Command => action,
|
240
|
+
:MerchTxnRef => unique_id || generate_unique_id.slice(0, 40)
|
241
|
+
)
|
242
|
+
end
|
243
|
+
|
244
|
+
def post_data(post)
|
245
|
+
post.collect { |key, value| "vpc_#{key}=#{CGI.escape(value.to_s)}" }.join("&")
|
246
|
+
end
|
247
|
+
|
248
|
+
def add_secure_hash(post)
|
249
|
+
post[:SecureHash] = calculate_secure_hash(post, @options[:secure_hash])
|
250
|
+
end
|
251
|
+
|
252
|
+
def calculate_secure_hash(post, secure_hash)
|
253
|
+
sorted_values = post.sort_by(&:to_s).map(&:last)
|
254
|
+
input = secure_hash + sorted_values.join
|
255
|
+
Digest::MD5.hexdigest(input).upcase
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|