fix: redirection

This commit is contained in:
mthiam
2026-02-10 15:53:19 +01:00
parent 85282bc757
commit fb090d363a
2 changed files with 50 additions and 21 deletions

View File

@@ -1,5 +1,6 @@
import logging
import requests
import json
from odoo import http
_logger = logging.getLogger(__name__)
@@ -43,7 +44,7 @@ class PaydunyaController(http.Controller):
tx_model = http.request.env['payment.transaction'].sudo()
handled = tx_model._handle_notification_data(data)
if handled:
return http.request.redirect('/payment/process')
return http.request.redirect('/shop/confirmation')
except Exception:
_logger.exception('Error handling PayDunya notification data')
@@ -56,25 +57,32 @@ class PaydunyaController(http.Controller):
_logger.info('PayDunya payment cancelled: token=%s', token)
return http.request.redirect('/shop/cart')
@http.route('/payment/paydunya/callback', type='http', auth='public', methods=['POST'], csrf=False)
@http.route('/payment/paydunya/callback', type='http', auth='public', methods=['GET', 'POST'], csrf=False)
def paydunya_callback(self, **kwargs):
"""Handle IPN callback from PayDunya.
PayDunya sends data as application/x-www-form-urlencoded with 'data' key containing JSON.
"""
try:
# The 'data' parameter contains the JSON-encoded transaction info
import json
payload = {}
data_str = http.request.params.get('data')
if data_str:
data = json.loads(data_str)
_logger.info('PayDunya IPN callback received: %s', data)
tx_model = http.request.env['payment.transaction'].sudo()
tx_model._handle_notification_data(data)
payload = {'data': data_str}
elif http.request.params:
payload = dict(http.request.params)
else:
raw_body = http.request.httprequest.get_data(as_text=True)
if raw_body:
try:
payload = json.loads(raw_body)
except Exception:
payload = {'data': raw_body}
_logger.info('PayDunya IPN callback received: %s', payload)
tx_model = http.request.env['payment.transaction'].sudo()
tx_model._handle_notification_data(payload)
except Exception:
_logger.exception('Error handling PayDunya callback')
# Always return 200 OK to PayDunya
return 'OK'

View File

@@ -1,6 +1,7 @@
import logging
import requests
import hashlib
import json
from odoo import models
_logger = logging.getLogger(__name__)
@@ -9,6 +10,29 @@ _logger = logging.getLogger(__name__)
class PaymentTransaction(models.Model):
_inherit = 'payment.transaction'
def _normalize_paydunya_notification_data(self, data):
"""Normalize PayDunya notification payload across callback and confirm formats."""
payload = data
if not isinstance(payload, dict):
return {}
# Callback can send {"data": "<json>"} or {"data": {...}}
if 'data' in payload:
wrapped = payload.get('data')
if isinstance(wrapped, str):
try:
payload = json.loads(wrapped)
except Exception:
payload = payload
elif isinstance(wrapped, dict):
payload = wrapped
# Confirm endpoint can send {"response_data": {...}}
if isinstance(payload, dict) and isinstance(payload.get('response_data'), dict):
payload = payload['response_data']
return payload if isinstance(payload, dict) else {}
def _get_paydunya_channel(self, processing_values):
"""Return the PayDunya channel to force based on selected payment method."""
self.ensure_one()
@@ -140,11 +164,7 @@ class PaymentTransaction(models.Model):
def _get_tx_from_notification(self, data):
"""Find the transaction corresponding to a PayDunya notification payload."""
# Extract invoice data if wrapped
if isinstance(data, dict) and 'data' in data:
invoice_data = data['data']
else:
invoice_data = data
invoice_data = self._normalize_paydunya_notification_data(data)
token = invoice_data.get('invoice', {}).get('token') or invoice_data.get('token')
if not token:
@@ -158,21 +178,22 @@ class PaymentTransaction(models.Model):
Validates the hash according to PayDunya documentation (SHA-512 of MASTER-KEY).
PayDunya sends data as application/x-www-form-urlencoded with key 'data' containing JSON.
"""
# Extract the actual data if wrapped
if isinstance(data, dict) and 'data' in data:
invoice_data = data['data']
else:
invoice_data = data
invoice_data = self._normalize_paydunya_notification_data(data)
if not invoice_data:
_logger.warning('PayDunya: invalid notification payload: %s', data)
return False
# Verify hash to ensure the callback is from PayDunya
provided_hash = invoice_data.get('hash')
if not provided_hash and isinstance(data, dict):
provided_hash = data.get('hash')
if provided_hash:
provider = self.env['payment.provider'].search([('code', '=', 'paydunya')], limit=1)
if provider and provider.paydunya_master_key:
expected_hash = hashlib.sha512(
provider.paydunya_master_key.encode()
).hexdigest()
if provided_hash != expected_hash:
if str(provided_hash).lower() != expected_hash:
_logger.warning('PayDunya: Hash mismatch! Possible security issue. Expected %s, got %s',
expected_hash, provided_hash)
return False