taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit e628c733ee80768f3aae623be9921de4550f11a1
parent a6bfddd10e1b1a8505a9e2b8ee46e1b7e194ded3
Author: Sebastian <sebasjm@taler-systems.com>
Date:   Thu, 15 Jan 2026 11:57:39 -0300

fix handling no bank account

merchant now returns 404 and code 2500

Diffstat:
Mpackages/merchant-backoffice-ui/src/paths/instance/orders/create/CreatePage.tsx | 125++++++++++++++++++++++++++++++++++++++++---------------------------------------
Mpackages/merchant-backoffice-ui/src/paths/instance/templates/use/UsePage.tsx | 5+++--
Mpackages/taler-util/src/http-client/merchant.ts | 11+++++++++--
3 files changed, 75 insertions(+), 66 deletions(-)

diff --git a/packages/merchant-backoffice-ui/src/paths/instance/orders/create/CreatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/orders/create/CreatePage.tsx @@ -26,6 +26,7 @@ import { Duration, HttpStatusCode, OrderVersion, + TalerErrorCode, TalerMerchantApi, TalerProtocolDuration, assertUnreachable, @@ -195,9 +196,9 @@ export function CreatePage({ : !value.payments?.refund_delay ? i18n.str`Must have a refund deadline` : Duration.cmp( - value.payments.refund_delay, - value.payments.auto_refund_delay, - ) == -1 + value.payments.refund_delay, + value.payments.auto_refund_delay, + ) == -1 ? i18n.str`Auto refund can't be after refund deadline` : undefined, }), @@ -209,15 +210,15 @@ export function CreatePage({ : undefined, fulfillment_message: !!value.shipping?.fulfillment_message && - !!value.shipping?.fulfillment_url + !!value.shipping?.fulfillment_url ? i18n.str`Either fulfillment url or fulfillment message must be specified.` : undefined, fulfillment_url: !!value.shipping?.fulfillment_message && - !!value.shipping?.fulfillment_url + !!value.shipping?.fulfillment_url ? i18n.str`Either fulfillment url or fulfillment message must be specified.` : !!value.shipping?.fulfillment_url && - isInvalidUrl(value.shipping.fulfillment_url) + isInvalidUrl(value.shipping.fulfillment_url) ? i18n.str`is not a valid URL` : undefined, }), @@ -234,86 +235,86 @@ export function CreatePage({ const refundDelay = !value.payments?.refund_delay ? Duration.getZero() : Duration.add( - payDelay, - !value.payments?.refund_delay - ? Duration.getZero() - : value.payments.refund_delay, - ); + payDelay, + !value.payments?.refund_delay + ? Duration.getZero() + : value.payments.refund_delay, + ); const autoRefundDelay = !value.payments?.auto_refund_delay ? Duration.getZero() : Duration.add( - payDelay, - !value.payments?.auto_refund_delay - ? Duration.getZero() - : value.payments.auto_refund_delay, - ); + payDelay, + !value.payments?.auto_refund_delay + ? Duration.getZero() + : value.payments.auto_refund_delay, + ); const wireDelay = !value.payments?.wire_transfer_delay ? Duration.getZero() : Duration.add( - refundDelay, - !value.payments?.wire_transfer_delay - ? Duration.getZero() - : value.payments.wire_transfer_delay, - ); + refundDelay, + !value.payments?.wire_transfer_delay + ? Duration.getZero() + : value.payments.wire_transfer_delay, + ); const pay_deadline = !value.payments?.pay_delay ? undefined : AbsoluteTime.toProtocolTimestamp( - AbsoluteTime.addDuration(AbsoluteTime.now(), payDelay), - ); + AbsoluteTime.addDuration(AbsoluteTime.now(), payDelay), + ); const refund_deadline = !value.payments?.refund_delay ? undefined : AbsoluteTime.toProtocolTimestamp( - AbsoluteTime.addDuration(AbsoluteTime.now(), refundDelay), - ); + AbsoluteTime.addDuration(AbsoluteTime.now(), refundDelay), + ); const wire_transfer_deadline = !value.payments || !value.payments.wire_transfer_delay ? undefined : AbsoluteTime.toProtocolTimestamp( - AbsoluteTime.addDuration(AbsoluteTime.now(), wireDelay), - ); + AbsoluteTime.addDuration(AbsoluteTime.now(), wireDelay), + ); const request: undefined | TalerMerchantApi.PostOrderRequest = !value.payments || !value.shipping || !price || !summary ? undefined : { - order: { - version: OrderVersion.V0, - amount: price, - // version: OrderVersion.V1, - // choices: [{ - // amount: price, - // max_fee: value.payments.max_fee as AmountString, - // }], - summary: summary, - products: productList, - extra: undefinedIfEmpty(value.extra), - pay_deadline, - refund_deadline, - wire_transfer_deadline, - auto_refund: value.payments.auto_refund_delay - ? Duration.toTalerProtocolDuration( - value.payments.auto_refund_delay, - ) - : undefined, - delivery_date: value.shipping.delivery_date - ? { t_s: value.shipping.delivery_date.getTime() / 1000 } - : undefined, - delivery_location: value.shipping.delivery_location, - fulfillment_url: value.shipping.fulfillment_url, - fulfillment_message: value.shipping.fulfillment_message, - minimum_age: value.payments.minimum_age, - }, - inventory_products: inventoryList.map((p) => ({ - product_id: p.product.id, - quantity: p.quantity, - })), - create_token: value.payments.createToken, - }; + order: { + version: OrderVersion.V0, + amount: price, + // version: OrderVersion.V1, + // choices: [{ + // amount: price, + // max_fee: value.payments.max_fee as AmountString, + // }], + summary: summary, + products: productList, + extra: undefinedIfEmpty(value.extra), + pay_deadline, + refund_deadline, + wire_transfer_deadline, + auto_refund: value.payments.auto_refund_delay + ? Duration.toTalerProtocolDuration( + value.payments.auto_refund_delay, + ) + : undefined, + delivery_date: value.shipping.delivery_date + ? { t_s: value.shipping.delivery_date.getTime() / 1000 } + : undefined, + delivery_location: value.shipping.delivery_location, + fulfillment_url: value.shipping.fulfillment_url, + fulfillment_message: value.shipping.fulfillment_message, + minimum_age: value.payments.minimum_age, + }, + inventory_products: inventoryList.map((p) => ({ + product_id: p.product.id, + quantity: p.quantity, + })), + create_token: value.payments.createToken, + }; const [notification, safeFunctionHandler] = useLocalNotificationBetter(); const create = safeFunctionHandler( @@ -327,8 +328,8 @@ export function CreatePage({ switch (fail.case) { case HttpStatusCode.Unauthorized: return i18n.str`Unauthorized`; - case HttpStatusCode.NotFound: - return i18n.str`Not found`; + case TalerErrorCode.MERCHANT_PRIVATE_POST_ORDERS_INSTANCE_CONFIGURATION_LACKS_WIRE: + return i18n.str`No active bank accounts configured. At least one bank account must be available to create new orders`; case HttpStatusCode.Conflict: return i18n.str`Conflict`; case HttpStatusCode.Gone: diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/use/UsePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/use/UsePage.tsx @@ -23,6 +23,7 @@ import { AmountString, assertUnreachable, HttpStatusCode, + TalerErrorCode, TalerMerchantApi, UsingTemplateDetails, } from "@gnu-taler/taler-util"; @@ -100,8 +101,8 @@ export function UsePage({ switch (fail.case) { case HttpStatusCode.Unauthorized: return i18n.str`Unauthorized.`; - case HttpStatusCode.NotFound: - return i18n.str`Not found.`; + case TalerErrorCode.MERCHANT_PRIVATE_POST_ORDERS_INSTANCE_CONFIGURATION_LACKS_WIRE: + return i18n.str`No active bank accounts configured. At least one bank account must be available to create new orders`; case HttpStatusCode.Conflict: return i18n.str`Conflict.`; case HttpStatusCode.Gone: diff --git a/packages/taler-util/src/http-client/merchant.ts b/packages/taler-util/src/http-client/merchant.ts @@ -1473,8 +1473,15 @@ export class TalerMerchantInstanceHttpClient { ); return opSuccessFromHttp(resp, codecForPostOrderResponse()); } - case HttpStatusCode.NotFound: - return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.NotFound: { + const details = await readTalerErrorResponse(resp); + switch (details.code) { + case TalerErrorCode.MERCHANT_PRIVATE_POST_ORDERS_INSTANCE_CONFIGURATION_LACKS_WIRE: + return opKnownTalerFailure(details.code, details); + default: + return opUnknownHttpFailure(resp, details); + } + } case HttpStatusCode.Unauthorized: // FIXME: missing in docs return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.UnavailableForLegalReasons: