activemerchant 1.29.1 → 1.30.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.
Files changed (50) hide show
  1. data/CHANGELOG +48 -0
  2. data/CONTRIBUTORS +19 -0
  3. data/README.md +43 -41
  4. data/lib/active_merchant/billing/check.rb +15 -11
  5. data/lib/active_merchant/billing/credit_card.rb +5 -1
  6. data/lib/active_merchant/billing/credit_card_formatting.rb +8 -8
  7. data/lib/active_merchant/billing/gateway.rb +1 -1
  8. data/lib/active_merchant/billing/gateways/authorize_net.rb +9 -1
  9. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +15 -4
  10. data/lib/active_merchant/billing/gateways/balanced.rb +9 -3
  11. data/lib/active_merchant/billing/gateways/banwire.rb +15 -1
  12. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +6 -2
  13. data/lib/active_merchant/billing/gateways/beanstream.rb +26 -24
  14. data/lib/active_merchant/billing/gateways/braintree_blue.rb +5 -2
  15. data/lib/active_merchant/billing/gateways/cyber_source.rb +55 -22
  16. data/lib/active_merchant/billing/gateways/eway.rb +114 -171
  17. data/lib/active_merchant/billing/gateways/eway_managed.rb +52 -22
  18. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +222 -0
  19. data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +13 -2
  20. data/lib/active_merchant/billing/gateways/litle.rb +50 -19
  21. data/lib/active_merchant/billing/gateways/merchant_ware.rb +44 -9
  22. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +190 -0
  23. data/lib/active_merchant/billing/gateways/moneris.rb +3 -5
  24. data/lib/active_merchant/billing/gateways/moneris_us.rb +1 -1
  25. data/lib/active_merchant/billing/gateways/nab_transact.rb +20 -3
  26. data/lib/active_merchant/billing/gateways/netbilling.rb +1 -0
  27. data/lib/active_merchant/billing/gateways/netpay.rb +223 -0
  28. data/lib/active_merchant/billing/gateways/optimal_payment.rb +18 -3
  29. data/lib/active_merchant/billing/gateways/orbital.rb +9 -5
  30. data/lib/active_merchant/billing/gateways/payment_express.rb +62 -1
  31. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +1 -1
  32. data/lib/active_merchant/billing/gateways/paypal_express.rb +2 -0
  33. data/lib/active_merchant/billing/gateways/pin.rb +157 -0
  34. data/lib/active_merchant/billing/gateways/qbms.rb +3 -2
  35. data/lib/active_merchant/billing/gateways/quickpay.rb +66 -28
  36. data/lib/active_merchant/billing/gateways/sage_pay.rb +6 -0
  37. data/lib/active_merchant/billing/gateways/smart_ps.rb +1 -1
  38. data/lib/active_merchant/billing/gateways/spreedly_core.rb +235 -0
  39. data/lib/active_merchant/billing/gateways/stripe.rb +1 -0
  40. data/lib/active_merchant/billing/gateways/wirecard.rb +15 -9
  41. data/lib/active_merchant/billing/gateways/worldpay.rb +15 -4
  42. data/lib/active_merchant/billing/integrations/payflow_link/helper.rb +4 -1
  43. data/lib/active_merchant/billing/integrations/paypal/notification.rb +39 -31
  44. data/lib/active_merchant/billing/integrations/quickpay/helper.rb +13 -10
  45. data/lib/active_merchant/billing/integrations/quickpay/notification.rb +14 -14
  46. data/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb +2 -2
  47. data/lib/active_merchant/version.rb +1 -1
  48. data.tar.gz.sig +0 -0
  49. metadata +109 -49
  50. metadata.gz.sig +0 -0
@@ -44,22 +44,40 @@ module ActiveMerchant #:nodoc:
44
44
  fraud_http_accept_encoding fraud_http_accept_charset
45
45
  fraud_http_referer fraud_http_user_agent apikey),
46
46
 
47
- :capture => %w(protocol msgtype merchant amount transaction
48
- fraud_remote_addr fraud_http_accept
49
- fraud_http_accept_language fraud_http_accept_encoding
50
- fraud_http_accept_charset fraud_http_referer
51
- fraud_http_user_agent apikey),
47
+ :capture => %w(protocol msgtype merchant amount transaction apikey),
52
48
 
