implement long-polling for auto-refunds

This commit is contained in:
Florian Dold 2021-06-22 15:30:19 +02:00
parent c51b372abe
commit 39c4b42daf
No known key found for this signature in database
GPG Key ID: D2E4F00F29D02A4B

View File

@ -44,6 +44,8 @@ import {
TalerErrorDetails, TalerErrorDetails,
URL, URL,
timestampAddDuration, timestampAddDuration,
codecForMerchantOrderStatusPaid,
isTimestampExpired,
} from "@gnu-taler/taler-util"; } from "@gnu-taler/taler-util";
import { import {
AbortStatus, AbortStatus,
@ -493,7 +495,7 @@ export async function applyRefund(
ws.notify({ ws.notify({
type: NotificationType.RefundStarted, type: NotificationType.RefundStarted,
}); });
await processPurchaseQueryRefund(ws, proposalId); await processPurchaseQueryRefundImpl(ws, proposalId, true, false);
} }
purchase = await ws.db purchase = await ws.db
@ -571,7 +573,7 @@ export async function processPurchaseQueryRefund(
const onOpErr = (e: TalerErrorDetails): Promise<void> => const onOpErr = (e: TalerErrorDetails): Promise<void> =>
incrementPurchaseQueryRefundRetry(ws, proposalId, e); incrementPurchaseQueryRefundRetry(ws, proposalId, e);
await guardOperationException( await guardOperationException(
() => processPurchaseQueryRefundImpl(ws, proposalId, forceNow), () => processPurchaseQueryRefundImpl(ws, proposalId, forceNow, true),
onOpErr, onOpErr,
); );
} }
@ -597,6 +599,7 @@ async function processPurchaseQueryRefundImpl(
ws: InternalWalletState, ws: InternalWalletState,
proposalId: string, proposalId: string,
forceNow: boolean, forceNow: boolean,
waitForAutoRefund: boolean,
): Promise<void> { ): Promise<void> {
if (forceNow) { if (forceNow) {
await resetPurchaseQueryRefundRetry(ws, proposalId); await resetPurchaseQueryRefundRetry(ws, proposalId);
@ -617,6 +620,34 @@ async function processPurchaseQueryRefundImpl(
} }
if (purchase.timestampFirstSuccessfulPay) { if (purchase.timestampFirstSuccessfulPay) {
if (
waitForAutoRefund &&
purchase.autoRefundDeadline &&
!isTimestampExpired(purchase.autoRefundDeadline)
) {
const requestUrl = new URL(
`orders/${purchase.download.contractData.orderId}`,
purchase.download.contractData.merchantBaseUrl,
);
requestUrl.searchParams.set(
"h_contract",
purchase.download.contractData.contractTermsHash,
);
// Long-poll for one second
requestUrl.searchParams.set("timeout_ms", "1000");
requestUrl.searchParams.set("await_refund_obtained", "yes");
logger.trace("making long-polling request for auto-refund");
const resp = await ws.http.get(requestUrl.href);
const orderStatus = await readSuccessResponseJsonOrThrow(
resp,
codecForMerchantOrderStatusPaid(),
);
if (!orderStatus.refunded) {
incrementPurchaseQueryRefundRetry(ws, proposalId, undefined);
return;
}
}
const requestUrl = new URL( const requestUrl = new URL(
`orders/${purchase.download.contractData.orderId}/refund`, `orders/${purchase.download.contractData.orderId}/refund`,
purchase.download.contractData.merchantBaseUrl, purchase.download.contractData.merchantBaseUrl,