kount package

kount.client module

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# This file is part of the Kount python sdk project
# https://github.com/Kount/kount-ris-python-sdk
# Copyright (C) 2017 Kount Inc. All Rights Reserved.
"""class Client"""

from __future__ import (absolute_import, unicode_literals,
                        division, print_function)

import logging
import requests

from . import config
from . import request
from . import response
from .version import VERSION
from .config import SDKConfig

__author__ = SDKConfig.SDK_AUTHOR
__version__ = VERSION
__maintainer__ = SDKConfig.SDK_MAINTAINER
__email__ = SDKConfig.MAINTAINER_EMAIL
__status__ = SDKConfig.STATUS


LOG = logging.getLogger('kount.client')


class Client:

    def __init__(self, api_url, api_key,
                 timeout=None,
                 raise_errors=None):
        """
        Client class used to execute Kount request
        :param api_url: endpoint to which the request should be sent
        :param api_key: merchant api key, provided by Kount
        :param timeout: request timeout, if not set the default value
         from SDKConfig will be used
        :param raise_errors: indicates if request validation error should
         be thrown, if not set the default value from SDKConfig will be used
        """
        self.api_url = api_url
        self.api_key = api_key
        conf = config.SDKConfig
        self.timeout = timeout or conf.get_default_timeout()
        LOG.debug("url - %s, len_key - %s", self.api_url, len(self.api_key))

    def process(self, req):

        if not isinstance(req, request.Request):
            raise ValueError("invalid request, %s" % type(request))
        
        res = self._execute(req.params)
        if res:
            return response.Response(res)
        return None

    def _execute(self, params):
        """validate data and request post
        https://pypi.python.org/pypi/requests
        Use simplejson if available.
        if raise_errors==False, the validation errors will not be raised,
        only logged; by default raise_errors=True"""
        if LOG.isEnabledFor(logging.DEBUG):
            for key, param in params.items():
                LOG.debug('%s=%s', key, param)
    
        headers_api = {'X-Kount-Api-Key': self.api_key}

        if self.api_key == "API_KEY":
            raise Exception('Please configure the API Key in settings.py file')

        params['FRMT'] = 'JSON'
        LOG.debug("url=%s, headers=%s, params=%s", self.api_url,
                  headers_api, params)

        req = requests.post(self.api_url,
                            headers=headers_api,
                            data=params,
                            timeout=self.timeout)
        
        try:
            resp = req.json()
        except ValueError as jde:
            LOG.error("ValueError - %s", jde)
            try:
                text_to_json = parse_k_v(req.text)
                LOG.debug("process text: %s", text_to_json)
                return text_to_json
            except ValueError:
                error = "Neither JSON nor String %s" % req.text
                LOG.debug(error)
                raise ValueError(error)
        else:
            LOG.debug("MERC = %s, SESS = %s, SDK ELAPSED = %s ms.",
                      params.get('MERC', None),
                      params.get("SESS", None),
                      req.elapsed.total_seconds())
            return resp


def parse_k_v(text):
    """parse text to dict"""
    return dict(c.split('=', 1) for c in text.split('\n'))

kount.inquiry module

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# This file is part of the Kount python sdk project
# https://github.com/Kount/kount-ris-python-sdk/)
# Copyright (C) 2017 Kount Inc. All Rights Reserved
"""RIS initial inquiry class"""
import time

import ipaddress
import logging
from datetime import datetime

from .config import SDKConfig
from .request import (Request, CurrencyType, InquiryMode,
                      Gender, AddressType, ShippingType)
from .util.address import Address
from .util.cartitem import CartItem
from .version import VERSION

__author__ = SDKConfig.SDK_AUTHOR
__version__ = VERSION
__maintainer__ = SDKConfig.SDK_MAINTAINER
__email__ = SDKConfig.MAINTAINER_EMAIL
__status__ = SDKConfig.STATUS

# common logger for inquiry and request
LOG = logging.getLogger('kount.request')


