module ActiveMerchant #:nodoc: module Billing #:nodoc: class AlliedWalletGateway < Gateway self.display_name = 'Allied Wallet' self.homepage_url = 'https://www.alliedwallet.com' self.live_url = 'https://api.alliedwallet.com/merchants/' self.supported_countries = ['US'] self.default_currency = 'USD' self.money_format = :dollars self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb, :maestro] def initialize(options={}) requires!(options, :site_id, :merchant_id, :token) super end def purchase(amount, payment_method, options={}) post = {} add_invoice(post, amount, options) add_payment_method(post, payment_method) add_customer_data(post, options) commit(:purchase, post) end def authorize(amount, payment_method, options={}) post = {} add_invoice(post, amount, options) add_payment_method(post, payment_method) add_customer_data(post, options) commit(:authorize, post) end def capture(amount, authorization, options={}) post = {} add_invoice(post, amount, options) add_reference(post, authorization, :capture) add_customer_data(post, options) commit(:capture, post) end def void(authorization, options={}) post = {} add_reference(post, authorization, :void) commit(:void, post) end def refund(amount, authorization, options={}) post = {} add_invoice(post, amount, options) add_reference(post, authorization, :refund) add_amount(post, amount) add_customer_data(post, options) commit(:refund, post) end def verify(credit_card, options={}) MultiResponse.run(:use_first_response) do |r| r.process { authorize(100, credit_card, options) } r.process(:ignore_result) { void(r.authorization, options) } end end def supports_scrubbing? true end def scrub(transcript) transcript. gsub(%r((Authorization: Bearer )[a-zA-Z0-9._-]+)i, '\1[FILTERED]'). gsub(%r(("cardNumber\\?":\\?")[^"]*)i, '\1[FILTERED]'). gsub(%r(("cVVCode\\?":\\?")\d+[^"]*)i, '\1[FILTERED]'). gsub(%r(("cVVCode\\?":)null), '\1[BLANK]'). gsub(%r(("cVVCode\\?":\\?")\\?"), '\1[BLANK]"'). gsub(%r(("cVVCode\\?":\\?")\s+), '\1[BLANK]"') end private def add_amount(post, amount) post[:amount] = amount end def add_invoice(post, money, options) post[:siteId] = @options[:site_id] post[:amount] = amount(money) post[:trackingId] = options[:order_id] post[:currency] = options[:currency] || currency(money) end def add_payment_method(post, payment_method) post[:nameOnCard] = payment_method.name post[:cardNumber] = payment_method.number post[:cVVCode] = payment_method.verification_value post[:expirationYear] = format(payment_method.year, :four_digits) post[:expirationMonth] = format(payment_method.month, :two_digits) end def add_customer_data(post, options) post[:email] = options[:email] || 'unspecified@example.com' post[:iPAddress] = options[:ip] if (billing_address = options[:billing_address]) post[:firstName], post[:lastName] = split_names(billing_address[:name]) post[:addressLine1] = billing_address[:address1] post[:addressLine2] = billing_address[:address2] post[:city] = billing_address[:city] post[:state] = billing_address[:state] post[:countryId] = billing_address[:country] post[:postalCode] = billing_address[:zip] post[:phone] = billing_address[:phone] end end def add_reference(post, authorization, action) transactions = { capture: :authorizetransactionid, void: :authorizeTransactionid, refund: :referencetransactionid, recurring: :saleTransactionid } post[transactions[action]] = authorization end ACTIONS = { purchase: 'SALE', authorize: 'AUTHORIZE', capture: 'CAPTURE', void: 'VOID', refund: 'REFUND' } def commit(action, post) begin raw_response = ssl_post(url(action), post.to_json, headers) response = parse(raw_response) rescue ResponseError => e raise unless(e.response.code.to_s =~ /4\d\d/) response = parse(e.response.body) end succeeded = success_from(response['status']) Response.new( succeeded, message_from(succeeded, response), response, authorization: response['id'], :avs_result => AVSResult.new(code: response['avs_response']), :cvv_result => CVVResult.new(response['cvv2_response']), test: test? ) rescue JSON::ParserError unparsable_response(raw_response) end def unparsable_response(raw_response) message = 'Unparsable response received from Allied Wallet. Please contact Allied Wallet if you continue to receive this message.' message += " (The raw response returned by the API was #{raw_response.inspect})" return Response.new(false, message) end def headers { 'Content-type' => 'application/json', 'Authorization' => 'Bearer ' + @options[:token] } end def url(action) live_url + CGI.escape(@options[:merchant_id]) + '/' + ACTIONS[action] + 'transactions' end def parse(body) JSON.parse(body) end def parse_element(response, node) if node.has_elements? node.elements.each{|element| parse_element(response, element) } else response[node.name.underscore.to_sym] = node.text end end def success_from(response) response == 'Successful' end def message_from(succeeded, response) if succeeded 'Succeeded' else response['message'] || 'Unable to read error message' end end end end end