OnlinetoursGit/qiwi-pay

View on GitHub
lib/qiwi-pay/confirmation.rb

Summary

Maintainability
A
0 mins
Test Coverage
# frozen_string_literal: true

module QiwiPay
  # Qiwi payment confirmation (callback)
  #
  # @note Confirmation parameters list
  #   Параметр          Тип данных  Описание
  #   txn_id            integer     Идентификатор транзакции
  #   txn_status        integer     Статус транзакции
  #   txn_type          integer     Тип транзакции
  #   txn_date          timestamp   Дата транзакции в формате ISO8601 с временной зоной
  #   error_code        integer     Код ошибки работы системы
  #   pan               string(19)  Номер карты Покупателя в формате 411111XXXXXX1111
  #   amount            decimal     Сумма списания
  #   currency          integer     Валюта суммы списания в цифровом формате согласно ISO 4217
  #   auth_code         string(6)   Код авторизации
  #   eci               string(2)   Индикатор E-Commerce операции
  #   card_name         string(64)  Имя Покупателя, как указано на карте (латинские буквы)
  #   card_bank         string(64)  Банк-эмитент карты
  #   order_id          string(256) Уникальный номер заказа в системе ТСП
  #   ip                string(15)  IP-адрес Покупателя
  #   email             string(64)  E-mail Покупателя
  #   country           string(3)   Страна Покупателя в формате 3-х буквенных кодов согласно ISO 3166-1
  #   city              string(64)  Город местонахождения Покупателя
  #   region            string(6)   Регион страны формате геокодов согласно ISO 3166-2
  #   address           string(64)  Адрес местонахождения Покупателя
  #   phone             string(15)  Контактный телефон Покупателя
  #   cf1               string(256) Поля для ввода произвольной информации, дополняющей данные по операции. Например - описание услуг ТСП.
  #   cf2               string(256) Поля для ввода произвольной информации, дополняющей данные по операции. Например - описание услуг ТСП.
  #   cf3               string(256) Поля для ввода произвольной информации, дополняющей данные по операции. Например - описание услуг ТСП.
  #   cf4               string(256) Поля для ввода произвольной информации, дополняющей данные по операции. Например - описание услуг ТСП.
  #   cf5               string(256) Поля для ввода произвольной информации, дополняющей данные по операции. Например - описание услуг ТСП.
  #   product_name      string(256) Описание услуги которую получает Плательщик.
  #   card_token        string(40)  Токен карты (если функционал токенизации включен для данного сайта)
  #   card_token_expire timestamp   Срок истечения токена карты (если функционал токенизации включен для данного сайта)
  #   sign              string(64)  Контрольная сумма переданных параметров. Контрольная сумма передается в верхнем регистре.
  #   cheque            string      URL чека
  #   cheque_link       string      URL чека
  #   request_id
  #   issuer_name
  #   issuer_country
  #
  # @note {timestamp} data type is represented by string in format {YYYY-MM-DDThh:mm:ss±hh:mm}
  class Confirmation
    include QiwiPay::MessagesForCodes

    # Available confirmation parameters
    ALLOWED_PARAMS = %i[
      txn_id txn_status txn_type txn_date error_code pan
      amount currency auth_code eci card_name card_bank
      order_id ip email country city region address phone
      cf1 cf2 cf3 cf4 cf5
      product_name
      card_token card_token_expire
      sign
      cheque cheque_link
      request_id
      issuer_name issuer_country
    ].freeze

    # Parameters of integer type
    INTEGER_PARAMS = %i[
      txn_id
      txn_status
      txn_type
      error_code
      currency
    ]

    # Request params used to calculate signature
    SIGN_PARAMS = %i[
      txn_id
      txn_status
      txn_type
      error_code
      amount
      currency
      ip
      email
    ].freeze

    # IPs allowed to receive confirmation from
    ALLOWED_IPS = %w[
      91.232.231.36
      79.142.22.81
      79.142.28.154
      195.189.102.81
    ].freeze

    attr_reader(*ALLOWED_PARAMS)
    attr_reader :secret

    # @param crds [Credentials] Api access credentials object
    # @param params [Hash] Request params
    def initialize(crds, params)
      ALLOWED_PARAMS.each do |pname|
        pval = params.fetch(pname, nil) || params.fetch(pname.to_s, nil)
        pval = pval.to_i if INTEGER_PARAMS.include?(pname)
        instance_variable_set "@#{pname}", pval
      end
      @secret = crds.secret
    end

    # Check server IP address validity
    # @param ip [String]
    # @return [Boolean]
    def valid_server_ip?(ip)
      ALLOWED_IPS.include? ip
    end

    # Check confirmation params signature validity
    # @return [Boolean]
    def valid_sign?
      calculated_sign.upcase == sign
    end

    # Check if payment operation was successful (has valid sign and no errors)
    def success?
      valid_sign? && !error?
    end

    # Check if error code present in response
    def error?
      !error_code.zero?
    end

    # Converts confirmation data to hash
    def to_h
      {}.tap do |h|
        ALLOWED_PARAMS.each { |p| h[p] = send(p) }
        h[:txn_status_message] = txn_status_message
        h[:txn_type_message] = txn_type_message
      end
    end

    private

    # Calculates signature for parameters
    def calculated_sign
      params = SIGN_PARAMS.each_with_object({}) do |p, h|
        h[p] = send(p).tap { |v| v ? v.to_s : nil }
      end
      Signature.new(params, @secret).sign.upcase
    end
  end
end