diff options
Diffstat (limited to 'packages/taler-util/src/http-client/bank-core.ts')
-rw-r--r-- | packages/taler-util/src/http-client/bank-core.ts | 204 |
1 files changed, 80 insertions, 124 deletions
diff --git a/packages/taler-util/src/http-client/bank-core.ts b/packages/taler-util/src/http-client/bank-core.ts index dbb6c7112..8a3283d0f 100644 --- a/packages/taler-util/src/http-client/bank-core.ts +++ b/packages/taler-util/src/http-client/bank-core.ts @@ -17,6 +17,7 @@ import { HttpStatusCode, LibtoolVersion, + LongPollParams, TalerErrorCode, codecForChallenge, codecForTalerErrorDetail, @@ -29,22 +30,26 @@ import { HttpRequestLibrary, createPlatformHttpLib } from "@gnu-taler/taler-util/http"; -import { FailCasesByMethod, ResultByMethod, opEmptySuccess, opFixedSuccess, opKnownFailure, opSuccess, opUnknownFailure } from "../operation.js"; +import { FailCasesByMethod, ResultByMethod, opEmptySuccess, opFixedSuccess, opSuccess, opUnknownFailure } from "../operation.js"; import { TalerAuthenticationHttpClient } from "./authentication.js"; import { TalerBankConversionHttpClient } from "./bank-conversion.js"; import { TalerBankIntegrationHttpClient } from "./bank-integration.js"; import { TalerRevenueHttpClient } from "./bank-revenue.js"; import { TalerWireGatewayHttpClient } from "./bank-wire.js"; import { AccessToken, PaginationParams, TalerCorebankApi, UserAndToken, WithdrawalOperationStatus, codecForAccountData, codecForBankAccountCreateWithdrawalResponse, codecForBankAccountTransactionInfo, codecForBankAccountTransactionsResponse, codecForCashoutPending, codecForCashoutStatusResponse, codecForCashouts, codecForCoreBankConfig, codecForCreateTransactionResponse, codecForGlobalCashouts, codecForListBankAccountsResponse, codecForMonitorResponse, codecForPublicAccountsResponse, codecForRegisterAccountResponse, codecForWithdrawalPublicInfo } from "./types.js"; -import { addPaginationParams, makeBearerTokenAuthHeader } from "./utils.js"; +import { addLongPollingParam, addPaginationParams, makeBearerTokenAuthHeader } from "./utils.js"; export type TalerCoreBankResultByMethod<prop extends keyof TalerCoreBankHttpClient> = ResultByMethod<TalerCoreBankHttpClient, prop> export type TalerCoreBankErrorsByMethod<prop extends keyof TalerCoreBankHttpClient> = FailCasesByMethod<TalerCoreBankHttpClient, prop> /** - * Protocol version spoken with the bank. + * Protocol version spoken with the core bank. * + * Endpoint must be ordered in the same way that in the docs + * Response code (http and taler) must have the same order that in the docs + * That way is easier to see changes + * * Uses libtool's current:revision:age versioning. */ export class TalerCoreBankHttpClient { @@ -134,8 +139,8 @@ export class TalerCoreBankHttpClient { switch (resp.status) { case HttpStatusCode.Accepted: return opKnownAlternativeFailure(resp, resp.status, codecForChallenge()) case HttpStatusCode.NoContent: return opEmptySuccess() - case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Conflict: { const body = await resp.json() const details = codecForTalerErrorDetail().decode(body) @@ -166,17 +171,17 @@ export class TalerCoreBankHttpClient { switch (resp.status) { case HttpStatusCode.Accepted: return opKnownAlternativeFailure(resp, resp.status, codecForChallenge()) case HttpStatusCode.NoContent: return opEmptySuccess() - case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Conflict: { const body = await resp.json() const details = codecForTalerErrorDetail().decode(body) switch (details.code) { case TalerErrorCode.BANK_NON_ADMIN_PATCH_LEGAL_NAME: return opKnownTalerFailure(details.code, resp); - case TalerErrorCode.BANK_NON_ADMIN_PATCH_DEBT_LIMIT: return opKnownTalerFailure(details.code, resp); case TalerErrorCode.BANK_NON_ADMIN_PATCH_CASHOUT: return opKnownTalerFailure(details.code, resp); - case TalerErrorCode.BANK_NON_ADMIN_PATCH_CONTACT: return opKnownTalerFailure(details.code, resp); + case TalerErrorCode.BANK_NON_ADMIN_PATCH_DEBT_LIMIT: return opKnownTalerFailure(details.code, resp); case TalerErrorCode.BANK_TAN_CHANNEL_NOT_SUPPORTED: return opKnownTalerFailure(details.code, resp); + case TalerErrorCode.BANK_MISSING_TAN_INFO: return opKnownTalerFailure(details.code, resp); default: return opUnknownFailure(resp, body) } } @@ -289,9 +294,10 @@ export class TalerCoreBankHttpClient { * https://docs.taler.net/core/api-corebank.html#get--accounts-$USERNAME-transactions * */ - async getTransactions(auth: UserAndToken, pagination?: PaginationParams) { + async getTransactions(auth: UserAndToken, params?: PaginationParams & LongPollParams) { const url = new URL(`accounts/${auth.username}/transactions`, this.baseUrl); - addPaginationParams(url, pagination) + addPaginationParams(url, params) + addLongPollingParam(url, params) const resp = await this.httpLib.fetch(url.href, { method: "GET", headers: { @@ -342,8 +348,8 @@ export class TalerCoreBankHttpClient { body, }); switch (resp.status) { - case HttpStatusCode.Accepted: return opKnownAlternativeFailure(resp, resp.status, codecForChallenge()) case HttpStatusCode.Ok: return opSuccess(resp, codecForCreateTransactionResponse()) + case HttpStatusCode.Accepted: return opKnownAlternativeFailure(resp, resp.status, codecForChallenge()) case HttpStatusCode.BadRequest: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); @@ -382,62 +388,63 @@ export class TalerCoreBankHttpClient { case HttpStatusCode.Ok: return opSuccess(resp, codecForBankAccountCreateWithdrawalResponse()) case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); + //FIXME: missing in docs case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp); default: return opUnknownFailure(resp, await resp.text()) } } /** - * https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-withdrawals-$WITHDRAWAL_ID-abort + * https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-withdrawals-$WITHDRAWAL_ID-confirm * */ - async abortWithdrawalById(auth: UserAndToken, wid: string) { - const url = new URL(`accounts/${auth.username}/withdrawals/${wid}/abort`, this.baseUrl); + async confirmWithdrawalById(auth: UserAndToken, wid: string, cid?: string) { + const url = new URL(`accounts/${auth.username}/withdrawals/${wid}/confirm`, this.baseUrl); const resp = await this.httpLib.fetch(url.href, { method: "POST", headers: { - Authorization: makeBearerTokenAuthHeader(auth.token) + Authorization: makeBearerTokenAuthHeader(auth.token), + "X-Challenge-Id": cid, }, }); switch (resp.status) { + case HttpStatusCode.Accepted: return opKnownAlternativeFailure(resp, resp.status, codecForChallenge()) case HttpStatusCode.NoContent: return opEmptySuccess() //FIXME: missing in docs case HttpStatusCode.BadRequest: return opKnownHttpFailure(resp.status, resp) case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp) - case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.Conflict: { + const body = await resp.json() + const details = codecForTalerErrorDetail().decode(body) + switch (details.code) { + case TalerErrorCode.BANK_CONFIRM_ABORT_CONFLICT: return opKnownTalerFailure(details.code, resp); + case TalerErrorCode.BANK_CONFIRM_INCOMPLETE: return opKnownTalerFailure(details.code, resp); + case TalerErrorCode.BANK_UNALLOWED_DEBIT: return opKnownTalerFailure(details.code, resp); + default: return opUnknownFailure(resp, body) + } + } default: return opUnknownFailure(resp, await resp.text()) } } /** - * https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-withdrawals-$WITHDRAWAL_ID-confirm + * https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-withdrawals-$WITHDRAWAL_ID-abort * */ - async confirmWithdrawalById(auth: UserAndToken, wid: string, cid?: string) { - const url = new URL(`accounts/${auth.username}/withdrawals/${wid}/confirm`, this.baseUrl); + async abortWithdrawalById(auth: UserAndToken, wid: string) { + const url = new URL(`accounts/${auth.username}/withdrawals/${wid}/abort`, this.baseUrl); const resp = await this.httpLib.fetch(url.href, { method: "POST", headers: { - Authorization: makeBearerTokenAuthHeader(auth.token), - "X-Challenge-Id": cid, + Authorization: makeBearerTokenAuthHeader(auth.token) }, }); switch (resp.status) { - case HttpStatusCode.Accepted: return opKnownAlternativeFailure(resp, resp.status, codecForChallenge()) case HttpStatusCode.NoContent: return opEmptySuccess() //FIXME: missing in docs case HttpStatusCode.BadRequest: return opKnownHttpFailure(resp.status, resp) case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp) - case HttpStatusCode.Conflict: { - const body = await resp.json() - const details = codecForTalerErrorDetail().decode(body) - switch (details.code) { - case TalerErrorCode.BANK_CONFIRM_ABORT_CONFLICT: return opKnownTalerFailure(details.code, resp); - case TalerErrorCode.BANK_CONFIRM_INCOMPLETE: return opKnownTalerFailure(details.code, resp); - case TalerErrorCode.BANK_UNALLOWED_DEBIT: return opKnownTalerFailure(details.code, resp); - default: return opUnknownFailure(resp, body) - } - } + case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); default: return opUnknownFailure(resp, await resp.text()) } } @@ -446,14 +453,13 @@ export class TalerCoreBankHttpClient { * https://docs.taler.net/core/api-corebank.html#get--withdrawals-$WITHDRAWAL_ID * */ - async getWithdrawalById(wid: string, wait?: { + async getWithdrawalById(wid: string, params?: { old_state?: WithdrawalOperationStatus, - timeoutMs: number - }) { + } & LongPollParams) { const url = new URL(`withdrawals/${wid}`, this.baseUrl); - if (wait) { - url.searchParams.set("long_poll_ms", String(wait.timeoutMs)) - url.searchParams.set("old_state", !wait.old_state ? "pending" : wait.old_state) + addLongPollingParam(url, params) + if (params) { + url.searchParams.set("old_state", !params.old_state ? "pending" : params.old_state) } const resp = await this.httpLib.fetch(url.href, { method: "GET", @@ -486,8 +492,8 @@ export class TalerCoreBankHttpClient { body, }); switch (resp.status) { - case HttpStatusCode.Accepted: return opKnownAlternativeFailure(resp, resp.status, codecForChallenge()) case HttpStatusCode.Ok: return opSuccess(resp, codecForCashoutPending()) + case HttpStatusCode.Accepted: return opKnownAlternativeFailure(resp, resp.status, codecForChallenge()) case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp) case HttpStatusCode.Conflict: { const body = await resp.json() @@ -514,61 +520,6 @@ export class TalerCoreBankHttpClient { } /** - * https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-cashouts-$CASHOUT_ID-abort - * @deprecated since 4 - */ - async abortCashoutById(auth: UserAndToken, cid: number) { - const url = new URL(`accounts/${auth.username}/cashouts/${cid}/abort`, this.baseUrl); - const resp = await this.httpLib.fetch(url.href, { - method: "POST", - headers: { - Authorization: makeBearerTokenAuthHeader(auth.token) - }, - }); - switch (resp.status) { - case HttpStatusCode.NoContent: return opEmptySuccess() - case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); - case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); - case HttpStatusCode.NotImplemented: return opKnownHttpFailure(resp.status, resp); - default: return opUnknownFailure(resp, await resp.text()) - } - } - - /** - * https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-cashouts-$CASHOUT_ID-confirm - * @deprecated since 4 - */ - async confirmCashoutById(auth: UserAndToken, cid: number, body: TalerCorebankApi.CashoutConfirmRequest) { - const url = new URL(`accounts/${auth.username}/cashouts/${cid}/confirm`, this.baseUrl); - const resp = await this.httpLib.fetch(url.href, { - method: "POST", - headers: { - Authorization: makeBearerTokenAuthHeader(auth.token) - }, - body, - }); - switch (resp.status) { - case HttpStatusCode.NoContent: return opEmptySuccess() - case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); - case HttpStatusCode.Conflict: { - const body = await resp.json() - const details = codecForTalerErrorDetail().decode(body) - switch (details.code) { - case TalerErrorCode.BANK_CONFIRM_ABORT_CONFLICT: return opKnownTalerFailure(details.code, resp); - case TalerErrorCode.BANK_CONFIRM_INCOMPLETE: return opKnownTalerFailure(details.code, resp); - case TalerErrorCode.BANK_UNALLOWED_DEBIT: return opKnownTalerFailure(details.code, resp); - case TalerErrorCode.BANK_BAD_CONVERSION: return opKnownTalerFailure(details.code, resp); - case TalerErrorCode.BANK_TAN_CHALLENGE_FAILED: return opKnownTalerFailure(details.code, resp); - default: return opUnknownFailure(resp, body) - } - } - case HttpStatusCode.TooManyRequests: return opKnownHttpFailure(resp.status, resp); - case HttpStatusCode.NotImplemented: return opKnownHttpFailure(resp.status, resp); - default: return opUnknownFailure(resp, await resp.text()) - } - } - - /** * https://docs.taler.net/core/api-corebank.html#get--accounts-$USERNAME-cashouts-$CASHOUT_ID * */ @@ -604,7 +555,6 @@ export class TalerCoreBankHttpClient { switch (resp.status) { case HttpStatusCode.Ok: return opSuccess(resp, codecForCashouts()) case HttpStatusCode.NoContent: return opFixedSuccess({ cashouts: [] }); - case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp);; case HttpStatusCode.NotImplemented: return opKnownHttpFailure(resp.status, resp); default: return opUnknownFailure(resp, await resp.text()) } @@ -632,41 +582,13 @@ export class TalerCoreBankHttpClient { } // - // MONITOR + // 2FA // /** - * https://docs.taler.net/core/api-corebank.html#get--monitor + * https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-challenge-$CHALLENGE_ID * */ - async getMonitor(auth: AccessToken, params: { timeframe?: TalerCorebankApi.MonitorTimeframeParam, which?: number } = {}) { - const url = new URL(`monitor`, this.baseUrl); - if (params.timeframe) { - url.searchParams.set("timeframe", TalerCorebankApi.MonitorTimeframeParam[params.timeframe]) - } - if (params.which) { - url.searchParams.set("which", String(params.which)) - } - const resp = await this.httpLib.fetch(url.href, { - method: "GET", - headers: { - Authorization: makeBearerTokenAuthHeader(auth) - }, - }); - switch (resp.status) { - case HttpStatusCode.Ok: return opSuccess(resp, codecForMonitorResponse()) - case HttpStatusCode.BadRequest: return opKnownHttpFailure(resp.status, resp); - case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp); - //FIXME remove when server is updated - //FIXME: should be 404 ? - case HttpStatusCode.ServiceUnavailable: return opKnownHttpFailure(resp.status, resp); - default: return opUnknownFailure(resp, await resp.text()) - } - } - - // - // 2FA - // async sendChallenge(auth: UserAndToken, cid: string) { const url = new URL(`accounts/${auth.username}/challenge/${cid}`, this.baseUrl); const resp = await this.httpLib.fetch(url.href, { @@ -691,6 +613,10 @@ export class TalerCoreBankHttpClient { } } + /** + * https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-challenge-$CHALLENGE_ID-confirm + * + */ async confirmChallenge(auth: UserAndToken, cid: string, body: TalerCorebankApi.ChallengeSolve) { const url = new URL(`accounts/${auth.username}/challenge/${cid}/confirm`, this.baseUrl); const resp = await this.httpLib.fetch(url.href, { @@ -718,6 +644,36 @@ export class TalerCoreBankHttpClient { } } + // + // MONITOR + // + + /** + * https://docs.taler.net/core/api-corebank.html#get--monitor + * + */ + async getMonitor(auth: AccessToken, params: { timeframe?: TalerCorebankApi.MonitorTimeframeParam, which?: number } = {}) { + const url = new URL(`monitor`, this.baseUrl); + if (params.timeframe) { + url.searchParams.set("timeframe", TalerCorebankApi.MonitorTimeframeParam[params.timeframe]) + } + if (params.which) { + url.searchParams.set("which", String(params.which)) + } + const resp = await this.httpLib.fetch(url.href, { + method: "GET", + headers: { + Authorization: makeBearerTokenAuthHeader(auth) + }, + }); + switch (resp.status) { + case HttpStatusCode.Ok: return opSuccess(resp, codecForMonitorResponse()) + case HttpStatusCode.BadRequest: return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp); + default: return opUnknownFailure(resp, await resp.text()) + } + } + // // Others API |