@cedros/pay-react 1.1.26 → 1.1.27
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 +163 -13
- package/package.json +14 -1
package/README.md
CHANGED
|
@@ -370,6 +370,8 @@ cargo install cedros-pay-server
|
|
|
370
370
|
- `POST /paywall/v1/stripe-session` - Create Stripe checkout (single item)
|
|
371
371
|
- `GET /paywall/v1/stripe-session/verify` - Verify Stripe payment session (security-critical)
|
|
372
372
|
- `POST /paywall/v1/cart/checkout` - Create Stripe checkout (cart)
|
|
373
|
+
- `POST /paywall/v1/subscription/stripe-session` - Create Stripe subscription checkout
|
|
374
|
+
- `POST /paywall/v1/subscription/stripe-mobile-session` - Create Stripe-native mobile subscription session
|
|
373
375
|
- `POST /paywall/v1/cart/quote` - Get x402 quote for cart items
|
|
374
376
|
- `POST /paywall/v1/gasless-transaction` - Build gasless transaction (optional)
|
|
375
377
|
- `POST /paywall/v1/nonce` - Generate nonce for admin authentication
|
|
@@ -378,6 +380,34 @@ cargo install cedros-pay-server
|
|
|
378
380
|
- `POST /paywall/v1/refunds/approve` - Get fresh quote for pending refund (admin-only)
|
|
379
381
|
- `POST /paywall/v1/refunds/deny` - Deny pending refund (admin-only)
|
|
380
382
|
|
|
383
|
+
**Turnkey cross-channel setup**
|
|
384
|
+
|
|
385
|
+
Cedros is designed so you create the product once in the admin dashboard and then let the packages choose the right payment rail for web, Apple App Store, and Google Play at runtime.
|
|
386
|
+
|
|
387
|
+
For the full operator runbook, see [`ui/docs/cross-channel-setup.md`](./docs/cross-channel-setup.md).
|
|
388
|
+
|
|
389
|
+
1. In **Admin → Products**, create the product and set:
|
|
390
|
+
- the normal commerce fields such as title, price, fulfillment, and checkout requirements
|
|
391
|
+
- the **Store policy classification** such as `digital_in_app`, `physical_goods`, `real_world_service`, or `reader_content`
|
|
392
|
+
- the **store-managed product kind** plus any Apple product ID or Google Play product/base-plan mapping when the product is sold inside app-store builds
|
|
393
|
+
2. In **Admin → Payment Options → Stripe**, add your Stripe API keys, webhook secret, and any mobile redirect URI schemes you use.
|
|
394
|
+
3. In **Admin → Payment Options → App Stores**, add:
|
|
395
|
+
- Apple issuer ID, key ID, private key, and bundle ID
|
|
396
|
+
- Google service-account credentials, package name, RTDN push identity, and push audience
|
|
397
|
+
4. In Stripe, App Store Connect, and Google Play Console, create the matching products and point their webhooks / notifications at your Cedros server endpoints.
|
|
398
|
+
5. In your React Native app, set Cedros provider config once for the build, especially `distributionChannel`, and Cedros will hydrate the product catalog from `/paywall/v1/products` automatically unless you disable catalog sync.
|
|
399
|
+
|
|
400
|
+
**Manual setup that still matters**
|
|
401
|
+
|
|
402
|
+
- Stripe:
|
|
403
|
+
Use the Cedros Stripe webhook endpoint so subscription and Checkout lifecycle events reach Cedros.
|
|
404
|
+
- Apple:
|
|
405
|
+
Create matching App Store Connect products and configure App Store Server Notifications to your tenant-scoped Cedros Apple notification URL.
|
|
406
|
+
- Google:
|
|
407
|
+
Create matching Play Console products and configure Real-time developer notifications to your tenant-scoped Cedros Google notification URL.
|
|
408
|
+
- Store policy exceptions:
|
|
409
|
+
Only enable reader-app, external-link, User Choice Billing, Alternative Billing Only, or external-offers behavior when your app is actually approved for those storefront programs.
|
|
410
|
+
|
|
381
411
|
**Example - Quote Request:**
|
|
382
412
|
|
|
383
413
|
```bash
|
|
@@ -424,6 +454,44 @@ X-Signer: <wallet-address>
|
|
|
424
454
|
# Only one refund allowed per transaction signature
|
|
425
455
|
```
|
|
426
456
|
|
|
457
|
+
**React Native Stripe subscriptions**
|
|
458
|
+
|
|
459
|
+
- Cedros now supports two explicit Stripe subscription flows on mobile.
|
|
460
|
+
- Hosted redirect checkout remains the stock default:
|
|
461
|
+
|
|
462
|
+
```json
|
|
463
|
+
{
|
|
464
|
+
"flow": "redirect_checkout",
|
|
465
|
+
"sessionId": "cs_test_123",
|
|
466
|
+
"url": "https://checkout.stripe.com/c/pay/cs_test_123"
|
|
467
|
+
}
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
- `@cedros/pay-react-native` opens `url` automatically in the device browser for this flow.
|
|
471
|
+
- Native mobile subscriptions use a dedicated PaymentSheet contract from `POST /paywall/v1/subscription/stripe-mobile-session`:
|
|
472
|
+
|
|
473
|
+
```json
|
|
474
|
+
{
|
|
475
|
+
"flow": "payment_sheet",
|
|
476
|
+
"subscriptionId": "sub_123",
|
|
477
|
+
"customerId": "cus_123",
|
|
478
|
+
"customerEphemeralKeySecret": "ephkey_123",
|
|
479
|
+
"paymentIntentClientSecret": "pi_123_secret_abc"
|
|
480
|
+
}
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
- In React Native, use `SubscribeButton` with `flow="payment_sheet"` or call `subscriptionManager.processMobileSubscription(...)` directly when you want the native Stripe sheet.
|
|
484
|
+
- Set `stripeReturnUrl` in `CedrosProvider` for PaymentSheet app return handling on iOS, for example `covenant://stripe-return`.
|
|
485
|
+
- If Stripe should return to your app via a custom deep link such as `covenant://subscription/success`, allowlist the URI scheme on the server with `stripe.allowed_redirect_schemes` or `CEDROS_STRIPE_ALLOWED_REDIRECT_SCHEMES=covenant`.
|
|
486
|
+
- Universal links such as `https://app.example.com/subscription/success` do not need to be allowlisted.
|
|
487
|
+
|
|
488
|
+
**React Native store-aware product sync**
|
|
489
|
+
|
|
490
|
+
- `@cedros/pay-react-native` can now hydrate its provider-level store policy catalog from `GET /paywall/v1/products`.
|
|
491
|
+
- By default, Cedros merges the server catalog with any manually supplied `paymentPolicy.productCatalog`, with manual entries taking precedence.
|
|
492
|
+
- This means the host app can usually pass just the product id to `CedrosPay` while keeping the canonical fulfillment and store-product mapping in the Cedros admin dashboard.
|
|
493
|
+
- If you need to disable that behavior, set `paymentPolicy.productCatalogSync.enabled` to `false`.
|
|
494
|
+
|
|
427
495
|
**Example - Get Pending Refunds (Admin - Nonce Required):**
|
|
428
496
|
|
|
429
497
|
```bash
|
|
@@ -1473,24 +1541,30 @@ function AdminPage() {
|
|
|
1473
1541
|
|
|
1474
1542
|
### Unified Dashboard with Plugin System
|
|
1475
1543
|
|
|
1476
|
-
For apps using both **cedros-login** and **cedros-pay**, use
|
|
1544
|
+
For apps using both **cedros-login** and **cedros-pay**, use `AdminShell` from `@cedros/admin-react` with both plugins to create a combined admin interface:
|
|
1477
1545
|
|
|
1478
1546
|
```tsx
|
|
1479
|
-
import { AdminShell,
|
|
1480
|
-
import {
|
|
1547
|
+
import { AdminShell, HOST_SERVICE_IDS } from "@cedros/admin-react";
|
|
1548
|
+
import {
|
|
1549
|
+
cedrosLoginPlugin,
|
|
1550
|
+
useCedrosLogin,
|
|
1551
|
+
} from "@cedros/login-react/admin-only";
|
|
1552
|
+
import { cedrosPayPlugin } from "@cedros/pay-react/admin";
|
|
1481
1553
|
|
|
1482
1554
|
function UnifiedAdmin() {
|
|
1483
1555
|
const { user, getAccessToken, serverUrl } = useCedrosLogin();
|
|
1484
1556
|
|
|
1485
1557
|
// Build host context from your auth providers
|
|
1486
1558
|
const hostContext = {
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1559
|
+
services: {
|
|
1560
|
+
[HOST_SERVICE_IDS.cedrosLogin]: {
|
|
1561
|
+
user,
|
|
1562
|
+
getAccessToken,
|
|
1563
|
+
serverUrl,
|
|
1564
|
+
},
|
|
1565
|
+
[HOST_SERVICE_IDS.cedrosPay]: {
|
|
1566
|
+
serverUrl: "https://api.example.com",
|
|
1567
|
+
},
|
|
1494
1568
|
},
|
|
1495
1569
|
};
|
|
1496
1570
|
|
|
@@ -1505,7 +1579,7 @@ function UnifiedAdmin() {
|
|
|
1505
1579
|
}
|
|
1506
1580
|
```
|
|
1507
1581
|
|
|
1508
|
-
> **Note:** The
|
|
1582
|
+
> **Note:** The shared admin standard is the shell + plugin contract. `cedros-pay` exports `cedrosPayPlugin` for composition under a single `/admin` dashboard.
|
|
1509
1583
|
|
|
1510
1584
|
### cedrosPayPlugin Sections
|
|
1511
1585
|
|
|
@@ -1554,8 +1628,84 @@ See the [cedros-login documentation](https://github.com/cedros-dev/cedros-login)
|
|
|
1554
1628
|
| `solanaEndpoint` | `string` | Custom Solana RPC endpoint |
|
|
1555
1629
|
| `tokenMint` | `string` | SPL token mint address (default: USDC) - see [Token Mint Validation](#-token-mint-validation) |
|
|
1556
1630
|
| `dangerouslyAllowUnknownMint` | `boolean` | Allow unknown token mints (default: false) - ⚠️ WARNING: Only enable after triple-checking mint address - see [Token Mint Validation](#-token-mint-validation) |
|
|
1631
|
+
| `featureFlags` | `Partial<Record<FeatureFlagName, boolean>>` | Explicit feature flag overrides. Precedence is `config.featureFlags` > environment variable > registry default. |
|
|
1557
1632
|
| `logLevel` | `LogLevel` | Logging verbosity (default: `LogLevel.WARN` in production, `LogLevel.DEBUG` in development) - see [Logging](#-logging) |
|
|
1558
1633
|
|
|
1634
|
+
### Feature Flags
|
|
1635
|
+
|
|
1636
|
+
Cedros Pay uses a central feature flag registry in [`src/featureFlags.ts`](./src/featureFlags.ts). Each flag has one stable positive name, a description, a default value, and a rollout stage. Call sites should read flags through the resolved helper instead of hard-coding boolean checks.
|
|
1637
|
+
|
|
1638
|
+
#### Consumer overrides
|
|
1639
|
+
|
|
1640
|
+
Package consumers can opt into or out of flags in provider config:
|
|
1641
|
+
|
|
1642
|
+
```tsx
|
|
1643
|
+
<CedrosProvider
|
|
1644
|
+
config={{
|
|
1645
|
+
stripePublicKey: "pk_test_...",
|
|
1646
|
+
serverUrl: "https://api.example.com",
|
|
1647
|
+
solanaCluster: "devnet",
|
|
1648
|
+
featureFlags: {
|
|
1649
|
+
complianceCheck: true
|
|
1650
|
+
}
|
|
1651
|
+
}}
|
|
1652
|
+
>
|
|
1653
|
+
<App />
|
|
1654
|
+
</CedrosProvider>
|
|
1655
|
+
```
|
|
1656
|
+
|
|
1657
|
+
Environment variable overrides are also supported when your runtime or bundler exposes `process.env` values to the package:
|
|
1658
|
+
|
|
1659
|
+
```bash
|
|
1660
|
+
CEDROS_FEATURE_COMPLIANCE_CHECK=true
|
|
1661
|
+
```
|
|
1662
|
+
|
|
1663
|
+
Supported boolean env values are `1`, `true`, `yes`, `on`, `0`, `false`, `no`, and `off`.
|
|
1664
|
+
|
|
1665
|
+
#### Adding a new flag
|
|
1666
|
+
|
|
1667
|
+
Define the flag once in [`src/featureFlags.ts`](./src/featureFlags.ts):
|
|
1668
|
+
|
|
1669
|
+
```ts
|
|
1670
|
+
export const FEATURE_FLAG_REGISTRY = defineFeatureFlagRegistry({
|
|
1671
|
+
complianceCheck: {
|
|
1672
|
+
description: 'Enable pre-flight compliance checks before Stripe checkout.',
|
|
1673
|
+
default: false,
|
|
1674
|
+
stage: 'stable',
|
|
1675
|
+
},
|
|
1676
|
+
newParser: {
|
|
1677
|
+
description: 'Use the new parser implementation.',
|
|
1678
|
+
default: false,
|
|
1679
|
+
stage: 'experimental',
|
|
1680
|
+
},
|
|
1681
|
+
});
|
|
1682
|
+
```
|
|
1683
|
+
|
|
1684
|
+
Then resolve it where needed:
|
|
1685
|
+
|
|
1686
|
+
```ts
|
|
1687
|
+
const enabled = isFeatureEnabled('newParser', {
|
|
1688
|
+
featureFlags: config.featureFlags,
|
|
1689
|
+
});
|
|
1690
|
+
```
|
|
1691
|
+
|
|
1692
|
+
#### Flipping the default later
|
|
1693
|
+
|
|
1694
|
+
Use positive names such as `newParser`, not negative names such as `disableNewParser`. That keeps the flag name stable across rollout:
|
|
1695
|
+
|
|
1696
|
+
1. Ship it disabled by default with `default: false`.
|
|
1697
|
+
2. Let consumers opt in with `featureFlags.newParser = true` or `CEDROS_FEATURE_NEW_PARSER=true`.
|
|
1698
|
+
3. When the feature is ready, change only the registry entry to `default: true`.
|
|
1699
|
+
4. Consumers can still opt out temporarily with `false` if they need a rollback window.
|
|
1700
|
+
|
|
1701
|
+
Precedence is always:
|
|
1702
|
+
|
|
1703
|
+
1. Explicit runtime config in `featureFlags`
|
|
1704
|
+
2. Environment variable override
|
|
1705
|
+
3. Registry default
|
|
1706
|
+
|
|
1707
|
+
The existing top-level `complianceCheck` config field is still accepted for backward compatibility, but new integrations should prefer `featureFlags.complianceCheck`.
|
|
1708
|
+
|
|
1559
1709
|
### CedrosPay Component
|
|
1560
1710
|
|
|
1561
1711
|
| Prop | Type | Description |
|
|
@@ -1573,8 +1723,8 @@ See the [cedros-login documentation](https://github.com/cedros-dev/cedros-login)
|
|
|
1573
1723
|
| --------------- | ------------------------ | ---------------------------------- |
|
|
1574
1724
|
| `customerEmail` | `string` | Pre-fill email for Stripe checkout |
|
|
1575
1725
|
| `couponCode` | `string` | Coupon code to apply |
|
|
1576
|
-
| `successUrl` | `string` | Stripe redirect URL on success
|
|
1577
|
-
| `cancelUrl` | `string` | Stripe redirect URL on cancel
|
|
1726
|
+
| `successUrl` | `string` | Stripe redirect URL on success. React Native may use an allowlisted app deep link or universal link. |
|
|
1727
|
+
| `cancelUrl` | `string` | Stripe redirect URL on cancel. React Native may use an allowlisted app deep link or universal link. |
|
|
1578
1728
|
| `metadata` | `Record<string, string>` | Custom tracking data |
|
|
1579
1729
|
|
|
1580
1730
|
#### Display Options
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cedros/pay-react",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.27",
|
|
4
4
|
"description": "React frontend library for Cedros Pay - unified Stripe and Solana x402 payments",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -12,6 +12,12 @@
|
|
|
12
12
|
"import": "./dist/index.mjs",
|
|
13
13
|
"require": "./dist/index.js"
|
|
14
14
|
},
|
|
15
|
+
"./admin": {
|
|
16
|
+
"react-native": "./src/admin.ts",
|
|
17
|
+
"types": "./dist/admin.d.ts",
|
|
18
|
+
"import": "./dist/admin.mjs",
|
|
19
|
+
"require": "./dist/admin.js"
|
|
20
|
+
},
|
|
15
21
|
"./stripe-only": {
|
|
16
22
|
"react-native": "./src/stripe-only.ts",
|
|
17
23
|
"types": "./dist/stripe-only.d.ts",
|
|
@@ -65,6 +71,7 @@
|
|
|
65
71
|
},
|
|
66
72
|
"homepage": "https://github.com/conorholds/cedros-pay/tree/main/ui#readme",
|
|
67
73
|
"peerDependencies": {
|
|
74
|
+
"@cedros/admin-react": "^0.1.0",
|
|
68
75
|
"@cedros/login-react": ">=0.0.4",
|
|
69
76
|
"@solana/spl-token": "^0.4.14",
|
|
70
77
|
"@solana/wallet-adapter-base": "^0.9.23",
|
|
@@ -77,6 +84,9 @@
|
|
|
77
84
|
"react-dom": "^18.0.0 || ^19.0.0"
|
|
78
85
|
},
|
|
79
86
|
"peerDependenciesMeta": {
|
|
87
|
+
"@cedros/admin-react": {
|
|
88
|
+
"optional": true
|
|
89
|
+
},
|
|
80
90
|
"@cedros/login-react": {
|
|
81
91
|
"optional": true
|
|
82
92
|
},
|
|
@@ -120,6 +130,8 @@
|
|
|
120
130
|
"zod": "^4.1.5"
|
|
121
131
|
},
|
|
122
132
|
"devDependencies": {
|
|
133
|
+
"@cedros/admin-react": "file:../../cedros-admin/ui",
|
|
134
|
+
"@cedros/data-react": "file:../../cedros-data/ui",
|
|
123
135
|
"@cedros/login-react": "^0.0.4",
|
|
124
136
|
"@solana/spl-token": "^0.4.14",
|
|
125
137
|
"@solana/wallet-adapter-base": "^0.9.23",
|
|
@@ -171,6 +183,7 @@
|
|
|
171
183
|
"storybook": "storybook dev -p 6006",
|
|
172
184
|
"build-storybook": "storybook build",
|
|
173
185
|
"prepublishOnly": "npm run lint && npm run type-check && npm test && npm run build",
|
|
186
|
+
"prepack": "npm run build",
|
|
174
187
|
"prepare": "husky"
|
|
175
188
|
},
|
|
176
189
|
"overrides": {
|