lib/active_merchant/billing/gateways/dibs.rb
module ActiveMerchant #:nodoc:
module Billing #:nodoc:
class DibsGateway < Gateway
self.display_name = 'DIBS'
self.homepage_url = 'http://www.dibspayment.com/'
self.live_url = 'https://api.dibspayment.com/merchant/v1/JSON/Transaction/'
self.supported_countries = %w[US FI NO SE GB]
self.default_currency = 'USD'
self.money_format = :cents
self.supported_cardtypes = %i[visa master american_express discover]
def initialize(options = {})
requires!(options, :merchant_id, :secret_key)
super
end
def purchase(amount, payment_method, options = {})
MultiResponse.run(false) do |r|
r.process { authorize(amount, payment_method, options) }
r.process { capture(amount, r.authorization, options) }
end
end
def authorize(amount, payment_method, options = {})
post = {}
add_amount(post, amount)
add_invoice(post, amount, options)
if payment_method.respond_to?(:number)
add_payment_method(post, payment_method, options)
commit(:authorize, post)
else
add_ticket_id(post, payment_method)
commit(:authorize_ticket, post)
end
end
def capture(amount, authorization, options = {})
post = {}
add_amount(post, amount)
add_reference(post, authorization)
commit(:capture, post)
end
def void(authorization, options = {})
post = {}
add_reference(post, authorization)
commit(:void, post)
end
def refund(amount, authorization, options = {})
post = {}
add_amount(post, amount)
add_reference(post, authorization)
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 store(payment_method, options = {})
post = {}
add_invoice(post, 0, options)
add_payment_method(post, payment_method, options)
commit(:store, post)
end
def supports_scrubbing?
true
end
def scrub(transcript)
transcript.
gsub(%r(("cardNumber\\?":\\?")[^"]*)i, '\1[FILTERED]').
gsub(%r(("cvc\\?":\\?")[^"]*)i, '\1[FILTERED]')
end
private
CURRENCY_CODES = Hash.new { |_h, k| raise ArgumentError.new("Unsupported currency: #{k}") }
CURRENCY_CODES['USD'] = '840'
CURRENCY_CODES['DKK'] = '208'
CURRENCY_CODES['NOK'] = '578'
CURRENCY_CODES['SEK'] = '752'
CURRENCY_CODES['GBP'] = '826'
CURRENCY_CODES['EUR'] = '978'
def add_invoice(post, money, options)
post[:orderId] = options[:order_id] || generate_unique_id
post[:currency] = CURRENCY_CODES[options[:currency] || currency(money)]
end
def add_ticket_id(post, payment_method)
post[:ticketId] = payment_method
end
def add_payment_method(post, payment_method, options)
post[:cardNumber] = payment_method.number
post[:cvc] = payment_method.verification_value if payment_method.verification_value
post[:expYear] = format(payment_method.year, :two_digits)
post[:expMonth] = payment_method.month
post[:clientIp] = options[:ip] || '127.0.0.1'
post[:test] = true if test?
end
def add_reference(post, authorization)
post[:transactionId] = authorization
end
def add_amount(post, amount)
post[:amount] = amount
end
ACTIONS = {
authorize: 'AuthorizeCard',
authorize_ticket: 'AuthorizeTicket',
capture: 'CaptureTransaction',
void: 'CancelTransaction',
refund: 'RefundTransaction',
store: 'CreateTicket'
}
def commit(action, post)
post[:merchantId] = @options[:merchant_id]
data = build_request(post)
raw = parse(ssl_post(url(action), "request=#{data}", headers))
succeeded = success_from(raw)
Response.new(
succeeded,
message_from(succeeded, raw),
raw,
authorization: authorization_from(post, raw),
test: test?
)
rescue JSON::ParserError
unparsable_response(raw)
end
def headers
{
'Content-Type' => 'application/x-www-form-urlencoded'
}
end
def build_request(post)
add_hmac(post)
post.to_json
end
def add_hmac(post)
data = post.sort.collect { |key, value| "#{key}=#{value}" }.join('&')
digest = OpenSSL::Digest.new('sha256')
key = [@options[:secret_key]].pack('H*')
post[:MAC] = OpenSSL::HMAC.hexdigest(digest, key, data)
end
def url(action)
live_url + ACTIONS[action]
end
def parse(body)
JSON.parse(body)
end
def success_from(raw_response)
raw_response['status'] == 'ACCEPT'
end
def message_from(succeeded, response)
if succeeded
'Succeeded'
else
response['status'] + ': ' + response['declineReason'] || 'Unable to read error message'
end
end
def authorization_from(request, response)
response['transactionId'] || response['ticketId'] || request[:transactionId]
end
def unparsable_response(raw_response)
message = 'Invalid JSON response received from Dibs. Please contact Dibs 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
end
end
end