@bacano/sdk 1.2.2 → 1.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTENT_TYPE_MANAGEMENT.md +42 -2
- package/FLOWS.md +114 -0
- package/README.md +89 -18
- package/STOREFRONT_FORMS.md +50 -0
- package/STOREFRONT_PAYMENTS.md +231 -0
- package/client.d.ts +9 -1
- package/content-management-types.d.ts +44 -1
- package/content-management.cjs +26 -0
- package/content-management.js +26 -0
- package/flows.d.ts +109 -0
- package/form-conditions.d.ts +6 -0
- package/index.cjs +142 -3
- package/index.d.ts +3 -0
- package/index.js +142 -3
- package/modules/checkout.d.ts +1 -1
- package/modules/content.d.ts +1 -0
- package/package.json +1 -1
- package/react/flow-form.d.ts +9 -0
- package/react/form-scale-control.d.ts +9 -0
- package/react/forms.cjs +260 -65
- package/react/forms.d.ts +1 -0
- package/react/forms.js +254 -59
- package/react.cjs +106 -2
- package/react.js +106 -2
- package/skills/bacano-web/SKILL.md +2 -0
- package/skills/bacano-web/references/storefront.md +2 -0
- package/transport/documents.d.ts +2 -1
- package/types.d.ts +14 -1
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
`@bacano/sdk/content-management` permite que una herramienta administrativa o
|
|
4
4
|
un agente autorizado consulte y mantenga **tipos, componentes, grupos, listas
|
|
5
|
-
de opciones, entradas
|
|
5
|
+
de opciones, entradas, imágenes y bloques adicionales de productos** de Bacano Content, y **formularios web**.
|
|
6
6
|
Cada capacidad requiere
|
|
7
|
-
un permiso explícito. El acceso no autoriza productos, ventas, clientes,
|
|
7
|
+
un permiso explícito. El acceso a bloques no autoriza modificar productos, ventas, clientes,
|
|
8
8
|
configuración general, GraphQL, SQL ni acceso directo a Storage.
|
|
9
9
|
|
|
10
10
|
Este contrato es independiente del cliente público del storefront. Debe usarse
|
|
@@ -38,6 +38,10 @@ Scopes disponibles:
|
|
|
38
38
|
- `forms:publish`: publicar, pausar, reactivar o archivar formularios. Requiere
|
|
39
39
|
`forms:manage`. También se exige para cambiar notificaciones de formularios
|
|
40
40
|
que ya fueron publicados, porque afectan envíos en curso.
|
|
41
|
+
- `product_content:manage`: consultar, crear, actualizar, ordenar y retirar
|
|
42
|
+
bloques adicionales exclusivamente en los productos cuyos IDs se incluyeron
|
|
43
|
+
al generar el acceso. Requiere que el usuario mantenga `products.view` y
|
|
44
|
+
`websites.manage`; no modifica precio, inventario ni variantes.
|
|
41
45
|
|
|
42
46
|
Los permisos de Content no conceden acceso a formularios ni viceversa. Los
|
|
43
47
|
tokens existentes no se amplían; solicita uno nuevo con el alcance necesario.
|
|
@@ -89,6 +93,42 @@ El cliente ofrece:
|
|
|
89
93
|
`applyOptionListLifecycle(idOrKey, operation)`.
|
|
90
94
|
- `listMedia(filters)` y `uploadImage(input)` para reutilizar o cargar imágenes
|
|
91
95
|
cuando el acceso incluya `content_media:upload`.
|
|
96
|
+
- `listProductBlocks(productId, filters)`, `createProductBlock(productId, input)`,
|
|
97
|
+
`updateProductBlock(productId, blockId, input)`,
|
|
98
|
+
`reorderProductBlocks(productId, input)` y
|
|
99
|
+
`retireProductBlock(productId, blockId, expectedUpdatedAt)`.
|
|
100
|
+
|
|
101
|
+
## Bloques adicionales de un producto
|
|
102
|
+
|
|
103
|
+
Al generar un acceso con `product_content:manage`, indica de 1 a 50 IDs de
|
|
104
|
+
productos activos de la empresa. El token no habilita otros productos aunque
|
|
105
|
+
el usuario tenga acceso a ellos en el backoffice. Usa un tipo de contenido
|
|
106
|
+
activo de uso `product_additional`; los campos y las referencias de imágenes
|
|
107
|
+
se validan con las mismas reglas de guardado del administrador.
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
const [block] = await content.listProductBlocks(productId, {
|
|
111
|
+
contentType: "landing_producto",
|
|
112
|
+
locale: "es-CO",
|
|
113
|
+
});
|
|
114
|
+
await content.updateProductBlock(productId, block.id, {
|
|
115
|
+
content: { ...block.content, titulo: "Nuevo título" },
|
|
116
|
+
sortOrder: block.sortOrder,
|
|
117
|
+
expectedUpdatedAt: block.updatedAt,
|
|
118
|
+
});
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
`createProductBlock` requiere `contentType`, `locale`, `content` y `sortOrder`.
|
|
122
|
+
Para ordenar, envía **todos** los bloques del idioma en el orden deseado,
|
|
123
|
+
incluyendo el `id` y `expectedUpdatedAt` de cada uno. El servidor aplica el
|
|
124
|
+
cambio atómicamente; una versión obsoleta devuelve conflicto HTTP 409. Vuelve
|
|
125
|
+
a listar y pide revisar el conflicto antes de repetir. Retirar un bloque quita
|
|
126
|
+
su asociación con el producto, sin borrar el tipo, la entrada independiente ni
|
|
127
|
+
los archivos de imagen. Para builds estáticos, el cliente público ofrece
|
|
128
|
+
`client.content.getForProducts(productIds)` y devuelve un registro indexado por
|
|
129
|
+
ID normalizado en minúsculas, incluyendo listas vacías para productos sin
|
|
130
|
+
bloques visibles. Agrupa hasta 50 productos por solicitud; no revela bloques
|
|
131
|
+
de productos no publicados en el sitio. `getForProduct` sigue disponible.
|
|
92
132
|
|
|
93
133
|
## Idioma, nombres y keys
|
|
94
134
|
|
package/FLOWS.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Flows: participant SDK
|
|
2
|
+
|
|
3
|
+
This delivery provides a local integration surface. Production identity and access-management adapters are intentionally not enabled yet. The local gateway returns 404 outside development even if its demo flag is enabled. Do not deploy demo credentials or replace Clerk with this adapter.
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import { createFlowsClient } from "@bacano/sdk";
|
|
7
|
+
|
|
8
|
+
let token: string | null = null;
|
|
9
|
+
const flows = createFlowsClient({
|
|
10
|
+
apiUrl: "http://localhost:3001",
|
|
11
|
+
getAccessToken: () => token,
|
|
12
|
+
});
|
|
13
|
+
const session = await flows.localDemoLogin("ana@example.test", "Academy123!");
|
|
14
|
+
token = session.token;
|
|
15
|
+
const cases = await flows.listCases();
|
|
16
|
+
const journey = await flows.getJourney(cases[0].id);
|
|
17
|
+
// Render only available steps and the capabilities returned by the server.
|
|
18
|
+
await flows.logout();
|
|
19
|
+
token = null;
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Existing Bacano clients expose the same methods on `client.flows`. No direct Hasura access or administrative credential belongs in the website. Bearer identity is resolved by the gateway; request bodies cannot choose a participant.
|
|
23
|
+
|
|
24
|
+
## Surface
|
|
25
|
+
|
|
26
|
+
- `listCases()`, `getJourney(caseId)`: explicitly granted cases and filtered state.
|
|
27
|
+
- `getContent(caseId, stepId)`: ordered published Content resources compatible with Flows. Private fields are removed by the backend.
|
|
28
|
+
- `getFile(caseId, stepId, fileId)`: authenticated Blob, only for files referenced in accessible content and belonging to the company. Revoke object URLs on unmount/logout.
|
|
29
|
+
- `getForm(caseId, stepId)`: current published form, version and definition hash.
|
|
30
|
+
- `getResponse(caseId, stepId)`: own response or explicitly shared evaluation; historical labels/answers, attempt and submission time. Never internal notes.
|
|
31
|
+
- `act(caseId, command)`: `complete_content`, `complete_task`, `submit_form`. No review/approval/move operation for the participant.
|
|
32
|
+
|
|
33
|
+
Every command supplies `stepId`, `revision` (case), `flowRevision`, and `idempotencyKey`. Keep the **same complete envelope and key** on network retries. New input requires a new key. On revision conflict refresh the journey and ask the person to review before resending. The server rechecks access, assignment, sequence and state; rendered buttons are not authorization.
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
import { BacanoFlowForm } from "@bacano/sdk/react/forms";
|
|
37
|
+
|
|
38
|
+
<BacanoFlowForm
|
|
39
|
+
key={`${caseId}:${stepId}:${publishedForm.correction?.attempt ?? 0}`}
|
|
40
|
+
form={publishedForm}
|
|
41
|
+
onRefresh={reloadPublishedForm}
|
|
42
|
+
onSubmit={(values, form) => submitStep({
|
|
43
|
+
operation: "submit_form",
|
|
44
|
+
submission: { values, formVersion: form.version, definitionHash: form.definitionHash },
|
|
45
|
+
})}
|
|
46
|
+
/>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The component reuses existing Forms controls but never posts to the website-entry endpoint. A publication conflict leaves entered answers in place; refreshing the definition does not clear them. It does not persist sensitive drafts in localStorage. Clearing the authenticated view on logout removes its state. Applications must provide error/loading states and retain an idempotency envelope for retries.
|
|
50
|
+
|
|
51
|
+
### Corrections
|
|
52
|
+
|
|
53
|
+
After an operator requests changes, `getForm` may include `initialValues` and
|
|
54
|
+
`correction: { attempt, formChanged }`. These are the authenticated participant's
|
|
55
|
+
own previous answers to this case/step/form, filtered against the currently
|
|
56
|
+
published questions and selected conditional branches. They never contain internal
|
|
57
|
+
evaluations or another participant's answers. Numbers/scales use editable strings;
|
|
58
|
+
checkboxes preserve booleans. Removed options and fields are omitted.
|
|
59
|
+
|
|
60
|
+
Initialize a custom renderer from `initialValues ?? {}` once per case/step/attempt.
|
|
61
|
+
Do not overwrite unsent edits during refresh or use case revision as a component
|
|
62
|
+
key. Show a review warning when `formChanged` is true. Submitting creates a new
|
|
63
|
+
immutable response; the earlier attempt remains in the operator history.
|
|
64
|
+
Requesting changes requires participant instructions, not the configured evaluation
|
|
65
|
+
form. Approving still requires that evaluation when configured.
|
|
66
|
+
|
|
67
|
+
## Stage presentation
|
|
68
|
+
|
|
69
|
+
Each journey stage exposes `presentation`: `step_by_step` (default, including older definitions) or `single_view`. Treat an absent value from an older gateway as `step_by_step`. This preference is independent of sequential/free execution order and manual/automatic advancement.
|
|
70
|
+
|
|
71
|
+
For `single_view`, render the stage's steps together in their existing order, with stable component keys based on case and step IDs. Each activity saves independently; do not introduce a combined submit or automatically complete content when a form is sent.
|
|
72
|
+
|
|
73
|
+
- Unavailable steps may show a locked heading, but must not load their content, form or files.
|
|
74
|
+
- Internal steps may show their public status, never private instructions, evaluations or review controls. Respect `canReadResponse` for explicitly shared responses.
|
|
75
|
+
- Operator-assigned tasks are omitted entirely from the participant journey,
|
|
76
|
+
including their titles. They remain operable in Bacano and still govern
|
|
77
|
+
sequencing/advancement. A stage with only internal tasks may therefore have
|
|
78
|
+
no visible steps: show a waiting state, never advance it in the browser.
|
|
79
|
+
Explicitly participant-assigned tasks remain available to that participant.
|
|
80
|
+
- Refresh the journey after every action. Use the updated revisions for new commands. Concurrent actions may conflict; preserve unsent form values and let the participant retry after refreshing.
|
|
81
|
+
- Keep sibling forms mounted when a step is completed so their local inputs survive. Do not use the case revision as a React key.
|
|
82
|
+
- In single-view mode, keep the current page after saving; the participant can navigate to the next stage using the journey navigation.
|
|
83
|
+
|
|
84
|
+
This is configuration delivered by the SDK, not an automatic layout component. Consuming applications implement the layout; the local Academy example implements both modes.
|
|
85
|
+
|
|
86
|
+
## Local identity and access
|
|
87
|
+
|
|
88
|
+
- Local demo emails: `ana@example.test`, `luis@example.test`; password `Academy123!`.
|
|
89
|
+
- Enable only the local backend override (`docker-compose.flows-demo.yml`) and an explicit website UUID. Origins must be localhost/loopback.
|
|
90
|
+
- The seed explicitly creates two client/contact fixtures, two separate real cases and grant rows. Runtime access is **not** inferred from email or contact.
|
|
91
|
+
- Opaque local sessions expire after one hour; API restart or logout invalidates them. Session loss never deletes case data.
|
|
92
|
+
- Revoking a `flow_case_access` row blocks subsequent reads and commands without deleting audit history.
|
|
93
|
+
- A manual-advance stage remains there after its required form is submitted. An operator must move it; automatic stages use the existing domain rules. Empty stages do not advance spontaneously.
|
|
94
|
+
|
|
95
|
+
## Pending before production
|
|
96
|
+
|
|
97
|
+
Verify Clerk through the existing website identity adapter; add operator grant/revoke actions guarded by `flows.share`; validate isolation across real sites/tenants and production accounts; replace local fixtures and test deployment. Do not enable production by weakening the development/origin checks.
|
|
98
|
+
|
|
99
|
+
## Contenido con devolución relacionada
|
|
100
|
+
|
|
101
|
+
Un paso `content` puede exponer `canReadResponse: true`. En ese caso consulta
|
|
102
|
+
`getContent(caseId, step.id)` y `getResponse(caseId, step.id)` para presentar el
|
|
103
|
+
material de apoyo junto a la devolución original del mismo caso. No uses IDs de
|
|
104
|
+
respuestas ni de otros pasos para saltarte la disponibilidad del recorrido.
|
|
105
|
+
|
|
106
|
+
Si `canComplete` es verdadero y el contenido no es de consulta, ofrece continuar
|
|
107
|
+
mediante `act(..., { operation: "complete_content", ... })` con las revisiones e
|
|
108
|
+
idempotency key vigentes. La aprobación interna entrega el resultado; esta acción
|
|
109
|
+
registra por separado la confirmación del participante. No marques el paso como
|
|
110
|
+
completado por abrirlo. Si la respuesta no pudo cargarse, no ofrezcas confirmarla.
|
|
111
|
+
|
|
112
|
+
Tras cada acción vuelve a consultar el recorrido y presenta su etapa actual.
|
|
113
|
+
Durante una espera interna puedes consultar periódicamente el estado; conserva
|
|
114
|
+
los formularios con valores sin enviar que sigan en la misma etapa agrupada.
|
package/README.md
CHANGED
|
@@ -7,6 +7,10 @@ Buyer credentials are owned by each storefront's Clerk application. Read
|
|
|
7
7
|
sign-in, customer profiles, authenticated checkout, or order history. The guide
|
|
8
8
|
ships inside the npm package.
|
|
9
9
|
|
|
10
|
+
For participant journeys, forms and activities, see [FLOWS.md](./FLOWS.md).
|
|
11
|
+
Flows currently includes an explicitly gated local identity adapter; production
|
|
12
|
+
participant authentication and grant management are not enabled by this sample.
|
|
13
|
+
|
|
10
14
|
## Installation
|
|
11
15
|
|
|
12
16
|
```bash
|
|
@@ -107,6 +111,12 @@ when instrumenting analytics, advertising signals, contact actions, ecommerce
|
|
|
107
111
|
events, attribution, or preview behavior. It is the canonical implementation
|
|
108
112
|
contract for storefront agents and ships inside the npm package.
|
|
109
113
|
|
|
114
|
+
Every storefront that accepts payments must follow
|
|
115
|
+
[`STOREFRONT_PAYMENTS.md`](./STOREFRONT_PAYMENTS.md). It defines the SDK flow,
|
|
116
|
+
provider boundaries, Mercado Pago Orders setup and payload invariants, safe
|
|
117
|
+
retry behavior, diagnostics and the minimum sandbox evidence required before
|
|
118
|
+
production.
|
|
119
|
+
|
|
110
120
|
Commercial forms and newsletter subscriptions must follow
|
|
111
121
|
[`STOREFRONT_LEADS.md`](./STOREFRONT_LEADS.md). Storefronts own the form UI;
|
|
112
122
|
Bacano owns consent evidence, identity resolution, attribution and idempotent
|
|
@@ -639,9 +649,16 @@ ahora" and "Pagar al recoger", while `SHIPPING` may return "Pagar ahora" and
|
|
|
639
649
|
"Pagar contraentrega".
|
|
640
650
|
|
|
641
651
|
Only payment methods marked as **Disponible para web** in Bacano and enabled in
|
|
642
|
-
the website payment settings are returned. Gateway methods such as Wompi
|
|
643
|
-
|
|
644
|
-
never leave
|
|
652
|
+
the website payment settings are returned. Gateway methods such as Wompi,
|
|
653
|
+
Mercado Pago, Openpay and Addi expose `gatewayCode`,
|
|
654
|
+
`requiresPaymentSession` and public configuration only; secrets never leave
|
|
655
|
+
Bacano.
|
|
656
|
+
|
|
657
|
+
Openpay uses its hosted Webcheckout. The storefront does not render Openpay.js,
|
|
658
|
+
does not request card/PSE data and does not send a provider transaction ID when
|
|
659
|
+
reconciling the return. Open the Bacano `redirectUrl` immediately and let the
|
|
660
|
+
backend verify the charge. See [STOREFRONT_PAYMENTS.md](./STOREFRONT_PAYMENTS.md)
|
|
661
|
+
for the provider-specific contract and retry rules.
|
|
645
662
|
|
|
646
663
|
Each payment option also exposes `initialPaymentPolicy` (`none`, `optional` or
|
|
647
664
|
`required`), `requiresInitialPayment`, `minInitialAmount` and
|
|
@@ -657,6 +674,60 @@ initialPayment: {
|
|
|
657
674
|
The API enforces the policy, minimum and order total. Do not infer deposits from
|
|
658
675
|
labels or delivery mode.
|
|
659
676
|
|
|
677
|
+
#### Addi: conditional buyer identification
|
|
678
|
+
|
|
679
|
+
The Addi backend adapter is implemented on the integration branch and internally
|
|
680
|
+
tested. It still requires migration, merchant configuration and sandbox validation
|
|
681
|
+
before use. Render only methods returned by Bacano, never invent an Addi option:
|
|
682
|
+
|
|
683
|
+
- When the selected method has `gatewayCode === "ADDI"`, show the identification
|
|
684
|
+
fields immediately below that payment method, before submitting the order.
|
|
685
|
+
- Request **Cédula de ciudadanía** only if a compatible document is missing.
|
|
686
|
+
Reuse an existing CC without asking the buyer to enter it twice; allow correction.
|
|
687
|
+
- Addi only accepts CC in this integration. Show the document type as the fixed
|
|
688
|
+
label **Cédula de ciudadanía (CC)**, not a selector offering unsupported types.
|
|
689
|
+
The editable field is **Número de cédula**; no document photo is requested here.
|
|
690
|
+
- Submit identification through the existing `contact.documentType` and
|
|
691
|
+
`contact.documentNumber` fields. Use Bacano's document-type identifiers from
|
|
692
|
+
`customerIdentification`; the backend adapter must map the CC identifier to
|
|
693
|
+
Addi's `idType: "CC"`. Do not assume the two systems use identical codes.
|
|
694
|
+
- Switching away from Addi removes its extra identification requirement and
|
|
695
|
+
hides fields added only for Addi. Keep any identification fields required by
|
|
696
|
+
the website's own `customerIdentification` policy.
|
|
697
|
+
- Validate missing/incompatible identification before proceeding, with an
|
|
698
|
+
inline message explaining that Addi requires a CC. Backend validation must
|
|
699
|
+
enforce the same rule; hiding a field is not a security boundary.
|
|
700
|
+
|
|
701
|
+
Suggested helper text: “Para continuar con Addi, necesitamos tu número de
|
|
702
|
+
cédula. Completarás el proceso de financiación en Addi.”
|
|
703
|
+
|
|
704
|
+
This condition concerns identification only; the integration must also validate
|
|
705
|
+
the other buyer data required by Addi. Credit evaluation and financing remain
|
|
706
|
+
in Addi's hosted checkout, not in a custom storefront credit form.
|
|
707
|
+
For Addi, also provide `contact.firstName`, `lastName`, `email`, a Colombian
|
|
708
|
+
`cellphone`, and residence in `contact.address.line1` and
|
|
709
|
+
`contact.address.municipalityName`. Ask explicitly before reusing a delivery
|
|
710
|
+
address as residence. These fields already exist in the SDK contact contract.
|
|
711
|
+
This first adapter supports complete product-order payments in COP, not deposits
|
|
712
|
+
or service orders. Errors must remain visible; never mark a payment approved from
|
|
713
|
+
redirect parameters. Use the backend's order status.
|
|
714
|
+
See the [official Addi API](https://api-docs.addi-staging.com/integration/).
|
|
715
|
+
|
|
716
|
+
#### Payment-method surcharge (planned; not yet available)
|
|
717
|
+
|
|
718
|
+
The planned company payment-method setting is **Recargo al comprador (%)**,
|
|
719
|
+
defaulting to **0 %**, shared by web and point of sale. This is a merchant
|
|
720
|
+
surcharge, not the provider's financing interest or settlement commission.
|
|
721
|
+
The agreed basis is products after discounts, excluding shipping.
|
|
722
|
+
Provider/merchant contractual eligibility and the calculation/tax rules must be
|
|
723
|
+
confirmed before enabling it.
|
|
724
|
+
|
|
725
|
+
Once supported, storefronts must show the backend-calculated surcharge and final
|
|
726
|
+
total when a method is selected, before the buyer confirms. Switching methods
|
|
727
|
+
must remove/recalculate it; 0 % adds no charge. Do not calculate a surcharge
|
|
728
|
+
locally or add it directly to the gateway amount. There are no surcharge SDK
|
|
729
|
+
fields or operations available yet; the response contract remains to be defined.
|
|
730
|
+
|
|
660
731
|
```typescript
|
|
661
732
|
const payNow = paymentOptions.find((option) => option.mode === "pay_now");
|
|
662
733
|
|
|
@@ -1537,22 +1608,22 @@ function ProfilePage() {
|
|
|
1537
1608
|
|
|
1538
1609
|
### Hooks Summary
|
|
1539
1610
|
|
|
1540
|
-
| Hook | Returns
|
|
1541
|
-
| ----------------------------- |
|
|
1542
|
-
| `useBacano()` | `BacanoClient`
|
|
1543
|
-
| `useBacanoState()` | `{ client, loading, error }`
|
|
1544
|
-
| `useProducts(opts?)` | `{ data, loading, error, refetch }`
|
|
1545
|
-
| `useProduct(id)` | `{ data, loading, error, refetch }`
|
|
1546
|
-
| `useCategories()` | `{ data, loading, error, refetch }`
|
|
1547
|
-
| `useBrands()` | `{ data, loading, error, refetch }`
|
|
1548
|
-
| `useProductFilters(opts?)` | `{ data, loading, error, refetch }`
|
|
1549
|
-
| `useSearchSuggestions(opts?)` | `{ data, loading, error, refetch }`
|
|
1550
|
-
| `useAvailability(ids)` | `{ data, loading, error, refetch }`
|
|
1611
|
+
| Hook | Returns | Auth Required |
|
|
1612
|
+
| ----------------------------- | ---------------------------------------------------------------------------------------------- | ------------- |
|
|
1613
|
+
| `useBacano()` | `BacanoClient` | No |
|
|
1614
|
+
| `useBacanoState()` | `{ client, loading, error }` | No |
|
|
1615
|
+
| `useProducts(opts?)` | `{ data, loading, error, refetch }` | No |
|
|
1616
|
+
| `useProduct(id)` | `{ data, loading, error, refetch }` | No |
|
|
1617
|
+
| `useCategories()` | `{ data, loading, error, refetch }` | No |
|
|
1618
|
+
| `useBrands()` | `{ data, loading, error, refetch }` | No |
|
|
1619
|
+
| `useProductFilters(opts?)` | `{ data, loading, error, refetch }` | No |
|
|
1620
|
+
| `useSearchSuggestions(opts?)` | `{ data, loading, error, refetch }` | No |
|
|
1621
|
+
| `useAvailability(ids)` | `{ data, loading, error, refetch }` | No |
|
|
1551
1622
|
| `useCart()` | `{ cart, loading, error, startCheckout, getOrCreate, addItem, updateItem, removeItem, clear }` | No |
|
|
1552
|
-
| `useCheckout()` | `{ checkout, loading, error }`
|
|
1553
|
-
| `useOrders(opts?)` | `{ data, loading, error, refetch }`
|
|
1554
|
-
| `useOrder(id)` | `{ data, loading, error, refetch }`
|
|
1555
|
-
| `useProfile()` | `{ profile, loading, error, updateProfile }`
|
|
1623
|
+
| `useCheckout()` | `{ checkout, loading, error }` | No |
|
|
1624
|
+
| `useOrders(opts?)` | `{ data, loading, error, refetch }` | Yes |
|
|
1625
|
+
| `useOrder(id)` | `{ data, loading, error, refetch }` | Yes |
|
|
1626
|
+
| `useProfile()` | `{ profile, loading, error, updateProfile }` | Yes |
|
|
1556
1627
|
|
|
1557
1628
|
---
|
|
1558
1629
|
|
package/STOREFRONT_FORMS.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Formularios de websites
|
|
2
2
|
|
|
3
|
+
## Escalas discretas (desarrollo local)
|
|
4
|
+
|
|
5
|
+
El tipo `scale` incorpora `scale: { min, max, display, minLabel?, maxLabel? }`.
|
|
6
|
+
`display` admite `numbers` o `stars`. Los límites son enteros entre 0 y 10,
|
|
7
|
+
con mínimo menor al máximo; las estrellas comienzan en 1. No usa `optionSource`
|
|
8
|
+
ni `validation`: sus límites viven en `scale`. Ejemplo: `scale: { min: 1, max: 5, display: "stars" }`.
|
|
9
|
+
|
|
10
|
+
El renderer muestra una selección única, sin valor inicial. Envía el entero elegido
|
|
11
|
+
como string (`"4"`), igual que los campos numéricos existentes. El backend valida
|
|
12
|
+
el rango, guarda el número y conserva `4 / 5` en el snapshot histórico. Funciona
|
|
13
|
+
tanto en formularios web como en pasos de Flows. No es un slider continuo ni una
|
|
14
|
+
calificación calculada automáticamente. Renderers propios deben respetar el
|
|
15
|
+
rango, `required`, las etiquetas y la interacción por teclado.
|
|
16
|
+
|
|
3
17
|
Desde SDK 1.2.0, `BacanoForm` instrumenta interacciones mediante el provider
|
|
4
18
|
global de marketing. Para modales montados ocultos, pasar `visible={open}`.
|
|
5
19
|
Renderers personalizados usan `useBacanoFormTracking`. Leer la sección de
|
|
@@ -250,6 +264,42 @@ consultarlo.
|
|
|
250
264
|
no recibe ni debe inferir si Bacano creó un lead, encontró un cliente o marcó
|
|
251
265
|
una identidad para revisión.
|
|
252
266
|
|
|
267
|
+
## Preguntas condicionales
|
|
268
|
+
|
|
269
|
+
Un campo `radio` o `select` con opciones inline puede incluir ramas recursivas:
|
|
270
|
+
|
|
271
|
+
```ts
|
|
272
|
+
branches: [
|
|
273
|
+
{ value: "simple", fields: [/* campos normales */] },
|
|
274
|
+
{ value: "complete", fields: [/* campos normales o condicionales */] },
|
|
275
|
+
]
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
`value` corresponde al valor estable de una opción. La etiqueta puede cambiar sin
|
|
279
|
+
mover sus campos. Las definiciones sin `branches` siguen funcionando igual.
|
|
280
|
+
`BacanoForm` y el renderer de formularios de Flows muestran solo el camino elegido,
|
|
281
|
+
aplican la obligatoriedad de sus hijos y descartan valores ocultos al cambiar de
|
|
282
|
+
opción. El backend vuelve a validarlo; no acepta respuestas de caminos ocultos.
|
|
283
|
+
|
|
284
|
+
Para un renderer propio, importar desde la entrada principal del SDK:
|
|
285
|
+
|
|
286
|
+
```ts
|
|
287
|
+
import { activeFormValues, formRootFields, visibleFormFields } from "@bacano/sdk";
|
|
288
|
+
|
|
289
|
+
const fields = visibleFormFields(formRootFields(definition), values);
|
|
290
|
+
const submissionValues = activeFormValues(definition, values);
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
`visibleFormFields` devuelve la ruta activa aplanada, incluyendo las preguntas
|
|
294
|
+
padre. Para preservar secciones, pasos y presentación, recorrer cada contenedor
|
|
295
|
+
y sus ramas seleccionadas. Al modificar una respuesta, usar `activeFormValues`
|
|
296
|
+
también para actualizar el estado: evita restaurar respuestas ocultas al volver
|
|
297
|
+
a una opción anterior. Filtrar nuevamente antes de enviar.
|
|
298
|
+
|
|
299
|
+
Los sitios que tengan instalado un SDK anterior deben actualizarlo. Una definición
|
|
300
|
+
con ramas necesita un renderer compatible; no basta con actualizar el backend.
|
|
301
|
+
La definición admite cinco niveles condicionales y cien campos en total.
|
|
302
|
+
|
|
253
303
|
## Checklist mínimo del storefront
|
|
254
304
|
|
|
255
305
|
- Usar un solo `BacanoProvider` y el cliente global ya inicializado.
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
# Pagos en storefronts Bacano
|
|
2
|
+
|
|
3
|
+
Contrato canónico para agentes que implementan o auditan pagos con
|
|
4
|
+
`@bacano/sdk`. El storefront presenta las opciones y abre la URL devuelta por
|
|
5
|
+
Bacano; las credenciales, payloads, webhooks, conciliación, inventario y
|
|
6
|
+
contabilidad pertenecen al backend.
|
|
7
|
+
|
|
8
|
+
## Flujo obligatorio del SDK
|
|
9
|
+
|
|
10
|
+
1. Consultar `checkout.getPaymentOptions({ fulfillmentFamily })` y mostrar
|
|
11
|
+
únicamente los métodos retornados por Bacano.
|
|
12
|
+
2. Enviar `paymentMode` y `paymentMethodId` a `checkout.submit()`.
|
|
13
|
+
3. Si el resultado exige pasarela, llamar una sola vez a
|
|
14
|
+
`checkout.createPaymentSession()` con el `orderId`, `publicOrderToken`,
|
|
15
|
+
método y una `returnUrl` pública.
|
|
16
|
+
4. Cuando `integrationMode === "redirect"`, navegar inmediatamente a
|
|
17
|
+
`redirectUrl` con `window.location.assign()`. No insertar una pantalla
|
|
18
|
+
intermedia de confirmación.
|
|
19
|
+
5. En el retorno, conciliar la sesión existente y después consultar el pedido.
|
|
20
|
+
Nunca crear otro pedido para reintentar el mismo pago.
|
|
21
|
+
6. Aprobar la compra solo por el estado verificado por Bacano. Los parámetros
|
|
22
|
+
del navegador y la pantalla del proveedor no son evidencia financiera.
|
|
23
|
+
|
|
24
|
+
El storefront no construye URLs de Wompi, Mercado Pago, Openpay o Addi, no envía
|
|
25
|
+
credenciales del comercio y no reproduce los payloads privados del proveedor.
|
|
26
|
+
|
|
27
|
+
### Conciliación segura al regresar del proveedor
|
|
28
|
+
|
|
29
|
+
La llamada canónica es:
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
await client.checkout.reconcilePaymentSession({
|
|
33
|
+
orderId,
|
|
34
|
+
publicOrderToken,
|
|
35
|
+
paymentSessionId,
|
|
36
|
+
// Solo si el proveedor devuelve un ID que Bacano espera y verifica.
|
|
37
|
+
gatewayTransactionId,
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
- `paymentSessionId` es la referencia estable creada por Bacano y debe viajar
|
|
42
|
+
en la `returnUrl`.
|
|
43
|
+
- Para **Mercado Pago Orders**, **Openpay** y **Addi**, se omite
|
|
44
|
+
`gatewayTransactionId`: Bacano recupera el identificador remoto guardado y
|
|
45
|
+
consulta al proveedor con credenciales del servidor.
|
|
46
|
+
- Para **Wompi**, se envía el ID público de transacción retornado por Wompi;
|
|
47
|
+
Bacano comprueba que coincida antes de consultar la pasarela.
|
|
48
|
+
- No tratar `payment_id`, `collection_status`, `status`, ni ningún otro
|
|
49
|
+
parámetro del navegador como evidencia de aprobación. En Mercado Pago,
|
|
50
|
+
`payment_id` identifica un pago dentro de la Order y no sustituye el ID de
|
|
51
|
+
Order remoto almacenado por Bacano.
|
|
52
|
+
- Incluso si la conciliación responde con error temporal, consultar el pedido
|
|
53
|
+
y esperar el estado confirmado mediante `orders.waitForPayment()`; un
|
|
54
|
+
timeout significa **pendiente**, no rechazado.
|
|
55
|
+
|
|
56
|
+
## Mercado Pago · contrato vigente
|
|
57
|
+
|
|
58
|
+
La integración de Bacano usa **Checkout Pro con API de Orders** (`POST
|
|
59
|
+
/v1/orders`), no la API antigua de Preferences. Esta diferencia es crítica:
|
|
60
|
+
una aplicación o payload de Preferences puede autenticar correctamente y aun
|
|
61
|
+
así recibir `403` o `400` al crear la order.
|
|
62
|
+
|
|
63
|
+
### Configuración del comercio
|
|
64
|
+
|
|
65
|
+
- Crear o elegir una aplicación en **Mercado Pago Developers** preparada para
|
|
66
|
+
Checkout Pro y **API de Orders**.
|
|
67
|
+
- En Bacano, **Access Token de la aplicación** significa la credencial privada
|
|
68
|
+
con la que el backend llama la API. No es la Public Key y tampoco es la firma
|
|
69
|
+
del webhook.
|
|
70
|
+
- **Firma secreta del Webhook** es un secreto distinto, generado al guardar la
|
|
71
|
+
configuración de notificaciones en Mercado Pago.
|
|
72
|
+
- Pruebas y producción tienen credenciales diferentes. El ambiente elegido en
|
|
73
|
+
Bacano debe coincidir con el vendedor/credencial verificado por Mercado Pago.
|
|
74
|
+
- Copiar en Mercado Pago la **URL de notificaciones de Bacano** mostrada en la
|
|
75
|
+
configuración del método. La ruta identifica la conexión del comercio; no
|
|
76
|
+
debe inventarse ni compartirse entre configuraciones.
|
|
77
|
+
- Activar el evento **Order (Mercado Pago)** (`orders_v2`). No seleccionar
|
|
78
|
+
`Pagos (legacy)` como sustituto.
|
|
79
|
+
- Webhook, API pública y `returnUrl` deben ser HTTPS alcanzable. En local se
|
|
80
|
+
necesita un túnel; `localhost` no sirve para Mercado Pago.
|
|
81
|
+
- La Public Key no se utiliza en este modo de redirección alojada y nunca debe
|
|
82
|
+
colocarse en el campo Access Token.
|
|
83
|
+
|
|
84
|
+
No registrar, copiar a código, enviar al navegador ni incluir en capturas el
|
|
85
|
+
Access Token o la firma secreta. Si una credencial queda expuesta, rotarla.
|
|
86
|
+
|
|
87
|
+
### Formato privado de Orders para Colombia
|
|
88
|
+
|
|
89
|
+
Este es el contrato del adaptador de Bacano validado contra la API colombiana
|
|
90
|
+
de Orders el 22 de septiembre de 2026. No debe implementarse en el storefront,
|
|
91
|
+
pero un agente que modifique el backend debe preservarlo y volver a probarlo si
|
|
92
|
+
Mercado Pago cambia su esquema.
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
"type": "online",
|
|
97
|
+
"processing_mode": "manual",
|
|
98
|
+
"total_amount": "19000",
|
|
99
|
+
"items": [
|
|
100
|
+
{
|
|
101
|
+
"title": "Pedido Bacano",
|
|
102
|
+
"quantity": 1,
|
|
103
|
+
"unit_price": "19000"
|
|
104
|
+
}
|
|
105
|
+
],
|
|
106
|
+
"taxes": [{ "type": "IVA", "value": "0" }]
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Reglas que evitaron un rechazo real del proveedor:
|
|
111
|
+
|
|
112
|
+
- Los montos enviados a Orders son strings de pesos COP enteros: `"19000"`,
|
|
113
|
+
no `"19000.00"`. Bacano conserva centavos internamente y rechaza fracciones
|
|
114
|
+
que no pueda representar; nunca redondea silenciosamente.
|
|
115
|
+
- El ítem usa `title`, `quantity` y `unit_price`. En este contrato no enviar
|
|
116
|
+
`currency_id`, `total_amount` ni `unit_measure` dentro de `items[]`.
|
|
117
|
+
- `taxes[].value` es string, incluso cuando el IVA es cero. No enviarlo como
|
|
118
|
+
número.
|
|
119
|
+
- Orders rechaza `config.notification_url` en el payload de creación. La URL
|
|
120
|
+
se registra en **Webhooks** de la aplicación de Mercado Pago y no se repite
|
|
121
|
+
dentro de cada order.
|
|
122
|
+
- Si existe IVA, `unit_price × quantity + taxes` debe reconciliar exactamente
|
|
123
|
+
con `total_amount`. El adaptador utiliza el IVA calculado por Bacano; no
|
|
124
|
+
inventa una tarifa fija.
|
|
125
|
+
- El monto persistido, el total remoto autenticado y el pedido deben coincidir
|
|
126
|
+
antes de aprobar el pago.
|
|
127
|
+
|
|
128
|
+
La idempotencia de creación pertenece a Bacano. Tras una respuesta incierta se
|
|
129
|
+
reutiliza el mismo intento y la misma clave; generar una nueva order podría
|
|
130
|
+
producir un cobro duplicado. Un rechazo definitivo de creación (`400`, `401` o
|
|
131
|
+
`403`) cierra esa sesión y permite corregir la configuración sin considerar el
|
|
132
|
+
pedido pagado.
|
|
133
|
+
|
|
134
|
+
### Diagnóstico rápido
|
|
135
|
+
|
|
136
|
+
| Síntoma | Interpretación inicial | Acción segura |
|
|
137
|
+
| --- | --- | --- |
|
|
138
|
+
| `MERCADOPAGO_ACCOUNT_ENVIRONMENT_MISMATCH` | La credencial y el ambiente no corresponden | Verificar credencial de prueba/productiva y vendedor; no cambiar el ambiente para ocultarlo |
|
|
139
|
+
| `MERCADOPAGO_HTTP_401` | Access Token inválido, revocado o mal copiado | Rotar/verificar el Access Token de la aplicación |
|
|
140
|
+
| `MERCADOPAGO_HTTP_403` al crear | La cuenta autentica, pero la aplicación no está habilitada para Orders o la operación | Confirmar API de Orders y capacidades de la aplicación |
|
|
141
|
+
| `MERCADOPAGO_HTTP_400` al crear | El proveedor rechazó el payload | Inspeccionar una versión sanitizada del error; nunca imprimir token ni PII |
|
|
142
|
+
| `MERCADOPAGO_RETURN_HTTPS_REQUIRED` | La URL de retorno no es HTTPS pública | Usar dominio publicado o túnel local |
|
|
143
|
+
| `MERCADOPAGO_CHECKOUT_PENDING_RECONCILIATION` | El resultado de creación es incierto | Reintentar la sesión existente; no crear otro pedido |
|
|
144
|
+
|
|
145
|
+
Un `403` que cambia a `400` después de crear una aplicación de Orders indica
|
|
146
|
+
que la autorización avanzó y ahora debe corregirse el contrato de la solicitud;
|
|
147
|
+
no significa que el Access Token sea la firma del webhook.
|
|
148
|
+
|
|
149
|
+
## Openpay by BBVA · contrato vigente
|
|
150
|
+
|
|
151
|
+
Bacano usa el **Webcheckout alojado sin ID de cliente** de Openpay Colombia.
|
|
152
|
+
El storefront no carga Openpay.js ni recibe llaves: crea una sesión Bacano y
|
|
153
|
+
abre el `redirectUrl` validado que devuelve el backend.
|
|
154
|
+
|
|
155
|
+
### Configuración del comercio
|
|
156
|
+
|
|
157
|
+
- Registrar en Bacano el **ID del comercio** y la **llave privada** del mismo
|
|
158
|
+
ambiente. La llave pública no participa en Webcheckout server-to-server.
|
|
159
|
+
- Sandbox usa `https://sandbox-api.openpay.co`; producción usa
|
|
160
|
+
`https://api.openpay.co`. Bacano fija esos orígenes y no acepta una URL de API
|
|
161
|
+
suministrada por el comercio.
|
|
162
|
+
- La API pública de Bacano debe ser HTTPS. Al guardar, Bacano registra el
|
|
163
|
+
webhook en Openpay con credenciales Basic generadas internamente y completa
|
|
164
|
+
la verificación que Openpay envía al endpoint. No se copian esas credenciales
|
|
165
|
+
al storefront ni se solicitan al usuario.
|
|
166
|
+
- El método queda guardado aunque falle la provisión remota del webhook; la
|
|
167
|
+
interfaz reporta el error y permite reintentar la misma conexión. No se
|
|
168
|
+
ofrece en el checkout hasta que el webhook figure verificado.
|
|
169
|
+
|
|
170
|
+
Referencia oficial: [API Openpay Colombia](https://documents.openpay.co/api/index.html).
|
|
171
|
+
|
|
172
|
+
### Creación, recuperación y confirmación
|
|
173
|
+
|
|
174
|
+
- `POST /v1/{MERCHANT_ID}/checkouts` recibe monto entero COP, `iva` string,
|
|
175
|
+
referencia única, comprador, retorno HTTPS y una expiración anterior a la
|
|
176
|
+
expiración local de la sesión.
|
|
177
|
+
- Bacano persiste primero sesión, payload y snapshot cifrado de credenciales.
|
|
178
|
+
El primer intento crea directamente el checkout. Tras un timeout, primero
|
|
179
|
+
busca la misma referencia; si Openpay responde duplicado `1006`, recupera el
|
|
180
|
+
checkout existente. Nunca genera otra referencia para un reintento técnico.
|
|
181
|
+
- Solo se redirige a un link HTTPS del host exacto de Openpay y ruta `/ck/...`.
|
|
182
|
+
- El retorno y el webhook son señales para conciliar. Bacano consulta cargos
|
|
183
|
+
con la llave privada y exige igualdad de referencia, moneda e importe antes
|
|
184
|
+
de aprobar. Campos adicionales del webhook o del navegador no se registran
|
|
185
|
+
como evidencia financiera.
|
|
186
|
+
- Un cargo `failed` o `cancelled` no cierra por sí solo la sesión mientras el
|
|
187
|
+
checkout alojado siga disponible: el comprador puede probar otro medio. Un
|
|
188
|
+
cargo posterior `completed` aprueba si es el único aprobado y todos los demás
|
|
189
|
+
cargos son fallidos o cancelados. Cargos simultáneos pendientes, más de un
|
|
190
|
+
aprobado, reembolsos, contracargos o discrepancias pasan a revisión manual.
|
|
191
|
+
- El retorno al sitio no declara vencida una sesión remota por la hora local;
|
|
192
|
+
solo permite reintentar cuando el proveedor confirma el cierre del checkout.
|
|
193
|
+
|
|
194
|
+
El comprador usa los medios habilitados por Openpay dentro de su página
|
|
195
|
+
alojada; el SDK no pide tarjeta, PSE ni efectivo de forma separada.
|
|
196
|
+
|
|
197
|
+
### Diagnóstico rápido
|
|
198
|
+
|
|
199
|
+
| Síntoma | Acción segura |
|
|
200
|
+
| --- | --- |
|
|
201
|
+
| `OPENPAY_CREDENTIALS_REQUIRED` | Ingresar la llave privada; no la llave pública |
|
|
202
|
+
| `OPENPAY_MERCHANT_ID_REQUIRED` | Copiar el ID del comercio del mismo ambiente |
|
|
203
|
+
| `OPENPAY_HTTP_401` / `OPENPAY_HTTP_403` | Verificar pareja comercio/llave y sandbox/producción |
|
|
204
|
+
| `OPENPAY_PUBLIC_HTTPS_REQUIRED` | Publicar la API Bacano por HTTPS antes de registrar el webhook |
|
|
205
|
+
| `OPENPAY_CHECKOUT_PENDING_RECONCILIATION` | Reutilizar la sesión y consultar; no crear otro pedido |
|
|
206
|
+
| `OPENPAY_*_REVIEW_REQUIRED` | No aprobar ni reintentar con otra referencia; revisar la evidencia |
|
|
207
|
+
|
|
208
|
+
## Reglas específicas visibles
|
|
209
|
+
|
|
210
|
+
- Addi puede exigir CC y datos de contacto/residencia. Mostrar esos campos solo
|
|
211
|
+
cuando el método retornado tenga `gatewayCode === "ADDI"`; la evaluación de
|
|
212
|
+
crédito ocurre en Addi.
|
|
213
|
+
- El storefront debe usar el texto del modo seleccionado: para `pay_now`, el
|
|
214
|
+
botón principal comunica **Pagar ahora**, no solo **Confirmar pedido**.
|
|
215
|
+
- Recargos, impuestos, descuentos, envío y total final siempre vienen de
|
|
216
|
+
Bacano. El storefront no los recalcula ni altera el monto de la pasarela.
|
|
217
|
+
- Los secretos vacíos al editar una conexión significan conservar los
|
|
218
|
+
existentes; nunca intentar precargarlos en el navegador.
|
|
219
|
+
|
|
220
|
+
## Prueba mínima antes de publicar
|
|
221
|
+
|
|
222
|
+
- Ejecutar un pago sandbox completo por cada pasarela activa, no solo validar
|
|
223
|
+
el formulario de configuración.
|
|
224
|
+
- Confirmar redirección inmediata al checkout alojado.
|
|
225
|
+
- Probar aprobación, rechazo, retorno, refresco, doble clic y reintento.
|
|
226
|
+
- Confirmar que el webhook responde, que Bacano consulta el recurso autenticado
|
|
227
|
+
y que repetir el evento no duplica pago, pedido, inventario ni conversión.
|
|
228
|
+
- Verificar el pedido desde `orders.getPublicOrder()` o
|
|
229
|
+
`orders.waitForPayment()`; no desde parámetros de retorno.
|
|
230
|
+
- Si el flujo real no se ejecutó, reportarlo como **NO VERIFICADO**, nunca como
|
|
231
|
+
listo para producción.
|
package/client.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { type FlowsClient } from "./flows";
|
|
1
2
|
import type { BacanoClientConfig, BacanoClientContext, Brand, Cart, CartItem, CatalogAttributeList, CatalogCategoryList, CatalogPageResult, CheckoutResult, CheckoutSubmission, ContentEntry, CustomerAddress, CustomerProfile, CustomerProfileUpdate, GetAttributeListOptions, GetCatalogPageOptions, GetCategoryListOptions, GetContentOptions, GetOrdersOptions, GetProductFiltersOptions, GetProductRecommendationsOptions, GetProductSeoEntriesOptions, GetProductsOptions, GetSearchSuggestionsOptions, GetStaticCatalogBootstrapOptions, GetStaticCatalogSnapshotOptions, Order, Product, ProductAvailability, ProductCategory, ProductContentBlock, ProductFilters, ProductRecommendationsResult, ProductSeoEntriesResult, ProductVariantLiveState, PublicOrder, PublicOrderLookupInput, SearchSuggestion, StartGuestCheckoutInput, StaticCatalogBootstrap, StaticCatalogSnapshot, WaitForPublicOrderPaymentInput, WebsiteCampaignCaptureInput, WebsiteCampaignCaptureResult, WebsiteCheckoutAddress, WebsiteCheckoutItem, WebsiteCouponActionResult, WebsiteDeliveryOption, WebsiteFormResponseInput, WebsiteFormResponseResult, WebsiteFreeShippingProgress, WebsiteFulfillmentFamily, WebsiteGuestContact, WebsiteLocationOptions, WebsitePaymentMethod, WebsitePaymentOption, WebsitePaymentSessionResult, WebsitePublishedForm, WebsiteShippingPolicy, WebsiteShippingQuote } from "./types";
|
|
2
3
|
export interface BacanoClient {
|
|
4
|
+
flows: FlowsClient;
|
|
3
5
|
/** Initialize the client and resolve its website context. */
|
|
4
6
|
init(): Promise<void>;
|
|
5
7
|
/** Get the resolved website context (company_id, chain_id, etc.) */
|
|
@@ -33,6 +35,7 @@ export interface BacanoClient {
|
|
|
33
35
|
getByCategory(categoryKey: string, opts?: GetContentOptions): Promise<ContentEntry[]>;
|
|
34
36
|
getByTag(tag: string, opts?: GetContentOptions): Promise<ContentEntry[]>;
|
|
35
37
|
getForProduct(productId: string, opts?: GetContentOptions): Promise<ProductContentBlock[]>;
|
|
38
|
+
getForProducts(productIds: string[], opts?: GetContentOptions): Promise<Record<string, ProductContentBlock[]>>;
|
|
36
39
|
};
|
|
37
40
|
forms: {
|
|
38
41
|
/** Returns the current published definition or null when it is unavailable. */
|
|
@@ -89,7 +92,12 @@ export interface BacanoClient {
|
|
|
89
92
|
orderId: string;
|
|
90
93
|
publicOrderToken: string;
|
|
91
94
|
paymentSessionId: string;
|
|
92
|
-
|
|
95
|
+
/**
|
|
96
|
+
* Provider transaction returned to the browser. Required by providers
|
|
97
|
+
* such as Wompi; omit it for Mercado Pago Orders and Addi, which Bacano
|
|
98
|
+
* reconciles server-side from the stored payment session.
|
|
99
|
+
*/
|
|
100
|
+
gatewayTransactionId?: string;
|
|
93
101
|
}): Promise<WebsitePaymentSessionResult>;
|
|
94
102
|
};
|
|
95
103
|
orders: {
|