diff options
author | Sebastian <sebasjm@gmail.com> | 2024-03-01 11:56:12 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2024-03-01 11:56:15 -0300 |
commit | 4d0bd5958690000a508c946b6d64819d55231375 (patch) | |
tree | 3c09c5833fd59201bfed62541826ea4580ebdad5 | |
parent | 1facde4ab16c8d943f16f7cb0ded8dc9104dacfd (diff) | |
download | wallet-core-4d0bd5958690000a508c946b6d64819d55231375.tar.gz wallet-core-4d0bd5958690000a508c946b6d64819d55231375.tar.bz2 wallet-core-4d0bd5958690000a508c946b6d64819d55231375.zip |
notify the UI about order paid by another wallet
After the request about the status of a shared payment returns
"PAID = true" save the information in the database and use
it to notify that the order is already-paid with paid:true
If the order is already-aid with paid:false the UI will
show claim-by-another-wallet which is not wrong
but for this use case the other-wallet intentionally paid
in the same session and is expected to be redirected to
the purchased fulfillment url.
note that the purchase does not create a transaction yet,
since the payment is not made in the first wallet.
And we should also take into account how this interacts
with the repurchase detection.
-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 e92156572..405ec14d7 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) @@ -2011,7 +2013,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( @@ -2024,6 +2026,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 }; @@ -2469,6 +2472,7 @@ export async function sharePayment( } return { + proposalId: p.proposalId, nonce: p.noncePriv, session: p.lastSessionId ?? p.downloadSessionId, token: p.claimToken, @@ -2478,6 +2482,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, @@ -2485,12 +2494,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}`, @@ -2498,7 +2509,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, @@ -2528,7 +2541,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"], @@ -2540,6 +2553,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 }; |