class Inquiry(Request):
    """RIS initial inquiry class.
        Contains specific methods for setting various inquiry properties
        Class constructor. Sets the RIS mode to "Inquiry" ("Q"),
        sets currency to "USD", and sets the Python SDK identifier.
        The mode and currency can be adjusted by called
        InquiryMode and CurrencyType methods respectively.
        """
    def __init__(self):
        super(Inquiry, self).__init__()
        self.version()
        self.params["SDK"] = SDKConfig.SDK
        self.params["ANID"] = ""
        self.params["FRMT"] = "JSON"
        self.params["VERS"] = SDKConfig.VERS
        self.inquiry_mode = InquiryMode.DEFAULT
        self.currency_type = CurrencyType.USD
        LOG.debug('Inquiry: %s', self.params)

    def version(self):
        """SDK_Type-RIS_VERSION-SDK_BUILD_DATETIMESTAMP"""
        datestr = datetime.now().strftime('%Y%m%d%H%M')
        vers = "Sdk-Ris-%s-%s" % (SDKConfig.LANG, SDKConfig.SDK_VERSION)
        assert len(vers) <= 32
        self.set_param("SDK_VERSION", vers)

    def set_cash(self, cash):
        """Set cash amount of any feasible goods.
            Arg: cash - int, cash amount of any feasible goods"""
        self.set_param("CASH", cash)

    def set_date_of_birth(self, dob):
        """Set the date of birth in the format YYYY-MM-DD.
         Arg: dob - Date of birth
         """
        self.set_param("DOB", dob)

    def set_gender(self, gender):
        """Set the gender. Either M(ale) of F(emale).
            Acceptable values: GENDER
            Arg: - gender"""
    
        self.set_param("GENDER", gender)

    def set_user_defined_field(self, label, value):
        """Set a user defined field.
            Arg: label - The name of the user defined field
            Arg: value - The value of the user defined field
        """
        self.set_param("UDF[%s]" % label, value)

    def set_request_mode(self, mode):
        """Set the request mode.
            Acceptable values are: InquiryMode
            Arg: mode - Mode of the request
        """
        self.set_param("MODE", mode)
    

    def set_currency(self, currency):
        """Set the three character ISO-4217 currency code.
            Arg: currency - Type of currency, CurrencyType
        """
        self.set_param("CURR", currency)

    def set_total(self, total=0):
        """Set the total amount in lowest possible denomination of currency.
            Arg: total - Transaction amount in lowest possible
            denomination of given currency
        """
        self.set_param("TOTL", total)

    def set_email_client(self, email_addr):
        """Set the email address of the client.
            Arg: email - Email address of the client
        """
        self.set_param("EMAL", email_addr)

    def set_customer_name(self, c_name):
        """the name of the client or company.
            Arg: c_name - Name of the client or company
         """
        self.set_param("NAME", c_name)

    def _address(self, adr_type, address):
        """Set the address.
            Arg: address - The billing or shipping address; type Address
            adr_type - billing or shipping, values in ['B', 'S']
        """
        if not isinstance(address, Address):
            raise ValueError
        self.params[adr_type + "2A1"] = address.address1
        self.params["%s2A2" % adr_type] = address.address2
        self.params["%s2CI" % adr_type] = address.city
        self.params["%s2ST" % adr_type] = address.state
        self.params["%s2PC" % adr_type] = address.postal_code
        self.params["%s2CC" % adr_type] = address.country
        self.params["%sPREMISE" % adr_type] = address.premise
        self.params["%sSTREET" % adr_type] = address.street

    def set_billing_address(self, address):
        """Set the billing address.
            Arg: address - The billing address, type Address
            Address
        """
        LOG.debug("B2A1 = %s, B2A2 = %s, B2CI = %s, B2ST = %s, "
                  "B2PC = %s, B2CC = %s, BPREMISE = %s, BSTREET = %s",
                  address.address1, address.address2, address.city,
                  address.state, address.postal_code, address.country,
                  address.premise, address.street)
        self._address(AddressType.BILLING, address)

    def set_shipping_address(self, address):
        """Set the shipping address.
            Arg: address - The shipping address, type Address
        """
        LOG.debug("S2A1 = %s, S2A2 = %s, S2CI = %s, S2ST = %s, "
                  "S2PC = %s, S2CC = %s, SPREMISE = %s, SSTREET = %s",
                  address.address1, address.address2, address.city,
                  address.state, address.postal_code, address.country,
                  address.premise, address.street)
        self._address(AddressType.SHIPPING, address)

    def set_billing_phone_number(self, billing_phone=""):
        """Set the billing phone number.
            Arg: billing_phone - Billing phone number
         """
        self.set_param("B2PN", billing_phone)

    def set_shipping_phone_number(self, shipping_phone):
        """Set the shipping phone number.
            Arg: shipping_phone - shipping phone number
         """
        self.set_param("S2PN", shipping_phone)

    def set_shipping_name(self, ship_name=""):
        """Set the shipping name.
            Arg: ship_name - Shipping name
        """
        self.set_param("S2NM", ship_name)

    def set_email_shipping(self, shipping_email):
        """Set the shipping email address of the client.
            Arg: shipping_email - shipping email
        """
        self.set_param("S2EM", shipping_email)

    def set_unique_customer_id(self, unique_customer):
        """Set the unique ID or cookie set by merchant.
           Arg: unique_customer - Customer-unique ID or cookie set by merchant.
        """
        self.set_param("UNIQ", unique_customer)

    def set_ip_address(self, ip_adr):
        """Set the IP address. ipaddress
        Arg: ip_adr - IP Address of the client
        """
        ipaddress.ip_address(ip_adr)
        self.set_param("IPAD", ip_adr)

    def set_user_agent(self, useragent):
        """Set the user agent string of the client.
        Arg: useragent - user agent string of the client
        """
        self.set_param("UAGT", useragent)

    def set_timestamp(self, time_stamp=None):
        """Set the timestamp (in seconds) since the UNIX epoch
            for when the UNIQ value was set.
            Arg: time_stamp -  The timestamp
        """
        if time_stamp is None:
            time_stamp = time.time()
        self.set_param("EPOC", time_stamp)

    def set_shipment_type(self, shipment):
        """Set shipment type
            Arg: shipment -  type ShippingType
        """

        self.set_param("SHTP", shipment)

    def set_anid(self, anid_order):
        """Set the anid
            Automatic Number Identification (ANI) submitted with order.
            If the ANI cannot be determined,
            merchant must pass 0123456789 as the ANID.
            This field is only valid for MODE=P RIS submissions.
            Arg: anid_order - Anid of the client
        """
        self.set_param("ANID", anid_order)

    def set_company_name(self, name):
        """Set the name of the company.
        Arg: name - Name of the company
        """
        self.set_param("NAME", name)

    def set_website(self, web_site):
        """Set the website.
            Arg: site - the website
        """
        self.set_param("SITE", web_site)

    def set_shopping_cart(self, cart):
        """Set the shopping cart.
            Arg: cart - Cart items in the shopping cart, type Cart
        """
        for index, item in enumerate(cart):
            if not isinstance(item, CartItem):
                raise ValueError('Invalid cart item: %s', item)
            LOG.debug("PROD_TYPE[%i] = %s, PROD_ITEM[%i] = %s, "
                    "PROD_DESC[%i] = %s, PROD_QUANT[%i] = %s, "
                    "PROD_PRICE[%i] = %s",
                    index, item.product_type,
                    index, item.item_name,
                    index, item.description,
                    index, item.quantity,
                    index, item.price)

            self.params["PROD_TYPE[%i]" % index] = item.product_type
            self.params["PROD_ITEM[%i]" % index] = item.item_name
            self.params["PROD_DESC[%i]" % index] = item.description
            self.params["PROD_QUANT[%i]" % index] = item.quantity
            self.params["PROD_PRICE[%i]" % index] = item.price

