towards consuming new merchant API

This commit is contained in:
Florian Dold 2020-07-21 12:23:48 +05:30
parent dd2efc3d78
commit f4a8702b3c
No known key found for this signature in database
GPG Key ID: D2E4F00F29D02A4B
10 changed files with 41 additions and 70 deletions

View File

@ -336,7 +336,7 @@ export class CryptoImplementation {
const d = buildSigPS(SignaturePurpose.WALLET_COIN_DEPOSIT) const d = buildSigPS(SignaturePurpose.WALLET_COIN_DEPOSIT)
.put(decodeCrock(depositInfo.contractTermsHash)) .put(decodeCrock(depositInfo.contractTermsHash))
.put(decodeCrock(depositInfo.wireInfoHash)) .put(decodeCrock(depositInfo.wireInfoHash))
.put(hash(decodeCrock(depositInfo.denomPub))) .put(decodeCrock(depositInfo.denomPubHash))
.put(timestampRoundedToBuffer(depositInfo.timestamp)) .put(timestampRoundedToBuffer(depositInfo.timestamp))
.put(timestampRoundedToBuffer(depositInfo.refundDeadline)) .put(timestampRoundedToBuffer(depositInfo.refundDeadline))
.put(amountToBuffer(depositInfo.spendAmount)) .put(amountToBuffer(depositInfo.spendAmount))
@ -350,7 +350,7 @@ export class CryptoImplementation {
coin_pub: depositInfo.coinPub, coin_pub: depositInfo.coinPub,
coin_sig: encodeCrock(coinSig), coin_sig: encodeCrock(coinSig),
contribution: Amounts.stringify(depositInfo.spendAmount), contribution: Amounts.stringify(depositInfo.spendAmount),
denom_pub: depositInfo.denomPub, h_denom: depositInfo.denomPubHash,
exchange_url: depositInfo.exchangeBaseUrl, exchange_url: depositInfo.exchangeBaseUrl,
ub_sig: depositInfo.denomSig, ub_sig: depositInfo.denomSig,
}; };

View File

@ -25,6 +25,7 @@ import { NodeHttpLib } from "./NodeHttpLib";
import { Wallet } from "../wallet"; import { Wallet } from "../wallet";
import { Configuration } from "../util/talerconfig"; import { Configuration } from "../util/talerconfig";
import { Amounts, AmountJson } from "../util/amounts"; import { Amounts, AmountJson } from "../util/amounts";
import { OperationFailedAndReportedError, OperationFailedError } from "../operations/errors";
const logger = new Logger("integrationtest.ts"); const logger = new Logger("integrationtest.ts");
@ -69,9 +70,9 @@ async function makePayment(
} }
const confirmPayResult = await wallet.confirmPay( const confirmPayResult = await wallet.confirmPay(
preparePayResult.proposalId, preparePayResult.proposalId,
undefined, undefined,
); );
console.log("confirmPayResult", confirmPayResult); console.log("confirmPayResult", confirmPayResult);

View File

