diff options
-rw-r--r-- | packages/taler-wallet-core/src/db.ts | 6 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/pay-merchant.ts | 24 |
2 files changed, 25 insertions, 5 deletions
diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts index 9efc9fbe0..7e4f9fa4a 100644 --- a/packages/taler-wallet-core/src/db.ts +++ b/packages/taler-wallet-core/src/db.ts @@ -1326,6 +1326,12 @@ export interface PurchaseRecord { * did not picked up yet */ refundAmountAwaiting: AmountString | undefined; + + /** + * When the purchase has been shared to other wallet + * and the other wallet completed before this one. + */ + paidByOther: boolean | undefined; } export enum ConfigRecordKey { diff --git a/packages/taler-wallet-core/src/pay-merchant.ts b/packages/taler-wallet-core/src/pay-merchant.ts index 05cbd26b7..8eff7e17b 100644 --- a/packages/taler-wallet-core/src/pay-merchant.ts +++ b/packages/taler-wallet-core/src/pay-merchant.ts @@ -880,7 +880,7 @@ async function createOrReusePurchase( ); if (oldProposal.purchaseStatus === PurchaseStatus.DialogShared) { const download = await expectProposalDownload(wex, oldProposal); - const paid = await checkIfOrderIsAlreadyPaid(wex, download.contractData); + const paid = await checkIfOrderIsAlreadyPaid(wex, download.contractData, false); logger.info(`old proposal paid: ${paid}`); if (paid) { // if this transaction was shared and the order is paid then it @@ -895,6 +895,7 @@ async function createOrReusePurchase( } const oldTxState = computePayMerchantTransactionState(p); p.purchaseStatus = PurchaseStatus.FailedClaim; + p.paidByOther = true; const newTxState = computePayMerchantTransactionState(p); await tx.purchases.put(p); return { oldTxState, newTxState }; @@ -942,6 +943,7 @@ async function createOrReusePurchase( lastSessionId: undefined, merchantPaySig: undefined, payInfo: undefined, + paidByOther: undefined, refundAmountAwaiting: undefined, timestampAccept: undefined, timestampFirstSuccessfulPay: undefined, @@ -1377,7 +1379,7 @@ async function checkPaymentByProposalId( status: PreparePayResultType.AlreadyConfirmed, contractTerms: download.contractTermsRaw, contractTermsHash: download.contractData.contractTermsHash, - paid: false, + paid: purchase.paidByOther === true, amountRaw: Amounts.stringify(download.contractData.amount), amountEffective: purchase.payInfo ? Amounts.stringify(purchase.payInfo.totalPayCost) @@ -2009,7 +2011,7 @@ async function processPurchasePay( const download = await expectProposalDownload(wex, purchase); if (purchase.shared) { - const paid = await checkIfOrderIsAlreadyPaid(wex, download.contractData); + const paid = await checkIfOrderIsAlreadyPaid(wex, download.contractData, false); if (paid) { const transitionInfo = await wex.db.runReadWriteTx( @@ -2022,6 +2024,7 @@ async function processPurchasePay( } const oldTxState = computePayMerchantTransactionState(p); p.purchaseStatus = PurchaseStatus.FailedClaim; + p.paidByOther = true; const newTxState = computePayMerchantTransactionState(p); await tx.purchases.put(p); return { oldTxState, newTxState }; @@ -2467,6 +2470,7 @@ export async function sharePayment( } return { + proposalId: p.proposalId, nonce: p.noncePriv, session: p.lastSessionId ?? p.downloadSessionId, token: p.claimToken, @@ -2476,6 +2480,11 @@ export async function sharePayment( if (result === undefined) { throw Error("This purchase can't be shared"); } + + // schedule a task to watch for the status + const ctx = new PayMerchantTransactionContext(wex, result.proposalId); + wex.taskScheduler.startShepherdTask(ctx.taskId); + const privatePayUri = stringifyPayUri({ merchantBaseUrl, orderId, @@ -2483,12 +2492,14 @@ export async function sharePayment( noncePriv: result.nonce, claimToken: result.token, }); + return { privatePayUri }; } async function checkIfOrderIsAlreadyPaid( wex: WalletExecutionContext, contract: WalletContractData, + doLongPolling: boolean, ) { const requestUrl = new URL( `orders/${contract.orderId}`, @@ -2496,7 +2507,9 @@ async function checkIfOrderIsAlreadyPaid( ); requestUrl.searchParams.set("h_contract", contract.contractTermsHash); - requestUrl.searchParams.set("timeout_ms", "1000"); + if (doLongPolling) { + requestUrl.searchParams.set("timeout_ms", "30000"); + } const resp = await wex.http.fetch(requestUrl.href, { cancellationToken: wex.cancellationToken, @@ -2526,7 +2539,7 @@ async function processPurchaseDialogShared( return TaskRunResult.finished(); } - const paid = await checkIfOrderIsAlreadyPaid(wex, download.contractData); + const paid = await checkIfOrderIsAlreadyPaid(wex, download.contractData, true); if (paid) { const transitionInfo = await wex.db.runReadWriteTx( ["purchases"], @@ -2538,6 +2551,7 @@ async function processPurchaseDialogShared( } const oldTxState = computePayMerchantTransactionState(p); p.purchaseStatus = PurchaseStatus.FailedClaim; + p.paidByOther = true const newTxState = computePayMerchantTransactionState(p); await tx.purchases.put(p); return { oldTxState, newTxState }; |