kount.request module

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# This file is part of the Kount python sdk project
# https://github.com/Kount/kount-ris-python-sdk/)
# Copyright (C) 2017 Kount Inc. All Rights Reserved.
"""RIS Request superclass for Inquiry and Update"""

import logging

from .config import SDKConfig
from .util.khash import Khash
from .util import payment as payments
from .version import VERSION

__author__ = SDKConfig.SDK_AUTHOR
__version__ = VERSION
__maintainer__ = SDKConfig.SDK_MAINTAINER
__email__ = SDKConfig.MAINTAINER_EMAIL
__status__ = SDKConfig.STATUS

LOG = logging.getLogger('kount.request')


class _RisType(object):

    __CACHED_ATTRS = None

    @classmethod
    def is_valid(cls, val):
        attrs = cls.__CACHED_ATTRS
        if attrs is None:
            attrs = {
                v for k, v in vars(cls).items() if not k.startswith('_')
            }
            cls.__CACHED_ATTRS = attrs
        return val in attrs


class AuthStatus(_RisType):
    """Authorization status"""
    APPROVE = 'A'
    DECLINE = 'D'
    REVIEW = 'R'
    ESCALATE = "E"
    REVIEW_TIMEOUT = 'X'
    APPROVED_DECLINED_TIMEOUT = 'Y'
    ELEVATED = 'C'


