lib/active_merchant/billing/gateways/payment_express.rb in activemerchant-1.28.0 vs lib/active_merchant/billing/gateways/payment_express.rb in activemerchant-1.29.0

- old
+ new

@@ -1,98 +1,95 @@ require 'rexml/document' module ActiveMerchant #:nodoc: module Billing #:nodoc: - - # In NZ DPS supports ANZ, Westpac, National Bank, ASB and BNZ. - # In Australia DPS supports ANZ, NAB, Westpac, CBA, St George and Bank of South Australia. + + # In NZ DPS supports ANZ, Westpac, National Bank, ASB and BNZ. + # In Australia DPS supports ANZ, NAB, Westpac, CBA, St George and Bank of South Australia. # The Maybank in Malaysia is supported and the Citibank for Singapore. class PaymentExpressGateway < Gateway self.default_currency = 'NZD' - # PS supports all major credit cards; Visa, Mastercard, Amex, Diners, BankCard & JCB. - # Various white label cards can be accepted as well; Farmers, AirNZCard and Elders etc. + # PS supports all major credit cards; Visa, Mastercard, Amex, Diners, BankCard & JCB. + # Various white label cards can be accepted as well; Farmers, AirNZCard and Elders etc. # Please note that not all acquirers and Eftpos networks can support some of these card types. # VISA, Mastercard, Diners Club and Farmers cards are supported # # However, regular accounts with DPS only support VISA and Mastercard self.supported_cardtypes = [ :visa, :master, :american_express, :diners_club, :jcb ] - + self.supported_countries = %w[ AU MY NZ SG ZA GB US ] - + self.homepage_url = 'http://www.paymentexpress.com/' self.display_name = 'PaymentExpress' self.live_url = self.test_url = 'https://sec.paymentexpress.com/pxpost.aspx' - + APPROVED = '1' - + TRANSACTIONS = { :purchase => 'Purchase', :credit => 'Refund', :authorization => 'Auth', :capture => 'Complete', :validate => 'Validate' } - + # We require the DPS gateway username and password when the object is created. # # The PaymentExpress gateway also supports a :use_custom_payment_token boolean option. # If set to true the gateway will use BillingId for the Token type. If set to false, # then the token will be sent as the DPS specified "DpsBillingId". This is per the documentation at # http://www.paymentexpress.com/technical_resources/ecommerce_nonhosted/pxpost.html#Tokenbilling def initialize(options = {}) - # A DPS username and password must exist requires!(options, :login, :password) - # Make the options an instance variable - @options = options super end - + # Funds are transferred immediately. # # `payment_source` can be a usual ActiveMerchant credit_card object, or can also - # be a string of the `DpsBillingId` or `BillingId` which can be gotten through the + # be a string of the `DpsBillingId` or `BillingId` which can be gotten through the # store method. If you are using a `BillingId` instead of `DpsBillingId` you must # also set the instance method `#use_billing_id_for_token` to true, see the `#store` # method for an example of how to do this. def purchase(money, payment_source, options = {}) request = build_purchase_or_authorization_request(money, payment_source, options) - commit(:purchase, request) + commit(:purchase, request) end - + # NOTE: Perhaps in options we allow a transaction note to be inserted # Verifies that funds are available for the requested card and amount and reserves the specified amount. # See: http://www.paymentexpress.com/technical_resources/ecommerce_nonhosted/pxpost.html#Authcomplete # # `payment_source` can be a usual ActiveMerchant credit_card object or a token, see #purchased method def authorize(money, payment_source, options = {}) request = build_purchase_or_authorization_request(money, payment_source, options) commit(:authorization, request) end - + # Transfer pre-authorized funds immediately # See: http://www.paymentexpress.com/technical_resources/ecommerce_nonhosted/pxpost.html#Authcomplete def capture(money, identification, options = {}) - request = build_capture_or_credit_request(money, identification, options) + request = build_capture_or_credit_request(money, identification, options) commit(:capture, request) end - + # Refund funds to the card holder def refund(money, identification, options = {}) requires!(options, :description) - - request = build_capture_or_credit_request(money, identification, options) + + request = build_capture_or_credit_request(money, identification, options) commit(:credit, request) end def credit(money, identification, options = {}) deprecated CREDIT_DEPRECATION_MESSAGE refund(money, identification, options) end - + # Token Based Billing - # + # # Instead of storing the credit card details locally, you can store them inside the # Payment Express system and instead bill future transactions against a token. # # This token can either be specified by your code or autogenerated by the PaymentExpress # system. The default is to let PaymentExpress generate the token for you and so use @@ -100,11 +97,11 @@ # method will ask PaymentExpress to create a token for you. Additionally, if you are # using the default `DpsBillingId`, you do not have to do anything extra in the # initialization of your gateway object. # # To specify and use your own token, you need to do two things. - # + # # Firstly, pass in a `:billing_id` as an option in the hash of this store method. No # validation is done on this BillingId by PaymentExpress so you must ensure that it is unique. # # gateway.store(credit_card, {:billing_id => 'YourUniqueBillingId'}) # @@ -122,68 +119,68 @@ # Note, once stored, PaymentExpress does not support unstoring a stored card. def store(credit_card, options = {}) request = build_token_request(credit_card, options) commit(:validate, request) end - + private def use_custom_payment_token? @options[:use_custom_payment_token] end - + def build_purchase_or_authorization_request(money, payment_source, options) - result = new_transaction + result = new_transaction if payment_source.is_a?(String) add_billing_token(result, payment_source) else add_credit_card(result, payment_source) end - + add_amount(result, money, options) add_invoice(result, options) add_address_verification_data(result, options) result end - + def build_capture_or_credit_request(money, identification, options) result = new_transaction - + add_amount(result, money, options) add_invoice(result, options) add_reference(result, identification) result end - + def build_token_request(credit_card, options) result = new_transaction add_credit_card(result, credit_card) add_amount(result, 100, options) #need to make an auth request for $1 add_token_request(result, options) result end - + def add_credentials(xml) xml.add_element("PostUsername").text = @options[:login] xml.add_element("PostPassword").text = @options[:password] end - + def add_reference(xml, identification) xml.add_element("DpsTxnRef").text = identification end - + def add_credit_card(xml, credit_card) xml.add_element("CardHolderName").text = credit_card.name xml.add_element("CardNumber").text = credit_card.number xml.add_element("DateExpiry").text = format_date(credit_card.month, credit_card.year) - + if credit_card.verification_value? xml.add_element("Cvc2").text = credit_card.verification_value xml.add_element("Cvc2Presence").text = "1" end - + if requires_start_date_or_issue_number?(credit_card) 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? xml.add_element("IssueNumber").text = credit_card.issue_number unless credit_card.issue_number.blank? end end @@ -193,53 +190,53 @@ xml.add_element("BillingId").text = token else xml.add_element("DpsBillingId").text = token end end - + def add_token_request(xml, options) xml.add_element("BillingId").text = options[:billing_id] if options[:billing_id] xml.add_element("EnableAddBillCard").text = 1 end - + def add_amount(xml, money, options) xml.add_element("Amount").text = amount(money) xml.add_element("InputCurrency").text = options[:currency] || currency(money) end - + def add_transaction_type(xml, action) xml.add_element("TxnType").text = TRANSACTIONS[action] end - + def add_invoice(xml, options) xml.add_element("TxnId").text = options[:order_id].to_s.slice(0, 16) unless options[:order_id].blank? xml.add_element("MerchantReference").text = options[:description] unless options[:description].blank? end - + def add_address_verification_data(xml, options) address = options[:billing_address] || options[:address] return if address.nil? - + xml.add_element("EnableAvsData").text = 1 xml.add_element("AvsAction").text = 1 - + xml.add_element("AvsStreetAddress").text = address[:address1] xml.add_element("AvsPostCode").text = address[:zip] end - + def new_transaction REXML::Document.new.add_element("Txn") end # Take in the request and post it to DPS def commit(action, request) add_credentials(request) add_transaction_type(request, action) - + # Parse the XML response response = parse( ssl_post(self.live_url, request.to_s) ) - + # Return a response PaymentExpressResponse.new(response[:success] == APPROVED, response[:card_holder_help_text], response, :test => response[:test_mode] == '1', :authorization => response[:dps_txn_ref] ) @@ -247,11 +244,11 @@ # Response XML documentation: http://www.paymentexpress.com/technical_resources/ecommerce_nonhosted/pxpost.html#XMLTxnOutput def parse(xml_string) response = {} - xml = REXML::Document.new(xml_string) + xml = REXML::Document.new(xml_string) # Gather all root elements such as HelpText xml.elements.each('Txn/*') do |element| response[element.name.underscore.to_sym] = element.text unless element.name == 'Transaction' end @@ -260,18 +257,18 @@ # So we could access the MerchantResponseText by going # response[account_merchant_response_text] xml.elements.each('Txn/Transaction/*') do |element| response[element.name.underscore.to_sym] = element.text end - + response end - + def format_date(month, year) "#{format(month, :two_digits)}#{format(year, :two_digits)}" end end - + class PaymentExpressResponse < Response # add a method to response so we can easily get the token # for Validate transactions def token @params["billing_id"] || @params["dps_billing_id"]