Skip to Content
Menu
This question has been flagged
1 Reply
747 Views

Hello!
I have tried to implement Echelon Payment Gateway into odoo.
I would like to implement the inline payment.
I have created the method and provider and when comes to the payment page, when pay is clicked, it says template is required. But in sandbox, the call has been captured. So basically i need the payment success page of odoo

 line 804, in _get_template

    assert template not in (False, None, ""), "template is required"

AssertionError: template is required


this is my controller. I dont actually want to redirect but i think the error is about redirecting.







"""echelon"""

# -*- coding: utf-8 -*-
import hmac
import logging
import pprint

import requests
from werkzeug.exceptions import Forbidden
from werkzeug.utils import redirect

from odoo import http, _
from odoo.exceptions import AccessError, MissingError, ValidationError, UserError
from odoo.http import request, route
from odoo.addons.payment import utils as payment_utils
from odoo.addons.payment.controllers import portal as payment_portal

_logger = logging.getLogger(__name__)


class PaymentPortal(payment_portal.PaymentPortal):

@route('/invoice/transaction/<int:invoice_id>', type='json', auth='public')
def invoice_transaction(self, invoice_id, access_token, **kwargs):
""" Create a draft transaction and return its processing values.

:param int invoice_id: The invoice to pay, as an `account.move` id
:param str access_token: The access token used to authenticate the request
:param dict kwargs: Locally unused data passed to `_create_transaction`
:return: The mandatory values for the processing of the transaction
:rtype: dict
:raise: ValidationError if the invoice id or the access token is invalid
"""
# Check the invoice id and the access token
try:
invoice_sudo = self._document_check_access('account.move', invoice_id, access_token)
except MissingError as error:
raise error
except AccessError:
raise ValidationError(_("The access token is invalid."))

logged_in = not request.env.user._is_public()
partner_sudo = request.env.user.partner_id if logged_in else invoice_sudo.partner_id
self._validate_transaction_kwargs(kwargs, additional_allowed_keys={
'name_next_installment',
'partner_id',
'card_number',
'expiry_month',
'expiry_year',
'cvv_number',
})
return self._process_transaction(partner_sudo.id, invoice_sudo.currency_id.id, [invoice_id], False, **kwargs)




class EchelonController(http.Controller):

@http.route('/payment/echelon', type='json', auth='public')
def echelon_payment(self, **post):
card_number = post.get('card_number')
expiry_month = post.get('expiry_month')
cvv_number = post.get('cvv_number')
expiry_year = post.get('expiry_year')
amount = post.get('amount')
partner_id = request.env['res.partner'].browse(int(post.get('partner_id')))
invoice_id = request.env['account.move'].browse(int(post.get('invoice_id')))
provider_id = request.env['payment.provider'].browse(int(post.get('provider_id')))
landing_route = post.get('landing_route')

payloads = {
"expiry_month": int(expiry_month),
"expiry_year": int(expiry_year),
"name": partner_id.name,
"card": card_number,
"amount": amount,
"transaction_details": {
"description": invoice_id.name,
"invoice_number": invoice_id.name,
"order_number": "123"
},
"capture": True,
"save_card": False
}
headers = {
"Content-Type": "application/json",
"Authorization": "Basic "
}
url = 'https://api.sandbox.echelonsecure.app/api/v2/transactions/charge'
response = requests.post(url, json=payloads, headers=headers, auth=(provider_id.api_key, provider_id.pin))
response_json = response.json()
_logger.info("Echelon charge API response: %s", pprint.pformat(response_json))
print('Echelon response:', response_json)

flow = post.get('flow')
is_validation = post.get('is_validation')
token_id = post.get('token_id')
tokenize = False

# Always create transaction record regardless of success/failure
tx_sudo = request.env['payment.transaction'].sudo().create({
'provider_id': provider_id.id,
'payment_method_id': provider_id.payment_method_ids.id,
'reference': invoice_id.name,
'amount': amount,
'currency_id': invoice_id.currency_id.id,
'partner_id': partner_id.id,
'token_id': token_id,
'operation': f'online_{flow}' if not is_validation else 'validation',
'tokenize': tokenize,
'landing_route': landing_route,
'invoice_ids': [(6, 0, [invoice_id.id])],
'state': 'pending'
})

if response.status_code == 200 and response_json.get('status') == 'Approved':
# Payment was approved
payment = request.env['account.payment'].sudo().create({
'payment_type': 'inbound',
'partner_type': 'customer',
'partner_id': partner_id.id,
'amount': amount,
'state': 'in_process',
'invoice_ids': [(6, 0, [invoice_id.id])],
'payment_transaction_id': tx_sudo.id,
'currency_id': invoice_id.currency_id.id,
'journal_id': provider_id.journal_id.id,
})
tx_sudo.write({'state': 'done'})

else:
# Log error and keep transaction pending or mark as error
_logger.error("Echelon charge failed: %s", pprint.pformat(response_json))
tx_sudo.write({'state': 'error'})

# Common rendering values
processing_values = {
'provider_id': provider_id.id,
'provider_code': provider_id.code,
'reference': invoice_id.name,
'amount': amount,
'currency_id': invoice_id.currency_id.id,
'partner_id': partner_id.id,
}
rendering_values = dict()
redirect_form_view = provider_id._get_redirect_form_view()
redirect_form_html = request.env['ir.qweb']._render(redirect_form_view.id, rendering_values)
processing_values.update(redirect_form_html=redirect_form_html)

return processing_values

Avatar
Discard
Best Answer

Hii,

Here is updated code 
import hmac

import logging

import pprint

import requests


from odoo import http, _

from odoo.exceptions import AccessError, MissingError, ValidationError

from odoo.http import request, route

from odoo.addons.payment.controllers import portal as payment_portal


_logger = logging.getLogger(__name__)



class PaymentPortal(payment_portal.PaymentPortal):


    @route('/invoice/transaction/<int:invoice_id>', type='json', auth='public')

    def invoice_transaction(self, invoice_id, access_token, **kwargs):

        """Create a draft transaction and return its processing values."""

        try:

            invoice_sudo = self._document_check_access('account.move', invoice_id, access_token)

        except MissingError as error:

            raise error

        except AccessError:

            raise ValidationError(_("The access token is invalid."))


        logged_in = not request.env.user._is_public()

        partner_sudo = request.env.user.partner_id if logged_in else invoice_sudo.partner_id


        self._validate_transaction_kwargs(kwargs, additional_allowed_keys={

            'name_next_installment',

            'partner_id',

            'card_number',

            'expiry_month',

            'expiry_year',

            'cvv_number',

        })


        return self._process_transaction(

            tx_sudo.id,

    'redirect_url': landing_route,  # if you want to redirect the user client-side

}



Instead, return a meaningful JSON response — e.g.:i hope it is use full

Avatar
Discard
Related Posts Replies Views Activity
0
Nov 21
3087
1
Jul 25
310
1
Jun 25
698
1
Jun 25
1480
3
Jan 25
3337