Module: Azericard::Request

Defined in:
lib/azericard/request.rb

Class Method Summary collapse

Class Method Details

.generate_mac(text_to_sign) ⇒ Object

Generates MAC – Message Authentication Code



110
111
112
# File 'lib/azericard/request.rb', line 110

def self.generate_mac(text_to_sign)
  OpenSSL::HMAC.hexdigest('sha1', hex2bin(Azericard.secret_key), text_to_sign)
end

.hex2bin(str) ⇒ Object

Decodes a hexadecimally encoded binary string



115
116
117
# File 'lib/azericard/request.rb', line 115

def self.hex2bin(str)
  str.scan(/../).map { |x| x.to_i(16).chr }.join
end

.options_for_request(options = {}) ⇒ Azericard::AzericardOptions

Parameters:

  • options (Hash) (defaults to: {})

Returns:



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/azericard/request.rb', line 53

def self.options_for_request(options={})
  nonce      = options.fetch :nonce      , SecureRandom.hex(8)
  timestamp  = options.fetch :timestamp  , Time.now.utc.strftime('%Y%m%d%H%M%S')
  merch_name = options.fetch :merch_name , Azericard.merchant_name
  merch_url  = options.fetch :merch_url  , Azericard.merchant_url
  terminal   = options.fetch :terminal   , Azericard.terminal.to_s
  email      = options.fetch :email      , Azericard.merchant_email
  country    = options.fetch :country    , Azericard.country_code
  merch_gmt  = options.fetch :merch_gmt  , Azericard.gmt_offset

  desc = backref = rrn = intref = nil

  # Order total amount in float format with decimal point separator
  amount = options.fetch(:amount).to_f.to_s

  # Order currency: 3-character currency code
  currency = options.fetch(:currency)

  # Merchant order ID
  order = options.fetch(:order).to_s

  # Operation type
  #
  # 0 - auth
  # 21 - checkout
  # 24 - reversal
  tr_type = options.fetch(:tr_type).to_s

  if tr_type == '0'
    # Order description
    desc = options.fetch(:desc).to_s

    # Merchant URL for posting authorization result
    backref = options.fetch(:backref)

    text_to_sign = "#{amount.size}#{amount}#{currency.size}#{currency}#{order.size}#{order}" \
      "#{desc.size}#{desc}#{merch_name.size}#{merch_name}#{merch_url.size}#{merch_url}" \
      "#{terminal.size}#{terminal}#{email.size}#{email}#{tr_type.size}#{tr_type}#{country.size}#{country}" \
      "#{merch_gmt.size}#{merch_gmt}#{timestamp.size}#{timestamp}#{nonce.size}#{nonce}#{backref.size}#{backref}"
  elsif tr_type == '21' || tr_type == '24'
    # Merchant bank's retrieval reference number
    rrn = options.fetch(:rrn).to_s

    # E-Commerce gateway internal reference number
    intref = options.fetch(:intref)

    text_to_sign = "#{order.size}#{order}#{amount.size}#{amount}#{currency.size}#{currency}" \
      "#{rrn.size}#{rrn}#{intref.size}#{intref}#{tr_type.size}#{tr_type}#{terminal.size}#{terminal}" \
      "#{timestamp.size}#{timestamp}#{nonce.size}#{nonce}"
  end

  AzericardOptions.new(nonce, timestamp, amount, currency, order, tr_type, desc, backref, rrn, intref, text_to_sign)
rescue KeyError => e
  e.message
end

.process(request_options) ⇒ true

Parameters:

Returns:

  • (true)

Raises:



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/azericard/request.rb', line 10

def self.process(request_options)
  p_sign = generate_mac(request_options.text_to_sign)

  request = Typhoeus::Request.new(
    Azericard.endpoint,
    method: :post,
    followlocation: true,
    ssl_verifypeer: false,
    ssl_verifyhost: 2,
    sslversion: 'tlsv1.2',
    ssl_cipher_list: 'ECDHE-RSA-AES256-GCM-SHA384',
    headers: {
      "User-Agent" => Azericard.user_agent
    },
    body: {
      "AMOUNT"    => request_options.amount,
      "CURRENCY"  => request_options.currency,
      "ORDER"     => request_options.order,
      "RRN"       => request_options.rrn,
      "INT_REF"   => request_options.intref,
      "TERMINAL"  => Azericard.terminal,
      "TRTYPE"    => request_options.tr_type,
      "TIMESTAMP" => request_options.timestamp,
      "NONCE"     => request_options.nonce,
      "P_SIGN"    => p_sign
    }
  )

  response = request.run

  if response.success?
    if response.body == '0'
      true
    else
      raise AzericardResponseError, "Azericard responded with: #{response.body[0..4]}"
    end
  else
    raise HTTPResponseError, "Azericard request failed: #{response.code}"
  end
end