test case for order claiming; more accurate EC
This commit is contained in:
parent
1548086f50
commit
b1fd7d09a6
@ -1266,22 +1266,24 @@ function shellWrap(s: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class WalletCli {
|
export class WalletCli {
|
||||||
constructor(private globalTestState: GlobalTestState) {}
|
constructor(private globalTestState: GlobalTestState, private name: string = "default") {}
|
||||||
|
|
||||||
|
get dbfile(): string {
|
||||||
|
return this.globalTestState.testDir + `/walletdb-${this.name}.json`;
|
||||||
|
}
|
||||||
|
|
||||||
deleteDatabase() {
|
deleteDatabase() {
|
||||||
const wdb = this.globalTestState.testDir + "/walletdb.json";
|
fs.unlinkSync(this.dbfile);
|
||||||
fs.unlinkSync(wdb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async apiRequest(
|
async apiRequest(
|
||||||
request: string,
|
request: string,
|
||||||
payload: unknown,
|
payload: unknown,
|
||||||
): Promise<CoreApiResponse> {
|
): Promise<CoreApiResponse> {
|
||||||
const wdb = this.globalTestState.testDir + "/walletdb.json";
|
|
||||||
const resp = await sh(
|
const resp = await sh(
|
||||||
this.globalTestState,
|
this.globalTestState,
|
||||||
"wallet",
|
`wallet-${this.name}`,
|
||||||
`taler-wallet-cli --no-throttle --wallet-db '${wdb}' api '${request}' ${shellWrap(
|
`taler-wallet-cli --no-throttle --wallet-db '${this.dbfile}' api '${request}' ${shellWrap(
|
||||||
JSON.stringify(payload),
|
JSON.stringify(payload),
|
||||||
)}`,
|
)}`,
|
||||||
);
|
);
|
||||||
@ -1290,20 +1292,18 @@ export class WalletCli {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async runUntilDone(): Promise<void> {
|
async runUntilDone(): Promise<void> {
|
||||||
const wdb = this.globalTestState.testDir + "/walletdb.json";
|
|
||||||
await sh(
|
await sh(
|
||||||
this.globalTestState,
|
this.globalTestState,
|
||||||
"wallet",
|
`wallet-${this.name}`,
|
||||||
`taler-wallet-cli --no-throttle --wallet-db ${wdb} run-until-done`,
|
`taler-wallet-cli --no-throttle --wallet-db ${this.dbfile} run-until-done`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async runPending(): Promise<void> {
|
async runPending(): Promise<void> {
|
||||||
const wdb = this.globalTestState.testDir + "/walletdb.json";
|
|
||||||
await sh(
|
await sh(
|
||||||
this.globalTestState,
|
this.globalTestState,
|
||||||
"wallet",
|
`wallet-${this.name}`,
|
||||||
`taler-wallet-cli --no-throttle --wallet-db ${wdb} run-pending`,
|
`taler-wallet-cli --no-throttle --wallet-db ${this.dbfile} run-pending`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
/**
|
/**
|
||||||
* Imports.
|
* Imports.
|
||||||
*/
|
*/
|
||||||
import { runTest, GlobalTestState, MerchantPrivateApi } from "./harness";
|
import { runTest, GlobalTestState, MerchantPrivateApi, WalletCli } from "./harness";
|
||||||
import { createSimpleTestkudosEnvironment, withdrawViaBank } from "./helpers";
|
import { createSimpleTestkudosEnvironment, withdrawViaBank } from "./helpers";
|
||||||
import { PreparePayResultType } from "taler-wallet-core";
|
import { PreparePayResultType } from "taler-wallet-core";
|
||||||
|
|
||||||
|
@ -3209,6 +3209,13 @@ export enum TalerErrorCode {
|
|||||||
*/
|
*/
|
||||||
WALLET_HTTP_REQUEST_TIMEOUT = 7013,
|
WALLET_HTTP_REQUEST_TIMEOUT = 7013,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The order has already been claimed by another wallet.
|
||||||
|
* Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).
|
||||||
|
* (A value of 0 indicates that the error is generated client-side).
|
||||||
|
*/
|
||||||
|
WALLET_ORDER_ALREADY_CLAIMED = 7014,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* End of error code range.
|
* End of error code range.
|
||||||
* Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).
|
* Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).
|
||||||
|
@ -30,6 +30,9 @@ import Axios from "axios";
|
|||||||
import { OperationFailedError, makeErrorDetails } from "../operations/errors";
|
import { OperationFailedError, makeErrorDetails } from "../operations/errors";
|
||||||
import { TalerErrorCode } from "../TalerErrorCode";
|
import { TalerErrorCode } from "../TalerErrorCode";
|
||||||
import { URL } from "../util/url";
|
import { URL } from "../util/url";
|
||||||
|
import { Logger } from "../util/logging";
|
||||||
|
|
||||||
|
const logger = new Logger("NodeHttpLib.ts");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of the HTTP request library interface for node.
|
* Implementation of the HTTP request library interface for node.
|
||||||
@ -96,6 +99,7 @@ export class NodeHttpLib implements HttpRequestLibrary {
|
|||||||
try {
|
try {
|
||||||
responseJson = JSON.parse(respText);
|
responseJson = JSON.parse(respText);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.trace(`invalid json: '${respText}'`);
|
||||||
throw new OperationFailedError(
|
throw new OperationFailedError(
|
||||||
makeErrorDetails(
|
makeErrorDetails(
|
||||||
TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
|
TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
|
||||||
@ -109,6 +113,7 @@ export class NodeHttpLib implements HttpRequestLibrary {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (responseJson === null || typeof responseJson !== "object") {
|
if (responseJson === null || typeof responseJson !== "object") {
|
||||||
|
logger.trace(`invalid json (not an object): '${respText}'`);
|
||||||
throw new OperationFailedError(
|
throw new OperationFailedError(
|
||||||
makeErrorDetails(
|
makeErrorDetails(
|
||||||
TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
|
TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
|
||||||
|
@ -71,6 +71,7 @@ import {
|
|||||||
readSuccessResponseJsonOrThrow,
|
readSuccessResponseJsonOrThrow,
|
||||||
throwUnexpectedRequestError,
|
throwUnexpectedRequestError,
|
||||||
getHttpResponseErrorDetails,
|
getHttpResponseErrorDetails,
|
||||||
|
readSuccessResponseJsonOrErrorCode,
|
||||||
} from "../util/http";
|
} from "../util/http";
|
||||||
import { TalerErrorCode } from "../TalerErrorCode";
|
import { TalerErrorCode } from "../TalerErrorCode";
|
||||||
import { URL } from "../util/url";
|
import { URL } from "../util/url";
|
||||||
@ -638,13 +639,25 @@ async function processDownloadProposalImpl(
|
|||||||
requestBody.token = proposal.claimToken;
|
requestBody.token = proposal.claimToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
const resp = await ws.http.postJson(orderClaimUrl, requestBody, {
|
const httpResponse = await ws.http.postJson(orderClaimUrl, requestBody, {
|
||||||
timeout: getProposalRequestTimeout(proposal),
|
timeout: getProposalRequestTimeout(proposal),
|
||||||
});
|
});
|
||||||
const proposalResp = await readSuccessResponseJsonOrThrow(
|
const r = await readSuccessResponseJsonOrErrorCode(httpResponse, codecForProposal());
|
||||||
resp,
|
if (r.isError) {
|
||||||
codecForProposal(),
|
switch (r.talerErrorResponse.code) {
|
||||||
);
|
case TalerErrorCode.ORDERS_ALREADY_CLAIMED:
|
||||||
|
throw OperationFailedError.fromCode(
|
||||||
|
TalerErrorCode.WALLET_ORDER_ALREADY_CLAIMED,
|
||||||
|
"order already claimed (likely by other wallet)",
|
||||||
|
{
|
||||||
|
orderId: proposal.orderId,
|
||||||
|
claimUrl: orderClaimUrl,
|
||||||
|
});
|
||||||
|
default:
|
||||||
|
throwUnexpectedRequestError(httpResponse, r.talerErrorResponse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const proposalResp = r.response;
|
||||||
|
|
||||||
// The proposalResp contains the contract terms as raw JSON,
|
// The proposalResp contains the contract terms as raw JSON,
|
||||||
// as the coded to parse them doesn't necessarily round-trip.
|
// as the coded to parse them doesn't necessarily round-trip.
|
||||||
|
@ -59,11 +59,11 @@ function TalerPayDialog({ talerPayUri }: { talerPayUri: string }): JSX.Element {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let insufficientBalance = false;
|
let insufficientBalance = false;
|
||||||
if (payStatus.status == "insufficient-balance") {
|
if (payStatus.status == PreparePayResultType.InsufficientBalance) {
|
||||||
insufficientBalance = true;
|
insufficientBalance = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (payStatus.status === "payment-possible") {
|
if (payStatus.status === PreparePayResultType.PaymentPossible) {
|
||||||
amountEffective = Amounts.parseOrThrow(payStatus.amountEffective);
|
amountEffective = Amounts.parseOrThrow(payStatus.amountEffective);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user