activemerchant 1.2.1 → 1.3.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.tar.gz.sig +0 -0
- data/CHANGELOG +310 -294
- data/CONTRIBUTERS +13 -0
- data/README +55 -31
- data/Rakefile +21 -13
- data/lib/active_merchant.rb +7 -0
- data/lib/active_merchant/billing/avs_result.rb +95 -0
- data/lib/active_merchant/billing/base.rb +8 -3
- data/lib/active_merchant/billing/check.rb +61 -0
- data/lib/active_merchant/billing/credit_card.rb +104 -80
- data/lib/active_merchant/billing/credit_card_formatting.rb +11 -8
- data/lib/active_merchant/billing/credit_card_methods.rb +76 -32
- data/lib/active_merchant/billing/cvv_result.rb +38 -0
- data/lib/active_merchant/billing/expiry_date.rb +28 -0
- data/lib/active_merchant/billing/gateway.rb +47 -111
- data/lib/active_merchant/billing/gateways/authorize_net.rb +508 -121
- data/lib/active_merchant/billing/gateways/bogus.rb +26 -32
- data/lib/active_merchant/billing/gateways/brain_tree.rb +82 -70
- data/lib/active_merchant/billing/gateways/card_stream.rb +43 -15
- data/lib/active_merchant/billing/gateways/cyber_source.rb +9 -29
- data/lib/active_merchant/billing/gateways/data_cash.rb +18 -38
- data/lib/active_merchant/billing/gateways/efsnet.rb +23 -50
- data/lib/active_merchant/billing/gateways/eway.rb +8 -19
- data/lib/active_merchant/billing/gateways/exact.rb +17 -25
- data/lib/active_merchant/billing/gateways/linkpoint.rb +18 -25
- data/lib/active_merchant/billing/gateways/moneris.rb +9 -39
- data/lib/active_merchant/billing/gateways/net_registry.rb +113 -182
- data/lib/active_merchant/billing/gateways/netbilling.rb +168 -0
- data/lib/active_merchant/billing/gateways/pay_junction.rb +52 -73
- data/lib/active_merchant/billing/gateways/pay_secure.rb +120 -0
- data/lib/active_merchant/billing/gateways/payflow.rb +13 -14
- data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +55 -37
- data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +4 -0
- data/lib/active_merchant/billing/gateways/payflow_express.rb +2 -4
- data/lib/active_merchant/billing/gateways/payment_express.rb +11 -30
- data/lib/active_merchant/billing/gateways/paypal.rb +3 -14
- data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +36 -16
- data/lib/active_merchant/billing/gateways/paypal_express.rb +1 -2
- data/lib/active_merchant/billing/gateways/plugnpay.rb +7 -15
- data/lib/active_merchant/billing/gateways/protx.rb +24 -25
- data/lib/active_merchant/billing/gateways/psigate.rb +34 -71
- data/lib/active_merchant/billing/gateways/psl_card.rb +24 -19
- data/lib/active_merchant/billing/gateways/quickpay.rb +10 -24
- data/lib/active_merchant/billing/gateways/realex.rb +7 -19
- data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +113 -0
- data/lib/active_merchant/billing/gateways/skip_jack.rb +437 -0
- data/lib/active_merchant/billing/gateways/trans_first.rb +5 -14
- data/lib/active_merchant/billing/gateways/trust_commerce.rb +100 -39
- data/lib/active_merchant/billing/gateways/usa_epay.rb +60 -55
- data/lib/active_merchant/billing/gateways/verifi.rb +32 -39
- data/lib/active_merchant/billing/gateways/viaklix.rb +31 -37
- data/lib/active_merchant/billing/integrations.rb +2 -0
- data/lib/active_merchant/billing/integrations/bogus.rb +5 -0
- data/lib/active_merchant/billing/integrations/bogus/return.rb +10 -0
- data/lib/active_merchant/billing/integrations/chronopay.rb +5 -0
- data/lib/active_merchant/billing/integrations/chronopay/return.rb +10 -0
- data/lib/active_merchant/billing/integrations/gestpay.rb +5 -0
- data/lib/active_merchant/billing/integrations/gestpay/return.rb +10 -0
- data/lib/active_merchant/billing/integrations/hi_trust.rb +26 -0
- data/lib/active_merchant/billing/integrations/hi_trust/helper.rb +58 -0
- data/lib/active_merchant/billing/integrations/hi_trust/notification.rb +57 -0
- data/lib/active_merchant/billing/integrations/hi_trust/return.rb +67 -0
- data/lib/active_merchant/billing/integrations/nochex.rb +5 -0
- data/lib/active_merchant/billing/integrations/nochex/return.rb +10 -0
- data/lib/active_merchant/billing/integrations/paypal.rb +5 -0
- data/lib/active_merchant/billing/integrations/paypal/return.rb +10 -0
- data/lib/active_merchant/billing/integrations/return.rb +35 -0
- data/lib/active_merchant/billing/integrations/two_checkout.rb +5 -0
- data/lib/active_merchant/billing/integrations/two_checkout/return.rb +17 -0
- data/lib/active_merchant/billing/response.rb +12 -8
- data/lib/active_merchant/lib/posts_data.rb +39 -7
- data/lib/active_merchant/lib/requires_parameters.rb +2 -3
- data/lib/active_merchant/lib/utils.rb +18 -0
- data/lib/active_merchant/lib/validateable.rb +3 -3
- data/lib/support/gateway_support.rb +22 -9
- data/script/destroy +14 -0
- data/script/generate +7 -7
- data/test/fixtures.yml +25 -3
- data/test/remote/gateways/remote_authorize_net_test.rb +145 -0
- data/test/remote/gateways/remote_brain_tree_test.rb +118 -0
- data/test/{remote_tests → remote/gateways}/remote_card_stream_test.rb +56 -68
- data/test/{remote_tests → remote/gateways}/remote_cyber_source_test.rb +21 -32
- data/test/{remote_tests → remote/gateways}/remote_data_cash_test.rb +2 -2
- data/test/{remote_tests → remote/gateways}/remote_efsnet_test.rb +22 -34
- data/test/{remote_tests → remote/gateways}/remote_eway_test.rb +18 -15
- data/test/{remote_tests → remote/gateways}/remote_exact_test.rb +20 -19
- data/test/{remote_tests → remote/gateways}/remote_linkpoint_test.rb +31 -63
- data/test/remote/gateways/remote_moneris_test.rb +82 -0
- data/test/{remote_tests → remote/gateways}/remote_net_registry_test.rb +19 -54
- data/test/remote/gateways/remote_netbilling_test.rb +70 -0
- data/test/{remote_tests → remote/gateways}/remote_pay_junction_test.rb +41 -60
- data/test/remote/gateways/remote_pay_secure_test.rb +39 -0
- data/test/{remote_tests → remote/gateways}/remote_payflow_express_test.rb +2 -2
- data/test/{remote_tests → remote/gateways}/remote_payflow_test.rb +34 -38
- data/test/{remote_tests → remote/gateways}/remote_payflow_uk_test.rb +13 -12
- data/test/{remote_tests → remote/gateways}/remote_payment_express_test.rb +26 -36
- data/test/{remote_tests → remote/gateways}/remote_paypal_express_test.rb +3 -3
- data/test/{remote_tests → remote/gateways}/remote_paypal_test.rb +25 -21
- data/test/{remote_tests → remote/gateways}/remote_plugnpay_test.rb +18 -16
- data/test/{remote_tests → remote/gateways}/remote_protx_test.rb +33 -33
- data/test/remote/gateways/remote_psigate_test.rb +50 -0
- data/test/{remote_tests → remote/gateways}/remote_psl_card_test.rb +27 -26
- data/test/{remote_tests → remote/gateways}/remote_quickpay_test.rb +48 -48
- data/test/{remote_tests → remote/gateways}/remote_realex_test.rb +30 -33
- data/test/remote/gateways/remote_secure_pay_tech_test.rb +37 -0
- data/test/remote/gateways/remote_secure_pay_test.rb +28 -0
- data/test/remote/gateways/remote_skipjack_test.rb +105 -0
- data/test/{remote_tests → remote/gateways}/remote_trans_first_test.rb +7 -10
- data/test/remote/gateways/remote_trust_commerce_test.rb +152 -0
- data/test/{remote_tests → remote/gateways}/remote_usa_epay_test.rb +11 -22
- data/test/{remote_tests → remote/gateways}/remote_verifi_test.rb +27 -27
- data/test/{remote_tests → remote/gateways}/remote_viaklix_test.rb +8 -18
- data/test/{remote_tests → remote/integrations}/remote_gestpay_integration_test.rb +1 -1
- data/test/{remote_tests → remote/integrations}/remote_paypal_integration_test.rb +1 -1
- data/test/test_helper.rb +102 -61
- data/test/unit/avs_result_test.rb +59 -0
- data/test/unit/base_test.rb +33 -39
- data/test/unit/check_test.rb +76 -0
- data/test/unit/credit_card_formatting_test.rb +10 -15
- data/test/unit/credit_card_methods_test.rb +132 -17
- data/test/unit/credit_card_test.rb +157 -228
- data/test/unit/cvv_result_test.rb +33 -0
- data/test/unit/expiry_date_test.rb +21 -0
- data/test/unit/gateways/authorize_net_test.rb +180 -40
- data/test/unit/gateways/bogus_test.rb +2 -3
- data/test/unit/gateways/brain_tree_test.rb +63 -29
- data/test/unit/gateways/card_stream_test.rb +59 -6
- data/test/unit/gateways/cyber_source_test.rb +59 -40
- data/test/unit/gateways/data_cash_test.rb +82 -1
- data/test/unit/gateways/efsnet_test.rb +97 -44
- data/test/unit/gateways/eway_test.rb +55 -42
- data/test/unit/gateways/exact_test.rb +93 -55
- data/test/unit/gateways/gateway_test.rb +7 -0
- data/test/unit/gateways/linkpoint_test.rb +60 -58
- data/test/unit/gateways/moneris_test.rb +67 -76
- data/test/unit/gateways/net_registry_test.rb +351 -419
- data/test/unit/gateways/netbilling_test.rb +54 -0
- data/test/unit/gateways/pay_junction_test.rb +108 -46
- data/test/unit/gateways/pay_secure_test.rb +71 -0
- data/test/unit/gateways/payflow_express_test.rb +0 -8
- data/test/unit/gateways/payflow_test.rb +136 -65
- data/test/unit/gateways/payflow_uk_test.rb +0 -38
- data/test/unit/gateways/payment_express_test.rb +31 -51
- data/test/unit/gateways/paypal_express_test.rb +8 -2
- data/test/unit/gateways/paypal_test.rb +213 -54
- data/test/unit/gateways/plugnpay_test.rb +39 -32
- data/test/unit/gateways/protx_test.rb +45 -33
- data/test/unit/gateways/psigate_test.rb +146 -87
- data/test/unit/gateways/psl_card_test.rb +37 -24
- data/test/unit/gateways/quickpay_test.rb +33 -46
- data/test/unit/gateways/realex_test.rb +32 -31
- data/test/unit/gateways/secure_pay_tech_test.rb +44 -0
- data/test/unit/gateways/secure_pay_test.rb +35 -26
- data/test/unit/gateways/skip_jack_test.rb +125 -0
- data/test/unit/gateways/trans_first_test.rb +24 -37
- data/test/unit/gateways/trust_commerce_test.rb +47 -26
- data/test/unit/gateways/usa_epay_test.rb +52 -41
- data/test/unit/gateways/verifi_test.rb +41 -35
- data/test/unit/gateways/viaklix_test.rb +38 -32
- data/test/unit/generators/test_gateway_generator.rb +46 -0
- data/test/unit/generators/test_generator_helper.rb +20 -0
- data/test/unit/generators/test_integration_generator.rb +53 -0
- data/test/unit/integrations/action_view_helper_test.rb +7 -14
- data/test/unit/integrations/bogus_module_test.rb +4 -0
- data/test/unit/integrations/chronopay_module_test.rb +4 -0
- data/test/unit/integrations/gestpay_module_test.rb +4 -0
- data/test/unit/integrations/helpers/hi_trust_helper_test.rb +16 -0
- data/test/unit/integrations/hi_trust_module_test.rb +13 -0
- data/test/unit/integrations/nochex_module_test.rb +4 -0
- data/test/unit/integrations/notifications/hi_trust_notification_test.rb +38 -0
- data/test/unit/integrations/paypal_module_test.rb +4 -0
- data/test/unit/integrations/returns/chronopay_return_test.rb +11 -0
- data/test/unit/integrations/returns/gestpay_return_test.rb +10 -0
- data/test/unit/integrations/returns/hi_trust_return_test.rb +24 -0
- data/test/unit/integrations/returns/nochex_return_test.rb +10 -0
- data/test/unit/integrations/returns/paypal_return_test.rb +10 -0
- data/test/unit/integrations/returns/return_test.rb +11 -0
- data/test/unit/integrations/returns/two_checkout_return_test.rb +24 -0
- data/test/unit/integrations/two_checkout_module_test.rb +4 -0
- data/test/unit/posts_data_test.rb +86 -0
- data/test/unit/response_test.rb +15 -1
- data/test/unit/utils_test.rb +7 -0
- data/test/unit/validateable_test.rb +10 -6
- metadata +180 -142
- metadata.gz.sig +0 -0
- data/lib/active_merchant/billing/gateways/paypal/api_cert_chain.crt +0 -35
- data/script/generator/base.rb +0 -45
- data/script/generator/generator.rb +0 -24
- data/script/generator/generators/gateway/gateway_generator.rb +0 -14
- data/script/generator/generators/gateway/templates/gateway.rb +0 -73
- data/script/generator/generators/gateway/templates/gateway_test.rb +0 -41
- data/script/generator/generators/gateway/templates/remote_gateway_test.rb +0 -56
- data/script/generator/generators/integration/integration_generator.rb +0 -25
- data/script/generator/generators/integration/templates/helper.rb +0 -34
- data/script/generator/generators/integration/templates/helper_test.rb +0 -54
- data/script/generator/generators/integration/templates/integration.rb +0 -18
- data/script/generator/generators/integration/templates/module_test.rb +0 -9
- data/script/generator/generators/integration/templates/notification.rb +0 -100
- data/script/generator/generators/integration/templates/notification_test.rb +0 -41
- data/script/generator/manifest.rb +0 -20
- data/test/remote_tests/remote_authorize_net_test.rb +0 -113
- data/test/remote_tests/remote_brain_tree_test.rb +0 -78
- data/test/remote_tests/remote_moneris_test.rb +0 -110
- data/test/remote_tests/remote_psigate_test.rb +0 -87
- data/test/remote_tests/remote_secure_pay_test.rb +0 -36
- data/test/remote_tests/remote_trust_commerce_test.rb +0 -136
|
@@ -62,8 +62,8 @@ module ActiveMerchant #:nodoc:
|
|
|
62
62
|
commit(request, :recurring)
|
|
63
63
|
end
|
|
64
64
|
|
|
65
|
-
def recurring_inquiry(profile_id)
|
|
66
|
-
request = build_recurring_request(:inquiry, nil, :profile_id => profile_id)
|
|
65
|
+
def recurring_inquiry(profile_id, options = {})
|
|
66
|
+
request = build_recurring_request(:inquiry, nil, options.update( :profile_id => profile_id ))
|
|
67
67
|
commit(request, :recurring)
|
|
68
68
|
end
|
|
69
69
|
|
|
@@ -81,7 +81,7 @@ module ActiveMerchant #:nodoc:
|
|
|
81
81
|
end
|
|
82
82
|
|
|
83
83
|
def build_reference_sale_or_authorization_request(action, money, reference, options)
|
|
84
|
-
xml = Builder::XmlMarkup.new
|
|
84
|
+
xml = Builder::XmlMarkup.new
|
|
85
85
|
xml.tag! TRANSACTIONS[action] do
|
|
86
86
|
xml.tag! 'PayData' do
|
|
87
87
|
xml.tag! 'Invoice' do
|
|
@@ -98,19 +98,17 @@ module ActiveMerchant #:nodoc:
|
|
|
98
98
|
end
|
|
99
99
|
|
|
100
100
|
def build_credit_card_request(action, money, credit_card, options)
|
|
101
|
-
xml = Builder::XmlMarkup.new
|
|
101
|
+
xml = Builder::XmlMarkup.new
|
|
102
102
|
xml.tag! TRANSACTIONS[action] do
|
|
103
103
|
xml.tag! 'PayData' do
|
|
104
104
|
xml.tag! 'Invoice' do
|
|
105
105
|
xml.tag! 'CustIP', options[:ip] unless options[:ip].blank?
|
|
106
|
-
xml.tag! 'InvNum', options[:order_id] unless options[:order_id].blank?
|
|
106
|
+
xml.tag! 'InvNum', options[:order_id].to_s.gsub(/[^\w.]/, '') unless options[:order_id].blank?
|
|
107
107
|
xml.tag! 'Description', options[:description] unless options[:description].blank?
|
|
108
108
|
|
|
109
109
|
billing_address = options[:billing_address] || options[:address]
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
add_address(xml, 'BillTo', billing_address, options)
|
|
113
|
-
add_address(xml, 'ShipTo', shipping_address, options)
|
|
110
|
+
add_address(xml, 'BillTo', billing_address, options) if billing_address
|
|
111
|
+
add_address(xml, 'ShipTo', options[:shipping_address], options) if options[:shipping_address]
|
|
114
112
|
|
|
115
113
|
xml.tag! 'TotalAmt', amount(money), 'Currency' => options[:currency] || currency(money)
|
|
116
114
|
end
|
|
@@ -163,7 +161,7 @@ module ActiveMerchant #:nodoc:
|
|
|
163
161
|
raise StandardError, "Invalid Recurring Profile Action: #{action}"
|
|
164
162
|
end
|
|
165
163
|
|
|
166
|
-
xml = Builder::XmlMarkup.new
|
|
164
|
+
xml = Builder::XmlMarkup.new
|
|
167
165
|
xml.tag! 'RecurringProfiles' do
|
|
168
166
|
xml.tag! 'RecurringProfile' do
|
|
169
167
|
xml.tag! action.to_s.capitalize do
|
|
@@ -188,10 +186,8 @@ module ActiveMerchant #:nodoc:
|
|
|
188
186
|
xml.tag! 'EMail', options[:email] unless options[:email].nil?
|
|
189
187
|
|
|
190
188
|
billing_address = options[:billing_address] || options[:address]
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
add_address(xml, 'BillTo', billing_address, options)
|
|
194
|
-
add_address(xml, 'ShipTo', shipping_address, options)
|
|
189
|
+
add_address(xml, 'BillTo', billing_address, options) if billing_address
|
|
190
|
+
add_address(xml, 'ShipTo', options[:shipping_address], options) if options[:shipping_address]
|
|
195
191
|
end
|
|
196
192
|
xml.tag! 'Tender' do
|
|
197
193
|
yield xml
|
|
@@ -200,6 +196,9 @@ module ActiveMerchant #:nodoc:
|
|
|
200
196
|
if action != :add
|
|
201
197
|
xml.tag! "ProfileID", options[:profile_id]
|
|
202
198
|
end
|
|
199
|
+
if action == :inquiry
|
|
200
|
+
xml.tag! "PaymentHistory", ( options[:history] ? 'Y' : 'N' )
|
|
201
|
+
end
|
|
203
202
|
end
|
|
204
203
|
end
|
|
205
204
|
end
|
|
@@ -4,23 +4,32 @@ module ActiveMerchant #:nodoc:
|
|
|
4
4
|
def self.included(base)
|
|
5
5
|
base.default_currency = 'USD'
|
|
6
6
|
|
|
7
|
-
# The
|
|
8
|
-
#
|
|
9
|
-
# use the certification_id that has been configured here, or generate your own
|
|
7
|
+
# The certification id requirement has been removed by Payflow
|
|
8
|
+
# This is no longer being sent in the requests to the gateway
|
|
10
9
|
base.class_inheritable_accessor :certification_id
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
|
|
13
11
|
base.class_inheritable_accessor :partner
|
|
14
12
|
|
|
15
13
|
# Set the default partner to PayPal
|
|
16
14
|
base.partner = 'PayPal'
|
|
17
15
|
|
|
18
16
|
base.supported_countries = ['US', 'CA', 'SG', 'AU']
|
|
17
|
+
|
|
18
|
+
base.class_inheritable_accessor :timeout
|
|
19
|
+
base.timeout = 60
|
|
20
|
+
|
|
21
|
+
# Enable safe retry of failed connections
|
|
22
|
+
# Payflow is safe to retry because retried transactions use the same
|
|
23
|
+
# X-VPS-Request-ID header. If a transaction is detected as a duplicate
|
|
24
|
+
# only the original transaction data will be used by Payflow, and the
|
|
25
|
+
# subsequent Responses will have a :duplicate parameter set in the params
|
|
26
|
+
# hash.
|
|
27
|
+
base.retry_safe = true
|
|
19
28
|
end
|
|
20
29
|
|
|
21
30
|
XMLNS = 'http://www.paypal.com/XMLPay'
|
|
22
|
-
TEST_URL = 'https://pilot-payflowpro.verisign.com
|
|
23
|
-
LIVE_URL = 'https://payflowpro.verisign.com
|
|
31
|
+
TEST_URL = 'https://pilot-payflowpro.verisign.com'
|
|
32
|
+
LIVE_URL = 'https://payflowpro.verisign.com'
|
|
24
33
|
|
|
25
34
|
CARD_MAPPING = {
|
|
26
35
|
:visa => 'Visa',
|
|
@@ -40,6 +49,13 @@ module ActiveMerchant #:nodoc:
|
|
|
40
49
|
:void => "Void",
|
|
41
50
|
:credit => "Credit"
|
|
42
51
|
}
|
|
52
|
+
|
|
53
|
+
CVV_CODE = {
|
|
54
|
+
'Match' => 'M',
|
|
55
|
+
'No Match' => 'N',
|
|
56
|
+
'Service Not Available' => 'U',
|
|
57
|
+
'Service not Requested' => 'P'
|
|
58
|
+
}
|
|
43
59
|
|
|
44
60
|
def initialize(options = {})
|
|
45
61
|
requires!(options, :login, :password)
|
|
@@ -52,7 +68,7 @@ module ActiveMerchant #:nodoc:
|
|
|
52
68
|
end
|
|
53
69
|
|
|
54
70
|
def test?
|
|
55
|
-
@options[:test] ||
|
|
71
|
+
@options[:test] || super
|
|
56
72
|
end
|
|
57
73
|
|
|
58
74
|
def capture(money, authorization, options = {})
|
|
@@ -67,7 +83,7 @@ module ActiveMerchant #:nodoc:
|
|
|
67
83
|
|
|
68
84
|
private
|
|
69
85
|
def build_request(body, request_type = nil)
|
|
70
|
-
xml = Builder::XmlMarkup.new
|
|
86
|
+
xml = Builder::XmlMarkup.new
|
|
71
87
|
xml.instruct!
|
|
72
88
|
xml.tag! 'XMLPayRequest', 'Timeout' => 30, 'version' => "2.1", "xmlns" => XMLNS do
|
|
73
89
|
xml.tag! 'RequestData' do
|
|
@@ -95,7 +111,7 @@ module ActiveMerchant #:nodoc:
|
|
|
95
111
|
end
|
|
96
112
|
|
|
97
113
|
def build_reference_request(action, money, authorization, options)
|
|
98
|
-
xml = Builder::XmlMarkup.new
|
|
114
|
+
xml = Builder::XmlMarkup.new
|
|
99
115
|
xml.tag! TRANSACTIONS[action] do
|
|
100
116
|
xml.tag! 'PNRef', authorization
|
|
101
117
|
|
|
@@ -113,8 +129,10 @@ module ActiveMerchant #:nodoc:
|
|
|
113
129
|
return if address.nil?
|
|
114
130
|
xml.tag! tag do
|
|
115
131
|
xml.tag! 'Name', address[:name] unless options[:name].blank?
|
|
116
|
-
xml.tag! '
|
|
132
|
+
xml.tag! 'EMail', options[:email] unless options[:email].blank?
|
|
117
133
|
xml.tag! 'Phone', address[:phone] unless address[:phone].blank?
|
|
134
|
+
xml.tag! 'CustCode', options[:customer] if !options[:customer].blank? && tag == 'BillTo'
|
|
135
|
+
|
|
118
136
|
xml.tag! 'Address' do
|
|
119
137
|
xml.tag! 'Street', address[:address1] unless address[:address1].blank?
|
|
120
138
|
xml.tag! 'City', address[:city] unless address[:city].blank?
|
|
@@ -130,7 +148,10 @@ module ActiveMerchant #:nodoc:
|
|
|
130
148
|
xml = REXML::Document.new(data)
|
|
131
149
|
root = REXML::XPath.first(xml, "//ResponseData")
|
|
132
150
|
|
|
133
|
-
|
|
151
|
+
# REXML::XPath in Ruby 1.8.6 is now unable to match nodes based on their attributes
|
|
152
|
+
tx_result = REXML::XPath.first(root, "//TransactionResult")
|
|
153
|
+
|
|
154
|
+
if tx_result && tx_result.attributes['Duplicate'] == "true"
|
|
134
155
|
response[:duplicate] = true
|
|
135
156
|
end
|
|
136
157
|
|
|
@@ -142,12 +163,24 @@ module ActiveMerchant #:nodoc:
|
|
|
142
163
|
end
|
|
143
164
|
|
|
144
165
|
def parse_element(response, node)
|
|
145
|
-
|
|
166
|
+
node_name = node.name.underscore.to_sym
|
|
167
|
+
case
|
|
168
|
+
when node_name == :rp_payment_result
|
|
169
|
+
# Since we'll have multiple history items, we can't just flatten everything
|
|
170
|
+
# down as we do everywhere else. RPPaymentResult elements are not contained
|
|
171
|
+
# in an RPPaymentResults element so we'll come here multiple times
|
|
172
|
+
response[node_name] ||= []
|
|
173
|
+
response[node_name] << ( payment_result_response = {} )
|
|
174
|
+
node.elements.each{ |e| parse_element(payment_result_response, e) }
|
|
175
|
+
when node.has_elements?
|
|
146
176
|
node.elements.each{|e| parse_element(response, e) }
|
|
147
|
-
|
|
177
|
+
when node_name.to_s =~ /amt$/
|
|
178
|
+
# *Amt elements don't put the value in the #text - instead they use a Currency attribute
|
|
179
|
+
response[node_name] = node.attributes['Currency']
|
|
180
|
+
when node_name == :ext_data
|
|
148
181
|
response[node.attributes['Name'].underscore.to_sym] = node.attributes['Value']
|
|
149
182
|
else
|
|
150
|
-
response[
|
|
183
|
+
response[node_name] = node.text
|
|
151
184
|
end
|
|
152
185
|
end
|
|
153
186
|
|
|
@@ -155,11 +188,10 @@ module ActiveMerchant #:nodoc:
|
|
|
155
188
|
{
|
|
156
189
|
"Content-Type" => "text/xml",
|
|
157
190
|
"Content-Length" => content_length.to_s,
|
|
158
|
-
"X-VPS-Timeout" =>
|
|
159
|
-
"X-VPS-VIT-Client-Certification-Id" => @options[:certification_id].to_s,
|
|
191
|
+
"X-VPS-Timeout" => timeout.to_s,
|
|
160
192
|
"X-VPS-VIT-Integration-Product" => "ActiveMerchant",
|
|
161
193
|
"X-VPS-VIT-Runtime-Version" => RUBY_VERSION,
|
|
162
|
-
"X-VPS-Request-ID" => generate_unique_id
|
|
194
|
+
"X-VPS-Request-ID" => Utils.generate_unique_id
|
|
163
195
|
}
|
|
164
196
|
end
|
|
165
197
|
|
|
@@ -167,29 +199,15 @@ module ActiveMerchant #:nodoc:
|
|
|
167
199
|
request = build_request(request_body, request_type)
|
|
168
200
|
headers = build_headers(request.size)
|
|
169
201
|
|
|
170
|
-
|
|
171
|
-
return result
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
url = test? ? TEST_URL : LIVE_URL
|
|
175
|
-
data = ssl_post(url, request, headers)
|
|
176
|
-
|
|
177
|
-
@response = parse(data)
|
|
202
|
+
response = parse(ssl_post(test? ? TEST_URL : LIVE_URL, request, headers))
|
|
178
203
|
|
|
179
|
-
|
|
180
|
-
message = @response[:message]
|
|
181
|
-
|
|
182
|
-
build_response(success, message, @response,
|
|
204
|
+
build_response(response[:result] == "0", response[:message], response,
|
|
183
205
|
:test => test?,
|
|
184
|
-
:authorization =>
|
|
206
|
+
:authorization => response[:pn_ref] || response[:rp_ref],
|
|
207
|
+
:cvv_result => CVV_CODE[response[:cv_result]],
|
|
208
|
+
:avs_result => { :code => response[:avs_result] }
|
|
185
209
|
)
|
|
186
210
|
end
|
|
187
|
-
|
|
188
|
-
def parse_credit_card_number(request)
|
|
189
|
-
xml = REXML::Document.new(request)
|
|
190
|
-
card_number = REXML::XPath.first(xml, '//Tender/Card/CardNum')
|
|
191
|
-
card_number && card_number.text
|
|
192
|
-
end
|
|
193
211
|
end
|
|
194
212
|
end
|
|
195
213
|
end
|
|
@@ -84,10 +84,8 @@ module ActiveMerchant #:nodoc:
|
|
|
84
84
|
xml.tag! 'Description', options[:description] unless options[:description].blank?
|
|
85
85
|
|
|
86
86
|
billing_address = options[:billing_address] || options[:address]
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
add_address(xml, 'BillTo', billing_address, options)
|
|
90
|
-
add_address(xml, 'ShipTo', shipping_address, options)
|
|
87
|
+
add_address(xml, 'BillTo', billing_address, options) if billing_address
|
|
88
|
+
add_address(xml, 'ShipTo', options[:shipping_address], options) if options[:shipping_address]
|
|
91
89
|
|
|
92
90
|
xml.tag! 'TotalAmt', amount(money), 'Currency' => options[:currency] || currency(money)
|
|
93
91
|
end
|
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
require 'rexml/document'
|
|
2
2
|
|
|
3
|
-
module ActiveMerchant
|
|
4
|
-
module Billing
|
|
3
|
+
module ActiveMerchant #:nodoc:
|
|
4
|
+
module Billing #:nodoc:
|
|
5
5
|
|
|
6
6
|
# In NZ DPS supports ANZ, Westpac, National Bank, ASB and BNZ.
|
|
7
7
|
# In Australia DPS supports ANZ, NAB, Westpac, CBA, St George and Bank of South Australia.
|
|
8
8
|
# The Maybank in Malaysia is supported and the Citibank for Singapore.
|
|
9
9
|
class PaymentExpressGateway < Gateway
|
|
10
|
-
attr_reader :url
|
|
11
|
-
attr_reader :response
|
|
12
|
-
attr_reader :options
|
|
13
|
-
|
|
14
10
|
self.default_currency = 'NZD'
|
|
15
11
|
# PS supports all major credit cards; Visa, Mastercard, Amex, Diners, BankCard & JCB.
|
|
16
12
|
# Various white label cards can be accepted as well; Farmers, AirNZCard and Elders etc.
|
|
@@ -37,8 +33,6 @@ module ActiveMerchant
|
|
|
37
33
|
:validate => 'Validate'
|
|
38
34
|
}
|
|
39
35
|
|
|
40
|
-
POST_HEADERS = { "Content-Type" => "application/x-www-form-urlencoded" }
|
|
41
|
-
|
|
42
36
|
# We require the DPS gateway username and password when the object is created.
|
|
43
37
|
def initialize(options = {})
|
|
44
38
|
# A DPS username and password must exist
|
|
@@ -49,17 +43,14 @@ module ActiveMerchant
|
|
|
49
43
|
end
|
|
50
44
|
|
|
51
45
|
# Funds are transferred immediately.
|
|
52
|
-
def purchase(money,
|
|
46
|
+
def purchase(money, payment_source, options = {})
|
|
53
47
|
|
|
54
|
-
credit_card =
|
|
48
|
+
credit_card = payment_source if payment_source.respond_to?(:number)
|
|
55
49
|
|
|
56
50
|
if credit_card
|
|
57
|
-
if result = test_result_from_cc_number(credit_card.number)
|
|
58
|
-
return result
|
|
59
|
-
end
|
|
60
51
|
options[:credit_card] = credit_card
|
|
61
52
|
else
|
|
62
|
-
options[:token] =
|
|
53
|
+
options[:token] = payment_source
|
|
63
54
|
end
|
|
64
55
|
|
|
65
56
|
request = build_purchase_or_authorization_request(money, options)
|
|
@@ -70,10 +61,6 @@ module ActiveMerchant
|
|
|
70
61
|
# Verifies that funds are available for the requested card and amount and reserves the specified amount.
|
|
71
62
|
# See: http://www.paymentexpress.com/technical_resources/ecommerce_nonhosted/pxpost.html#Authcomplete
|
|
72
63
|
def authorize(money, credit_card, options = {})
|
|
73
|
-
if result = test_result_from_cc_number(credit_card.number)
|
|
74
|
-
return result
|
|
75
|
-
end
|
|
76
|
-
|
|
77
64
|
options[:credit_card] = credit_card
|
|
78
65
|
|
|
79
66
|
request = build_purchase_or_authorization_request(money, options)
|
|
@@ -184,7 +171,7 @@ module ActiveMerchant
|
|
|
184
171
|
end
|
|
185
172
|
|
|
186
173
|
def add_invoice(xml, options)
|
|
187
|
-
xml.add_element("TxnId").text = options[:order_id] unless options[:order_id].blank?
|
|
174
|
+
xml.add_element("TxnId").text = options[:order_id].to_s.slice(0, 16) unless options[:order_id].blank?
|
|
188
175
|
xml.add_element("MerchantReference").text = options[:description] unless options[:description].blank?
|
|
189
176
|
end
|
|
190
177
|
|
|
@@ -208,24 +195,18 @@ module ActiveMerchant
|
|
|
208
195
|
add_credentials(request)
|
|
209
196
|
add_transaction_type(request, action)
|
|
210
197
|
|
|
211
|
-
# Next, post it to the server
|
|
212
|
-
response = ssl_post(PAYMENT_URL, request.to_s, POST_HEADERS)
|
|
213
|
-
|
|
214
198
|
# Parse the XML response
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
success = @response[:success] == APPROVED
|
|
218
|
-
test = @response[:test_mode] == '1'
|
|
199
|
+
response = parse( ssl_post(PAYMENT_URL, request.to_s) )
|
|
219
200
|
|
|
220
201
|
# Return a response
|
|
221
|
-
PaymentExpressResponse.new(success,
|
|
222
|
-
:test =>
|
|
223
|
-
:authorization =>
|
|
202
|
+
PaymentExpressResponse.new(response[:success] == APPROVED, response[:response_text], response,
|
|
203
|
+
:test => response[:test_mode] == '1',
|
|
204
|
+
:authorization => response[:dps_txn_ref]
|
|
224
205
|
)
|
|
225
206
|
end
|
|
226
207
|
|
|
227
208
|
# Response XML documentation: http://www.paymentexpress.com/technical_resources/ecommerce_nonhosted/pxpost.html#XMLTxnOutput
|
|
228
|
-
def
|
|
209
|
+
def parse(xml_string)
|
|
229
210
|
response = {}
|
|
230
211
|
|
|
231
212
|
xml = REXML::Document.new(xml_string)
|
|
@@ -8,27 +8,16 @@ module ActiveMerchant #:nodoc:
|
|
|
8
8
|
|
|
9
9
|
self.supported_cardtypes = [:visa, :master, :american_express, :discover]
|
|
10
10
|
self.supported_countries = ['US']
|
|
11
|
-
|
|
12
11
|
self.homepage_url = 'https://www.paypal.com/cgi-bin/webscr?cmd=_wp-pro-overview-outside'
|
|
13
12
|
self.display_name = 'PayPal Website Payments Pro (US)'
|
|
14
13
|
|
|
15
14
|
def authorize(money, credit_card, options = {})
|
|
16
15
|
requires!(options, :ip)
|
|
17
|
-
|
|
18
|
-
if result = test_result_from_cc_number(credit_card.number)
|
|
19
|
-
return result
|
|
20
|
-
end
|
|
21
|
-
|
|
22
16
|
commit 'DoDirectPayment', build_sale_or_authorization_request('Authorization', money, credit_card, options)
|
|
23
17
|
end
|
|
24
18
|
|
|
25
19
|
def purchase(money, credit_card, options = {})
|
|
26
20
|
requires!(options, :ip)
|
|
27
|
-
|
|
28
|
-
if result = test_result_from_cc_number(credit_card.number)
|
|
29
|
-
return result
|
|
30
|
-
end
|
|
31
|
-
|
|
32
21
|
commit 'DoDirectPayment', build_sale_or_authorization_request('Sale', money, credit_card, options)
|
|
33
22
|
end
|
|
34
23
|
|
|
@@ -38,7 +27,7 @@ module ActiveMerchant #:nodoc:
|
|
|
38
27
|
|
|
39
28
|
private
|
|
40
29
|
def build_sale_or_authorization_request(action, money, credit_card, options)
|
|
41
|
-
|
|
30
|
+
billing_address = options[:billing_address] || options[:address]
|
|
42
31
|
currency_code = options[:currency] || currency(money)
|
|
43
32
|
|
|
44
33
|
xml = Builder::XmlMarkup.new :indent => 2
|
|
@@ -63,9 +52,9 @@ module ActiveMerchant #:nodoc:
|
|
|
63
52
|
xml.tag! 'n2:InvoiceID', options[:order_id]
|
|
64
53
|
xml.tag! 'n2:ButtonSource', application_id.to_s.slice(0,32) unless application_id.blank?
|
|
65
54
|
|
|
66
|
-
add_address(xml, 'n2:ShipToAddress', shipping_address)
|
|
55
|
+
add_address(xml, 'n2:ShipToAddress', options[:shipping_address]) if options[:shipping_address]
|
|
67
56
|
end
|
|
68
|
-
add_credit_card(xml, credit_card,
|
|
57
|
+
add_credit_card(xml, credit_card, billing_address, options)
|
|
69
58
|
xml.tag! 'n2:IPAddress', options[:ip]
|
|
70
59
|
end
|
|
71
60
|
end
|
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
module ActiveMerchant #:nodoc:
|
|
2
2
|
module Billing #:nodoc:
|
|
3
|
-
# This
|
|
3
|
+
# This module is included in both PaypalGateway and PaypalExpressGateway
|
|
4
4
|
module PaypalCommonAPI
|
|
5
5
|
def self.included(base)
|
|
6
|
-
|
|
7
6
|
base.default_currency = 'USD'
|
|
8
7
|
base.cattr_accessor :pem_file
|
|
9
8
|
base.cattr_accessor :signature
|
|
10
9
|
end
|
|
11
10
|
|
|
12
11
|
API_VERSION = '2.0'
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
|
|
13
|
+
URLS = {
|
|
14
|
+
:test => { :certificate => 'https://api.sandbox.paypal.com/2.0/',
|
|
15
|
+
:signature => 'https://api-3t.sandbox.paypal.com/2.0/' },
|
|
16
|
+
:live => { :certificate => 'https://api-aa.paypal.com/2.0/',
|
|
17
|
+
:signature => 'https://api-3t.paypal.com/2.0/' }
|
|
18
|
+
}
|
|
15
19
|
|
|
16
20
|
PAYPAL_NAMESPACE = 'urn:ebay:api:PayPalAPI'
|
|
17
21
|
EBAY_NAMESPACE = 'urn:ebay:apis:eBLBaseComponents'
|
|
@@ -36,6 +40,8 @@ module ActiveMerchant #:nodoc:
|
|
|
36
40
|
'WA' => 'Western Australia'
|
|
37
41
|
}
|
|
38
42
|
|
|
43
|
+
SUCCESS_CODES = [ 'Success', 'SuccessWithWarning' ]
|
|
44
|
+
|
|
39
45
|
# The gateway must be configured with either your PayPal PEM file
|
|
40
46
|
# or your PayPal API Signature. Only one is required.
|
|
41
47
|
#
|
|
@@ -60,6 +66,10 @@ module ActiveMerchant #:nodoc:
|
|
|
60
66
|
:signature => signature
|
|
61
67
|
}.update(options)
|
|
62
68
|
|
|
69
|
+
if @options[:pem].blank? && @options[:signature].blank?
|
|
70
|
+
raise ArgumentError, "An API Certificate or API Signature is required to make requests to PayPal"
|
|
71
|
+
end
|
|
72
|
+
|
|
63
73
|
super
|
|
64
74
|
end
|
|
65
75
|
|
|
@@ -273,27 +283,37 @@ module ActiveMerchant #:nodoc:
|
|
|
273
283
|
case country.code(:alpha2).to_s
|
|
274
284
|
when 'AU'
|
|
275
285
|
AUSTRALIAN_STATES[address[:state]] || address[:state]
|
|
276
|
-
when 'GB'
|
|
277
|
-
address[:state].blank? ? 'N/A' : address[:state]
|
|
278
286
|
else
|
|
279
|
-
address[:state]
|
|
287
|
+
address[:state].blank? ? 'N/A' : address[:state]
|
|
280
288
|
end
|
|
281
289
|
end
|
|
290
|
+
|
|
291
|
+
def endpoint_url
|
|
292
|
+
URLS[test? ? :test : :live][@options[:signature].blank? ? :certificate : :signature]
|
|
293
|
+
end
|
|
282
294
|
|
|
283
295
|
def commit(action, request)
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
data = ssl_post(url, build_request(request))
|
|
287
|
-
@response = parse(action, data)
|
|
296
|
+
response = parse(action, ssl_post(endpoint_url, build_request(request)))
|
|
288
297
|
|
|
289
|
-
|
|
290
|
-
message = @response[:message] || @response[:ack]
|
|
291
|
-
|
|
292
|
-
build_response(success, message, @response,
|
|
298
|
+
build_response(successful?(response), message_from(response), response,
|
|
293
299
|
:test => test?,
|
|
294
|
-
:authorization =>
|
|
300
|
+
:authorization => authorization_from(response),
|
|
301
|
+
:avs_result => { :code => response[:avs_code] },
|
|
302
|
+
:cvv_result => response[:cvv2_code]
|
|
295
303
|
)
|
|
296
304
|
end
|
|
305
|
+
|
|
306
|
+
def authorization_from(response)
|
|
307
|
+
response[:transaction_id] || response[:authorization_id] # latter one is from reauthorization
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
def successful?(response)
|
|
311
|
+
SUCCESS_CODES.include?(response[:ack])
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
def message_from(response)
|
|
315
|
+
response[:message] || response[:ack]
|
|
316
|
+
end
|
|
297
317
|
end
|
|
298
318
|
end
|
|
299
319
|
end
|