@lavapayments/checkout 0.1.2 → 0.2.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 +55 -16
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +7 -5
- package/dist/index.mjs +8 -6
- package/package.json +4 -9
package/README.md
CHANGED
|
@@ -19,14 +19,14 @@ import { useLavaCheckout } from '@lavapayments/checkout';
|
|
|
19
19
|
import { useState } from 'react';
|
|
20
20
|
|
|
21
21
|
function CheckoutButton() {
|
|
22
|
-
const [
|
|
23
|
-
|
|
22
|
+
const [customerId, setCustomerId] = useState(null);
|
|
23
|
+
|
|
24
24
|
const { open } = useLavaCheckout({
|
|
25
|
-
onSuccess: ({
|
|
25
|
+
onSuccess: ({ customerId }) => {
|
|
26
26
|
console.log('Checkout successful!');
|
|
27
|
-
|
|
28
|
-
// Store the
|
|
29
|
-
|
|
27
|
+
setCustomerId(customerId);
|
|
28
|
+
// Store the customerId for your application
|
|
29
|
+
saveCustomerIdToDatabase(userId, customerId);
|
|
30
30
|
},
|
|
31
31
|
onCancel: ({ checkoutSessionId }) => {
|
|
32
32
|
console.log('Checkout cancelled:', checkoutSessionId);
|
|
@@ -51,32 +51,32 @@ function CheckoutButton() {
|
|
|
51
51
|
}
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
###
|
|
54
|
+
### Credit Bundle Implementation
|
|
55
55
|
|
|
56
|
-
To allow
|
|
56
|
+
To allow existing subscribers to buy a credit pack:
|
|
57
57
|
|
|
58
58
|
```jsx
|
|
59
59
|
import { useLavaCheckout } from '@lavapayments/checkout';
|
|
60
60
|
|
|
61
|
-
function
|
|
61
|
+
function BuyCreditBundleButton({ customerId, creditBundleId }) {
|
|
62
62
|
const { open } = useLavaCheckout({
|
|
63
63
|
onSuccess: () => {
|
|
64
|
-
console.log('
|
|
64
|
+
console.log('Credit bundle purchase successful!');
|
|
65
65
|
// Refresh balance display
|
|
66
66
|
},
|
|
67
67
|
onCancel: () => {
|
|
68
|
-
console.log('
|
|
68
|
+
console.log('Purchase cancelled');
|
|
69
69
|
}
|
|
70
70
|
});
|
|
71
71
|
|
|
72
72
|
return (
|
|
73
73
|
<button
|
|
74
74
|
onClick={() => {
|
|
75
|
-
// Request a
|
|
76
|
-
fetch('/api/create-
|
|
75
|
+
// Request a credit bundle checkout session token from your backend
|
|
76
|
+
fetch('/api/create-bundle-session', {
|
|
77
77
|
method: 'POST',
|
|
78
78
|
headers: { 'Content-Type': 'application/json' },
|
|
79
|
-
body: JSON.stringify({
|
|
79
|
+
body: JSON.stringify({ customerId, creditBundleId })
|
|
80
80
|
})
|
|
81
81
|
.then(res => res.json())
|
|
82
82
|
.then(data => {
|
|
@@ -85,7 +85,7 @@ function TopUpButton({ connectionId }) {
|
|
|
85
85
|
});
|
|
86
86
|
}}
|
|
87
87
|
>
|
|
88
|
-
|
|
88
|
+
Buy Credits
|
|
89
89
|
</button>
|
|
90
90
|
);
|
|
91
91
|
}
|
|
@@ -93,4 +93,43 @@ function TopUpButton({ connectionId }) {
|
|
|
93
93
|
|
|
94
94
|
## Related Documentation
|
|
95
95
|
|
|
96
|
-
For complete documentation on Lava's usage-based billing system and backend integration, visit [
|
|
96
|
+
For complete documentation on Lava's usage-based billing system and backend integration, visit [www.lava.so](https://www.lava.so).
|
|
97
|
+
|
|
98
|
+
## Recommended Subscription Pattern (Logged In + Logged Out)
|
|
99
|
+
|
|
100
|
+
Use the same subscription CTA for both states. Your backend should pass `customer_id` only when you already know the customer.
|
|
101
|
+
|
|
102
|
+
- Logged-out/new customer: omit `customer_id` (checkout collects identity and creates customer)
|
|
103
|
+
- Logged-in/returning customer: include `customer_id` (checkout reuses existing customer)
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
// backend example
|
|
107
|
+
app.post('/api/create-subscription-session', async (req, res) => {
|
|
108
|
+
const { planId, customerId } = req.body;
|
|
109
|
+
|
|
110
|
+
const body: Record<string, string> = {
|
|
111
|
+
checkout_mode: 'subscription',
|
|
112
|
+
origin_url: 'https://your-app.com',
|
|
113
|
+
plan_id: planId,
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
// Include only for known/returning customers
|
|
117
|
+
if (customerId) {
|
|
118
|
+
body.customer_id = customerId;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const lavaRes = await fetch('https://api.lavapayments.com/v1/checkout_sessions', {
|
|
122
|
+
method: 'POST',
|
|
123
|
+
headers: {
|
|
124
|
+
Authorization: `Bearer ${process.env.LAVA_SECRET_KEY}`,
|
|
125
|
+
'Content-Type': 'application/json',
|
|
126
|
+
},
|
|
127
|
+
body: JSON.stringify(body),
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
const session = await lavaRes.json();
|
|
131
|
+
res.json({ checkoutSessionToken: session.checkout_session_token });
|
|
132
|
+
});
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Then in your frontend, always call `open(checkoutSessionToken)` from `useLavaCheckout`.
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
declare function useLavaCheckout({ onSuccess, onCancel, onError, }: {
|
|
2
2
|
onSuccess?: (args: {
|
|
3
3
|
checkoutSessionId: string;
|
|
4
|
-
|
|
4
|
+
customerId: string;
|
|
5
5
|
}) => void;
|
|
6
6
|
onCancel?: (args: {
|
|
7
7
|
checkoutSessionId: string;
|
|
@@ -11,7 +11,7 @@ declare function useLavaCheckout({ onSuccess, onCancel, onError, }: {
|
|
|
11
11
|
error: string;
|
|
12
12
|
}) => void;
|
|
13
13
|
}): {
|
|
14
|
-
open: (
|
|
14
|
+
open: (token: string) => void;
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
export { useLavaCheckout };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
declare function useLavaCheckout({ onSuccess, onCancel, onError, }: {
|
|
2
2
|
onSuccess?: (args: {
|
|
3
3
|
checkoutSessionId: string;
|
|
4
|
-
|
|
4
|
+
customerId: string;
|
|
5
5
|
}) => void;
|
|
6
6
|
onCancel?: (args: {
|
|
7
7
|
checkoutSessionId: string;
|
|
@@ -11,7 +11,7 @@ declare function useLavaCheckout({ onSuccess, onCancel, onError, }: {
|
|
|
11
11
|
error: string;
|
|
12
12
|
}) => void;
|
|
13
13
|
}): {
|
|
14
|
-
open: (
|
|
14
|
+
open: (token: string) => void;
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
export { useLavaCheckout };
|
package/dist/index.js
CHANGED
|
@@ -39,7 +39,7 @@ function useLavaCheckout({
|
|
|
39
39
|
checkoutSession = JSON.parse(
|
|
40
40
|
atob(checkoutSessionToken)
|
|
41
41
|
);
|
|
42
|
-
if (!checkoutSession.secret
|
|
42
|
+
if (!(checkoutSession.secret && checkoutSession.base)) {
|
|
43
43
|
throw new Error("Invalid checkout session token");
|
|
44
44
|
}
|
|
45
45
|
} catch (error) {
|
|
@@ -76,7 +76,7 @@ function useLavaCheckout({
|
|
|
76
76
|
if (typeof onSuccess === "function") {
|
|
77
77
|
onSuccess({
|
|
78
78
|
checkoutSessionId: e.data.checkoutSessionId,
|
|
79
|
-
|
|
79
|
+
customerId: e.data.customerId
|
|
80
80
|
});
|
|
81
81
|
}
|
|
82
82
|
setCheckoutSessionToken(null);
|
|
@@ -87,6 +87,8 @@ function useLavaCheckout({
|
|
|
87
87
|
}
|
|
88
88
|
setCheckoutSessionToken(null);
|
|
89
89
|
break;
|
|
90
|
+
default:
|
|
91
|
+
break;
|
|
90
92
|
}
|
|
91
93
|
}
|
|
92
94
|
function onBeforeUnload(e) {
|
|
@@ -104,9 +106,9 @@ function useLavaCheckout({
|
|
|
104
106
|
iframe = null;
|
|
105
107
|
}
|
|
106
108
|
};
|
|
107
|
-
}, [checkoutSessionToken]);
|
|
108
|
-
const open = (0, import_react.useCallback)((
|
|
109
|
-
setCheckoutSessionToken(
|
|
109
|
+
}, [checkoutSessionToken, onCancel, onError, onSuccess]);
|
|
110
|
+
const open = (0, import_react.useCallback)((token) => {
|
|
111
|
+
setCheckoutSessionToken(token);
|
|
110
112
|
}, []);
|
|
111
113
|
return { open };
|
|
112
114
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import {
|
|
2
|
+
import { useCallback, useEffect, useState } from "react";
|
|
3
3
|
function useLavaCheckout({
|
|
4
4
|
onSuccess,
|
|
5
5
|
onCancel,
|
|
@@ -15,7 +15,7 @@ function useLavaCheckout({
|
|
|
15
15
|
checkoutSession = JSON.parse(
|
|
16
16
|
atob(checkoutSessionToken)
|
|
17
17
|
);
|
|
18
|
-
if (!checkoutSession.secret
|
|
18
|
+
if (!(checkoutSession.secret && checkoutSession.base)) {
|
|
19
19
|
throw new Error("Invalid checkout session token");
|
|
20
20
|
}
|
|
21
21
|
} catch (error) {
|
|
@@ -52,7 +52,7 @@ function useLavaCheckout({
|
|
|
52
52
|
if (typeof onSuccess === "function") {
|
|
53
53
|
onSuccess({
|
|
54
54
|
checkoutSessionId: e.data.checkoutSessionId,
|
|
55
|
-
|
|
55
|
+
customerId: e.data.customerId
|
|
56
56
|
});
|
|
57
57
|
}
|
|
58
58
|
setCheckoutSessionToken(null);
|
|
@@ -63,6 +63,8 @@ function useLavaCheckout({
|
|
|
63
63
|
}
|
|
64
64
|
setCheckoutSessionToken(null);
|
|
65
65
|
break;
|
|
66
|
+
default:
|
|
67
|
+
break;
|
|
66
68
|
}
|
|
67
69
|
}
|
|
68
70
|
function onBeforeUnload(e) {
|
|
@@ -80,9 +82,9 @@ function useLavaCheckout({
|
|
|
80
82
|
iframe = null;
|
|
81
83
|
}
|
|
82
84
|
};
|
|
83
|
-
}, [checkoutSessionToken]);
|
|
84
|
-
const open = useCallback((
|
|
85
|
-
setCheckoutSessionToken(
|
|
85
|
+
}, [checkoutSessionToken, onCancel, onError, onSuccess]);
|
|
86
|
+
const open = useCallback((token) => {
|
|
87
|
+
setCheckoutSessionToken(token);
|
|
86
88
|
}, []);
|
|
87
89
|
return { open };
|
|
88
90
|
}
|
package/package.json
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lavapayments/checkout",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Lava Checkout",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/index.mjs",
|
|
8
8
|
"types": "dist/index.d.ts",
|
|
9
|
+
"unpkg": "dist/index.umd.js",
|
|
9
10
|
"files": [
|
|
10
11
|
"dist"
|
|
11
12
|
],
|
|
12
13
|
"scripts": {
|
|
13
|
-
"build": "tsup --dts --format cjs,esm src/index.ts",
|
|
14
|
+
"build": "tsup --dts --format cjs,esm --external react --external react-dom src/index.ts",
|
|
14
15
|
"typecheck": "tsc --noEmit",
|
|
15
|
-
"lint": "eslint src/",
|
|
16
|
-
"format": "prettier --write \"src/**/*.ts\"",
|
|
17
16
|
"prepublishOnly": "npm run build",
|
|
18
17
|
"clean": "rm -rf dist"
|
|
19
18
|
},
|
|
@@ -24,17 +23,13 @@
|
|
|
24
23
|
],
|
|
25
24
|
"author": "Lava",
|
|
26
25
|
"license": "MIT",
|
|
26
|
+
"homepage": "https://github.com/lavapayments/checkout",
|
|
27
27
|
"peerDependencies": {
|
|
28
28
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
|
|
29
29
|
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@types/node": "^20.0.0",
|
|
33
|
-
"@types/eslint": "^8.0.0",
|
|
34
|
-
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
|
35
|
-
"@typescript-eslint/parser": "^6.0.0",
|
|
36
|
-
"eslint": "^8.0.0",
|
|
37
|
-
"prettier": "^3.0.0",
|
|
38
33
|
"react": "^17.0.2",
|
|
39
34
|
"react-dom": "^17.0.2",
|
|
40
35
|
"tsup": "^8.0.0",
|