lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb
require 'rexml/document'
require 'digest/md5'
require 'active_merchant/billing/gateways/quickpay/quickpay_common'
module ActiveMerchant #:nodoc:
module Billing #:nodoc:
class QuickpayV4to7Gateway < Gateway
include QuickpayCommon
self.live_url = self.test_url = 'https://secure.quickpay.dk/api'
APPROVED = '000'
# The login is the QuickpayId
# The password is the md5checkword from the Quickpay manager
# To use the API-key from the Quickpay manager, specify :api-key
# Using the API-key, requires that you use version 4+. Specify :version => 4/5/6/7 in options.
def initialize(options = {})
requires!(options, :login, :password)
@protocol = options.delete(:version) || 7 # default to protocol version 7
super
end
def authorize(money, credit_card_or_reference, options = {})
post = {}
action = recurring_or_authorize(credit_card_or_reference)
add_amount(post, money, options)
add_invoice(post, options)
add_creditcard_or_reference(post, credit_card_or_reference, options)
add_autocapture(post, false)
add_fraud_parameters(post, options) if action.eql?(:authorize)
add_testmode(post)
commit(action, post)
end
def purchase(money, credit_card_or_reference, options = {})
post = {}
action = recurring_or_authorize(credit_card_or_reference)
add_amount(post, money, options)
add_creditcard_or_reference(post, credit_card_or_reference, options)
add_invoice(post, options)
add_fraud_parameters(post, options) if action.eql?(:authorize)
add_autocapture(post, true)
commit(action, post)
end
def capture(money, authorization, options = {})
post = {}
add_finalize(post, options)
add_reference(post, authorization)
add_amount_without_currency(post, money)
commit(:capture, post)
end
def void(identification, options = {})
post = {}
add_reference(post, identification)
commit(:cancel, post)
end
def refund(money, identification, options = {})
post = {}
add_amount_without_currency(post, money)
add_reference(post, identification)
commit(:refund, post)
end
def credit(money, identification, options = {})
ActiveMerchant.deprecated CREDIT_DEPRECATION_MESSAGE
refund(money, identification, options)
end
def store(creditcard, options = {})
post = {}
add_creditcard(post, creditcard, options)
add_amount(post, 0, options) if @protocol >= 7
add_invoice(post, options)
add_description(post, options)
add_fraud_parameters(post, options)
add_testmode(post)
commit(:subscribe, post)
end
private
def add_amount(post, money, options = {})
post[:amount] = amount(money)
post[:currency] = options[:currency] || currency(money)
end
def add_amount_without_currency(post, money, options = {})
post[:amount] = amount(money)
end
def add_invoice(post, options)
post[:ordernumber] = format_order_number(options[:order_id])
end
def add_creditcard(post, credit_card, options)
post[:cardnumber] = credit_card.number
post[:cvd] = credit_card.verification_value
post[:expirationdate] = expdate(credit_card)
post[:cardtypelock] = options[:cardtypelock] unless options[:cardtypelock].blank?
post[:acquirers] = options[:acquirers] unless options[:acquirers].blank?
end
def add_reference(post, identification)
post[:transaction] = identification
end
def add_creditcard_or_reference(post, credit_card_or_reference, options)
if credit_card_or_reference.is_a?(String)
add_reference(post, credit_card_or_reference)
else
add_creditcard(post, credit_card_or_reference, options)
end
end
def add_autocapture(post, autocapture)
post[:autocapture] = autocapture ? 1 : 0
end
def recurring_or_authorize(credit_card_or_reference)
credit_card_or_reference.is_a?(String) ? :recurring : :authorize
end
def add_description(post, options)
post[:description] = options[:description] || 'Description'
end
def add_testmode(post)
return if post[:transaction].present?
post[:testmode] = test? ? '1' : '0'
end
def add_fraud_parameters(post, options)
if @protocol >= 4
post[:fraud_remote_addr] = options[:ip] if options[:ip]
post[:fraud_http_accept] = options[:fraud_http_accept] if options[:fraud_http_accept]
post[:fraud_http_accept_language] = options[:fraud_http_accept_language] if options[:fraud_http_accept_language]
post[:fraud_http_accept_encoding] = options[:fraud_http_accept_encoding] if options[:fraud_http_accept_encoding]
post[:fraud_http_accept_charset] = options[:fraud_http_accept_charset] if options[:fraud_http_accept_charset]
post[:fraud_http_referer] = options[:fraud_http_referer] if options[:fraud_http_referer]
post[:fraud_http_user_agent] = options[:fraud_http_user_agent] if options[:fraud_http_user_agent]
end
end
def add_finalize(post, options)
post[:finalize] = options[:finalize] ? '1' : '0'
end
def commit(action, params)
response = parse(ssl_post(self.live_url, post_data(action, params)))
Response.new(
successful?(response),
message_from(response),
response,
test: test?,
authorization: response[:transaction]
)
end
def successful?(response)
response[:qpstat] == APPROVED
end
def parse(data)
response = {}
doc = REXML::Document.new(data)
doc.root.elements.each do |element|
response[element.name.to_sym] = element.text
end
response
end
def message_from(response)
response[:qpstatmsg].to_s
end
def post_data(action, params = {})
params[:protocol] = @protocol
params[:msgtype] = action.to_s
params[:merchant] = @options[:login]
params[:apikey] = @options[:apikey] if @options[:apikey]
params[:md5check] = generate_check_hash(action, params)
params.collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join('&')
end
def generate_check_hash(action, params)
string = MD5_CHECK_FIELDS[@protocol][action].collect do |key|
params[key.to_sym]
end.join('')
# Add the md5checkword
string << @options[:password].to_s
Digest::MD5.hexdigest(string)
end
def expdate(credit_card)
year = format(credit_card.year, :two_digits)
month = format(credit_card.month, :two_digits)
"#{year}#{month}"
end
# Limited to 20 digits max
def format_order_number(number)
number.to_s.gsub(/[^\w]/, '').rjust(4, '0')[0...20]
end
end
end
end