53
- :cancel => %w(protocol msgtype merchant transaction fraud_remote_addr
54
- fraud_http_accept fraud_http_accept_language
49
+ :cancel => %w(protocol msgtype merchant transaction apikey),
50
+
51
+ :refund => %w(protocol msgtype merchant amount transaction apikey),
52
+
53
+ :subscribe => %w(protocol msgtype merchant ordernumber cardnumber
54
+ expirationdate cvd cardtypelock description testmode
55
+ fraud_remote_addr fraud_http_accept fraud_http_accept_language
55
56
  fraud_http_accept_encoding fraud_http_accept_charset
56
57
  fraud_http_referer fraud_http_user_agent apikey),
57
58
 
58
- :refund => %w(protocol msgtype merchant amount transaction
59
- fraud_remote_addr fraud_http_accept fraud_http_accept_language
59
+ :recurring => %w(protocol msgtype merchant ordernumber amount currency
60
+ autocapture transaction apikey),
61
+
62
+ :status => %w(protocol msgtype merchant transaction apikey),
63
+
64
+ :chstatus => %w(protocol msgtype merchant apikey)
65
+ },
66
+
67
+ 5 => {
68
+ :authorize => %w(protocol msgtype merchant ordernumber amount
69
+ currency autocapture cardnumber expirationdate cvd
70
+ cardtypelock testmode fraud_remote_addr
71
+ fraud_http_accept fraud_http_accept_language
60
72
  fraud_http_accept_encoding fraud_http_accept_charset
61
73
  fraud_http_referer fraud_http_user_agent apikey),
62
74
 
75
+ :capture => %w(protocol msgtype merchant amount transaction apikey),
76
+
77
+ :cancel => %w(protocol msgtype merchant transaction apikey),
78
+
79
+ :refund => %w(protocol msgtype merchant amount transaction apikey),
80
+
63
81
  :subscribe => %w(protocol msgtype merchant ordernumber cardnumber
64
82
  expirationdate cvd cardtypelock description testmode
65
83
  fraud_remote_addr fraud_http_accept fraud_http_accept_language
@@ -67,20 +85,40 @@ module ActiveMerchant #:nodoc:
67
85
  fraud_http_referer fraud_http_user_agent apikey),
68
86
 
69
87
  :recurring => %w(protocol msgtype merchant ordernumber amount currency
70
- autocapture transaction fraud_remote_addr fraud_http_accept
71
- fraud_http_accept_language fraud_http_accept_encoding
72
- fraud_http_accept_charset fraud_http_referer
73
- fraud_http_user_agent apikey),
88
+ autocapture transaction apikey),
89
+
90
+ :status => %w(protocol msgtype merchant transaction apikey),
74
91
 
75
- :status => %w(protocol msgtype merchant transaction fraud_remote_addr
92
+ :chstatus => %w(protocol msgtype merchant apikey)
93
+ },
94
+
95
+ 6 => {
96
+ :authorize => %w(protocol msgtype merchant ordernumber amount
97
+ currency autocapture cardnumber expirationdate cvd
98
+ cardtypelock testmode fraud_remote_addr
76
99
  fraud_http_accept fraud_http_accept_language
77
100
  fraud_http_accept_encoding fraud_http_accept_charset
78
101
  fraud_http_referer fraud_http_user_agent apikey),
79
102
 
80
- :chstatus => %w(protocol msgtype merchant fraud_remote_addr fraud_http_accept
81
- fraud_http_accept_language fraud_http_accept_encoding
82
- fraud_http_accept_charset fraud_http_referer
83
- fraud_http_user_agent apikey)
103
+ :capture => %w(protocol msgtype merchant amount transaction
104
+ apikey),
105
+
106
+ :cancel => %w(protocol msgtype merchant transaction apikey),
107
+
108
+ :refund => %w(protocol msgtype merchant amount transaction apikey),
109
+
110
+ :subscribe => %w(protocol msgtype merchant ordernumber cardnumber
111
+ expirationdate cvd cardtypelock description testmode
112
+ fraud_remote_addr fraud_http_accept fraud_http_accept_language
113
+ fraud_http_accept_encoding fraud_http_accept_charset
114
+ fraud_http_referer fraud_http_user_agent apikey),
115
+
116
+ :recurring => %w(protocol msgtype merchant ordernumber amount currency
117
+ autocapture transaction apikey),
118
+
119
+ :status => %w(protocol msgtype merchant transaction apikey),
120
+
121
+ :chstatus => %w(protocol msgtype merchant apikey)
84
122
  }
85
123
  }
