activemerchant 1.29.1 → 1.31.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 (53) hide show
  1. data/CHANGELOG +58 -0
  2. data/CONTRIBUTORS +27 -0
  3. data/README.md +45 -41
  4. data/lib/active_merchant/billing/check.rb +11 -11
  5. data/lib/active_merchant/billing/credit_card.rb +1 -1
  6. data/lib/active_merchant/billing/credit_card_formatting.rb +8 -8
  7. data/lib/active_merchant/billing/gateway.rb +2 -2
  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/evo_ca.rb +308 -0
  17. data/lib/active_merchant/billing/gateways/eway.rb +114 -171
  18. data/lib/active_merchant/billing/gateways/eway_managed.rb +52 -22
  19. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +232 -0
  20. data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +13 -2
  21. data/lib/active_merchant/billing/gateways/litle.rb +50 -19
  22. data/lib/active_merchant/billing/gateways/merchant_ware.rb +44 -9
  23. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +190 -0
  24. data/lib/active_merchant/billing/gateways/moneris.rb +3 -5
  25. data/lib/active_merchant/billing/gateways/moneris_us.rb +1 -1
  26. data/lib/active_merchant/billing/gateways/nab_transact.rb +20 -3
  27. data/lib/active_merchant/billing/gateways/netbilling.rb +1 -0
  28. data/lib/active_merchant/billing/gateways/netpay.rb +223 -0
  29. data/lib/active_merchant/billing/gateways/ogone.rb +6 -4
  30. data/lib/active_merchant/billing/gateways/optimal_payment.rb +18 -3
  31. data/lib/active_merchant/billing/gateways/orbital.rb +9 -5
  32. data/lib/active_merchant/billing/gateways/payment_express.rb +62 -1
  33. data/lib/active_merchant/billing/gateways/paymill.rb +161 -0
  34. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +1 -1
  35. data/lib/active_merchant/billing/gateways/paypal_express.rb +17 -11
  36. data/lib/active_merchant/billing/gateways/pin.rb +157 -0
  37. data/lib/active_merchant/billing/gateways/qbms.rb +3 -2
  38. data/lib/active_merchant/billing/gateways/quickpay.rb +66 -28
  39. data/lib/active_merchant/billing/gateways/sage_pay.rb +6 -0
  40. data/lib/active_merchant/billing/gateways/smart_ps.rb +1 -1
  41. data/lib/active_merchant/billing/gateways/spreedly_core.rb +235 -0
  42. data/lib/active_merchant/billing/gateways/stripe.rb +1 -0
  43. data/lib/active_merchant/billing/gateways/wirecard.rb +15 -9
  44. data/lib/active_merchant/billing/gateways/worldpay.rb +19 -5
  45. data/lib/active_merchant/billing/integrations/payflow_link/helper.rb +4 -1
  46. data/lib/active_merchant/billing/integrations/paypal/notification.rb +39 -31
  47. data/lib/active_merchant/billing/integrations/quickpay/helper.rb +13 -10
  48. data/lib/active_merchant/billing/integrations/quickpay/notification.rb +14 -14
  49. data/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb +2 -2
  50. data/lib/active_merchant/version.rb +1 -1
  51. data.tar.gz.sig +0 -0
  52. metadata +32 -24
  53. metadata.gz.sig +0 -0
