diff --git a/example_project/templates/netaxept/query_result.html b/example_project/templates/netaxept/query_result.html
new file mode 100644
index 0000000..7155071
--- /dev/null
+++ b/example_project/templates/netaxept/query_result.html
@@ -0,0 +1,13 @@
+
+
+
+Annuled: {{ query_response.annuled }}
+
+Authorized: {{ query_response.authorized }}
+
+Status code: {{ query_response.raw_response.status_code }}
+
+Raw response:
{{ query_response.raw_response.text }}
+
+
+
diff --git a/example_project/templates/operation_list.html b/example_project/templates/operation_list.html
index 4206c31..b713084 100644
--- a/example_project/templates/operation_list.html
+++ b/example_project/templates/operation_list.html
@@ -21,6 +21,9 @@ Operations
Authorize - Payment intents manual flow
{% elif payment.gateway == 'netaxept' %}
Register and Authorize
+ {% if payment.token %}
+ Query
+ {% endif %}
{% endif %}
See payment in admin
diff --git a/example_project/views/netaxept.py b/example_project/views/netaxept.py
index a48e715..89ae6d8 100644
--- a/example_project/views/netaxept.py
+++ b/example_project/views/netaxept.py
@@ -1,9 +1,11 @@
"""
Example views for interactive testing of payment with netaxept.
"""
+
from django.http import HttpRequest
from django.http import HttpResponse
from django.shortcuts import redirect, get_object_or_404
+from django.template.response import TemplateResponse
from django.urls import path
from django.views.decorators.http import require_GET
from structlog import get_logger
@@ -11,7 +13,7 @@
from payment import get_payment_gateway
from payment.gateways.netaxept import actions
from payment.gateways.netaxept import gateway_to_netaxept_config
-from payment.gateways.netaxept.netaxept_protocol import get_payment_terminal_url
+from payment.gateways.netaxept import netaxept_protocol
from payment.models import Payment
logger = get_logger()
@@ -20,7 +22,7 @@
@require_GET
def register_and_authorize(request: HttpRequest, payment_id: int) -> HttpResponse:
"""
- Register the payment with netaxept, and take the user to the terminal page for payment authorization.
+ Register the payment with netaxept, and take the user to the terminal page for payment authorization
"""
logger.info('netaxept-register-and-authorize', payment_id=payment_id)
@@ -29,7 +31,7 @@ def register_and_authorize(request: HttpRequest, payment_id: int) -> HttpRespons
payment = get_object_or_404(Payment, id=payment_id)
payment_gateway, gateway_config = get_payment_gateway(payment.gateway)
netaxept_config = gateway_to_netaxept_config(gateway_config)
- return redirect(get_payment_terminal_url(config=netaxept_config, transaction_id=transaction_id))
+ return redirect(netaxept_protocol.get_payment_terminal_url(config=netaxept_config, transaction_id=transaction_id))
@require_GET
@@ -39,28 +41,34 @@ def after_terminal(request):
We expect query-string parameters: transactionId and responseCode.
See: https://shop.nets.eu/web/partners/response-codes
- We know we opened the terminal with AutoAuth set to True, so we interpret this callback to mean that an
- AUTH operation was performed. Netaxept does not provide any way to authenticate that the callback really comes
- from netaxept (other than them sending us a valid hard to guess 32 character long transaction_id), so we cannot
- be 100% sure of the information received.
- We decide to store the authorization operation nonetheless. If by any chance the information was faked we will
- detect it in the next step, when we try to capture the money.
+ We opened the terminal with AutoAuth set to True, so this callback should mean an AUTH operation was performed
+ (and the response_code should indicate the outcome of the operation).
+ But we cannot rely on the information received (because netaxept does not include any digital signature),
+ so we go on and verify if the authorization was succesful.
"""
transaction_id = request.GET['transactionId']
response_code = request.GET['responseCode']
- logger.info('netaxept-webhook', transaction_id=transaction_id, response_code=response_code)
+ logger.info('netaxept-after-terminal', transaction_id=transaction_id, response_code=response_code)
+
+ payment_authorized = actions.verify_auth_transaction(transaction_id=transaction_id, response_code=response_code)
- success = (response_code == 'OK')
+ return HttpResponse('transaction id {}, response code {}, payment authorized {}'
+ .format(transaction_id, response_code, payment_authorized))
- actions.create_auth_transaction(transaction_id=transaction_id, success=success)
- if success:
- return HttpResponse('ok')
- elif response_code:
- return HttpResponse('response code {}'.format(response_code))
+def query(request: HttpRequest, transaction_id: str) -> HttpResponse:
+ """
+ Retries the status of the given transaction from netaxept.
+ """
+ logger.info('netaxept-query', transaction_id=transaction_id)
+ payment_gateway, gateway_config = get_payment_gateway('netaxept')
+ netaxept_config = gateway_to_netaxept_config(gateway_config)
+ query_response = netaxept_protocol.query(config=netaxept_config, transaction_id=transaction_id)
+ return TemplateResponse(request, 'netaxept/query_result.html', {'query_response': query_response})
urls = [
path('register_and_authorize/', register_and_authorize, name='netaxept_register_and_authorize'),
path('after_terminal', after_terminal, name='netaxept_after_terminal'),
+ path('query/', query, name='netaxept_query'),
]
diff --git a/payment/gateways/netaxept/actions.py b/payment/gateways/netaxept/actions.py
index eb7c31f..a3dfc42 100644
--- a/payment/gateways/netaxept/actions.py
+++ b/payment/gateways/netaxept/actions.py
@@ -1,11 +1,15 @@
from django.db import transaction
from django.shortcuts import get_object_or_404
+from structlog import get_logger
+from payment.gateways.netaxept.netaxept_protocol import query
from payment import get_payment_gateway, TransactionKind
from payment.gateways.netaxept import NetaxeptProtocolError
from payment.gateways.netaxept import netaxept_protocol, gateway_to_netaxept_config
from payment.models import Payment, Transaction
+logger = get_logger()
+
class NetaxeptException(Exception):
def __str__(self):
@@ -19,13 +23,15 @@ class PaymentAlreadyRegistered(NetaxeptException):
def register_payment(payment_id: int) -> str:
"""
- Registers the payment with netaxept.
- - Records a Transaction representing the registration.
- Stores the newly created netaxept transaction_id in the Payment.
+ - Records a Transaction representing the registration.
:param payment_id: The id of a Payment object.
:return: The newly created netaxept transaction_id
- :raises NetaxeptException: If the registration fails
+ :raises NetaxeptException: If the payment was already registered or the registration fails
"""
+ logger.info('netaxept-actions-register', payment_id=payment_id)
+
payment = get_object_or_404(Payment, id=payment_id)
if payment.token != '':
@@ -39,7 +45,8 @@ def register_payment(payment_id: int) -> str:
config=netaxept_config,
order_number=payment_id,
amount=payment.total,
- language='en')
+ language='en',
+ customer_email=payment.customer_email)
except NetaxeptProtocolError as exception:
Transaction.objects.create(
payment=payment,
@@ -52,6 +59,9 @@ def register_payment(payment_id: int) -> str:
raise NetaxeptException(exception.error)
with transaction.atomic():
+ payment.token = register_response.transaction_id
+ payment.save()
+
Transaction.objects.create(
payment=payment,
kind=TransactionKind.REGISTER,
@@ -61,21 +71,44 @@ def register_payment(payment_id: int) -> str:
error=None,
gateway_response=register_response.raw_response)
- payment.token = register_response.transaction_id
- payment.save()
-
return register_response.transaction_id
-def create_auth_transaction(transaction_id: str, success: bool) -> Transaction:
- """ Record the outcome of a netaxept auth transaction. """
+def verify_auth_transaction(transaction_id: str, response_code: str) -> bool:
+ """
+ Verify and record the outcome of a netaxept auth transaction.
+
+ :param transaction_id: The id of the transaction
+ :param response_code: The response code received in the callback
+ :return: whether the transaction was effectively authorized
+ """
+ logger.info('netaxept-actions-verify-auth-transaction', transaction_id=transaction_id, response_code=response_code)
+
payment = Payment.objects.get(token=transaction_id)
- return Transaction.objects.create(
+ _payment_gateway, gateway_config = get_payment_gateway('netaxept')
+ netaxept_config = gateway_to_netaxept_config(gateway_config)
+
+ try:
+ query_response = query(config=netaxept_config, transaction_id=transaction_id)
+ transaction_authorized = query_response.authorized
+ error = None
+ except NetaxeptProtocolError as exception:
+ transaction_authorized = False
+ error = exception
+
+ if response_code == 'OK' and not transaction_authorized:
+ logger.error('Inconsistent auth status detected!', transaction_id=transaction_id, response_code=response_code,
+ transaction_authorized=transaction_authorized)
+
+ # Record the outcome whether the authorization succeeded or not
+ Transaction.objects.create(
payment=payment,
kind=TransactionKind.AUTH,
token=transaction_id,
- is_success=success,
+ is_success=transaction_authorized,
amount=payment.total,
- error=None,
- gateway_response={})
+ error=error,
+ gateway_response={'response_code': response_code})
+
+ return transaction_authorized
diff --git a/payment/gateways/netaxept/netaxept_protocol.py b/payment/gateways/netaxept/netaxept_protocol.py
index 7686f68..63f7c8b 100644
--- a/payment/gateways/netaxept/netaxept_protocol.py
+++ b/payment/gateways/netaxept/netaxept_protocol.py
@@ -14,16 +14,16 @@
API details: https://shop.nets.eu/web/partners/appi
Test card numbers: https://shop.nets.eu/web/partners/test-cards
"""
+from dataclasses import dataclass
from decimal import Decimal
from enum import Enum
+from typing import Optional, Union, Dict, Any
from urllib.parse import urlencode, urljoin
import requests
import xmltodict
-from dataclasses import dataclass
from moneyed import Money
from structlog import get_logger
-from typing import Optional, Union, Dict
logger = get_logger()
@@ -54,11 +54,12 @@ def __init__(self, error: str, raw_response: Dict[str, str]):
@dataclass
class RegisterResponse:
transaction_id: str
- raw_response: Dict[str, str]
+ raw_response: Dict[str, Any]
def register(config: NetaxeptConfig, amount: Money, order_number: Union[str, int],
- language: Optional[str] = None, description: Optional[str] = None) -> RegisterResponse:
+ language: Optional[str] = None, description: Optional[str] = None,
+ customer_email: Optional[str] = None) -> RegisterResponse:
"""
Registering a payment is the first step for netaxept, before taking the user to the netaxept
terminal hosted page.
@@ -70,12 +71,13 @@ def register(config: NetaxeptConfig, amount: Money, order_number: Union[str, int
:param order_number: An alphanumerical string identifying the payment. 32 chars max (letters and numbers)
:param language: The iso639-1 code of the language in which the terminal should be displayed.
:param description: A text that will be displayed in the netaxept admin (but not to the user).
+ :param customer_email: The email of the customer, can then be seen in the netaxept admin portal.
:return: a RegisterResponse
:raises: NetaxeptProtocolError
"""
logger.info('netaxept-register', amount=amount, order_number=order_number, language=language,
- description=description)
+ description=description, customer_email=customer_email)
params = {
'merchantId': config.merchant_id,
@@ -94,10 +96,11 @@ def register(config: NetaxeptConfig, amount: Money, order_number: Union[str, int
'redirectUrl': config.after_terminal_url
}
- response = requests.post(url=urljoin(config.base_url, 'Netaxept/Register.aspx'),
- data=params)
- raw_response = _build_raw_response(response)
+ if customer_email is not None:
+ params['customerEmail'] = customer_email
+ response = requests.post(url=urljoin(config.base_url, 'Netaxept/Register.aspx'), data=params)
+ raw_response = _build_raw_response(response)
logger.info('netaxept-register', amount=amount, order_number=order_number, language=language,
description=description, raw_response=raw_response)
@@ -115,7 +118,7 @@ def register(config: NetaxeptConfig, amount: Money, order_number: Union[str, int
@dataclass
class ProcessResponse:
response_code: str
- raw_response: Dict[str, str]
+ raw_response: Dict[str, Any]
def process(config: NetaxeptConfig, transaction_id: str, operation: NetaxeptOperation,
@@ -138,11 +141,8 @@ def process(config: NetaxeptConfig, transaction_id: str, operation: NetaxeptOper
'transactionAmount': _decimal_to_netaxept_amount(amount),
}
- response = requests.post(url=urljoin(config.base_url, 'Netaxept/Process.aspx'),
- data=params)
-
+ response = requests.post(url=urljoin(config.base_url, 'Netaxept/Process.aspx'), data=params)
raw_response = _build_raw_response(response)
-
logger.info('netaxept-process-response', transaction_id=transaction_id, operation=operation.value,
amount=amount, raw_response=raw_response)
@@ -162,6 +162,44 @@ def get_payment_terminal_url(config: NetaxeptConfig, transaction_id: str) -> str
return '{}?{}'.format(urljoin(config.base_url, 'Terminal/default.aspx'), qs)
+@dataclass
+class QueryResponse:
+ """ The query response is a very complete object, but we just model what's interesting for our use-case.
+ (The complete response is captured in the raw_response)
+ """
+ annuled: bool
+ authorized: bool
+ raw_response: Dict[str, Any]
+
+
+def query(config: NetaxeptConfig, transaction_id: str) -> QueryResponse:
+ logger.info('netaxept-query', transaction_id=transaction_id)
+
+ params = {
+ 'merchantId': config.merchant_id,
+ 'token': config.secret,
+ 'transactionId': transaction_id,
+ }
+
+ response = requests.post(url=urljoin(config.base_url, 'Netaxept/Query.aspx'), data=params)
+ raw_response = _build_raw_response(response)
+ logger.info('netaxept-query-response', transaction_id=transaction_id, raw_response=raw_response)
+ if response.status_code == requests.codes.ok:
+ d = xmltodict.parse(response.text)
+ if 'PaymentInfo' in d:
+ summary = d['PaymentInfo']['Summary']
+ annuled = summary['Annuled'] == 'true'
+ authorized = summary['Authorized'] == 'true'
+ return QueryResponse(
+ annuled=annuled,
+ authorized=authorized,
+ raw_response=raw_response
+ )
+ elif 'Exception' in d:
+ raise NetaxeptProtocolError(d['Exception']['Error']['Message'], raw_response)
+ raise NetaxeptProtocolError(response.reason, raw_response)
+
+
def _decimal_to_netaxept_amount(decimal_amount: Decimal) -> int:
""" Return the netaxept representation of the decimal representation of the amount. """
return int((decimal_amount * 100).to_integral_value())
diff --git a/tests/gateways/test_netaxept.py b/tests/gateways/test_netaxept.py
index fde536e..9876cf1 100644
--- a/tests/gateways/test_netaxept.py
+++ b/tests/gateways/test_netaxept.py
@@ -5,13 +5,14 @@
import pytest
from moneyed import Money
-from pytest import raises
+from pytest import raises, mark
from payment import GatewayConfig, ChargeStatus
from payment.gateways.netaxept import gateway_to_netaxept_config, capture, refund
+from payment.gateways.netaxept.actions import verify_auth_transaction
from payment.gateways.netaxept.netaxept_protocol import NetaxeptConfig, get_payment_terminal_url, \
_iso6391_to_netaxept_language, _money_to_netaxept_amount, _money_to_netaxept_currency, register, RegisterResponse, \
- NetaxeptProtocolError, process, ProcessResponse, NetaxeptOperation
+ NetaxeptProtocolError, process, ProcessResponse, NetaxeptOperation, query, QueryResponse
from payment.interface import GatewayResponse
from payment.utils import create_payment_information
@@ -50,11 +51,6 @@ def it_should_transform_money_to_netaxept_representation():
assert _money_to_netaxept_currency(money) == 'NOK'
-def it_should_build_terminal_url():
- assert get_payment_terminal_url(_netaxept_config, transaction_id='11111') == \
- 'https://test.epayment.nets.eu/Terminal/default.aspx?merchantId=123456&transactionId=11111'
-
-
##############################################################################
# Protocol tests
@@ -79,15 +75,16 @@ def it_should_register(requests_post):
7624b99699f344e3b6da9884d20f0b27
""")
requests_post.return_value = mock_response
- register_response = register(_netaxept_config, amount=Money(10, 'CHF'), order_number='123')
+ register_response = register(config=_netaxept_config, amount=Money(10, 'CHF'), order_number='123',
+ customer_email='nwolff@gmail.com')
assert register_response == RegisterResponse(
transaction_id='7624b99699f344e3b6da9884d20f0b27',
raw_response=asdict(mock_response))
- requests_post.assert_called_with(
+ requests_post.assert_called_once_with(
url='https://test.epayment.nets.eu/Netaxept/Register.aspx',
data={'merchantId': '123456', 'token': 'supersekret', 'description': None, 'orderNumber': '123',
'amount': 1000, 'currencyCode': 'CHF', 'autoAuth': True, 'terminalSinglePage': True,
- 'language': None, 'redirectUrl': 'http://localhost'})
+ 'language': None, 'customerEmail': 'nwolff@gmail.com', 'redirectUrl': 'http://localhost'})
@patch('requests.post')
@@ -109,7 +106,7 @@ def it_should_handle_registration_failure(requests_post):
assert excinfo.value == NetaxeptProtocolError(
error='Unable to translate supermerchant to submerchant, please check currency code and merchant ID',
raw_response=asdict(mock_response))
- requests_post.assert_called_with(
+ requests_post.assert_called_once_with(
url='https://test.epayment.nets.eu/Netaxept/Register.aspx',
data={'merchantId': '123456', 'token': 'supersekret', 'description': None, 'orderNumber': '123',
'amount': 1000, 'currencyCode': 'CAD', 'autoAuth': True, 'terminalSinglePage': True,
@@ -141,7 +138,7 @@ def it_should_process(requests_post):
assert process_response == ProcessResponse(
response_code='OK',
raw_response=asdict(mock_response))
- requests_post.assert_called_with(
+ requests_post.assert_called_once_with(
url='https://test.epayment.nets.eu/Netaxept/Process.aspx',
data={'merchantId': '123456', 'token': 'supersekret', 'operation': 'CAPTURE',
'transactionId': '1111111111114cf693a1cf86123e0d8f', 'transactionAmount': 1000})
@@ -170,17 +167,104 @@ def it_should_handle_process_failure(requests_post):
assert excinfo.value == NetaxeptProtocolError(
error='Unable to translate supermerchant to submerchant, please check currency code and merchant ID',
raw_response=asdict(mock_response))
- requests_post.assert_called_with(
+ requests_post.assert_called_once_with(
url='https://test.epayment.nets.eu/Netaxept/Process.aspx',
data={'merchantId': '123456', 'token': 'supersekret', 'operation': 'CAPTURE',
'transactionId': '1111111111114cf693a1cf86123e0d8f', 'transactionAmount': 1000})
+@patch('requests.post')
+def it_should_query(requests_post):
+ mock_response = MockResponse(
+ status_code=200,
+ url='https://test.epayment.nets.eu/Netaxept/Query.aspx',
+ encoding='ISO-8859-1',
+ reason='OK',
+ text="""
+
+ 11111111
+ 2019-10-14T10:15:07.2677951+02:00
+ 1111111111114cf693a1cf86123e0d8f
+
+ 700
+ NOK
+ 7
+
+ 0
+ 0
+ 700
+ 2019-09-11T16:30:06.967
+
+
+ 2019-09-11T16:30:08.513
+ 2019-09-11T16:30:24.903
+ Chrome-Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.75 Safari/537.36
+
+
+
+ 85.218.56.162
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 700
+ 0
+ false
+ false
+ true
+ 169337
+
+
+ Visa
+ NO
+ 492500******0004
+ Visa
+ 2301
+ 3
+
+
+
+ 2019-09-11T16:30:06.967
+ Register
+
+
+ 2019-09-11T16:30:24.81
+ 127.0.0.1: Auto AUTH
+ Auth
+ 672
+
+
+
+
+
+
+ CH
+ false
+
+ """)
+ requests_post.return_value = mock_response
+ query_response = query(config=_netaxept_config, transaction_id='233abb21f18b47dc98469fb9000b1f21')
+ assert query_response == QueryResponse(
+ annuled=False,
+ authorized=True,
+ raw_response=asdict(mock_response))
+
+
##############################################################################
# SPI tests
@pytest.fixture()
-def netaxept_authorized_payment(payment_dummy):
+def netaxept_payment(payment_dummy):
payment_dummy.charge_status = ChargeStatus.NOT_CHARGED
payment_dummy.save()
return payment_dummy
@@ -191,7 +275,7 @@ def it_builds_netaxept_config():
@patch('payment.gateways.netaxept.process')
-def it_should_capture(process, netaxept_authorized_payment):
+def it_should_capture(process, netaxept_payment):
mock_process_response = ProcessResponse(
response_code='OK',
raw_response={'status_code': 200, 'url': 'https://test.epayment.nets.eu/Netaxept/Register.aspx',
@@ -199,9 +283,9 @@ def it_should_capture(process, netaxept_authorized_payment):
'text': '\n \n 675\n 2019-09-16T17:31:00.7593672+02:00\n 123456\n CAPTURE\n OK\n 1111111111114cf693a1cf86123e0d8f\n '})
process.return_value = mock_process_response
payment_info = create_payment_information(
- payment=netaxept_authorized_payment,
- payment_token='1111111111114cf693a1cf86123e0d8f',
- amount=Money(10, 'CHF'))
+ payment=netaxept_payment,
+ payment_token='1111111111114cf693a1cf86123e0d8f',
+ amount=Money(10, 'CHF'))
capture_result = capture(config=_gateway_config, payment_information=payment_info)
assert capture_result == GatewayResponse(
is_success=True,
@@ -211,7 +295,7 @@ def it_should_capture(process, netaxept_authorized_payment):
transaction_id='1111111111114cf693a1cf86123e0d8f',
error=None,
raw_response=mock_process_response.raw_response)
- process.assert_called_with(
+ process.assert_called_once_with(
config=NetaxeptConfig(
merchant_id='123456',
secret='supersekret',
@@ -223,12 +307,12 @@ def it_should_capture(process, netaxept_authorized_payment):
@patch('payment.gateways.netaxept.process')
-def it_should_not_capture_when_protocol_error(process, netaxept_authorized_payment):
+def it_should_not_capture_when_protocol_error(process, netaxept_payment):
process.side_effect = NetaxeptProtocolError(error='some error', raw_response={})
payment_info = create_payment_information(
- payment=netaxept_authorized_payment,
- payment_token='1111111111114cf693a1cf86123e0d8f',
- amount=Money(10, 'CHF'))
+ payment=netaxept_payment,
+ payment_token='1111111111114cf693a1cf86123e0d8f',
+ amount=Money(10, 'CHF'))
capture_result = capture(config=_gateway_config, payment_information=payment_info)
assert capture_result == GatewayResponse(
is_success=False,
@@ -238,19 +322,15 @@ def it_should_not_capture_when_protocol_error(process, netaxept_authorized_payme
transaction_id='1111111111114cf693a1cf86123e0d8f',
error='some error',
raw_response={})
- process.assert_called_with(
- config=NetaxeptConfig(
- merchant_id='123456',
- secret='supersekret',
- base_url='https://test.epayment.nets.eu',
- after_terminal_url='http://localhost'),
+ process.assert_called_once_with(
+ config=_netaxept_config,
amount=Decimal('10'),
transaction_id='1111111111114cf693a1cf86123e0d8f',
operation=NetaxeptOperation.CAPTURE)
@patch('payment.gateways.netaxept.process')
-def it_should_refund(process, netaxept_authorized_payment):
+def it_should_refund(process, netaxept_payment):
mock_process_response = ProcessResponse(
response_code='OK',
raw_response={
@@ -260,9 +340,9 @@ def it_should_refund(process, netaxept_authorized_payment):
'text': '\n \n 675\n 2019-09-16T17:31:00.7593672+02:00\n 123456\n REFUND\n OK\n 1111111111114cf693a1cf86123e0d8f\n '})
process.return_value = mock_process_response
payment_info = create_payment_information(
- payment=netaxept_authorized_payment,
- payment_token='1111111111114cf693a1cf86123e0d8f',
- amount=Money(10, 'CHF'))
+ payment=netaxept_payment,
+ payment_token='1111111111114cf693a1cf86123e0d8f',
+ amount=Money(10, 'CHF'))
capture_result = refund(config=_gateway_config, payment_information=payment_info)
assert capture_result == GatewayResponse(
is_success=True,
@@ -272,12 +352,39 @@ def it_should_refund(process, netaxept_authorized_payment):
transaction_id='1111111111114cf693a1cf86123e0d8f',
error=None,
raw_response=mock_process_response.raw_response)
- process.assert_called_with(
- config=NetaxeptConfig(
- merchant_id='123456',
- secret='supersekret',
- base_url='https://test.epayment.nets.eu',
- after_terminal_url='http://localhost'),
+ process.assert_called_once_with(
+ config=_netaxept_config,
amount=Decimal('10'),
transaction_id='1111111111114cf693a1cf86123e0d8f',
operation=NetaxeptOperation.CREDIT)
+
+
+##############################################################################
+# Actions tests
+
+@pytest.fixture()
+def netaxept_payment_with_token(netaxept_payment):
+ netaxept_payment.token = '1111111111114cf693a1cf86123e0d8f'
+ netaxept_payment.save()
+ return netaxept_payment
+
+
+@mark.django_db
+@patch('payment.gateways.netaxept.actions.query')
+def it_should_verify(query, netaxept_payment_with_token):
+ mock_query_response = QueryResponse(
+ annuled=False,
+ authorized=False,
+ raw_response={}
+ )
+ query.return_value = mock_query_response
+
+ verify_result = verify_auth_transaction(transaction_id='1111111111114cf693a1cf86123e0d8f', response_code='OK')
+ assert not verify_result
+
+
+def it_should_build_terminal_url():
+ assert get_payment_terminal_url(_netaxept_config, transaction_id='11111') == \
+ 'https://test.epayment.nets.eu/Terminal/default.aspx?merchantId=123456&transactionId=11111'
+
+
diff --git a/tests/settings.py b/tests/settings.py
index dfc2b73..034f72d 100644
--- a/tests/settings.py
+++ b/tests/settings.py
@@ -100,10 +100,10 @@
'auto_capture': True,
'template_path': 'payment/netaxept.html',
'connection_params': {
- 'merchant_id': os.environ.get('NETAXEPT_MERCHANT_ID'),
- 'token': os.environ.get('NETAXEPT_TOKEN'),
'base_url': os.environ.get('NETAXEPT_BASE_URL') or 'https://test.epayment.nets.eu',
'after_terminal_url': os.environ.get('NETAXEPT_AFTER_TERMINAL_URL'),
+ 'merchant_id': os.environ.get('NETAXEPT_MERCHANT_ID'),
+ 'secret': os.environ.get('NETAXEPT_TOKEN'),
}
}
},