aktivemerchant 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,39 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
class PayflowExpressResponse < Response
|
4
|
+
def email
|
5
|
+
@params['e_mail']
|
6
|
+
end
|
7
|
+
|
8
|
+
def full_name
|
9
|
+
"#{@params['name']} #{@params['lastname']}"
|
10
|
+
end
|
11
|
+
|
12
|
+
def token
|
13
|
+
@params['token']
|
14
|
+
end
|
15
|
+
|
16
|
+
def payer_id
|
17
|
+
@params['payer_id']
|
18
|
+
end
|
19
|
+
|
20
|
+
# Really the shipping country, but it is all the information provided
|
21
|
+
def payer_country
|
22
|
+
address['country']
|
23
|
+
end
|
24
|
+
|
25
|
+
def address
|
26
|
+
{ 'name' => full_name,
|
27
|
+
'company' => nil,
|
28
|
+
'address1' => @params['street'],
|
29
|
+
'address2' => @params['shiptostreet2'] || @params['street2'],
|
30
|
+
'city' => @params['city'],
|
31
|
+
'state' => @params['state'],
|
32
|
+
'country' => @params['country'],
|
33
|
+
'zip' => @params['zip'],
|
34
|
+
'phone' => nil
|
35
|
+
}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
class PayflowResponse < Response
|
4
|
+
def profile_id
|
5
|
+
@params['profile_id']
|
6
|
+
end
|
7
|
+
|
8
|
+
def payment_history
|
9
|
+
@payment_history ||= @params['rp_payment_result'].collect{ |result| result.stringify_keys } rescue []
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,224 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/payflow/payflow_common_api'
|
2
|
+
require File.dirname(__FILE__) + '/payflow/payflow_express_response'
|
3
|
+
require File.dirname(__FILE__) + '/paypal_express_common'
|
4
|
+
|
5
|
+
module ActiveMerchant #:nodoc:
|
6
|
+
module Billing #:nodoc:
|
7
|
+
# ==General Parameters
|
8
|
+
# The following parameters are supported for #setup_authorization, #setup_purchase, #authorize and #purchase transactions. I've read
|
9
|
+
# in the docs that they recommend you pass the exact same parameters to both setup and authorize/purchase.
|
10
|
+
#
|
11
|
+
# This information was gleaned from a mix of:
|
12
|
+
# * PayFlow documentation
|
13
|
+
# * for key value pairs: {Express Checkout for Payflow Pro (PDF)}[https://cms.paypal.com/cms_content/US/en_US/files/developer/PFP_ExpressCheckout_PP.pdf]
|
14
|
+
# * XMLPay: {Payflow Pro XMLPay Developer's Guide (PDF)}[https://cms.paypal.com/cms_content/US/en_US/files/developer/PP_PayflowPro_XMLPay_Guide.pdf]
|
15
|
+
# * previous ActiveMerchant code
|
16
|
+
# * trial & error
|
17
|
+
#
|
18
|
+
# The following parameters are currently supported.
|
19
|
+
# [<tt>:ip</tt>] (opt) Customer IP Address
|
20
|
+
# [<tt>:order_id</tt>] (opt) An order or invoice number. This will be passed through to the Payflow backend at manager.paypal.com, and show up as "Supplier Reference #"
|
21
|
+
# [<tt>:description</tt>] (opt) Order description, shown to buyer (after redirected to PayPal). If Order Line Items are used (see below), then the description is suppressed. This will not be passed through to the Payflow backend.
|
22
|
+
# [<tt>:billing_address</tt>] (opt) See ActiveMerchant::Billing::Gateway for details
|
23
|
+
# [<tt>:shipping_address</tt>] (opt) See ActiveMerchant::Billing::Gateway for details
|
24
|
+
# [<tt>:currency</tt>] (req) Currency of transaction, will be set to USD by default for PayFlow Express if not specified
|
25
|
+
# [<tt>:email</tt>] (opt) Email of buyer; used to pre-fill PayPal login screen
|
26
|
+
# [<tt>:payer_id</tt>] (opt) Unique PayPal buyer account identification number, as returned by details_for request
|
27
|
+
# [<tt>:token</tt>] (req for #authorize & #purchase) Token returned by setup transaction
|
28
|
+
# [<tt>:no_shipping</tt>] (opt) Boolean for whether or not to display shipping address to buyer
|
29
|
+
# [<tt>:address_override</tt>] (opt) Boolean. If true, display shipping address passed by parameters, rather than shipping address on file with PayPal
|
30
|
+
# [<tt>:allow_note</tt>] (opt) Boolean for permitting buyer to add note during checkout. Note contents can be retrieved with details_for transaction
|
31
|
+
# [<tt>:return_url</tt>] (req) URL to which the buyer’s browser is returned after choosing to pay.
|
32
|
+
# [<tt>:cancel_return_url</tt>] (req) URL to which the buyer is returned if the buyer cancels the order.
|
33
|
+
# [<tt>:notify_url</tt>] (opt) Your URL for receiving Instant Payment Notification (IPN) about this transaction.
|
34
|
+
# [<tt>:comment</tt>] (opt) Comment field which will be reported to Payflow backend (at manager.paypal.com) as Comment1
|
35
|
+
# [<tt>:comment2</tt>] (opt) Comment field which will be reported to Payflow backend (at manager.paypal.com) as Comment2
|
36
|
+
# [<tt>:discount</tt>] (opt) Total discounts in cents
|
37
|
+
#
|
38
|
+
# ==Line Items
|
39
|
+
# Support for order line items is available, but has to be enabled on the PayFlow backend. This is what I was told by Todd Sieber at Technical Support:
|
40
|
+
#
|
41
|
+
# <em>You will need to call Payflow Support at 1-888-883-9770, choose option #2. Request that they update your account in "Pandora" under Product Settings >> PayPal Mark and update the Features Bitmap to 1111111111111112. This is 15 ones and a two.</em>
|
42
|
+
#
|
43
|
+
# See here[https://www.x.com/message/206214#206214] for the forum discussion (requires login to {x.com}[https://x.com]
|
44
|
+
#
|
45
|
+
# [<tt>:items</tt>] (opt) Array of Order Line Items hashes. These are shown to the buyer after redirect to PayPal.
|
46
|
+
#
|
47
|
+
#
|
48
|
+
#
|
49
|
+
# The following keys are supported for line items:
|
50
|
+
# [<tt>:name</tt>] Name of line item
|
51
|
+
# [<tt>:description</tt>] Description of line item
|
52
|
+
# [<tt>:amount</tt>] Line Item Amount in Cents (as Integer)
|
53
|
+
# [<tt>:quantity</tt>] Line Item Quantity (default to 1 if left blank)
|
54
|
+
#
|
55
|
+
# ====Customization of Payment Page
|
56
|
+
# [<tt>:page_style</tt>] (opt) Your URL for receiving Instant Payment Notification (IPN) about this transaction.
|
57
|
+
# [<tt>:header_image</tt>] (opt) Your URL for receiving Instant Payment Notification (IPN) about this transaction.
|
58
|
+
# [<tt>:background_color</tt>] (opt) Your URL for receiving Instant Payment Notification (IPN) about this transaction.
|
59
|
+
# ====Additional options for old Checkout Experience, being phased out in 2010 and 2011
|
60
|
+
# [<tt>:header_background_color</tt>] (opt) Your URL for receiving Instant Payment Notification (IPN) about this transaction.
|
61
|
+
# [<tt>:header_border_color</tt>] (opt) Your URL for receiving Instant Payment Notification (IPN) about this transaction.
|
62
|
+
|
63
|
+
|
64
|
+
class PayflowExpressGateway < Gateway
|
65
|
+
include PayflowCommonAPI
|
66
|
+
include PaypalExpressCommon
|
67
|
+
|
68
|
+
self.test_redirect_url = 'https://www.sandbox.paypal.com/cgi-bin/webscr'
|
69
|
+
self.homepage_url = 'https://www.paypal.com/cgi-bin/webscr?cmd=xpt/merchant/ExpressCheckoutIntro-outside'
|
70
|
+
self.display_name = 'PayPal Express Checkout'
|
71
|
+
|
72
|
+
def authorize(money, options = {})
|
73
|
+
requires!(options, :token, :payer_id)
|
74
|
+
request = build_sale_or_authorization_request('Authorization', money, options)
|
75
|
+
commit(request, options)
|
76
|
+
end
|
77
|
+
|
78
|
+
def purchase(money, options = {})
|
79
|
+
requires!(options, :token, :payer_id)
|
80
|
+
request = build_sale_or_authorization_request('Sale', money, options)
|
81
|
+
commit(request, options)
|
82
|
+
end
|
83
|
+
|
84
|
+
def refund(money, identification, options = {})
|
85
|
+
request = build_reference_request(:credit, money, identification, options)
|
86
|
+
commit(request, options)
|
87
|
+
end
|
88
|
+
|
89
|
+
def credit(money, identification, options = {})
|
90
|
+
ActiveMerchant.deprecated CREDIT_DEPRECATION_MESSAGE
|
91
|
+
refund(money, identification, options)
|
92
|
+
end
|
93
|
+
|
94
|
+
def setup_authorization(money, options = {})
|
95
|
+
requires!(options, :return_url, :cancel_return_url)
|
96
|
+
|
97
|
+
request = build_setup_express_sale_or_authorization_request('Authorization', money, options)
|
98
|
+
commit(request, options)
|
99
|
+
end
|
100
|
+
|
101
|
+
def setup_purchase(money, options = {})
|
102
|
+
requires!(options, :return_url, :cancel_return_url)
|
103
|
+
|
104
|
+
request = build_setup_express_sale_or_authorization_request('Sale', money, options)
|
105
|
+
commit(request, options)
|
106
|
+
end
|
107
|
+
|
108
|
+
def details_for(token)
|
109
|
+
request = build_get_express_details_request(token)
|
110
|
+
commit(request, options)
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
def build_get_express_details_request(token)
|
115
|
+
xml = Builder::XmlMarkup.new :indent => 2
|
116
|
+
xml.tag! 'GetExpressCheckout' do
|
117
|
+
xml.tag! 'Authorization' do
|
118
|
+
xml.tag! 'PayData' do
|
119
|
+
xml.tag! 'Tender' do
|
120
|
+
xml.tag! 'PayPal' do
|
121
|
+
xml.tag! 'Token', token
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
xml.target!
|
128
|
+
end
|
129
|
+
|
130
|
+
def build_setup_express_sale_or_authorization_request(action, money, options = {})
|
131
|
+
xml = Builder::XmlMarkup.new :indent => 2
|
132
|
+
xml.tag! 'SetExpressCheckout' do
|
133
|
+
xml.tag! action do
|
134
|
+
add_pay_data xml, money, options
|
135
|
+
end
|
136
|
+
end
|
137
|
+
xml.target!
|
138
|
+
end
|
139
|
+
|
140
|
+
def build_sale_or_authorization_request(action, money, options)
|
141
|
+
xml = Builder::XmlMarkup.new :indent => 2
|
142
|
+
xml.tag! 'DoExpressCheckout' do
|
143
|
+
xml.tag! action do
|
144
|
+
add_pay_data xml, money, options
|
145
|
+
end
|
146
|
+
end
|
147
|
+
xml.target!
|
148
|
+
end
|
149
|
+
|
150
|
+
def add_pay_data(xml, money, options)
|
151
|
+
xml.tag! 'PayData' do
|
152
|
+
xml.tag! 'Invoice' do
|
153
|
+
xml.tag! 'CustIP', options[:ip] unless options[:ip].blank?
|
154
|
+
xml.tag! 'InvNum', options[:order_id] unless options[:order_id].blank?
|
155
|
+
# Description field will be shown to buyer, unless line items are also being supplied (then only line items are shown).
|
156
|
+
xml.tag! 'Description', options[:description] unless options[:description].blank?
|
157
|
+
# Comment, Comment2 should make it to the backend at manager.paypal.com, as with Payflow credit card transactions
|
158
|
+
# but that doesn't seem to work (yet?). See: https://www.x.com/thread/51908?tstart=0
|
159
|
+
xml.tag! 'Comment', options[:comment] unless options[:comment].nil?
|
160
|
+
xml.tag!('ExtData', 'Name'=> 'COMMENT2', 'Value'=> options[:comment2]) unless options[:comment2].nil?
|
161
|
+
|
162
|
+
billing_address = options[:billing_address] || options[:address]
|
163
|
+
add_address(xml, 'BillTo', billing_address, options) if billing_address
|
164
|
+
add_address(xml, 'ShipTo', options[:shipping_address], options) if options[:shipping_address]
|
165
|
+
|
166
|
+
# Note: To get order line-items to show up with Payflow Express, this feature has to be enabled on the backend.
|
167
|
+
# Call Support at 888 883 9770, press 2. Then request that they update your account in "Pandora" under Product Settings >> PayPal
|
168
|
+
# Mark and update the Features Bitmap to 1111111111111112. This is 15 ones and a two.
|
169
|
+
# See here for the forum discussion: https://www.x.com/message/206214#206214
|
170
|
+
items = options[:items] || []
|
171
|
+
items.each_with_index do |item, index|
|
172
|
+
xml.tag! 'ExtData', 'Name' => "L_DESC#{index}", 'Value' => item[:description]
|
173
|
+
xml.tag! 'ExtData', 'Name' => "L_COST#{index}", 'Value' => amount(item[:amount])
|
174
|
+
xml.tag! 'ExtData', 'Name' => "L_QTY#{index}", 'Value' => item[:quantity] || '1'
|
175
|
+
xml.tag! 'ExtData', 'Name' => "L_NAME#{index}", 'Value' => item[:name]
|
176
|
+
# Note: An ItemURL is supported in Paypal Express (different API), but not PayFlow Express, as far as I can tell.
|
177
|
+
# L_URLn nor L_ITEMURLn seem to work
|
178
|
+
end
|
179
|
+
if items.any?
|
180
|
+
xml.tag! 'ExtData', 'Name' => 'CURRENCY', 'Value' => options[:currency] || currency(money)
|
181
|
+
xml.tag! 'ExtData', 'Name' => "ITEMAMT", 'Value' => amount(options[:subtotal] || money)
|
182
|
+
end
|
183
|
+
xml.tag! 'DiscountAmt', amount(options[:discount]) if options[:discount]
|
184
|
+
xml.tag! 'TotalAmt', amount(money), 'Currency' => options[:currency] || currency(money)
|
185
|
+
|
186
|
+
end
|
187
|
+
|
188
|
+
xml.tag! 'Tender' do
|
189
|
+
add_paypal_details(xml, options)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def add_paypal_details(xml, options)
|
195
|
+
xml.tag! 'PayPal' do
|
196
|
+
xml.tag! 'EMail', options[:email] unless options[:email].blank?
|
197
|
+
xml.tag! 'ReturnURL', options[:return_url] unless options[:return_url].blank?
|
198
|
+
xml.tag! 'CancelURL', options[:cancel_return_url] unless options[:cancel_return_url].blank?
|
199
|
+
xml.tag! 'NotifyURL', options[:notify_url] unless options[:notify_url].blank?
|
200
|
+
xml.tag! 'PayerID', options[:payer_id] unless options[:payer_id].blank?
|
201
|
+
xml.tag! 'Token', options[:token] unless options[:token].blank?
|
202
|
+
xml.tag! 'NoShipping', options[:no_shipping] ? '1' : '0'
|
203
|
+
xml.tag! 'AddressOverride', options[:address_override] ? '1' : '0'
|
204
|
+
xml.tag! 'ButtonSource', application_id.to_s.slice(0,32) unless application_id.blank?
|
205
|
+
|
206
|
+
# Customization of the payment page
|
207
|
+
xml.tag! 'PageStyle', options[:page_style] unless options[:page_style].blank?
|
208
|
+
xml.tag! 'HeaderImage', options[:header_image] unless options[:header_image].blank?
|
209
|
+
xml.tag! 'PayflowColor', options[:background_color] unless options[:background_color].blank?
|
210
|
+
# Note: HeaderImage and PayflowColor apply to both the new (as of 2010) and the old checkout experience
|
211
|
+
# HeaderBackColor and HeaderBorderColor apply only to the old checkout experience which is being phased out.
|
212
|
+
xml.tag! 'HeaderBackColor', options[:header_background_color] unless options[:header_background_color].blank?
|
213
|
+
xml.tag! 'HeaderBorderColor', options[:header_border_color] unless options[:header_border_color].blank?
|
214
|
+
xml.tag! 'ExtData', 'Name' => 'ALLOWNOTE', 'Value' => options[:allow_note]
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
def build_response(success, message, response, options = {})
|
219
|
+
PayflowExpressResponse.new(success, message, response, options)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/payflow_express'
|
2
|
+
|
3
|
+
module ActiveMerchant #:nodoc:
|
4
|
+
module Billing #:nodoc:
|
5
|
+
class PayflowExpressUkGateway < PayflowExpressGateway
|
6
|
+
self.default_currency = 'GBP'
|
7
|
+
self.partner = 'PayPalUk'
|
8
|
+
|
9
|
+
self.supported_countries = ['GB']
|
10
|
+
self.homepage_url = 'https://www.paypal.com/uk/cgi-bin/webscr?cmd=_additional-payment-overview-outside'
|
11
|
+
self.display_name = 'PayPal Express Checkout (UK)'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/payflow'
|
2
|
+
require File.dirname(__FILE__) + '/payflow_express_uk'
|
3
|
+
|
4
|
+
module ActiveMerchant #:nodoc:
|
5
|
+
module Billing #:nodoc:
|
6
|
+
class PayflowUkGateway < PayflowGateway
|
7
|
+
self.default_currency = 'GBP'
|
8
|
+
self.partner = 'PayPalUk'
|
9
|
+
|
10
|
+
def express
|
11
|
+
@express ||= PayflowExpressUkGateway.new(@options)
|
12
|
+
end
|
13
|
+
|
14
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :solo, :switch]
|
15
|
+
self.supported_countries = ['GB']
|
16
|
+
self.homepage_url = 'https://www.paypal.com/uk/webapps/mpp/pro'
|
17
|
+
self.display_name = 'PayPal Payments Pro (UK)'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,353 @@
|
|
1
|
+
require 'rexml/document'
|
2
|
+
|
3
|
+
module ActiveMerchant #:nodoc:
|
4
|
+
module Billing #:nodoc:
|
5
|
+
|
6
|
+
# In NZ DPS supports ANZ, Westpac, National Bank, ASB and BNZ.
|
7
|
+
# In Australia DPS supports ANZ, NAB, Westpac, CBA, St George and Bank of South Australia.
|
8
|
+
# The Maybank in Malaysia is supported and the Citibank for Singapore.
|
9
|
+
class PaymentExpressGateway < Gateway
|
10
|
+
self.default_currency = 'NZD'
|
11
|
+
# PS supports all major credit cards; Visa, Mastercard, Amex, Diners, BankCard & JCB.
|
12
|
+
# Various white label cards can be accepted as well; Farmers, AirNZCard and Elders etc.
|
13
|
+
# Please note that not all acquirers and Eftpos networks can support some of these card types.
|
14
|
+
# VISA, Mastercard, Diners Club and Farmers cards are supported
|
15
|
+
#
|
16
|
+
# However, regular accounts with DPS only support VISA and Mastercard
|
17
|
+
self.supported_cardtypes = [ :visa, :master, :american_express, :diners_club, :jcb ]
|
18
|
+
|
19
|
+
self.supported_countries = %w[ AU CA DE ES FR GB HK IE MY NL NZ SG US ZA ]
|
20
|
+
|
21
|
+
self.homepage_url = 'http://www.paymentexpress.com/'
|
22
|
+
self.display_name = 'PaymentExpress'
|
23
|
+
|
24
|
+
self.live_url = self.test_url = 'https://sec.paymentexpress.com/pxpost.aspx'
|
25
|
+
|
26
|
+
APPROVED = '1'
|
27
|
+
|
28
|
+
TRANSACTIONS = {
|
29
|
+
:purchase => 'Purchase',
|
30
|
+
:credit => 'Refund',
|
31
|
+
:authorization => 'Auth',
|
32
|
+
:capture => 'Complete',
|
33
|
+
:validate => 'Validate'
|
34
|
+
}
|
35
|
+
|
36
|
+
# We require the DPS gateway username and password when the object is created.
|
37
|
+
#
|
38
|
+
# The PaymentExpress gateway also supports a :use_custom_payment_token boolean option.
|
39
|
+
# If set to true the gateway will use BillingId for the Token type. If set to false,
|
40
|
+
# then the token will be sent as the DPS specified "DpsBillingId". This is per the documentation at
|
41
|
+
# http://www.paymentexpress.com/technical_resources/ecommerce_nonhosted/pxpost.html#Tokenbilling
|
42
|
+
def initialize(options = {})
|
43
|
+
requires!(options, :login, :password)
|
44
|
+
super
|
45
|
+
end
|
46
|
+
|
47
|
+
# Funds are transferred immediately.
|
48
|
+
#
|
49
|
+
# `payment_source` can be a usual ActiveMerchant credit_card object, or can also
|
50
|
+
# be a string of the `DpsBillingId` or `BillingId` which can be gotten through the
|
51
|
+
# store method. If you are using a `BillingId` instead of `DpsBillingId` you must
|
52
|
+
# also set the instance method `#use_billing_id_for_token` to true, see the `#store`
|
53
|
+
# method for an example of how to do this.
|
54
|
+
def purchase(money, payment_source, options = {})
|
55
|
+
request = build_purchase_or_authorization_request(money, payment_source, options)
|
56
|
+
commit(:purchase, request)
|
57
|
+
end
|
58
|
+
|
59
|
+
# NOTE: Perhaps in options we allow a transaction note to be inserted
|
60
|
+
# Verifies that funds are available for the requested card and amount and reserves the specified amount.
|
61
|
+
# See: http://www.paymentexpress.com/technical_resources/ecommerce_nonhosted/pxpost.html#Authcomplete
|
62
|
+
#
|
63
|
+
# `payment_source` can be a usual ActiveMerchant credit_card object or a token, see #purchased method
|
64
|
+
def authorize(money, payment_source, options = {})
|
65
|
+
request = build_purchase_or_authorization_request(money, payment_source, options)
|
66
|
+
commit(:authorization, request)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Transfer pre-authorized funds immediately
|
70
|
+
# See: http://www.paymentexpress.com/technical_resources/ecommerce_nonhosted/pxpost.html#Authcomplete
|
71
|
+
def capture(money, identification, options = {})
|
72
|
+
request = build_capture_or_credit_request(money, identification, options)
|
73
|
+
commit(:capture, request)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Refund funds to the card holder
|
77
|
+
def refund(money, identification, options = {})
|
78
|
+
requires!(options, :description)
|
79
|
+
|
80
|
+
request = build_capture_or_credit_request(money, identification, options)
|
81
|
+
commit(:credit, request)
|
82
|
+
end
|
83
|
+
|
84
|
+
def credit(money, identification, options = {})
|
85
|
+
ActiveMerchant.deprecated CREDIT_DEPRECATION_MESSAGE
|
86
|
+
refund(money, identification, options)
|
87
|
+
end
|
88
|
+
|
89
|
+
# Token Based Billing
|
90
|
+
#
|
91
|
+
# Instead of storing the credit card details locally, you can store them inside the
|
92
|
+
# Payment Express system and instead bill future transactions against a token.
|
93
|
+
#
|
94
|
+
# This token can either be specified by your code or autogenerated by the PaymentExpress
|
95
|
+
# system. The default is to let PaymentExpress generate the token for you and so use
|
96
|
+
# the `DpsBillingId`. If you do not pass in any option of the `billing_id`, then the store
|
97
|
+
# method will ask PaymentExpress to create a token for you. Additionally, if you are
|
98
|
+
# using the default `DpsBillingId`, you do not have to do anything extra in the
|
99
|
+
# initialization of your gateway object.
|
100
|
+
#
|
101
|
+
# To specify and use your own token, you need to do two things.
|
102
|
+
#
|
103
|
+
# Firstly, pass in a `:billing_id` as an option in the hash of this store method. No
|
104
|
+
# validation is done on this BillingId by PaymentExpress so you must ensure that it is unique.
|
105
|
+
#
|
106
|
+
# gateway.store(credit_card, {:billing_id => 'YourUniqueBillingId'})
|
107
|
+
#
|
108
|
+
# Secondly, you will need to pass in the option `{:use_custom_payment_token => true}` when
|
109
|
+
# initializing your gateway instance, like so:
|
110
|
+
#
|
111
|
+
# gateway = ActiveMerchant::Billing::PaymentExpressGateway.new(
|
112
|
+
# :login => 'USERNAME',
|
113
|
+
# :password => 'PASSWORD',
|
114
|
+
# :use_custom_payment_token => true
|
115
|
+
# )
|
116
|
+
#
|
117
|
+
# see: http://www.paymentexpress.com/technical_resources/ecommerce_nonhosted/pxpost.html#Tokenbilling
|
118
|
+
#
|
119
|
+
# Note, once stored, PaymentExpress does not support unstoring a stored card.
|
120
|
+
def store(credit_card, options = {})
|
121
|
+
request = build_token_request(credit_card, options)
|
122
|
+
commit(:validate, request)
|
123
|
+
end
|
124
|
+
|
125
|
+
private
|
126
|
+
|
127
|
+
def use_custom_payment_token?
|
128
|
+
@options[:use_custom_payment_token]
|
129
|
+
end
|
130
|
+
|
131
|
+
def build_purchase_or_authorization_request(money, payment_source, options)
|
132
|
+
result = new_transaction
|
133
|
+
|
134
|
+
if payment_source.is_a?(String)
|
135
|
+
add_billing_token(result, payment_source)
|
136
|
+
else
|
137
|
+
add_credit_card(result, payment_source)
|
138
|
+
end
|
139
|
+
|
140
|
+
add_amount(result, money, options)
|
141
|
+
add_invoice(result, options)
|
142
|
+
add_address_verification_data(result, options)
|
143
|
+
add_optional_elements(result, options)
|
144
|
+
result
|
145
|
+
end
|
146
|
+
|
147
|
+
def build_capture_or_credit_request(money, identification, options)
|
148
|
+
result = new_transaction
|
149
|
+
|
150
|
+
add_amount(result, money, options)
|
151
|
+
add_invoice(result, options)
|
152
|
+
add_reference(result, identification)
|
153
|
+
add_optional_elements(result, options)
|
154
|
+
result
|
155
|
+
end
|
156
|
+
|
157
|
+
def build_token_request(credit_card, options)
|
158
|
+
result = new_transaction
|
159
|
+
add_credit_card(result, credit_card)
|
160
|
+
add_amount(result, 100, options) #need to make an auth request for $1
|
161
|
+
add_token_request(result, options)
|
162
|
+
add_optional_elements(result, options)
|
163
|
+
result
|
164
|
+
end
|
165
|
+
|
166
|
+
def add_credentials(xml)
|
167
|
+
xml.add_element("PostUsername").text = @options[:login]
|
168
|
+
xml.add_element("PostPassword").text = @options[:password]
|
169
|
+
end
|
170
|
+
|
171
|
+
def add_reference(xml, identification)
|
172
|
+
xml.add_element("DpsTxnRef").text = identification
|
173
|
+
end
|
174
|
+
|
175
|
+
def add_credit_card(xml, credit_card)
|
176
|
+
xml.add_element("CardHolderName").text = credit_card.name
|
177
|
+
xml.add_element("CardNumber").text = credit_card.number
|
178
|
+
xml.add_element("DateExpiry").text = format_date(credit_card.month, credit_card.year)
|
179
|
+
|
180
|
+
if credit_card.verification_value?
|
181
|
+
xml.add_element("Cvc2").text = credit_card.verification_value
|
182
|
+
xml.add_element("Cvc2Presence").text = "1"
|
183
|
+
end
|
184
|
+
|
185
|
+
if requires_start_date_or_issue_number?(credit_card)
|
186
|
+
xml.add_element("DateStart").text = format_date(credit_card.start_month, credit_card.start_year) unless credit_card.start_month.blank? || credit_card.start_year.blank?
|
187
|
+
xml.add_element("IssueNumber").text = credit_card.issue_number unless credit_card.issue_number.blank?
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def add_billing_token(xml, token)
|
192
|
+
if use_custom_payment_token?
|
193
|
+
xml.add_element("BillingId").text = token
|
194
|
+
else
|
195
|
+
xml.add_element("DpsBillingId").text = token
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def add_token_request(xml, options)
|
200
|
+
xml.add_element("BillingId").text = options[:billing_id] if options[:billing_id]
|
201
|
+
xml.add_element("EnableAddBillCard").text = 1
|
202
|
+
end
|
203
|
+
|
204
|
+
def add_amount(xml, money, options)
|
205
|
+
xml.add_element("Amount").text = amount(money)
|
206
|
+
xml.add_element("InputCurrency").text = options[:currency] || currency(money)
|
207
|
+
end
|
208
|
+
|
209
|
+
def add_transaction_type(xml, action)
|
210
|
+
xml.add_element("TxnType").text = TRANSACTIONS[action]
|
211
|
+
end
|
212
|
+
|
213
|
+
def add_invoice(xml, options)
|
214
|
+
xml.add_element("TxnId").text = options[:order_id].to_s.slice(0, 16) unless options[:order_id].blank?
|
215
|
+
xml.add_element("MerchantReference").text = options[:description].to_s.slice(0, 50) unless options[:description].blank?
|
216
|
+
end
|
217
|
+
|
218
|
+
def add_address_verification_data(xml, options)
|
219
|
+
address = options[:billing_address] || options[:address]
|
220
|
+
return if address.nil?
|
221
|
+
|
222
|
+
xml.add_element("EnableAvsData").text = 1
|
223
|
+
xml.add_element("AvsAction").text = 1
|
224
|
+
|
225
|
+
xml.add_element("AvsStreetAddress").text = address[:address1]
|
226
|
+
xml.add_element("AvsPostCode").text = address[:zip]
|
227
|
+
end
|
228
|
+
|
229
|
+
# The options hash may contain optional data which will be passed
|
230
|
+
# through the specialized optional fields at PaymentExpress
|
231
|
+
# as follows:
|
232
|
+
#
|
233
|
+
# {
|
234
|
+
# :client_type => :web, # Possible values are: :web, :ivr, :moto, :unattended, :internet, or :recurring
|
235
|
+
# :txn_data1 => "String up to 255 characters",
|
236
|
+
# :txn_data2 => "String up to 255 characters",
|
237
|
+
# :txn_data3 => "String up to 255 characters"
|
238
|
+
# }
|
239
|
+
#
|
240
|
+
# +:client_type+, while not documented for PxPost, will be sent as
|
241
|
+
# the +ClientType+ XML element as described in the documentation for
|
242
|
+
# the PaymentExpress WebService: http://www.paymentexpress.com/Technical_Resources/Ecommerce_NonHosted/WebService#clientType
|
243
|
+
# (PaymentExpress have confirmed that this value works the same in PxPost).
|
244
|
+
# The value sent for +:client_type+ will be normalized and sent
|
245
|
+
# as one of the explicit values allowed by PxPost:
|
246
|
+
#
|
247
|
+
# :web => "Web"
|
248
|
+
# :ivr => "IVR"
|
249
|
+
# :moto => "MOTO"
|
250
|
+
# :unattended => "Unattended"
|
251
|
+
# :internet => "Internet"
|
252
|
+
# :recurring => "Recurring"
|
253
|
+
#
|
254
|
+
# If you set the +:client_type+ to any value not listed above,
|
255
|
+
# the ClientType element WILL NOT BE INCLUDED at all in the
|
256
|
+
# POST data.
|
257
|
+
#
|
258
|
+
# +:txn_data1+, +:txn_data2+, and +:txn_data3+ will be sent as
|
259
|
+
# +TxnData1+, +TxnData2+, and +TxnData3+, respectively, and are
|
260
|
+
# free form fields of the merchant's choosing, as documented here:
|
261
|
+
# http://www.paymentexpress.com/technical_resources/ecommerce_nonhosted/pxpost.html#txndata
|
262
|
+
#
|
263
|
+
# These optional elements are added to all transaction types:
|
264
|
+
# +purchase+, +authorize+, +capture+, +refund+, +store+
|
265
|
+
def add_optional_elements(xml, options)
|
266
|
+
if client_type = normalized_client_type(options[:client_type])
|
267
|
+
xml.add_element("ClientType").text = client_type
|
268
|
+
end
|
269
|
+
|
270
|
+
xml.add_element("TxnData1").text = options[:txn_data1].to_s.slice(0,255) unless options[:txn_data1].blank?
|
271
|
+
xml.add_element("TxnData2").text = options[:txn_data2].to_s.slice(0,255) unless options[:txn_data2].blank?
|
272
|
+
xml.add_element("TxnData3").text = options[:txn_data3].to_s.slice(0,255) unless options[:txn_data3].blank?
|
273
|
+
end
|
274
|
+
|
275
|
+
def new_transaction
|
276
|
+
REXML::Document.new.add_element("Txn")
|
277
|
+
end
|
278
|
+
|
279
|
+
# Take in the request and post it to DPS
|
280
|
+
def commit(action, request)
|
281
|
+
add_credentials(request)
|
282
|
+
add_transaction_type(request, action)
|
283
|
+
|
284
|
+
# Parse the XML response
|
285
|
+
response = parse( ssl_post(self.live_url, request.to_s) )
|
286
|
+
|
287
|
+
# Return a response
|
288
|
+
PaymentExpressResponse.new(response[:success] == APPROVED, message_from(response), response,
|
289
|
+
:test => response[:test_mode] == '1',
|
290
|
+
:authorization => authorization_from(action, response)
|
291
|
+
)
|
292
|
+
end
|
293
|
+
|
294
|
+
# Response XML documentation: http://www.paymentexpress.com/technical_resources/ecommerce_nonhosted/pxpost.html#XMLTxnOutput
|
295
|
+
def parse(xml_string)
|
296
|
+
response = {}
|
297
|
+
|
298
|
+
xml = REXML::Document.new(xml_string)
|
299
|
+
|
300
|
+
# Gather all root elements such as HelpText
|
301
|
+
xml.elements.each('Txn/*') do |element|
|
302
|
+
response[element.name.underscore.to_sym] = element.text unless element.name == 'Transaction'
|
303
|
+
end
|
304
|
+
|
305
|
+
# Gather all transaction elements and prefix with "account_"
|
306
|
+
# So we could access the MerchantResponseText by going
|
307
|
+
# response[account_merchant_response_text]
|
308
|
+
xml.elements.each('Txn/Transaction/*') do |element|
|
309
|
+
response[element.name.underscore.to_sym] = element.text
|
310
|
+
end
|
311
|
+
|
312
|
+
response
|
313
|
+
end
|
314
|
+
|
315
|
+
def message_from(response)
|
316
|
+
(response[:card_holder_help_text] || response[:response_text])
|
317
|
+
end
|
318
|
+
|
319
|
+
def authorization_from(action, response)
|
320
|
+
case action
|
321
|
+
when :validate
|
322
|
+
(response[:billing_id] || response[:dps_billing_id])
|
323
|
+
else
|
324
|
+
response[:dps_txn_ref]
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
def format_date(month, year)
|
329
|
+
"#{format(month, :two_digits)}#{format(year, :two_digits)}"
|
330
|
+
end
|
331
|
+
|
332
|
+
def normalized_client_type(client_type_from_options)
|
333
|
+
case client_type_from_options.to_s.downcase
|
334
|
+
when 'web' then "Web"
|
335
|
+
when 'ivr' then "IVR"
|
336
|
+
when 'moto' then "MOTO"
|
337
|
+
when 'unattended' then "Unattended"
|
338
|
+
when 'internet' then "Internet"
|
339
|
+
when 'recurring' then "Recurring"
|
340
|
+
else nil
|
341
|
+
end
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
class PaymentExpressResponse < Response
|
346
|
+
# add a method to response so we can easily get the token
|
347
|
+
# for Validate transactions
|
348
|
+
def token
|
349
|
+
@params["billing_id"] || @params["dps_billing_id"]
|
350
|
+
end
|
351
|
+
end
|
352
|
+
end
|
353
|
+
end
|