@@ -0,0 +1,161 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class PaymillGateway < Gateway
4
+ self.supported_countries = %w(AT BE CH CZ DE DK EE ES FI FR GB HU IE
5
+ IS IT LI LU LV NL NO PL PT SE SI TR)
6
+
7
+ self.supported_cardtypes = [:visa, :master]
8
+ self.homepage_url = 'https://paymill.com'
9
+ self.display_name = 'Paymill'
10
+ self.money_format = :cents
11
+ self.default_currency = 'EUR'
12
+
13
+ def initialize(options = {})
14
+ requires!(options, :public_key, :private_key)
15
+ super
16
+ end
17
+
18
+ def purchase(money, credit_card, options = {})
19
+ MultiResponse.run do |r|
20
+ r.process { save_card(credit_card) }
21
+ r.process { purchase_with_token(money, r.authorization, options) }
22
+ end
23
+ end
24
+
25
+ def authorize(money, credit_card, options = {})
26
+ MultiResponse.run do |r|
27
+ r.process { save_card(credit_card) }
28
+ r.process { authorize_with_token(money, r.authorization, options) }
29
+ end
30
+ end
31
+
32
+ def capture(money, authorization, options = {})
33
+ post = {}
34
+
35
+ add_amount(post, money, options)
36
+ post[:preauthorization] = preauth(authorization)
37
+ post[:description] = options[:description]
38
+ commit(:post, 'transactions', post)
39
+ end
40
+
41
+ def refund(money, authorization, options={})
42
+ post = {}
43
+
44
+ post[:amount] = amount(money)
45
+ post[:description] = options[:description]
46
+ commit(:post, "refunds/#{transaction_id(authorization)}", post)
47
+ end
48
+
49
+ private
50
+
51
+ def add_credit_card(post, credit_card)
52
+ post['account.number'] = credit_card.number
53
+ post['account.expiry.month'] = sprintf("%.2i", credit_card.month)
54
+ post['account.expiry.year'] = sprintf("%.4i", credit_card.year)
55
+ post['account.verification'] = credit_card.verification_value
56
+ end
57
+
58
+ def headers
59
+ { 'Authorization' => ('Basic ' + Base64.strict_encode64("#{@options[:private_key]}:X").chomp) }
60
+ end
61
+
62
+ def commit(method, url, parameters=nil)
63
+ begin
64
+ raw_response = ssl_request(method, "https://api.paymill.com/v2/#{url}", post_data(parameters), headers)
65
+ rescue ResponseError => e
66
+ parsed = JSON.parse(e.response.body)
67
+ return Response.new(false, parsed['error'], parsed, {})
68
+ end
69
+
70
+ response_from(raw_response)
71
+ end
72
+
73
+ def response_from(raw_response)
74
+ parsed = JSON.parse(raw_response)
75
+
76
+ options = {
77
+ :authorization => authorization_from(parsed),
78
+ :test => (parsed['mode'] == 'test'),
79
+ }
80
+
81
+ Response.new(true, 'Transaction approved', parsed, options)
82
+ end
83
+
84
+ def authorization_from(parsed_response)
85
+ [
86
+ parsed_response['data']['id'],
87
+ parsed_response['data']['preauthorization'].try(:[], 'id')
88
+ ].join(";")
89
+ end
90
+
91
+ def purchase_with_token(money, card_token, options)
92
+ post = {}
93
+
94
+ add_amount(post, money, options)
95
+ post[:token] = card_token
96
+ post[:description] = options[:description]
97
+ commit(:post, 'transactions', post)
98
+ end
99
+
100
+ def authorize_with_token(money, card_token, options)
101
+ post = {}
102
+
103
+ add_amount(post, money, options)
104
+ post[:token] = card_token
105
+ commit(:post, 'preauthorizations', post)
106
+ end
107
+
108
+ def save_card(credit_card)
109
+ post = {}
110
+
111
+ add_credit_card(post, credit_card)
112
+ post['channel.id'] = @options[:public_key]
113
+ post['jsonPFunction'] = 'jsonPFunction'
114
+ post['transaction.mode'] = (test? ? 'CONNECTOR_TEST' : 'LIVE')
115
+
116
+ begin
117
+ raw_response = ssl_request(:get, "#{save_card_url}?#{post_data(post)}", nil, {})
118
+ rescue ResponseError => e
119
+ return Response.new(false, e.response.body, e.response.body, {})
120
+ end
121
+
122
+ response_for_save_from(raw_response)
123
+ end
124
+
125
+ def response_for_save_from(raw_response)
126
+ parsed = JSON.parse(raw_response.sub(/jsonPFunction\(/, '').sub(/\)\z/, ''))
127
+ succeeded = parsed['transaction']['processing']['result'] == 'ACK'
128
+
129
+ options = { :test => test? }
130
+ if succeeded
131
+ options[:authorization] = parsed['transaction']['identification']['uniqueId']
132
+ end
133
+
134
+ message = parsed['transaction']['processing']['return']['message']
135
+ Response.new(succeeded, message, parsed, options)
136
+ end
137
+
138
+ def save_card_url
139
+ (test? ? 'https://test-token.paymill.de' : 'https://token-v2.paymill.de')
140
+ end
141
+
142
+ def post_data(params)
143
+ no_blanks = params.reject { |key, value| value.blank? }
144
+ no_blanks.map { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&")
145
+ end
146
+
147
+ def add_amount(post, money, options)
148
+ post[:amount] = amount(money)
149
+ post[:currency] = (options[:currency] || currency(money))
150
+ end
151
+
152
+ def preauth(authorization)
153
+ authorization.split(";").last
154
+ end
155
+
156
+ def transaction_id(authorization)
157
+ authorization.split(';').first
158
+ end
159
+ end
160
+ end
161
+ end
@@ -397,7 +397,7 @@ module ActiveMerchant #:nodoc:
397
397
  transaction_search_optional_fields = %w{ Payer ReceiptID Receiver
398
398
  TransactionID InvoiceID CardNumber
399
399
  AuctionItemNumber TransactionClass
400
- CurrencyCode Status }
400
+ CurrencyCode Status ProfileID }
401
401
  build_request_wrapper('TransactionSearch') do |xml|