@ -30,7 +30,7 @@ import {
setupRefreshPlanchet, setupRefreshPlanchet,
encodeCrock, encodeCrock,
} from "../crypto/talerCrypto"; } from "../crypto/talerCrypto";
import { OperationFailedAndReportedError } from "../operations/errors"; import { OperationFailedAndReportedError, OperationFailedError } from "../operations/errors";
import { Bank } from "./bank"; import { Bank } from "./bank";
import { classifyTalerUri, TalerUriType } from "../util/taleruri"; import { classifyTalerUri, TalerUriType } from "../util/taleruri";
import { Configuration } from "../util/talerconfig"; import { Configuration } from "../util/talerconfig";
@ -97,7 +97,6 @@ async function doPay(
if (pay) { if (pay) {
await wallet.confirmPay(result.proposalId, undefined); await wallet.confirmPay(result.proposalId, undefined);
console.log("paid!");
} else { } else {
console.log("not paying"); console.log("not paying");
} }

View File

@ -130,7 +130,7 @@ export async function getBalancesInsideTransaction(
if (t.timestampFirstSuccessfulPay) { if (t.timestampFirstSuccessfulPay) {
return; return;
} }
for (const c of t.payReq.coins) { for (const c of t.coinDepositPermissions) {
addTo( addTo(
balanceStore, balanceStore,
"pendingPayment", "pendingPayment",

View File

@ -24,8 +24,6 @@
* Imports. * Imports.
*/ */
import { OperationError } from "../types/walletTypes"; 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, * This exception is there to let the caller know that an error happened,

View File

@ -246,7 +246,7 @@ export async function getHistory(
contribution: string; contribution: string;
denomPub: 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); const c = await tx.get(Stores.coins, x.coin_pub);
if (!c) { if (!c) {
// FIXME: what to do here?? // FIXME: what to do here??
@ -269,7 +269,7 @@ export async function getHistory(
verboseDetails = { coins }; verboseDetails = { coins };
} }
const amountPaidWithFees = Amounts.sum( const amountPaidWithFees = Amounts.sum(
purchase.payReq.coins.map((x) => purchase.coinDepositPermissions.map((x) =>
Amounts.parseOrThrow(x.contribution), Amounts.parseOrThrow(x.contribution),
), ),
).amount; ).amount;
@ -280,7 +280,7 @@ export async function getHistory(
replay: pe.isReplay, replay: pe.isReplay,
sessionId: pe.sessionId, sessionId: pe.sessionId,
timestamp: pe.timestamp, timestamp: pe.timestamp,
numCoins: purchase.payReq.coins.length, numCoins: purchase.coinDepositPermissions.length,
amountPaidWithFees: Amounts.stringify(amountPaidWithFees), amountPaidWithFees: Amounts.stringify(amountPaidWithFees),
verboseDetails, verboseDetails,
}); });

View File

@ -42,6 +42,7 @@ import {
codecForProposal, codecForProposal,
codecForContractTerms, codecForContractTerms,
CoinDepositPermission, CoinDepositPermission,
codecForMerchantPayResponse,
} from "../types/talerTypes"; } from "../types/talerTypes";
import { import {
ConfirmPayResult, ConfirmPayResult,
@ -431,12 +432,6 @@ async function recordConfirmPay(
sessionId = proposal.downloadSessionId; sessionId = proposal.downloadSessionId;
} }
logger.trace(`recording payment with session ID ${sessionId}`); 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 payCostInfo = await getTotalPaymentCost(ws, coinSelection);
const t: PurchaseRecord = { const t: PurchaseRecord = {
abortDone: false, abortDone: false,
@ -445,8 +440,8 @@ async function recordConfirmPay(
contractData: d.contractData, contractData: d.contractData,
lastSessionId: sessionId, lastSessionId: sessionId,
payCoinSelection: coinSelection, payCoinSelection: coinSelection,
payReq,
payCostInfo, payCostInfo,
coinDepositPermissions,
timestampAccept: getTimestampNow(), timestampAccept: getTimestampNow(),
timestampLastRefundStatus: undefined, timestampLastRefundStatus: undefined,
proposalId: proposal.proposalId, proposalId: proposal.proposalId,
@ -609,7 +604,6 @@ async function processDownloadProposalImpl(
).href; ).href;
logger.trace("downloading contract from '" + orderClaimUrl + "'"); logger.trace("downloading contract from '" + orderClaimUrl + "'");
const proposalResp = await httpPostTalerJson({ const proposalResp = await httpPostTalerJson({
url: orderClaimUrl, url: orderClaimUrl,
body: { body: {
@ -777,26 +771,24 @@ export async function submitPay(
throw Error("not submitting payment for aborted purchase"); throw Error("not submitting payment for aborted purchase");
} }
const sessionId = purchase.lastSessionId; const sessionId = purchase.lastSessionId;
let resp;
const payReq = { ...purchase.payReq, session_id: sessionId };
console.log("paying with 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); console.log("got success from pay URL", merchantResp);
const now = getTimestampNow(); const now = getTimestampNow();
@ -1030,7 +1022,7 @@ export async function confirmPay(
coinPriv: coin.coinPriv, coinPriv: coin.coinPriv,
coinPub: coin.coinPub, coinPub: coin.coinPub,
contractTermsHash: d.contractData.contractTermsHash, contractTermsHash: d.contractData.contractTermsHash,
denomPub: coin.denomPub, denomPubHash: coin.denomPubHash,
denomSig: coin.denomSig, denomSig: coin.denomSig,
exchangeBaseUrl: coin.exchangeBaseUrl, exchangeBaseUrl: coin.exchangeBaseUrl,
feeDeposit: denom.feeDeposit, feeDeposit: denom.feeDeposit,
@ -1050,8 +1042,6 @@ export async function confirmPay(
sessionIdOverride, sessionIdOverride,
); );
logger.trace("confirmPay: submitting payment after creating purchase record");
logger.trace("purchaseRecord:", purchase);
return submitPay(ws, proposalId); return submitPay(ws, proposalId);
} }

View File

@ -1250,10 +1250,9 @@ export interface PurchaseRecord {
contractData: WalletContractData; contractData: WalletContractData;
/** /**
* The payment request, ready to be send to the merchant's * Deposit permissions, available once the user has accepted the payment.
* /pay URL.
*/ */
payReq: PayReq; coinDepositPermissions: CoinDepositPermission[];
payCoinSelection: PayCoinSelection; payCoinSelection: PayCoinSelection;

View File

@ -215,7 +215,7 @@ export interface CoinDepositPermission {
/** /**
* The denomination public key associated with this coin. * 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. * The amount that is subtracted from this coin with this payment.
*/ */
@ -433,31 +433,6 @@ export class ContractTerms {
extra: any; 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. * 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 AmountString = string;
export type Base32String = string; export type Base32String = string;
export type EddsaSignatureString = string; export type EddsaSignatureString = string;
@ -1044,3 +1023,8 @@ export const codecForWithdrawResponse = (): Codec<WithdrawResponse> =>
makeCodecForObject<WithdrawResponse>() makeCodecForObject<WithdrawResponse>()
.property("ev_sig", codecForString) .property("ev_sig", codecForString)
.build("WithdrawResponse"); .build("WithdrawResponse");
export const codecForMerchantPayResponse = (): Codec<MerchantPayResponse> =>
makeCodecForObject<MerchantPayResponse>()
.property("sig", codecForString)
.build("MerchantPayResponse");

View File

@ -473,7 +473,7 @@ export interface DepositInfo {
merchantPub: string; merchantPub: string;
feeDeposit: AmountJson; feeDeposit: AmountJson;
wireInfoHash: string; wireInfoHash: string;
denomPub: string; denomPubHash: string;
denomSig: string; denomSig: string;
} }