@base44-preview/sdk 0.8.53-pr.331.bf2d5aa → 0.8.54-pr.316.81dc6f9
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 +1 -0
- package/dist/client.js +3 -0
- package/dist/client.types.d.ts +5 -0
- package/dist/index.d.ts +1 -0
- package/dist/modules/app.types.d.ts +38 -21
- package/dist/modules/payments-checkout.d.ts +31 -0
- package/dist/modules/payments-checkout.js +235 -0
- package/dist/modules/payments.d.ts +20 -0
- package/dist/modules/payments.js +79 -0
- package/dist/modules/payments.types.d.ts +626 -0
- package/dist/modules/payments.types.js +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -29,6 +29,7 @@ The SDK provides access to Base44's functionality through the following modules:
|
|
|
29
29
|
- **[`entities`](https://docs.base44.com/developers/references/sdk/docs/interfaces/entities)**: Work with your app's data entities using CRUD operations.
|
|
30
30
|
- **[`functions`](https://docs.base44.com/developers/references/sdk/docs/interfaces/functions)**: Execute backend functions.
|
|
31
31
|
- **[`integrations`](https://docs.base44.com/developers/references/sdk/docs/type-aliases/integrations)**: Access pre-built and third-party integrations.
|
|
32
|
+
- **[`payments`](https://docs.base44.com/developers/references/sdk/docs/interfaces/payments)**: Embed checkouts, look up purchases, and handle refunds and subscriptions with the service role.
|
|
32
33
|
|
|
33
34
|
## Quickstarts
|
|
34
35
|
|
package/dist/client.js
CHANGED
|
@@ -14,6 +14,7 @@ import { createAppModule } from "./modules/app.js";
|
|
|
14
14
|
import { createUsersModule } from "./modules/users.js";
|
|
15
15
|
import { RoomsSocket } from "./utils/socket-utils.js";
|
|
16
16
|
import { createAnalyticsModule } from "./modules/analytics.js";
|
|
17
|
+
import { createPaymentsModule, createServiceRolePaymentsModule, } from "./modules/payments.js";
|
|
17
18
|
import { createActorsModule, resolveActorsHost, } from "./modules/actors.js";
|
|
18
19
|
/**
|
|
19
20
|
* Creates a Base44 client.
|
|
@@ -202,6 +203,7 @@ export function createClient(config) {
|
|
|
202
203
|
appLogs: createAppLogsModule(axiosClient, appId),
|
|
203
204
|
app: createAppModule(axiosClient, appId),
|
|
204
205
|
users: createUsersModule(axiosClient, appId),
|
|
206
|
+
payments: createPaymentsModule(axiosClient, appId),
|
|
205
207
|
analytics: createAnalyticsModule({
|
|
206
208
|
axiosClient,
|
|
207
209
|
serverUrl,
|
|
@@ -252,6 +254,7 @@ export function createClient(config) {
|
|
|
252
254
|
headers: aiGatewayHeaders,
|
|
253
255
|
}),
|
|
254
256
|
appLogs: createAppLogsModule(serviceRoleAxiosClient, appId),
|
|
257
|
+
payments: createServiceRolePaymentsModule(serviceRoleAxiosClient, appId),
|
|
255
258
|
cleanup: () => {
|
|
256
259
|
if (socket) {
|
|
257
260
|
socket.disconnect();
|
package/dist/client.types.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { EntitiesModule } from "./modules/entities.types.js";
|
|
|
2
2
|
import type { IntegrationsModule } from "./modules/integrations.types.js";
|
|
3
3
|
import type { AuthModule } from "./modules/auth.types.js";
|
|
4
4
|
import type { SsoModule } from "./modules/sso.types.js";
|
|
5
|
+
import type { PaymentsModule, ServiceRolePaymentsModule } from "./modules/payments.types.js";
|
|
5
6
|
import type { ConnectorsModule, UserConnectorsModule } from "./modules/connectors.types.js";
|
|
6
7
|
import type { FunctionsModule } from "./modules/functions.types.js";
|
|
7
8
|
import type { AgentsModule } from "./modules/agents.types.js";
|
|
@@ -138,6 +139,8 @@ export interface Base44Client {
|
|
|
138
139
|
functions: FunctionsModule;
|
|
139
140
|
/** {@link IntegrationsModule | Integrations module} for calling pre-built integration endpoints. */
|
|
140
141
|
integrations: IntegrationsModule;
|
|
142
|
+
/** {@link PaymentsModule | Payments module} for checkouts and purchases. */
|
|
143
|
+
payments: PaymentsModule;
|
|
141
144
|
/** Cleanup function to disconnect WebSocket connections. Call when you're done with the client. */
|
|
142
145
|
cleanup: () => void;
|
|
143
146
|
/**
|
|
@@ -233,6 +236,8 @@ export interface Base44Client {
|
|
|
233
236
|
functions: FunctionsModule;
|
|
234
237
|
/** {@link IntegrationsModule | Integrations module} with elevated permissions. */
|
|
235
238
|
integrations: IntegrationsModule;
|
|
239
|
+
/** {@link ServiceRolePaymentsModule | Payments module} for creating checkouts, refunds, and subscription changes. */
|
|
240
|
+
payments: ServiceRolePaymentsModule;
|
|
236
241
|
/** {@link SsoModule | SSO module} for generating SSO tokens. */
|
|
237
242
|
sso: SsoModule;
|
|
238
243
|
/** Cleanup function to disconnect WebSocket connections. */
|
package/dist/index.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export type { AppLogsModule } from "./modules/app-logs.types.js";
|
|
|
14
14
|
export type { AppModule, AppPublicSettings, AppPublicSettingsResponse, } from "./modules/app.types.js";
|
|
15
15
|
export type { ActorsModule, ActorClient, ActorRef, Connection, ActorSubscription, ActorConnectOptions, ActorNameRegistry, ActorRegistry, } from "./modules/actors.types.js";
|
|
16
16
|
export type { SsoModule, SsoAccessTokenResponse } from "./modules/sso.types.js";
|
|
17
|
+
export type { PaymentsModule, ServiceRolePaymentsModule, PaymentsErrorCode, PaymentsRecurringFrequency, CheckoutBuyer, CheckoutFreeTrial, CheckoutItem, CheckoutItemRecurring, CheckoutPresentation, CheckoutElement, CheckoutMount, MountableCheckout, CreateCheckoutParams, CreateCheckoutResult, CompleteCheckoutResult, EmbeddedCheckout, PayPalEmbeddedCheckout, StripeEmbeddedCheckout, MountCheckoutOptions, ListPurchasesParams, ServiceRoleListPurchasesParams, ListPurchasesResult, Purchase, PurchaseItem, PurchaseStatus, RefundParams, RefundResult, CancelSubscriptionOptions, SubscriptionResult, } from "./modules/payments.types.js";
|
|
17
18
|
export { Actor, type Conn } from "./actor.js";
|
|
18
19
|
export type { ConnectorsModule, UserConnectorsModule, ConnectorApiRequest, ConnectorApiResponse, ConnectorApiResponsePhase, } from "./modules/connectors.types.js";
|
|
19
20
|
export type { CustomIntegrationsModule, CustomIntegrationCallParams, CustomIntegrationCallResponse, } from "./modules/custom-integrations.types.js";
|
|
@@ -1,49 +1,66 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The app's access
|
|
3
|
-
*
|
|
2
|
+
* The app's [visibility](/Setting-up-your-app/Managing-access#setting-your-app-visibility).
|
|
3
|
+
*
|
|
4
|
+
* You can set and manage the app's visibility in the app's dashboard or with the Base44 CLI [`visibility`](/developers/references/cli/commands/visibility) command.
|
|
5
|
+
*
|
|
6
|
+
* The following table shows the supported values and the visibility each one represents:
|
|
7
|
+
*
|
|
8
|
+
* | Value | Visibility |
|
|
9
|
+
* | --- | --- |
|
|
10
|
+
* | `private_with_login` | **Private**: Only [invited users](/Setting-up-your-app/Managing-access#inviting-users-to-your-app) |
|
|
11
|
+
* | `workspace_with_login` | **Workspace**: Users in your Base44 [workspace](/documentation/account-and-billing/about-workspaces) |
|
|
12
|
+
* | `public_with_login` | **Public (login required)**: Visitors must log in |
|
|
13
|
+
* | `public_without_login` | **Public (no login)**: Anyone |
|
|
14
|
+
*
|
|
15
|
+
* <Note>
|
|
16
|
+
* If your workspace [enforces SSO for apps](/Enterprise/Enterprise-SSO-and-app-visibility), apps set to `public_without_login` also require sign-in.
|
|
17
|
+
* </Note>
|
|
4
18
|
*/
|
|
5
19
|
export type AppPublicSettings = "private_with_login" | "public_with_login" | "public_without_login" | "workspace_with_login" | string;
|
|
6
20
|
/**
|
|
7
|
-
* The app's public
|
|
21
|
+
* The app's public settings.
|
|
8
22
|
*/
|
|
9
23
|
export interface AppPublicSettingsResponse {
|
|
10
24
|
/** The app's ID. */
|
|
11
25
|
id: string;
|
|
12
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* The app's visibility.
|
|
28
|
+
* For supported values, see [`AppPublicSettings`](#apppublicsettings).
|
|
29
|
+
*/
|
|
13
30
|
public_settings: AppPublicSettings;
|
|
14
31
|
}
|
|
15
32
|
/**
|
|
16
|
-
* App module for reading
|
|
33
|
+
* App module for reading an app's public settings.
|
|
34
|
+
*
|
|
35
|
+
* Use it to read the app's visibility and determine whether the current visitor can access the app.
|
|
36
|
+
* If the app requires login, use `redirectToLogin()` from the {@link AuthModule | auth module} to send the visitor to the login page.
|
|
17
37
|
*
|
|
18
|
-
*
|
|
19
|
-
* can send the visitor to login instead of rendering an empty shell.
|
|
38
|
+
* Learn more about [app visibility](/Setting-up-your-app/Managing-access#setting-your-app-visibility).
|
|
20
39
|
*
|
|
21
|
-
* ## Authentication
|
|
40
|
+
* ## Authentication modes
|
|
22
41
|
*
|
|
23
|
-
*
|
|
24
|
-
* client's token, when it has one, is sent with the request — a signed-in visitor
|
|
25
|
-
* who has no access to the app is reported differently from an anonymous one.
|
|
42
|
+
* You can use this module with a client in any authentication mode. The client sends its token, if it has one, with the request.
|
|
26
43
|
*/
|
|
27
44
|
export interface AppModule {
|
|
28
45
|
/**
|
|
29
|
-
*
|
|
46
|
+
* Retrieves the app's public settings.
|
|
30
47
|
*
|
|
31
|
-
* Rejects with a {@linkcode Base44Error} when the visitor
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* visitor
|
|
48
|
+
* Rejects with a {@linkcode Base44Error} that has a `status` of `403` when the visitor can't access the app.
|
|
49
|
+
* Check `data.extra_data.reason` to find the cause:
|
|
50
|
+
* - `auth_required`: The visitor must sign in.
|
|
51
|
+
* - `user_not_registered`: The visitor is signed in but doesn't have access.
|
|
35
52
|
*
|
|
36
|
-
* @returns Promise resolving to the app's ID and
|
|
53
|
+
* @returns Promise resolving to the app's ID and visibility.
|
|
37
54
|
*
|
|
38
55
|
* @example
|
|
39
56
|
* ```typescript
|
|
40
|
-
* //
|
|
57
|
+
* // Redirect a visitor who isn't signed in
|
|
41
58
|
* try {
|
|
42
59
|
* const { public_settings } = await base44.app.getPublicSettings();
|
|
43
|
-
* console.log('App
|
|
60
|
+
* console.log('App visibility:', public_settings);
|
|
44
61
|
* } catch (error) {
|
|
45
|
-
* if (error.status === 403) {
|
|
46
|
-
*
|
|
62
|
+
* if (error.status === 403 && error.data?.extra_data?.reason === 'auth_required') {
|
|
63
|
+
* base44.auth.redirectToLogin('<URL to return to after login>');
|
|
47
64
|
* }
|
|
48
65
|
* }
|
|
49
66
|
* ```
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { CheckoutElement, CheckoutMount, CompleteCheckoutResult, MountableCheckout, MountCheckoutOptions } from "./payments.types.js";
|
|
2
|
+
/** @internal */
|
|
3
|
+
export type LoadScript = (src: string) => Promise<void>;
|
|
4
|
+
/**
|
|
5
|
+
* The response of `GET /payments/config`.
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
export interface PaymentsCheckoutConfig {
|
|
9
|
+
paypal?: {
|
|
10
|
+
script_url?: string;
|
|
11
|
+
};
|
|
12
|
+
stripe?: {
|
|
13
|
+
script_url?: string;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/** @internal */
|
|
17
|
+
export interface MountCheckoutDeps {
|
|
18
|
+
completeCheckout: (checkoutId: string) => Promise<CompleteCheckoutResult>;
|
|
19
|
+
getConfig: () => Promise<PaymentsCheckoutConfig>;
|
|
20
|
+
loadScript: LoadScript;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Appends a script tag once per URL and resolves when it loads.
|
|
24
|
+
* @internal
|
|
25
|
+
*/
|
|
26
|
+
export declare const loadScript: LoadScript;
|
|
27
|
+
/**
|
|
28
|
+
* Mounts the embedded checkout that createCheckout() returned.
|
|
29
|
+
* @internal
|
|
30
|
+
*/
|
|
31
|
+
export declare function mountCheckout(element: CheckoutElement, checkout: MountableCheckout, options: MountCheckoutOptions, deps: MountCheckoutDeps): Promise<CheckoutMount>;
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
// The backend picks each script URL, but the script runs on the buyer's page, so only these hosts may load.
|
|
2
|
+
const ALLOWED_SCRIPT_HOSTS = {
|
|
3
|
+
paypal: ["www.paypal.com", "www.sandbox.paypal.com"],
|
|
4
|
+
stripe: ["js.stripe.com"],
|
|
5
|
+
};
|
|
6
|
+
async function scriptUrlFor(provider, deps) {
|
|
7
|
+
var _a, _b;
|
|
8
|
+
const value = (_b = (_a = (await deps.getConfig())) === null || _a === void 0 ? void 0 : _a[provider]) === null || _b === void 0 ? void 0 : _b.script_url;
|
|
9
|
+
let url;
|
|
10
|
+
try {
|
|
11
|
+
url = value ? new URL(value) : undefined;
|
|
12
|
+
}
|
|
13
|
+
catch (_c) {
|
|
14
|
+
url = undefined;
|
|
15
|
+
}
|
|
16
|
+
if (!url ||
|
|
17
|
+
url.protocol !== "https:" ||
|
|
18
|
+
url.port !== "" ||
|
|
19
|
+
url.username !== "" ||
|
|
20
|
+
url.password !== "" ||
|
|
21
|
+
!ALLOWED_SCRIPT_HOSTS[provider].includes(url.hostname)) {
|
|
22
|
+
const name = provider === "paypal" ? "PayPal" : "Stripe";
|
|
23
|
+
throw new Error(`The payments config has no valid ${name} script URL`);
|
|
24
|
+
}
|
|
25
|
+
return url.href;
|
|
26
|
+
}
|
|
27
|
+
function browserGlobals() {
|
|
28
|
+
return window;
|
|
29
|
+
}
|
|
30
|
+
const scriptLoads = new Map();
|
|
31
|
+
/**
|
|
32
|
+
* Appends a script tag once per URL and resolves when it loads.
|
|
33
|
+
* @internal
|
|
34
|
+
*/
|
|
35
|
+
export const loadScript = (src) => {
|
|
36
|
+
let load = scriptLoads.get(src);
|
|
37
|
+
if (!load) {
|
|
38
|
+
load = new Promise((resolve, reject) => {
|
|
39
|
+
const script = document.createElement("script");
|
|
40
|
+
script.src = src;
|
|
41
|
+
script.async = true;
|
|
42
|
+
script.onload = () => resolve();
|
|
43
|
+
script.onerror = () => {
|
|
44
|
+
// Forget the failure so a later mount can retry.
|
|
45
|
+
scriptLoads.delete(src);
|
|
46
|
+
script.remove();
|
|
47
|
+
reject(new Error(`Failed to load ${src}`));
|
|
48
|
+
};
|
|
49
|
+
document.head.appendChild(script);
|
|
50
|
+
});
|
|
51
|
+
scriptLoads.set(src, load);
|
|
52
|
+
}
|
|
53
|
+
return load;
|
|
54
|
+
};
|
|
55
|
+
async function loadGlobal(src, read, load) {
|
|
56
|
+
if (!read()) {
|
|
57
|
+
await load(src);
|
|
58
|
+
}
|
|
59
|
+
const value = read();
|
|
60
|
+
if (!value) {
|
|
61
|
+
throw new Error(`${src} loaded but didn't define its global`);
|
|
62
|
+
}
|
|
63
|
+
return value;
|
|
64
|
+
}
|
|
65
|
+
// Stripe asks for a single Stripe instance per key.
|
|
66
|
+
const stripeInstances = new Map();
|
|
67
|
+
// Stripe allows one Embedded Checkout at a time, so mounts run in order and replace the last.
|
|
68
|
+
let stripeQueue = Promise.resolve();
|
|
69
|
+
let activeStripeCheckout = null;
|
|
70
|
+
function mountStripe(element, scriptUrl, embedded, deps) {
|
|
71
|
+
const mount = stripeQueue.then(async () => {
|
|
72
|
+
var _a;
|
|
73
|
+
const Stripe = await loadGlobal(scriptUrl, () => browserGlobals().Stripe, deps.loadScript);
|
|
74
|
+
let stripe = stripeInstances.get(embedded.publishable_key);
|
|
75
|
+
if (!stripe) {
|
|
76
|
+
stripe = Stripe(embedded.publishable_key);
|
|
77
|
+
stripeInstances.set(embedded.publishable_key, stripe);
|
|
78
|
+
}
|
|
79
|
+
// Try the pre-dahlia name first, since dahlia and later reject the ui_mode Base44 sessions use.
|
|
80
|
+
// A newer Stripe.js that the app loaded itself is still tried rather than refused.
|
|
81
|
+
const create = (_a = stripe.initEmbeddedCheckout) !== null && _a !== void 0 ? _a : stripe.createEmbeddedCheckoutPage;
|
|
82
|
+
if (typeof create !== "function") {
|
|
83
|
+
throw new Error("Stripe.js doesn't support Embedded Checkout");
|
|
84
|
+
}
|
|
85
|
+
activeStripeCheckout === null || activeStripeCheckout === void 0 ? void 0 : activeStripeCheckout.destroy();
|
|
86
|
+
const checkout = await create.call(stripe, {
|
|
87
|
+
fetchClientSecret: () => Promise.resolve(embedded.client_secret),
|
|
88
|
+
});
|
|
89
|
+
try {
|
|
90
|
+
checkout.mount(element);
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
checkout.destroy();
|
|
94
|
+
throw error;
|
|
95
|
+
}
|
|
96
|
+
let destroyed = false;
|
|
97
|
+
const handle = {
|
|
98
|
+
destroy() {
|
|
99
|
+
if (destroyed)
|
|
100
|
+
return;
|
|
101
|
+
destroyed = true;
|
|
102
|
+
if (activeStripeCheckout === handle)
|
|
103
|
+
activeStripeCheckout = null;
|
|
104
|
+
checkout.destroy();
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
activeStripeCheckout = handle;
|
|
108
|
+
return handle;
|
|
109
|
+
});
|
|
110
|
+
stripeQueue = mount.catch(() => undefined);
|
|
111
|
+
return mount;
|
|
112
|
+
}
|
|
113
|
+
async function mountPayPal(element, scriptUrl, checkoutId, currency, embedded, options, deps) {
|
|
114
|
+
var _a;
|
|
115
|
+
const paypal = await loadGlobal(scriptUrl, () => browserGlobals().paypal, deps.loadScript);
|
|
116
|
+
if (typeof paypal.createInstance !== "function") {
|
|
117
|
+
throw new Error("Another PayPal JS SDK version is already loaded on this page. Remove it to use mountCheckout().");
|
|
118
|
+
}
|
|
119
|
+
const subscription = embedded.intent === "subscription";
|
|
120
|
+
const sdk = await paypal.createInstance({
|
|
121
|
+
clientId: embedded.client_id,
|
|
122
|
+
merchantId: embedded.merchant_id,
|
|
123
|
+
// Sent only when set, since the backend returns null when no attribution ID is configured.
|
|
124
|
+
...(embedded.partner_attribution_id
|
|
125
|
+
? { partnerAttributionId: embedded.partner_attribution_id }
|
|
126
|
+
: {}),
|
|
127
|
+
components: [subscription ? "paypal-subscriptions" : "paypal-payments"],
|
|
128
|
+
pageType: "checkout",
|
|
129
|
+
});
|
|
130
|
+
const methods = await sdk.findEligibleMethods({
|
|
131
|
+
currencyCode: currency.toUpperCase(),
|
|
132
|
+
...(subscription ? { paymentFlow: "RECURRING_PAYMENT" } : {}),
|
|
133
|
+
});
|
|
134
|
+
if (!methods.isEligible("paypal")) {
|
|
135
|
+
throw new Error("PayPal isn't available for this checkout");
|
|
136
|
+
}
|
|
137
|
+
const createSession = subscription
|
|
138
|
+
? (_a = sdk.createPayPalSubscriptionPaymentSession) !== null && _a !== void 0 ? _a : sdk.createPayPalSubscriptionSession
|
|
139
|
+
: sdk.createPayPalOneTimePaymentSession;
|
|
140
|
+
if (typeof createSession !== "function") {
|
|
141
|
+
throw new Error("The loaded PayPal JS SDK can't create this checkout");
|
|
142
|
+
}
|
|
143
|
+
let destroyed = false;
|
|
144
|
+
let completing = false;
|
|
145
|
+
// App callbacks run only while mounted, and their own errors never reach PayPal or onError.
|
|
146
|
+
const notify = (callback) => {
|
|
147
|
+
if (destroyed)
|
|
148
|
+
return;
|
|
149
|
+
try {
|
|
150
|
+
callback();
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
console.error("[Base44 SDK] A mountCheckout() callback threw", error);
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
const button = document.createElement("paypal-button");
|
|
157
|
+
const session = createSession.call(sdk, {
|
|
158
|
+
// Errors are reported here, not rethrown, so PayPal doesn't report them a second time.
|
|
159
|
+
async onApprove() {
|
|
160
|
+
completing = true;
|
|
161
|
+
button.disabled = true;
|
|
162
|
+
let result;
|
|
163
|
+
try {
|
|
164
|
+
// Runs even after destroy(), so an approved payment is still captured.
|
|
165
|
+
result = await deps.completeCheckout(checkoutId);
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
// Re-enabled only on failure, since a paid order can't be approved again.
|
|
169
|
+
completing = false;
|
|
170
|
+
button.disabled = false;
|
|
171
|
+
notify(() => { var _a; return (_a = options.onError) === null || _a === void 0 ? void 0 : _a.call(options, error); });
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
completing = false;
|
|
175
|
+
notify(() => { var _a; return (_a = options.onComplete) === null || _a === void 0 ? void 0 : _a.call(options, result); });
|
|
176
|
+
},
|
|
177
|
+
onCancel() {
|
|
178
|
+
notify(() => { var _a; return (_a = options.onCancel) === null || _a === void 0 ? void 0 : _a.call(options); });
|
|
179
|
+
},
|
|
180
|
+
onError(error) {
|
|
181
|
+
notify(() => { var _a; return (_a = options.onError) === null || _a === void 0 ? void 0 : _a.call(options, error); });
|
|
182
|
+
},
|
|
183
|
+
});
|
|
184
|
+
button.setAttribute("type", subscription ? "subscribe" : "pay");
|
|
185
|
+
const onClick = () => {
|
|
186
|
+
if (completing)
|
|
187
|
+
return;
|
|
188
|
+
// Not awaited before start(), which must run inside the click to open PayPal's popup.
|
|
189
|
+
const id = Promise.resolve(subscription ? { subscriptionId: checkoutId } : { orderId: checkoutId });
|
|
190
|
+
const report = (error) => notify(() => { var _a; return (_a = options.onError) === null || _a === void 0 ? void 0 : _a.call(options, error); });
|
|
191
|
+
try {
|
|
192
|
+
Promise.resolve(session.start({ presentationMode: "auto" }, id)).catch(report);
|
|
193
|
+
}
|
|
194
|
+
catch (error) {
|
|
195
|
+
report(error);
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
button.addEventListener("click", onClick);
|
|
199
|
+
element.appendChild(button);
|
|
200
|
+
return {
|
|
201
|
+
destroy() {
|
|
202
|
+
var _a;
|
|
203
|
+
if (destroyed)
|
|
204
|
+
return;
|
|
205
|
+
destroyed = true;
|
|
206
|
+
button.removeEventListener("click", onClick);
|
|
207
|
+
button.remove();
|
|
208
|
+
(_a = session.destroy) === null || _a === void 0 ? void 0 : _a.call(session);
|
|
209
|
+
},
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Mounts the embedded checkout that createCheckout() returned.
|
|
214
|
+
* @internal
|
|
215
|
+
*/
|
|
216
|
+
export async function mountCheckout(element, checkout, options, deps) {
|
|
217
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
218
|
+
throw new Error("mountCheckout() requires a browser environment");
|
|
219
|
+
}
|
|
220
|
+
if (!element) {
|
|
221
|
+
throw new Error("mountCheckout() requires an element to render in");
|
|
222
|
+
}
|
|
223
|
+
const embedded = checkout === null || checkout === void 0 ? void 0 : checkout.embedded;
|
|
224
|
+
if (!embedded) {
|
|
225
|
+
throw new Error("This checkout isn't embedded. Create it with presentation: 'embedded', or send the buyer to its redirect_url.");
|
|
226
|
+
}
|
|
227
|
+
switch (embedded.provider) {
|
|
228
|
+
case "stripe":
|
|
229
|
+
return mountStripe(element, await scriptUrlFor("stripe", deps), embedded, deps);
|
|
230
|
+
case "paypal":
|
|
231
|
+
return mountPayPal(element, await scriptUrlFor("paypal", deps), checkout.checkout_id, checkout.currency, embedded, options, deps);
|
|
232
|
+
default:
|
|
233
|
+
throw new Error(`Embedded checkout isn't supported for provider ${embedded.provider}`);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { AxiosInstance } from "axios";
|
|
2
|
+
import { PaymentsModule, ServiceRolePaymentsModule } from "./payments.types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Creates the payments module for anonymous and user authentication.
|
|
5
|
+
*
|
|
6
|
+
* @param axios - Axios instance
|
|
7
|
+
* @param appId - Application ID
|
|
8
|
+
* @returns Payments module for the browser
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
export declare function createPaymentsModule(axios: AxiosInstance, appId: string): PaymentsModule;
|
|
12
|
+
/**
|
|
13
|
+
* Creates the payments module for service role authentication.
|
|
14
|
+
*
|
|
15
|
+
* @param axios - Axios instance (should be service role client)
|
|
16
|
+
* @param appId - Application ID
|
|
17
|
+
* @returns Payments module for backend functions
|
|
18
|
+
* @internal
|
|
19
|
+
*/
|
|
20
|
+
export declare function createServiceRolePaymentsModule(axios: AxiosInstance, appId: string): ServiceRolePaymentsModule;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { loadScript, mountCheckout, } from "./payments-checkout.js";
|
|
2
|
+
function requireId(value, name) {
|
|
3
|
+
if (!value || typeof value !== "string") {
|
|
4
|
+
throw new Error(`${name} is required and must be a string`);
|
|
5
|
+
}
|
|
6
|
+
return encodeURIComponent(value);
|
|
7
|
+
}
|
|
8
|
+
function createPaymentsRequests(axios, appId) {
|
|
9
|
+
const base = `/apps/${appId}/payments`;
|
|
10
|
+
return {
|
|
11
|
+
async completeCheckout(checkoutId) {
|
|
12
|
+
const id = requireId(checkoutId, "Checkout ID");
|
|
13
|
+
return axios.post(`${base}/checkout-sessions/${id}/complete`);
|
|
14
|
+
},
|
|
15
|
+
async listPurchases(params = {}) {
|
|
16
|
+
return axios.get(`${base}/purchases`, { params });
|
|
17
|
+
},
|
|
18
|
+
async createCheckout(params) {
|
|
19
|
+
return axios.post(`${base}/checkout-sessions`, params);
|
|
20
|
+
},
|
|
21
|
+
async refund(params) {
|
|
22
|
+
return axios.post(`${base}/refunds`, params);
|
|
23
|
+
},
|
|
24
|
+
async cancelSubscription(subscriptionId, options = {}) {
|
|
25
|
+
const id = requireId(subscriptionId, "Subscription ID");
|
|
26
|
+
return axios.post(`${base}/subscriptions/${id}/cancel`, options);
|
|
27
|
+
},
|
|
28
|
+
async pauseSubscription(subscriptionId) {
|
|
29
|
+
const id = requireId(subscriptionId, "Subscription ID");
|
|
30
|
+
return axios.post(`${base}/subscriptions/${id}/pause`);
|
|
31
|
+
},
|
|
32
|
+
async resumeSubscription(subscriptionId) {
|
|
33
|
+
const id = requireId(subscriptionId, "Subscription ID");
|
|
34
|
+
return axios.post(`${base}/subscriptions/${id}/resume`);
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Creates the payments module for anonymous and user authentication.
|
|
40
|
+
*
|
|
41
|
+
* @param axios - Axios instance
|
|
42
|
+
* @param appId - Application ID
|
|
43
|
+
* @returns Payments module for the browser
|
|
44
|
+
* @internal
|
|
45
|
+
*/
|
|
46
|
+
export function createPaymentsModule(axios, appId) {
|
|
47
|
+
const requests = createPaymentsRequests(axios, appId);
|
|
48
|
+
// One fetch per client, retried on the next mount if it fails.
|
|
49
|
+
let config;
|
|
50
|
+
const getConfig = () => {
|
|
51
|
+
config !== null && config !== void 0 ? config : (config = axios.get(`/apps/${appId}/payments/config`).catch((error) => {
|
|
52
|
+
config = undefined;
|
|
53
|
+
throw error;
|
|
54
|
+
}));
|
|
55
|
+
return config;
|
|
56
|
+
};
|
|
57
|
+
return {
|
|
58
|
+
completeCheckout: requests.completeCheckout,
|
|
59
|
+
listPurchases: requests.listPurchases,
|
|
60
|
+
mountCheckout(element, checkout, options = {}) {
|
|
61
|
+
return mountCheckout(element, checkout, options, {
|
|
62
|
+
completeCheckout: requests.completeCheckout,
|
|
63
|
+
getConfig,
|
|
64
|
+
loadScript,
|
|
65
|
+
});
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Creates the payments module for service role authentication.
|
|
71
|
+
*
|
|
72
|
+
* @param axios - Axios instance (should be service role client)
|
|
73
|
+
* @param appId - Application ID
|
|
74
|
+
* @returns Payments module for backend functions
|
|
75
|
+
* @internal
|
|
76
|
+
*/
|
|
77
|
+
export function createServiceRolePaymentsModule(axios, appId) {
|
|
78
|
+
return createPaymentsRequests(axios, appId);
|
|
79
|
+
}
|
|
@@ -0,0 +1,626 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How often a recurring item bills.
|
|
3
|
+
*/
|
|
4
|
+
export type PaymentsRecurringFrequency = "day" | "week" | "month" | "year";
|
|
5
|
+
/**
|
|
6
|
+
* Free trial before the first charge of a recurring item.
|
|
7
|
+
*/
|
|
8
|
+
export interface CheckoutFreeTrial {
|
|
9
|
+
/** Unit of the trial length. Stripe supports only `'day'` and `'week'`. */
|
|
10
|
+
frequency: PaymentsRecurringFrequency;
|
|
11
|
+
/** Number of `frequency` units the trial lasts, from 1 to 999. */
|
|
12
|
+
interval: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Billing terms that turn a checkout item into a subscription.
|
|
16
|
+
*/
|
|
17
|
+
export interface CheckoutItemRecurring {
|
|
18
|
+
/** Unit of the billing period. */
|
|
19
|
+
frequency: PaymentsRecurringFrequency;
|
|
20
|
+
/** Number of `frequency` units between charges, from 1 to 3650. Defaults to `1`. */
|
|
21
|
+
interval?: number;
|
|
22
|
+
/** Whether the subscription renews automatically at the end of its billing cycles. Stripe doesn't support `false`. */
|
|
23
|
+
auto_renewal?: boolean;
|
|
24
|
+
/** Number of billing cycles before the subscription ends, at least 1. Omit for no limit. Not supported for Stripe. */
|
|
25
|
+
billing_cycles?: number;
|
|
26
|
+
/** Free trial before the first charge. Stripe applies one trial to the whole checkout, so every recurring item must request the same trial. */
|
|
27
|
+
free_trial?: CheckoutFreeTrial;
|
|
28
|
+
/** Subscription title shown to the buyer, up to 150 characters. */
|
|
29
|
+
title?: string;
|
|
30
|
+
/** Subscription description shown to the buyer, up to 500 characters. */
|
|
31
|
+
description?: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* A line item in a checkout.
|
|
35
|
+
*/
|
|
36
|
+
export interface CheckoutItem {
|
|
37
|
+
/** Item name shown to the buyer, 1 to 255 characters. */
|
|
38
|
+
name: string;
|
|
39
|
+
/** Unit price in the currency's minor units, such as cents. Must be greater than `0`. Providers may also reject a total below their minimum charge. */
|
|
40
|
+
amount: number;
|
|
41
|
+
/** Number of units, from 1 to 1,000,000. Defaults to `1`. */
|
|
42
|
+
quantity?: number;
|
|
43
|
+
/** Whether the item ships, so the provider collects a shipping address. */
|
|
44
|
+
shippable?: boolean;
|
|
45
|
+
/** Billing terms. Set this to sell the item as a subscription. PayPal and Wix Payments allow one recurring item per checkout, and PayPal allows no other items with it. */
|
|
46
|
+
recurring?: CheckoutItemRecurring;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Details about the buyer, used to prefill the checkout. Every field is optional.
|
|
50
|
+
*/
|
|
51
|
+
export interface CheckoutBuyer {
|
|
52
|
+
/** Buyer's email address. */
|
|
53
|
+
email?: string;
|
|
54
|
+
/** Buyer's first name. */
|
|
55
|
+
first_name?: string;
|
|
56
|
+
/** Buyer's last name. */
|
|
57
|
+
last_name?: string;
|
|
58
|
+
/** Buyer's phone number. */
|
|
59
|
+
phone?: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* How the buyer pays.
|
|
63
|
+
*
|
|
64
|
+
* - `'redirect'`: The buyer leaves the app for the provider's hosted checkout page at `redirect_url`.
|
|
65
|
+
* - `'embedded'`: The checkout renders inside the app with [`mountCheckout()`](/developers/references/sdk/docs/interfaces/payments#mountcheckout).
|
|
66
|
+
*/
|
|
67
|
+
export type CheckoutPresentation = "redirect" | "embedded";
|
|
68
|
+
/**
|
|
69
|
+
* Parameters for [`createCheckout()`](/developers/references/sdk/docs/interfaces/service-role-payments#createcheckout).
|
|
70
|
+
*/
|
|
71
|
+
export interface CreateCheckoutParams {
|
|
72
|
+
/** Items to sell, 1 to 100 entries. */
|
|
73
|
+
items: CheckoutItem[];
|
|
74
|
+
/** Three-letter ISO currency code, such as `'usd'`. Defaults to the payment account's currency. Required for PayPal. */
|
|
75
|
+
currency?: string;
|
|
76
|
+
/** App-relative path the buyer returns to after paying, such as `'/thank-you'`. Must start with `/`. */
|
|
77
|
+
success_path: string;
|
|
78
|
+
/** App-relative path the buyer returns to after cancelling. Must start with `/`. Not supported for Stripe embedded checkout. */
|
|
79
|
+
cancel_path?: string;
|
|
80
|
+
/** Details about the buyer, used to prefill the checkout. */
|
|
81
|
+
buyer?: CheckoutBuyer;
|
|
82
|
+
/** Your own key-value pairs, up to 50 keys. Returned in each purchase's `metadata` to service role callers only. Not supported for PayPal. */
|
|
83
|
+
metadata?: Record<string, string>;
|
|
84
|
+
/** Key that makes retries return the same checkout instead of creating another, 1 to 200 characters. Not supported for Wix Payments or PayPal subscriptions. */
|
|
85
|
+
idempotency_key?: string;
|
|
86
|
+
/** How the buyer pays. Defaults to `'redirect'`. PayPal apps must pass `'embedded'`, and Wix Payments supports only `'redirect'`. */
|
|
87
|
+
presentation?: CheckoutPresentation;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Data that Stripe Embedded Checkout needs to render.
|
|
91
|
+
*/
|
|
92
|
+
export interface StripeEmbeddedCheckout {
|
|
93
|
+
/** Payment provider. */
|
|
94
|
+
provider: "stripe";
|
|
95
|
+
/** Stripe publishable key of the app's payment account. */
|
|
96
|
+
publishable_key: string;
|
|
97
|
+
/** Client secret of the Stripe Checkout Session. */
|
|
98
|
+
client_secret: string;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Data that the PayPal button needs to render.
|
|
102
|
+
*/
|
|
103
|
+
export interface PayPalEmbeddedCheckout {
|
|
104
|
+
/** Payment provider. */
|
|
105
|
+
provider: "paypal";
|
|
106
|
+
/** PayPal client ID. */
|
|
107
|
+
client_id: string;
|
|
108
|
+
/** PayPal merchant ID of the app's seller account. */
|
|
109
|
+
merchant_id: string;
|
|
110
|
+
/** PayPal partner attribution ID, when set. */
|
|
111
|
+
partner_attribution_id?: string | null;
|
|
112
|
+
/** Whether the checkout is a one-time payment or a subscription. */
|
|
113
|
+
intent: "capture" | "subscription";
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Data that an embedded checkout needs to render, by provider.
|
|
117
|
+
*/
|
|
118
|
+
export type EmbeddedCheckout = StripeEmbeddedCheckout | PayPalEmbeddedCheckout;
|
|
119
|
+
/**
|
|
120
|
+
* Result of [`createCheckout()`](/developers/references/sdk/docs/interfaces/service-role-payments#createcheckout).
|
|
121
|
+
*
|
|
122
|
+
* Exactly one of `redirect_url` and `embedded` is set, depending on the checkout's `presentation`.
|
|
123
|
+
*/
|
|
124
|
+
export interface CreateCheckoutResult {
|
|
125
|
+
/** ID of the checkout. For Stripe it's the Checkout Session ID, and for PayPal it's the PayPal order or subscription ID. */
|
|
126
|
+
checkout_id: string;
|
|
127
|
+
/** Three-letter ISO currency code of the checkout, in lowercase. */
|
|
128
|
+
currency: string;
|
|
129
|
+
/** Amount the buyer pays now, in minor units. It's `0` for a subscription that starts with a free trial. */
|
|
130
|
+
amount_total: number;
|
|
131
|
+
/** Absolute URL of the provider's hosted checkout page, for redirect checkouts. */
|
|
132
|
+
redirect_url: string | null;
|
|
133
|
+
/** Data for [`mountCheckout()`](/developers/references/sdk/docs/interfaces/payments#mountcheckout), for embedded checkouts. */
|
|
134
|
+
embedded: EmbeddedCheckout | null;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Result of [`completeCheckout()`](/developers/references/sdk/docs/interfaces/payments#completecheckout).
|
|
138
|
+
*/
|
|
139
|
+
export interface CompleteCheckoutResult {
|
|
140
|
+
/** ID of the checkout. */
|
|
141
|
+
checkout_id: string;
|
|
142
|
+
/** Whether the payment went through or the provider is still processing it. */
|
|
143
|
+
status: "paid" | "pending";
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Status of a purchase.
|
|
147
|
+
*
|
|
148
|
+
* - `'pending'`: The buyer hasn't finished paying, or the provider is still processing the payment.
|
|
149
|
+
* - `'paid'`: The payment went through.
|
|
150
|
+
* - `'refunded'`: The payment was refunded.
|
|
151
|
+
* - `'canceled'`: The checkout or subscription was canceled.
|
|
152
|
+
* - `'failed'`: The payment failed.
|
|
153
|
+
* - `'unknown'`: The provider reported a state that doesn't map to the others.
|
|
154
|
+
*/
|
|
155
|
+
export type PurchaseStatus = "pending" | "paid" | "refunded" | "canceled" | "failed" | "unknown";
|
|
156
|
+
/**
|
|
157
|
+
* A line item of a purchase.
|
|
158
|
+
*/
|
|
159
|
+
export interface PurchaseItem {
|
|
160
|
+
/** Item name. */
|
|
161
|
+
name: string;
|
|
162
|
+
/** Unit price in minor units, when the provider reports it. */
|
|
163
|
+
amount?: number | null;
|
|
164
|
+
/** Number of units, when the provider reports it. */
|
|
165
|
+
quantity?: number | null;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* A completed or in-progress checkout.
|
|
169
|
+
*/
|
|
170
|
+
export interface Purchase {
|
|
171
|
+
/** ID of the checkout the purchase came from. */
|
|
172
|
+
checkout_id: string;
|
|
173
|
+
/** Status of the purchase. */
|
|
174
|
+
status: PurchaseStatus;
|
|
175
|
+
/** Line items of the purchase. */
|
|
176
|
+
items: PurchaseItem[];
|
|
177
|
+
/** Total amount in minor units. */
|
|
178
|
+
amount_total?: number | null;
|
|
179
|
+
/** Three-letter ISO currency code, in lowercase. */
|
|
180
|
+
currency?: string | null;
|
|
181
|
+
/** Buyer's email address. */
|
|
182
|
+
buyer_email?: string | null;
|
|
183
|
+
/** The metadata passed to [`createCheckout()`](/developers/references/sdk/docs/interfaces/service-role-payments#createcheckout). Always `null` unless you call with the service role. */
|
|
184
|
+
metadata?: Record<string, string> | null;
|
|
185
|
+
/** ID of the subscription, for recurring purchases. */
|
|
186
|
+
subscription_id?: string | null;
|
|
187
|
+
/** ID of the payment to pass to [`refund()`](/developers/references/sdk/docs/interfaces/service-role-payments#refund). It's `null` where the provider doesn't name a single payment, such as PayPal subscriptions. */
|
|
188
|
+
payment_id?: string | null;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Parameters for [`listPurchases()`](/developers/references/sdk/docs/interfaces/payments#listpurchases).
|
|
192
|
+
*/
|
|
193
|
+
export interface ListPurchasesParams {
|
|
194
|
+
/** Only return the purchase from this checkout. */
|
|
195
|
+
checkout_id?: string;
|
|
196
|
+
/** Only return purchases of this subscription. */
|
|
197
|
+
subscription_id?: string;
|
|
198
|
+
/** Maximum number of purchases to return, from 1 to 100. Defaults to `20`. */
|
|
199
|
+
limit?: number;
|
|
200
|
+
/** The `next_cursor` from the previous page. Send the same filters and `limit` as that call. */
|
|
201
|
+
cursor?: string;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Parameters for [`listPurchases()`](/developers/references/sdk/docs/interfaces/service-role-payments#listpurchases) with the service role.
|
|
205
|
+
*/
|
|
206
|
+
export interface ServiceRoleListPurchasesParams extends ListPurchasesParams {
|
|
207
|
+
/** Only return purchases made with this email address. */
|
|
208
|
+
buyer_email?: string;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* A page of purchases.
|
|
212
|
+
*/
|
|
213
|
+
export interface ListPurchasesResult {
|
|
214
|
+
/** Purchases on this page. */
|
|
215
|
+
items: Purchase[];
|
|
216
|
+
/** Cursor for the next page, or `null` on the last page. */
|
|
217
|
+
next_cursor: string | null;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Parameters for [`refund()`](/developers/references/sdk/docs/interfaces/service-role-payments#refund).
|
|
221
|
+
*/
|
|
222
|
+
export interface RefundParams {
|
|
223
|
+
/** The `payment_id` of the purchase to refund. */
|
|
224
|
+
payment_id: string;
|
|
225
|
+
/** Amount to refund in minor units. Must be greater than `0`. */
|
|
226
|
+
amount: number;
|
|
227
|
+
/** Key that makes retries return the original refund instead of refunding twice, 1 to 100 characters. */
|
|
228
|
+
idempotency_key: string;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Result of [`refund()`](/developers/references/sdk/docs/interfaces/service-role-payments#refund).
|
|
232
|
+
*/
|
|
233
|
+
export interface RefundResult {
|
|
234
|
+
/** Provider's ID of the refund. */
|
|
235
|
+
refund_id: string;
|
|
236
|
+
/** ID of the refunded payment. */
|
|
237
|
+
payment_id: string;
|
|
238
|
+
/** Refunded amount in minor units. */
|
|
239
|
+
amount: number;
|
|
240
|
+
/** Three-letter ISO currency code, in lowercase. */
|
|
241
|
+
currency: string;
|
|
242
|
+
/** Whether the refund went through or the provider is still processing it. */
|
|
243
|
+
status: "succeeded" | "pending";
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Options for [`cancelSubscription()`](/developers/references/sdk/docs/interfaces/service-role-payments#cancelsubscription).
|
|
247
|
+
*/
|
|
248
|
+
export interface CancelSubscriptionOptions {
|
|
249
|
+
/** Cancel at the end of the current billing period instead of now. Defaults to `false`. Not supported for PayPal. */
|
|
250
|
+
at_period_end?: boolean;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* State of a subscription after a change.
|
|
254
|
+
*/
|
|
255
|
+
export interface SubscriptionResult {
|
|
256
|
+
/** ID of the subscription. */
|
|
257
|
+
subscription_id: string;
|
|
258
|
+
/** Current status of the subscription. */
|
|
259
|
+
status: "active" | "past_due" | "paused" | "canceled";
|
|
260
|
+
/** Whether the subscription is set to cancel at the end of the current billing period. */
|
|
261
|
+
cancel_at_period_end: boolean;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Error codes that payments methods reject with, in the `code` of a `Base44Error`.
|
|
265
|
+
*
|
|
266
|
+
* Some notable ones:
|
|
267
|
+
*
|
|
268
|
+
* - `payment_declined`: The buyer's payment method was declined when completing the checkout. The buyer can try again with another method.
|
|
269
|
+
* - `refund_failed`: The refund's outcome is unknown. Retry with the same `idempotency_key` and `amount`, which returns the original refund if one was made.
|
|
270
|
+
* - `refund_in_progress`: A refund with the same `idempotency_key` is still running.
|
|
271
|
+
* - `refund_amount_mismatch`: The `idempotency_key` was already used for a different amount.
|
|
272
|
+
* - `rate_limited`: Too many requests. Wait for the number of seconds in the `Retry-After` response header, available at `error.originalError.response.headers['retry-after']`.
|
|
273
|
+
* - `refund_not_supported`, `subscription_action_not_supported`, `complete_not_supported`, `presentation_not_supported`: The app's payment provider doesn't support the operation.
|
|
274
|
+
*/
|
|
275
|
+
export type PaymentsErrorCode = "forbidden" | "unauthenticated" | "not_found" | "conflict" | "rate_limited" | "payments_not_connected" | "invalid_request" | "invalid_items" | "amount_below_minimum" | "currency_mismatch" | "currency_required" | "invalid_metadata" | "idempotency_not_supported" | "idempotency_key_reused" | "multiple_subscription_items" | "recurring_option_not_supported" | "invalid_cursor" | "presentation_not_supported" | "embedded_checkout_unavailable" | "checkout_not_found" | "checkout_not_approved" | "checkout_closed" | "payment_declined" | "complete_not_supported" | "provider_unavailable" | "payment_not_found" | "refund_rejected" | "refund_in_progress" | "refund_amount_mismatch" | "refund_temporarily_unavailable" | "refund_failed" | "refund_not_supported" | "subscription_not_found" | "subscription_not_active" | "subscription_action_not_supported";
|
|
276
|
+
/**
|
|
277
|
+
* Callbacks for [`mountCheckout()`](/developers/references/sdk/docs/interfaces/payments#mountcheckout).
|
|
278
|
+
*/
|
|
279
|
+
export interface MountCheckoutOptions {
|
|
280
|
+
/**
|
|
281
|
+
* Called after the buyer approves a PayPal payment and the SDK completes the checkout.
|
|
282
|
+
*
|
|
283
|
+
* Use it to update the page, not to grant access. Browser callbacks can be faked, so unlock paid content only after your backend confirms the purchase, for example with [`listPurchases()`](/developers/references/sdk/docs/interfaces/service-role-payments#listpurchases) in a backend function.
|
|
284
|
+
*
|
|
285
|
+
* Stripe doesn't call this. After a Stripe payment, the buyer returns to the checkout's `success_path` with a `session_id` query parameter. That parameter is the `checkout_id`. Show the result there with [`listPurchases()`](/developers/references/sdk/docs/interfaces/payments#listpurchases), and grant access only after your backend confirms it.
|
|
286
|
+
*/
|
|
287
|
+
onComplete?: (result: CompleteCheckoutResult) => void;
|
|
288
|
+
/** Called when the buyer closes the PayPal window without paying. The button stays mounted so the buyer can try again. */
|
|
289
|
+
onCancel?: () => void;
|
|
290
|
+
/**
|
|
291
|
+
* Called when a PayPal checkout fails after it's mounted, including a declined payment with the `payment_declined` code. The button stays mounted so the buyer can try again. If it keeps failing with `payment_declined`, create a new checkout and mount it. Stripe shows its own errors inside the checkout.
|
|
292
|
+
*
|
|
293
|
+
* The error is a `Base44Error` when completing the checkout fails, or PayPal's own error object when the PayPal window fails.
|
|
294
|
+
*/
|
|
295
|
+
onError?: (error: unknown) => void;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* An element on the page to render the checkout in, such as the result of `document.getElementById()`.
|
|
299
|
+
*
|
|
300
|
+
* Typed structurally so that the SDK's types don't require the DOM library in backend code.
|
|
301
|
+
*/
|
|
302
|
+
export interface CheckoutElement {
|
|
303
|
+
/** Present on every DOM element. */
|
|
304
|
+
appendChild(node: never): unknown;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* The fields of a {@linkcode CreateCheckoutResult} that [`mountCheckout()`](/developers/references/sdk/docs/interfaces/payments#mountcheckout) reads.
|
|
308
|
+
*/
|
|
309
|
+
export interface MountableCheckout {
|
|
310
|
+
/** ID of the checkout. */
|
|
311
|
+
checkout_id: string;
|
|
312
|
+
/** Three-letter ISO currency code of the checkout. */
|
|
313
|
+
currency: string;
|
|
314
|
+
/** Data for the embedded checkout. Mounting rejects when it's `null`. */
|
|
315
|
+
embedded: EmbeddedCheckout | null;
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* A mounted embedded checkout.
|
|
319
|
+
*/
|
|
320
|
+
export interface CheckoutMount {
|
|
321
|
+
/** Removes the checkout from the page. Call it when the component that holds it unmounts. For Stripe, mounting another checkout destroys this one for you. */
|
|
322
|
+
destroy: () => void;
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Payments module for selling from the app through its connected payment provider.
|
|
326
|
+
*
|
|
327
|
+
* This module provides:
|
|
328
|
+
* - An embedded checkout that renders in any framework, with a PayPal button or Stripe Embedded Checkout
|
|
329
|
+
* - Completing PayPal checkouts
|
|
330
|
+
* - Lookup of the signed-in user's purchases
|
|
331
|
+
*
|
|
332
|
+
* Creating checkouts, refunds, and subscription changes are in {@linkcode ServiceRolePaymentsModule}.
|
|
333
|
+
*
|
|
334
|
+
* Each app connects one provider, which is Stripe, PayPal, or Wix Payments. Amounts are always integers in the currency's minor units, such as cents.
|
|
335
|
+
*
|
|
336
|
+
* | | Stripe | PayPal | Wix Payments |
|
|
337
|
+
* | :- | :- | :- | :- |
|
|
338
|
+
* | Redirect checkout | Yes | No | Yes |
|
|
339
|
+
* | Embedded checkout | Yes | Yes, the only mode | No |
|
|
340
|
+
* | Refunds | Yes | Yes | No |
|
|
341
|
+
* | Cancel a subscription | Yes, now or at period end | Yes, now only | No |
|
|
342
|
+
* | Pause and resume a subscription | Yes | Yes | No |
|
|
343
|
+
*
|
|
344
|
+
* ## Authentication modes
|
|
345
|
+
*
|
|
346
|
+
* - **Anonymous or user authentication** (`base44.payments`): Completes checkouts, mounts embedded checkouts, and lists the signed-in user's own purchases.
|
|
347
|
+
* - **Service role authentication** (`base44.asServiceRole.payments`): Creates checkouts, lists any purchase, refunds payments, and changes subscriptions. Use it in backend functions.
|
|
348
|
+
*
|
|
349
|
+
* Failed requests reject with a `Base44Error` whose `code` is one of the {@linkcode PaymentsErrorCode} values. Invalid arguments and [`mountCheckout()`](#mountcheckout) failures reject with a plain `Error`.
|
|
350
|
+
*/
|
|
351
|
+
export interface PaymentsModule {
|
|
352
|
+
/**
|
|
353
|
+
* Completes a PayPal checkout after the buyer approves it.
|
|
354
|
+
*
|
|
355
|
+
* When you use {@linkcode mountCheckout | mountCheckout()}, it calls this for you. Call it yourself only if you render the PayPal button yourself. Calling it again for the same checkout returns the same result.
|
|
356
|
+
*
|
|
357
|
+
* Only PayPal checkouts need completing. Other providers reject with `complete_not_supported`.
|
|
358
|
+
*
|
|
359
|
+
* @param checkoutId - The `checkout_id` from [`createCheckout()`](/developers/references/sdk/docs/interfaces/service-role-payments#createcheckout).
|
|
360
|
+
* @returns Promise resolving to the checkout's payment status.
|
|
361
|
+
*
|
|
362
|
+
* @example
|
|
363
|
+
* ```typescript
|
|
364
|
+
* // Complete a PayPal checkout in your own onApprove handler
|
|
365
|
+
* const { status } = await base44.payments.completeCheckout(checkoutId);
|
|
366
|
+
* if (status === 'paid') {
|
|
367
|
+
* showThankYou();
|
|
368
|
+
* }
|
|
369
|
+
* ```
|
|
370
|
+
*/
|
|
371
|
+
completeCheckout(checkoutId: string): Promise<CompleteCheckoutResult>;
|
|
372
|
+
/**
|
|
373
|
+
* Lists the signed-in user's purchases.
|
|
374
|
+
*
|
|
375
|
+
* Only purchases made with the user's own email address are returned. Rejects with `forbidden` when no user is signed in. PayPal apps must pass `checkout_id` or `subscription_id`, and get at most one purchase.
|
|
376
|
+
*
|
|
377
|
+
* @param params - Optional filters and pagination.
|
|
378
|
+
* @returns Promise resolving to a page of purchases.
|
|
379
|
+
*
|
|
380
|
+
* @example
|
|
381
|
+
* ```typescript
|
|
382
|
+
* // Check a purchase on the success page
|
|
383
|
+
* const { items } = await base44.payments.listPurchases({ checkout_id: checkoutId });
|
|
384
|
+
* const paid = items[0]?.status === 'paid';
|
|
385
|
+
* ```
|
|
386
|
+
*
|
|
387
|
+
* @example
|
|
388
|
+
* ```typescript
|
|
389
|
+
* // Page through the user's purchases
|
|
390
|
+
* let cursor: string | undefined;
|
|
391
|
+
* do {
|
|
392
|
+
* const page = await base44.payments.listPurchases({ limit: 50, cursor });
|
|
393
|
+
* page.items.forEach((purchase) => console.log(purchase.checkout_id, purchase.status));
|
|
394
|
+
* cursor = page.next_cursor ?? undefined;
|
|
395
|
+
* } while (cursor);
|
|
396
|
+
* ```
|
|
397
|
+
*/
|
|
398
|
+
listPurchases(params?: ListPurchasesParams): Promise<ListPurchasesResult>;
|
|
399
|
+
/**
|
|
400
|
+
* Renders an embedded checkout inside an element on the page.
|
|
401
|
+
*
|
|
402
|
+
* Pass the result of a [`createCheckout()`](/developers/references/sdk/docs/interfaces/service-role-payments#createcheckout) call made with `presentation: 'embedded'`. Because only the service role can create checkouts, create it in a backend function and return the result to the page.
|
|
403
|
+
*
|
|
404
|
+
* The SDK loads the provider's script and renders the checkout for you:
|
|
405
|
+
* - PayPal: Renders a PayPal button. When the buyer approves the payment, the SDK calls {@linkcode completeCheckout | completeCheckout()} and then `onComplete`.
|
|
406
|
+
* - Stripe: Mounts Stripe Embedded Checkout. After paying, the buyer returns to the checkout's `success_path`. Stripe allows one embedded checkout per page, so mounting another Stripe checkout destroys the previous one.
|
|
407
|
+
*
|
|
408
|
+
* Requires a browser environment and can't be used in the backend. Rejects when the checkout isn't embedded, when the payments config can't be fetched or has no valid script URL for the provider, when the provider's script fails to load, or when PayPal isn't available for the checkout's currency.
|
|
409
|
+
*
|
|
410
|
+
* The checkout's callbacks run in the buyer's browser, where they can be faked. Grant access to what the buyer paid for only after your backend confirms the purchase, for example with [`listPurchases()`](/developers/references/sdk/docs/interfaces/service-role-payments#listpurchases) in a backend function.
|
|
411
|
+
*
|
|
412
|
+
* @param element - Element to render the checkout in. It should be empty.
|
|
413
|
+
* @param checkout - The result of [`createCheckout()`](/developers/references/sdk/docs/interfaces/service-role-payments#createcheckout).
|
|
414
|
+
* @param options - Callbacks for the checkout's outcome.
|
|
415
|
+
* @returns Promise resolving to the mounted checkout once it renders.
|
|
416
|
+
*
|
|
417
|
+
* @example
|
|
418
|
+
* ```typescript
|
|
419
|
+
* // Create the checkout in a backend function, then mount it
|
|
420
|
+
* const { data: checkout } = await base44.functions.invoke('createCheckout', { planId });
|
|
421
|
+
*
|
|
422
|
+
* const mount = await base44.payments.mountCheckout(
|
|
423
|
+
* document.getElementById('checkout')!,
|
|
424
|
+
* checkout,
|
|
425
|
+
* {
|
|
426
|
+
* onComplete: ({ status }) => navigate(status === 'paid' ? '/thank-you' : '/processing'),
|
|
427
|
+
* onError: () => setError('The payment failed. Please try again.'),
|
|
428
|
+
* }
|
|
429
|
+
* );
|
|
430
|
+
*
|
|
431
|
+
* // Later, when the page unmounts
|
|
432
|
+
* mount.destroy();
|
|
433
|
+
* ```
|
|
434
|
+
*
|
|
435
|
+
* @example
|
|
436
|
+
* ```tsx
|
|
437
|
+
* // React component
|
|
438
|
+
* function Checkout({ checkout }: { checkout: CreateCheckoutResult }) {
|
|
439
|
+
* const ref = useRef<HTMLDivElement>(null);
|
|
440
|
+
*
|
|
441
|
+
* useEffect(() => {
|
|
442
|
+
* let mount: CheckoutMount | undefined;
|
|
443
|
+
* let cancelled = false;
|
|
444
|
+
* base44.payments
|
|
445
|
+
* .mountCheckout(ref.current!, checkout, { onComplete: () => navigate('/thank-you') })
|
|
446
|
+
* .then((m) => (cancelled ? m.destroy() : (mount = m)))
|
|
447
|
+
* .catch(() => setError('The checkout could not load.'));
|
|
448
|
+
* return () => {
|
|
449
|
+
* cancelled = true;
|
|
450
|
+
* mount?.destroy();
|
|
451
|
+
* };
|
|
452
|
+
* }, [checkout]);
|
|
453
|
+
*
|
|
454
|
+
* return <div ref={ref} />;
|
|
455
|
+
* }
|
|
456
|
+
* ```
|
|
457
|
+
*/
|
|
458
|
+
mountCheckout(element: CheckoutElement, checkout: MountableCheckout, options?: MountCheckoutOptions): Promise<CheckoutMount>;
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Payments module with service role authentication, for backend functions.
|
|
462
|
+
*
|
|
463
|
+
* Creates checkouts, lists any purchase, refunds payments, and changes subscriptions. See {@linkcode PaymentsModule} for which providers support which operations.
|
|
464
|
+
*
|
|
465
|
+
* Refunds take a required `idempotency_key` and checkouts take an optional one, so retrying them doesn't charge or refund twice. Repeating a subscription change returns the subscription's current state.
|
|
466
|
+
*/
|
|
467
|
+
export interface ServiceRolePaymentsModule {
|
|
468
|
+
/**
|
|
469
|
+
* Creates a checkout.
|
|
470
|
+
*
|
|
471
|
+
* For a redirect checkout, send the buyer to the returned `redirect_url`. For an embedded checkout, return the result to the page and pass it to [`mountCheckout()`](/developers/references/sdk/docs/interfaces/payments#mountcheckout).
|
|
472
|
+
*
|
|
473
|
+
* A checkout with a `recurring` item creates a subscription.
|
|
474
|
+
*
|
|
475
|
+
* @param params - Items, return paths, and options for the checkout.
|
|
476
|
+
* @returns Promise resolving to the checkout.
|
|
477
|
+
*
|
|
478
|
+
* @example
|
|
479
|
+
* ```typescript
|
|
480
|
+
* // Create a redirect checkout in a backend function
|
|
481
|
+
* import { createClientFromRequest } from 'npm:@base44/sdk';
|
|
482
|
+
*
|
|
483
|
+
* Deno.serve(async (req) => {
|
|
484
|
+
* const base44 = createClientFromRequest(req);
|
|
485
|
+
* const checkout = await base44.asServiceRole.payments.createCheckout({
|
|
486
|
+
* items: [{ name: 'T-shirt', amount: 2500, quantity: 2, shippable: true }],
|
|
487
|
+
* currency: 'usd',
|
|
488
|
+
* success_path: '/thank-you',
|
|
489
|
+
* cancel_path: '/cart',
|
|
490
|
+
* });
|
|
491
|
+
*
|
|
492
|
+
* return Response.json({ url: checkout.redirect_url });
|
|
493
|
+
* });
|
|
494
|
+
* ```
|
|
495
|
+
*
|
|
496
|
+
* @example
|
|
497
|
+
* ```typescript
|
|
498
|
+
* // Create an embedded subscription checkout for the signed-in user
|
|
499
|
+
* import { createClientFromRequest } from 'npm:@base44/sdk';
|
|
500
|
+
*
|
|
501
|
+
* Deno.serve(async (req) => {
|
|
502
|
+
* const base44 = createClientFromRequest(req);
|
|
503
|
+
* const user = await base44.auth.me();
|
|
504
|
+
* const checkout = await base44.asServiceRole.payments.createCheckout({
|
|
505
|
+
* items: [{
|
|
506
|
+
* name: 'Pro plan',
|
|
507
|
+
* amount: 1500,
|
|
508
|
+
* recurring: { frequency: 'month', free_trial: { frequency: 'day', interval: 14 } },
|
|
509
|
+
* }],
|
|
510
|
+
* currency: 'usd',
|
|
511
|
+
* success_path: '/welcome',
|
|
512
|
+
* buyer: { email: user.email },
|
|
513
|
+
* presentation: 'embedded',
|
|
514
|
+
* });
|
|
515
|
+
*
|
|
516
|
+
* // Pass this to base44.payments.mountCheckout() on the page
|
|
517
|
+
* return Response.json(checkout);
|
|
518
|
+
* });
|
|
519
|
+
* ```
|
|
520
|
+
*/
|
|
521
|
+
createCheckout(params: CreateCheckoutParams): Promise<CreateCheckoutResult>;
|
|
522
|
+
/**
|
|
523
|
+
* Completes a PayPal checkout after the buyer approves it.
|
|
524
|
+
*
|
|
525
|
+
* See [`base44.payments.completeCheckout()`](/developers/references/sdk/docs/interfaces/payments#completecheckout).
|
|
526
|
+
*
|
|
527
|
+
* @param checkoutId - The `checkout_id` from {@linkcode createCheckout | createCheckout()}.
|
|
528
|
+
* @returns Promise resolving to the checkout's payment status.
|
|
529
|
+
*
|
|
530
|
+
* @example
|
|
531
|
+
* ```typescript
|
|
532
|
+
* // Complete a PayPal checkout from a backend function
|
|
533
|
+
* const { status } = await base44.asServiceRole.payments.completeCheckout(checkoutId);
|
|
534
|
+
* ```
|
|
535
|
+
*/
|
|
536
|
+
completeCheckout(checkoutId: string): Promise<CompleteCheckoutResult>;
|
|
537
|
+
/**
|
|
538
|
+
* Lists the app's purchases.
|
|
539
|
+
*
|
|
540
|
+
* Unlike [`base44.payments.listPurchases()`](/developers/references/sdk/docs/interfaces/payments#listpurchases), it returns any buyer's purchases and includes their `metadata`. PayPal apps must pass `checkout_id` or `subscription_id`, and get at most one purchase.
|
|
541
|
+
*
|
|
542
|
+
* @param params - Optional filters and pagination.
|
|
543
|
+
* @returns Promise resolving to a page of purchases.
|
|
544
|
+
*
|
|
545
|
+
* @example
|
|
546
|
+
* ```typescript
|
|
547
|
+
* // Find a buyer's purchases
|
|
548
|
+
* const { items } = await base44.asServiceRole.payments.listPurchases({
|
|
549
|
+
* buyer_email: 'buyer@example.com',
|
|
550
|
+
* });
|
|
551
|
+
* ```
|
|
552
|
+
*/
|
|
553
|
+
listPurchases(params?: ServiceRoleListPurchasesParams): Promise<ListPurchasesResult>;
|
|
554
|
+
/**
|
|
555
|
+
* Refunds all or part of a payment.
|
|
556
|
+
*
|
|
557
|
+
* Retrying with the same `idempotency_key` and `amount` returns the original refund instead of refunding twice. When the call rejects with `refund_failed`, the outcome is unknown, so retry it with the same values.
|
|
558
|
+
*
|
|
559
|
+
* Not supported for Wix Payments.
|
|
560
|
+
*
|
|
561
|
+
* @param params - The payment, amount, and idempotency key.
|
|
562
|
+
* @returns Promise resolving to the refund.
|
|
563
|
+
*
|
|
564
|
+
* @example
|
|
565
|
+
* ```typescript
|
|
566
|
+
* // Refund a purchase in full
|
|
567
|
+
* const { items } = await base44.asServiceRole.payments.listPurchases({ checkout_id: checkoutId });
|
|
568
|
+
* const purchase = items[0];
|
|
569
|
+
*
|
|
570
|
+
* const refund = await base44.asServiceRole.payments.refund({
|
|
571
|
+
* payment_id: purchase.payment_id!,
|
|
572
|
+
* amount: purchase.amount_total!,
|
|
573
|
+
* idempotency_key: `refund-${checkoutId}`,
|
|
574
|
+
* });
|
|
575
|
+
* ```
|
|
576
|
+
*/
|
|
577
|
+
refund(params: RefundParams): Promise<RefundResult>;
|
|
578
|
+
/**
|
|
579
|
+
* Cancels a subscription, now or at the end of the current billing period.
|
|
580
|
+
*
|
|
581
|
+
* Not supported for Wix Payments. PayPal supports cancelling now only.
|
|
582
|
+
*
|
|
583
|
+
* @param subscriptionId - The `subscription_id` of the purchase.
|
|
584
|
+
* @param options - When to cancel.
|
|
585
|
+
* @returns Promise resolving to the subscription's state.
|
|
586
|
+
*
|
|
587
|
+
* @example
|
|
588
|
+
* ```typescript
|
|
589
|
+
* // Cancel at the end of the billing period
|
|
590
|
+
* await base44.asServiceRole.payments.cancelSubscription(subscriptionId, {
|
|
591
|
+
* at_period_end: true,
|
|
592
|
+
* });
|
|
593
|
+
* ```
|
|
594
|
+
*/
|
|
595
|
+
cancelSubscription(subscriptionId: string, options?: CancelSubscriptionOptions): Promise<SubscriptionResult>;
|
|
596
|
+
/**
|
|
597
|
+
* Pauses a subscription's billing.
|
|
598
|
+
*
|
|
599
|
+
* Not supported for Wix Payments.
|
|
600
|
+
*
|
|
601
|
+
* @param subscriptionId - The `subscription_id` of the purchase.
|
|
602
|
+
* @returns Promise resolving to the subscription's state.
|
|
603
|
+
*
|
|
604
|
+
* @example
|
|
605
|
+
* ```typescript
|
|
606
|
+
* // Pause a subscription
|
|
607
|
+
* await base44.asServiceRole.payments.pauseSubscription(subscriptionId);
|
|
608
|
+
* ```
|
|
609
|
+
*/
|
|
610
|
+
pauseSubscription(subscriptionId: string): Promise<SubscriptionResult>;
|
|
611
|
+
/**
|
|
612
|
+
* Resumes a paused subscription's billing.
|
|
613
|
+
*
|
|
614
|
+
* Not supported for Wix Payments.
|
|
615
|
+
*
|
|
616
|
+
* @param subscriptionId - The `subscription_id` of the purchase.
|
|
617
|
+
* @returns Promise resolving to the subscription's state.
|
|
618
|
+
*
|
|
619
|
+
* @example
|
|
620
|
+
* ```typescript
|
|
621
|
+
* // Resume a paused subscription
|
|
622
|
+
* await base44.asServiceRole.payments.resumeSubscription(subscriptionId);
|
|
623
|
+
* ```
|
|
624
|
+
*/
|
|
625
|
+
resumeSubscription(subscriptionId: string): Promise<SubscriptionResult>;
|
|
626
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|