activemerchant 1.42.2 → 1.42.3

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.
Files changed (59) hide show
  1. checksums.yaml +8 -8
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/CHANGELOG +32 -0
  5. data/CONTRIBUTORS +12 -0
  6. data/README.md +3 -0
  7. data/lib/active_merchant/billing/base.rb +9 -2
  8. data/lib/active_merchant/billing/credit_card_methods.rb +1 -1
  9. data/lib/active_merchant/billing/gateway.rb +1 -1
  10. data/lib/active_merchant/billing/gateways/authorize_net.rb +3 -2
  11. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +8 -8
  12. data/lib/active_merchant/billing/gateways/balanced.rb +7 -2
  13. data/lib/active_merchant/billing/gateways/beanstream.rb +1 -1
  14. data/lib/active_merchant/billing/gateways/bogus.rb +32 -22
  15. data/lib/active_merchant/billing/gateways/braintree_blue.rb +124 -39
  16. data/lib/active_merchant/billing/gateways/cyber_source.rb +2 -2
  17. data/lib/active_merchant/billing/gateways/litle.rb +1 -1
  18. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +2 -2
  19. data/lib/active_merchant/billing/gateways/moneris.rb +1 -1
  20. data/lib/active_merchant/billing/gateways/moneris_us.rb +1 -1
  21. data/lib/active_merchant/billing/gateways/nab_transact.rb +3 -1
  22. data/lib/active_merchant/billing/gateways/netpay.rb +1 -1
  23. data/lib/active_merchant/billing/gateways/pay_junction.rb +7 -7
  24. data/lib/active_merchant/billing/gateways/payex.rb +402 -0
  25. data/lib/active_merchant/billing/gateways/payflow.rb +41 -11
  26. data/lib/active_merchant/billing/gateways/payment_express.rb +1 -1
  27. data/lib/active_merchant/billing/gateways/paymill.rb +55 -3
  28. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +1 -1
  29. data/lib/active_merchant/billing/gateways/payscout.rb +171 -0
  30. data/lib/active_merchant/billing/gateways/pin.rb +1 -1
  31. data/lib/active_merchant/billing/gateways/realex.rb +1 -1
  32. data/lib/active_merchant/billing/gateways/redsys.rb +1 -1
  33. data/lib/active_merchant/billing/gateways/so_easy_pay.rb +194 -0
  34. data/lib/active_merchant/billing/gateways/stripe.rb +23 -25
  35. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +26 -15
  36. data/lib/active_merchant/billing/gateways/webpay.rb +27 -11
  37. data/lib/active_merchant/billing/gateways/wirecard.rb +1 -1
  38. data/lib/active_merchant/billing/integrations/bit_pay/helper.rb +1 -1
  39. data/lib/active_merchant/billing/integrations/ipay88.rb +4 -0
  40. data/lib/active_merchant/billing/integrations/ipay88/helper.rb +1 -1
  41. data/lib/active_merchant/billing/integrations/ipay88/notification.rb +103 -0
  42. data/lib/active_merchant/billing/integrations/ipay88/return.rb +8 -74
  43. data/lib/active_merchant/billing/integrations/pay_fast/notification.rb +1 -1
  44. data/lib/active_merchant/billing/integrations/paypal/helper.rb +1 -1
  45. data/lib/active_merchant/billing/integrations/payu_in.rb +2 -9
  46. data/lib/active_merchant/billing/integrations/payu_in/helper.rb +15 -13
  47. data/lib/active_merchant/billing/integrations/payu_in/notification.rb +9 -20
  48. data/lib/active_merchant/billing/integrations/payu_in_paisa/helper.rb +1 -1
  49. data/lib/active_merchant/billing/integrations/payu_in_paisa/notification.rb +0 -10
  50. data/lib/active_merchant/billing/integrations/payu_in_paisa/return.rb +1 -1
  51. data/lib/active_merchant/billing/integrations/two_checkout/helper.rb +1 -1
  52. data/lib/active_merchant/billing/integrations/valitor/helper.rb +3 -3
  53. data/lib/active_merchant/billing/integrations/valitor/response_fields.rb +2 -2
  54. data/lib/active_merchant/billing/integrations/verkkomaksut/notification.rb +1 -1
  55. data/lib/active_merchant/billing/integrations/wirecard_checkout_page.rb +1 -1
  56. data/lib/active_merchant/billing/integrations/world_pay/helper.rb +2 -2
  57. data/lib/active_merchant/version.rb +1 -1
  58. metadata +7 -3
  59. metadata.gz.sig +0 -0
