@digilogiclabs/saas-factory-payments 0.1.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/LICENSE +22 -0
- package/README.md +679 -0
- package/dist/index.d.mts +365 -0
- package/dist/index.d.ts +365 -0
- package/dist/index.js +869 -0
- package/dist/index.mjs +806 -0
- package/dist/native/index.d.mts +266 -0
- package/dist/native/index.d.ts +266 -0
- package/dist/native/index.js +1833 -0
- package/dist/native/index.mjs +1815 -0
- package/dist/server/index.d.mts +122 -0
- package/dist/server/index.d.ts +122 -0
- package/dist/server/index.js +484 -0
- package/dist/server/index.mjs +443 -0
- package/dist/web/index.d.mts +281 -0
- package/dist/web/index.d.ts +281 -0
- package/dist/web/index.js +1651 -0
- package/dist/web/index.mjs +1604 -0
- package/package.json +153 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 DigiLogicLabs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
package/README.md
ADDED
|
@@ -0,0 +1,679 @@
|
|
|
1
|
+
# @digilogiclabs/saas-factory-payments
|
|
2
|
+
|
|
3
|
+
A comprehensive payments package for SaaS Factory that works seamlessly in both Next.js and React Native environments. Built with TypeScript and designed to be provider-agnostic (currently supporting Stripe with plans for Paddle, LemonSqueezy, and more).
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🌐 **Hybrid Support**: Works in both Next.js web applications and React Native mobile apps
|
|
8
|
+
- 🔒 **Type-Safe**: Built with TypeScript for better developer experience
|
|
9
|
+
- 🎨 **UI Components**: Pre-built components for checkout, pricing tables, and billing management
|
|
10
|
+
- 🪝 **React Hooks**: Powerful hooks for subscription and customer management
|
|
11
|
+
- 🔧 **Server Utilities**: Complete server-side API and webhook handling
|
|
12
|
+
- 📱 **Mobile-First**: Native mobile payment flows with Stripe React Native
|
|
13
|
+
- 🎯 **Provider-Agnostic**: Extensible architecture for multiple payment providers
|
|
14
|
+
- 🚀 **CLI Integration**: Works seamlessly with create-saas-app
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @digilogiclabs/saas-factory-payments
|
|
20
|
+
# or
|
|
21
|
+
yarn add @digilogiclabs/saas-factory-payments
|
|
22
|
+
# or
|
|
23
|
+
pnpm add @digilogiclabs/saas-factory-payments
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Peer Dependencies
|
|
27
|
+
|
|
28
|
+
The package requires different peer dependencies based on your platform:
|
|
29
|
+
|
|
30
|
+
**For Web (Next.js):**
|
|
31
|
+
```bash
|
|
32
|
+
npm install @stripe/stripe-js @stripe/react-stripe-js stripe
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**For React Native:**
|
|
36
|
+
```bash
|
|
37
|
+
npm install @stripe/stripe-react-native stripe
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**For Server-side:**
|
|
41
|
+
```bash
|
|
42
|
+
npm install stripe
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
## Quick Start
|
|
49
|
+
|
|
50
|
+
### 1. Setup Providers
|
|
51
|
+
|
|
52
|
+
First, wrap your app with the PaymentsProvider and platform-specific StripeProvider:
|
|
53
|
+
|
|
54
|
+
**Web (Next.js) - `pages/_app.tsx`:**
|
|
55
|
+
```tsx
|
|
56
|
+
import { PaymentsProvider } from '@digilogiclabs/saas-factory-payments';
|
|
57
|
+
import { StripeProvider } from '@digilogiclabs/saas-factory-payments/web';
|
|
58
|
+
|
|
59
|
+
export default function App({ Component, pageProps }) {
|
|
60
|
+
return (
|
|
61
|
+
<PaymentsProvider
|
|
62
|
+
config={{
|
|
63
|
+
provider: 'stripe',
|
|
64
|
+
publishableKey: process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!,
|
|
65
|
+
environment: process.env.NODE_ENV as 'development' | 'production',
|
|
66
|
+
}}
|
|
67
|
+
>
|
|
68
|
+
<StripeProvider>
|
|
69
|
+
<Component {...pageProps} />
|
|
70
|
+
</StripeProvider>
|
|
71
|
+
</PaymentsProvider>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**React Native - `App.tsx`:**
|
|
77
|
+
```tsx
|
|
78
|
+
import { PaymentsProvider } from '@digilogiclabs/saas-factory-payments';
|
|
79
|
+
import { StripeProvider } from '@digilogiclabs/saas-factory-payments/native';
|
|
80
|
+
|
|
81
|
+
export default function App() {
|
|
82
|
+
return (
|
|
83
|
+
<PaymentsProvider
|
|
84
|
+
config={{
|
|
85
|
+
provider: 'stripe',
|
|
86
|
+
publishableKey: process.env.EXPO_PUBLIC_STRIPE_PUBLISHABLE_KEY!,
|
|
87
|
+
environment: __DEV__ ? 'development' : 'production',
|
|
88
|
+
}}
|
|
89
|
+
>
|
|
90
|
+
<StripeProvider>
|
|
91
|
+
<MainApp />
|
|
92
|
+
</StripeProvider>
|
|
93
|
+
</PaymentsProvider>
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 2. Use Components
|
|
99
|
+
|
|
100
|
+
**Checkout Button (Web):**
|
|
101
|
+
```tsx
|
|
102
|
+
import { CheckoutButton } from '@digilogiclabs/saas-factory-payments/web';
|
|
103
|
+
|
|
104
|
+
export default function PricingPage() {
|
|
105
|
+
return (
|
|
106
|
+
<CheckoutButton
|
|
107
|
+
priceId="price_basic_monthly"
|
|
108
|
+
onSuccess={() => console.log('Payment successful!')}
|
|
109
|
+
onError={(error) => console.error('Payment failed:', error)}
|
|
110
|
+
>
|
|
111
|
+
Subscribe to Basic Plan
|
|
112
|
+
</CheckoutButton>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**Checkout Button (React Native):**
|
|
118
|
+
```tsx
|
|
119
|
+
import { CheckoutButton } from '@digilogiclabs/saas-factory-payments/native';
|
|
120
|
+
|
|
121
|
+
export default function PricingScreen() {
|
|
122
|
+
return (
|
|
123
|
+
<CheckoutButton
|
|
124
|
+
priceId="price_basic_monthly"
|
|
125
|
+
onSuccess={() => navigation.navigate('Success')}
|
|
126
|
+
onError={(error) => Alert.alert('Error', error)}
|
|
127
|
+
>
|
|
128
|
+
Subscribe to Basic Plan
|
|
129
|
+
</CheckoutButton>
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### 3. Manage Subscriptions
|
|
135
|
+
|
|
136
|
+
```tsx
|
|
137
|
+
import { useSubscription } from '@digilogiclabs/saas-factory-payments/web'; // or /native
|
|
138
|
+
|
|
139
|
+
function SubscriptionManager({ customerId }) {
|
|
140
|
+
const { subscription, loading, cancel, reactivate } = useSubscription({
|
|
141
|
+
customerId,
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
if (loading) return <div>Loading...</div>;
|
|
145
|
+
|
|
146
|
+
return (
|
|
147
|
+
<div>
|
|
148
|
+
<h3>Current Subscription</h3>
|
|
149
|
+
<p>Status: {subscription?.status}</p>
|
|
150
|
+
<p>Plan: {subscription?.priceId}</p>
|
|
151
|
+
|
|
152
|
+
{subscription?.status === 'active' && (
|
|
153
|
+
<button onClick={() => cancel()}>
|
|
154
|
+
Cancel Subscription
|
|
155
|
+
</button>
|
|
156
|
+
)}
|
|
157
|
+
|
|
158
|
+
{subscription?.cancelAtPeriodEnd && (
|
|
159
|
+
<button onClick={() => reactivate()}>
|
|
160
|
+
Reactivate Subscription
|
|
161
|
+
</button>
|
|
162
|
+
)}
|
|
163
|
+
</div>
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
## API Reference
|
|
170
|
+
|
|
171
|
+
### Components
|
|
172
|
+
|
|
173
|
+
#### CheckoutButton
|
|
174
|
+
|
|
175
|
+
A button component that handles subscription or one-time payment checkout.
|
|
176
|
+
|
|
177
|
+
**Props:**
|
|
178
|
+
- `priceId` (string): Stripe price ID
|
|
179
|
+
- `customerId?` (string): Existing customer ID
|
|
180
|
+
- `customerEmail?` (string): Customer email for new customers
|
|
181
|
+
- `successUrl?` (string): Redirect URL after successful payment
|
|
182
|
+
- `cancelUrl?` (string): Redirect URL after cancelled payment
|
|
183
|
+
- `onSuccess?` (function): Callback for successful payment
|
|
184
|
+
- `onError?` (function): Callback for payment errors
|
|
185
|
+
- `children` (ReactNode): Button content
|
|
186
|
+
|
|
187
|
+
#### PricingTable
|
|
188
|
+
|
|
189
|
+
A responsive pricing table component with multiple plans.
|
|
190
|
+
|
|
191
|
+
**Props:**
|
|
192
|
+
- `plans` (PricingPlan[]): Array of pricing plans
|
|
193
|
+
- `customerId?` (string): Customer ID for checkout
|
|
194
|
+
- `showFeatures?` (boolean): Whether to show plan features
|
|
195
|
+
- `layout?` ('grid' | 'list' | 'carousel'): Layout style
|
|
196
|
+
- `onPlanSelect?` (function): Callback when plan is selected
|
|
197
|
+
|
|
198
|
+
#### PaymentForm
|
|
199
|
+
|
|
200
|
+
An inline payment form for direct payment processing.
|
|
201
|
+
|
|
202
|
+
**Props:**
|
|
203
|
+
- `clientSecret?` (string): Payment intent client secret
|
|
204
|
+
- `amount?` (number): Payment amount in cents
|
|
205
|
+
- `currency?` (string): Payment currency
|
|
206
|
+
- `onSuccess?` (function): Success callback
|
|
207
|
+
- `onError?` (function): Error callback
|
|
208
|
+
|
|
209
|
+
#### BillingPortal (Web only)
|
|
210
|
+
|
|
211
|
+
A button that opens the Stripe Customer Portal for subscription management.
|
|
212
|
+
|
|
213
|
+
**Props:**
|
|
214
|
+
- `customerId` (string): Customer ID
|
|
215
|
+
- `returnUrl?` (string): Return URL after portal session
|
|
216
|
+
- `onSuccess?` (function): Success callback
|
|
217
|
+
- `onError?` (function): Error callback
|
|
218
|
+
|
|
219
|
+
### Hooks
|
|
220
|
+
|
|
221
|
+
#### useSubscription
|
|
222
|
+
|
|
223
|
+
Hook for managing customer subscriptions.
|
|
224
|
+
|
|
225
|
+
```tsx
|
|
226
|
+
const {
|
|
227
|
+
subscription,
|
|
228
|
+
subscriptions,
|
|
229
|
+
loading,
|
|
230
|
+
error,
|
|
231
|
+
refetch,
|
|
232
|
+
cancel,
|
|
233
|
+
reactivate,
|
|
234
|
+
updatePaymentMethod,
|
|
235
|
+
} = useSubscription({ customerId });
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
#### useCheckout
|
|
239
|
+
|
|
240
|
+
Hook for handling checkout processes.
|
|
241
|
+
|
|
242
|
+
```tsx
|
|
243
|
+
const {
|
|
244
|
+
loading,
|
|
245
|
+
error,
|
|
246
|
+
createCheckoutSession,
|
|
247
|
+
redirectToCheckout,
|
|
248
|
+
createPaymentIntent,
|
|
249
|
+
} = useCheckout({
|
|
250
|
+
onSuccess: (sessionId) => console.log('Success:', sessionId),
|
|
251
|
+
onError: (error) => console.error('Error:', error),
|
|
252
|
+
});
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
#### useCustomer
|
|
256
|
+
|
|
257
|
+
Hook for customer management.
|
|
258
|
+
|
|
259
|
+
```tsx
|
|
260
|
+
const {
|
|
261
|
+
customer,
|
|
262
|
+
paymentMethods,
|
|
263
|
+
loading,
|
|
264
|
+
error,
|
|
265
|
+
createCustomer,
|
|
266
|
+
updateCustomer,
|
|
267
|
+
fetchPaymentMethods,
|
|
268
|
+
} = useCustomer({ customerId });
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
#### usePayments
|
|
272
|
+
|
|
273
|
+
High-level hook that combines customer and subscription management.
|
|
274
|
+
|
|
275
|
+
```tsx
|
|
276
|
+
const {
|
|
277
|
+
customer,
|
|
278
|
+
subscriptions,
|
|
279
|
+
activeSubscription,
|
|
280
|
+
loading,
|
|
281
|
+
createCustomer,
|
|
282
|
+
subscribe,
|
|
283
|
+
cancelSubscription,
|
|
284
|
+
hasActiveSubscription,
|
|
285
|
+
isSubscribedToPlan,
|
|
286
|
+
} = usePayments({ customerId });
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
### Server-Side Utilities
|
|
291
|
+
|
|
292
|
+
#### StripeServerAPI
|
|
293
|
+
|
|
294
|
+
Complete server-side Stripe API wrapper.
|
|
295
|
+
|
|
296
|
+
```tsx
|
|
297
|
+
import { StripeServerAPI } from '@digilogiclabs/saas-factory-payments/server';
|
|
298
|
+
|
|
299
|
+
const stripeAPI = new StripeServerAPI(process.env.STRIPE_SECRET_KEY!);
|
|
300
|
+
|
|
301
|
+
// Create customer
|
|
302
|
+
const customer = await stripeAPI.createCustomer({
|
|
303
|
+
email: 'user@example.com',
|
|
304
|
+
name: 'John Doe',
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
// Create subscription
|
|
308
|
+
const subscription = await stripeAPI.createSubscription({
|
|
309
|
+
customerId: customer.id,
|
|
310
|
+
priceId: 'price_basic_monthly',
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
// Create checkout session
|
|
314
|
+
const session = await stripeAPI.createCheckoutSession({
|
|
315
|
+
priceId: 'price_basic_monthly',
|
|
316
|
+
successUrl: 'https://yourapp.com/success',
|
|
317
|
+
cancelUrl: 'https://yourapp.com/cancel',
|
|
318
|
+
});
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
#### Webhook Handling
|
|
322
|
+
|
|
323
|
+
Handle Stripe webhooks with built-in event processing.
|
|
324
|
+
|
|
325
|
+
**Next.js API Route (`pages/api/webhooks/stripe.ts`):**
|
|
326
|
+
```tsx
|
|
327
|
+
import { createNextJSWebhookHandler } from '@digilogiclabs/saas-factory-payments/server';
|
|
328
|
+
|
|
329
|
+
export default createNextJSWebhookHandler(
|
|
330
|
+
process.env.STRIPE_SECRET_KEY!,
|
|
331
|
+
process.env.STRIPE_WEBHOOK_SECRET!,
|
|
332
|
+
{
|
|
333
|
+
onCustomerSubscriptionCreated: async (subscription) => {
|
|
334
|
+
// Handle new subscription
|
|
335
|
+
console.log('New subscription:', subscription.id);
|
|
336
|
+
},
|
|
337
|
+
onInvoicePaymentSucceeded: async (invoice) => {
|
|
338
|
+
// Handle successful payment
|
|
339
|
+
console.log('Payment succeeded:', invoice.id);
|
|
340
|
+
},
|
|
341
|
+
onInvoicePaymentFailed: async (invoice) => {
|
|
342
|
+
// Handle failed payment
|
|
343
|
+
console.log('Payment failed:', invoice.id);
|
|
344
|
+
},
|
|
345
|
+
}
|
|
346
|
+
);
|
|
347
|
+
|
|
348
|
+
export const config = {
|
|
349
|
+
api: {
|
|
350
|
+
bodyParser: {
|
|
351
|
+
sizeLimit: '1mb',
|
|
352
|
+
},
|
|
353
|
+
},
|
|
354
|
+
};
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
**Express.js:**
|
|
358
|
+
```tsx
|
|
359
|
+
import express from 'express';
|
|
360
|
+
import { createStripeWebhookMiddleware } from '@digilogiclabs/saas-factory-payments/server';
|
|
361
|
+
|
|
362
|
+
const app = express();
|
|
363
|
+
|
|
364
|
+
app.use('/webhooks/stripe', express.raw({ type: 'application/json' }));
|
|
365
|
+
app.use('/webhooks/stripe', createStripeWebhookMiddleware(
|
|
366
|
+
process.env.STRIPE_SECRET_KEY!,
|
|
367
|
+
process.env.STRIPE_WEBHOOK_SECRET!,
|
|
368
|
+
{
|
|
369
|
+
onCustomerSubscriptionCreated: async (subscription) => {
|
|
370
|
+
// Handle subscription creation
|
|
371
|
+
},
|
|
372
|
+
}
|
|
373
|
+
));
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
## Configuration
|
|
377
|
+
|
|
378
|
+
### Environment Variables
|
|
379
|
+
|
|
380
|
+
Create a `.env.local` file (Next.js) or configure your environment:
|
|
381
|
+
|
|
382
|
+
```bash
|
|
383
|
+
# Stripe Configuration
|
|
384
|
+
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_...
|
|
385
|
+
STRIPE_SECRET_KEY=sk_test_...
|
|
386
|
+
STRIPE_WEBHOOK_SECRET=whsec_...
|
|
387
|
+
|
|
388
|
+
# For React Native (Expo)
|
|
389
|
+
EXPO_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_...
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
### PaymentsProvider Configuration
|
|
393
|
+
|
|
394
|
+
```tsx
|
|
395
|
+
interface PaymentsConfig {
|
|
396
|
+
provider: 'stripe'; // More providers coming soon
|
|
397
|
+
publishableKey: string;
|
|
398
|
+
secretKey?: string; // Server-side only
|
|
399
|
+
webhookSecret?: string; // Server-side only
|
|
400
|
+
environment: 'development' | 'production';
|
|
401
|
+
}
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
### Pricing Plans Configuration
|
|
405
|
+
|
|
406
|
+
```tsx
|
|
407
|
+
interface PricingPlan {
|
|
408
|
+
id: string;
|
|
409
|
+
name: string;
|
|
410
|
+
description?: string;
|
|
411
|
+
price: number; // In cents
|
|
412
|
+
currency: string;
|
|
413
|
+
interval: 'day' | 'week' | 'month' | 'year';
|
|
414
|
+
stripePriceId: string;
|
|
415
|
+
features: string[];
|
|
416
|
+
popular?: boolean;
|
|
417
|
+
trialPeriodDays?: number;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
const plans: PricingPlan[] = [
|
|
421
|
+
{
|
|
422
|
+
id: 'basic',
|
|
423
|
+
name: 'Basic Plan',
|
|
424
|
+
description: 'Perfect for getting started',
|
|
425
|
+
price: 999, // $9.99
|
|
426
|
+
currency: 'USD',
|
|
427
|
+
interval: 'month',
|
|
428
|
+
stripePriceId: 'price_basic_monthly',
|
|
429
|
+
features: [
|
|
430
|
+
'Up to 10 projects',
|
|
431
|
+
'Basic support',
|
|
432
|
+
'1GB storage',
|
|
433
|
+
],
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
id: 'pro',
|
|
437
|
+
name: 'Pro Plan',
|
|
438
|
+
description: 'For growing businesses',
|
|
439
|
+
price: 1999, // $19.99
|
|
440
|
+
currency: 'USD',
|
|
441
|
+
interval: 'month',
|
|
442
|
+
stripePriceId: 'price_pro_monthly',
|
|
443
|
+
features: [
|
|
444
|
+
'Unlimited projects',
|
|
445
|
+
'Priority support',
|
|
446
|
+
'10GB storage',
|
|
447
|
+
'Advanced analytics',
|
|
448
|
+
],
|
|
449
|
+
popular: true,
|
|
450
|
+
},
|
|
451
|
+
];
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
## Examples
|
|
456
|
+
|
|
457
|
+
### Complete Pricing Page (Web)
|
|
458
|
+
|
|
459
|
+
```tsx
|
|
460
|
+
import { useState } from 'react';
|
|
461
|
+
import { PricingTable, BillingPortal } from '@digilogiclabs/saas-factory-payments/web';
|
|
462
|
+
import { usePayments } from '@digilogiclabs/saas-factory-payments';
|
|
463
|
+
|
|
464
|
+
const plans = [
|
|
465
|
+
{
|
|
466
|
+
id: 'basic',
|
|
467
|
+
name: 'Basic',
|
|
468
|
+
price: 999,
|
|
469
|
+
currency: 'USD',
|
|
470
|
+
interval: 'month',
|
|
471
|
+
stripePriceId: 'price_basic_monthly',
|
|
472
|
+
features: ['Feature 1', 'Feature 2'],
|
|
473
|
+
},
|
|
474
|
+
{
|
|
475
|
+
id: 'pro',
|
|
476
|
+
name: 'Pro',
|
|
477
|
+
price: 1999,
|
|
478
|
+
currency: 'USD',
|
|
479
|
+
interval: 'month',
|
|
480
|
+
stripePriceId: 'price_pro_monthly',
|
|
481
|
+
features: ['All Basic features', 'Feature 3', 'Feature 4'],
|
|
482
|
+
popular: true,
|
|
483
|
+
},
|
|
484
|
+
];
|
|
485
|
+
|
|
486
|
+
export default function PricingPage() {
|
|
487
|
+
const [customerId] = useState('cus_example123');
|
|
488
|
+
const { hasActiveSubscription } = usePayments({ customerId });
|
|
489
|
+
|
|
490
|
+
if (hasActiveSubscription()) {
|
|
491
|
+
return (
|
|
492
|
+
<div className="text-center py-8">
|
|
493
|
+
<h2>Manage Your Subscription</h2>
|
|
494
|
+
<BillingPortal customerId={customerId}>
|
|
495
|
+
Manage Billing
|
|
496
|
+
</BillingPortal>
|
|
497
|
+
</div>
|
|
498
|
+
);
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
return (
|
|
502
|
+
<div className="max-w-6xl mx-auto px-4 py-8">
|
|
503
|
+
<h1 className="text-3xl font-bold text-center mb-8">Choose Your Plan</h1>
|
|
504
|
+
<PricingTable
|
|
505
|
+
plans={plans}
|
|
506
|
+
customerId={customerId}
|
|
507
|
+
onCheckoutSuccess={(plan) => {
|
|
508
|
+
console.log(`Successfully subscribed to ${plan.name}`);
|
|
509
|
+
}}
|
|
510
|
+
/>
|
|
511
|
+
</div>
|
|
512
|
+
);
|
|
513
|
+
}
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
### Mobile Subscription Flow (React Native)
|
|
517
|
+
|
|
518
|
+
```tsx
|
|
519
|
+
import React from 'react';
|
|
520
|
+
import { View, Text, StyleSheet } from 'react-native';
|
|
521
|
+
import { PricingTable } from '@digilogiclabs/saas-factory-payments/native';
|
|
522
|
+
import { usePayments } from '@digilogiclabs/saas-factory-payments';
|
|
523
|
+
|
|
524
|
+
const plans = [
|
|
525
|
+
// Same plans as above
|
|
526
|
+
];
|
|
527
|
+
|
|
528
|
+
export default function PricingScreen({ navigation, customerId }) {
|
|
529
|
+
const { hasActiveSubscription } = usePayments({ customerId });
|
|
530
|
+
|
|
531
|
+
if (hasActiveSubscription()) {
|
|
532
|
+
return (
|
|
533
|
+
<View style={styles.container}>
|
|
534
|
+
<Text style={styles.title}>You're all set!</Text>
|
|
535
|
+
<Text style={styles.subtitle}>
|
|
536
|
+
Manage your subscription in the account settings.
|
|
537
|
+
</Text>
|
|
538
|
+
</View>
|
|
539
|
+
);
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
return (
|
|
543
|
+
<View style={styles.container}>
|
|
544
|
+
<Text style={styles.title}>Choose Your Plan</Text>
|
|
545
|
+
<PricingTable
|
|
546
|
+
plans={plans}
|
|
547
|
+
customerId={customerId}
|
|
548
|
+
layout="carousel"
|
|
549
|
+
onCheckoutSuccess={(plan) => {
|
|
550
|
+
navigation.navigate('Success', { plan: plan.name });
|
|
551
|
+
}}
|
|
552
|
+
/>
|
|
553
|
+
</View>
|
|
554
|
+
);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
const styles = StyleSheet.create({
|
|
558
|
+
container: {
|
|
559
|
+
flex: 1,
|
|
560
|
+
padding: 20,
|
|
561
|
+
},
|
|
562
|
+
title: {
|
|
563
|
+
fontSize: 24,
|
|
564
|
+
fontWeight: 'bold',
|
|
565
|
+
textAlign: 'center',
|
|
566
|
+
marginBottom: 20,
|
|
567
|
+
},
|
|
568
|
+
subtitle: {
|
|
569
|
+
fontSize: 16,
|
|
570
|
+
textAlign: 'center',
|
|
571
|
+
color: '#666',
|
|
572
|
+
},
|
|
573
|
+
});
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
### Server API Routes (Next.js)
|
|
577
|
+
|
|
578
|
+
```tsx
|
|
579
|
+
// pages/api/payments/create-checkout-session.ts
|
|
580
|
+
import { NextApiRequest, NextApiResponse } from 'next';
|
|
581
|
+
import { StripeServerAPI } from '@digilogiclabs/saas-factory-payments/server';
|
|
582
|
+
|
|
583
|
+
const stripeAPI = new StripeServerAPI(process.env.STRIPE_SECRET_KEY!);
|
|
584
|
+
|
|
585
|
+
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
|
586
|
+
if (req.method !== 'POST') {
|
|
587
|
+
return res.status(405).json({ error: 'Method not allowed' });
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
try {
|
|
591
|
+
const { priceId, customerId, successUrl, cancelUrl } = req.body;
|
|
592
|
+
|
|
593
|
+
const session = await stripeAPI.createCheckoutSession({
|
|
594
|
+
priceId,
|
|
595
|
+
customerId,
|
|
596
|
+
successUrl,
|
|
597
|
+
cancelUrl,
|
|
598
|
+
allowPromotionCodes: true,
|
|
599
|
+
});
|
|
600
|
+
|
|
601
|
+
res.status(200).json({ sessionId: session.id });
|
|
602
|
+
} catch (error) {
|
|
603
|
+
console.error('Checkout session error:', error);
|
|
604
|
+
res.status(500).json({ error: 'Failed to create checkout session' });
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
## CLI Integration
|
|
610
|
+
|
|
611
|
+
This package is designed to work seamlessly with `create-saas-app`:
|
|
612
|
+
|
|
613
|
+
```bash
|
|
614
|
+
npx create-saas-app my-saas-app --payments=stripe
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
When using the `--payments=stripe` flag, the CLI will:
|
|
618
|
+
|
|
619
|
+
1. **Install Dependencies**: Automatically install the payments package and required peer dependencies
|
|
620
|
+
2. **Setup Environment**: Create `.env.example` with Stripe configuration variables
|
|
621
|
+
3. **Generate API Routes**: Create Next.js API routes for checkout, webhooks, and subscription management
|
|
622
|
+
4. **Configure Providers**: Set up PaymentsProvider and StripeProvider in your app
|
|
623
|
+
5. **Add Database Schema**: Include subscription and customer tables for your database
|
|
624
|
+
6. **Create Example Components**: Generate a basic pricing page with working checkout
|
|
625
|
+
|
|
626
|
+
### Manual Integration
|
|
627
|
+
|
|
628
|
+
If you're adding payments to an existing project:
|
|
629
|
+
|
|
630
|
+
1. **Install the package and dependencies**
|
|
631
|
+
2. **Set up environment variables**
|
|
632
|
+
3. **Configure providers in your app**
|
|
633
|
+
4. **Create API routes** (see examples above)
|
|
634
|
+
5. **Set up webhook endpoints**
|
|
635
|
+
6. **Add database tables for subscriptions and customers**
|
|
636
|
+
|
|
637
|
+
## TypeScript Support
|
|
638
|
+
|
|
639
|
+
This package is built with TypeScript and provides full type safety:
|
|
640
|
+
|
|
641
|
+
```tsx
|
|
642
|
+
import type {
|
|
643
|
+
PricingPlan,
|
|
644
|
+
Subscription,
|
|
645
|
+
Customer,
|
|
646
|
+
PaymentsConfig
|
|
647
|
+
} from '@digilogiclabs/saas-factory-payments';
|
|
648
|
+
|
|
649
|
+
// All components and hooks are fully typed
|
|
650
|
+
const subscription: Subscription = {
|
|
651
|
+
id: 'sub_123',
|
|
652
|
+
customerId: 'cus_123',
|
|
653
|
+
priceId: 'price_123',
|
|
654
|
+
status: 'active',
|
|
655
|
+
currentPeriodStart: new Date(),
|
|
656
|
+
currentPeriodEnd: new Date(),
|
|
657
|
+
cancelAtPeriodEnd: false,
|
|
658
|
+
};
|
|
659
|
+
```
|
|
660
|
+
|
|
661
|
+
## Contributing
|
|
662
|
+
|
|
663
|
+
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
|
|
664
|
+
|
|
665
|
+
## License
|
|
666
|
+
|
|
667
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|
|
668
|
+
|
|
669
|
+
## Support
|
|
670
|
+
|
|
671
|
+
- 📧 Email: support@digilogiclabs.com
|
|
672
|
+
- 💬 Discord: [Join our community](https://discord.gg/digilogiclabs)
|
|
673
|
+
- 📖 Documentation: [docs.digilogiclabs.com](https://docs.digilogiclabs.com)
|
|
674
|
+
- 🐛 Issues: [GitHub Issues](https://github.com/DigiLogicLabs/saas-factory-payments/issues)
|
|
675
|
+
|
|
676
|
+
---
|
|
677
|
+
|
|
678
|
+
Built with ❤️ by [DigiLogicLabs](https://digilogiclabs.com)
|
|
679
|
+
|