diff --git a/src/crypto/workers/cryptoImplementation.ts b/src/crypto/workers/cryptoImplementation.ts index 43def7b6b..979fe41d8 100644 --- a/src/crypto/workers/cryptoImplementation.ts +++ b/src/crypto/workers/cryptoImplementation.ts @@ -336,7 +336,7 @@ export class CryptoImplementation { const d = buildSigPS(SignaturePurpose.WALLET_COIN_DEPOSIT) .put(decodeCrock(depositInfo.contractTermsHash)) .put(decodeCrock(depositInfo.wireInfoHash)) - .put(hash(decodeCrock(depositInfo.denomPub))) + .put(decodeCrock(depositInfo.denomPubHash)) .put(timestampRoundedToBuffer(depositInfo.timestamp)) .put(timestampRoundedToBuffer(depositInfo.refundDeadline)) .put(amountToBuffer(depositInfo.spendAmount)) @@ -350,7 +350,7 @@ export class CryptoImplementation { coin_pub: depositInfo.coinPub, coin_sig: encodeCrock(coinSig), contribution: Amounts.stringify(depositInfo.spendAmount), - denom_pub: depositInfo.denomPub, + h_denom: depositInfo.denomPubHash, exchange_url: depositInfo.exchangeBaseUrl, ub_sig: depositInfo.denomSig, }; diff --git a/src/headless/integrationtest.ts b/src/headless/integrationtest.ts index db96d57c4..786907a09 100644 --- a/src/headless/integrationtest.ts +++ b/src/headless/integrationtest.ts @@ -25,6 +25,7 @@ import { NodeHttpLib } from "./NodeHttpLib"; import { Wallet } from "../wallet"; import { Configuration } from "../util/talerconfig"; import { Amounts, AmountJson } from "../util/amounts"; +import { OperationFailedAndReportedError, OperationFailedError } from "../operations/errors"; const logger = new Logger("integrationtest.ts"); @@ -69,9 +70,9 @@ async function makePayment( } const confirmPayResult = await wallet.confirmPay( - preparePayResult.proposalId, - undefined, - ); + preparePayResult.proposalId, + undefined, + ); console.log("confirmPayResult", confirmPayResult); diff --git a/src/headless/taler-wallet-cli.ts b/src/headless/taler-wallet-cli.ts index 3f116670d..fc13d77f3 100644 --- a/src/headless/taler-wallet-cli.ts +++ b/src/headless/taler-wallet-cli.ts @@ -30,7 +30,7 @@ import { setupRefreshPlanchet, encodeCrock, } from "../crypto/talerCrypto"; -import { OperationFailedAndReportedError } from "../operations/errors"; +import { OperationFailedAndReportedError, OperationFailedError } from "../operations/errors"; import { Bank } from "./bank"; import { classifyTalerUri, TalerUriType } from "../util/taleruri"; import { Configuration } from "../util/talerconfig"; @@ -97,7 +97,6 @@ async function doPay( if (pay) { await wallet.confirmPay(result.proposalId, undefined); - console.log("paid!"); } else { console.log("not paying"); } diff --git a/src/operations/balance.ts b/src/operations/balance.ts index 36971c395..81b4da6e0 100644 --- a/src/operations/balance.ts +++ b/src/operations/balance.ts @@ -130,7 +130,7 @@ export async function getBalancesInsideTransaction( if (t.timestampFirstSuccessfulPay) { return; } - for (const c of t.payReq.coins) { + for (const c of t.coinDepositPermissions) { addTo( balanceStore, "pendingPayment", diff --git a/src/operations/errors.ts b/src/operations/errors.ts index 9def02b0e..01a8283cb 100644 --- a/src/operations/errors.ts +++ b/src/operations/errors.ts @@ -24,8 +24,6 @@ * Imports. */ import { OperationError } from "../types/walletTypes"; -import { HttpResponse } from "../util/http"; -import { Codec } from "../util/codec"; /** * This exception is there to let the caller know that an error happened, diff --git a/src/operations/history.ts b/src/operations/history.ts index f04dad113..9cbbd5163 100644 --- a/src/operations/history.ts +++ b/src/operations/history.ts @@ -246,7 +246,7 @@ export async function getHistory( contribution: string; denomPub: string; }[] = []; - for (const x of purchase.payReq.coins) { + for (const x of purchase.coinDepositPermissions) { const c = await tx.get(Stores.coins, x.coin_pub); if (!c) { // FIXME: what to do here?? @@ -269,7 +269,7 @@ export async function getHistory( verboseDetails = { coins }; } const amountPaidWithFees = Amounts.sum( - purchase.payReq.coins.map((x) => + purchase.coinDepositPermissions.map((x) => Amounts.parseOrThrow(x.contribution), ), ).amount; @@ -280,7 +280,7 @@ export async function getHistory( replay: pe.isReplay, sessionId: pe.sessionId, timestamp: pe.timestamp, - numCoins: purchase.payReq.coins.length, + numCoins: purchase.coinDepositPermissions.length, amountPaidWithFees: Amounts.stringify(amountPaidWithFees), verboseDetails, }); diff --git a/src/operations/pay.ts b/src/operations/pay.ts index abcb2ad1d..74bfcc70b 100644 --- a/src/operations/pay.ts +++ b/src/operations/pay.ts @@ -42,6 +42,7 @@ import { codecForProposal, codecForContractTerms, CoinDepositPermission, + codecForMerchantPayResponse, } from "../types/talerTypes"; import { ConfirmPayResult, @@ -431,12 +432,6 @@ async function recordConfirmPay( sessionId = proposal.downloadSessionId; } logger.trace(`recording payment with session ID ${sessionId}`); - const payReq: PayReq = { - coins: coinDepositPermissions, - merchant_pub: d.contractData.merchantPub, - mode: "pay", - order_id: d.contractData.orderId, - }; const payCostInfo = await getTotalPaymentCost(ws, coinSelection); const t: PurchaseRecord = { abortDone: false, @@ -445,8 +440,8 @@ async function recordConfirmPay( contractData: d.contractData, lastSessionId: sessionId, payCoinSelection: coinSelection, - payReq, payCostInfo, + coinDepositPermissions, timestampAccept: getTimestampNow(), timestampLastRefundStatus: undefined, proposalId: proposal.proposalId, @@ -609,7 +604,6 @@ async function processDownloadProposalImpl( ).href; logger.trace("downloading contract from '" + orderClaimUrl + "'"); - const proposalResp = await httpPostTalerJson({ url: orderClaimUrl, body: { @@ -777,26 +771,24 @@ export async function submitPay( throw Error("not submitting payment for aborted purchase"); } const sessionId = purchase.lastSessionId; - let resp; - const payReq = { ...purchase.payReq, session_id: sessionId }; console.log("paying with session ID", sessionId); - const payUrl = new URL("pay", purchase.contractData.merchantBaseUrl).href; + const payUrl = new URL( + `orders/${purchase.contractData.orderId}/pay`, + purchase.contractData.merchantBaseUrl, + ).href; + + const merchantResp = await httpPostTalerJson({ + url: payUrl, + body: { + coins: purchase.coinDepositPermissions, + session_id: purchase.lastSessionId, + }, + codec: codecForMerchantPayResponse(), + http: ws.http, + }); - try { - console.log("pay req", payReq); - resp = await ws.http.postJson(payUrl, payReq); - } catch (e) { - // Gives the user the option to retry / abort and refresh - console.log("payment failed", e); - throw e; - } - if (resp.status !== 200) { - console.log(await resp.json()); - throw Error(`unexpected status (${resp.status}) for /pay`); - } - const merchantResp = await resp.json(); console.log("got success from pay URL", merchantResp); const now = getTimestampNow(); @@ -1030,7 +1022,7 @@ export async function confirmPay( coinPriv: coin.coinPriv, coinPub: coin.coinPub, contractTermsHash: d.contractData.contractTermsHash, - denomPub: coin.denomPub, + denomPubHash: coin.denomPubHash, denomSig: coin.denomSig, exchangeBaseUrl: coin.exchangeBaseUrl, feeDeposit: denom.feeDeposit, @@ -1050,8 +1042,6 @@ export async function confirmPay( sessionIdOverride, ); - logger.trace("confirmPay: submitting payment after creating purchase record"); - logger.trace("purchaseRecord:", purchase); return submitPay(ws, proposalId); } diff --git a/src/types/dbTypes.ts b/src/types/dbTypes.ts index 4f7b89b67..b085f83db 100644 --- a/src/types/dbTypes.ts +++ b/src/types/dbTypes.ts @@ -1250,10 +1250,9 @@ export interface PurchaseRecord { contractData: WalletContractData; /** - * The payment request, ready to be send to the merchant's - * /pay URL. + * Deposit permissions, available once the user has accepted the payment. */ - payReq: PayReq; + coinDepositPermissions: CoinDepositPermission[]; payCoinSelection: PayCoinSelection; diff --git a/src/types/talerTypes.ts b/src/types/talerTypes.ts index 0221d26bb..232f5f314 100644 --- a/src/types/talerTypes.ts +++ b/src/types/talerTypes.ts @@ -215,7 +215,7 @@ export interface CoinDepositPermission { /** * The denomination public key associated with this coin. */ - denom_pub: string; + h_denom: string; /** * The amount that is subtracted from this coin with this payment. */ @@ -433,31 +433,6 @@ export class ContractTerms { extra: any; } -/** - * Payment body sent to the merchant's /pay. - */ -export interface PayReq { - /** - * Coins with signature. - */ - coins: CoinDepositPermission[]; - - /** - * The merchant public key, used to uniquely - * identify the merchant instance. - */ - merchant_pub: string; - - /** - * Order ID that's being payed for. - */ - order_id: string; - - /** - * Mode for /pay. - */ - mode: "pay" | "abort-refund"; -} /** * Refund permission in the format that the merchant gives it to us. @@ -809,6 +784,10 @@ export interface CoinDumpJson { }>; } +export interface MerchantPayResponse { + sig: string; +} + export type AmountString = string; export type Base32String = string; export type EddsaSignatureString = string; @@ -1044,3 +1023,8 @@ export const codecForWithdrawResponse = (): Codec => makeCodecForObject() .property("ev_sig", codecForString) .build("WithdrawResponse"); + +export const codecForMerchantPayResponse = (): Codec => + makeCodecForObject() + .property("sig", codecForString) + .build("MerchantPayResponse"); diff --git a/src/types/walletTypes.ts b/src/types/walletTypes.ts index 63b20095e..ee7d071c6 100644 --- a/src/types/walletTypes.ts +++ b/src/types/walletTypes.ts @@ -473,7 +473,7 @@ export interface DepositInfo { merchantPub: string; feeDeposit: AmountJson; wireInfoHash: string; - denomPub: string; + denomPubHash: string; denomSig: string; }