class BankcardReply(_RisType):
    """Bankcard Reply"""
    MATCH = 'M'
    NO_MATCH = 'N'
    UNAVAILABLE = 'X'


class Gender(_RisType):
    """gender"""
    MALE = 'M'
    FEMALE = 'F'


class AddressType(_RisType):
    """address type"""
    BILLING = 'B'
    SHIPPING = 'S'


class ShippingType(_RisType):
    """
    "SD". Same day shipping type.
    "ND". Next day shipping type.
    "2D". Second day shipping type.
    "ST". Standard shipping type.
    "DE". Delivery shipping type.
    "PU". Pick-up shipping type
    """
    SAME_DAY = 'SD'
    NEXT_DAY = 'ND'
    SECOND_DAY = '2D'
    STANDARD = 'ST'
    DELIVERY = 'DE'
    PICK_UP = 'PU'


class RefundChargebackStatus(_RisType):
    """Refund charge back status.
    R - The transaction was a refund.
    C - The transaction was a chargeback.
    """
    REFUND = 'R'
    CHARGEBACK = 'C'


class MerchantAcknowledgment(_RisType):
    """merchant acknowledgment
    "Y". The product expects to ship.
    "N". The product does not expect to ship.
    """
    FALSE = 'N'
    TRUE = 'Y'


class CurrencyType(_RisType):
    """Currency type object
    "USD". United States Dollars
    "EUR". European currency unit
    "CAD". Canadian Dollar
    "AUD". Australian Dollar
    "JPY". Japanese Yen
    "HKD". Honk Kong Dollar
    "NZD". New Zealand Dollar
    """
    USD = 'USD'
    EUR = 'EUR'
    CAD = 'CAD'
    AUD = 'AUD'
    JPY = 'JPY'
    HKD = 'HKD'
    NZD = 'NZD'


class InquiryMode(_RisType):
    """
    "Q". Default inquiry mode, internet order type.
    "P". Phone order type.
    "W". Kount Central Mode W - Full Inquiry [W]ith thresholds.
    "J". Kount Central Mode J - Fast Inquiry [J]ust thresholds.
    """
    DEFAULT = 'Q'
    PHONE = 'P'
    WITH_THRESHOLDS = 'W'
    JUST_THRESHOLDS = 'J'


