@reactionary/acp 0.10.41 → 0.10.43
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/README.md +52 -57
- package/index.js +11 -0
- package/lib/acp-discounts.js +113 -0
- package/lib/acp-idempotency.js +119 -0
- package/lib/acp-mcp.js +206 -0
- package/lib/acp-payment-handlers.js +38 -0
- package/lib/acp-schemas.js +240 -70
- package/lib/acp-webhooks.js +72 -0
- package/lib/reactionary-acp-server.js +1156 -253
- package/package.json +3 -3
- package/src/index.d.ts +4 -0
- package/src/lib/acp-discounts.d.ts +45 -0
- package/src/lib/acp-idempotency.d.ts +23 -0
- package/src/lib/acp-mcp.d.ts +21 -0
- package/src/lib/acp-payment-handlers.d.ts +64 -0
- package/src/lib/acp-schemas.d.ts +766 -209
- package/src/lib/acp-webhooks.d.ts +48 -0
- package/src/lib/reactionary-acp-server.d.ts +343 -39
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/** An agent's order webhook receiver and the secret shared with it. */
|
|
2
|
+
export interface ACPWebhookEndpoint {
|
|
3
|
+
/** e.g. the agent's `.../agentic_checkout/webhooks/order_events` URL. */
|
|
4
|
+
url: string;
|
|
5
|
+
/** Shared secret for the `Merchant-Signature` HMAC. */
|
|
6
|
+
secret: string;
|
|
7
|
+
/**
|
|
8
|
+
* The authenticated agent (see `authenticate`) whose orders go to this
|
|
9
|
+
* endpoint. Endpoints without one receive orders of every agent that has
|
|
10
|
+
* no endpoint of its own.
|
|
11
|
+
*/
|
|
12
|
+
agentId?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface ACPWebhookOptions {
|
|
15
|
+
endpoints: ACPWebhookEndpoint[];
|
|
16
|
+
/**
|
|
17
|
+
* Delays before each retry of a failed delivery. Retries are held in
|
|
18
|
+
* memory, so they do not survive a restart. Defaults to 0.5s, 2s, 10s, 1m
|
|
19
|
+
* and 5m.
|
|
20
|
+
*/
|
|
21
|
+
retryDelaysMs?: number[];
|
|
22
|
+
/** Accepts `http:` endpoint URLs; intended for test environments. */
|
|
23
|
+
allowInsecureUrls?: boolean;
|
|
24
|
+
/** Fetch implementation; defaults to the global fetch. */
|
|
25
|
+
fetch?: typeof fetch;
|
|
26
|
+
}
|
|
27
|
+
export type ACPOrderEventType = 'order_create' | 'order_update';
|
|
28
|
+
/**
|
|
29
|
+
* Delivers order lifecycle events to agents' webhook receivers (checkout
|
|
30
|
+
* RFC §2.3), signed with `Merchant-Signature: t=<unix>,v1=<hex>` over
|
|
31
|
+
* `timestamp + "." + body` (HMAC-SHA256). Failed deliveries are retried as
|
|
32
|
+
* the same event, with a fresh timestamp and signature, as in the UCP
|
|
33
|
+
* adapter.
|
|
34
|
+
*/
|
|
35
|
+
export declare class ACPOrderWebhooks {
|
|
36
|
+
private readonly options;
|
|
37
|
+
private readonly retryDelaysMs;
|
|
38
|
+
private readonly fetchImpl;
|
|
39
|
+
constructor(options: ACPWebhookOptions);
|
|
40
|
+
/** The endpoint for an agent's orders, if any. */
|
|
41
|
+
getEndpoint(agentId: string | undefined): ACPWebhookEndpoint | undefined;
|
|
42
|
+
/** Sends an event without waiting for it; the order is the full current state. */
|
|
43
|
+
deliver(endpoint: ACPWebhookEndpoint, type: ACPOrderEventType, order: object): void;
|
|
44
|
+
private attempt;
|
|
45
|
+
private isAllowedUrl;
|
|
46
|
+
}
|
|
47
|
+
/** `t=<unix seconds>,v1=<hex HMAC-SHA256 of "t.body">`, as receivers verify. */
|
|
48
|
+
export declare function signWebhookPayload(body: string, secret: string, timestamp?: number): string;
|
|
@@ -1,36 +1,38 @@
|
|
|
1
|
-
import { type Cache, type Cart, type Checkout, type Inventory, type
|
|
2
|
-
import { type ReactionaryFeedInventoryOptions, type ReactionaryFeedProcessingOptions } from '@reactionary/feeds';
|
|
1
|
+
import { type Cache, type Cart, type Checkout, type Inventory, type Order, type MonetaryAmount, type PaymentMethod, type Product, type RequestContext, type Result, type ShippingMethod } from '@reactionary/core';
|
|
3
2
|
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
3
|
+
import { type ACPAffiliateAttribution, type ACPIntentTrace, type ACPAddress, type ACPAuthenticationMetadata, type ACPInterventionType, type ACPPaymentData } from './acp-schemas.js';
|
|
4
|
+
import { type ACPWebhookOptions } from './acp-webhooks.js';
|
|
5
|
+
import { type ACPPaymentHandler, type ACPPaymentHandlerOption } from './acp-payment-handlers.js';
|
|
4
6
|
export interface ReactionaryACPClient {
|
|
5
7
|
cart?: {
|
|
6
8
|
createCart(payload: unknown): Promise<Result<Cart>>;
|
|
7
9
|
add(payload: unknown): Promise<Result<Cart>>;
|
|
8
10
|
getById(payload: unknown): Promise<Result<Cart>>;
|
|
9
11
|
deleteCart?(payload: unknown): Promise<Result<void>>;
|
|
12
|
+
applyCouponCode?(payload: unknown): Promise<Result<Cart>>;
|
|
13
|
+
removeCouponCode?(payload: unknown): Promise<Result<Cart>>;
|
|
14
|
+
changeQuantity?(payload: unknown): Promise<Result<Cart>>;
|
|
15
|
+
remove?(payload: unknown): Promise<Result<Cart>>;
|
|
10
16
|
};
|
|
11
17
|
checkout?: {
|
|
12
18
|
initiateCheckoutForCart(payload: unknown): Promise<Result<Checkout>>;
|
|
13
19
|
getById(payload: unknown): Promise<Result<Checkout>>;
|
|
14
20
|
setShippingAddress(payload: unknown): Promise<Result<Checkout>>;
|
|
15
21
|
getAvailableShippingMethods(payload: unknown): Promise<Result<ShippingMethod[]>>;
|
|
16
|
-
getAvailablePaymentMethods(payload: unknown): Promise<Result<PaymentMethod[]>>;
|
|
22
|
+
getAvailablePaymentMethods?(payload: unknown): Promise<Result<PaymentMethod[]>>;
|
|
17
23
|
setShippingInstruction(payload: unknown): Promise<Result<Checkout>>;
|
|
18
24
|
addPaymentInstruction(payload: unknown): Promise<Result<Checkout>>;
|
|
19
25
|
finalizeCheckout(payload: unknown): Promise<Result<Checkout>>;
|
|
20
26
|
};
|
|
21
|
-
productSearch?: {
|
|
22
|
-
queryByTerm(payload: unknown): Promise<Result<ProductSearchResult>>;
|
|
23
|
-
};
|
|
24
27
|
product?: {
|
|
25
28
|
getBySKU(payload: unknown): Promise<Result<Product>>;
|
|
26
29
|
};
|
|
27
|
-
price?: {
|
|
28
|
-
getListPrice(payload: unknown): Promise<Result<Price>>;
|
|
29
|
-
getCustomerPrice(payload: unknown): Promise<Result<Price>>;
|
|
30
|
-
};
|
|
31
30
|
inventory?: {
|
|
32
31
|
getBySKU(payload: unknown): Promise<Result<Inventory>>;
|
|
33
32
|
};
|
|
33
|
+
order?: {
|
|
34
|
+
getById(payload: unknown): Promise<Result<Order>>;
|
|
35
|
+
};
|
|
34
36
|
}
|
|
35
37
|
export type ReactionaryACPClientFactory<TClient extends ReactionaryACPClient = ReactionaryACPClient> = (requestContext: RequestContext) => TClient;
|
|
36
38
|
export interface ReactionaryACPServerOptions {
|
|
@@ -39,24 +41,219 @@ export interface ReactionaryACPServerOptions {
|
|
|
39
41
|
basePath?: string;
|
|
40
42
|
sessionCache?: Cache;
|
|
41
43
|
sessionTtlSeconds?: number;
|
|
44
|
+
/**
|
|
45
|
+
* How long orders placed through ACP are remembered for order updates
|
|
46
|
+
* (`notifyOrderUpdated`). Defaults to 90 days.
|
|
47
|
+
*/
|
|
48
|
+
orderTtlSeconds?: number;
|
|
49
|
+
/**
|
|
50
|
+
* How long Idempotency-Key responses are kept for replay. At least, and by
|
|
51
|
+
* default, 24 hours (checkout RFC §6.6).
|
|
52
|
+
*/
|
|
53
|
+
idempotencyTtlSeconds?: number;
|
|
42
54
|
checkoutSessionTtlSeconds?: number;
|
|
43
|
-
|
|
55
|
+
/**
|
|
56
|
+
* Authenticates agents on checkout endpoints, e.g. by their
|
|
57
|
+
* `Authorization: Bearer` token (see `createBearerTokenAuthenticator`) or a
|
|
58
|
+
* request signature. Returning undefined answers 401. Checkout sessions are
|
|
59
|
+
* visible only to the agent that created them. Unset, checkout endpoints
|
|
60
|
+
* are open — the server logs a warning, as ACP requires authentication.
|
|
61
|
+
*/
|
|
62
|
+
authenticate?: (request: Request) => ACPAgent | undefined | Promise<ACPAgent | undefined>;
|
|
63
|
+
/**
|
|
64
|
+
* The buyer-facing order page, as a URL template with an `{orderId}`
|
|
65
|
+
* placeholder, e.g. `https://shop.example/account/orders/{orderId}`. Orders
|
|
66
|
+
* MUST carry a permalink; without this option it is left out and a warning
|
|
67
|
+
* is logged.
|
|
68
|
+
*/
|
|
69
|
+
orderPermalinkUrl?: string;
|
|
70
|
+
/**
|
|
71
|
+
* Asks for 3D Secure authentication: returning metadata makes completion
|
|
72
|
+
* answer `authentication_required` until the agent completes again with an
|
|
73
|
+
* `authentication_result`, which is passed to the backend's payment
|
|
74
|
+
* integration as protocol data `acp_authentication_result`. Advertise
|
|
75
|
+
* `3ds` in `interventions.supported` for agents to know.
|
|
76
|
+
*/
|
|
77
|
+
authentication?: ACPAuthenticationOptions;
|
|
78
|
+
/**
|
|
79
|
+
* Receives an order's affiliate attribution (first touch from session
|
|
80
|
+
* creation, last touch from completion) once the order exists, for the
|
|
81
|
+
* affiliate network. Attribution is write-only: never returned to agents
|
|
82
|
+
* or sent in webhooks.
|
|
83
|
+
*/
|
|
84
|
+
onOrderAttribution?: (attribution: {
|
|
85
|
+
orderId: string;
|
|
86
|
+
checkoutSessionId: string;
|
|
87
|
+
agentId?: string;
|
|
88
|
+
firstTouch?: ACPAffiliateAttribution;
|
|
89
|
+
lastTouch?: ACPAffiliateAttribution;
|
|
90
|
+
}) => void | Promise<void>;
|
|
91
|
+
/**
|
|
92
|
+
* Marketing consent (marketing consent RFC): channels offered to the
|
|
93
|
+
* buyer on every session, and where the buyer's decisions go once the
|
|
94
|
+
* order exists. Unset, no consent is offered.
|
|
95
|
+
*/
|
|
96
|
+
marketingConsent?: ACPMarketingConsentOptions;
|
|
97
|
+
/**
|
|
98
|
+
* Receives the agent's reason for canceling a session (intent traces),
|
|
99
|
+
* e.g. for conversion analytics. Traces are also kept on the session state
|
|
100
|
+
* but never returned to agents.
|
|
101
|
+
*/
|
|
102
|
+
onIntentTrace?: (trace: ACPIntentTrace, context: {
|
|
103
|
+
checkoutSessionId: string;
|
|
104
|
+
agentId?: string;
|
|
105
|
+
}) => void | Promise<void>;
|
|
106
|
+
/**
|
|
107
|
+
* Classifies backend shipping methods into ACP fulfillment types, e.g.
|
|
108
|
+
* click-and-collect methods as `pickup` with their location. Methods are
|
|
109
|
+
* `shipping` by default, as core shipping methods carry no type.
|
|
110
|
+
*/
|
|
111
|
+
classifyFulfillmentOption?: (method: ShippingMethod) => ACPFulfillmentClassification | undefined;
|
|
112
|
+
/**
|
|
113
|
+
* The URL where the buyer can continue the checkout on the merchant's
|
|
114
|
+
* site, as a template with a `{checkoutSessionId}` placeholder.
|
|
115
|
+
*/
|
|
116
|
+
continueUrl?: string;
|
|
117
|
+
/**
|
|
118
|
+
* Serves the ACP MCP transport binding at `{basePath}/mcp`: the checkout
|
|
119
|
+
* tools over JSON-RPC 2.0 (Streamable HTTP), dispatched to the REST
|
|
120
|
+
* handlers with the connection's Authorization. Discovery then lists the
|
|
121
|
+
* `mcp` transport.
|
|
122
|
+
*/
|
|
123
|
+
mcp?: boolean;
|
|
124
|
+
/**
|
|
125
|
+
* Sends signed order events (`order_create` on placement, `order_update`
|
|
126
|
+
* via `notifyOrderUpdated`) to the agents' webhook receivers, as ACP
|
|
127
|
+
* requires. Needs the client's `order.getById`. Unset, no webhooks are
|
|
128
|
+
* sent and a warning is logged.
|
|
129
|
+
*/
|
|
130
|
+
webhooks?: ACPWebhookOptions;
|
|
131
|
+
/**
|
|
132
|
+
* Payment handlers advertised in `capabilities.payment.handlers`, e.g.
|
|
133
|
+
* `createTokenizedCardHandler(...)`. Each maps to the backend payment
|
|
134
|
+
* method its payments are placed with.
|
|
135
|
+
*/
|
|
136
|
+
paymentHandlers?: ACPPaymentHandlerOption[];
|
|
137
|
+
/**
|
|
138
|
+
* Accepts raw card credentials (anything carrying a card number or CVC)
|
|
139
|
+
* and forwards them to the backend's payment integration, which persists
|
|
140
|
+
* payment data — putting the deployment in PCI DSS scope. Off by default:
|
|
141
|
+
* such completions are rejected, as handlers are expected to submit
|
|
142
|
+
* delegated tokens.
|
|
143
|
+
*/
|
|
144
|
+
acceptRawCardCredentials?: boolean;
|
|
44
145
|
links?: ACPLink[];
|
|
45
|
-
productFeed?: ACPProductFeedOptions;
|
|
46
146
|
discovery?: ACPDiscoveryOptions;
|
|
47
147
|
/**
|
|
48
148
|
* Email used to price transient checkouts before the buyer has supplied
|
|
49
149
|
* one. Never used for the real checkout created on completion.
|
|
50
150
|
*/
|
|
51
151
|
placeholderEmail?: string;
|
|
152
|
+
/**
|
|
153
|
+
* The interventions (e.g. 3DS) this seller can handle, and which it
|
|
154
|
+
* requires. Sessions report the intersection with what the agent declared.
|
|
155
|
+
* Defaults to none supported and none required.
|
|
156
|
+
*/
|
|
157
|
+
interventions?: ACPInterventionOptions;
|
|
158
|
+
/**
|
|
159
|
+
* Whether orders need a fulfillment option. When the backend offers none
|
|
160
|
+
* for an address, the session cannot become payable. Defaults to true;
|
|
161
|
+
* disable it for stores selling only goods that need no shipping.
|
|
162
|
+
*/
|
|
163
|
+
requireFulfillment?: boolean;
|
|
164
|
+
/**
|
|
165
|
+
* Checks line items against these fulfillment centers' combined stock,
|
|
166
|
+
* reporting `out_of_stock` per line item. Unset, stock is left to the
|
|
167
|
+
* backend.
|
|
168
|
+
*/
|
|
169
|
+
inventory?: ACPInventoryOptions;
|
|
52
170
|
/**
|
|
53
171
|
* How long checkout completion waits for the placed checkout to become
|
|
54
172
|
* `readyForFinalization` (i.e. its payment authorized, e.g. by a PSP
|
|
55
|
-
* webhook) before answering `
|
|
173
|
+
* webhook) before answering `complete_in_progress`. Defaults to 10s timeout,
|
|
56
174
|
* polled every 1s; a timeout of 0 disables it.
|
|
57
175
|
*/
|
|
58
176
|
paymentAuthorizationWait?: Partial<ACPPaymentAuthorizationWait>;
|
|
59
177
|
}
|
|
178
|
+
export interface ACPInventoryOptions {
|
|
179
|
+
fulfillmentCenterKeys: string[];
|
|
180
|
+
}
|
|
181
|
+
export interface ACPAuthenticationOptions {
|
|
182
|
+
getMetadata(context: {
|
|
183
|
+
checkoutSessionId: string;
|
|
184
|
+
handler: ACPPaymentHandler;
|
|
185
|
+
instrument: ACPPaymentData['instrument'];
|
|
186
|
+
amount: MonetaryAmount;
|
|
187
|
+
}): ACPAuthenticationMetadata | undefined | Promise<ACPAuthenticationMetadata | undefined>;
|
|
188
|
+
}
|
|
189
|
+
export interface ACPMarketingConsentChannel {
|
|
190
|
+
/** e.g. `email`, `sms`, `whatsapp`. */
|
|
191
|
+
channel: string;
|
|
192
|
+
/** What the buyer consents to receive. */
|
|
193
|
+
display_text: string;
|
|
194
|
+
privacy_policy_url: string;
|
|
195
|
+
}
|
|
196
|
+
export interface ACPMarketingConsentOptions {
|
|
197
|
+
channels: ACPMarketingConsentChannel[];
|
|
198
|
+
/**
|
|
199
|
+
* Whether the contact is already subscribed on the channel, so agents
|
|
200
|
+
* pre-check the box. Defaults to not subscribed.
|
|
201
|
+
*/
|
|
202
|
+
isSubscribed?(contact: string, channel: string): boolean | Promise<boolean>;
|
|
203
|
+
/**
|
|
204
|
+
* Receives the buyer's decisions for offered channels, with the contact
|
|
205
|
+
* they apply to. Channels the agent did not surface are left out, which
|
|
206
|
+
* preserves their current state.
|
|
207
|
+
*/
|
|
208
|
+
onConsents(consents: Array<{
|
|
209
|
+
channel: string;
|
|
210
|
+
opted_in: boolean;
|
|
211
|
+
contact: string;
|
|
212
|
+
}>, context: {
|
|
213
|
+
orderId: string;
|
|
214
|
+
checkoutSessionId: string;
|
|
215
|
+
agentId?: string;
|
|
216
|
+
}): void | Promise<void>;
|
|
217
|
+
}
|
|
218
|
+
/** An ACP fulfillment option type with its type-specific details. */
|
|
219
|
+
export type ACPFulfillmentClassification = {
|
|
220
|
+
type: 'shipping';
|
|
221
|
+
} | {
|
|
222
|
+
type: 'digital';
|
|
223
|
+
} | {
|
|
224
|
+
type: 'pickup';
|
|
225
|
+
location: {
|
|
226
|
+
name: string;
|
|
227
|
+
address: ACPAddress;
|
|
228
|
+
phone?: string;
|
|
229
|
+
instructions?: string;
|
|
230
|
+
};
|
|
231
|
+
pickup_type?: 'in_store' | 'curbside' | 'locker';
|
|
232
|
+
ready_by?: string;
|
|
233
|
+
pickup_by?: string;
|
|
234
|
+
} | {
|
|
235
|
+
type: 'local_delivery';
|
|
236
|
+
delivery_window?: {
|
|
237
|
+
start: string;
|
|
238
|
+
end: string;
|
|
239
|
+
};
|
|
240
|
+
service_area?: Record<string, unknown>;
|
|
241
|
+
};
|
|
242
|
+
/** An authenticated agent (platform) calling the checkout API. */
|
|
243
|
+
export interface ACPAgent {
|
|
244
|
+
id: string;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Authenticates agents by `Authorization: Bearer <token>`, given each
|
|
248
|
+
* agent's token. Tokens are compared in constant time.
|
|
249
|
+
*/
|
|
250
|
+
export declare function createBearerTokenAuthenticator(tokensByAgentId: Record<string, string>): (request: Request) => ACPAgent | undefined;
|
|
251
|
+
export interface ACPInterventionOptions {
|
|
252
|
+
supported: ACPInterventionType[];
|
|
253
|
+
required?: Array<'3ds' | 'biometric'>;
|
|
254
|
+
/** When required interventions apply. Defaults to `conditional`. */
|
|
255
|
+
enforcement?: 'always' | 'conditional' | 'optional';
|
|
256
|
+
}
|
|
60
257
|
export declare const DEFAULT_ACP_PLACEHOLDER_EMAIL = "pending@checkout.invalid";
|
|
61
258
|
export interface ACPPaymentAuthorizationWait {
|
|
62
259
|
timeoutMs: number;
|
|
@@ -64,11 +261,14 @@ export interface ACPPaymentAuthorizationWait {
|
|
|
64
261
|
}
|
|
65
262
|
export declare const DEFAULT_ACP_PAYMENT_AUTHORIZATION_WAIT: ACPPaymentAuthorizationWait;
|
|
66
263
|
export interface ACPDiscoveryOptions {
|
|
67
|
-
apiVersion?: string;
|
|
68
|
-
supportedVersions?: string[];
|
|
69
264
|
apiBaseUrl?: string;
|
|
70
265
|
documentationUrl?: string;
|
|
71
266
|
supportedCurrencies?: string[];
|
|
267
|
+
/**
|
|
268
|
+
* BCP 47 locales the backend can localize for. Advertised in discovery,
|
|
269
|
+
* and checkout requests are localized to the best match of their
|
|
270
|
+
* Accept-Language.
|
|
271
|
+
*/
|
|
72
272
|
supportedLocales?: string[];
|
|
73
273
|
}
|
|
74
274
|
export interface ACPDiscoveryResponse {
|
|
@@ -79,34 +279,30 @@ export interface ACPDiscoveryResponse {
|
|
|
79
279
|
documentation_url?: string;
|
|
80
280
|
};
|
|
81
281
|
api_base_url: string;
|
|
82
|
-
transports:
|
|
282
|
+
transports: Array<'rest' | 'mcp'>;
|
|
83
283
|
capabilities: {
|
|
84
|
-
services: Array<'checkout' | '
|
|
284
|
+
services: Array<'checkout' | 'orders' | 'delegate_payment' | 'carts'>;
|
|
285
|
+
extensions?: ACPDiscoveryExtension[];
|
|
286
|
+
intervention_types?: ACPInterventionType[];
|
|
85
287
|
supported_currencies?: string[];
|
|
86
288
|
supported_locales?: string[];
|
|
87
289
|
};
|
|
88
290
|
}
|
|
89
|
-
|
|
90
|
-
export interface
|
|
91
|
-
|
|
92
|
-
|
|
291
|
+
/** An extension the seller supports, as listed in discovery. */
|
|
292
|
+
export interface ACPDiscoveryExtension {
|
|
293
|
+
name: string;
|
|
294
|
+
spec?: string;
|
|
295
|
+
schema?: string;
|
|
93
296
|
}
|
|
297
|
+
/** The only ACP API version this adapter implements. */
|
|
298
|
+
export declare const ACP_API_VERSION = "2026-04-17";
|
|
299
|
+
/** A policy or support link shown with the checkout (2026-04-17 Link). */
|
|
94
300
|
export interface ACPLink {
|
|
95
|
-
type: 'terms_of_use' | 'privacy_policy' | '
|
|
301
|
+
type: 'terms_of_use' | 'privacy_policy' | 'return_policy' | 'shipping_policy' | 'contact_us' | 'about_us' | 'faq' | 'support';
|
|
302
|
+
/** Display text for the link. */
|
|
303
|
+
title?: string;
|
|
96
304
|
url: string;
|
|
97
305
|
}
|
|
98
|
-
export interface ACPProductFeedOptions extends ReactionaryFeedInventoryOptions, ReactionaryFeedProcessingOptions {
|
|
99
|
-
feeds: Record<string, ACPProductFeedDefinition>;
|
|
100
|
-
}
|
|
101
|
-
export interface ACPProductFeedDefinition {
|
|
102
|
-
languageContext: LanguageContext;
|
|
103
|
-
search: SearchIdentifier;
|
|
104
|
-
pageSize?: number;
|
|
105
|
-
maxPages?: number;
|
|
106
|
-
productUrlBase?: string;
|
|
107
|
-
fulfillmentCenterKeys?: string[];
|
|
108
|
-
fulfillmentCenterKey?: string;
|
|
109
|
-
}
|
|
110
306
|
export interface ReactionaryACPHttpHandler {
|
|
111
307
|
fetch(request: Request): Promise<Response>;
|
|
112
308
|
close(): Promise<void>;
|
|
@@ -117,36 +313,81 @@ export declare class ReactionaryACPServer<TClient extends ReactionaryACPClient =
|
|
|
117
313
|
private readonly options;
|
|
118
314
|
private readonly sessionStore;
|
|
119
315
|
private readonly checkoutSessionStore;
|
|
316
|
+
private readonly idempotency;
|
|
317
|
+
private readonly webhooks;
|
|
318
|
+
private readonly supportsDiscounts;
|
|
319
|
+
private readonly mcp;
|
|
120
320
|
constructor(clientFactory: ReactionaryACPClientFactory<TClient>, options?: ReactionaryACPServerOptions);
|
|
121
321
|
fetch(request: Request): Promise<Response>;
|
|
122
322
|
private handleFetch;
|
|
323
|
+
/**
|
|
324
|
+
* Checkout endpoints require an authenticated agent (checkout RFC §3.1),
|
|
325
|
+
* and a checkout session is visible only to the agent that created it, so
|
|
326
|
+
* another agent's session is reported as missing. Discovery and the
|
|
327
|
+
* readiness document stay public.
|
|
328
|
+
*/
|
|
329
|
+
private authenticate;
|
|
123
330
|
/**
|
|
124
331
|
* Requests addressing a checkout session resume the session that created
|
|
125
332
|
* it: agents need not echo the ACP session header, but backends scope carts
|
|
126
333
|
* to that session's (anonymous) identity.
|
|
127
334
|
*/
|
|
128
335
|
private resolveSessionId;
|
|
336
|
+
/**
|
|
337
|
+
* The best supported locale for the request's Accept-Language: an exact
|
|
338
|
+
* tag, else one of the same language. Only locales advertised in
|
|
339
|
+
* `discovery.supportedLocales` are used, as backends may not localize
|
|
340
|
+
* others.
|
|
341
|
+
*/
|
|
342
|
+
private resolveLocale;
|
|
343
|
+
/**
|
|
344
|
+
* The currency a checkout session is priced in: the one requested on its
|
|
345
|
+
* creation, which later requests for the session keep using.
|
|
346
|
+
*/
|
|
347
|
+
private resolveCheckoutCurrency;
|
|
348
|
+
/**
|
|
349
|
+
* Sends an `order_update` event with the order's current state, e.g. when
|
|
350
|
+
* the OMS ships or cancels it. Returns false for orders not placed through
|
|
351
|
+
* an ACP checkout session, or when webhooks are not configured.
|
|
352
|
+
*/
|
|
353
|
+
notifyOrderUpdated(orderId: string): Promise<boolean>;
|
|
129
354
|
getHandler(): ReactionaryACPHttpHandler;
|
|
130
355
|
toNodeHandler(): ReactionaryACPNodeRequestHandler;
|
|
131
356
|
close(): Promise<void>;
|
|
132
357
|
private createRequestContext;
|
|
133
358
|
private handleRequest;
|
|
359
|
+
/**
|
|
360
|
+
* The cart capability (cart RFC): pre-checkout baskets over a backend
|
|
361
|
+
* cart. Carts have no status — they exist, or answer 404 once canceled or
|
|
362
|
+
* expired — and no payment or negotiation, which belong to checkout.
|
|
363
|
+
*/
|
|
364
|
+
private handleCartRequest;
|
|
365
|
+
private getCartExpiry;
|
|
366
|
+
/** A cart's authoritative state; totals are estimates without an address. */
|
|
367
|
+
private toACPCart;
|
|
134
368
|
private getDiscoveryDocument;
|
|
369
|
+
/** The extensions the server implements; extension PRs add theirs here. */
|
|
370
|
+
private getDiscoveryExtensions;
|
|
135
371
|
private getReadinessDocument;
|
|
136
|
-
private getProductFeed;
|
|
137
|
-
private getRequestedProductFeed;
|
|
138
|
-
private getProductFeedDefinition;
|
|
139
372
|
private handlePost;
|
|
140
373
|
private createCheckoutSession;
|
|
141
374
|
private updateCheckoutSession;
|
|
142
375
|
private getCheckoutSession;
|
|
143
376
|
/**
|
|
144
377
|
* Creates the real checkout from the session state and finalizes it. A
|
|
145
|
-
* payment the PSP has not authorized yet leaves the session
|
|
378
|
+
* payment the PSP has not authorized yet leaves the session
|
|
379
|
+
* `complete_in_progress`, without an order yet;
|
|
146
380
|
* a repeated complete retries finalization.
|
|
147
381
|
*/
|
|
148
382
|
private completeCheckoutSession;
|
|
149
383
|
private cancelCheckoutSession;
|
|
384
|
+
/**
|
|
385
|
+
* Gives the session's cart exactly the requested items (line items are a
|
|
386
|
+
* full replacement), updating it in place where the backend supports it.
|
|
387
|
+
* Otherwise a new cart replaces it and the old one is deleted, if possible.
|
|
388
|
+
* Returns the cart key.
|
|
389
|
+
*/
|
|
390
|
+
private replaceCartItems;
|
|
150
391
|
private createCartForItems;
|
|
151
392
|
private getRequiredCheckoutSessionState;
|
|
152
393
|
private placeCheckout;
|
|
@@ -158,6 +399,69 @@ export declare class ReactionaryACPServer<TClient extends ReactionaryACPClient =
|
|
|
158
399
|
*/
|
|
159
400
|
private priceSession;
|
|
160
401
|
private toACPCheckoutSession;
|
|
402
|
+
private classifyFulfillmentOption;
|
|
403
|
+
/**
|
|
404
|
+
* Whether the discount extension is active for a session: the backend can
|
|
405
|
+
* apply coupons, and the agent declared the extension.
|
|
406
|
+
*/
|
|
407
|
+
private isDiscountExtensionActive;
|
|
408
|
+
/** Applies submitted discount codes, when the extension is active. */
|
|
409
|
+
private applyRequestedDiscounts;
|
|
410
|
+
/**
|
|
411
|
+
* 3D Secure (checkout RFC §4.4): when the authentication hook asks for it,
|
|
412
|
+
* the first completion answers `authentication_required` with the
|
|
413
|
+
* metadata; completing such a session without `authentication_result` is
|
|
414
|
+
* a 4XX `requires_3ds`. Failed or refused authentications are not
|
|
415
|
+
* authorized. Returns a response when completion must stop here.
|
|
416
|
+
*/
|
|
417
|
+
private checkAuthentication;
|
|
418
|
+
/**
|
|
419
|
+
* Records an order placed through a session once, and announces it to the
|
|
420
|
+
* creating agent's webhook receiver.
|
|
421
|
+
*/
|
|
422
|
+
private recordOrder;
|
|
423
|
+
/**
|
|
424
|
+
* Reports the order's affiliate attribution once it exists: first touch
|
|
425
|
+
* from the session's creation, last touch from its completion. A failing
|
|
426
|
+
* hook never blocks the checkout.
|
|
427
|
+
*/
|
|
428
|
+
private reportAttribution;
|
|
429
|
+
/**
|
|
430
|
+
* Passes the buyer's consent decisions on, once the order exists. Only
|
|
431
|
+
* offered channels with a resolvable contact count: email uses the buyer's
|
|
432
|
+
* email, falling back to the fulfillment email; sms and whatsapp the phone
|
|
433
|
+
* likewise (marketing consent RFC §3.5). Omitted channels are not consent.
|
|
434
|
+
*/
|
|
435
|
+
private reportMarketingConsents;
|
|
436
|
+
/** The offered marketing channels, with the buyer's subscription state. */
|
|
437
|
+
private getMarketingConsentOptions;
|
|
438
|
+
private sendOrderEvent;
|
|
439
|
+
/** The full current order (webhooks carry the whole order, not deltas). */
|
|
440
|
+
private toACPOrder;
|
|
441
|
+
/**
|
|
442
|
+
* The advertised handler a completion pays with. Sellers MUST check the
|
|
443
|
+
* handler is one they declared (sellers guide, "Complete a checkout
|
|
444
|
+
* session"), and raw card numbers are refused unless explicitly accepted,
|
|
445
|
+
* so they never reach the backend's persisted payment data.
|
|
446
|
+
*/
|
|
447
|
+
private resolvePaymentHandler;
|
|
448
|
+
/**
|
|
449
|
+
* The seller's capabilities for a session: interventions are the
|
|
450
|
+
* intersection of what the agent declared and what the seller supports,
|
|
451
|
+
* plus the seller's requirements (capability negotiation RFC §4.5.1).
|
|
452
|
+
*/
|
|
453
|
+
private getNegotiatedCapabilities;
|
|
454
|
+
/**
|
|
455
|
+
* An out_of_stock error per line item requesting more than the configured
|
|
456
|
+
* fulfillment centers hold (as in the UCP adapter). Back-ordered and
|
|
457
|
+
* pre-ordered items are always purchasable; without configured centers,
|
|
458
|
+
* stock is left to the backend.
|
|
459
|
+
*/
|
|
460
|
+
private getStockMessages;
|
|
461
|
+
/**
|
|
462
|
+
* Required interventions the agent cannot perform block the session when
|
|
463
|
+
* they always apply (checkout RFC §5, intervention_required).
|
|
464
|
+
*/
|
|
465
|
+
private getInterventionMessages;
|
|
161
466
|
private getPlacedView;
|
|
162
|
-
private getPaymentProvider;
|
|
163
467
|
}
|