diff options
Diffstat (limited to 'packages/taler-util/src')
-rw-r--r-- | packages/taler-util/src/http-client/bank-integration.ts | 42 | ||||
-rw-r--r-- | packages/taler-util/src/http-client/bank-revenue.ts | 16 | ||||
-rw-r--r-- | packages/taler-util/src/http-client/bank-wire.ts | 57 | ||||
-rw-r--r-- | packages/taler-util/src/http-client/types.ts | 43 |
4 files changed, 125 insertions, 33 deletions
diff --git a/packages/taler-util/src/http-client/bank-integration.ts b/packages/taler-util/src/http-client/bank-integration.ts index e59f6086a..7cddcb9a9 100644 --- a/packages/taler-util/src/http-client/bank-integration.ts +++ b/packages/taler-util/src/http-client/bank-integration.ts @@ -1,11 +1,14 @@ import { HttpRequestLibrary, readSuccessResponseJsonOrThrow } from "../http-common.js"; import { HttpStatusCode } from "../http-status-codes.js"; import { createPlatformHttpLib } from "../http.js"; -import { opSuccess, opUnknownFailure } from "../operation.js"; +import { opKnownFailure, opSuccess, opUnknownFailure } from "../operation.js"; +import { TalerErrorCode } from "../taler-error-codes.js"; +import { codecForTalerErrorDetail } from "../wallet-types.js"; import { TalerBankIntegrationApi, codecForBankWithdrawalOperationPostResponse, - codecForBankWithdrawalOperationStatus + codecForBankWithdrawalOperationStatus, + codecForIntegrationBankConfig } from "./types.js"; export class TalerBankIntegrationHttpClient { @@ -19,10 +22,25 @@ export class TalerBankIntegrationHttpClient { } /** + * https://docs.taler.net/core/api-bank-integration.html#get--config + * + */ + async getConfig() { + const url = new URL(`config`, this.baseUrl); + const resp = await this.httpLib.fetch(url.href, { + method: "GET" + }); + switch (resp.status) { + case HttpStatusCode.Ok: return opSuccess(resp, codecForIntegrationBankConfig()) + default: return opUnknownFailure(resp, await resp.text()) + } + } + + /** * https://docs.taler.net/core/api-bank-integration.html#get-$BANK_API_BASE_URL-withdrawal-operation-$wopid * */ - async getWithdrawalOperationById(woid: string, timeoutMs?: number): Promise<TalerBankIntegrationApi.BankWithdrawalOperationStatus> { + async getWithdrawalOperationById(woid: string, timeoutMs?: number) { const url = new URL(`withdrawal-operation/${woid}`, this.baseUrl); if (timeoutMs) { url.searchParams.set("long_poll_ms", String(timeoutMs)) @@ -30,7 +48,11 @@ export class TalerBankIntegrationHttpClient { const resp = await this.httpLib.fetch(url.href, { method: "GET" }); - return readSuccessResponseJsonOrThrow(resp, codecForBankWithdrawalOperationStatus()); + switch (resp.status) { + case HttpStatusCode.Ok: return opSuccess(resp, codecForBankWithdrawalOperationStatus()) + case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp) + default: return opUnknownFailure(resp, await resp.text()) + } } /** @@ -45,6 +67,18 @@ export class TalerBankIntegrationHttpClient { }); switch (resp.status) { case HttpStatusCode.Ok: return opSuccess(resp, codecForBankWithdrawalOperationPostResponse()) + case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp) + case HttpStatusCode.Conflict: { + const body = await resp.json() + const details = codecForTalerErrorDetail().decode(body) + switch (details.code) { + case TalerErrorCode.BANK_WITHDRAWAL_OPERATION_RESERVE_SELECTION_CONFLICT: return opKnownFailure("already-selected", resp); + case TalerErrorCode.BANK_DUPLICATE_RESERVE_PUB_SUBJECT: return opKnownFailure("duplicated-reserve-id", resp); + // case TalerErrorCode.BANK_ACCOUNT_NOT_FOUND: return opKnownFailure("account-not-found", resp); + case TalerErrorCode.BANK_ACCOUNT_IS_NOT_EXCHANGE: return opKnownFailure("account-not-exchange", resp); + default: return opUnknownFailure(resp, body) + } + } default: return opUnknownFailure(resp, await resp.text()) } } diff --git a/packages/taler-util/src/http-client/bank-revenue.ts b/packages/taler-util/src/http-client/bank-revenue.ts index d594da574..c6adac557 100644 --- a/packages/taler-util/src/http-client/bank-revenue.ts +++ b/packages/taler-util/src/http-client/bank-revenue.ts @@ -1,6 +1,9 @@ import { HttpRequestLibrary, makeBasicAuthHeader, readSuccessResponseJsonOrThrow } from "../http-common.js"; +import { HttpStatusCode } from "../http-status-codes.js"; import { createPlatformHttpLib } from "../http.js"; -import { TalerRevenueApi, codecForMerchantIncomingHistory } from "./types.js"; +import { opKnownFailure, opSuccess, opUnknownFailure } from "../operation.js"; +import { PaginationParams, TalerRevenueApi, codecForMerchantIncomingHistory } from "./types.js"; +import { addPaginationParams } from "./utils.js"; export class TalerRevenueHttpClient { httpLib: HttpRequestLibrary; @@ -18,14 +21,21 @@ export class TalerRevenueHttpClient { * * @returns */ - async getHistory(auth: string): Promise<TalerRevenueApi.MerchantIncomingHistory> { + async getHistory(auth: string, pagination?: PaginationParams) { const url = new URL(`history`, this.baseUrl); + addPaginationParams(url, pagination) const resp = await this.httpLib.fetch(url.href, { method: "GET", headers: { Authorization: makeBasicAuthHeader(this.username, auth), } }); - return readSuccessResponseJsonOrThrow(resp, codecForMerchantIncomingHistory()); + switch (resp.status) { + case HttpStatusCode.Ok: return opSuccess(resp, codecForMerchantIncomingHistory()) + case HttpStatusCode.BadRequest: return opKnownFailure("invalid-input", resp); + case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", resp); + case HttpStatusCode.NotFound: return opKnownFailure("endpoint-wrong-or-username-wrong", resp); + default: return opUnknownFailure(resp, await resp.text()) + } } }
\ No newline at end of file diff --git a/packages/taler-util/src/http-client/bank-wire.ts b/packages/taler-util/src/http-client/bank-wire.ts index 0a032cc61..af0857ac5 100644 --- a/packages/taler-util/src/http-client/bank-wire.ts +++ b/packages/taler-util/src/http-client/bank-wire.ts @@ -1,5 +1,7 @@ import { HttpRequestLibrary, makeBasicAuthHeader, readSuccessResponseJsonOrThrow } from "../http-common.js"; +import { HttpStatusCode } from "../http-status-codes.js"; import { createPlatformHttpLib } from "../http.js"; +import { opEmptySuccess, opFixedSuccess, opKnownFailure, opSuccess, opUnknownFailure } from "../operation.js"; import { PaginationParams, TalerWireGatewayApi, codecForAddIncomingResponse, codecForIncomingHistory, codecForOutgoingHistory, codecForTransferResponse } from "./types.js"; import { addPaginationParams } from "./utils.js"; @@ -28,7 +30,7 @@ export class TalerWireGatewayHttpClient { async transfer( auth: string, body: TalerWireGatewayApi.TransferRequest, - ): Promise<TalerWireGatewayApi.TransferResponse> { + ) { const url = new URL(`transfer`, this.baseUrl); const resp = await this.httpLib.fetch(url.href, { method: "POST", @@ -37,17 +39,21 @@ export class TalerWireGatewayHttpClient { }, body }); - return readSuccessResponseJsonOrThrow(resp, codecForTransferResponse()); + switch (resp.status) { + case HttpStatusCode.Ok: return opSuccess(resp, codecForTransferResponse()) + case HttpStatusCode.BadRequest: return opKnownFailure("invalid-input", resp); + case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", resp); + case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp); + case HttpStatusCode.Conflict: return opKnownFailure("request-uid-already-used", resp); + default: return opUnknownFailure(resp, await resp.text()) + } } /** * https://docs.taler.net/core/api-bank-wire.html#get-$BASE_URL-history-incoming * */ - async getHistoryIncoming( - auth: string, - pagination?: PaginationParams - ): Promise<TalerWireGatewayApi.IncomingHistory> { + async getHistoryIncoming(auth: string, pagination?: PaginationParams) { const url = new URL(`history/incoming`, this.baseUrl); addPaginationParams(url, pagination) const resp = await this.httpLib.fetch(url.href, { @@ -56,16 +62,21 @@ export class TalerWireGatewayHttpClient { Authorization: makeBasicAuthHeader(this.username, auth), } }); - return readSuccessResponseJsonOrThrow(resp, codecForIncomingHistory()); + switch (resp.status) { + case HttpStatusCode.Ok: return opSuccess(resp, codecForIncomingHistory()) + case HttpStatusCode.NoContent: return opFixedSuccess({ incoming_transactions: [], credit_account: "" }) + case HttpStatusCode.BadRequest: return opKnownFailure("invalid-input", resp); + case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", resp); + case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp); + default: return opUnknownFailure(resp, await resp.text()) + } + // return readSuccessResponseJsonOrThrow(resp, codecForIncomingHistory()); } /** * https://docs.taler.net/core/api-bank-wire.html#get-$BASE_URL-history-outgoing * */ - async getHistoryOutgoing( - auth: string, - pagination?: PaginationParams - ): Promise<TalerWireGatewayApi.OutgoingHistory> { + async getHistoryOutgoing(auth: string, pagination?: PaginationParams) { const url = new URL(`history/outgoing`, this.baseUrl); addPaginationParams(url, pagination) const resp = await this.httpLib.fetch(url.href, { @@ -74,16 +85,20 @@ export class TalerWireGatewayHttpClient { Authorization: makeBasicAuthHeader(this.username, auth), } }); - return readSuccessResponseJsonOrThrow(resp, codecForOutgoingHistory()); + switch (resp.status) { + case HttpStatusCode.Ok: return opSuccess(resp, codecForOutgoingHistory()) + case HttpStatusCode.NoContent: return opFixedSuccess({ outgoing_transactions: [], debit_account: "" }) + case HttpStatusCode.BadRequest: return opKnownFailure("invalid-input", resp); + case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", resp); + case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp); + default: return opUnknownFailure(resp, await resp.text()) + } } /** * https://docs.taler.net/core/api-bank-wire.html#post-$BASE_URL-admin-add-incoming * */ - async addIncoming( - auth: string, - body: TalerWireGatewayApi.AddIncomingRequest, - ): Promise<TalerWireGatewayApi.AddIncomingResponse> { + async addIncoming(auth: string, body: TalerWireGatewayApi.AddIncomingRequest,) { const url = new URL(`admin/add-incoming`, this.baseUrl); const resp = await this.httpLib.fetch(url.href, { method: "POST", @@ -92,7 +107,15 @@ export class TalerWireGatewayHttpClient { }, body }); - return readSuccessResponseJsonOrThrow(resp, codecForAddIncomingResponse()); + switch (resp.status) { + case HttpStatusCode.Ok: return opSuccess(resp, codecForAddIncomingResponse()) + case HttpStatusCode.NoContent: return opFixedSuccess({ outgoing_transactions: [], debit_account: "" }) + case HttpStatusCode.BadRequest: return opKnownFailure("invalid-input", resp); + case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", resp); + case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp); + case HttpStatusCode.Conflict: return opKnownFailure("reserve-id-already-used", resp); + default: return opUnknownFailure(resp, await resp.text()) + } } } diff --git a/packages/taler-util/src/http-client/types.ts b/packages/taler-util/src/http-client/types.ts index 95d0f8dd6..38df08f9a 100644 --- a/packages/taler-util/src/http-client/types.ts +++ b/packages/taler-util/src/http-client/types.ts @@ -227,10 +227,19 @@ export const codecForCurrencySpecificiation = .property("alt_unit_names", codecForMap(codecForString())) .build("CurrencySpecification") +export const codecForIntegrationBankConfig = + (): Codec<TalerCorebankApi.IntegrationConfig> => + buildCodecForObject<TalerCorebankApi.IntegrationConfig>() + .property("name", codecForConstString("taler-bank-integration")) + .property("version", codecForString()) + .property("currency", codecForString()) + .property("currency_specification", codecForCurrencySpecificiation()) + .build("TalerCorebankApi.IntegrationConfig") + export const codecForCoreBankConfig = (): Codec<TalerCorebankApi.Config> => buildCodecForObject<TalerCorebankApi.Config>() - .property("name", codecForString()) + .property("name", codecForConstString("taler-corebank")) .property("version", codecForString()) .property("allow_deletions", codecForBoolean()) .property("allow_registrations", codecForBoolean()) @@ -431,12 +440,12 @@ export const codecForBankWithdrawalOperationStatus = (): Codec<TalerBankIntegrationApi.BankWithdrawalOperationStatus> => buildCodecForObject<TalerBankIntegrationApi.BankWithdrawalOperationStatus>() .property("aborted", codecForBoolean()) - .property("amount", codecForAmountString()) - .property("confirm_transfer_url", codecOptional(codecForURL())) .property("selection_done", codecForBoolean()) - .property("sender_wire", codecForPaytoString()) - .property("suggested_exchange", codecOptional(codecForString())) .property("transfer_done", codecForBoolean()) + .property("amount", codecForAmountString()) + .property("sender_wire", codecOptional(codecForPaytoString())) + .property("suggested_exchange", codecOptional(codecForString())) + .property("confirm_transfer_url", codecOptional(codecForURL())) .property("wire_types", codecForList(codecForString())) .build("TalerBankIntegrationApi.BankWithdrawalOperationStatus"); @@ -457,11 +466,11 @@ export const codecForMerchantIncomingHistory = export const codecForMerchantIncomingBankTransaction = (): Codec<TalerRevenueApi.MerchantIncomingBankTransaction> => buildCodecForObject<TalerRevenueApi.MerchantIncomingBankTransaction>() - .property("amount", codecForAmountString()) + .property("row_id", codecForNumber()) .property("date", codecForTimestamp) + .property("amount", codecForAmountString()) .property("debit_account", codecForPaytoString()) .property("exchange_url", codecForURL()) - .property("row_id", codecForNumber()) .property("wtid", codecForString()) .build("TalerRevenueApi.MerchantIncomingBankTransaction"); @@ -842,9 +851,25 @@ export namespace TalerBankIntegrationApi { } export namespace TalerCorebankApi { + export interface IntegrationConfig { + // libtool-style representation of the Bank protocol version, see + // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning + // The format is "current:revision:age". + version: string; + + // Currency used by this bank. + currency: string; + + // How the bank SPA should render this currency. + currency_specification: CurrencySpecification; + + // Name of the API. + name: "taler-bank-integration"; + + } export interface Config { - // Name of this API, always "circuit". - name: string; + // Name of this API, always "taler-corebank". + name: "taler-corebank"; // API version in the form $n:$n:$n version: string; |