turnstile

Drupal paywall plugin
Log | Files | Refs | README | LICENSE

commit d92a965a5e3e7d755726b78e89e3ad7fbb1a0946
parent f914ba97fd759e11dc944b6e1e6595689ccdc64e
Author: Christian Grothoff <christian@grothoff.org>
Date:   Mon, 20 Oct 2025 17:16:54 +0200

address a few more fixmes

Diffstat:
Mjs/payment-button.js | 33++++++++++++++++++++++++++-------
Msrc/TalerMerchantApiService.php | 1-
2 files changed, 26 insertions(+), 8 deletions(-)

diff --git a/js/payment-button.js b/js/payment-button.js @@ -11,12 +11,14 @@ */ function pollPaymentStatus(paymentUrl, sessionId) { var separator = paymentUrl.indexOf('?') !== -1 ? '&' : '?'; - var pollUrl = paymentUrl + separator + 'timeout_ms=30000&session_id=' + encodeURIComponent(sessionId); + const timeout_ms = 30000; + var pollUrl = paymentUrl + separator + 'timeout_ms=' + timeout_ms + '&session_id=' + encodeURIComponent(sessionId); + const start_time = Date.now(); // in milliseconds since Epoch $.ajax({ url: pollUrl, method: 'GET', - timeout: 35000, // Slightly longer than server timeout + timeout: timeout_ms + 5000, // Slightly longer than server timeout headers: { 'Accept': 'application/json' }, @@ -26,10 +28,17 @@ console.log('Payment completed! Reloading page...'); window.location.reload(); } else if (xhr.status === 402) { - // FIXME: if long-polling failed and we got an answer - // too quickly, still wait a bit! console.log('Payment still pending, continuing to poll...'); - pollPaymentStatus(paymentUrl, sessionId); + const end_time = Date.now(); + // Prevent looping faster than the long-poll timeout + // (useful in case a bug causes the 402 to be returned + // immediately instead of long-polling properly). + const delay = (start_time + timeout_ms > end_time) + ? (start_time + timeout_ms - end_time) + : 0; + setTimeout(function() { + pollPaymentStatus(paymentUrl, sessionId); + }, delay); } }, error: function(xhr, textStatus, errorThrown) { @@ -39,9 +48,19 @@ pollPaymentStatus(paymentUrl, sessionId); } else if (textStatus === 'timeout') { console.log('Poll timeout, retrying...'); - pollPaymentStatus(paymentUrl, sessionId); + const end_time = Date.now(); + // Prevent looping faster than the long-poll timeout + // (useful in case a bug causes a timeout to be returned + // faster than what we wanted) + const delay = (start_time + timeout_ms > end_time) + ? (start_time + timeout_ms - end_time) + : 0; + setTimeout(function() { + pollPaymentStatus(paymentUrl, sessionId); + }, delay); } else { - // Other errors - wait a bit before retrying to avoid hammering the server + // Other errors - wait a bit before retrying to avoid hammering the server, + // But do not wait the full long-polling period to remain responsive console.log('Poll error: ' + textStatus + ', retrying in 5 seconds...'); setTimeout(function() { pollPaymentStatus(paymentUrl, sessionId); diff --git a/src/TalerMerchantApiService.php b/src/TalerMerchantApiService.php @@ -604,7 +604,6 @@ class TalerMerchantApiService { $this->logger->warning('Access denied by the merchant backend. Did your credentials change or expire? Check your Turnstile configuration!'); return FALSE; case 404: - // FIXME: go into details on why we could get 404 here... $body_log_fmt = json_encode($jbody, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); $this->logger->error('Failed to create order: @hint (@ec): @body', ['@hint' => $jbody['hint'] ?? 'N/A', '@ec' => $jbody['code'] ?? 'N/A', '@body' => $body_log_fmt ?? 'N/A']); return FALSE;