class Request(object):
    """RIS Request superclass for Inquiry and Update."""

    def __init__(self):
        """Map containing data that will be sent to RIS."""
        self.params = dict()
        self.payment = None
        self.close_on_finish = None

    def set_param(self, key, value):
        """Set a parm for the request.
        Args:
           key - The key for the parm
           value - The value for the parm
        """
        self.params[key] = value
        LOG.debug("%s = %s", key, value)

    def set_khash_payment_encoding(self, enabled=True):
        """Set KHASH payment encoding.
        Arg: enabled Boolean
        """
        self.set_param("PENC", "KHASH" if enabled else "")

    def set_version(self, version):
        """Set the version number.
        Args: version - The SDK version
        """
        self.set_param("VERS", version)

    def set_lbin(self, lbin):
        """Set the  Long Bank Identification Number.
        Arg: lbin - string
        """
        self.set_param("LBIN", lbin)

    def set_session_id(self, session_id):
        """Set the session id. Must be unique over a 30-day span
        Args: session_id -  Id of the current session
        """
        self.set_param("SESS", session_id)

    def set_merchant(self, merchant_id):
        """Set the merchant id.
        Args: merchant_id - Merchant ID
        """
        self.set_param("MERC", merchant_id)

    def set_kount_central_customer_id(self, customer_id):
        """Set the Kount Central Customer ID.
        Args: customer_id - KC Customer ID
        """
        self.set_param("CUSTOMER_ID", customer_id)

    def set_order_number(self, order_number):
        """Set the order number.
        Args: order_number - Merchant unique order number
        """
        self.set_param("ORDR", order_number)

    def set_merchant_acknowledgment(self, ma_type):
        """Set the merchant acknowledgment.
        Merchants acknowledgement to ship/process the order.
        The MACK field must be set as MerchantAcknowledgment.TRUE
        if personal data is to be
        collected to strengthen the score.
        Args: ma_type - merchant acknowledgment type
        """
        if MerchantAcknowledgment.is_valid(ma_type):
            self.set_param("MACK", ma_type)
        else:
            raise ValueError("Invalid MerchantAcknowledgment = %s" % ma_type)

    def set_authorization_status(self, auth_status):
        """Set the Authorization Status.
        Authorization Status returned to merchant from processor.
        Acceptable values for the
        AUTH field are AuthStatus. In orders where AUTH=A will
        aggregate towards order velocity of the persona while
        orders where AUTH=D will
        decrement the velocity of the persona.
        Args: auth_status - Auth status by issuer
        """
        if AuthStatus.is_valid(auth_status):
            self.set_param("AUTH", auth_status)
        else:
            raise ValueError("Invalid AuthStatus value %s" % auth_status)

    def set_avs_zip_reply(self, avs_zip_reply):
        """Set the Bankcard AVS zip code reply.
        Address Verification System Zip Code verification response
        returned to merchant from
        processor. Acceptable values are BCRSTAT.
        Args: avs_zip_reply - Bankcard AVS zip code reply
        """
        if BankcardReply.is_valid(avs_zip_reply):
            self.set_param("AVSZ", avs_zip_reply)
        else:
            raise ValueError('Invalid BankcardReply = %s' % avs_zip_reply)

    def set_avs_address_reply(self, avs_address_reply):
        """Set the Bankcard AVS street addres reply.
        Address Verification System Street verification response
        returned to merchant from processor. Acceptable values are BCRSTAT.
        Args: avs_address_reply - Bankcard AVS street address reply
        """
        if BankcardReply.is_valid(avs_address_reply):
            self.set_param("AVST", avs_address_reply)
        else:
            raise ValueError('Invalid BankcardReply = %s' % avs_address_reply)

    def set_avs_cvv_reply(self, cvv_reply):
        """Set the Bankcard CVV/CVC/CVV2 reply.
        Card Verification Value response returned to merchant from processor.
        Acceptable values are BCRSTAT
        Args: cvv_reply -  Bankcard CVV/CVC/CVV2 reply
        """
        if BankcardReply.is_valid(cvv_reply):
            self.set_param("CVVR", cvv_reply)
        else:
            raise ValueError('Invalid BankcardReply = %s' % cvv_reply)

    def set_payment(self, payment):
        """ Set a payment.
            Depending on the payment type, various request parameters are set:
            PTOK, PTYP, LAST4.
            If payment token hashing is not possible, the PENC parameter is set
            to empty string.
            Args: payment -  Payment
        """
        khasher = Khash.get()
        if "PENC" in self.params \
                and not isinstance(payment, payments.NoPayment) \
                and not payment.khashed:
            try:
                if not self.params.get("MERC"):
                    raise ValueError("merchant_id not set")
                if isinstance(payment, payments.GiftCardPayment):
                    merchant_id = int(self.params["MERC"])
                    payment.payment_token = khasher.hash_gift_card(
                        merchant_id, payment.payment_token)
                else:
                    payment.payment_token = khasher.hash_payment_token(
                        payment.payment_token)
                payment.khashed = True
                self.set_param("PENC", "KHASH")
                LOG.debug("payment.khashed=%s", payment.khashed)
            except ValueError as nfe:
                LOG.debug("Error converting Merchant ID to integer"
                          " value. Set a valid Merchant ID. %s",
                          str(nfe))
                raise nfe
            except Exception as nsae:
                LOG.debug("Unable to create payment token hash. Caught %s "
                          "KHASH payment encoding disabled", str(nsae))
                # Default to plain text payment tokens
                self.params["PENC"] = ""
        if khasher.khashed(payment.payment_token):
            self.set_param("PENC", "KHASH")
        self.set_param("PTOK", payment.payment_token)
        self.set_param("PTYP", payment.payment_type)
        self.set_param("LAST4", payment.last4)

    @staticmethod
    def _mask_token(token):
        """Encodes the provided payment token according to the MASK
           encoding scheme
           Args: token -  the Payment token for this request
           return - MASK-encoded token
        """
        encoded = token[0:6]
        for _ in range(6, len(token) - 4, 1):
            encoded = encoded + 'X'
        encoded = encoded + token[-4:]
        LOG.debug("mask_token = %s", token)
        return encoded

    def set_payment_by_type(self, ptyp, ptok):
        """ Set a payment by payment type and payment token.
        The payment type parameter provided is checked
        if it's one of the predefined payment types
        and Payment is created appropriately
        Args: ptyp - See SDK documentation for a list of accepted payment types
        ptok - The payment token
        """
        cls = {
            'BLML': payments.BillMeLaterPayment,
            'CARD': payments.CardPayment,
            'CHECK': payments.CheckPayment, # backwards compatibility
            'CHEK': payments.CheckPayment,
            'GIFT': payments.GiftCardPayment,
            'GOOG': payments.GooglePayment,
            'GDMP': payments.GreenDotMoneyPakPayment,
            'NONE': payments.NoPayment,
            'PYPL': payments.PaypalPayment,
        }.get(ptyp)
        if cls is None:
            cls = payments.Payment
        self.set_payment(cls(ptyp, ptok))

    def set_masked_payment(self, payment):
        """ Sets a card payment and masks the card number in the following way:
        First 6 characters remain as they are, following characters up to the
        last 4 are replaced with the 'X' character, last 4 characters
        remain as they are.
        If the provided Payment parameter is not a card payment,
        standard encoding will be applied.
        This method sets the following RIS Request fields:
        PTOK, PTYP, LAST4, PENC.
        Args: payment - card payment
        """
        token = payment.payment_token
        if isinstance(payment, payments.CardPayment) and \
                not payment.khashed:
            token = self._mask_token(token)
            self.set_param("PTOK", token)
            self.set_param("PTYP", payment.payment_type)
            self.set_param("LAST4", payment.last4)
            self.set_param("PENC", "MASK")
        else:
            self.set_param("PTOK", token)
            LOG.debug("Payment Masked: provided payment is not "
                      "a CardPayment, applying khash instead of masking")
            self.set_payment_by_type(payment, token)

    def is_set_khash_payment_encoding(self):
        """Check if KHASH payment encoding has been set.
           return boolean TRUE when set.
        """
        encoded = self.params.get("PENC") == "KHASH"
        LOG.debug("is_set_khash_payment_encoding = %s", encoded)
        return encoded

    def set_close_on_finish(self, close_on_finish):
        """Set a flag for the request transport.
           Arg: close_on_finish - Sets the close_on_finish flag
           return boolean TRUE when set.
        """
        self.close_on_finish = close_on_finish
        LOG.debug("close_on_finish = %s", close_on_finish)


