tlconnor-activemerchant 1.20.4 → 1.23.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/CHANGELOG +86 -6
  2. data/CONTRIBUTORS +33 -0
  3. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +2 -0
  4. data/lib/active_merchant/billing/gateways/barclays_epdq.rb +4 -4
  5. data/lib/active_merchant/billing/gateways/blue_pay.rb +492 -11
  6. data/lib/active_merchant/billing/gateways/braintree_blue.rb +46 -19
  7. data/lib/active_merchant/billing/gateways/certo_direct.rb +1 -1
  8. data/lib/active_merchant/billing/gateways/elavon.rb +2 -0
  9. data/lib/active_merchant/billing/gateways/epay.rb +3 -1
  10. data/lib/active_merchant/billing/gateways/itransact.rb +450 -0
  11. data/lib/active_merchant/billing/gateways/litle.rb +275 -0
  12. data/lib/active_merchant/billing/gateways/migs.rb +259 -0
  13. data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +100 -0
  14. data/lib/active_merchant/billing/gateways/moneris.rb +4 -30
  15. data/lib/active_merchant/billing/gateways/moneris_us.rb +211 -0
  16. data/lib/active_merchant/billing/gateways/nab_transact.rb +1 -1
  17. data/lib/active_merchant/billing/gateways/ogone.rb +104 -12
  18. data/lib/active_merchant/billing/gateways/orbital.rb +15 -6
  19. data/lib/active_merchant/billing/gateways/paybox_direct.rb +1 -4
  20. data/lib/active_merchant/billing/gateways/payflow.rb +8 -3
  21. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +4 -1
  22. data/lib/active_merchant/billing/gateways/payflow_express.rb +4 -2
  23. data/lib/active_merchant/billing/gateways/payment_express.rb +60 -13
  24. data/lib/active_merchant/billing/gateways/paypal.rb +3 -18
  25. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +333 -3
  26. data/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb +245 -0
  27. data/lib/active_merchant/billing/gateways/paypal_digital_goods.rb +43 -0
  28. data/lib/active_merchant/billing/gateways/paypal_express.rb +14 -65
  29. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +8 -3
  30. data/lib/active_merchant/billing/gateways/realex.rb +5 -7
  31. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +3 -2
  32. data/lib/active_merchant/billing/gateways/stripe.rb +1 -9
  33. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +2 -2
  34. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +1 -5
  35. data/lib/active_merchant/billing/gateways/viaklix.rb +7 -2
  36. data/lib/active_merchant/billing/gateways/vindicia.rb +359 -0
  37. data/lib/active_merchant/billing/integrations/dotpay.rb +22 -0
  38. data/lib/active_merchant/billing/integrations/dotpay/helper.rb +77 -0
  39. data/lib/active_merchant/billing/integrations/dotpay/notification.rb +86 -0
  40. data/lib/active_merchant/billing/integrations/dotpay/return.rb +11 -0
  41. data/lib/active_merchant/billing/integrations/epay.rb +21 -0
  42. data/lib/active_merchant/billing/integrations/epay/helper.rb +55 -0
  43. data/lib/active_merchant/billing/integrations/epay/notification.rb +110 -0
  44. data/lib/active_merchant/billing/integrations/paypal/notification.rb +2 -1
  45. data/lib/active_merchant/billing/integrations/quickpay/helper.rb +2 -3
  46. data/lib/active_merchant/billing/integrations/robokassa.rb +49 -0
  47. data/lib/active_merchant/billing/integrations/robokassa/common.rb +19 -0
  48. data/lib/active_merchant/billing/integrations/robokassa/helper.rb +50 -0
  49. data/lib/active_merchant/billing/integrations/robokassa/notification.rb +55 -0
  50. data/lib/active_merchant/billing/integrations/robokassa/return.rb +17 -0
  51. data/lib/active_merchant/billing/integrations/two_checkout.rb +25 -3
  52. data/lib/active_merchant/billing/integrations/two_checkout/helper.rb +58 -26
  53. data/lib/active_merchant/billing/integrations/two_checkout/notification.rb +71 -46
  54. data/lib/active_merchant/billing/integrations/verkkomaksut.rb +20 -0
  55. data/lib/active_merchant/billing/integrations/verkkomaksut/helper.rb +87 -0
  56. data/lib/active_merchant/billing/integrations/verkkomaksut/notification.rb +59 -0
  57. data/lib/active_merchant/version.rb +1 -1
  58. 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