aktivemerchant 2.0.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.
- checksums.yaml +7 -0
- data/CHANGELOG +1596 -0
- data/CONTRIBUTORS +511 -0
- data/MIT-LICENSE +20 -0
- data/README.md +18 -0
- data/lib/active_merchant.rb +108 -0
- data/lib/active_merchant/billing.rb +13 -0
- data/lib/active_merchant/billing/apple_pay_payment_token.rb +22 -0
- data/lib/active_merchant/billing/avs_result.rb +98 -0
- data/lib/active_merchant/billing/base.rb +72 -0
- data/lib/active_merchant/billing/check.rb +76 -0
- data/lib/active_merchant/billing/compatibility.rb +120 -0
- data/lib/active_merchant/billing/credit_card.rb +352 -0
- data/lib/active_merchant/billing/credit_card_formatting.rb +24 -0
- data/lib/active_merchant/billing/credit_card_methods.rb +160 -0
- data/lib/active_merchant/billing/cvv_result.rb +38 -0
- data/lib/active_merchant/billing/gateway.rb +268 -0
- data/lib/active_merchant/billing/gateways.rb +17 -0
- data/lib/active_merchant/billing/gateways/adyen.rb +209 -0
- data/lib/active_merchant/billing/gateways/alfabank.rb +117 -0
- data/lib/active_merchant/billing/gateways/app55.rb +176 -0
- data/lib/active_merchant/billing/gateways/authorize_net.rb +419 -0
- data/lib/active_merchant/billing/gateways/authorize_net_arb.rb +417 -0
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +976 -0
- data/lib/active_merchant/billing/gateways/balanced.rb +256 -0
- data/lib/active_merchant/billing/gateways/bank_frick.rb +225 -0
- data/lib/active_merchant/billing/gateways/banwire.rb +105 -0
- data/lib/active_merchant/billing/gateways/barclays_epdq.rb +314 -0
- data/lib/active_merchant/billing/gateways/barclays_epdq_extra_plus.rb +15 -0
- data/lib/active_merchant/billing/gateways/be2bill.rb +131 -0
- data/lib/active_merchant/billing/gateways/beanstream.rb +188 -0
- data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +393 -0
- data/lib/active_merchant/billing/gateways/beanstream_interac.rb +54 -0
- data/lib/active_merchant/billing/gateways/blue_pay.rb +506 -0
- data/lib/active_merchant/billing/gateways/bogus.rb +140 -0
- data/lib/active_merchant/billing/gateways/borgun.rb +210 -0
- data/lib/active_merchant/billing/gateways/braintree.rb +19 -0
- data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +9 -0
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +515 -0
- data/lib/active_merchant/billing/gateways/braintree_orange.rb +20 -0
- data/lib/active_merchant/billing/gateways/bridge_pay.rb +189 -0
- data/lib/active_merchant/billing/gateways/card_save.rb +23 -0
- data/lib/active_merchant/billing/gateways/card_stream.rb +220 -0
- data/lib/active_merchant/billing/gateways/cashnet.rb +191 -0
- data/lib/active_merchant/billing/gateways/cc5.rb +201 -0
- data/lib/active_merchant/billing/gateways/cecabank.rb +229 -0
- data/lib/active_merchant/billing/gateways/certo_direct.rb +278 -0
- data/lib/active_merchant/billing/gateways/checkout.rb +213 -0
- data/lib/active_merchant/billing/gateways/commercegate.rb +143 -0
- data/lib/active_merchant/billing/gateways/conekta.rb +209 -0
- data/lib/active_merchant/billing/gateways/cyber_source.rb +709 -0
- data/lib/active_merchant/billing/gateways/data_cash.rb +600 -0
- data/lib/active_merchant/billing/gateways/efsnet.rb +219 -0
- data/lib/active_merchant/billing/gateways/elavon.rb +348 -0
- data/lib/active_merchant/billing/gateways/epay.rb +275 -0
- data/lib/active_merchant/billing/gateways/evo_ca.rb +308 -0
- data/lib/active_merchant/billing/gateways/eway.rb +214 -0
- data/lib/active_merchant/billing/gateways/eway_managed.rb +291 -0
- data/lib/active_merchant/billing/gateways/eway_rapid.rb +524 -0
- data/lib/active_merchant/billing/gateways/exact.rb +218 -0
- data/lib/active_merchant/billing/gateways/fat_zebra.rb +173 -0
- data/lib/active_merchant/billing/gateways/federated_canada.rb +160 -0
- data/lib/active_merchant/billing/gateways/finansbank.rb +23 -0
- data/lib/active_merchant/billing/gateways/first_giving.rb +143 -0
- data/lib/active_merchant/billing/gateways/first_pay.rb +160 -0
- data/lib/active_merchant/billing/gateways/firstdata_e4.rb +355 -0
- data/lib/active_merchant/billing/gateways/garanti.rb +257 -0
- data/lib/active_merchant/billing/gateways/global_transport.rb +183 -0
- data/lib/active_merchant/billing/gateways/hdfc.rb +207 -0
- data/lib/active_merchant/billing/gateways/hps.rb +288 -0
- data/lib/active_merchant/billing/gateways/iats_payments.rb +251 -0
- data/lib/active_merchant/billing/gateways/ideal/ideal_base.rb +246 -0
- data/lib/active_merchant/billing/gateways/ideal/ideal_rabobank.pem +13 -0
- data/lib/active_merchant/billing/gateways/ideal/ideal_response.rb +29 -0
- data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +66 -0
- data/lib/active_merchant/billing/gateways/inspire.rb +213 -0
- data/lib/active_merchant/billing/gateways/instapay.rb +163 -0
- data/lib/active_merchant/billing/gateways/iridium.rb +457 -0
- data/lib/active_merchant/billing/gateways/itransact.rb +448 -0
- data/lib/active_merchant/billing/gateways/jetpay.rb +275 -0
- data/lib/active_merchant/billing/gateways/linkpoint.rb +438 -0
- data/lib/active_merchant/billing/gateways/litle.rb +346 -0
- data/lib/active_merchant/billing/gateways/maxipago.rb +197 -0
- data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +170 -0
- data/lib/active_merchant/billing/gateways/merchant_one.rb +114 -0
- data/lib/active_merchant/billing/gateways/merchant_ware.rb +319 -0
- data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +268 -0
- data/lib/active_merchant/billing/gateways/merchant_warrior.rb +195 -0
- data/lib/active_merchant/billing/gateways/mercury.rb +333 -0
- data/lib/active_merchant/billing/gateways/metrics_global.rb +303 -0
- data/lib/active_merchant/billing/gateways/migs.rb +265 -0
- data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +100 -0
- data/lib/active_merchant/billing/gateways/modern_payments.rb +37 -0
- data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +219 -0
- data/lib/active_merchant/billing/gateways/moneris.rb +309 -0
- data/lib/active_merchant/billing/gateways/moneris_us.rb +291 -0
- data/lib/active_merchant/billing/gateways/money_movers.rb +152 -0
- data/lib/active_merchant/billing/gateways/nab_transact.rb +280 -0
- data/lib/active_merchant/billing/gateways/net_registry.rb +198 -0
- data/lib/active_merchant/billing/gateways/netaxept.rb +181 -0
- data/lib/active_merchant/billing/gateways/netbilling.rb +190 -0
- data/lib/active_merchant/billing/gateways/netpay.rb +223 -0
- data/lib/active_merchant/billing/gateways/network_merchants.rb +242 -0
- data/lib/active_merchant/billing/gateways/nmi.rb +256 -0
- data/lib/active_merchant/billing/gateways/ogone.rb +435 -0
- data/lib/active_merchant/billing/gateways/openpay.rb +194 -0
- data/lib/active_merchant/billing/gateways/optimal_payment.rb +313 -0
- data/lib/active_merchant/billing/gateways/orbital.rb +803 -0
- data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +47 -0
- data/lib/active_merchant/billing/gateways/pac_net_raven.rb +207 -0
- data/lib/active_merchant/billing/gateways/pago_facil.rb +122 -0
- data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +261 -0
- data/lib/active_merchant/billing/gateways/pay_junction.rb +390 -0
- data/lib/active_merchant/billing/gateways/pay_secure.rb +112 -0
- data/lib/active_merchant/billing/gateways/pay_u_latam.rb +462 -0
- data/lib/active_merchant/billing/gateways/paybox_direct.rb +188 -0
- data/lib/active_merchant/billing/gateways/payex.rb +412 -0
- data/lib/active_merchant/billing/gateways/payflow.rb +304 -0
- data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +209 -0
- data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +39 -0
- data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +13 -0
- data/lib/active_merchant/billing/gateways/payflow_express.rb +224 -0
- data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +15 -0
- data/lib/active_merchant/billing/gateways/payflow_uk.rb +21 -0
- data/lib/active_merchant/billing/gateways/payment_express.rb +353 -0
- data/lib/active_merchant/billing/gateways/paymill.rb +281 -0
- data/lib/active_merchant/billing/gateways/paypal.rb +117 -0
- data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +670 -0
- data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +65 -0
- data/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb +262 -0
- data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
- data/lib/active_merchant/billing/gateways/paypal_digital_goods.rb +44 -0
- data/lib/active_merchant/billing/gateways/paypal_express.rb +264 -0
- data/lib/active_merchant/billing/gateways/paypal_express_common.rb +30 -0
- data/lib/active_merchant/billing/gateways/payscout.rb +162 -0
- data/lib/active_merchant/billing/gateways/paystation.rb +199 -0
- data/lib/active_merchant/billing/gateways/payway.rb +207 -0
- data/lib/active_merchant/billing/gateways/pin.rb +197 -0
- data/lib/active_merchant/billing/gateways/plugnpay.rb +283 -0
- data/lib/active_merchant/billing/gateways/psigate.rb +216 -0
- data/lib/active_merchant/billing/gateways/psl_card.rb +303 -0
- data/lib/active_merchant/billing/gateways/qbms.rb +292 -0
- data/lib/active_merchant/billing/gateways/quantum.rb +276 -0
- data/lib/active_merchant/billing/gateways/quickpay.rb +367 -0
- data/lib/active_merchant/billing/gateways/realex.rb +298 -0
- data/lib/active_merchant/billing/gateways/redsys.rb +391 -0
- data/lib/active_merchant/billing/gateways/sage.rb +175 -0
- data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +87 -0
- data/lib/active_merchant/billing/gateways/sage/sage_core.rb +114 -0
- data/lib/active_merchant/billing/gateways/sage/sage_vault.rb +149 -0
- data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +102 -0
- data/lib/active_merchant/billing/gateways/sage_pay.rb +398 -0
- data/lib/active_merchant/billing/gateways/sallie_mae.rb +143 -0
- data/lib/active_merchant/billing/gateways/secure_net.rb +252 -0
- data/lib/active_merchant/billing/gateways/secure_pay.rb +201 -0
- data/lib/active_merchant/billing/gateways/secure_pay_au.rb +281 -0
- data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +105 -0
- data/lib/active_merchant/billing/gateways/skip_jack.rb +452 -0
- data/lib/active_merchant/billing/gateways/smart_ps.rb +283 -0
- data/lib/active_merchant/billing/gateways/so_easy_pay.rb +194 -0
- data/lib/active_merchant/billing/gateways/spreedly_core.rb +247 -0
- data/lib/active_merchant/billing/gateways/stripe.rb +411 -0
- data/lib/active_merchant/billing/gateways/swipe_checkout.rb +157 -0
- data/lib/active_merchant/billing/gateways/tns.rb +227 -0
- data/lib/active_merchant/billing/gateways/trans_first.rb +126 -0
- data/lib/active_merchant/billing/gateways/transax.rb +23 -0
- data/lib/active_merchant/billing/gateways/transnational.rb +10 -0
- data/lib/active_merchant/billing/gateways/trust_commerce.rb +416 -0
- data/lib/active_merchant/billing/gateways/usa_epay.rb +25 -0
- data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +1516 -0
- data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +254 -0
- data/lib/active_merchant/billing/gateways/verifi.rb +225 -0
- data/lib/active_merchant/billing/gateways/viaklix.rb +183 -0
- data/lib/active_merchant/billing/gateways/vindicia.rb +385 -0
- data/lib/active_merchant/billing/gateways/webpay.rb +97 -0
- data/lib/active_merchant/billing/gateways/wepay.rb +189 -0
- data/lib/active_merchant/billing/gateways/wirecard.rb +421 -0
- data/lib/active_merchant/billing/gateways/worldpay.rb +331 -0
- data/lib/active_merchant/billing/gateways/worldpay_us.rb +181 -0
- data/lib/active_merchant/billing/model.rb +30 -0
- data/lib/active_merchant/billing/payment_token.rb +21 -0
- data/lib/active_merchant/billing/rails.rb +3 -0
- data/lib/active_merchant/billing/response.rb +91 -0
- data/lib/active_merchant/country.rb +332 -0
- data/lib/active_merchant/empty.rb +20 -0
- data/lib/active_merchant/errors.rb +29 -0
- data/lib/active_merchant/offsite_payments_shim.rb +19 -0
- data/lib/active_merchant/version.rb +3 -0
- data/lib/activemerchant.rb +1 -0
- data/lib/support/gateway_support.rb +71 -0
- data/lib/support/outbound_hosts.rb +25 -0
- data/lib/support/ssl_verify.rb +93 -0
- metadata +400 -0
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module ActiveMerchant #:nodoc:
|
4
|
+
module Billing #:nodoc:
|
5
|
+
class WebpayGateway < StripeGateway
|
6
|
+
self.live_url = 'https://api.webpay.jp/v1/'
|
7
|
+
|
8
|
+
self.supported_countries = ['JP']
|
9
|
+
self.default_currency = 'JPY'
|
10
|
+
self.money_format = :cents
|
11
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :jcb, :diners_club]
|
12
|
+
|
13
|
+
self.homepage_url = 'https://webpay.jp/'
|
14
|
+
self.display_name = 'WebPay'
|
15
|
+
|
16
|
+
def capture(money, authorization, options = {})
|
17
|
+
post = {}
|
18
|
+
add_amount(post, money, options)
|
19
|
+
add_application_fee(post, options)
|
20
|
+
commit(:post, "charges/#{CGI.escape(authorization)}/capture", post)
|
21
|
+
end
|
22
|
+
|
23
|
+
def refund(money, identification, options = {})
|
24
|
+
post = {}
|
25
|
+
add_amount(post, money, options)
|
26
|
+
MultiResponse.run do |r|
|
27
|
+
r.process { commit(:post, "charges/#{CGI.escape(identification)}/refund", post, options) }
|
28
|
+
|
29
|
+
return r unless options[:refund_fee_amount]
|
30
|
+
|
31
|
+
r.process { fetch_application_fees(identification, options) }
|
32
|
+
r.process { refund_application_fee(options[:refund_fee_amount], application_fee_from_response(r), options) }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def refund_fee(identification, options, meta)
|
37
|
+
raise NotImplementedError.new
|
38
|
+
end
|
39
|
+
|
40
|
+
def add_customer(post, creditcard, options)
|
41
|
+
post[:customer] = options[:customer] if options[:customer] && !creditcard.respond_to?(:number)
|
42
|
+
end
|
43
|
+
|
44
|
+
def store(creditcard, options = {})
|
45
|
+
post = {}
|
46
|
+
add_creditcard(post, creditcard, options)
|
47
|
+
post[:description] = options[:description]
|
48
|
+
post[:email] = options[:email]
|
49
|
+
|
50
|
+
if options[:customer]
|
51
|
+
MultiResponse.run(:first) do |r|
|
52
|
+
r.process { commit(:post, "customers/#{CGI.escape(options[:customer])}/", post, options) }
|
53
|
+
|
54
|
+
return r unless options[:set_default] and r.success? and !r.params["id"].blank?
|
55
|
+
|
56
|
+
r.process { update_customer(options[:customer], :default_card => r.params["id"]) }
|
57
|
+
end
|
58
|
+
else
|
59
|
+
commit(:post, 'customers', post, options)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def update(customer_id, creditcard, options = {})
|
64
|
+
post = {}
|
65
|
+
add_creditcard(post, creditcard, options)
|
66
|
+
commit(:post, "customers/#{CGI.escape(customer_id)}", post, options)
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def create_post_for_auth_or_purchase(money, creditcard, options)
|
72
|
+
stripe_post = super
|
73
|
+
stripe_post[:description] ||= stripe_post.delete(:metadata).try(:[], :email)
|
74
|
+
stripe_post
|
75
|
+
end
|
76
|
+
|
77
|
+
def json_error(raw_response)
|
78
|
+
msg = 'Invalid response received from the WebPay API. Please contact support@webpay.jp if you continue to receive this message.'
|
79
|
+
msg += " (The raw response returned by the API was #{raw_response.inspect})"
|
80
|
+
{
|
81
|
+
"error" => {
|
82
|
+
"message" => msg
|
83
|
+
}
|
84
|
+
}
|
85
|
+
end
|
86
|
+
|
87
|
+
def headers(options = {})
|
88
|
+
{
|
89
|
+
"Authorization" => "Basic " + Base64.encode64(@api_key.to_s + ":").strip,
|
90
|
+
"User-Agent" => "Webpay/v1 ActiveMerchantBindings/#{ActiveMerchant::VERSION}",
|
91
|
+
"X-Webpay-Client-User-Agent" => user_agent,
|
92
|
+
"X-Webpay-Client-User-Metadata" => {:ip => options[:ip]}.to_json
|
93
|
+
}
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,189 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
class WepayGateway < Gateway
|
4
|
+
self.test_url = 'https://stage.wepayapi.com/v2'
|
5
|
+
self.live_url = 'https://wepayapi.com/v2'
|
6
|
+
|
7
|
+
self.supported_countries = ['US']
|
8
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :discover]
|
9
|
+
self.homepage_url = 'https://www.wepay.com/'
|
10
|
+
self.default_currency = 'USD'
|
11
|
+
self.display_name = 'WePay'
|
12
|
+
|
13
|
+
def initialize(options = {})
|
14
|
+
requires!(options, :client_id, :account_id, :access_token)
|
15
|
+
super(options)
|
16
|
+
end
|
17
|
+
|
18
|
+
def purchase(money, payment_method, options = {})
|
19
|
+
post = {}
|
20
|
+
if payment_method.is_a?(String)
|
21
|
+
purchase_with_token(post, money, payment_method, options)
|
22
|
+
else
|
23
|
+
MultiResponse.run do |r|
|
24
|
+
r.process { store(payment_method, options) }
|
25
|
+
r.process { purchase_with_token(post, money, split_authorization(r.authorization).first, options) }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def authorize(money, payment_method, options = {})
|
31
|
+
post = {auto_capture: 0}
|
32
|
+
if payment_method.is_a?(String)
|
33
|
+
purchase_with_token(post, money, payment_method, options)
|
34
|
+
else
|
35
|
+
MultiResponse.run do |r|
|
36
|
+
r.process { store(payment_method, options) }
|
37
|
+
r.process { purchase_with_token(post, money, split_authorization(r.authorization).first, options) }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def capture(money, identifier, options = {})
|
43
|
+
post = {}
|
44
|
+
post[:checkout_id] = split_authorization(identifier).first
|
45
|
+
commit('/checkout/capture', post)
|
46
|
+
end
|
47
|
+
|
48
|
+
def void(identifier, options = {})
|
49
|
+
post = {}
|
50
|
+
post[:checkout_id] = split_authorization(identifier).first
|
51
|
+
post[:cancel_reason] = (options[:description] || "Void")
|
52
|
+
commit('/checkout/cancel', post)
|
53
|
+
end
|
54
|
+
|
55
|
+
def refund(money, identifier, options = {})
|
56
|
+
checkout_id, original_amount = split_authorization(identifier)
|
57
|
+
|
58
|
+
post = {}
|
59
|
+
post[:checkout_id] = checkout_id
|
60
|
+
if(money && (original_amount != amount(money)))
|
61
|
+
post[:amount] = amount(money)
|
62
|
+
end
|
63
|
+
post[:refund_reason] = (options[:description] || "Refund")
|
64
|
+
post[:app_fee] = options[:application_fee] if options[:application_fee]
|
65
|
+
post[:payer_email_message] = options[:payer_email_message] if options[:payer_email_message]
|
66
|
+
post[:payee_email_message] = options[:payee_email_message] if options[:payee_email_message]
|
67
|
+
commit("/checkout/refund", post)
|
68
|
+
end
|
69
|
+
|
70
|
+
def store(creditcard, options = {})
|
71
|
+
requires!(options, :email)
|
72
|
+
|
73
|
+
post = {}
|
74
|
+
post[:client_id] = @options[:client_id]
|
75
|
+
post[:user_name] = "#{creditcard.first_name} #{creditcard.last_name}"
|
76
|
+
post[:email] = options[:email]
|
77
|
+
post[:cc_number] = creditcard.number
|
78
|
+
post[:cvv] = creditcard.verification_value
|
79
|
+
post[:expiration_month] = creditcard.month
|
80
|
+
post[:expiration_year] = creditcard.year
|
81
|
+
post[:original_ip] = options[:ip] if options[:ip]
|
82
|
+
post[:original_device] = options[:device_fingerprint] if options[:device_fingerprint]
|
83
|
+
if(billing_address = (options[:billing_address] || options[:address]))
|
84
|
+
post[:address] = {
|
85
|
+
"address1" => billing_address[:address1],
|
86
|
+
"city" => billing_address[:city],
|
87
|
+
"state" => billing_address[:state],
|
88
|
+
"country" => billing_address[:country]
|
89
|
+
}
|
90
|
+
if(post[:country] == "US")
|
91
|
+
post[:address]["zip"] = billing_address[:zip]
|
92
|
+
else
|
93
|
+
post[:address]["postcode"] = billing_address[:zip]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
commit('/credit_card/create', post)
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
def purchase_with_token(post, money, token, options)
|
102
|
+
add_token(post, token)
|
103
|
+
add_product_data(post, money, options)
|
104
|
+
commit('/checkout/create', post)
|
105
|
+
end
|
106
|
+
|
107
|
+
def add_product_data(post, money, options)
|
108
|
+
post[:account_id] = @options[:account_id]
|
109
|
+
post[:amount] = amount(money)
|
110
|
+
post[:short_description] = (options[:description] || "Purchase")
|
111
|
+
post[:type] = (options[:type] || "GOODS")
|
112
|
+
post[:currency] = (options[:currency] || currency(money))
|
113
|
+
post[:long_description] = options[:long_description] if options[:long_description]
|
114
|
+
post[:payer_email_message] = options[:payer_email_message] if options[:payer_email_message]
|
115
|
+
post[:payee_email_message] = options[:payee_email_message] if options[:payee_email_message]
|
116
|
+
post[:reference_id] = options[:order_id] if options[:order_id]
|
117
|
+
post[:app_fee] = options[:application_fee] if options[:application_fee]
|
118
|
+
post[:fee_payer] = options[:fee_payer] if options[:fee_payer]
|
119
|
+
post[:redirect_uri] = options[:redirect_uri] if options[:redirect_uri]
|
120
|
+
post[:callback_uri] = options[:callback_uri] if options[:callback_uri]
|
121
|
+
post[:fallback_uri] = options[:fallback_uri] if options[:fallback_uri]
|
122
|
+
post[:require_shipping] = options[:require_shipping] if options[:require_shipping]
|
123
|
+
post[:shipping_fee] = options[:shipping_fee] if options[:shipping_fee]
|
124
|
+
post[:charge_tax] = options[:charge_tax] if options[:charge_tax]
|
125
|
+
post[:mode] = options[:mode] if options[:mode]
|
126
|
+
post[:preapproval_id] = options[:preapproval_id] if options[:preapproval_id]
|
127
|
+
post[:prefill_info] = options[:prefill_info] if options[:prefill_info]
|
128
|
+
post[:funding_sources] = options[:funding_sources] if options[:funding_sources]
|
129
|
+
end
|
130
|
+
|
131
|
+
def add_token(post, token)
|
132
|
+
post[:payment_method_id] = token
|
133
|
+
post[:payment_method_type] = "credit_card"
|
134
|
+
end
|
135
|
+
|
136
|
+
def parse(response)
|
137
|
+
JSON.parse(response)
|
138
|
+
end
|
139
|
+
|
140
|
+
def commit(action, params, options={})
|
141
|
+
begin
|
142
|
+
response = parse(ssl_post(
|
143
|
+
((test? ? test_url : live_url) + action),
|
144
|
+
params.to_json,
|
145
|
+
headers
|
146
|
+
))
|
147
|
+
rescue ResponseError => e
|
148
|
+
response = parse(e.response.body)
|
149
|
+
end
|
150
|
+
|
151
|
+
Response.new(
|
152
|
+
success_from(response),
|
153
|
+
message_from(response),
|
154
|
+
response,
|
155
|
+
authorization: authorization_from(response, params),
|
156
|
+
test: test?
|
157
|
+
)
|
158
|
+
end
|
159
|
+
|
160
|
+
def success_from(response)
|
161
|
+
(!response["error"])
|
162
|
+
end
|
163
|
+
|
164
|
+
def message_from(response)
|
165
|
+
(response["error"] ? response["error_description"] : "Success")
|
166
|
+
end
|
167
|
+
|
168
|
+
def authorization_from(response, params)
|
169
|
+
return response["credit_card_id"].to_s if response["credit_card_id"]
|
170
|
+
|
171
|
+
[response["checkout_id"], params[:amount]].join('|')
|
172
|
+
end
|
173
|
+
|
174
|
+
def split_authorization(authorization)
|
175
|
+
auth, original_amount = authorization.to_s.split("|")
|
176
|
+
[auth, original_amount]
|
177
|
+
end
|
178
|
+
|
179
|
+
def headers
|
180
|
+
{
|
181
|
+
"Content-Type" => "application/json",
|
182
|
+
"User-Agent" => "ActiveMerchantBindings/#{ActiveMerchant::VERSION}",
|
183
|
+
"Authorization" => "Bearer #{@options[:access_token]}"
|
184
|
+
}
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
@@ -0,0 +1,421 @@
|
|
1
|
+
require 'base64'
|
2
|
+
|
3
|
+
module ActiveMerchant #:nodoc:
|
4
|
+
module Billing #:nodoc:
|
5
|
+
class WirecardGateway < Gateway
|
6
|
+
self.test_url = 'https://c3-test.wirecard.com/secure/ssl-gateway'
|
7
|
+
self.live_url = 'https://c3.wirecard.com/secure/ssl-gateway'
|
8
|
+
|
9
|
+
# The Namespaces are not really needed, because it just tells the System, that there's actually no namespace used.
|
10
|
+
# It's just specified here for completeness.
|
11
|
+
ENVELOPE_NAMESPACES = {
|
12
|
+
'xmlns:xsi' => 'http://www.w3.org/1999/XMLSchema-instance',
|
13
|
+
'xsi:noNamespaceSchemaLocation' => 'wirecard.xsd'
|
14
|
+
}
|
15
|
+
|
16
|
+
PERMITTED_TRANSACTIONS = %w[ PREAUTHORIZATION CAPTURE PURCHASE ]
|
17
|
+
|
18
|
+
RETURN_CODES = %w[ ACK NOK ]
|
19
|
+
|
20
|
+
# Wirecard only allows phone numbers with a format like this: +xxx(yyy)zzz-zzzz-ppp, where:
|
21
|
+
# xxx = Country code
|
22
|
+
# yyy = Area or city code
|
23
|
+
# zzz-zzzz = Local number
|
24
|
+
# ppp = PBX extension
|
25
|
+
# For example, a typical U.S. or Canadian number would be "+1(202)555-1234-739" indicating PBX extension 739 at phone
|
26
|
+
# number 5551234 within area code 202 (country code 1).
|
27
|
+
VALID_PHONE_FORMAT = /\+\d{1,3}(\(?\d{3}\)?)?\d{3}-\d{4}-\d{3}/
|
28
|
+
|
29
|
+
self.supported_cardtypes = [ :visa, :master, :american_express, :diners_club, :jcb, :switch ]
|
30
|
+
self.supported_countries = %w(AD CY GI IM MT RO CH AT DK GR IT MC SM TR BE EE HU LV NL SK GB BG FI IS LI NO SI VA FR IL LT PL ES CZ DE IE LU PT SE)
|
31
|
+
self.homepage_url = 'http://www.wirecard.com'
|
32
|
+
self.display_name = 'Wirecard'
|
33
|
+
self.default_currency = 'EUR'
|
34
|
+
self.money_format = :cents
|
35
|
+
|
36
|
+
# Public: Create a new Wirecard gateway.
|
37
|
+
#
|
38
|
+
# options - A hash of options:
|
39
|
+
# :login - The username
|
40
|
+
# :password - The password
|
41
|
+
# :signature - The BusinessCaseSignature
|
42
|
+
def initialize(options = {})
|
43
|
+
requires!(options, :login, :password, :signature)
|
44
|
+
super
|
45
|
+
end
|
46
|
+
|
47
|
+
# Authorization - the second parameter may be a CreditCard or
|
48
|
+
# a String which represents a GuWID reference to an earlier
|
49
|
+
# transaction. If a GuWID is given, rather than a CreditCard,
|
50
|
+
# then then the :recurring option will be forced to "Repeated"
|
51
|
+
def authorize(money, payment_method, options = {})
|
52
|
+
if payment_method.respond_to?(:number)
|
53
|
+
options[:credit_card] = payment_method
|
54
|
+
else
|
55
|
+
options[:preauthorization] = payment_method
|
56
|
+
end
|
57
|
+
commit(:preauthorization, money, options)
|
58
|
+
end
|
59
|
+
|
60
|
+
def capture(money, authorization, options = {})
|
61
|
+
options[:preauthorization] = authorization
|
62
|
+
commit(:capture, money, options)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Purchase - the second parameter may be a CreditCard or
|
66
|
+
# a String which represents a GuWID reference to an earlier
|
67
|
+
# transaction. If a GuWID is given, rather than a CreditCard,
|
68
|
+
# then then the :recurring option will be forced to "Repeated"
|
69
|
+
def purchase(money, payment_method, options = {})
|
70
|
+
if payment_method.respond_to?(:number)
|
71
|
+
options[:credit_card] = payment_method
|
72
|
+
else
|
73
|
+
options[:preauthorization] = payment_method
|
74
|
+
end
|
75
|
+
commit(:purchase, money, options)
|
76
|
+
end
|
77
|
+
|
78
|
+
def void(identification, options = {})
|
79
|
+
options[:preauthorization] = identification
|
80
|
+
commit(:reversal, nil, options)
|
81
|
+
end
|
82
|
+
|
83
|
+
def refund(money, identification, options = {})
|
84
|
+
options[:preauthorization] = identification
|
85
|
+
commit(:bookback, money, options)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Store card - Wirecard supports the notion of "Recurring
|
89
|
+
# Transactions" by allowing the merchant to provide a reference
|
90
|
+
# to an earlier transaction (the GuWID) rather than a credit
|
91
|
+
# card. A reusable reference (GuWID) can be obtained by sending
|
92
|
+
# a purchase or authorization transaction with the element
|
93
|
+
# "RECURRING_TRANSACTION/Type" set to "Initial". Subsequent
|
94
|
+
# transactions can then use the GuWID in place of a credit
|
95
|
+
# card by setting "RECURRING_TRANSACTION/Type" to "Repeated".
|
96
|
+
#
|
97
|
+
# This implementation of card store utilizes a Wirecard
|
98
|
+
# "Authorization Check" (a Preauthorization that is automatically
|
99
|
+
# reversed). It defaults to a check amount of "100" (i.e.
|
100
|
+
# $1.00) but this can be overriden (see below).
|
101
|
+
#
|
102
|
+
# IMPORTANT: In order to reuse the stored reference, the
|
103
|
+
# +authorization+ from the response should be saved by
|
104
|
+
# your application code.
|
105
|
+
#
|
106
|
+
# ==== Options specific to +store+
|
107
|
+
#
|
108
|
+
# * <tt>:amount</tt> -- The amount, in cents, that should be
|
109
|
+
# "validated" by the Authorization Check. This amount will
|
110
|
+
# be reserved and then reversed. Default is 100.
|
111
|
+
#
|
112
|
+
# Note: This is not the only way to achieve a card store
|
113
|
+
# operation at Wirecard. Any +purchase+ or +authorize+
|
114
|
+
# can be sent with +options[:recurring] = 'Initial'+ to make
|
115
|
+
# the returned authorization/GuWID usable in later transactions
|
116
|
+
# with +options[:recurring] = 'Repeated'+.
|
117
|
+
def store(creditcard, options = {})
|
118
|
+
options[:credit_card] = creditcard
|
119
|
+
options[:recurring] = 'Initial'
|
120
|
+
money = options.delete(:amount) || 100
|
121
|
+
# Amex does not support authorization_check
|
122
|
+
if creditcard.brand == 'american_express'
|
123
|
+
commit(:preauthorization, money, options)
|
124
|
+
else
|
125
|
+
commit(:authorization_check, money, options)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
private
|
130
|
+
def clean_description(description)
|
131
|
+
description.to_s.slice(0,32).encode("US-ASCII", invalid: :replace, undef: :replace, replace: '?')
|
132
|
+
end
|
133
|
+
|
134
|
+
def prepare_options_hash(options)
|
135
|
+
result = @options.merge(options)
|
136
|
+
setup_address_hash!(result)
|
137
|
+
result
|
138
|
+
end
|
139
|
+
|
140
|
+
# Create all address hash key value pairs so that
|
141
|
+
# it still works if only provided with one or two of them
|
142
|
+
def setup_address_hash!(options)
|
143
|
+
options[:billing_address] = options[:billing_address] || options[:address] || {}
|
144
|
+
options[:shipping_address] = options[:shipping_address] || {}
|
145
|
+
# Include Email in address-hash from options-hash
|
146
|
+
options[:billing_address][:email] = options[:email] if options[:email]
|
147
|
+
end
|
148
|
+
|
149
|
+
# If a GuWID (string-based reference) is passed rather than a
|
150
|
+
# credit card, then the :recurring type needs to be forced to
|
151
|
+
# "Repeated"
|
152
|
+
def setup_recurring_flag(options)
|
153
|
+
options[:recurring] = 'Repeated' if options[:preauthorization].present?
|
154
|
+
end
|
155
|
+
|
156
|
+
# Contact WireCard, make the XML request, and parse the
|
157
|
+
# reply into a Response object
|
158
|
+
def commit(action, money, options)
|
159
|
+
request = build_request(action, money, options)
|
160
|
+
|
161
|
+
headers = { 'Content-Type' => 'text/xml',
|
162
|
+
'Authorization' => encoded_credentials }
|
163
|
+
|
164
|
+
response = parse(ssl_post(test? ? self.test_url : self.live_url, request, headers))
|
165
|
+
# Pending Status also means Acknowledged (as stated in their specification)
|
166
|
+
success = response[:FunctionResult] == "ACK" || response[:FunctionResult] == "PENDING"
|
167
|
+
message = response[:Message]
|
168
|
+
authorization = response[:GuWID]
|
169
|
+
|
170
|
+
Response.new(success, message, response,
|
171
|
+
:test => test?,
|
172
|
+
:authorization => authorization,
|
173
|
+
:avs_result => { :code => avs_code(response, options) },
|
174
|
+
:cvv_result => response[:CVCResponseCode]
|
175
|
+
)
|
176
|
+
rescue ResponseError => e
|
177
|
+
if e.response.code == "401"
|
178
|
+
return Response.new(false, "Invalid Login")
|
179
|
+
else
|
180
|
+
raise
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
# Generates the complete xml-message, that gets sent to the gateway
|
185
|
+
def build_request(action, money, options)
|
186
|
+
options = prepare_options_hash(options)
|
187
|
+
options[:action] = action
|
188
|
+
xml = Builder::XmlMarkup.new :indent => 2
|
189
|
+
xml.instruct!
|
190
|
+
xml.tag! 'WIRECARD_BXML' do
|
191
|
+
xml.tag! 'W_REQUEST' do
|
192
|
+
xml.tag! 'W_JOB' do
|
193
|
+
xml.tag! 'JobID', ''
|
194
|
+
# UserID for this transaction
|
195
|
+
xml.tag! 'BusinessCaseSignature', options[:signature] || options[:login]
|
196
|
+
# Create the whole rest of the message
|
197
|
+
add_transaction_data(xml, money, options)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
xml.target!
|
202
|
+
end
|
203
|
+
|
204
|
+
# Includes the whole transaction data (payment, creditcard, address)
|
205
|
+
def add_transaction_data(xml, money, options)
|
206
|
+
options[:order_id] ||= generate_unique_id
|
207
|
+
|
208
|
+
xml.tag! "FNC_CC_#{options[:action].to_s.upcase}" do
|
209
|
+
xml.tag! 'FunctionID', clean_description(options[:description])
|
210
|
+
xml.tag! 'CC_TRANSACTION' do
|
211
|
+
xml.tag! 'TransactionID', options[:order_id]
|
212
|
+
xml.tag! 'CommerceType', options[:commerce_type] if options[:commerce_type]
|
213
|
+
case options[:action]
|
214
|
+
when :preauthorization, :purchase, :authorization_check
|
215
|
+
setup_recurring_flag(options)
|
216
|
+
add_invoice(xml, money, options)
|
217
|
+
|
218
|
+
if options[:credit_card]
|
219
|
+
add_creditcard(xml, options[:credit_card])
|
220
|
+
else
|
221
|
+
xml.tag! 'GuWID', options[:preauthorization]
|
222
|
+
end
|
223
|
+
|
224
|
+
add_address(xml, options[:billing_address])
|
225
|
+
when :capture, :bookback
|
226
|
+
xml.tag! 'GuWID', options[:preauthorization]
|
227
|
+
add_amount(xml, money)
|
228
|
+
when :reversal
|
229
|
+
xml.tag! 'GuWID', options[:preauthorization]
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
# Includes the payment (amount, currency, country) to the transaction-xml
|
236
|
+
def add_invoice(xml, money, options)
|
237
|
+
add_amount(xml, money)
|
238
|
+
xml.tag! 'Currency', options[:currency] || currency(money)
|
239
|
+
xml.tag! 'CountryCode', options[:billing_address][:country]
|
240
|
+
xml.tag! 'RECURRING_TRANSACTION' do
|
241
|
+
xml.tag! 'Type', options[:recurring] || 'Single'
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
# Include the amount in the transaction-xml
|
246
|
+
def add_amount(xml, money)
|
247
|
+
xml.tag! 'Amount', amount(money)
|
248
|
+
end
|
249
|
+
|
250
|
+
# Includes the credit-card data to the transaction-xml
|
251
|
+
def add_creditcard(xml, creditcard)
|
252
|
+
raise "Creditcard must be supplied!" if creditcard.nil?
|
253
|
+
xml.tag! 'CREDIT_CARD_DATA' do
|
254
|
+
xml.tag! 'CreditCardNumber', creditcard.number
|
255
|
+
xml.tag! 'CVC2', creditcard.verification_value
|
256
|
+
xml.tag! 'ExpirationYear', creditcard.year
|
257
|
+
xml.tag! 'ExpirationMonth', format(creditcard.month, :two_digits)
|
258
|
+
xml.tag! 'CardHolderName', [creditcard.first_name, creditcard.last_name].join(' ')
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
# Includes the IP address of the customer to the transaction-xml
|
263
|
+
def add_customer_data(xml, options)
|
264
|
+
return unless options[:ip]
|
265
|
+
xml.tag! 'CONTACT_DATA' do
|
266
|
+
xml.tag! 'IPAddress', options[:ip]
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
# Includes the address to the transaction-xml
|
271
|
+
def add_address(xml, address)
|
272
|
+
return if address.nil?
|
273
|
+
xml.tag! 'CORPTRUSTCENTER_DATA' do
|
274
|
+
xml.tag! 'ADDRESS' do
|
275
|
+
xml.tag! 'Address1', address[:address1]
|
276
|
+
xml.tag! 'Address2', address[:address2] if address[:address2]
|
277
|
+
xml.tag! 'City', address[:city]
|
278
|
+
xml.tag! 'ZipCode', address[:zip]
|
279
|
+
|
280
|
+
if address[:state] =~ /[A-Za-z]{2}/ && address[:country] =~ /^(us|ca)$/i
|
281
|
+
xml.tag! 'State', address[:state].upcase
|
282
|
+
end
|
283
|
+
|
284
|
+
xml.tag! 'Country', address[:country]
|
285
|
+
xml.tag! 'Phone', address[:phone] if address[:phone] =~ VALID_PHONE_FORMAT
|
286
|
+
xml.tag! 'Email', address[:email]
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
# Read the XML message from the gateway and check if it was successful,
|
292
|
+
# and also extract required return values from the response.
|
293
|
+
def parse(xml)
|
294
|
+
basepath = '/WIRECARD_BXML/W_RESPONSE'
|
295
|
+
response = {}
|
296
|
+
|
297
|
+
xml = REXML::Document.new(xml)
|
298
|
+
if root = REXML::XPath.first(xml, "#{basepath}/W_JOB")
|
299
|
+
parse_response(response, root)
|
300
|
+
elsif root = REXML::XPath.first(xml, "//ERROR")
|
301
|
+
parse_error_only_response(response, root)
|
302
|
+
else
|
303
|
+
response[:Message] = "No valid XML response message received. \
|
304
|
+
Propably wrong credentials supplied with HTTP header."
|
305
|
+
end
|
306
|
+
|
307
|
+
response
|
308
|
+
end
|
309
|
+
|
310
|
+
def parse_error_only_response(response, root)
|
311
|
+
error_code = REXML::XPath.first(root, "Number")
|
312
|
+
response[:ErrorCode] = error_code.text if error_code
|
313
|
+
response[:Message] = parse_error(root)
|
314
|
+
end
|
315
|
+
|
316
|
+
# Parse the <ProcessingStatus> Element which contains all important information
|
317
|
+
def parse_response(response, root)
|
318
|
+
status = nil
|
319
|
+
|
320
|
+
root.elements.to_a.each do |node|
|
321
|
+
if node.name =~ /FNC_CC_/
|
322
|
+
status = REXML::XPath.first(node, "CC_TRANSACTION/PROCESSING_STATUS")
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
message = ""
|
327
|
+
if status
|
328
|
+
if info = status.elements['Info']
|
329
|
+
message << info.text
|
330
|
+
end
|
331
|
+
|
332
|
+
status.elements.to_a.each do |node|
|
333
|
+
if (node.elements.size == 0)
|
334
|
+
response[node.name.to_sym] = (node.text || '').strip
|
335
|
+
else
|
336
|
+
node.elements.each do |childnode|
|
337
|
+
name = "#{node.name}_#{childnode.name}"
|
338
|
+
response[name.to_sym] = (childnode.text || '').strip
|
339
|
+
end
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
error_code = REXML::XPath.first(status, "ERROR/Number")
|
344
|
+
response['ErrorCode'] = error_code.text if error_code
|
345
|
+
end
|
346
|
+
|
347
|
+
parse_error(root, message)
|
348
|
+
response[:Message] = message
|
349
|
+
end
|
350
|
+
|
351
|
+
# Parse a generic error response from the gateway
|
352
|
+
def parse_error(root, message = "")
|
353
|
+
# Get errors if available and append them to the message
|
354
|
+
errors = errors_to_string(root)
|
355
|
+
unless errors.strip.blank?
|
356
|
+
message << ' - ' unless message.strip.blank?
|
357
|
+
message << errors
|
358
|
+
end
|
359
|
+
message
|
360
|
+
end
|
361
|
+
|
362
|
+
# Parses all <ERROR> elements in the response and converts the information
|
363
|
+
# to a single string
|
364
|
+
def errors_to_string(root)
|
365
|
+
# Get context error messages (can be 0..*)
|
366
|
+
errors = []
|
367
|
+
REXML::XPath.each(root, "//ERROR") do |error_elem|
|
368
|
+
error = {}
|
369
|
+
error[:Advice] = []
|
370
|
+
error[:Message] = error_elem.elements['Message'].text
|
371
|
+
error_elem.elements.each('Advice') do |advice|
|
372
|
+
error[:Advice] << advice.text
|
373
|
+
end
|
374
|
+
errors << error
|
375
|
+
end
|
376
|
+
# Convert all messages to a single string
|
377
|
+
string = ''
|
378
|
+
errors.each do |error|
|
379
|
+
string << error[:Message] if error[:Message]
|
380
|
+
error[:Advice].each_with_index do |advice, index|
|
381
|
+
string << ' (' if index == 0
|
382
|
+
string << "#{index+1}. #{advice}"
|
383
|
+
string << ' and ' if index < error[:Advice].size - 1
|
384
|
+
string << ')' if index == error[:Advice].size - 1
|
385
|
+
end
|
386
|
+
end
|
387
|
+
string
|
388
|
+
end
|
389
|
+
|
390
|
+
# Amex have different AVS response codes
|
391
|
+
AMEX_TRANSLATED_AVS_CODES = {
|
392
|
+
"A" => "B", # CSC and Address Matched
|
393
|
+
"F" => "D", # All Data Matched
|
394
|
+
"N" => "I", # CSC Match
|
395
|
+
"U" => "U", # Data Not Checked
|
396
|
+
"Y" => "D", # All Data Matched
|
397
|
+
"Z" => "P", # CSC and Postcode Matched
|
398
|
+
"F" => "D" # Street address and zip code match
|
399
|
+
}
|
400
|
+
|
401
|
+
# Amex have different AVS response codes to visa etc
|
402
|
+
def avs_code(response, options)
|
403
|
+
if response.has_key?(:AVS_ProviderResultCode)
|
404
|
+
if options[:credit_card].present? && ActiveMerchant::Billing::CreditCard.brand?(options[:credit_card].number) == "american_express"
|
405
|
+
AMEX_TRANSLATED_AVS_CODES[response[:AVS_ProviderResultCode]]
|
406
|
+
else
|
407
|
+
response[:AVS_ProviderResultCode]
|
408
|
+
end
|
409
|
+
end
|
410
|
+
end
|
411
|
+
|
412
|
+
# Encode login and password in Base64 to supply as HTTP header
|
413
|
+
# (for http basic authentication)
|
414
|
+
def encoded_credentials
|
415
|
+
credentials = [@options[:login], @options[:password]].join(':')
|
416
|
+
"Basic " << Base64.encode64(credentials).strip
|
417
|
+
end
|
418
|
+
end
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|