diff options
Diffstat (limited to 'packages/taler-wallet-core/src/pay-merchant.ts')
-rw-r--r-- | packages/taler-wallet-core/src/pay-merchant.ts | 73 |
1 files changed, 55 insertions, 18 deletions
diff --git a/packages/taler-wallet-core/src/pay-merchant.ts b/packages/taler-wallet-core/src/pay-merchant.ts index 5e01ae716..09e9e1fb3 100644 --- a/packages/taler-wallet-core/src/pay-merchant.ts +++ b/packages/taler-wallet-core/src/pay-merchant.ts @@ -103,8 +103,8 @@ import { DbRetryInfo, PendingTaskType, spendCoins, - TaskId, TaskIdentifiers, + TaskIdStr, TaskRunResult, TaskRunResultType, TombstoneTag, @@ -150,7 +150,7 @@ const logger = new Logger("pay-merchant.ts"); export class PayMerchantTransactionContext implements TransactionContext { readonly transactionId: TransactionIdStr; - readonly taskId: TaskId; + readonly taskId: TaskIdStr; constructor( public ws: InternalWalletState, @@ -391,7 +391,8 @@ export class PayMerchantTransactionContext implements TransactionContext { } export class RefundTransactionContext implements TransactionContext { - public transactionId: string; + public transactionId: TransactionIdStr; + public taskId: TaskIdStr | undefined = undefined; constructor( public ws: InternalWalletState, public refundGroupId: string, @@ -612,6 +613,7 @@ export function extractContractData( async function processDownloadProposal( ws: InternalWalletState, proposalId: string, + cancellationToken: CancellationToken, ): Promise<TaskRunResult> { const proposal = await ws.db.runReadOnlyTx(["purchases"], async (tx) => { return await tx.purchases.get(proposalId); @@ -662,6 +664,7 @@ async function processDownloadProposal( method: "POST", body: requestBody, timeout: getProposalRequestTimeout(retryRecord?.retryInfo), + cancellationToken, }); const r = await readSuccessResponseJsonOrErrorCode( httpResponse, @@ -861,6 +864,7 @@ async function createOrReusePurchase( sessionId: string | undefined, claimToken: string | undefined, noncePriv: string | undefined, + cancellationToken: CancellationToken, ): Promise<string> { const oldProposals = await ws.db.runReadOnlyTx(["purchases"], async (tx) => { return tx.purchases.indexes.byUrlAndOrderId.getAll([ @@ -891,7 +895,11 @@ async function createOrReusePurchase( ); if (oldProposal.purchaseStatus === PurchaseStatus.DialogShared) { const download = await expectProposalDownload(ws, oldProposal); - const paid = await checkIfOrderIsAlreadyPaid(ws, download.contractData); + const paid = await checkIfOrderIsAlreadyPaid( + ws, + download.contractData, + cancellationToken, + ); logger.info(`old proposal paid: ${paid}`); if (paid) { // if this transaction was shared and the order is paid then it @@ -1466,6 +1474,7 @@ export async function preparePayForUri( uriResult.sessionId, uriResult.claimToken, uriResult.noncePriv, + CancellationToken.CONTINUE, ); await waitProposalDownloaded(ws, proposalId); @@ -1951,20 +1960,20 @@ export async function processPurchase( switch (purchase.purchaseStatus) { case PurchaseStatus.PendingDownloadingProposal: - return processDownloadProposal(ws, proposalId); + return processDownloadProposal(ws, proposalId, cancellationToken); case PurchaseStatus.PendingPaying: case PurchaseStatus.PendingPayingReplay: - return processPurchasePay(ws, proposalId); + return processPurchasePay(ws, proposalId, cancellationToken); case PurchaseStatus.PendingQueryingRefund: - return processPurchaseQueryRefund(ws, purchase); + return processPurchaseQueryRefund(ws, purchase, cancellationToken); case PurchaseStatus.PendingQueryingAutoRefund: - return processPurchaseAutoRefund(ws, purchase); + return processPurchaseAutoRefund(ws, purchase, cancellationToken); case PurchaseStatus.AbortingWithRefund: - return processPurchaseAbortingRefund(ws, purchase); + return processPurchaseAbortingRefund(ws, purchase, cancellationToken); case PurchaseStatus.PendingAcceptRefund: - return processPurchaseAcceptRefund(ws, purchase); + return processPurchaseAcceptRefund(ws, purchase, cancellationToken); case PurchaseStatus.DialogShared: - return processPurchaseDialogShared(ws, purchase); + return processPurchaseDialogShared(ws, purchase, cancellationToken); case PurchaseStatus.FailedClaim: case PurchaseStatus.Done: case PurchaseStatus.DoneRepurchaseDetected: @@ -1990,6 +1999,7 @@ export async function processPurchase( async function processPurchasePay( ws: InternalWalletState, proposalId: string, + cancellationToken: CancellationToken, ): Promise<TaskRunResult> { const purchase = await ws.db.runReadOnlyTx(["purchases"], async (tx) => { return tx.purchases.get(proposalId); @@ -2024,7 +2034,11 @@ async function processPurchasePay( const download = await expectProposalDownload(ws, purchase); if (purchase.shared) { - const paid = await checkIfOrderIsAlreadyPaid(ws, download.contractData); + const paid = await checkIfOrderIsAlreadyPaid( + ws, + download.contractData, + cancellationToken, + ); if (paid) { const transitionInfo = await ws.db.runReadWriteTx( @@ -2088,6 +2102,7 @@ async function processPurchasePay( method: "POST", body: reqBody, timeout: getPayRequestTimeout(purchase), + cancellationToken, }), ); @@ -2163,7 +2178,11 @@ async function processPurchasePay( }; logger.trace(`/paid request body: ${j2s(reqBody)}`); const resp = await ws.runSequentialized([EXCHANGE_COINS_LOCK], () => - ws.http.fetch(payAgainUrl, { method: "POST", body: reqBody }), + ws.http.fetch(payAgainUrl, { + method: "POST", + body: reqBody, + cancellationToken, + }), ); logger.trace(`/paid response status: ${resp.status}`); if ( @@ -2499,6 +2518,7 @@ export async function sharePayment( async function checkIfOrderIsAlreadyPaid( ws: InternalWalletState, contract: WalletContractData, + cancellationToken: CancellationToken, ) { const requestUrl = new URL( `orders/${contract.orderId}`, @@ -2508,7 +2528,9 @@ async function checkIfOrderIsAlreadyPaid( requestUrl.searchParams.set("timeout_ms", "1000"); - const resp = await ws.http.fetch(requestUrl.href); + const resp = await ws.http.fetch(requestUrl.href, { + cancellationToken, + }); if ( resp.status === HttpStatusCode.Ok || resp.status === HttpStatusCode.Accepted || @@ -2518,13 +2540,14 @@ async function checkIfOrderIsAlreadyPaid( } else if (resp.status === HttpStatusCode.PaymentRequired) { return false; } - //forbidden, not found, not acceptable + // forbidden, not found, not acceptable throw Error(`this order cant be paid: ${resp.status}`); } async function processPurchaseDialogShared( ws: InternalWalletState, purchase: PurchaseRecord, + cancellationToken: CancellationToken, ): Promise<TaskRunResult> { const proposalId = purchase.proposalId; logger.trace(`processing dialog-shared for proposal ${proposalId}`); @@ -2534,7 +2557,11 @@ async function processPurchaseDialogShared( return TaskRunResult.finished(); } - const paid = await checkIfOrderIsAlreadyPaid(ws, download.contractData); + const paid = await checkIfOrderIsAlreadyPaid( + ws, + download.contractData, + cancellationToken, + ); if (paid) { const transitionInfo = await ws.db.runReadWriteTx( ["purchases"], @@ -2565,6 +2592,7 @@ async function processPurchaseDialogShared( async function processPurchaseAutoRefund( ws: InternalWalletState, purchase: PurchaseRecord, + cancellationToken: CancellationToken, ): Promise<TaskRunResult> { const proposalId = purchase.proposalId; logger.trace(`processing auto-refund for proposal ${proposalId}`); @@ -2624,7 +2652,9 @@ async function processPurchaseAutoRefund( requestUrl.searchParams.set("timeout_ms", "1000"); requestUrl.searchParams.set("await_refund_obtained", "yes"); - const resp = await ws.http.fetch(requestUrl.href); + const resp = await ws.http.fetch(requestUrl.href, { + cancellationToken, + }); // FIXME: Check other status codes! @@ -2661,6 +2691,7 @@ async function processPurchaseAutoRefund( async function processPurchaseAbortingRefund( ws: InternalWalletState, purchase: PurchaseRecord, + cancellationToken: CancellationToken, ): Promise<TaskRunResult> { const proposalId = purchase.proposalId; const download = await expectProposalDownload(ws, purchase); @@ -2701,6 +2732,7 @@ async function processPurchaseAbortingRefund( const abortHttpResp = await ws.http.fetch(requestUrl.href, { method: "POST", body: abortReq, + cancellationToken, }); if (abortHttpResp.status === HttpStatusCode.NotFound) { @@ -2753,6 +2785,7 @@ async function processPurchaseAbortingRefund( async function processPurchaseQueryRefund( ws: InternalWalletState, purchase: PurchaseRecord, + cancellationToken: CancellationToken, ): Promise<TaskRunResult> { const proposalId = purchase.proposalId; logger.trace(`processing query-refund for proposal ${proposalId}`); @@ -2768,7 +2801,9 @@ async function processPurchaseQueryRefund( download.contractData.contractTermsHash, ); - const resp = await ws.http.fetch(requestUrl.href); + const resp = await ws.http.fetch(requestUrl.href, { + cancellationToken, + }); const orderStatus = await readSuccessResponseJsonOrThrow( resp, codecForMerchantOrderStatusPaid(), @@ -2834,6 +2869,7 @@ async function processPurchaseQueryRefund( async function processPurchaseAcceptRefund( ws: InternalWalletState, purchase: PurchaseRecord, + cancellationToken: CancellationToken, ): Promise<TaskRunResult> { const download = await expectProposalDownload(ws, purchase); @@ -2849,6 +2885,7 @@ async function processPurchaseAcceptRefund( body: { h_contract: download.contractData.contractTermsHash, }, + cancellationToken, }); const refundResponse = await readSuccessResponseJsonOrThrow( |