86
124
 
@@ -89,7 +127,7 @@ module ActiveMerchant #:nodoc:
89
127
  # The login is the QuickpayId
90
128
  # The password is the md5checkword from the Quickpay manager
91
129
  # To use the API-key from the Quickpay manager, specify :api-key
92
- # Using the API-key, requires that you use version 4. Specify :version => 4 in options.
130
+ # Using the API-key, requires that you use version 4+. Specify :version => 4/5/6 in options.
93
131
  def initialize(options = {})
94
132
  requires!(options, :login, :password)
95
133
  @protocol = options.delete(:version) || 3 # default to protocol version 3
@@ -99,26 +137,30 @@ module ActiveMerchant #:nodoc:
99
137
  def authorize(money, credit_card_or_reference, options = {})
100
138
  post = {}
101
139
 
140
+ action = recurring_or_authorize(credit_card_or_reference)
141
+
102
142
  add_amount(post, money, options)
103
143
  add_invoice(post, options)
104
144
  add_creditcard_or_reference(post, credit_card_or_reference, options)
105
145
  add_autocapture(post, false)
106
- add_fraud_parameters(post, options)
146
+ add_fraud_parameters(post, options) if action.eql?(:authorize)
107
147
  add_testmode(post)
108
148
 
109
- commit(recurring_or_authorize(credit_card_or_reference), post)
149
+ commit(action, post)
110
150
  end
111
151
 
112
152
  def purchase(money, credit_card_or_reference, options = {})
113
153
  post = {}
114
154
 
155
+ action = recurring_or_authorize(credit_card_or_reference)
156
+
115
157
  add_amount(post, money, options)
116
158
  add_creditcard_or_reference(post, credit_card_or_reference, options)
117
159
  add_invoice(post, options)
118
- add_fraud_parameters(post, options)
160
+ add_fraud_parameters(post, options) if action.eql?(:authorize)
119
161
  add_autocapture(post, true)
120
162
 
121
- commit(recurring_or_authorize(credit_card_or_reference), post)
163
+ commit(action, post)
122
164
  end
123
165
 
124
166
  def capture(money, authorization, options = {})
@@ -126,8 +168,6 @@ module ActiveMerchant #:nodoc:
126
168
 
127
169
  add_reference(post, authorization)
128
170
  add_amount_without_currency(post, money)
129
- add_fraud_parameters(post, options)
130
-
131
171
  commit(:capture, post)
132
172
  end
133
173
 
@@ -135,7 +175,6 @@ module ActiveMerchant #:nodoc:
135
175
  post = {}
136
176
 
137
177
  add_reference(post, identification)
138
- add_fraud_parameters(post, options)
139
178
 
140
179
  commit(:cancel, post)
141
180
  end
@@ -145,7 +184,6 @@ module ActiveMerchant #:nodoc:
145
184
 
146
185
  add_amount_without_currency(post, money)
147
186
  add_reference(post, identification)
148
- add_fraud_parameters(post, options)
149
187
 
150
188
  commit(:refund, post)
151
189
  end
@@ -219,7 +257,7 @@ module ActiveMerchant #:nodoc:
219
257
  end
220
258
 
221
259
  def add_fraud_parameters(post, options)
222
- if @protocol == 4
260
+ if @protocol >= 4
223
261
  post[:fraud_remote_addr] = options[:fraud_remote_addr] if options[:fraud_remote_addr]
224
262
  post[:fraud_http_accept] = options[:fraud_http_accept] if options[:fraud_http_accept]
225
263
  post[:fraud_http_accept_language] = options[:fraud_http_accept_language] if options[:fraud_http_accept_language]
@@ -65,6 +65,7 @@ module ActiveMerchant #:nodoc:
65
65
  add_credit_card(post, credit_card)
66
66
  add_address(post, options)
67
67
  add_customer_data(post, options)
68
+ add_optional_data(post, options)
68
69
 
