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.
- data/CHANGELOG +58 -0
- data/CONTRIBUTORS +27 -0
- data/README.md +45 -41
- data/lib/active_merchant/billing/check.rb +11 -11
- data/lib/active_merchant/billing/credit_card.rb +1 -1
- data/lib/active_merchant/billing/credit_card_formatting.rb +8 -8
- data/lib/active_merchant/billing/gateway.rb +2 -2
- data/lib/active_merchant/billing/gateways/authorize_net.rb +9 -1
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +15 -4
- data/lib/active_merchant/billing/gateways/balanced.rb +9 -3
- data/lib/active_merchant/billing/gateways/banwire.rb +15 -1
- data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +6 -2
- data/lib/active_merchant/billing/gateways/beanstream.rb +26 -24
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +5 -2
- data/lib/active_merchant/billing/gateways/cyber_source.rb +55 -22
- data/lib/active_merchant/billing/gateways/evo_ca.rb +308 -0
- data/lib/active_merchant/billing/gateways/eway.rb +114 -171
- data/lib/active_merchant/billing/gateways/eway_managed.rb +52 -22
- data/lib/active_merchant/billing/gateways/firstdata_e4.rb +232 -0
- data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +13 -2
- data/lib/active_merchant/billing/gateways/litle.rb +50 -19
- data/lib/active_merchant/billing/gateways/merchant_ware.rb +44 -9
- data/lib/active_merchant/billing/gateways/merchant_warrior.rb +190 -0
- data/lib/active_merchant/billing/gateways/moneris.rb +3 -5
- data/lib/active_merchant/billing/gateways/moneris_us.rb +1 -1
- data/lib/active_merchant/billing/gateways/nab_transact.rb +20 -3
- data/lib/active_merchant/billing/gateways/netbilling.rb +1 -0
- data/lib/active_merchant/billing/gateways/netpay.rb +223 -0
- data/lib/active_merchant/billing/gateways/ogone.rb +6 -4
- data/lib/active_merchant/billing/gateways/optimal_payment.rb +18 -3
- data/lib/active_merchant/billing/gateways/orbital.rb +9 -5
- data/lib/active_merchant/billing/gateways/payment_express.rb +62 -1
- data/lib/active_merchant/billing/gateways/paymill.rb +161 -0
- data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +1 -1
- data/lib/active_merchant/billing/gateways/paypal_express.rb +17 -11
- data/lib/active_merchant/billing/gateways/pin.rb +157 -0
- data/lib/active_merchant/billing/gateways/qbms.rb +3 -2
- data/lib/active_merchant/billing/gateways/quickpay.rb +66 -28
- data/lib/active_merchant/billing/gateways/sage_pay.rb +6 -0
- data/lib/active_merchant/billing/gateways/smart_ps.rb +1 -1
- data/lib/active_merchant/billing/gateways/spreedly_core.rb +235 -0
- data/lib/active_merchant/billing/gateways/stripe.rb +1 -0
- data/lib/active_merchant/billing/gateways/wirecard.rb +15 -9
- data/lib/active_merchant/billing/gateways/worldpay.rb +19 -5
- data/lib/active_merchant/billing/integrations/payflow_link/helper.rb +4 -1
- data/lib/active_merchant/billing/integrations/paypal/notification.rb +39 -31
- data/lib/active_merchant/billing/integrations/quickpay/helper.rb +13 -10
- data/lib/active_merchant/billing/integrations/quickpay/notification.rb +14 -14
- data/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb +2 -2
- data/lib/active_merchant/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +32 -24
- 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
|
|
54
|
-
|
|
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
|
-
:
|
|
59
|
-
|
|
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
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
fraud_http_user_agent apikey),
|
|
88
|
+
autocapture transaction apikey),
|
|
89
|
+
|
|
90
|
+
:status => %w(protocol msgtype merchant transaction apikey),
|
|
74
91
|
|
|
75
|
-
:
|
|
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
|
-
:
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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
|
|
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(
|
|
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(
|
|
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
|
|
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"] }
|