@@ -19,20 +19,23 @@ module ActiveMerchant #:nodoc:
19
19
  commit(request, options)
20
20
  end
21
21
 
22
- def purchase(money, credit_card_or_reference, options = {})
23
- request = build_sale_or_authorization_request(:purchase, money, credit_card_or_reference, options)
22
+ def purchase(money, funding_source, options = {})
23
+ request = build_sale_or_authorization_request(:purchase, money, funding_source, options)
24
24
 
25
25
  commit(request, options)
26
26
  end
27
27
 
28
- def credit(money, identification_or_credit_card, options = {})
29
- if identification_or_credit_card.is_a?(String)
28
+ def credit(money, funding_source, options = {})
29
+ if funding_source.is_a?(String)
30
30
  deprecated CREDIT_DEPRECATION_MESSAGE
31
31
  # Perform referenced credit
32
- refund(money, identification_or_credit_card, options)
33
- else
32
+ refund(money, funding_source, options)
33
+ elsif card_brand(funding_source) == 'check'
34
34
  # Perform non-referenced credit
35
- request = build_credit_card_request(:credit, money, identification_or_credit_card, options)
35
+ request = build_check_request(:credit, money, funding_source, options)
36
+ commit(request, options)
37
+ else
38
+ request = build_credit_card_request(:credit, money, funding_source, options)
36
39
  commit(request, options)
37
40
  end
38
41
  end
@@ -76,11 +79,13 @@ module ActiveMerchant #:nodoc:
76
79
  end
77
80
 
78
81
  private
79
- def build_sale_or_authorization_request(action, money, credit_card_or_reference, options)
80
- if credit_card_or_reference.is_a?(String)
81
- build_reference_sale_or_authorization_request(action, money, credit_card_or_reference, options)
82
+ def build_sale_or_authorization_request(action, money, funding_source, options)
83
+ if funding_source.is_a?(String)
84
+ build_reference_sale_or_authorization_request(action, money, funding_source, options)
85
+ elsif card_brand(funding_source) == 'check'
86
+ build_check_request(action, money, funding_source, options)
82
87
  else
83
- build_credit_card_request(action, money, credit_card_or_reference, options)
88
+ build_credit_card_request(action, money, funding_source, options)
84
89
  end
85
90
  end
86
91
 
@@ -147,6 +152,31 @@ module ActiveMerchant #:nodoc:
147
152
  xml.target!
148
153
  end
149
154
 
155
+ def build_check_request(action, money, check, options)
156
+ xml = Builder::XmlMarkup.new
157
+ xml.tag! TRANSACTIONS[action] do
158
+ xml.tag! 'PayData' do
159
+ xml.tag! 'Invoice' do
160
+ xml.tag! 'CustIP', options[:ip] unless options[:ip].blank?
161
+ xml.tag! 'InvNum', options[:order_id].to_s.gsub(/[^\w.]/, '') unless options[:order_id].blank?
162
+ xml.tag! 'Description', options[:description] unless options[:description].blank?
163
+ xml.tag! 'BillTo' do
164
+ xml.tag! 'Name', check.name
165
+ end
166
+ xml.tag! 'TotalAmt', amount(money), 'Currency' => options[:currency] || currency(money)
167
+ end
168
+ xml.tag! 'Tender' do
169
+ xml.tag! 'ACH' do
170
+ xml.tag! 'AcctType', check.account_type == 'checking' ? 'C' : 'S'
171
+ xml.tag! 'AcctNum', check.account_number
172
+ xml.tag! 'ABA', check.routing_number
173
+ end
174
+ end
175
+ end
176
+ end
177
+ xml.target!
178
+ end
179
+
150
180
  def add_credit_card(xml, credit_card)
