module ActiveMerchant #:nodoc: module Billing #:nodoc: class PayJunctionV2Gateway < Gateway self.display_name = "PayJunction" self.homepage_url = "https://www.payjunction.com/" self.test_url = "https://api.payjunctionlabs.com/transactions" self.live_url = "https://api.payjunction.com/transactions" self.supported_countries = ["US"] self.default_currency = "USD" self.money_format = :dollars self.supported_cardtypes = [:visa, :master, :american_express, :discover] def initialize(options={}) requires!(options, :api_login, :api_password, :api_key) super end def purchase(amount, payment_method, options={}) post = {} add_invoice(post, amount, options) add_payment_method(post, payment_method) commit("purchase", post) end def authorize(amount, payment_method, options={}) post = {} post[:status] = "HOLD" add_invoice(post, amount, options) add_payment_method(post, payment_method) commit("authorize", post) end def capture(amount, authorization, options={}) post = {} post[:status] = "CAPTURE" post[:transactionId] = authorization add_invoice(post, amount, options) commit("capture", post) end def void(authorization, options={}) post = {} post[:status] = "VOID" post[:transactionId] = authorization commit("void", post) end def refund(amount, authorization, options={}) post = {} post[:action] = "REFUND" post[:transactionId] = authorization add_invoice(post, amount, options) commit("refund", post) end def credit(amount, payment_method, options={}) post = {} post[:action] = "REFUND" add_invoice(post, amount, options) add_payment_method(post, payment_method) commit("credit", 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 store(payment_method, options = {}) verify(payment_method, options) end def supports_scrubbing? true end def scrub(transcript) transcript. gsub(%r((Authorization: Basic )\w+), '\1[FILTERED]'). gsub(%r((X-Pj-Application-Key: )[\w-]+), '\1[FILTERED]'). gsub(%r((cardNumber=)\d+), '\1[FILTERED]'). gsub(%r((cardCvv=)\d+), '\1[FILTERED]') end private def add_invoice(post, money, options) post[:amountBase] = amount(money) if money post[:invoiceNumber] = options[:order_id] if options[:order_id] end def add_payment_method(post, payment_method) if payment_method.is_a? Integer post[:transactionId] = payment_method else post[:cardNumber] = payment_method.number post[:cardExpMonth] = format(payment_method.month, :two_digits) post[:cardExpYear] = format(payment_method.year, :four_digits) post[:cardCvv] = payment_method.verification_value end end def commit(action, params) response = begin parse(ssl_invoke(action, params)) rescue ResponseError => e parse(e.response.body) end success = success_from(response) Response.new( success, message_from(response), response, authorization: success ? authorization_from(response) : nil, error_code: success ? nil : error_from(response), test: test? ) end def ssl_invoke(action, params) if ["purchase", "authorize", "refund", "credit"].include?(action) ssl_post(url(), post_data(params), headers) else ssl_request(:put, url(params), post_data(params), headers) end end def headers { "Authorization" => "Basic " + Base64.encode64("#{@options[:api_login]}:#{@options[:api_password]}").strip, "Content-Type" => "application/x-www-form-urlencoded;charset=UTF-8", "Accept" => "application/json", "X-PJ-Application-Key" => "#{@options[:api_key]}" } end def post_data(params) params.map {|k, v| "#{k}=#{CGI.escape(v.to_s)}"}.join('&') end def url(params={}) test? ? "#{test_url}/#{params[:transactionId]}" : "#{live_url}/#{params[:transactionId]}" end def parse(body) begin JSON.parse(body) rescue JSON::ParserError message = "Invalid JSON response received from PayJunctionV2Gateway. Please contact PayJunctionV2Gateway if you continue to receive this message." message += " (The raw response returned by the API was #{body.inspect})" { "errors" => [{ "message" => message }] } end end def success_from(response) return response["response"]["approved"] if response["response"] false end def message_from(response) return response["response"]["message"] if response["response"] response["errors"].inject(""){ |message,error| error["message"] + "|" + message } if response["errors"] end def authorization_from(response) response["transactionId"] end def error_from(response) response["response"]["code"] if response["response"] end end end end