# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import http.client import logging import braintree from trytond.protocols.wrappers import ( HTTPStatus, Response, abort, with_pool, with_transaction) from trytond.wsgi import app logger = logging.getLogger(__name__) @app.route( '//account_payment_braintree/checkout//', methods=['GET', 'POST']) @with_pool @with_transaction(context={'_skip_warnings': True}) def checkout(request, pool, model, id): Payment = pool.get('account.payment') Customer = pool.get('account.payment.braintree.customer') if model == Payment.__name__: Model = Payment elif model == Customer.__name__: Model = Customer else: abort(HTTPStatus.FORBIDDEN) try: record, = Model.search([ ('braintree_checkout_id', '=', id), ]) except ValueError: abort(HTTPStatus.FORBIDDEN) if request.method == 'GET': Report = pool.get('account.payment.braintree.checkout', type='report') # TODO language data = { 'model': Model.__name__, 'client_token': record.braintree_client_token, } ext, content, _, _ = Report.execute([record.id], data) assert ext == 'html' return Response(content, HTTPStatus.OK, content_type='text/html') elif request.method == 'POST': record.braintree_set_nonce( request.form['payment_method_nonce'], request.form.get('device_data')) if model == Payment.__name__: Payment.process([record]) return Response( '', HTTPStatus.OK, content_type='text/html') @app.route( '//account_payment_braintree/webhook/', methods={'POST'}) @with_pool @with_transaction(context={'_skip_warnings': True}) def webhooks_endpoint(request, pool, account): Account = pool.get('account.payment.braintree.account') account, = Account.search([ ('webhook_identifier', '=', account), ]) gateway = account.gateway() try: notification = gateway.webhook_notification.parse( str(request.form['bt_signature']), request.form['bt_payload']) except braintree.exceptions.invalid_signature_error.InvalidSignatureError: abort(http.client.BAD_REQUEST) result = account.webhook(notification) if result is None: logger.info( "No callback for notification kind '%s'", notification.kind) elif not result: return Response(status=http.client.NOT_FOUND) return Response(status=http.client.NO_CONTENT)