151
181
  xml.tag! 'Card' do
152
182
  xml.tag! 'CardType', credit_card_type(credit_card)
@@ -227,7 +227,7 @@ module ActiveMerchant #:nodoc:
227
227
  end
228
228
 
229
229
  # The options hash may contain optional data which will be passed
230
- # through the the specialized optional fields at PaymentExpress
230
+ # through the specialized optional fields at PaymentExpress
231
231
  # as follows:
232
232
  #
233
233
  # {
@@ -67,7 +67,7 @@ module ActiveMerchant #:nodoc:
67
67
  raw_response = ssl_request(method, "https://api.paymill.com/v2/#{url}", post_data(parameters), headers)
68
68
  rescue ResponseError => e
69
69
  parsed = JSON.parse(e.response.body)
70
- return Response.new(false, parsed['error'], parsed, {})
70
+ return Response.new(false, response_message(parsed), parsed, {})
71
71
  end
72
72
 
73
73
  response_from(raw_response)
@@ -75,13 +75,13 @@ module ActiveMerchant #:nodoc:
75
75
 
76
76
  def response_from(raw_response)
77
77
  parsed = JSON.parse(raw_response)
78
-
79
78
  options = {
80
79
  :authorization => authorization_from(parsed),
81
80
  :test => (parsed['mode'] == 'test'),
82
81
  }
83
82
 
84
- Response.new(true, 'Transaction approved', parsed, options)
83
+ succeeded = (parsed['data'] == []) || (parsed['data']['response_code'] == 20000)
84
+ Response.new(succeeded, response_message(parsed), parsed, options)
85
85
  end
86
86
 
87
87
  def authorization_from(parsed_response)
@@ -175,6 +175,58 @@ module ActiveMerchant #:nodoc:
175
175
  authorization.split(';').first
176
176
  end
177
177
 
178
+ RESPONSE_CODES = {
179
+ 10001 => "General undefined response.",
180
+ 10002 => "Still waiting on something.",
181
+
182
+ 20000 => "General success response.",
183
+
184
+ 40000 => "General problem with data.",
185
+ 40001 => "General problem with payment data.",
186
+ 40100 => "Problem with credit card data.",
187
+ 40101 => "Problem with cvv.",
188
+ 40102 => "Card expired or not yet valid.",
189
+ 40103 => "Limit exceeded.",
190
+ 40104 => "Card invalid.",
191
+ 40105 => "Expiry date not valid.",
192
+ 40106 => "Credit card brand required.",
193
+ 40200 => "Problem with bank account data.",
194
+ 40201 => "Bank account data combination mismatch.",
195
+ 40202 => "User authentication failed.",
196
+ 40300 => "Problem with 3d secure data.",
197
+ 40301 => "Currency / amount mismatch",
198
+ 40400 => "Problem with input data.",
199
+ 40401 => "Amount too low or zero.",
200
+ 40402 => "Usage field too long.",
201
+ 40403 => "Currency not allowed.",
202
+
203
+ 50000 => "General problem with backend.",
204
+ 50001 => "Country blacklisted.",
205
+ 50100 => "Technical error with credit card.",
206
+ 50101 => "Error limit exceeded.",
207
+ 50102 => "Card declined by authorization system.",
208
+ 50103 => "Manipulation or stolen card.",
209
+ 50104 => "Card restricted.",
210
+ 50105 => "Invalid card configuration data.",
211
+ 50200 => "Technical error with bank account.",
212
+ 50201 => "Card blacklisted.",
213
+ 50300 => "Technical error with 3D secure.",
214
+ 50400 => "Decline because of risk issues.",
215
+ 50500 => "General timeout.",
216
+ 50501 => "Timeout on side of the acquirer.",
217
+ 50502 => "Risk management transaction timeout.",
218
+ 50600 => "Duplicate transaction."
219
+ }
220
+
221
+ def response_message(parsed_response)
222
+ return parsed_response["error"] if parsed_response["error"]
223
+ return "Transaction approved." if (parsed_response['data'] == [])
224
+
225
+ code = parsed_response["data"]["response_code"]
226
+ RESPONSE_CODES[code] || code.to_s
227
+ end
228
+
229
+
178
230
  class ResponseParser