class UpdateMode(_RisType):
    """UpdateMode - U, X"""
    NO_RESPONSE = 'U'
    WITH_RESPONSE = 'X'


class Update(Request):
    """RIS update class.
     defaults to update_mode WithResponse.
     """

    def __init__(self):
        super(Update, self).__init__()
        self.set_mode(UpdateMode.NO_RESPONSE)
        self.params['VERS'] = SDKConfig.VERS
        # self.params["SDK"] = "python"
        self.set_khash_payment_encoding(True)

    def set_mode(self, mode):
        """Set the mode.
        Args - mode - Mode of the request
        """
        if UpdateMode.is_valid(mode):
            self.params["MODE"] = mode
        else:
            raise ValueError("Invalid UpdateMode: %s" % mode)

    def set_transaction_id(self, transaction_id):
        """Set the transaction id.
        Arg - transaction_id, String Transaction id
        """
        self.params["TRAN"] = transaction_id

    def set_refund_chargeback_status(self, rc_status):
        """Set the Refund/Chargeback status: R = Refund C = Chargeback.
        Arg - rc_status, String Refund or chargeback status
        """
        if RefundChargebackStatus.is_valid(rc_status):
            self.params["RFCB"] = rc_status
        else:
            raise ValueError("Invalid RefundChargebackStatus: %s" % rc_status)

