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:
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: