lib/active_merchant/billing/gateways/redsys.rb in activemerchant-1.79.2 vs lib/active_merchant/billing/gateways/redsys.rb in activemerchant-1.80.0
- old
+ new
@@ -33,59 +33,59 @@
# specify the key/value :signature_algorithm => "sha256" to use the
# SHA256 method. Otherwise it will default to using the SHA1.
#
#
class RedsysGateway < Gateway
- self.live_url = "https://sis.sermepa.es/sis/operaciones"
- self.test_url = "https://sis-t.redsys.es:25443/sis/operaciones"
+ self.live_url = 'https://sis.sermepa.es/sis/operaciones'
+ self.test_url = 'https://sis-t.redsys.es:25443/sis/operaciones'
self.supported_countries = ['ES']
self.default_currency = 'EUR'
self.money_format = :cents
# Not all card types may be activated by the bank!
self.supported_cardtypes = [:visa, :master, :american_express, :jcb, :diners_club]
- self.homepage_url = "http://www.redsys.es/"
- self.display_name = "Redsys"
+ self.homepage_url = 'http://www.redsys.es/'
+ self.display_name = 'Redsys'
CURRENCY_CODES = {
- "AED" => '784',
- "ARS" => '32',
- "AUD" => '36',
- "BRL" => '986',
- "BOB" => '68',
- "CAD" => '124',
- "CHF" => '756',
- "CLP" => '152',
- "CNY" => '156',
- "COP" => '170',
- "CRC" => '188',
- "CZK" => '203',
- "DKK" => '208',
- "DOP" => '214',
- "EUR" => '978',
- "GBP" => '826',
- "GTQ" => '320',
- "HUF" => '348',
- "IDR" => '360',
- "INR" => '356',
- "JPY" => '392',
- "KRW" => '410',
- "MYR" => '458',
- "MXN" => '484',
- "NOK" => '578',
- "NZD" => '554',
- "PEN" => '604',
- "PLN" => '985',
- "RUB" => '643',
- "SAR" => '682',
- "SEK" => '752',
- "SGD" => '702',
- "THB" => '764',
- "TWD" => '901',
- "USD" => '840',
- "UYU" => '858'
+ 'AED' => '784',
+ 'ARS' => '32',
+ 'AUD' => '36',
+ 'BRL' => '986',
+ 'BOB' => '68',
+ 'CAD' => '124',
+ 'CHF' => '756',
+ 'CLP' => '152',
+ 'CNY' => '156',
+ 'COP' => '170',
+ 'CRC' => '188',
+ 'CZK' => '203',
+ 'DKK' => '208',
+ 'DOP' => '214',
+ 'EUR' => '978',
+ 'GBP' => '826',
+ 'GTQ' => '320',
+ 'HUF' => '348',
+ 'IDR' => '360',
+ 'INR' => '356',
+ 'JPY' => '392',
+ 'KRW' => '410',
+ 'MYR' => '458',
+ 'MXN' => '484',
+ 'NOK' => '578',
+ 'NZD' => '554',
+ 'PEN' => '604',
+ 'PLN' => '985',
+ 'RUB' => '643',
+ 'SAR' => '682',
+ 'SEK' => '752',
+ 'SGD' => '702',
+ 'THB' => '764',
+ 'TWD' => '901',
+ 'USD' => '840',
+ 'UYU' => '858'
}
# The set of supported transactions for this gateway.
# More operations are supported by the gateway itself, but
# are not supported in this library.
@@ -99,76 +99,76 @@
# These are the text meanings sent back by the acquirer when
# a card has been rejected. Syntax or general request errors
# are not covered here.
RESPONSE_TEXTS = {
- 0 => "Transaction Approved",
- 400 => "Cancellation Accepted",
- 481 => "Cancellation Accepted",
- 500 => "Reconciliation Accepted",
- 900 => "Refund / Confirmation approved",
+ 0 => 'Transaction Approved',
+ 400 => 'Cancellation Accepted',
+ 481 => 'Cancellation Accepted',
+ 500 => 'Reconciliation Accepted',
+ 900 => 'Refund / Confirmation approved',
- 101 => "Card expired",
- 102 => "Card blocked temporarily or under susciption of fraud",
- 104 => "Transaction not permitted",
- 107 => "Contact the card issuer",
- 109 => "Invalid identification by merchant or POS terminal",
- 110 => "Invalid amount",
- 114 => "Card cannot be used to the requested transaction",
- 116 => "Insufficient credit",
- 118 => "Non-registered card",
- 125 => "Card not effective",
- 129 => "CVV2/CVC2 Error",
- 167 => "Contact the card issuer: suspected fraud",
- 180 => "Card out of service",
- 181 => "Card with credit or debit restrictions",
- 182 => "Card with credit or debit restrictions",
- 184 => "Authentication error",
- 190 => "Refusal with no specific reason",
- 191 => "Expiry date incorrect",
+ 101 => 'Card expired',
+ 102 => 'Card blocked temporarily or under susciption of fraud',
+ 104 => 'Transaction not permitted',
+ 107 => 'Contact the card issuer',
+ 109 => 'Invalid identification by merchant or POS terminal',
+ 110 => 'Invalid amount',
+ 114 => 'Card cannot be used to the requested transaction',
+ 116 => 'Insufficient credit',
+ 118 => 'Non-registered card',
+ 125 => 'Card not effective',
+ 129 => 'CVV2/CVC2 Error',
+ 167 => 'Contact the card issuer: suspected fraud',
+ 180 => 'Card out of service',
+ 181 => 'Card with credit or debit restrictions',
+ 182 => 'Card with credit or debit restrictions',
+ 184 => 'Authentication error',
+ 190 => 'Refusal with no specific reason',
+ 191 => 'Expiry date incorrect',
- 201 => "Card expired",
- 202 => "Card blocked temporarily or under suspicion of fraud",
- 204 => "Transaction not permitted",
- 207 => "Contact the card issuer",
- 208 => "Lost or stolen card",
- 209 => "Lost or stolen card",
- 280 => "CVV2/CVC2 Error",
- 290 => "Declined with no specific reason",
+ 201 => 'Card expired',
+ 202 => 'Card blocked temporarily or under suspicion of fraud',
+ 204 => 'Transaction not permitted',
+ 207 => 'Contact the card issuer',
+ 208 => 'Lost or stolen card',
+ 209 => 'Lost or stolen card',
+ 280 => 'CVV2/CVC2 Error',
+ 290 => 'Declined with no specific reason',
- 480 => "Original transaction not located, or time-out exceeded",
- 501 => "Original transaction not located, or time-out exceeded",
- 502 => "Original transaction not located, or time-out exceeded",
- 503 => "Original transaction not located, or time-out exceeded",
+ 480 => 'Original transaction not located, or time-out exceeded',
+ 501 => 'Original transaction not located, or time-out exceeded',
+ 502 => 'Original transaction not located, or time-out exceeded',
+ 503 => 'Original transaction not located, or time-out exceeded',
- 904 => "Merchant not registered at FUC",
- 909 => "System error",
- 912 => "Issuer not available",
- 913 => "Duplicate transmission",
- 916 => "Amount too low",
- 928 => "Time-out exceeded",
- 940 => "Transaction cancelled previously",
- 941 => "Authorization operation already cancelled",
- 942 => "Original authorization declined",
- 943 => "Different details from origin transaction",
- 944 => "Session error",
- 945 => "Duplicate transmission",
- 946 => "Cancellation of transaction while in progress",
- 947 => "Duplicate tranmission while in progress",
- 949 => "POS Inoperative",
- 950 => "Refund not possible",
- 9064 => "Card number incorrect",
- 9078 => "No payment method available",
- 9093 => "Non-existent card",
- 9218 => "Recursive transaction in bad gateway",
- 9253 => "Check-digit incorrect",
- 9256 => "Preauth not allowed for merchant",
- 9257 => "Preauth not allowed for card",
- 9261 => "Operating limit exceeded",
- 9912 => "Issuer not available",
- 9913 => "Confirmation error",
- 9914 => "KO Confirmation"
+ 904 => 'Merchant not registered at FUC',
+ 909 => 'System error',
+ 912 => 'Issuer not available',
+ 913 => 'Duplicate transmission',
+ 916 => 'Amount too low',
+ 928 => 'Time-out exceeded',
+ 940 => 'Transaction cancelled previously',
+ 941 => 'Authorization operation already cancelled',
+ 942 => 'Original authorization declined',
+ 943 => 'Different details from origin transaction',
+ 944 => 'Session error',
+ 945 => 'Duplicate transmission',
+ 946 => 'Cancellation of transaction while in progress',
+ 947 => 'Duplicate tranmission while in progress',
+ 949 => 'POS Inoperative',
+ 950 => 'Refund not possible',
+ 9064 => 'Card number incorrect',
+ 9078 => 'No payment method available',
+ 9093 => 'Non-existent card',
+ 9218 => 'Recursive transaction in bad gateway',
+ 9253 => 'Check-digit incorrect',
+ 9256 => 'Preauth not allowed for merchant',
+ 9257 => 'Preauth not allowed for card',
+ 9261 => 'Operating limit exceeded',
+ 9912 => 'Issuer not available',
+ 9913 => 'Confirmation error',
+ 9914 => 'KO Confirmation'
}
# Creates a new instance
#
# Redsys requires a login and secret_key, and optionally also accepts a
@@ -182,11 +182,11 @@
# * <tt>:test</tt> -- +true+ or +false+. Defaults to +false+. (OPTIONAL)
# * <tt>:signature_algorithm</tt> -- +"sha256"+ Defaults to +"sha1"+. (OPTIONAL)
def initialize(options = {})
requires!(options, :login, :secret_key)
options[:terminal] ||= 1
- options[:signature_algorithm] ||= "sha1"
+ options[:signature_algorithm] ||= 'sha1'
super
end
def purchase(money, payment, options = {})
requires!(options, :order_id)
@@ -297,12 +297,12 @@
def add_payment(data, card)
if card.is_a?(String)
data[:credit_card_token] = card
else
name = [card.first_name, card.last_name].join(' ').slice(0, 60)
- year = sprintf("%.4i", card.year)
- month = sprintf("%.2i", card.month)
+ year = sprintf('%.4i', card.year)
+ month = sprintf('%.2i', card.month)
data[:card] = {
:name => name,
:pan => card.number,
:date => "#{year[2..3]}#{month}",
:cvv => card.verification_value
@@ -393,33 +393,34 @@
xml.DS_MERCHANT_EXPIRYDATE data[:card][:date]
xml.DS_MERCHANT_CVV2 data[:card][:cvv]
xml.DS_MERCHANT_IDENTIFIER 'REQUIRED' if data[:store_in_vault]
elsif data[:credit_card_token]
xml.DS_MERCHANT_IDENTIFIER data[:credit_card_token]
+ xml.DS_MERCHANT_DIRECTPAYMENT 'true'
end
end
end
def parse(data)
params = {}
success = false
- message = ""
+ message = ''
options = @options.merge(:test => test?)
xml = Nokogiri::XML(data)
- code = xml.xpath("//RETORNOXML/CODIGO").text
- if code == "0"
- op = xml.xpath("//RETORNOXML/OPERACION")
+ code = xml.xpath('//RETORNOXML/CODIGO').text
+ if code == '0'
+ op = xml.xpath('//RETORNOXML/OPERACION')
op.children.each do |element|
params[element.name.downcase.to_sym] = element.text
end
if validate_signature(params)
message = response_text(params[:ds_response])
options[:authorization] = build_authorization(params)
success = is_success_response?(params[:ds_response])
else
- message = "Response failed validation check"
+ message = 'Response failed validation check'
end
else
# Some kind of programmer error with the request!
message = "#{code} ERROR"
end
@@ -446,15 +447,15 @@
data[:ds_signature].to_s.downcase == sig
end
end
def build_authorization(params)
- [params[:ds_order], params[:ds_amount], params[:ds_currency]].join("|")
+ [params[:ds_order], params[:ds_amount], params[:ds_currency]].join('|')
end
def split_authorization(authorization)
- order_id, amount, currency = authorization.split("|")
+ order_id, amount, currency = authorization.split('|')
[order_id, amount.to_i, currency]
end
def currency_code(currency)
return currency if currency =~ /^\d+$/
@@ -467,11 +468,11 @@
end
def response_text(code)
code = code.to_i
code = 0 if code < 100
- RESPONSE_TEXTS[code] || "Unkown code, please check in manual"
+ RESPONSE_TEXTS[code] || 'Unkown code, please check in manual'
end
def is_success_response?(code)
(code.to_i < 100) || [400, 481, 500, 900].include?(code.to_i)
end
@@ -479,16 +480,16 @@
def clean_order_id(order_id)
cleansed = order_id.gsub(/[^\da-zA-Z]/, '')
if cleansed =~ /^\d{4}/
cleansed[0..11]
else
- "%04d%s" % [rand(0..9999), cleansed[0...8]]
+ '%04d%s' % [rand(0..9999), cleansed[0...8]]
end
end
def sha256_authentication?
- @options[:signature_algorithm] == "sha256"
+ @options[:signature_algorithm] == 'sha256'
end
def sign_request(xml_request_string, order_id)
key = encrypt(@options[:secret_key], order_id)
Base64.strict_encode64(mac256(key, xml_request_string))
@@ -512,11 +513,17 @@
def mac256(key, data)
OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), key, data)
end
def xml_signed_fields(data)
- data[:ds_amount] + data[:ds_order] + data[:ds_merchantcode] + data[:ds_currency] +
- data[:ds_response] + data[:ds_transactiontype] + data[:ds_securepayment]
+ xml_signed_fields = data[:ds_amount] + data[:ds_order] + data[:ds_merchantcode] +
+ data[:ds_currency] + data[:ds_response]
+
+ if data[:ds_cardnumber]
+ xml_signed_fields += data[:ds_cardnumber]
+ end
+
+ xml_signed_fields += data[:ds_transactiontype] + data[:ds_securepayment]
end
def get_key(order_id)
encrypt(@options[:secret_key], order_id)
end