69
70
  commit(:purchase, post)
70
71
  end
@@ -79,6 +80,7 @@ module ActiveMerchant #:nodoc:
79
80
  add_credit_card(post, credit_card)
80
81
  add_address(post, options)
81
82
  add_customer_data(post, options)
83
+ add_optional_data(post, options)
82
84
 
83
85
  commit(:authorization, post)
84
86
  end
@@ -156,6 +158,10 @@ module ActiveMerchant #:nodoc:
156
158
  add_pair(post, :ClientIPAddress, options[:ip])
157
159
  end
158
160
 
161
+ def add_optional_data(post, options)
162
+ add_pair(post, :GiftAidPayment, options[:gift_aid_payment]) unless options[:gift_aid_payment].blank?
163
+ end
164
+
159
165
  def add_address(post, options)
160
166
  if billing_address = options[:billing_address] || options[:address]
161
167
  first_name, last_name = parse_first_and_last_name(billing_address[:name])
@@ -221,7 +221,7 @@ module ActiveMerchant #:nodoc:
221
221
  parameters[:amount] = amount(money) if money
222
222
  response = parse( ssl_post(self.live_url, post_data(action,parameters)) )
223
223
  Response.new(response["response"] == "1", message_from(response), response,
224
- :authorization => response["transactionid"],
224
+ :authorization => (response["transactionid"] || response["customer_vault_id"]),
225
225
  :test => test?,
226
226
  :cvv_result => response["cvvresponse"],
227
227
  :avs_result => { :code => response["avsresponse"] }
@@ -0,0 +1,235 @@
1
+ require 'nokogiri'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ # Public: This gateway allows you to interact with any gateway you've
6
+ # created in Spreedly Core (https://spreedlycore.com). It's an adapter
7
+ # which can be particularly useful if you already have code interacting with
8
+ # ActiveMerchant and want to easily take advantage of Core's vault.
9
+ class SpreedlyCoreGateway < Gateway
10
+ self.live_url = 'https://spreedlycore.com/v1'
11
+
12
+ self.supported_countries = %w(AD AE AT AU BD BE BG BN CA CH CY CZ DE DK EE EG ES FI FR GB
13
+ GI GR HK HU ID IE IL IM IN IS IT JO KW LB LI LK LT LU LV MC
14
+ MT MU MV MX MY NL NO NZ OM PH PL PT QA RO SA SE SG SI SK SM
15
+ TR TT UM US VA VN ZA)
16
+
17
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover]
18
+ self.homepage_url = 'https://spreedlycore.com'
19
+ self.display_name = 'Spreedly Core'
20
+ self.money_format = :cents
21
+ self.default_currency = 'USD'
22
+
23
+ # Public: Create a new Spreedly Core Gateway.
24
+ #
25
+ # options - A hash of options:
26
+ # :login - Your Spreedly Core API login.
27
+ # :password - Your Spreedly Core API secret.
28
+ # :gateway_token - The token of the gateway you've created in
29
+ # Spreedly Core.
30
+ def initialize(options = {})
31
+ requires!(options, :login, :password, :gateway_token)
32
+ super
33
+ end
34
+
35
+ # Public: Run a purchase transaction.
36
+ #
37
+ # money - The monetary amount of the transaction in cents.
38
+ # payment_method - The CreditCard or the Spreedly Core payment method
39
+ # token.
40
+ # options - A standard ActiveMerchant options hash
41
+ def purchase(money, payment_method, options = {})
42
+ if payment_method.is_a?(String)
43
+ purchase_with_token(money, payment_method, options)
44
+ else
45
+ MultiResponse.run do |r|
46
+ r.process { save_card(false, payment_method, options) }
47
+ r.process { purchase_with_token(money, r.authorization, options) }
48
+ end
49
+ end
50
+ end
51
+
52
+ # Public: Run an authorize transaction.
53
+ #
54
+ # money - The monetary amount of the transaction in cents.
55
+ # payment_method - The CreditCard or the Spreedly Core payment method
56
+ # token.
57
+ # options - A standard ActiveMerchant options hash
58
+ def authorize(money, payment_method, options = {})
59
+ if payment_method.is_a?(String)
60
+ authorize_with_token(money, payment_method, options)
61
+ else
62
+ MultiResponse.run do |r|
63
+ r.process { save_card(false, payment_method, options) }
64
+ r.process { authorize_with_token(money, r.authorization, options) }
65
+ end
66
+ end
67
+ end
68
+
69
+ def capture(money, authorization, options={})
70
+ request = build_xml_request('transaction') do |doc|
71
+ add_invoice(doc, money, options)
72
+ end
73
+
74
+ commit("transactions/#{authorization}/capture.xml", request)
75
+ end
76
+
77
+ def refund(money, authorization, options={})
78
+ request = build_xml_request('transaction') do |doc|
79
+ add_invoice(doc, money, options)
80
+ end
81
+
82
+ commit("transactions/#{authorization}/credit.xml", request)
83
+ end
84
+
85
+ def void(authorization, options={})
86
+ commit("transactions/#{authorization}/void.xml", '')
87
+ end
88
+
89
+ # Public: Store a credit card in the Spreedly Core vault and retain it.
90
+ #
91
+ # credit_card - The CreditCard to store
92
+ # options - A standard ActiveMerchant options hash
93
+ def store(credit_card, options={})
94
+ save_card(true, credit_card, options)
95
+ end
96
+
97
+ # Public: Redact the CreditCard in Spreedly Core. This wipes the
98
+ # sensitive payment information from the card.
99
+ #
100
+ # credit_card - The CreditCard to store
101
+ # options - A standard ActiveMerchant options hash
102
+ def unstore(authorization, options={})
103
+ commit("payment_methods/#{authorization}/redact.xml", '', :put)
104
+ end
105
+
106
+ private
107
+ def save_card(retain, credit_card, options)
108
+ request = build_xml_request('payment_method') do |doc|
109
+ add_credit_card(doc, credit_card, options)
110
+ add_data(doc, options)
111
+ doc.retained(true) if retain
112
+ end
113
+
114
+ commit("payment_methods.xml", request, :post, :payment_method_token)
115
+ end
116
+
117
+ def purchase_with_token(money, payment_method_token, options)
118
+ request = auth_purchase_request(money, payment_method_token, options)
119
+ commit("gateways/#{@options[:gateway_token]}/purchase.xml", request)
120
+ end
121
+
122
+ def authorize_with_token(money, payment_method_token, options)
123
+ request = auth_purchase_request(money, payment_method_token, options)
124
+ commit("gateways/#{@options[:gateway_token]}/authorize.xml", request)
125
+ end
126
+
127
+ def auth_purchase_request(money, payment_method_token, options)
128
+ build_xml_request('transaction') do |doc|
129
+ add_invoice(doc, money, options)
130
+ doc.payment_method_token(payment_method_token)
131
+ end
132
+ end
133
+
134
+ def add_invoice(doc, money, options)
135
+ doc.amount amount(money)
136
+ doc.currency_code(options[:currency] || currency(money) || default_currency)
137
+ end
138
+
139
+ def add_credit_card(doc, credit_card, options)
140
+ doc.credit_card do
141
+ doc.number(credit_card.number)
142
+ doc.first_name(credit_card.first_name)
143
+ doc.last_name(credit_card.last_name)
144
+ doc.month(credit_card.month)
145
+ doc.year(credit_card.year)
146
+ doc.email(options[:email])
147
+ doc.address1(options[:billing_address].try(:[], :address1))
148
+ doc.address2(options[:billing_address].try(:[], :address2))
149
+ doc.city(options[:billing_address].try(:[], :city))
150
+ doc.state(options[:billing_address].try(:[], :state))
151
+ doc.zip(options[:billing_address].try(:[], :zip))
152
+ end
153
+ end
154
+
155
+ def add_data(doc, options)
156
+ doc.data do
157
+ data_to_doc(doc, options[:data])
158
+ end
159
+ end
160
+
161
+ def data_to_doc(doc, value)
162
+ return doc.text value unless value.kind_of? Hash
163
+ value.each do |k, v|
164
+ doc.send(k) do
165
+ data_to_doc(doc, v)
166
+ end
167
+ end
168
+ end
169
+
170
+ def parse(xml)
171
+ response = {}
172
+
173
+ doc = Nokogiri::XML(xml)
174
+ doc.root.xpath('*').each do |node|
175
+ if (node.elements.empty?)
176
+ response[node.name.downcase.to_sym] = node.text
177
+ else
178
+ node.elements.each do |childnode|
179
+ childnode_to_response(response, node, childnode)
180
+ end
181
+ end
182
+ end
183
+
184
+ response
185
+ end
186
+
187
+ def childnode_to_response(response, node, childnode)
188
+ name = "#{node.name.downcase}_#{childnode.name.downcase}"
189
+ if name == 'payment_method_data' && !childnode.elements.empty?
190
+ response[name.to_sym] = Hash.from_xml(childnode.to_s).values.first
191
+ else
192
+ response[name.to_sym] = childnode.text
193
+ end
194
+ end
195
+
196
+ def build_xml_request(root)
197
+ builder = Nokogiri::XML::Builder.new
198
+ builder.__send__(root) do |doc|
199
+ yield(doc)
200
+ end
201
+ builder.to_xml
202
+ end
203
+
204
+ def commit(relative_url, request, method = :post, authorization_field = :token)
205
+ begin
206
+ raw_response = ssl_request(method, "#{live_url}/#{relative_url}", request, headers)
207
+ rescue ResponseError => e
208
+ raw_response = e.response.body
209
+ end
210
+
211
+ response_from(raw_response, authorization_field)
212
+ end
213
+
214
+ def response_from(raw_response, authorization_field)
215
+ parsed = parse(raw_response)
216
+ options = {
217
+ :authorization => parsed[authorization_field],
218
+ :test => (parsed[:on_test_gateway] == 'true'),
219
+ :avs_result => { :code => parsed[:response_avs_code] },
220
+ :cvv_result => parsed[:response_cvv_code]
221
+ }
222
+
223
+ Response.new(parsed[:succeeded] == 'true', parsed[:message] || parsed[:error], parsed, options)
224
+ end
225
+
226
+ def headers
227
+ {
228
+ 'Authorization' => ('Basic ' + Base64.strict_encode64("#{@options[:login]}:#{@options[:password]}").chomp),
229
+ 'Content-Type' => 'text/xml'
230
+ }
231
+ end
232
+ end
233
+ end
234
+ end
235
+
@@ -50,6 +50,7 @@ module ActiveMerchant #:nodoc:
50
50
  add_customer(post, options)
