@phpsandbox/sdk 0.4.0 → 0.5.0

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 CHANGED
@@ -55,6 +55,33 @@ PHPSandbox.rest('token', 'https://api.phpsandbox.io/v1', {
55
55
  });
56
56
  ```
57
57
 
58
+ ## App server integration
59
+
60
+ Apps hosted on PHPSandbox can use one environment-scoped identity for Customers and Payments:
61
+
62
+ ```ts
63
+ import { PHPSandbox } from '@phpsandbox/sdk';
64
+
65
+ const platform = PHPSandbox.app();
66
+ const customer = await platform.customers.identify({
67
+ externalId: account.customerExternalId,
68
+ email: account.email,
69
+ billingStatus: account.hasSubscription ? 'paid' : 'free',
70
+ });
71
+ const checkout = await platform.payments.checkout({
72
+ customerId: customer.id,
73
+ requestId: order.requestId,
74
+ orderId: order.id,
75
+ priceId: order.priceId,
76
+ successPath: '/thanks',
77
+ cancelPath: '/account',
78
+ });
79
+ ```
80
+
81
+ Persist an opaque UUID on each app account for its external customer identity; separate databases must not reuse sequential IDs. Initialize this client only on the app server. It reads the provisioned app configuration and exposes only app runtime capabilities, without notebook or organization administration. Production uses its own identity and never falls back to development. Select `{ mode: 'test' }` once for an intentional sandbox run. Runtimes without `process.env` can supply server bindings through `{ env }`.
82
+
83
+ Verify incoming payment callbacks with `platform.payments.verifyEvent(rawBody, signature)`, passing the `phpsandbox-signature` header. The client verifies the original bytes, timestamp and environment before returning the event; the app must still validate order ownership and apply revisions idempotently.
84
+
58
85
  ## Server invitations
59
86
 
60
87
  Server administrators can invite someone by email and inspect the shared invitation state:
@@ -309,6 +336,16 @@ if (!state.enabled) {
309
336
  await notebook.mail.enable();
310
337
  }
311
338
 
339
+ // Capture a development email in the notebook inbox without external delivery.
340
+ await notebook.mail.capture({
341
+ requestId: crypto.randomUUID(),
342
+ from: 'hello@example.com',
343
+ fromName: 'Example app',
344
+ to: 'alex@example.com',
345
+ subject: 'Welcome',
346
+ text: 'Hello Alex',
347
+ });
348
+
312
349
  const mails = await notebook.mail.list();
313
350
  const mail = await notebook.mail.get(mails.data[0].hash);
314
351
 
package/dist/app.d.ts ADDED
@@ -0,0 +1,21 @@
1
+ import type { Client } from './index.js';
2
+ import { CustomerRuntime } from './customers.js';
3
+ import { PaymentRuntime, type PaymentMode } from './payments.js';
4
+ export interface AppRuntimeOptions {
5
+ /** Defaults to live in production and test otherwise. There is no fallback between modes. */
6
+ mode?: PaymentMode;
7
+ /** Supply server bindings explicitly on runtimes without process.env. */
8
+ env?: Record<string, string | undefined>;
9
+ }
10
+ export declare function resolveAppConfiguration(options: AppRuntimeOptions): {
11
+ mode: "test" | "live";
12
+ token: string;
13
+ url: string;
14
+ };
15
+ /** Scoped app-server APIs. Organization and workspace management are deliberately excluded. */
16
+ export declare class AppRuntime {
17
+ readonly mode: PaymentMode;
18
+ readonly customers: CustomerRuntime;
19
+ readonly payments: PaymentRuntime;
20
+ constructor(client: Client, token: string, mode: PaymentMode);
21
+ }
package/dist/app.js ADDED
@@ -0,0 +1,23 @@
1
+ import { CustomerRuntime } from './customers.js';
2
+ import { PaymentRuntime } from './payments.js';
3
+ export function resolveAppConfiguration(options) {
4
+ if (typeof window !== 'undefined' && typeof document !== 'undefined') {
5
+ throw new Error('Application credentials must only be used on a trusted server.');
6
+ }
7
+ const environment = options.env ?? (typeof process === 'undefined' ? {} : process.env);
8
+ const mode = options.mode ?? (environment.NODE_ENV === 'production' ? 'live' : 'test');
9
+ const token = environment[`PHPSANDBOX_APP_${mode.toUpperCase()}_TOKEN`];
10
+ const url = environment.PHPSANDBOX_APP_API_URL;
11
+ if (!token || !/^happ_[a-f0-9]{64}$/.test(token) || !url) {
12
+ throw new Error(`Connect your app's ${mode === 'live' ? 'production' : 'development'} platform environment before using Customers or Payments.`);
13
+ }
14
+ return { mode, token, url };
15
+ }
16
+ /** Scoped app-server APIs. Organization and workspace management are deliberately excluded. */
17
+ export class AppRuntime {
18
+ constructor(client, token, mode) {
19
+ this.mode = mode;
20
+ this.customers = new CustomerRuntime(client);
21
+ this.payments = new PaymentRuntime(client, { token, mode });
22
+ }
23
+ }