lib/active_merchant/billing/gateways/data_cash.rb in activemerchant-1.59.0 vs lib/active_merchant/billing/gateways/data_cash.rb in activemerchant-1.60.0

- old
+ new

@@ -4,72 +4,33 @@ module Billing class DataCashGateway < Gateway self.default_currency = 'GBP' self.supported_countries = ['GB'] - # From the DataCash docs; Page 13, the following cards are - # usable: - # American Express, ATM, Carte Blanche, Diners Club, Discover, - # EnRoute, GE Capital, JCB, Laser, Maestro, Mastercard, Solo, - # Switch, Visa, Visa Delta, VISA Electron, Visa Purchasing - # - # Note continuous authority is only supported for :visa, :master and :american_express card types self.supported_cardtypes = [ :visa, :master, :american_express, :discover, :diners_club, :jcb, :maestro, :switch, :solo, :laser ] self.homepage_url = 'http://www.datacash.com/' self.display_name = 'DataCash' - # Datacash server URLs self.test_url = 'https://testserver.datacash.com/Transaction' self.live_url = 'https://mars.transaction.datacash.com/Transaction' - # Different Card Transaction Types AUTH_TYPE = 'auth' CANCEL_TYPE = 'cancel' FULFILL_TYPE = 'fulfill' PRE_TYPE = 'pre' REFUND_TYPE = 'refund' TRANSACTION_REFUND_TYPE = 'txn_refund' - # Constant strings for use in the ExtendedPolicy complex element for - # CV2 checks POLICY_ACCEPT = 'accept' POLICY_REJECT = 'reject' - # Datacash success code - DATACASH_SUCCESS = '1' - - # Creates a new DataCashGateway - # - # The gateway requires that a valid login and password be passed - # in the +options+ hash. - # - # ==== Options - # - # * <tt>:login</tt> -- The Datacash account login. - # * <tt>:password</tt> -- The Datacash account password. - # * <tt>:test => +true+ or +false+</tt> -- Use the test or live Datacash url. - # def initialize(options = {}) requires!(options, :login, :password) super end - # Perform a purchase, which is essentially an authorization and capture in a single operation. - # - # ==== Parameters - # * <tt>money</tt> The amount to be authorized as an Integer value in cents. - # * <tt>authorization_or_credit_card</tt>:: The continuous authority reference or CreditCard details for the transaction. - # * <tt>options</tt> A hash of optional parameters. - # * <tt>:order_id</tt> A unique reference for this order (corresponds to merchantreference in datacash documentation) - # * <tt>:set_up_continuous_authority</tt> - # Set to true to set up a recurring historic transaction account be set up. - # Only supported for :visa, :master and :american_express card types - # See http://www.datacash.com/services/recurring/historic.php for more details of historic transactions. - # * <tt>:address</tt>:: billing address for card - # - # The continuous authority reference will be available in response#params['ca_reference'] if you have requested one def purchase(money, authorization_or_credit_card, options = {}) requires!(options, :order_id) if authorization_or_credit_card.is_a?(String) request = build_purchase_or_authorization_request_with_continuous_authority_reference_request(AUTH_TYPE, money, authorization_or_credit_card, options) @@ -78,26 +39,10 @@ end commit(request) end - # Performs an authorization, which reserves the funds on the customer's credit card, but does not - # charge the card. - # - # ==== Parameters - # - # * <tt>money</tt> The amount to be authorized as an Integer value in cents. - # * <tt>authorization_or_credit_card</tt>:: The continuous authority reference or CreditCard details for the transaction. - # * <tt>options</tt> A hash of optional parameters. - # * <tt>:order_id</tt> A unique reference for this order (corresponds to merchantreference in datacash documentation) - # * <tt>:set_up_continuous_authority</tt>:: - # Set to true to set up a recurring historic transaction account be set up. - # Only supported for :visa, :master and :american_express card types - # See http://www.datacash.com/services/recurring/historic.php for more details of historic transactions. - # * <tt>:address</tt>:: billing address for card - # - # The continuous authority reference will be available in response#params['ca_reference'] if you have requested one def authorize(money, authorization_or_credit_card, options = {}) requires!(options, :order_id) if authorization_or_credit_card.is_a?(String) request = build_purchase_or_authorization_request_with_continuous_authority_reference_request(AUTH_TYPE, money, authorization_or_credit_card, options) @@ -106,90 +51,42 @@ end commit(request) end - # Captures the funds from an authorized transaction. - # - # ==== Parameters - # - # * <tt>money</tt> -- The amount to be captured as anInteger value in cents. - # * <tt>authorization</tt> -- The authorization returned from the previous authorize request. def capture(money, authorization, options = {}) commit(build_void_or_capture_request(FULFILL_TYPE, money, authorization, options)) end - # Void a previous transaction - # - # ==== Parameters - # - # * <tt>authorization</tt> - The authorization returned from the previous authorize request. def void(authorization, options = {}) request = build_void_or_capture_request(CANCEL_TYPE, nil, authorization, options) commit(request) end - # Refund to a card - # - # ==== Parameters - # - # * <tt>money</tt> The amount to be refunded as an Integer value in cents. Set to nil for a full refund on existing transaction. - # * <tt>reference_or_credit_card</tt> The credit card you want to refund OR the datacash_reference for the existing transaction you are refunding - # * <tt>options</tt> Are ignored when refunding via reference to an existing transaction, otherwise - # * <tt>:order_id</tt> A unique reference for this order (corresponds to merchantreference in datacash documentation) - # * <tt>:address</tt>:: billing address for card def credit(money, reference_or_credit_card, options = {}) if reference_or_credit_card.is_a?(String) ActiveMerchant.deprecated CREDIT_DEPRECATION_MESSAGE refund(money, reference_or_credit_card) else - request = build_refund_request(money, reference_or_credit_card, options) + request = build_credit_request(money, reference_or_credit_card, options) commit(request) end end def refund(money, reference, options = {}) commit(build_transaction_refund_request(money, reference)) end + private - # Create the xml document for a 'cancel' or 'fulfill' transaction. - # - # Final XML should look like: - # <Request> - # <Authentication> - # <client>99000001</client> - # <password>******</password> - # </Authentication> - # <Transaction> - # <TxnDetails> - # <amount>25.00</amount> - # </TxnDetails> - # <HistoricTxn> - # <reference>4900200000000001</reference> - # <authcode>A6</authcode> - # <method>fulfill</method> - # </HistoricTxn> - # </Transaction> - # </Request> - # - # Parameters: - # * <tt>type</tt> must be FULFILL_TYPE or CANCEL_TYPE - # * <tt>money</tt> - optional - Integer value in cents - # * <tt>authorization</tt> - the Datacash authorization from a previous succesful authorize transaction - # * <tt>options</tt> - # * <tt>order_id</tt> - A unique reference for the transaction - # - # Returns: - # -Builder xml document - # + def build_void_or_capture_request(type, money, authorization, options) parsed_authorization = parse_authorization_string(authorization) xml = Builder::XmlMarkup.new :indent => 2 xml.instruct! - xml.tag! :Request do + xml.tag! :Request, :version => '2' do add_authentication(xml) xml.tag! :Transaction do xml.tag! :HistoricTxn do xml.tag! :reference, parsed_authorization[:reference] @@ -207,75 +104,14 @@ end end xml.target! end - # Create the xml document for an 'auth' or 'pre' transaction with a credit card - # - # Final XML should look like: - # - # <Request> - # <Authentication> - # <client>99000000</client> - # <password>*******</password> - # </Authentication> - # <Transaction> - # <TxnDetails> - # <merchantreference>123456</merchantreference> - # <amount currency="EUR">10.00</amount> - # </TxnDetails> - # <CardTxn> - # <Card> - # <pan>4444********1111</pan> - # <expirydate>03/04</expirydate> - # <Cv2Avs> - # <street_address1>Flat 7</street_address1> - # <street_address2>89 Jumble - # Street</street_address2> - # <street_address3>Mytown</street_address3> - # <postcode>AV12FR</postcode> - # <cv2>123</cv2> - # <ExtendedPolicy> - # <cv2_policy notprovided="reject" - # notchecked="accept" - # matched="accept" - # notmatched="reject" - # partialmatch="reject"/> - # <postcode_policy notprovided="reject" - # notchecked="accept" - # matched="accept" - # notmatched="reject" - # partialmatch="accept"/> - # <address_policy notprovided="reject" - # notchecked="accept" - # matched="accept" - # notmatched="reject" - # partialmatch="accept"/> - # </ExtendedPolicy> - # </Cv2Avs> - # </Card> - # <method>auth</method> - # </CardTxn> - # </Transaction> - # </Request> - # - # Parameters: - # -type must be 'auth' or 'pre' - # -money - A money object with the price and currency - # -credit_card - The credit_card details to use - # -options: - # :order_id is the merchant reference number - # :billing_address is the billing address for the cc - # :address is the delivery address - # - # Returns: - # -xml: Builder document containing the markup - # def build_purchase_or_authorization_request_with_credit_card_request(type, money, credit_card, options) xml = Builder::XmlMarkup.new :indent => 2 xml.instruct! - xml.tag! :Request do + xml.tag! :Request, :version => '2' do add_authentication(xml) xml.tag! :Transaction do if options[:set_up_continuous_authority] xml.tag! :ContAuthTxn, :type => 'setup' @@ -292,51 +128,17 @@ end end xml.target! end - # Create the xml document for an 'auth' or 'pre' transaction with - # continuous authorization - # - # Final XML should look like: - # - # <Request> - # <Transaction> - # <ContAuthTxn type="historic" /> - # <TxnDetails> - # <merchantreference>3851231</merchantreference> - # <capturemethod>cont_auth</capturemethod> - # <amount currency="GBP">18.50</amount> - # </TxnDetails> - # <HistoricTxn> - # <reference>4500200040925092</reference> - # <method>auth</method> - # </HistoricTxn> - # </Transaction> - # <Authentication> - # <client>99000001</client> - # <password>mypasswd</password> - # </Authentication> - # </Request> - # - # Parameters: - # -type must be 'auth' or 'pre' - # -money - A money object with the price and currency - # -authorization - The authorization containing a continuous authority reference previously set up on a credit card - # -options: - # :order_id is the merchant reference number - # - # Returns: - # -xml: Builder document containing the markup - # def build_purchase_or_authorization_request_with_continuous_authority_reference_request(type, money, authorization, options) parsed_authorization = parse_authorization_string(authorization) raise ArgumentError, "The continuous authority reference is required for continuous authority transactions" if parsed_authorization[:ca_reference].blank? xml = Builder::XmlMarkup.new :indent => 2 xml.instruct! - xml.tag! :Request do + xml.tag! :Request, :version => '2' do add_authentication(xml) xml.tag! :Transaction do xml.tag! :ContAuthTxn, :type => 'historic' xml.tag! :HistoricTxn do xml.tag! :reference, parsed_authorization[:ca_reference] @@ -350,35 +152,15 @@ end end xml.target! end - # Create the xml document for a full or partial refund transaction with - # - # Final XML should look like: - # - # <Request> - # <Authentication> - # <client>99000001</client> - # <password>*******</password> - # </Authentication> - # <Transaction> - # <HistoricTxn> - # <method>txn_refund</method> - # <reference>12345678</reference> - # </HistoricTxn> - # <TxnDetails> - # <amount>10.00</amount> - # </TxnDetails> - # </Transaction> - # </Request> - # def build_transaction_refund_request(money, authorization) parsed_authorization = parse_authorization_string(authorization) xml = Builder::XmlMarkup.new :indent => 2 xml.instruct! - xml.tag! :Request do + xml.tag! :Request, :version => '2' do add_authentication(xml) xml.tag! :Transaction do xml.tag! :HistoricTxn do xml.tag! :reference, parsed_authorization[:reference] xml.tag! :method, TRANSACTION_REFUND_TYPE @@ -391,38 +173,14 @@ end end xml.target! end - # Create the xml document for a full or partial refund with - # - # Final XML should look like: - # - # <Request> - # <Authentication> - # <client>99000001</client> - # <password>*****</password> - # </Authentication> - # <Transaction> - # <CardTxn> - # <Card> - # <pan>633300*********1</pan> - # <expirydate>04/06</expirydate> - # <startdate>01/04</startdate> - # </Card> - # <method>refund</method> - # </CardTxn> - # <TxnDetails> - # <merchantreference>1000001</merchantreference> - # <amount currency="GBP">95.99</amount> - # </TxnDetails> - # </Transaction> - # </Request> - def build_refund_request(money, credit_card, options) + def build_credit_request(money, credit_card, options) xml = Builder::XmlMarkup.new :indent => 2 xml.instruct! - xml.tag! :Request do + xml.tag! :Request, :version => '2' do add_authentication(xml) xml.tag! :Transaction do xml.tag! :CardTxn do xml.tag! :method, REFUND_TYPE add_credit_card(xml, credit_card, options[:billing_address]) @@ -434,36 +192,17 @@ end end xml.target! end - - # Adds the authentication element to the passed builder xml doc - # - # Parameters: - # -xml: Builder document that is being built up - # - # Returns: - # -none: The results is stored in the passed xml document - # def add_authentication(xml) xml.tag! :Authentication do xml.tag! :client, @options[:login] xml.tag! :password, @options[:password] end end - # Add credit_card details to the passed XML Builder doc - # - # Parameters: - # -xml: Builder document that is being built up - # -credit_card: ActiveMerchant::Billing::CreditCard object - # -billing_address: Hash containing all of the billing address details - # - # Returns: - # -none: The results is stored in the passed xml document - # def add_credit_card(xml, credit_card, address) xml.tag! :Card do # DataCash calls the CC number 'pan' @@ -518,48 +257,23 @@ end end end end - # Send the passed data to DataCash for processing - # - # Parameters: - # -request: The XML data that is to be sent to Datacash - # - # Returns: - # - ActiveMerchant::Billing::Response object - # def commit(request) response = parse(ssl_post(test? ? self.test_url : self.live_url, request)) - Response.new(response[:status] == DATACASH_SUCCESS, response[:reason], response, + Response.new(response[:status] == '1', response[:reason], response, :test => test?, :authorization => "#{response[:datacash_reference]};#{response[:authcode]};#{response[:ca_reference]}" ) end - # Returns a date string in the format Datacash expects - # - # Parameters: - # -month: integer, the month - # -year: integer, the year - # - # Returns: - # -String: date in MM/YY format - # def format_date(month, year) "#{format(month,:two_digits)}/#{format(year, :two_digits)}" end - # Parse the datacash response and create a Response object - # - # Parameters: - # -body: The XML returned from Datacash - # - # Returns: - # -a hash with all of the values returned in the Datacash XML response - # def parse(body) response = {} xml = REXML::Document.new(body) root = REXML::XPath.first(xml, "//Response") @@ -569,17 +283,9 @@ end response end - # Parse an xml element - # - # Parameters: - # -response: The hash that the values are being returned in - # -node: The node that is currently being read - # - # Returns: - # - none (results are stored in the passed hash) def parse_element(response, node) if node.has_elements? node.elements.each{|e| parse_element(response, e) } else response[node.name.underscore.to_sym] = node.text