179
231
  def initialize(raw_response="", options={})
180
232
  @raw_response = raw_response
@@ -242,7 +242,7 @@ module ActiveMerchant #:nodoc:
242
242
  commit 'DoAuthorization', build_do_authorize(transaction_id, money, options)
243
243
  end
244
244
 
245
- # The ManagePendingTransactionStatus API operation accepts or denys a
245
+ # The ManagePendingTransactionStatus API operation accepts or denies a
246
246
  # pending transaction held by Fraud Management Filters.
247
247
  #
248
248
  # ==== Parameters:
@@ -0,0 +1,171 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class PayscoutGateway < Gateway
4
+ self.live_url = self.test_url = 'https://secure.payscout.com/api/transact.php'
5
+
6
+ self.supported_countries = ['US']
7
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover]
8
+ self.default_currency = 'USD'
9
+ self.homepage_url = 'http://www.payscout.com/'
10
+ self.display_name = 'Payscout'
11
+
12
+ self.ssl_version = 'SSLv3'
13
+
14
+ def initialize(options = {})
15
+ requires!(options, :username, :password)
16
+ super
17
+ end
18
+
19
+ def authorize(money, creditcard, options = {})
20
+ post = {}
21
+ add_invoice(post, options)
22
+ add_creditcard(post, creditcard)
23
+ add_currency(post, money, options)
24
+ add_address(post, options)
25
+
26
+ commit('auth', money, post)
27
+ end
28
+
29
+ def purchase(money, creditcard, options = {})
30
+ post = {}
31
+ add_invoice(post, options)
32
+ add_creditcard(post, creditcard)
33
+ add_currency(post, money, options)
34
+ add_address(post, options)
35
+
36
+ commit('sale', money, post)
37
+ end
38
+
39
+ def capture(money, authorization, options = {})
40
+ post = {}
41
+ post[:transactionid] = authorization
42
+
43
+ commit('capture', money, post)
44
+ end
45
+
46
+
47
+ def refund(money, authorization, options = {})
48
+ post = {}
49
+ post[:transactionid] = authorization
50
+
51
+ commit('refund', money, post)
52
+ end
53
+
54
+ def void(authorization, options = {})
55
+ post = {}
56
+ post[:transactionid] = authorization
57
+
58
+ commit('void', nil, post)
59
+ end
60
+
61
+ private
62
+
63
+ def add_address(post, options)
64
+ if address = options[:billing_address] || options[:address]
65
+ post[:address1] = address[:address1].to_s
66
+ post[:address2] = address[:address2].to_s
67
+ post[:city] = address[:city].to_s
68
+ post[:state] = (address[:state].blank? ? 'n/a' : address[:state])
69
+ post[:zip] = address[:zip].to_s
70
+ post[:country] = address[:country].to_s
71
+ post[:phone] = address[:phone].to_s
72
+ post[:fax] = address[:fax].to_s
73
+ post[:email] = address[:email].to_s
74
+ end
75
+
76
+ if address = options[:shipping_address]
77
+ post[:shipping_firstname] = address[:first_name].to_s
78
+ post[:shipping_lastname] = address[:last_name].to_s
79
+ post[:shipping_company] = address[:company].to_s
80
+ post[:shipping_address1] = address[:address1].to_s
81
+ post[:shipping_address2] = address[:address2].to_s
82
+ post[:shipping_city] = address[:city].to_s
83
+ post[:shipping_country] = address[:country].to_s
84
+ post[:shipping_state] = (address[:state].blank? ? 'n/a' : address[:state])
85
+ post[:shipping_zip] = address[:zip].to_s
86
+ post[:shipping_email] = address[:email].to_s
87
+ end
88
+ end
89
+
90
+ def add_currency(post, money, options)
91
+ post[:currency] = options[:currency] || currency(money)
92
+ end
93
+
94
+ def add_invoice(post, options)
95
+ post[:orderdescription] = options[:description]
96
+ post[:orderid] = options[:order_id]
97
+ end
98
+
99
+ def add_creditcard(post, creditcard)
100
+ post[:ccnumber] = creditcard.number
101
+ post[:cvv] = creditcard.verification_value if creditcard.verification_value?
102
+ post[:ccexp] = expdate(creditcard)
103
+ post[:firstname] = creditcard.first_name
104
+ post[:lastname] = creditcard.last_name
105
+ end
106
+
107
+ def parse(body)
108
+ Hash[body.split('&').map{|x|x.split('=')}]
109
+ end
110
+
111
+ def commit(action, money, parameters)
112
+ parameters[:amount] = amount(money) unless action == 'void'
113
+ url = (test? ? self.test_url : self.live_url)
114
+ data = ssl_post(url, post_data(action, parameters))
115
+
116
+ response = parse(data)
117
+ response[:action] = action
118
+
119
+ message = message_from(response)
120
+ test_mode = (test? || message =~ /TESTMODE/)
121
+ Response.new(success?(response), message, response,
122
+ :test => test_mode,
123
+ :authorization => response['transactionid'],
124
+ :fraud_review => fraud_review?(response),
125
+ :avs_result => { :code => response['avsresponse'] },
126
+ :cvv_result => response['cvvresponse']
127
+ )
128
+ end
129
+
130
+ def message_from(response)
131
+ case response['response']
132
+ when '1'
133
+ 'The transaction has been approved'
134
+ when '2'
135
+ 'The transaction has been declined'
136
+ when '3'
137
+ response['responsetext']
138
+ else
139
+ 'There was an error processing the transaction'
140
+ end
141
+ end
142
+
143
+ def fraud_review?(response)
144
+ false
145
+ end
146
+
147
+ def success?(response)
148
+ (response['response'] == '1')
149
+ end
150
+
151
+ def post_data(action, parameters = {})
152
+ post = {}
153
+
154
+ post[:username] = @options[:username]
155
+ post[:password] = @options[:password]
156
+ post[:type] = action
157
+
158
+ request = post.merge(parameters).collect { |key, value| "#{key}=#{URI.escape(value.to_s)}" }.join("&")
159
+ request
160
+ end
161
+
162
+ def expdate(creditcard)
163
+ year = sprintf("%.4i", creditcard.year)
164
+ month = sprintf("%.2i", creditcard.month)
165
+
166
+ "#{month}#{year[-2..-1]}"
167
+ end
168
+ end
169
+ end
170
+ end
171
+
@@ -90,7 +90,7 @@ module ActiveMerchant #:nodoc:
90
90
  :expiry_month => creditcard.month,