402
402
  xml.tag! 'StartDate', date_to_iso(options[:start_date])
403
403
  xml.tag! 'EndDate', date_to_iso(options[:end_date]) unless options[:end_date].blank?
@@ -1,5 +1,6 @@
1
1
  require File.dirname(__FILE__) + '/paypal/paypal_common_api'
2
2
  require File.dirname(__FILE__) + '/paypal/paypal_express_response'
3
+ require File.dirname(__FILE__) + '/paypal/paypal_recurring_api'
3
4
  require File.dirname(__FILE__) + '/paypal_express_common'
4
5
 
5
6
  module ActiveMerchant #:nodoc:
@@ -7,6 +8,7 @@ module ActiveMerchant #:nodoc:
7
8
  class PaypalExpressGateway < Gateway
8
9
  include PaypalCommonAPI
9
10
  include PaypalExpressCommon
11
+ include PaypalRecurringApi
10
12
 
11
13
  NON_STANDARD_LOCALE_CODES = {
12
14
  'DK' => 'da_DK',
@@ -28,16 +30,16 @@ module ActiveMerchant #:nodoc:
28
30
  self.supported_countries = ['US']
29
31
  self.homepage_url = 'https://www.paypal.com/cgi-bin/webscr?cmd=xpt/merchant/ExpressCheckoutIntro-outside'
30
32
  self.display_name = 'PayPal Express Checkout'
31
-
33
+
32
34
  def setup_authorization(money, options = {})
33
35
  requires!(options, :return_url, :cancel_return_url)
34
-
36
+
35
37
  commit 'SetExpressCheckout', build_setup_request('Authorization', money, options)
36
38
  end
37
-
39
+
38
40
  def setup_purchase(money, options = {})
39
41
  requires!(options, :return_url, :cancel_return_url)
40
-
42
+
41
43
  commit 'SetExpressCheckout', build_setup_request('Sale', money, options)
42
44
  end
43
45
 
@@ -47,13 +49,13 @@ module ActiveMerchant #:nodoc:
47
49
 
48
50
  def authorize(money, options = {})
49
51
  requires!(options, :token, :payer_id)
50
-
52
+
51
53
  commit 'DoExpressCheckoutPayment', build_sale_or_authorization_request('Authorization', money, options)
52
54
  end
53
55
 
54
56
  def purchase(money, options = {})
55
57
  requires!(options, :token, :payer_id)
56
-
58
+
57
59
  commit 'DoExpressCheckoutPayment', build_sale_or_authorization_request('Sale', money, options)
58
60
  end
59
61
 
@@ -75,10 +77,10 @@ module ActiveMerchant #:nodoc:
75
77
 
76
78
  xml.target!
77
79
  end
78
-
80
+
79
81
  def build_sale_or_authorization_request(action, money, options)
80
82
  currency_code = options[:currency] || currency(money)
81
-
83
+
82
84
  xml = Builder::XmlMarkup.new :indent => 2
83
85
  xml.tag! 'DoExpressCheckoutPaymentReq', 'xmlns' => PAYPAL_NAMESPACE do
84
86
  xml.tag! 'DoExpressCheckoutPaymentRequest', 'xmlns:n2' => EBAY_NAMESPACE do
@@ -139,7 +141,7 @@ module ActiveMerchant #:nodoc:
139
141
  xml.tag! 'n2:AllowNote', options[:allow_note] ? '1' : '0'
140
142
  end
141
143
  xml.tag! 'n2:CallbackURL', options[:callback_url] unless options[:callback_url].blank?
142
-
144
+
143
145
  add_payment_details(xml, with_money_default(money), currency_code, options)
144
146
  if options[:shipping_options]
145
147
  options[:shipping_options].each do |shipping_option|
@@ -153,16 +155,20 @@ module ActiveMerchant #:nodoc:
153
155
 
154
156
  xml.tag! 'n2:CallbackTimeout', options[:callback_timeout] unless options[:callback_timeout].blank?
155
157
  xml.tag! 'n2:CallbackVersion', options[:callback_version] unless options[:callback_version].blank?
158
+
159
+ if options.has_key?(:allow_buyer_optin)
160
+ xml.tag! 'n2:BuyerEmailOptInEnable', (options[:allow_buyer_optin] ? '1' : '0')
161
+ end
156
162
  end
157
163
  end
158
164
  end
159
165
 
160
166
  xml.target!
161
167
  end
162
-
168
+
163
169
  def build_reference_transaction_request(action, money, options)
164
170
  currency_code = options[:currency] || currency(money)
165
-
171
+
166
172
  # I am not sure why it's set like this for express gateway
167
173
  # but I don't want to break the existing behavior
168
174
  xml = Builder::XmlMarkup.new :indent => 2
@@ -0,0 +1,157 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class PinGateway < Gateway
4
+ self.test_url = 'https://test-api.pin.net.au/1'
5
+ self.live_url = 'https://api.pin.net.au/1'
6
+
7
+ self.default_currency = 'AUD'
8
+ self.money_format = :cents
9
+ self.supported_countries = ['AU']
10
+ self.supported_cardtypes = [:visa, :master]
11
+ self.homepage_url = 'http://www.pin.net.au/'
12
+ self.display_name = 'Pin'
13
+
14
+ def initialize(options = {})
15
+ requires!(options, :api_key)
16
+ super
17
+ end
18
+
19
+ # Create a charge using a credit card, card token or customer token
20
+ #
21
+ # To charge a credit card: purchase([money], [creditcard hash], ...)
22
+ # To charge a customer: purchase([money], [token], ...)
23
+ def purchase(money, creditcard, options = {})
24
+ post = {}
25
+
26
+ add_amount(post, money, options)
27
+ add_customer_data(post, options)
28
+ add_invoice(post, options)
29
+ add_creditcard(post, creditcard)
30
+ add_address(post, creditcard, options)
31
+
32
+ commit('charges', post)
33
+ end
34
+
35
+ # Create a customer and associated credit card. The token that is returned
36
+ # can be used instead of a credit card parameter in the purchase method
37
+ def store(creditcard, options = {})
38
+ post = {}
39
+
40
+ add_creditcard(post, creditcard)
41
+ add_customer_data(post, options)
42
+ add_address(post, creditcard, options)
43
+ commit('customers', post)
44
+ end
45
+
46
+ # Refund a transaction, note that the money attribute is ignored at the
47
+ # moment as the API does not support partial refunds. The parameter is
48
+ # kept for compatibility reasons
49
+ def refund(money, token, options = {})
50
+ commit("charges/#{CGI.escape(token)}/refunds", :amount => amount(money))
51
+ end
52
+
53
+ private
54
+ def add_amount(post, money, options)
55
+ post[:amount] = amount(money)
56
+ post[:currency] = (options[:currency] || currency(money))
57
+ post[:currency] = post[:currency].upcase if post[:currency]
58
+ end
59
+
60
+ def add_customer_data(post, options)
61
+ post[:email] = options[:email]
62
+ post[:ip_address] = options[:ip]
63
+ end
64
+
65
+ def add_address(post, creditcard, options)
66
+ return if creditcard.kind_of?(String)
67
+ address = (options[:billing_address] || options[:address])
68
+ return unless address
69
+
70
+ post[:card] ||= {}
71
+ post[:card].merge!(
72
+ :address_line1 => address[:address1],
73
+ :address_city => address[:city],
74
+ :address_postcode => address[:zip],
75
+ :address_state => address[:state],
76
+ :address_country => address[:country]
77
+ )
78
+ end
79
+
80
+ def add_invoice(post, options)
81
+ post[:description] = options[:description]
82
+ end
83
+
84
+ def add_creditcard(post, creditcard)
85
+ if creditcard.respond_to?(:number)
86
+ post[:card] ||= {}
87
+
88
+ post[:card].merge!(
89
+ :number => creditcard.number,
90
+ :expiry_month => creditcard.month,
91
+ :expiry_year => creditcard.year,
92
+ :cvc => creditcard.verification_value,
93
+ :name => "#{creditcard.first_name} #{creditcard.last_name}"
94
+ )
95
+ elsif creditcard.kind_of?(String)
96
+ post[:customer_token] = creditcard
97
+ end
98
+ end
99
+
100
+ def headers
101
+ {
102
+ "Content-Type" => "application/json",
103
+ "Authorization" => "Basic #{Base64.strict_encode64(options[:api_key] + ':').strip}"
104
+ }
105
+ end
106
+
107
+ def commit(action, params)
108
+ url = "#{test? ? test_url : live_url}/#{action}"
109
+
110
+ begin
111
+ body = parse(ssl_post(url, post_data(params), headers))
112
+ rescue ResponseError => e
113
+ body = parse(e.response.body)
114
+ end
115
+
116
+ if body["response"]
117
+ success_response(body)
118
+ elsif body["error"]
119
+ error_response(body)
120
+ end
121
+ end
122
+
123
+ def success_response(body)
124
+ response = body["response"]
125
+ Response.new(
126
+ true,
127
+ response['status_message'],
128
+ body,
129
+ :authorization => token(response),
130
+ :test => test?
131
+ )
132
+ end
133
+
134
+ def error_response(body)
135
+ Response.new(
136
+ false,
137
+ body['error_description'],
138
+ body,
139
+ :authorization => nil,
140
+ :test => test?
141
+ )
142
+ end
143
+
144
+ def token(response)
145
+ response['token']
146
+ end
147
+
148
+ def parse(body)
149
+ JSON.parse(body)
150
+ end
151
+
152
+ def post_data(parameters = {})
153
+ parameters.to_json
154
+ end
155
+ end
156
+ end
157
+ end
@@ -126,6 +126,7 @@ module ActiveMerchant #:nodoc:
126
126
  parameters[:trans_request_id] ||= SecureRandom.hex(10)
127
127
 
128
128
  req = build_request(type, money, parameters)
129
+
129
130
  data = ssl_post(url, req, "Content-Type" => "application/x-qbmsxml")
130
131
  response = parse(type, data)
131
132
  message = (response[:status_message] || '').strip
@@ -260,8 +261,8 @@ module ActiveMerchant #:nodoc:
260
261
 
261
262
  def add_address(xml, parameters)
262
263
  if address = parameters[:billing_address] || parameters[:address]
263
- xml.tag!("CreditCardAddress", address[:address1][0...30])
264
- xml.tag!("CreditCardPostalCode", address[:zip][0...9])
264
+ xml.tag!("CreditCardAddress", (address[:address1] || "")[0...30])
265
+ xml.tag!("CreditCardPostalCode", (address[:zip] || "")[0...9])
265
266
  end
266
267
  end
267
268
 
@@ -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"] }