Skip to content

Commit

Permalink
use gateway authorize
Browse files Browse the repository at this point in the history
  • Loading branch information
nwolff committed Oct 16, 2019
1 parent b2e66e9 commit d79f011
Show file tree
Hide file tree
Showing 7 changed files with 158 additions and 127 deletions.
12 changes: 0 additions & 12 deletions example_project/templates/netaxept/after_auth.html

This file was deleted.

2 changes: 1 addition & 1 deletion example_project/templates/view_payment.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ <H3>Operations</H3>
<li><a href="{% url 'stripe_checkout' payment.id %}">Authorize - Checkout</a></li>
<li><a href="{% url 'stripe_payment_intents_manual_flow' payment.id %}">Authorize - Payment intents manual flow</a>
{% elif payment.gateway == 'netaxept' %}
<li><a href="{% url 'netaxept_register_and_authorize' payment.id %}">Register and Authorize</a></li>
<li><a href="{% url 'netaxept_register_and_goto_terminal' payment.id %}">Register and Goto Terminal</a></li>
{% if payment.token %}
<li><a href="{% url 'netaxept_query' payment.token %}">Query</a></li>
{% endif %}
Expand Down
18 changes: 12 additions & 6 deletions example_project/views/netaxept.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@
from payment.gateways.netaxept import gateway_to_netaxept_config
from payment.gateways.netaxept import netaxept_protocol
from payment.models import Payment
from payment.utils import gateway_authorize

logger = get_logger()


@require_GET
def register_and_authorize(request: HttpRequest, payment_id: int) -> HttpResponse:
def register_and_goto_terminal(request: HttpRequest, payment_id: int) -> HttpResponse:
"""
Register the payment with netaxept, and take the user to the terminal page for payment authorization
"""
Expand Down Expand Up @@ -50,11 +51,15 @@ def after_terminal(request):
response_code = request.GET['responseCode']
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)
payment = Payment.objects.get(token=transaction_id)

return TemplateResponse(request, 'netaxept/after_auth.html',
{'transaction_id': transaction_id, 'response_code': response_code,
'payment_authorized': payment_authorized})
try:
gateway_authorize(payment=payment, payment_token=payment.token)
except Exception as exc:
logger.error('netaxept after terminal', exc_info=exc)
return HttpResponse('Error authorizing {}: {}'.format(payment.id, exc))
else:
return redirect('view_payment', payment_id=payment.id)


def query(request: HttpRequest, transaction_id: str) -> HttpResponse:
Expand All @@ -69,7 +74,8 @@ def query(request: HttpRequest, transaction_id: str) -> HttpResponse:


urls = [
path('register_and_authorize/<payment_id>', register_and_authorize, name='netaxept_register_and_authorize'),
path('register_and_goto_terminal/<payment_id>', register_and_goto_terminal,
name='netaxept_register_and_goto_terminal'),
path('after_terminal', after_terminal, name='netaxept_after_terminal'),
path('query/<transaction_id>', query, name='netaxept_query'),
]
63 changes: 44 additions & 19 deletions payment/gateways/netaxept/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
from .netaxept_protocol import NetaxeptConfig, NetaxeptOperation, process, NetaxeptProtocolError
from ... import OperationType
from structlog import get_logger

from . import netaxept_protocol
from .netaxept_protocol import NetaxeptConfig, NetaxeptOperation, NetaxeptProtocolError
from ... import TransactionKind
from ...interface import GatewayConfig, GatewayResponse, PaymentData

logger = get_logger()


def get_client_token(**_):
""" Not implemented for netaxept gateway. """
Expand All @@ -11,41 +16,69 @@ def get_client_token(**_):
def authorize(payment_information: PaymentData,
config: GatewayConfig,
should_capture: bool = False) -> GatewayResponse:
raise NotImplementedError()
"""
:param payment_information:
:param config:
:param should_capture: This will be ignored, it is too late to choose if we want to capture or not.
:return:
"""
logger.info('netaxept-authorize', payment_information=payment_information)

netaxept_config = gateway_to_netaxept_config(config)