91
91
  :expiry_year => creditcard.year,
92
92
  :cvc => creditcard.verification_value,
93
- :name => "#{creditcard.first_name} #{creditcard.last_name}"
93
+ :name => creditcard.name
94
94
  )
95
95
  elsif creditcard.kind_of?(String)
96
96
  if creditcard =~ /^card_/
@@ -12,7 +12,7 @@ module ActiveMerchant
12
12
  # login - The unique id of the merchant
13
13
  # password - The secret is used to digitally sign the request
14
14
  # account - This is an optional third part of the authentication process
15
- # and is used if the merchant wishes do distuinguish cc traffic from the different sources
15
+ # and is used if the merchant wishes do distinguish cc traffic from the different sources
16
16
  # by using a different account. This must be created in advance
17
17
  #
18
18
  # the Realex team decided to make the orderid unique per request,
@@ -49,7 +49,7 @@ module ActiveMerchant #:nodoc:
49
49
  self.default_currency = 'EUR'
50
50
  self.money_format = :cents
51
51
 
52
- # Not all card types may be actived by the bank!
52
+ # Not all card types may be activated by the bank!
53
53
  self.supported_cardtypes = [:visa, :master, :american_express, :jcb, :diners_club]
54
54
 
55
55
  # Homepage URL of the gateway for reference