51
51
  add_customer_data(post,options)
52
52
  post[:description] = options[:description] || options[:email]
53
+ post[:application_fee] = options[:application_fee] if options[:application_fee]
53
54
  add_flags(post, options)
54
55
 
55
56
  meta = generate_meta(options)
@@ -16,7 +16,7 @@ module ActiveMerchant #:nodoc:
16
16
  'xsi:noNamespaceSchemaLocation' => 'wirecard.xsd'
17
17
  }
18
18
 
19
- PERMITTED_TRANSACTIONS = %w[ AUTHORIZATION CAPTURE_AUTHORIZATION PURCHASE ]
19
+ PERMITTED_TRANSACTIONS = %w[ PREAUTHORIZATION CAPTURE PURCHASE ]
20
20
 
21
21
  RETURN_CODES = %w[ ACK NOK ]
22
22
 
@@ -63,13 +63,13 @@ module ActiveMerchant #:nodoc:
63
63
  # Authorization
64
64
  def authorize(money, creditcard, options = {})
65
65
  options[:credit_card] = creditcard
66
- commit(:authorization, money, options)
66
+ commit(:preauthorization, money, options)
67
67
  end
68
68
 
69
69
  # Capture Authorization
70
70
  def capture(money, authorization, options = {})
71
- options[:authorization] = authorization
72
- commit(:capture_authorization, money, options)
71
+ options[:preauthorization] = authorization
72
+ commit(:capture, money, options)
73
73
  end