try:
query_response = netaxept_protocol.query(config=netaxept_config, transaction_id=payment_information.token)
transaction_authorized = query_response.authorized
error = None
except NetaxeptProtocolError as exception:
transaction_authorized = False
error = exception.error

return GatewayResponse(
is_success=transaction_authorized,
kind=TransactionKind.AUTH,
amount=payment_information.amount,
currency=payment_information.currency,
transaction_id=payment_information.token,
error=error,
raw_response={} # XXX query_response
)


def process_payment(payment_information: PaymentData, config: GatewayConfig) -> GatewayResponse:
raise NotImplementedError()


def capture(payment_information: PaymentData, config: GatewayConfig) -> GatewayResponse:
return _op(payment_information, config, OperationType.CAPTURE)
return _op(payment_information, config, NetaxeptOperation.CAPTURE, TransactionKind.CAPTURE)


def refund(payment_information: PaymentData, config: GatewayConfig) -> GatewayResponse:
return _op(payment_information, config, OperationType.REFUND)
return _op(payment_information, config, NetaxeptOperation.CREDIT, TransactionKind.REFUND)


def void(payment_information: PaymentData, config: GatewayConfig) -> GatewayResponse:
return _op(payment_information, config, OperationType.VOID)
return _op(payment_information, config, NetaxeptOperation.ANNUL, TransactionKind.VOID)


def gateway_to_netaxept_config(gateway_config: GatewayConfig) -> NetaxeptConfig:
return NetaxeptConfig(**gateway_config.connection_params)


def _op(payment_information: PaymentData, config: GatewayConfig, operation_type: OperationType) -> GatewayResponse:
def _op(payment_information: PaymentData, config: GatewayConfig,
netaxept_operation: NetaxeptOperation,
transaction_kind: str) -> GatewayResponse:
try:
process_result = process(
process_result = netaxept_protocol.process(
config=gateway_to_netaxept_config(config),
transaction_id=payment_information.token,
operation=_operation_type_to_netaxept_op[operation_type],
operation=netaxept_operation,
amount=payment_information.amount)
# We don't need to introspect anything inside the process_result: If no exception was thrown we immediately
# know process ran successfully
return GatewayResponse(
is_success=True,
kind=operation_type.value,
kind=transaction_kind,
amount=payment_information.amount,
currency=payment_information.currency,
transaction_id=payment_information.token,
Expand All @@ -55,18 +88,10 @@ def _op(payment_information: PaymentData, config: GatewayConfig, operation_type:
except NetaxeptProtocolError as exception:
return GatewayResponse(
is_success=False,
kind=operation_type.value,
kind=transaction_kind,
amount=payment_information.amount,
currency=payment_information.currency,
transaction_id=payment_information.token,
error=exception.error,
raw_response=exception.raw_response
)


_operation_type_to_netaxept_op = {
OperationType.AUTH: NetaxeptOperation.AUTH,
OperationType.CAPTURE: NetaxeptOperation.CAPTURE,
OperationType.VOID: NetaxeptOperation.ANNUL,
OperationType.REFUND: NetaxeptOperation.CREDIT,
}
44 changes: 0 additions & 44 deletions payment/gateways/netaxept/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
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
Expand Down Expand Up @@ -72,46 +71,3 @@ def register_payment(payment_id: int) -> str:
gateway_response=register_response.raw_response)

return register_response.transaction_id


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)

_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=transaction_authorized,
amount=payment.total,
error=error,
gateway_response={
'response_code': response_code,
'authorization_id': query_response.authorization_id,
})

return transaction_authorized
2 changes: 1 addition & 1 deletion payment/gateways/netaxept/netaxept_protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ def get_payment_terminal_url(config: NetaxeptConfig, transaction_id: str) -> str

@dataclass
class QueryResponse:
""" The query response is a very complete object, but we just model what's interesting for our use-case.
""" The query response is a very rich, deeply nested object, but we just model what's interesting for our use-case.
(The complete response is captured in the raw_response)
"""
annulled: bool
Expand Down
Loading

0 comments on commit d79f011

Please sign in to comment.