@@ -0,0 +1,194 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class SoEasyPayGateway < Gateway
4
+ self.live_url = self.test_url = 'https://secure.soeasypay.com/gateway.asmx'
5
+ self.money_format = :cents
6
+
7
+ self.supported_countries = [
8
+ 'US', 'CA', 'AT', 'BE', 'BG', 'HR', 'CY', 'CZ', 'DK', 'EE',
9
+ 'FI', 'FR', 'DE', 'GR', 'HU', 'IE', 'IT', 'LV', 'LT', 'LU',
10
+ 'MT', 'NL', 'PL', 'PT', 'RO', 'SK', 'SI', 'ES', 'SE', 'GB',
11
+ 'IS', 'NO', 'CH'
12
+ ]
13
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover, :maestro, :jcb, :solo, :diners_club]
14
+ self.homepage_url = 'http://www.soeasypay.com/'
15
+ self.display_name = 'SoEasyPay'
16
+
17
+ def initialize(options = {})
18
+ requires!(options, :login, :password)
19
+ super
20
+ end
21
+
22
+ def authorize(money, payment_source, options = {})
23
+ if payment_source.respond_to?(:number)
24
+ commit('AuthorizeTransaction', do_authorization(money, payment_source, options), options)
25
+ else
26
+ commit('ReauthorizeTransaction', do_reauthorization(money, payment_source, options), options)
27
+ end
28
+ end
29
+
30
+ def purchase(money, payment_source, options = {})
31
+ if payment_source.respond_to?(:number)
32
+ commit('SaleTransaction', do_sale(money, payment_source, options), options)
33
+ else
34
+ commit('RebillTransaction', do_rebill(money, payment_source, options), options)
35
+ end
36
+ end
37
+
38
+ def capture(money, authorization, options = {})
39
+ commit('CaptureTransaction', do_capture(money, authorization, options), options)
40
+ end
41
+
42
+ def refund(money, authorization, options={})
43
+ commit('RefundTransaction', do_refund(money, authorization, options), options)
44
+ end
45
+
46
+ def void(authorization, options={})
47
+ commit('CancelTransaction', do_void(authorization, options), options)
48
+ end
49
+
50
+ private
51
+
52
+ def do_authorization(money, card, options)
53
+ build_soap('AuthorizeTransaction') do |soap|
54
+ fill_credentials(soap, options)
55
+ fill_order_info(soap, money, options)
56
+ fill_cardholder(soap, card, options)
57
+ fill_card(soap, card)
58
+ end
59
+ end
60
+
61
+ def do_sale(money, card, options)
62
+ build_soap('SaleTransaction') do |soap|
63
+ fill_credentials(soap, options)
64
+ fill_order_info(soap, money, options)
65
+ fill_cardholder(soap, card, options)
66
+ fill_card(soap, card)
67
+ end
68
+ end
69
+
70
+ def do_reauthorization(money, authorization, options)
71
+ build_soap('ReauthorizeTransaction') do |soap|
72
+ fill_credentials(soap, options)
73
+ fill_order_info(soap, money, options)
74
+ fill_transaction_id(soap, authorization)
75
+ end
76
+ end
77
+
78
+ def do_rebill(money, authorization, options)
79
+ build_soap('RebillTransaction') do |soap|
80
+ fill_credentials(soap, options)
81
+ fill_order_info(soap, money, options)
82
+ fill_transaction_id(soap, authorization)
83
+ end
84
+ end
85
+
86
+ def do_capture(money, authorization, options)
87
+ build_soap('CaptureTransaction') do |soap|
88
+ fill_credentials(soap, options)
89
+ fill_order_info(soap, money, options, :no_currency)
90
+ fill_transaction_id(soap, authorization)
91
+ end
92
+ end
93
+
94
+ def do_refund(money, authorization, options)
95
+ build_soap('RefundTransaction') do |soap|
96
+ fill_credentials(soap, options)
97
+ fill_order_info(soap, money, options, :no_currency)
98
+ fill_transaction_id(soap, authorization)
99
+ end
100
+ end
101
+
102
+ def do_void(authorization, options)
103
+ build_soap('CancelTransaction') do |soap|
104
+ fill_credentials(soap, options)
105
+ fill_transaction_id(soap, authorization)
106
+ end
107
+ end
108
+
109
+ def fill_credentials(soap, options)
110
+ soap.tag!('websiteID', @options[:login].to_s)
111
+ soap.tag!('password', @options[:password].to_s)
112
+ end
113
+
114
+ def fill_cardholder(soap, card, options)
115
+ ch_info = options[:billing_address] || options[:address]
116
+
117
+ soap.tag!('customerIP',options[:ip].to_s)
118
+ name = card.name || ch_info[:name]
119
+ soap.tag!('cardHolderName', name.to_s)
120
+ address = ch_info[:address1] || ''
121
+ address << ch_info[:address2] if ch_info[:address2]
122
+ soap.tag!('cardHolderAddress', address.to_s)
123
+ soap.tag!('cardHolderZipcode', ch_info[:zip].to_s)
124
+ soap.tag!('cardHolderCity', ch_info[:city].to_s)
125
+ soap.tag!('cardHolderState', ch_info[:state].to_s)
126
+ soap.tag!('cardHolderCountryCode', ch_info[:country].to_s)
127
+ soap.tag!('cardHolderPhone', ch_info[:phone].to_s)
128
+ soap.tag!('cardHolderEmail', options[:email].to_s)
129
+ end
130
+
131
+ def fill_transaction_id(soap, transaction_id)
132
+ soap.tag!('transactionID', transaction_id.to_s)
133
+ end
134
+
135
+ def fill_card(soap, card)
136
+ soap.tag!('cardNumber', card.number.to_s)
137
+ soap.tag!('cardSecurityCode', card.verification_value.to_s)
138
+ soap.tag!('cardExpireMonth', card.month.to_s.rjust(2, "0"))
139
+ soap.tag!('cardExpireYear', card.year.to_s)
140
+ end
141
+
142
+ def fill_order_info(soap, money, options, skip_currency=false)
143
+ soap.tag!('orderID', options[:order_id].to_s)
144
+ soap.tag!('orderDescription', "Order #{options[:order_id]}")
145
+ soap.tag!('amount', amount(money).to_s)
146
+ soap.tag!('currency', (options[:currency] || currency(money)).to_s) unless skip_currency
147
+ end
148
+
149
+ def parse(response, action)
150
+ result = {}
151
+ document = REXML::Document.new(response)
152
+ response_element = document.root.get_elements("//[@xsi:type='tns:#{action}Response']").first
153
+ response_element.elements.each do |element|
154
+ result[element.name.underscore] = element.text
155
+ end
156
+ result
157
+ end
158
+
159
+ def commit(soap_action, soap, options)
160
+ headers = {"SOAPAction" => "\"urn:Interface##{soap_action}\"",
161
+ "Content-Type" => "text/xml; charset=utf-8"}
162
+ response_string = ssl_post(test? ? self.test_url : self.live_url, soap, headers)
163
+ response = parse(response_string, soap_action)
164
+ return Response.new(response['errorcode'] == '000',
165
+ response['errormessage'],
166
+ response,
167
+ :test => test?,
168
+ :authorization => response['transaction_id'])
169
+ end
170
+
171
+ def build_soap(request)
172
+ retval = Builder::XmlMarkup.new(:indent => 2)
173
+ retval.instruct!(:xml, :version => '1.0', :encoding => 'utf-8')
174
+ retval.tag!('soap:Envelope', {
175
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
176
+ 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',
177
+ 'xmlns:soapenc' => 'http://schemas.xmlsoap.org/soap/encoding/',
178
+ 'xmlns:tns' => 'urn:Interface',
179
+ 'xmlns:types' => 'urn:Interface/encodedTypes',
180
+ 'xmlns:soap' => 'http://schemas.xmlsoap.org/soap/envelope/'}) do
181
+ retval.tag!('soap:Body', {'soap:encodingStyle'=>'http://schemas.xmlsoap.org/soap/encoding/'}) do
182
+ retval.tag!("tns:#{request}") do
183
+ retval.tag!("#{request}Request", {'xsi:type'=>"tns:#{request}Request"}) do
184
+ yield retval
185
+ end
186
+ end
187
+ end
188
+ end
189
+ retval.target!
190
+ end
191
+
192
+ end
193
+ end
194
+ end