Unit and Integration tests¶
conftest.py
import os
import pytest
from kount import config
def pytest_addoption(parser):
parser.addoption('--conf-key', action='store',
default=os.environ.get('CONF_KEY', ''))
parser.addoption('--api-key', action='store',
default=os.environ.get('RIS_SDK_SANDBOX_API_KEY', ''))
parser.addoption('--merchant-id', action='store',
default=os.environ.get('RIS_SDK_SANDBOX_MERCHANT_ID', ''))
parser.addoption('--api-url', action='store',
default=os.environ.get('RIS_SDK_SANDBOX_URL', 'https://risk.test.kount.net'))
@pytest.fixture(scope='session', autouse=True)
def conf_key(request):
try:
config.SDKConfig.setup(request.config.getoption('--conf-key'))
except ValueError as e:
if not config.SDKConfig.get_configuration_key():
msg = "Configuration key not set, use --conf-key or " \
"set environment variable CONF_KEY"
else:
msg = 'Configuration key error: %s' % str(e)
pytest.exit(msg)
@pytest.fixture(scope='class')
def api_key(request):
request.cls.api_key = request.config.getoption('--api-key')
@pytest.fixture(scope='class')
def merchant_id(request):
request.cls.merchant_id = request.config.getoption('--merchant-id')
@pytest.fixture(scope='class')
def api_url(request):
request.cls.api_url = request.config.getoption('--api-url')
test_address.py
#!/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 unittest
from kount.util.address import Address
from kount.version import VERSION
from kount.config import SDKConfig
__author__ = SDKConfig.SDK_AUTHOR
__version__ = VERSION
__maintainer__ = SDKConfig.SDK_MAINTAINER
__email__ = SDKConfig.MAINTAINER_EMAIL
__status__ = SDKConfig.STATUS
class TestAddress(unittest.TestCase):
"""Address class test cases"""
def test_address_valid(self):
"""valid address"""
adr = Address(address1="567 West S2A1 Court North",
address2=None, state="Gnome", postal_code="AK",
premise="99762", country="US")
self.assertTrue(isinstance(adr, Address))
adr = Address("1234 North B2A1 Tree Lane South", None,
"Albuquerque", "NM", "87101", "US")
self.assertTrue(isinstance(adr, Address))
adr = Address("567 West S2A1 Court North", None,
"Gnome", "AK", "99762", "US")
self.assertEqual("567 West S2A1 Court North", str(adr.address1))
def test_address_incorrect_string(self):
"""incorrect address"""
for bad_type in [42**42, "<script>alert(42)</script>", None, "", 42]:
adr = Address(bad_type)
self.assertEqual("", str(adr.country))
def test_address_cyrillic(self):
"""incorrect address - cyrillic"""
for bad_type in ["Сирма", "'%=:*-+<", "ъ"]:
adr = Address(bad_type)
self.assertEqual("", str(adr.country))
self.assertEqual(bad_type, adr.address1)
if __name__ == "__main__":
unittest.main()
test_api_kount.py
#!/usr/bin/env python
"""Test class TestAPIRIS"""
# -*- 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 logging
import unittest
import pytest
from kount.client import Client
from kount.version import VERSION
from .json_test import example_data_products
from kount.config import SDKConfig
__author__ = SDKConfig.SDK_AUTHOR
__version__ = VERSION
__maintainer__ = SDKConfig.SDK_MAINTAINER
__email__ = SDKConfig.MAINTAINER_EMAIL
__status__ = SDKConfig.STATUS
LOGGER = logging.getLogger('kount')
expected1 = {
'AUTO': 'R',
'BRND': None,
'BROWSER': None,
'CARDS': '1',
'COOKIES': None,
'COUNTERS_TRIGGERED': 0,
'COUNTRY': None,
'DDFS': None,
'DEVICES': '1',
'DEVICE_LAYERS': '....',
'DSR': None,
'EMAILS': '1',
'FINGERPRINT': None,
'FLASH': None,
'GEOX': 'US',
'HTTP_COUNTRY': None,
'IP_CITY': None,
'IP_COUNTRY': None,
'IP_IPAD': None,
'IP_LAT': None,
'IP_LON': None,
'IP_ORG': None,
'IP_REGION': None,
'JAVASCRIPT': None,
'KAPT': 'N',
'LANGUAGE': None,
'LOCALTIME': ' ',
'MERC': '', # will be replaced
'MOBILE_DEVICE': None,
'MOBILE_FORWARDER': None,
'MOBILE_TYPE': None,
'MODE': 'Q',
'NETW': 'N',
'ORDR': 'F8E874A38B7B',
'OS': None,
'PC_REMOTE': None,
'PIP_CITY': None,
'PIP_COUNTRY': None,
'PIP_IPAD': None,
'PIP_LAT': None,
'PIP_LON': None,
'PIP_ORG': None,
'PIP_REGION': None,
'PREVIOUSLY_WHITELISTED': 'N',
'PROXY': None,
'REASON_CODE': None,
'REGION': None,
'REGN': None,
'RULES_TRIGGERED': 1,
'RULE_DESCRIPTION_0': 'Review if order total > $1000 USD',
'SCOR': '34',
'OMNISCORE':36.3,
'SESS': 'F8E874A38B7B4B6DBB71492A584A969D',
'SITE': 'DEFAULT',
'THREE_DS_MERCHANT_RESPONSE': None,
'TIMEZONE': None,
'UAS': None,
'VERS': '0710',
'VOICE_DEVICE': None,
'WARNING_COUNT': 0}
def dict_compare(dict1, dict2):
"""compare 2 dictionaries"""
dict1_keys = set(dict1.keys())
dict2_keys = set(dict2.keys())
intersect_keys = dict1_keys.intersection(dict2_keys)
added = dict1_keys - dict2_keys
removed = dict2_keys - dict1_keys
modified = {o: (dict1[o],
dict2[o]) for o in intersect_keys if dict1[o] != dict2[o]}
same = set(o for o in intersect_keys if dict1[o] == dict2[o])
return added, removed, modified, same
CURLED = {
'ANID': '',
'AUTH': 'A',
'AVST': 'M',
'AVSZ': 'M',
'B2A1': '1234 North B2A1 Tree Lane South',
'B2CC': 'US',
'B2CI': 'Albuquerque',
'B2PC': '87101',
'B2PN': '555+867-5309',
'B2ST': 'NM',
'CASH': '4444',
'CURR': 'USD',
'CVVR': 'M',
'EMAL': 'curly.riscaller15@kountqa.com',
'FRMT': 'JSON',
'IPAD': '4.127.51.215',
'LAST4': '2514',
'MACK': 'Y',
'MERC': '999666',
'MODE': 'Q',
'NAME': 'Goofy Grumpus',
'ORDR': '088E9F496135',
'PROD_DESC[]': '3000 CANDLEPOWER PLASMA FLASHLIGHT',
'PROD_ITEM[]': 'SG999999',
'PROD_PRICE[]': '68990',
'PROD_QUANT[]': '2',
'PROD_TYPE[]': 'SPORTING_GOODS',
'PTOK': '0007380568572514',
'PTYP': 'CARD',
'S2A1': '567 West S2A1 Court North',
'S2CC': 'US',
'S2CI': 'Gnome',
'S2EM': 'sdkTestShipTo@kountsdktestdomain.com',
'S2NM': 'SdkTestShipToFirst SdkShipToLast',
'S2PC': '99762',
'S2PN': '208 777-1212',
'S2ST': 'AK',
'SESS': '088E9F4961354D4F90041988B8D5C66B',
'SITE': 'DEFAULT',
'TOTL': '123456',
'UNIQ': '088E9F4961354D4F9004',
'VERS': '0710'}
@pytest.mark.usefixtures("api_url", "api_key", "merchant_id")
class TestAPIRIS(unittest.TestCase):
"""
implemented curl from https://kopana.atlassian.net/wiki/display/KS/Testing
"""
maxDiff = None
timeout = 5
def _expected_response(self):
r = dict(expected1)
r['MERC'] = self.merchant_id
return r
def test_api_kount(self):
"""expected modified 'TRAN'"""
data = CURLED
self.assertIn('MODE', CURLED)
expected = {
"VERS": "0710", "MODE": "Q", "TRAN": "PTPN0Z04P8Y6",
"MERC": "999666", "SESS": "088E9F4961354D4F90041988B8D5C66B",
"ORDR": "088E9F496135", "AUTO": "R", "SCOR": "29", "GEOX": "US",
"BRND": None, "REGN": None, "NETW": "N", "KAPT": "N", "CARDS": "1",
"DEVICES": "1", "EMAILS": "1", "VELO": "0",
"VMAX": "0", "SITE": "DEFAULT", "DEVICE_LAYERS": "....",
"FINGERPRINT": None, "TIMEZONE": None, "LOCALTIME": " ",
"REGION": None,
"COUNTRY": None, "PROXY": None, "JAVASCRIPT": None, "FLASH": None,
"COOKIES": None, "HTTP_COUNTRY": None, "LANGUAGE": None,
"MOBILE_DEVICE": None, "MOBILE_TYPE": None,
"MOBILE_FORWARDER": None,
"VOICE_DEVICE": None, "PC_REMOTE": None, "RULES_TRIGGERED": 1,
"RULE_ID_0": "1024842",
"RULE_DESCRIPTION_0": "Review if order total > $1000 USD",
"COUNTERS_TRIGGERED": 0,
"REASON_CODE": None, "DDFS": None, "DSR": None,
"UAS": None, "BROWSER": None,
"OS": None, "PIP_IPAD": None, "PIP_LAT": None, "PIP_LON": None,
"PIP_COUNTRY": None,
"PIP_REGION": None, "PIP_CITY": None, "PIP_ORG": None,
"IP_IPAD": None,
"IP_LAT": None, "IP_LON": None, "IP_COUNTRY": None,
"IP_REGION": None,
"IP_CITY": None, "IP_ORG": None, "WARNING_COUNT": 0,"OMNISCORE":None, "PREVIOUSLY_WHITELISTED": "N", "THREE_DS_MERCHANT_RESPONSE":None}
for raise_errors in [True, False]:
actual = self._client(raise_errors=raise_errors)._execute(data)
added, removed, modified, _ = dict_compare(actual, expected)
self.assertEqual(added, set())
self.assertEqual(removed, set())
modified_exp = {
'REGN': (actual['REGN'], expected['REGN']),
'TRAN': (actual['TRAN'], expected['TRAN']),
'SCOR': (actual['SCOR'], expected['SCOR']),
'OMNISCORE': (actual['OMNISCORE'], expected['OMNISCORE'])
}
self.assertEqual(sorted(modified), sorted(modified_exp))
def test_api_kount_2_items(self):
"expected modified 'TRAN'"
data = example_data_products.copy()
self.assertIn('MODE', data)
for raise_errors in [True, False]:
actual = self._client(raise_errors=raise_errors)._execute(data)
del (actual['TRAN'], actual['RULE_ID_0'],
actual['VELO'], actual['VMAX'])
self.assertEqual(actual, self._expected_response())
def test_last_2_items_bad_email(self):
"last_2_items_bad_email"
data = example_data_products.copy()
self.assertIn('MODE', CURLED)
bad = CURLED['EMAL'].replace('@', "%40")
data["EMAL"] = bad
expected = {
'ERROR_0':
"321 BAD_EMAL Cause: [Invalid email address], Field: [EMAL],"
" Value: [%s]" % (bad),
'ERRO': 321,
'ERROR_COUNT': 1,
'WARNING_COUNT': 0,
'MODE': 'E'}
actual = self._client(raise_errors=False)._execute(data)
self.assertEqual(actual, expected)
def test_2_items_bad_s2em(self):
"""bad S2EM"""
bad = example_data_products["S2EM"].replace('@', "%40")
data = example_data_products.copy()
data["S2EM"] = bad
actual = self._client(raise_errors=False)._execute(params=data)
del (actual['TRAN'], actual['RULE_ID_0'],
actual['VELO'], actual['VMAX'])
self.assertEqual(actual, self._expected_response())
def test_two_items_none_email(self):
"email = None"
data = example_data_products.copy()
data["EMAL"] = None
self.assertIn('MODE', data)
expected = {
'ERRO': 221, 'ERROR_COUNT': 1,
'MODE': 'E', 'WARNING_COUNT': 0,
'ERROR_0': "221 MISSING_EMAL Cause: "
"[Non-empty value was required in this case], "
"Field: [EMAL], Value: []"}
for raise_errors in [True, False]:
actual = self._client(raise_errors=raise_errors)._execute(data)
self.assertEqual(actual, expected)
def test_two_items_missing_or_long_email(self):
"missing or long incorrect email"
data = example_data_products.copy()
del data["EMAL"]
self.assertIn('MODE', data)
expected = {
'ERRO': 221, 'ERROR_COUNT': 1,
'MODE': 'E', 'WARNING_COUNT': 0,
'ERROR_0': "221 MISSING_EMAL Cause: "
"[Non-empty value was required in this case], "
"Field: [EMAL], Value: []"}
for raise_errors in [True, False]:
actual = self._client(raise_errors=raise_errors)._execute(data)
self.assertEqual(actual, expected)
data["EMAL"] = "a" * 57 + "@aaa.com"
response = self._client(raise_errors=False)._execute(data)
self.assertEqual(321, response['ERRO'])
def test_api_kount_empty_data(self):
"empty data"
data = {'FRMT': 'JSON'}
expected = {"MODE": "E", "ERRO": "201"}
actual = self._client(raise_errors=False)._execute(data)
self.assertEqual(actual, expected)
def _client(self, **kwargs):
kwargs['api_url'] = self.api_url
kwargs['api_key'] = self.api_key
kwargs['timeout'] = self.timeout
return Client(**kwargs)
test_basic_connectivity.py
#!/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.
"""Test Cases from sdk documentation
generate_unique_id
default_inquiry
Test Basic Connectivity
"""
import unittest
import pytest
from kount.client import Client
from kount.util.payment import CardPayment
from kount.version import VERSION
from .test_inquiry import generate_unique_id, default_inquiry
from kount.config import SDKConfig
__author__ = SDKConfig.SDK_AUTHOR
__version__ = VERSION
__maintainer__ = SDKConfig.SDK_MAINTAINER
__email__ = SDKConfig.MAINTAINER_EMAIL
__status__ = SDKConfig.STATUS
PTOK = "0007380568572514"
EMAIL = 'predictive@kount.com'
@pytest.mark.usefixtures("api_url", "api_key", "merchant_id")
class TestBasicConnectivity(unittest.TestCase):
"""Test Basic Connectivity"""
maxDiff = None
def _client(self, **kwargs):
kwargs['api_url'] = self.api_url
kwargs['api_key'] = self.api_key
return Client(**kwargs)
def _process(self, request, **client_kwargs):
return self._client(**client_kwargs).process(request)
def setUp(self):
self.session_id = generate_unique_id()[:32]
self.email_client = EMAIL
payment = CardPayment(PTOK, khashed=False)
self.inq = default_inquiry(self.merchant_id,
self.session_id,
self.email_client,
payment=payment)
def test_12_expected_score(self):
"test_12_expected_score"
self.inq.params["UDF[~K!_SCOR]"] = '42'
res = self._process(self.inq)
self.assertIsNotNone(res)
self.assertEqual('42', res.get_score())
def request_with_Lbin(self):
"test_Lbin_set_in_requst"
self.inq.params["LBIN"] = '1234567'
self.assertEqual('1234567', self.inq.params.get("LBIN"))
res = self._process(self.inq)
self.assertEqual(0, len(res.get_errors))
def request_without_Lbin(self):
"test_Lbin_not_set_in_requst"
res = self._process(self.inq)
self.assertEqual(0, len(res.get_errors))
def test_13_expected_decision(self):
"""test_13_expected_decision"""
self.inq.params["UDF[~K!_AUTO]"] = 'R'
res = self._process(self.inq)
self.assertIsNotNone(res)
self.assertEqual("R", res.get_auto())
def test_16_expected_geox(self):
"""test_16_expected_geox"""
self.inq.params["UDF[~K!_SCOR]"] = '42'
self.inq.params["UDF[~K!_AUTO]"] = 'D'
self.inq.params["UDF[~K!_GEOX]"] = 'NG'
res = self._process(self.inq)
self.assertIsNotNone(res)
self.assertEqual("D", res.get_auto())
self.assertEqual("NG", res.get_geox())
self.assertEqual("42", res.get_score())
def test_cyrillic(self):
"""test_cyrillic"""
bad = u'Сирма :ы№'
self.inq.params["S2NM"] = bad
self.inq.params["EMAL"] = bad
res = self._process(self.inq, raise_errors=False)
self.assertIsNotNone(res)
self.assertEqual({
u'ERRO': 321,
u'ERROR_0': u"321 BAD_EMAL Cause: [Invalid email address]"\
", Field: [EMAL], Value: [%s]" % (bad),
u'ERROR_COUNT': 1, u'MODE': u'E', u'WARNING_COUNT': 0},
{u'ERRO':res.get_error_code(),
u'ERROR_0': res.get_errors()[0],
u'ERROR_COUNT': len(res.get_errors()),
u'MODE': res.get_mode(),
u'WARNING_COUNT': len(res.get_warnings())})
def test_long(self):
"""test_long request"""
bad_list = [
'Сирма :ы№',
'abcqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq 12345']
expected = """Neither JSON nor String """\
"""<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">\n"""\
"<html><head>\n"\
"<title>413 Request Entity Too Large</title>\n"\
"</head><body>\n"\
"<h1>Request Entity Too Large</h1>\n"\
"The requested resource<br />/<br />\n"\
"does not allow request data with POST requests, or the"\
" amount of data provided in\n"\
"the request exceeds the capacity limit.\n"\
"</body></html>\n"\
"MODE=E\n"\
"ERRO=201"
inq = self.inq
for bad in bad_list:
inq.params["S2NM"] = bad
try:
self._process(inq, raise_errors=False)
except ValueError as vale:
self.assertEqual(expected, str(vale))
class TestBasicConnectivityKhashed(TestBasicConnectivity):
"""Test Basic Connectivity Khashed"""
maxDiff = None
def setUp(self):
self.session_id = generate_unique_id()[:32]
self.email_client = EMAIL
payment = CardPayment(PTOK)
self.inq = default_inquiry(
self.merchant_id, self.session_id,
self.email_client, payment=payment)
if __name__ == "__main__":
unittest.main(
# defaultTest="TestBasicConnectivity.test_16_expected_geox"
)
json_test.py
#!/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.
"example data from https://kopana.atlassian.net/wiki/display/KS/Testing"
from kount.version import VERSION
from kount.config import SDKConfig
__author__ = SDKConfig.SDK_AUTHOR
__version__ = VERSION
__maintainer__ = SDKConfig.SDK_MAINTAINER
__email__ = SDKConfig.MAINTAINER_EMAIL
__status__ = SDKConfig.STATUS
example_data = {
'ANID': '',
'AUTH': 'A',
'AVST': 'M',
'AVSZ': 'M',
'B2A1': '1234+North+B2A1+Tree+Lane+South',
'B2CC': 'US',
'B2CI': 'Albuquerque',
'B2PC': '87101',
'B2PN': '555+867-5309',
'B2ST': 'NM',
'CASH': '4444',
'CURR': 'USD',
'CVVR': 'M',
'EMAL': 'curly.riscaller15@kountqa.com',
'FRMT': 'JSON',
'IPAD': '4.127.51.215',
'LAST4': '2514',
'MACK': 'Y',
'MERC': '999666',
'MODE': 'Q',
'NAME': 'Goofy+Grumpus',
'ORDR': '088E9F496135',
'PROD_DESC[]': '3000+CANDLEPOWER+PLASMA+FLASHLIGHT',
'PROD_ITEM[]': 'SG999999',
'PROD_PRICE[]': '68990',
'PROD_QUANT[]': '2',
'PROD_TYPE[]': 'SPORTING%5FGOODS',
'PTOK': '0007380568572514',
'PTYP': 'CARD',
'S2A1': '567+West+S2A1+Court+North',
'S2CC': 'US',
'S2CI': 'Gnome',
'S2EM': 'sdkTestShipTo@kountsdktestdomain.com',
'S2NM': 'SdkTestShipToFirst+SdkShipToLast',
'S2PC': '99762',
'S2PN': '208+777-1212',
'S2ST': 'AK',
'SESS': '088E9F4961354D4F90041988B8D5C66B',
'SITE': 'DEFAULT',
'TOTL': '123456',
'UAGT': 'Mozilla%2F5.0+%28Macintosh%3B+Intel+Mac+OS+X+10%5F9%5F5%29+'\
'AppleWebKit%2F537.36+%28KHTML%2C+like+Gecko%29+'\
'Chrome%2F37.0.2062.124+Safari%2F537.36',
'UNIQ': '088E9F4961354D4F9004',
'VERS': '0710'
}
example_data_products = {
'ANID': '',
'AUTH': 'A',
'AVST': 'M',
'AVSZ': 'M',
'B2A1': '1234+North+B2A1+Tree+Lane+South',
'B2CC': 'US',
'B2CI': 'Albuquerque',
'B2PC': '87101',
'B2PN': '555+867-5309',
'B2ST': 'NM',
'CASH': '4444',
'CURR': 'USD',
'CVVR': 'M',
'EMAL': 'curly.riscaller15@kountqa.com',
'FRMT': 'JSON', # set if not via sdk
'IPAD': '129.173.116.98',
'MACK': 'Y',
'MERC': '999666',
'MODE': 'Q',
'NAME': 'Goofy+Grumpus',
'ORDR': 'F8E874A38B7B',
'PROD_DESC[0]': '3000+CANDLEPOWER+PLASMA+FLASHLIGHT',
'PROD_DESC[1]': '3000+HP+NUCLEAR+TOILET',
'PROD_ITEM[0]': 'SG999999',
'PROD_ITEM[1]': 'TP999999',
'PROD_PRICE[0]': '68990',
'PROD_PRICE[1]': '1000990',
'PROD_QUANT[0]': '2',
'PROD_QUANT[1]': '44',
'PROD_TYPE[0]': 'SPORTING%5FGOODS',
'PROD_TYPE[1]': 'SPORTING%5FGOODS2',
'PTOK': '0055071350519059',
'PTYP': 'CARD',
'S2A1': '567+West+S2A1+Court+North',
'S2CC': 'US',
'S2CI': 'Gnome',
'S2EM': 'sdkTestShipTo@kountsdktestdomain.com',
'S2NM': 'SdkTestShipToFirst+SdkShipToLast',
'S2PC': '99762',
'S2PN': '208+777-1212',
'S2ST': 'AK',
'SESS': 'F8E874A38B7B4B6DBB71492A584A969D',
'SITE': 'DEFAULT',
'TOTL': '107783',
'UAGT': 'Mozilla%2F5.0+%28Macintosh%3B+Intel+Mac+OS+X+10%5F9%5F5%29+'\
'AppleWebKit%2F537.36+%28KHTML%2C+like+Gecko%29+'\
'Chrome%2F37.0.2062.124+Safari%2F537.36',
'UNIQ': 'F8E874A38B7B4B6DBB71',
'SDK': 'PYTH',
'VERS': '0710'
}
test_inquiry.py
#!/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.
"""Test Cases for Inquiry class"""
import pytest
import unittest
import uuid
from kount.client import Client
from kount.request import (AuthStatus, BankcardReply, InquiryMode,
CurrencyType, MerchantAcknowledgment)
from kount.inquiry import Inquiry
from kount.util.payment import CardPayment, Payment, GiftCardPayment
from kount.util.cartitem import CartItem
from kount.util.address import Address
from kount.config import SDKConfig
from kount.version import VERSION
__author__ = SDKConfig.SDK_AUTHOR
__version__ = VERSION
__maintainer__ = SDKConfig.SDK_MAINTAINER
__email__ = SDKConfig.MAINTAINER_EMAIL
__status__ = SDKConfig.STATUS
EMAIL_CLIENT = "sdkTest@kountsdktestdomain.com"
PTOK = "0007380568572514"
BILLING_ADDRESS = Address("1234 North B2A1 Tree Lane South",
"", "Albuquerque", "NM", "87101", "US")
SHIPPING_ADDRESS = Address("567 West S2A1 Court North", "",
"Gnome", "AK", "99762", "US")
expected = {
'ANID': '',
'AUTH': 'A',
'AVST': 'M',
'AVSZ': 'M',
'B2A1': '1234 North B2A1 Tree Lane South',
'B2A2': '',
'B2CC': 'US',
'B2CI': 'Albuquerque',
'B2PC': '87101',
'B2PN': '555-867-5309',
'B2ST': 'NM',
'BPREMISE': '',
'BSTREET': '',
'CASH': '4444',
'CURR': 'USD',
'CVVR': 'M',
'EMAL': EMAIL_CLIENT,
'FRMT': 'JSON',
# 'IPAD': '131.206.45.21',
'LAST4': '2514',
'MACK': 'Y',
'MERC': '999666',
'MODE': 'Q',
'NAME': 'SdkTestFirstName SdkTestLastName',
'PENC': 'KHASH',
# 'PENC': '',
'PROD_DESC[0]': '3000 CANDLEPOWER PLASMA FLASHLIGHT',
'PROD_ITEM[0]': 'SG999999',
'PROD_PRICE[0]': '68990',
'PROD_QUANT[0]': '2',
'PROD_TYPE[0]': 'SPORTING_GOODS',
# 'PTOK': '0007380568572514',
'PTOK': '000738F16NA2S935A5HY', # for khashed=True in Payment
'PTYP': 'CARD',
'S2A1': '567 West S2A1 Court North',
'S2A2': '',
'S2CC': 'US',
'S2CI': 'Gnome',
'S2EM': 'sdkTestShipToEmail@kountsdktestdomain.com',
'S2NM': 'SdkShipToFN SdkShipToLN',
'S2PC': '99762',
'S2PN': '555-777-1212',
'S2ST': 'AK',
'SDK': 'PYTH',
'SDK_VERSION': 'Sdk-Ris-%s-%s' % (SDKConfig.LANG, SDKConfig.SDK_VERSION),
'SITE': 'DEFAULT',
'SPREMISE': '',
'SSTREET': '',
'TOTL': '123456',
'VERS': SDKConfig.VERS,
}
def generate_unique_id():
"""unique session id"""
return str(uuid.uuid4()).replace('-', '').upper()
def default_inquiry(merchant_id, session_id, email_client, payment):
"""default_inquiry, PENC is not set"""
inq = Inquiry()
inq.set_request_mode(InquiryMode.DEFAULT)
inq.set_shipping_address(SHIPPING_ADDRESS)
inq.set_shipping_name("SdkShipToFN SdkShipToLN") # S2NM
inq.set_billing_address(BILLING_ADDRESS)
inq.set_currency(CurrencyType.USD) # CURR
inq.set_total('123456') # TOTL
inq.set_billing_phone_number("555-867-5309") # B2PN
inq.set_shipping_phone_number("555-777-1212") # S2PN
inq.set_email_client(email_client)
inq.set_customer_name("SdkTestFirstName SdkTestLastName")
inq.set_unique_customer_id(session_id[:20]) # UNIQ
inq.set_website("DEFAULT") # SITE
inq.set_email_shipping("sdkTestShipToEmail@kountsdktestdomain.com")
inq.set_ip_address("4.127.51.215") # IPAD
cart_items = list()
cart_items.append(CartItem("SPORTING_GOODS", "SG999999",
"3000 CANDLEPOWER PLASMA FLASHLIGHT",
'2', '68990'))
inq.set_shopping_cart(cart_items)
inq.version()
inq.set_version(SDKConfig.VERS) # 0695
inq.set_merchant(merchant_id)
inq.set_payment(payment) # PTOK
inq.set_session_id(session_id) # SESS
inq.set_order_number(session_id[:10]) # ORDR
inq.set_authorization_status(AuthStatus.APPROVE) # AUTH
inq.set_avs_zip_reply(BankcardReply.MATCH)
inq.set_avs_address_reply(BankcardReply.MATCH)
inq.set_avs_cvv_reply(BankcardReply.MATCH)
inq.set_merchant_acknowledgment(MerchantAcknowledgment.TRUE) # "MACK"
inq.set_cash('4444')
return inq
@pytest.mark.usefixtures("api_url", "api_key", "merchant_id")
class TestInquiry(unittest.TestCase):
"""Inquiry class tests"""
maxDiff = None
def setUp(self):
self.session_id = str(generate_unique_id())
self.client = Client(self.api_url, self.api_key)
def test_utilities(self):
"""test_utilities"""
payment = Payment(
payment_type="CARD",
payment_token=PTOK,
khashed=False)
self.assertEqual(payment._payment_type, 'CARD')
self.assertEqual(payment.last4, '2514')
self.assertEqual(payment.payment_token, '0007380568572514')
self.assertFalse(payment.khashed)
inq = default_inquiry(
merchant_id=self.merchant_id,
session_id=self.session_id,
email_client=EMAIL_CLIENT,
payment=payment)
expected_not_khashed = expected.copy()
expected_not_khashed["PTOK"] = '0007380568572514'
actual = inq.params
self.assertEqual(actual['PTYP'], 'CARD')
self.assertIn(expected_not_khashed['SDK_VERSION'],
actual['SDK_VERSION'])
del (actual['UNIQ'],
actual['IPAD'],
actual['SDK_VERSION'],
actual['SESS'],
actual['ORDR'],
expected_not_khashed['SDK_VERSION'],
expected_not_khashed['PENC'])
self.assertEqual(actual, expected_not_khashed)
def test_utilities_khashed(self):
"""test_utilities khashed"""
_expected = expected.copy()
payment = CardPayment(PTOK)
self.assertEqual(payment._payment_type, 'CARD')
self.assertEqual(payment.last4, '2514')
self.assertEqual(payment.payment_token, '000738F16NA2S935A5HY')
self.assertTrue(payment.khashed)
result = default_inquiry(
session_id=self.session_id,
merchant_id=self.merchant_id,
email_client=EMAIL_CLIENT,
payment=payment)
actual = result.params
self.assertEqual(actual['PTYP'], 'CARD')
self.assertIn(_expected['SDK_VERSION'], actual['SDK_VERSION'])
del (actual['UNIQ'],
actual['IPAD'],
actual['SDK_VERSION'],
actual['SESS'],
actual['ORDR'],
_expected['SDK_VERSION'])
self.assertEqual(actual, _expected)
def test_utilities_gift_khashed(self):
"""test_utilities GIFT khashed"""
_expected = expected.copy()
payment = GiftCardPayment(PTOK)
self.assertEqual(payment._payment_type, 'GIFT')
self.assertEqual(payment.last4, '2514')
self.assertEqual(payment.payment_token, '000738F16NA2S935A5HY')
self.assertTrue(payment.khashed)
result = default_inquiry(
session_id=self.session_id,
merchant_id=self.merchant_id,
email_client=EMAIL_CLIENT,
payment=payment)
actual = result.params
self.assertEqual(actual['PTYP'], 'GIFT')
self.assertIn(_expected['SDK_VERSION'], actual['SDK_VERSION'])
del (_expected['SDK_VERSION'],
_expected['PTYP'],
actual['PTYP'],
actual['UNIQ'],
actual['IPAD'],
actual['SDK_VERSION'],
actual['SESS'],
actual['ORDR'])
self.assertEqual(actual, _expected)
def test_inquiry_with_masked_payment(self):
"""test inquiry with masked payment"""
session_id = self.session_id
merchant_id = "999666"
email_client = EMAIL_CLIENT
inq = Inquiry()
inq.set_request_mode(InquiryMode.DEFAULT)
inq.set_shipping_address(SHIPPING_ADDRESS)
inq.set_shipping_name("SdkShipToFN SdkShipToLN") # S2NM
inq.set_billing_address(BILLING_ADDRESS)
inq.set_currency(CurrencyType.USD) # CURR
inq.set_total('123456') # TOTL
inq.set_billing_phone_number("555-867-5309") # B2PN
inq.set_shipping_phone_number("555-777-1212") # S2PN
inq.set_email_client(email_client)
inq.set_customer_name("SdkTestFirstName SdkTestLastName")
inq.set_unique_customer_id(session_id[:20]) # UNIQ
inq.set_website("DEFAULT") # SITE
inq.set_email_shipping("sdkTestShipToEmail@kountsdktestdomain.com")
inq.set_ip_address("4.127.51.215") # IPAD
cart_items = list()
cart_items.append(CartItem("SPORTING_GOODS", "SG999999",
"3000 CANDLEPOWER PLASMA FLASHLIGHT",
'2', '68990'))
inq.set_shopping_cart(cart_items)
inq.version()
inq.set_version(SDKConfig.VERS) # 0695
inq.set_merchant(merchant_id)
inq.set_session_id(session_id) # SESS
inq.set_order_number(session_id[:10]) # ORDR
inq.set_authorization_status(AuthStatus.APPROVE) # AUTH
inq.set_avs_zip_reply(BankcardReply.MATCH)
inq.set_avs_address_reply(BankcardReply.MATCH)
inq.set_avs_cvv_reply(BankcardReply.MATCH)
inq.set_merchant_acknowledgment(MerchantAcknowledgment.TRUE) # "MACK"
inq.set_cash('4444')
payment = CardPayment(PTOK, khashed=False)
inq.set_masked_payment(payment)
_expected = expected.copy()
_expected["PTOK"] = "000738XXXXXX2514"
_expected["PENC"] = "MASK"
_expected["PTYP"] = "CARD"
actual = inq.params
del (actual['UNIQ'],
actual['IPAD'],
actual['SESS'],
actual['ORDR'])
self.assertEqual(actual, _expected)
if __name__ == "__main__":
unittest.main()
test_payment.py
#!/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.
"Test Payment Type"
import unittest
import pytest
from kount.util.khash import Khash
from kount.util.payment import (
BillMeLaterPayment, CardPayment, CheckPayment,
GiftCardPayment, GooglePayment,
GreenDotMoneyPakPayment, NoPayment,
Payment, PaypalPayment)
from kount.version import VERSION
from kount.config import SDKConfig
__author__ = SDKConfig.SDK_AUTHOR
__version__ = VERSION
__maintainer__ = SDKConfig.SDK_MAINTAINER
__email__ = SDKConfig.MAINTAINER_EMAIL
__status__ = SDKConfig.STATUS
@pytest.mark.usefixtures("conf_key")
class TestPaymentType(unittest.TestCase):
"""Test Payment Type"""
def setUp(self):
self.test = 1234567890*1000000000
def test_giftcardpayment(self):
"""giftcard payment"""
ptype = GiftCardPayment(gift_card_number=self.test, khashed=False)
self.assertTrue(isinstance(ptype, Payment))
self.assertEqual(ptype.last4, str(self.test)[-4:])
self.assertFalse(ptype.khashed)
self.assertEqual(ptype.payment_type, "GIFT")
self.assertEqual(ptype.payment_token, str(self.test))
def test_payments(self):
"all predefined payments"
plist = (Payment, BillMeLaterPayment, CardPayment,
CheckPayment, GiftCardPayment, GooglePayment,
GreenDotMoneyPakPayment, NoPayment, Payment, PaypalPayment)
payment_dict = {
"BLML": BillMeLaterPayment(self.test, khashed=False),
"CARD": CardPayment(self.test, khashed=False),
"CHEK": CheckPayment(self.test, khashed=False),
"CHECK": CheckPayment(self.test, khashed=False), # backwards compatibility
"GIFT": GiftCardPayment(self.test, khashed=False),
"GOOG": GooglePayment(self.test, khashed=False),
"GDMP": GreenDotMoneyPakPayment(self.test, khashed=False),
"NONE": NoPayment(),
"PYPL": PaypalPayment(self.test, khashed=False),
}
ptypes = []
for current in payment_dict:
curp = payment_dict[current]
if current == "NONE":
self.assertEqual(curp.last4, "NONE")
self.assertIsNone(curp.payment_token)
else:
self.assertEqual(curp.last4, str(self.test)[-4:])
self.assertEqual(curp.payment_token, str(self.test))
if current == "CHECK":
self.assertEqual(curp._payment_type, "CHEK")
else:
self.assertEqual(curp._payment_type, current)
ptypes.append(payment_dict[current])
self.assertIsInstance(payment_dict[current], plist)
if curp.payment_token is not None:
self.assertEqual(curp.payment_token, str(self.test))
def test_user_defined_payment(self):
"user defined payments"""
curp = Payment("PM42", self.test, False)
self.assertEqual(curp.last4, str(self.test)[-4:])
self.assertEqual(curp.payment_token, str(self.test))
self.assertFalse(curp.khashed)
self.assertEqual(curp._payment_type, "PM42")
self.assertEqual(curp.payment_token, str(self.test))
self.assertIsInstance(curp, Payment)
def test_user_defined_payment_khashed(self):
"user defined payments with Payment - khashed token"
curp = Payment("PM42", self.test, True)
self.assertEqual(curp.last4, str(self.test)[-4:])
self.assertEqual(curp.payment_token,
Khash.get().hash_payment_token(self.test))
self.assertTrue(curp.khashed)
self.assertEqual(curp._payment_type, "PM42")
self.assertIsInstance(curp, Payment)
def test_user_defined_newpayment(self):
"user defined payments - token khashed and notkhashed "
curp = Payment("PM42", self.test, khashed=False)
self.assertEqual(curp.last4, str(self.test)[-4:])
self.assertEqual(curp.payment_token, str((self.test)))
self.assertFalse(curp.khashed)
self.assertEqual(curp.payment_type, "PM42")
self.assertIsInstance(curp, Payment)
curp = Payment("PM42", self.test, True)
self.assertEqual(curp.last4, str(self.test)[-4:])
self.assertEqual(curp.payment_token,
Khash.get().hash_payment_token(self.test))
self.assertTrue(curp.khashed)
if __name__ == "__main__":
unittest.main(
#~ defaultTest="TestPaymentType.test_payments"
)
test_validation_error.py
test_khash.py
#!/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 unittest
import pytest
from kount.version import VERSION
from kount.util.khash import Khash
from kount.config import SDKConfig
__author__ = SDKConfig.SDK_AUTHOR
__version__ = VERSION
__maintainer__ = SDKConfig.SDK_MAINTAINER
__email__ = SDKConfig.MAINTAINER_EMAIL
__status__ = SDKConfig.STATUS
@pytest.mark.usefixtures("conf_key")
class TestKhash(unittest.TestCase):
"""Khash class test cases"""
def setUp(self):
self.list_for_hash = ["4111111111111111",
'5199185454061655',
4259344583883]
self.expected = ['WMS5YA6FUZA1KC', '2NOQRXNKTTFL11', 'FEXQI1QS6TH2O5']
self.merchant_id = '666666'
self.khash = Khash.get()
def test_token_valid(self):
"""valid token"""
self.assertEqual(
"BADTOKGM3BD98ZY871QB",
self.khash.hash_payment_token(token="BADTOKEN"))
self.assertEqual(
"000738F16NA2S935A5HY",
self.khash.hash_payment_token(token="0007380568572514"))
for i, plain_text in enumerate(self.list_for_hash):
card_hashed = self.khash.hash_payment_token(token=plain_text)
expected = "%s%s" % (str(self.list_for_hash[i])[:6],
self.expected[i])
self.assertEqual(card_hashed, expected)
self.assertTrue(self.khash.khashed(card_hashed))
def test_token_invalid(self):
"""invalid token"""
with self.assertRaises(ValueError):
self.khash.hash_payment_token(token="")
with self.assertRaises(ValueError):
self.khash.hash_payment_token(token=None)
card_hashed = self.khash.hash_payment_token(token="10**200")
self.assertEqual(card_hashed, "10**20GA6AXR02LVUE5X")
with self.assertRaises(ValueError):
self.khash.hash_payment_token(token=-42)
with self.assertRaises(ValueError):
self.khash.hash_payment_token(token=10**200)
with self.assertRaises(ValueError):
self.khash.hash_payment_token(token=0)
card_hashed = self.khash.hash_payment_token(token="Beatles")
self.assertEqual(card_hashed, "Beatle5STRFTYPXBR14E")
self.assertTrue(self.khash.khashed(card_hashed))
bad = "John"
try:
self.khash.hash_payment_token(token=bad)
except ValueError as vale:
self.assertEqual("incorrect arg: [%s]" % bad, str(vale))
with self.assertRaises(ValueError):
self.assertTrue(self.khash.hash_payment_token(token=bad))
def test_hash_gift_card(self):
"""gift card"""
for i in range(len(self.list_for_hash)):
card_hashed = self.khash.hash_gift_card(
self.merchant_id, self.list_for_hash[i])
expected = "%s%s" % (self.merchant_id, self.expected[i])
self.assertEqual(card_hashed, expected)
self.assertTrue(self.khash.khashed(card_hashed))
def test_hash_gift_card_int_merchantid(self):
"""test_hash_gift_card_int_merchantid"""
for i in range(len(self.list_for_hash)):
card_hashed = self.khash.hash_gift_card(
self.merchant_id, self.list_for_hash[i])
expected = "%s%s" % (self.merchant_id, self.expected[i])
self.assertEqual(card_hashed, expected)
self.assertTrue(self.khash.khashed(card_hashed))
def test_list_for_hash_empty(self):
"""list_for_hash_empty"""
list_for_hash = ""
with self.assertRaises(ValueError):
self.khash.hash_gift_card(self.merchant_id, list_for_hash)
def test_list_for_hash_none(self):
"""hash_none"""
list_for_hash = None
with self.assertRaises(ValueError):
self.khash.hash_gift_card(self.merchant_id, list_for_hash)
def test_gift_card_empty_values(self):
"""gift_card_empty_values"""
list_for_hash = []
with self.assertRaises(ValueError):
self.khash.hash_gift_card(self.merchant_id, list_for_hash)
def test_gift_card_no_merchant(self):
"""gift card without merchant"""
list_for_hash = []
merchant_id = ""
with self.assertRaises(ValueError):
self.khash.hash_gift_card(merchant_id, list_for_hash)
def test_gift_card_merchant_empty_str(self):
"""gift_card_merchant_empty_str"""
merchant_id = ""
with self.assertRaises(ValueError):
self.khash.hash_gift_card(merchant_id, self.list_for_hash)
def test_list_for_hash_merchant_none(self):
"""list_for_hash_merchant_none"""
list_for_hash = []
merchant_id = None
with self.assertRaises(ValueError):
self.khash.hash_gift_card(merchant_id, list_for_hash)
def test_list_for_hash_args_missing(self):
"""list_for_hash_args_missing"""
list_for_hash = None
merchant_id = None
with self.assertRaises(ValueError):
self.khash.hash_gift_card(merchant_id, list_for_hash)
if __name__ == "__main__":
unittest.main(verbosity=2)
test_ris_test_suite.py
#!/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.
"""Test Cases from sdk documentation"""
import unittest
import pytest
from kount.request import (AuthStatus, BankcardReply, InquiryMode,
CurrencyType, MerchantAcknowledgment)
from kount.request import Update, UpdateMode
from kount.util.khash import Khash
from kount.client import Client
from kount.util.cartitem import CartItem
from kount.util.payment import CardPayment
from kount.version import VERSION
from .test_basic_connectivity import generate_unique_id, default_inquiry
from kount.config import SDKConfig
__author__ = SDKConfig.SDK_AUTHOR
__version__ = VERSION
__maintainer__ = SDKConfig.SDK_MAINTAINER
__email__ = SDKConfig.MAINTAINER_EMAIL
__status__ = SDKConfig.STATUS
# raise_errors - if True - raise errors instead of logging in debugger
_RAISE_ERRORS = False
PTOK = "0007380568572514"
EMAIL_CLIENT = "sdkTest@kountsdktestdomain.com"
@pytest.mark.usefixtures("merchant_id", "api_key", "api_url")
class TestRisTestSuite(unittest.TestCase):
"""Ris Test Suite
default logging errors instead fo raising
to raise errors - put raise_errors=True in Client:
Client(url=URL_API, key=KOUNT_API_KEY,
timeout=TIMEOUT, RAISE_ERRORS=True)
"""
maxDiff = None
def setUp(self):
self.session_id = generate_unique_id()[:32]
self.payment = CardPayment(PTOK, khashed=False)
self.client = Client(self.api_url, self.api_key,
raise_errors=_RAISE_ERRORS)
def inquiry(self):
return default_inquiry(
merchant_id=self.merchant_id,
session_id=self.session_id,
email_client=EMAIL_CLIENT,
payment=self.payment)
def test_1_ris_q_1_item_required_field_1_rule_review(self):
"""test_1_ris_q_1_item_required_field_1_rule_review"""
res = self.client.process(self.inquiry())
self.assertIsNotNone(res)
self.assertEqual("R", res.get_auto())
self.assertEqual(0, len(res.get_warnings()))
expected = ['Review if order total > $1000 USD']
actual = sorted(res.get_rules_triggered().values())
self.assertEqual(expected, actual)
self.assertEqual(self.session_id, res.get_session_id())
self.assertEqual(res.get_session_id()[:10], res.get_order_id())
def test_2_ris_q_multi_cart_items2optional_fields2rules_decline(self):
"""test_2_ris_q_multi_cart_items2optional_fields2rules_decline
cart_item - PROD_TYPE[0, PROD_ITEM[0], PROD_DESC[0]
PROD_QUANT[0],PROD_PRICE[0]"""
inq = self.inquiry()
inq.set_user_agent(
"Mozilla/5.0 (Macintosh; "
"Intel Mac OS X 10_9_5) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/37.0.2062.124 "
"Safari/537.36")
inq.set_total(123456789)
cart_items = [
CartItem(
"cart item type 0", "cart item 0",
"cart item 0 description", 10, 1000),
CartItem(
"cart item type 1", "cart item 1",
"cart item 1 description", 11, 1001),
CartItem(
"cart item type 2", "cart item 2",
"cart item 1 description", 12, 1002)]
inq.set_shopping_cart(cart_items)
res = self.client.process(inq)
self.assertIsNotNone(res)
self.assertEqual("D", res.get_auto())
self.assertEqual(0, len(res.get_warnings()))
expected = sorted(
{'1024842': 'Review if order total > $1000 USD',
'1024844': 'Decline if order total > $1000000 USD'}.values())
actual = sorted(res.get_rules_triggered().values())
self.assertEqual(expected, actual)
def test_3_ris_q_with_user_defined_fields(self):
"""test_3_ris_q_with_user_defined_fields"""
udf1 = "ARBITRARY_ALPHANUM_UDF"
udf2 = "ARBITRARY_NUMERIC_UDF"
inq = self.inquiry()
inq.set_user_defined_field(udf1, "alphanumeric trigger value")
inq.set_user_defined_field(udf2, "777")
res = self.client.process(inq)
self.assertIsNotNone(res)
self.assertEqual("R", res.get_auto())
self.assertEqual(3, len(res.get_rules_triggered()))
self.assertEqual(0, len(res.get_warnings()))
self.assertEqual(0, len(res.get_errors()))
self.assertEqual(0, len(res.get_counters_triggered()))
expected = sorted(
{'1025086': 'review if %s contains "trigger"' % udf1,
'1024842': 'Review if order total > $1000 USD',
'1025088': "review if %s == 777" % udf2}.values())
actual = sorted(res.get_rules_triggered().values())
self.assertEqual(expected, actual)
def test_4_ris_q_hard_error_expected(self):
"""test_4_ris_q hard_error_expected,
overwrite the PTOK value to induce an error in the RIS"""
inq = self.inquiry()
inq.params["PENC"] = "KHASH"
inq.params["PTOK"] = "BADPTOK"
res = self.client.process(inq)
self.assertIsNotNone(res)
self.assertEqual(
["332 BAD_CARD Cause: [PTOK invalid format], "
"Field: [PTOK], Value: [hidden]"],
res.get_errors())
self.assertEqual("E", res.get_mode())
self.assertEqual(332, res.get_error_code())
self.assertEqual(0, len(res.get_warnings()))
def test_5_ris_q_warning_approved(self):
"""test_5_ris_q_warning_approved"""
inq = self.inquiry()
inq.set_total(1000)
label = "UDF_DOESNOTEXIST"
mesg = "throw a warning please!"
inq.set_user_defined_field(label, mesg)
res = self.client.process(inq)
self.assertIsNotNone(res)
self.assertEqual("A", res.get_auto())
self.assertEqual(2, len(res.get_warnings()))
self.assertEqual(res.get_warnings()[0],
"399 BAD_OPTN Field: [UDF], Value: "
"[%s=>%s]" % (label, mesg))
self.assertEqual(res.get_warnings()[1],
"399 BAD_OPTN Field: [UDF], Value: "
"[The label [%s]"
" is not defined for merchant ID [%s].]" % (
label, self.merchant_id))
def test_6_ris_q_hard_soft_errors_expected(self):
"""test_6_ris_q_hard_soft_errors_expected"""
inq = self.inquiry()
inq.params["PENC"] = "KHASH"
inq.params["PTOK"] = "BADPTOK"
label = "UDF_DOESNOTEXIST"
mess = "throw a warning please!"
inq.params["UDF[%s]" % label] = mess
res = self.client.process(inq)
self.assertIsNotNone(res)
self.assertEqual("E", res.get_mode())
self.assertEqual(332, res.get_error_code())
self.assertEqual(1, len(res.get_errors()))
self.assertEqual(
[("332 BAD_CARD Cause: [PTOK invalid format], "
"Field: [PTOK], Value: [hidden]")],
res.get_errors())
warnings = res.get_warnings()
self.assertEqual(2, len(warnings))
self.assertEqual(
"399 BAD_OPTN Field: [UDF], Value: [%s=>%s]"
% (label, mess), warnings[0])
self.assertEqual(
"399 BAD_OPTN Field: [UDF], Value: [The label [%s] "
"is not defined for merchant ID [%s].]"
% (label, self.merchant_id), warnings[1])
def test_7_ris_w2_kc_rules_review(self):
"""test_7_ris_w2_kc_rules_review"""
inq = self.inquiry()
inq.set_request_mode(InquiryMode.WITH_THRESHOLDS)
inq.set_total(10001)
inq.set_kount_central_customer_id("KCentralCustomerOne")
res = self.client.process(inq)
self.assertIsNotNone(res)
self.assertEqual(res.get_kc_decision(), 'R')
self.assertEqual(len(res.get_kc_warnings()), 0)
self.assertEqual(len(res.get_kc_events()), 2)
events = res.get_kc_events()
print(events)
self.assertEqual(events[0].code, 'billingToShippingAddressReview')
self.assertEqual(events[1].expression, '10001 > 10000')
self.assertEqual(events[0].decision, 'R')
self.assertEqual(events[1].code, 'orderTotalReview')
self.assertEqual(events[0].expression, '5053 > 1')
self.assertEqual(events[1].decision, 'R')
def test_8_ris_j_1_kount_central_rule_decline(self):
"""test_8_ris_j_1_kount_central_rule_decline"""
inq = self.inquiry()
inq.set_request_mode(InquiryMode.JUST_THRESHOLDS)
inq.set_total(1000)
inq.set_kount_central_customer_id("KCentralCustomerDeclineMe")
if not _RAISE_ERRORS:
res = self.client.process(inq)
self.assertIsNotNone(res)
self.assertEqual("D", res.get_kc_decision())
self.assertEqual(0, len(res.get_kc_warnings()))
kc_events = res.get_kc_events()
self.assertEqual(1, len(kc_events), )
self.assertEqual(kc_events[0].code, "orderTotalDecline")
def test_9_mode_u_after_mode_q(self):
"""test_9_mode_u_after_mode_q"""
res = self.client.process(self.inquiry())
self.assertIsNotNone(res)
transaction_id = res.get_transaction_id()
session_id = res.get_session_id()
order_id = res.get_order_id()
update1 = Update()
update1.set_mode(UpdateMode.NO_RESPONSE)
update1.set_transaction_id(transaction_id)
update1.set_merchant(self.merchant_id)
update1.set_session_id(session_id)
update1.set_order_number(order_id)
# PTOK has to be khashed manually because of its explicit setting
token_new = "5386460135176807"
update1.params["PTOK"] = Khash.get().hash_payment_token(token_new)
update1.params["LAST4"] = token_new[-4:]
update1.params["FRMT"] = 'JSON'
update1.set_khash_payment_encoding(True)
update1.set_merchant_acknowledgment(MerchantAcknowledgment.TRUE)
update1.set_authorization_status(AuthStatus.APPROVE)
update1.set_avs_zip_reply(BankcardReply.MATCH)
update1.set_avs_address_reply(BankcardReply.MATCH)
update1.set_avs_cvv_reply(BankcardReply.MATCH)
res = self.client.process(update1)
self.assertIsNotNone(res)
self.assertEqual("U", res.get_mode())
self.assertIsNone(res.get_geox())
self.assertIsNone(res.get_score())
self.assertIsNone(res.get_auto())
def test_10_mode_x_after_mode_q(self):
"""test_10_mode_x_after_mode_q
PTOK has to be khashed manually because of
its explicit setting"""
res = self.client.process(self.inquiry())
self.assertIsNotNone(res)
transaction_id = res.get_transaction_id()
session_id = res.get_session_id()
order_id = res.get_order_id()
update1 = Update()
update1.set_mode(UpdateMode.WITH_RESPONSE)
update1.set_transaction_id(transaction_id)
update1.set_merchant(self.merchant_id)
update1.set_session_id(session_id)
update1.set_order_number(order_id)
token_new = "5386460135176807"
update1.set_khash_payment_encoding(self.payment.khashed)
if self.payment.khashed:
token_new = Khash.get().hash_payment_token(token_new)
update1.params["PTOK"] = token_new
update1.params["LAST4"] = token_new[-4:]
update1.params["FRMT"] = 'JSON'
update1.set_merchant_acknowledgment(MerchantAcknowledgment.TRUE)
update1.set_authorization_status(AuthStatus.APPROVE)
update1.set_avs_zip_reply(BankcardReply.MATCH)
update1.set_avs_address_reply(BankcardReply.MATCH)
update1.set_avs_cvv_reply(BankcardReply.MATCH)
res = self.client.process(update1)
self.assertIsNotNone(res)
self.assertEqual("X", res.get_mode())
self.assertIsNotNone(res.get_geox())
self.assertIsNotNone(res.get_score())
self.assertIsNotNone(res.get_auto())
def test_11_mode_p(self):
res = self.client.process(self.inquiry())
self.assertIsNotNone(res)
inq = self.inquiry()
inq.set_request_mode(InquiryMode.PHONE)
inq.set_anid("2085551212")
inq.set_total(1000)
res = self.client.process(inq)
self.assertIsNotNone(res)
self.assertEqual("P", res.get_mode())
self.assertEqual("A", res.get_auto())
def test_14_ris_q_using_payment_encoding_mask_valid(self):
"""test_14_ris_q_using_payment_encoding_mask_valid"""
ptok_2 = "370070XXXXX9797"
last4 = ptok_2[-4:]
penc = 'MASK'
res = self.client.process(self.inquiry())
self.assertIsNotNone(res)
inq = self.inquiry()
inq.params['LAST4'] = last4
inq.params['PTOK'] = ptok_2
inq.params['PENC'] = penc
res = self.client.process(inq)
self.assertIsNotNone(res)
self.assertEqual("AMEX", res.get_brand())
def test_15_ris_q_using_payment_encoding_mask_error(self):
"""test_15_ris_q_using_payment_encoding_mask_error"""
ptok_2 = "370070538959797"
last4 = ptok_2[-4:]
penc = 'MASK'
inq = self.inquiry()
res = self.client.process(inq)
self.assertIsNotNone(res)
inq.params['LAST4'] = last4
inq.params['PTOK'] = ptok_2
inq.params['PENC'] = penc
res = self.client.process(inq)
self.assertIsNotNone(res)
self.assertEqual({
'ERRO': 340,
'ERROR_0':
'340 BAD_MASK Cause: [value [%s] did not match regex '
'/^\\d{6}X{5,9}\\d{1,4}$/], Field: [PTOK], Value: '
'[%s]' % (ptok_2, ptok_2),
'ERROR_COUNT': 1,
'MODE': 'E',
'WARNING_COUNT': 0}, res.params)
class TestRisTestSuiteKhashed(TestRisTestSuite):
"""Ris Test Suite Khashed
default logging errors instead fo raising
to raise errors - put raise_errors=True in Client:
Client(url=URL_API, key=KOUNT_API_KEY,
timeout=TIMEOUT, RAISE_ERRORS=True)
"""
maxDiff = None
def setUp(self):
self.session_id = generate_unique_id()[:32]
self.payment = CardPayment(PTOK)
self.client = Client(self.api_url, self.api_key,
raise_errors=_RAISE_ERRORS)
if __name__ == "__main__":
unittest.main(verbosity=2)
test_ris_validator.py
test_xmlparser.py
test_bed_examples.py
#!/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.
"""Test Cases for an example implementation
generate_unique_id
put test data in user_inquiry
"""
import unittest
import pytest
from kount.client import Client
from kount.config import SDKConfig
from kount.util.payment import CardPayment
from kount.inquiry import Inquiry
from kount.request import (AuthStatus, BankcardReply, InquiryMode,
CurrencyType, MerchantAcknowledgment)
from kount.util.cartitem import CartItem
from kount.util.address import Address
from kount.version import VERSION
from .test_inquiry import generate_unique_id
__author__ = SDKConfig.SDK_AUTHOR
__version__ = VERSION
__maintainer__ = SDKConfig.SDK_MAINTAINER
__email__ = SDKConfig.MAINTAINER_EMAIL
__status__ = SDKConfig.STATUS
PTOK = "4111111111111111"
EMAIL = 'john@test.com'
BILLING_ADDRESS = Address("", "", "Manchester", "NH", "03109", "US")
BILLING_PHONE = "555-888-5678"
def user_inquiry(session_id, merchant_id, email_client, payment):
"""user_inquiry, PENC is not set"""
result = Inquiry()
result.set_request_mode(InquiryMode.DEFAULT)
result.set_billing_address(BILLING_ADDRESS)
result.set_currency(CurrencyType.USD) # CURR
result.set_total(3500) # TOTL
result.set_billing_phone_number(BILLING_PHONE) # B2PN
result.set_email_client(email_client)
result.set_customer_name("J Test")
result.set_unique_customer_id(session_id[:20]) # UNIQ
result.set_website("DEFAULT") # SITE
# result.set_ip_address("4.127.51.215") # IPAD
result.set_ip_address('2001:0:3238:DFE1:63::FEFB') # IPAD
cart_items = [CartItem("1", "8482", "Standard Monthly Plan", 1, '3500')]
result.set_shopping_cart(cart_items)
result.version()
result.set_version(SDKConfig.VERS) # 0710
result.set_merchant(merchant_id)
result.set_payment(payment) # PTOK
result.set_session_id(session_id) # SESS
result.set_order_number(session_id[:10]) # ORDR
result.set_authorization_status(AuthStatus.APPROVE) # AUTH
result.set_avs_zip_reply(BankcardReply.MATCH)
result.set_avs_address_reply(BankcardReply.MATCH)
result.set_avs_cvv_reply(BankcardReply.MATCH)
result.set_merchant_acknowledgment(MerchantAcknowledgment.TRUE) # "MACK"
return result
expected = {
'ANID': '',
'AUTH': 'A',
'AVST': 'M',
'AVSZ': 'M',
'B2A1': '',
'B2A2': '',
'B2CC': 'US',
'B2CI': 'Manchester',
'B2PC': '03109',
'B2PN': BILLING_PHONE,
'B2ST': 'NH',
'BPREMISE': '',
'BSTREET': '',
'CURR': 'USD',
'CVVR': 'M',
'EMAL': EMAIL,
'FRMT': 'JSON',
'IPAD': '2001:0:3238:DFE1:63::FEFB',
'LAST4': '1111',
'MACK': 'Y',
'MERC': '999666',
'MODE': 'Q',
'NAME': 'J Test',
# 'ORDR': '4F7132C2FE',
# 'PENC': 'KHASH',
'PROD_DESC[0]': 'Standard Monthly Plan',
'PROD_ITEM[0]': '8482',
'PROD_PRICE[0]': '3500',
'PROD_QUANT[0]': 1,
'PROD_TYPE[0]': '1',
'PTOK': PTOK,
'PTYP': 'CARD',
'SDK': 'PYTH',
# 'SDK_VERSION': 'Sdk-Ris-Python-0695-201708301601',
# 'SESS': '4F7132C2FE8547928CD9329B78AA0A59',
'SITE': 'DEFAULT',
'TOTL': 3500,
# 'UNIQ': '4F7132C2FE8547928CD9',
'VERS': '0720'}
@pytest.mark.usefixtures("api_url", "api_key", "merchant_id")
class TestBed(unittest.TestCase):
"""Test Bed for use-cases, with & without Khash"""
maxDiff = None
def setUp(self):
self.session_id = generate_unique_id()[:32]
self.email_client = EMAIL
def test_not_khashed(self):
"""test without khashed card"""
# required khashed=False
payment = CardPayment(PTOK, False)
self.inq = user_inquiry(
self.session_id, self.merchant_id, self.email_client,
payment=payment)
self.assertNotIn('PENC', self.inq.params)
self.compare(expected)
def test_khashed(self):
"""test with khashed card"""
# not required default khashed=True
payment = CardPayment(PTOK)
self.inq = user_inquiry(
self.session_id, self.merchant_id, self.email_client,
payment=payment)
self.assertIn('PENC', self.inq.params)
self.assertEqual('KHASH', self.inq.params['PENC'])
expected_khashed = expected.copy()
expected_khashed['PENC'] = 'KHASH'
expected_khashed['PTOK'] = '411111WMS5YA6FUZA1KC'
self.compare(expected_khashed)
def compare(self, expected_dict):
"""common method for both tests"""
res = Client(self.api_url, self.api_key).process(self.inq)
self.assertIsNotNone(res)
self.assertNotIn('ERRO', repr(res))
actual = self.inq.params.copy()
remove = ['SDK_VERSION', 'SESS', 'UNIQ', 'ORDR']
for k in remove:
if k in actual:
del actual[k]
self.assertEqual(expected_dict, actual)
if __name__ == "__main__":
unittest.main(verbosity=2)
test_base85_encode_decode.py
#!/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 unittest
import sys
from kount.util.a85 import a85decode, a85encode
from kount.version import VERSION
from kount.config import SDKConfig
__author__ = SDKConfig.SDK_AUTHOR
__version__ = VERSION
__maintainer__ = SDKConfig.SDK_MAINTAINER
__email__ = SDKConfig.MAINTAINER_EMAIL
__status__ = SDKConfig.STATUS
class Base85EncodeDecodeTest(unittest.TestCase):
"""Base85EncodeDecodeTest"""
plain_text = "This is sample text for testing purposes."
encoded_text = b"<+oue+DGm>F(&p)Ch4`2AU&;>AoD]4FCfN8Bl7Q+E-62?Df]K2/c"
def test_encode(self):
"""test valid encode"""
encoded = a85encode(self.plain_text.encode('utf-8'))
decoded = a85decode(encoded)
self.assertEqual(encoded, self.encoded_text)
self.assertEqual(decoded, self.plain_text.encode('utf-8'))
def test_decode(self):
"""test valid decode"""
decoded = a85decode(self.encoded_text)
self.assertEqual(decoded, self.plain_text.encode('utf-8'))
def test_decode_invalid(self):
"""test invalid decode"""
self.assertEqual(a85decode(b''), b'')
self.assertRaises(ValueError, a85decode, self.plain_text)
def test_encode_invalid(self):
"""test invalid encode"""
self.assertEqual(a85encode(b''), b'')
if sys.version_info[0] > 2: # TODO
self.assertRaises(TypeError, a85encode, '')
self.assertRaises(TypeError, a85encode, self.plain_text)
if __name__ == "__main__":
unittest.main(verbosity=2)