kount.response module

kount.ris_validator module

kount.settings module

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# This file is part of the Kount python sdk project
# https://github.com/Kount/kount-ris-python-sdk/)
# Copyright (C) 2017 Kount Inc. All Rights Reserved.

import os

from . import resources
from .version import VERSION
from .settings import CONFIGURATION_KEY, SDK_AUTHOR, SDK_MAINTAINER, MAINTAINER_EMAIL, DEFAULT_TIMEOUT

__author__ = SDK_AUTHOR
__version__ = VERSION
__maintainer__ = SDK_MAINTAINER
__email__ = MAINTAINER_EMAIL
__status__ = "Development"


class SDKConfig:

    VERS = "0720"

    SDK = "PYTH"

    LANG = "Python"

    SDK_VERSION = "0.0.0"
    
    SDK_AUTHOR = __author__

    SDK_MAINTAINER = __maintainer__

    MAINTAINER_EMAIL = __email__

    STATUS = __status__
    # default behaviour for request failures
    _RAISE_ERRORS = True

    # requests timeout
    _DEFAULT_TIMEOUT = DEFAULT_TIMEOUT

    # should be set from the sdk user
    _CONFIGURATION_KEY = CONFIGURATION_KEY

    @classmethod
    def get_default_timeout(cls):
        return cls._DEFAULT_TIMEOUT

    @classmethod
    def get_configuration_key(cls):
        return cls._CONFIGURATION_KEY

    @classmethod
    def get_should_raise_validation_errors(cls):
        return cls._RAISE_ERRORS

    @classmethod
    def setup(cls,
              config_key,
              default_timeout=5,
              raise_errors=True,
              xml_rules_file_name=None):
        """
        Call this method before start using the SDK
        :param config_key: mandatory parameter, configuration key provided
         by Kount
        :param default_timeout: request timeout, default value is 5 seconds
        :param raise_errors: indicate if the request should throw an exception
         in case of error, default value is True
        :param xml_rules_file_name: xml rules for validation of the request,
         should not be overwritten, unless you know what you are doing
        """

        cls._CONFIGURATION_KEY = config_key
        cls._DEFAULT_TIMEOUT = default_timeout
        cls._RAISE_ERRORS = raise_errors

        from .util import khash
        k = khash.Khash(config_key)
        k.verify()

kount.version module

# Set the value to a VERSION in this dedicated module in the project
VERSION = '3.3.3'