74
74
 
75
75
  # Purchase
@@ -148,16 +148,17 @@ module ActiveMerchant #:nodoc:
148
148
  options[:order_id] ||= generate_unique_id
149
149
 
150
150
  xml.tag! "FNC_CC_#{options[:action].to_s.upcase}" do
151
- xml.tag! 'FunctionID', options[:description]
151
+ xml.tag! 'FunctionID', options[:description].to_s.slice(0,32)
152
152
  xml.tag! 'CC_TRANSACTION' do
153
153
  xml.tag! 'TransactionID', options[:order_id]
154
154
  case options[:action]
155
- when :authorization, :purchase
155
+ when :preauthorization, :purchase
156
156
  add_invoice(xml, money, options)
157
157
  add_creditcard(xml, options[:credit_card])
158
158
  add_address(xml, options[:billing_address])
159
- when :capture_authorization
160
- xml.tag! 'GuWID', options[:authorization]
159
+ when :capture
160
+ xml.tag! 'GuWID', options[:preauthorization]
161
+ add_amount(xml, money)
161
162
  end
162
163
  end
163
164
  end
@@ -165,7 +166,7 @@ module ActiveMerchant #:nodoc:
165
166
 
166
167
  # Includes the payment (amount, currency, country) to the transaction-xml
167
168
  def add_invoice(xml, money, options)
168
- xml.tag! 'Amount', amount(money)
169
+ add_amount(xml, money)
169
170
  xml.tag! 'Currency', options[:currency] || currency(money)
170
171
  xml.tag! 'CountryCode', options[:billing_address][:country]
171
172
  xml.tag! 'RECURRING_TRANSACTION' do
@@ -173,6 +174,11 @@ module ActiveMerchant #:nodoc:
173
174
  end
174
175
  end
175
176
 
177
+ # Include the amount in the transaction-xml
178
+ def add_amount(xml, money)
179
+ xml.tag! 'Amount', amount(money)
180
+ end
181
+
176
182
  # Includes the credit-card data to the transaction-xml
177
183
  def add_creditcard(xml, creditcard)
178
184
  raise "Creditcard must be supplied!" if creditcard.nil?
@@ -38,6 +38,10 @@ module ActiveMerchant #:nodoc:
38
38
  def capture(money, authorization, options = {})
39
39
  MultiResponse.run do |r|
40
40
  r.process{inquire_request(authorization, options, "AUTHORISED")} unless options[:authorization_validated]
41
+ if r.params
42
+ authorization_currency = r.params['amount_currency_code']
43
+ options = options.merge(:currency => authorization_currency) if authorization_currency.present?
44
+ end
41
45
  r.process{capture_request(money, authorization, options)}
42
46
  end
43
47
  end
@@ -148,10 +152,10 @@ module ActiveMerchant #:nodoc:
148
152
  end
149
153
 
150
154
  def add_amount(xml, money, options)
151
- xml.tag! 'amount',
152
- :value => amount(money),
153
- 'currencyCode' => (options[:currency] || currency(money)),
154
- 'exponent' => 2
155
+ currency = options[:currency] || currency(money)
156
+ amount = localized_amount(money, currency)
157
+
158
+ xml.tag! 'amount', :value => amount, 'currencyCode' => currency, 'exponent' => 2
155
159
  end
156
160
 
157
161
  def add_payment_method(xml, amount, payment_method, options)
@@ -261,6 +265,13 @@ module ActiveMerchant #:nodoc:
261
265
  credentials = "#{@options[:login]}:#{@options[:password]}"
262
266
  "Basic #{[credentials].pack('m').strip}"
263
267
  end
268
+
269
+ def localized_amount(money, currency)
270
+ amount = amount(money)
271
+ return amount unless CURRENCIES_WITHOUT_FRACTIONS.include?(currency.to_s)
272
+
273
+ amount.to_i / 100 * 100
274
+ end
264
275
  end
265
276
  end
266
277
  end
@@ -20,7 +20,6 @@ module ActiveMerchant #:nodoc:
20
20
  mapping :credential2, 'pwd'
21
21
  mapping :credential3, 'partner'
22
22
  mapping :order, 'user1'
23
- mapping :description, 'description'
24
23
 
25
24
  mapping :amount, 'amt'
26
25
 
@@ -35,6 +34,10 @@ module ActiveMerchant #:nodoc:
35
34
 
36
35
  mapping :customer, :name => 'name'
37
36
 
37
+ def description(value)
38
+ add_field('description', "#{value}".delete("#"))
39
+ end
40
+
38
41
  def customer(params = {})
39
42
  add_field(mappings[:customer][:name], [params.delete(:first_name), params.delete(:last_name)].compact.join(' '))
40
43
  end