@pandait.tech/payment-nuvei 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/README.md +211 -0
- package/dist/handlers/index.cjs +1671 -0
- package/dist/handlers/index.cjs.map +1 -0
- package/dist/handlers/index.d.cts +413 -0
- package/dist/handlers/index.d.ts +413 -0
- package/dist/handlers/index.js +1656 -0
- package/dist/handlers/index.js.map +1 -0
- package/dist/index.cjs +170 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +115 -0
- package/dist/index.d.ts +115 -0
- package/dist/index.js +157 -0
- package/dist/index.js.map +1 -0
- package/dist/payment-links/index.cjs +58 -0
- package/dist/payment-links/index.cjs.map +1 -0
- package/dist/payment-links/index.d.cts +60 -0
- package/dist/payment-links/index.d.ts +60 -0
- package/dist/payment-links/index.js +49 -0
- package/dist/payment-links/index.js.map +1 -0
- package/dist/ui/index.cjs +1236 -0
- package/dist/ui/index.cjs.map +1 -0
- package/dist/ui/index.d.cts +148 -0
- package/dist/ui/index.d.ts +148 -0
- package/dist/ui/index.js +1222 -0
- package/dist/ui/index.js.map +1 -0
- package/package.json +90 -0
package/README.md
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# @pandait.tech/payment-nuvei
|
|
2
|
+
|
|
3
|
+
Nuvei Ecuador payment gateway adapter for Next.js. Ships:
|
|
4
|
+
|
|
5
|
+
- **SDK wrapper** for Nuvei's REST endpoints (debit, verify, refund, card list/delete).
|
|
6
|
+
- **Route-handler factories** for `/api/payment/*` and `/api/webhooks/nuvei` — drop-in for Next.js App Router.
|
|
7
|
+
- **Payment-link primitives** (token gen, expiry helpers, anonymous-auth helper).
|
|
8
|
+
- **React UI components** (`CardVisual`, `SavedCards`, `NuveiPaymentForm`) with bank-color branding driven by the package's BIN/bank-colors database.
|
|
9
|
+
|
|
10
|
+
Extracted from `pauhenriques-website` (production-validated).
|
|
11
|
+
|
|
12
|
+
## Status
|
|
13
|
+
|
|
14
|
+
V0 — Phase 1 of `panda-commerce-kit`. Published to public npm.
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pnpm add @pandait.tech/payment-nuvei
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Peer deps the consumer must install:
|
|
23
|
+
|
|
24
|
+
| Peer | When required |
|
|
25
|
+
|---|---|
|
|
26
|
+
| `next` >= 14 | Always (handlers + UI use `next/server` and `next/script`) |
|
|
27
|
+
| `react` >= 18 | Only if importing `/ui` |
|
|
28
|
+
| `react-icons` >= 5 | Only if importing `/ui` |
|
|
29
|
+
| `zod` >= 3.22 | Always (used by 3ds-complete handler validation) |
|
|
30
|
+
| `firebase-admin` >= 12 | Always (handlers need Firestore + Auth admin SDKs) |
|
|
31
|
+
| `firebase` >= 10 | Only if importing `createAnonymousAuthHelper` |
|
|
32
|
+
|
|
33
|
+
## Public API
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
// Pure SDK functions (server-side)
|
|
37
|
+
import {
|
|
38
|
+
debitWithToken,
|
|
39
|
+
verifyThreeDS,
|
|
40
|
+
refundTransaction,
|
|
41
|
+
listCards,
|
|
42
|
+
deleteCard,
|
|
43
|
+
verifyCard,
|
|
44
|
+
} from "@pandait.tech/payment-nuvei";
|
|
45
|
+
|
|
46
|
+
// Route handler factories
|
|
47
|
+
import {
|
|
48
|
+
createChargeHandler,
|
|
49
|
+
createWebhookHandler,
|
|
50
|
+
create3dsCallbackHandler,
|
|
51
|
+
create3dsCompleteHandler,
|
|
52
|
+
create3dsTimeoutHandler,
|
|
53
|
+
createRefundHandler,
|
|
54
|
+
createInitCheckoutHandler,
|
|
55
|
+
createCardsHandler,
|
|
56
|
+
createVerifyHandler,
|
|
57
|
+
createTestChargeHandler,
|
|
58
|
+
} from "@pandait.tech/payment-nuvei/handlers";
|
|
59
|
+
|
|
60
|
+
// Payment-link primitives
|
|
61
|
+
import {
|
|
62
|
+
generatePaymentLinkToken,
|
|
63
|
+
defaultExpiry,
|
|
64
|
+
isExpired,
|
|
65
|
+
createAnonymousAuthHelper,
|
|
66
|
+
PAYMENT_LINK_PRICE_MIN,
|
|
67
|
+
PAYMENT_LINK_PRICE_MAX,
|
|
68
|
+
} from "@pandait.tech/payment-nuvei/payment-links";
|
|
69
|
+
|
|
70
|
+
// React UI components
|
|
71
|
+
import {
|
|
72
|
+
CardVisual,
|
|
73
|
+
SavedCards,
|
|
74
|
+
NuveiPaymentForm,
|
|
75
|
+
// utilities
|
|
76
|
+
getBinDatabase,
|
|
77
|
+
lookupBin,
|
|
78
|
+
lookupBankPalette,
|
|
79
|
+
} from "@pandait.tech/payment-nuvei/ui";
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Handler factories — usage
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
// app/api/payment/charge/route.ts
|
|
86
|
+
import { createChargeHandler } from "@pandait.tech/payment-nuvei/handlers";
|
|
87
|
+
import { dbAdmin, authAdmin } from "@/lib/firebase";
|
|
88
|
+
import { sendPaymentConfirmation, sendPaymentFailed } from "@/lib/email";
|
|
89
|
+
import { getPriceDisplay } from "@/lib/pricing";
|
|
90
|
+
|
|
91
|
+
export const POST = createChargeHandler({
|
|
92
|
+
firebase: { db: dbAdmin, auth: authAdmin },
|
|
93
|
+
email: { sendPaymentConfirmation, sendPaymentFailed },
|
|
94
|
+
getPriceDisplay,
|
|
95
|
+
merchantName: "Acme Shop",
|
|
96
|
+
// Required for 3DS to work. Without it, browser-info is sent to Nuvei but
|
|
97
|
+
// 3DS challenges won't initiate — the handler logs a loud error if browserInfo
|
|
98
|
+
// is provided but cloudFunctionsBaseUrl is missing.
|
|
99
|
+
cloudFunctionsBaseUrl: process.env.CLOUD_FUNCTIONS_BASE_URL,
|
|
100
|
+
rateLimit: checkRateLimit, // optional
|
|
101
|
+
turnstile: verifyTurnstile, // optional
|
|
102
|
+
// Optional consumer-specific side effects after order transitions to paid
|
|
103
|
+
onPaymentSucceeded: async (order) => {
|
|
104
|
+
await ensureFulfillment(order.id);
|
|
105
|
+
},
|
|
106
|
+
// Optional retry URL for payment-failed emails
|
|
107
|
+
getRetryUrl: (order) => `https://shop.example.com/checkout?orderId=${order.id}`,
|
|
108
|
+
});
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Apply the same pattern to the remaining handlers — each one is documented inline with its own `XHandlerDeps` interface.
|
|
112
|
+
|
|
113
|
+
## UI components — usage
|
|
114
|
+
|
|
115
|
+
All `/ui` exports are client components (`"use client"`) and expect a Tailwind setup. The components consume CSS variables for theming so the same components work for every white-label client with their own branding.
|
|
116
|
+
|
|
117
|
+
### 1. Define CSS variables in your global stylesheet
|
|
118
|
+
|
|
119
|
+
Add this to your `app/globals.css` (Next.js) or equivalent, in `:root`:
|
|
120
|
+
|
|
121
|
+
```css
|
|
122
|
+
:root {
|
|
123
|
+
/* Brand */
|
|
124
|
+
--color-primary: #a68a63;
|
|
125
|
+
--color-primary-hover: #b89a73;
|
|
126
|
+
|
|
127
|
+
/* Text */
|
|
128
|
+
--color-text-main: #c1c4a7;
|
|
129
|
+
|
|
130
|
+
/* Surfaces */
|
|
131
|
+
--color-background: #343d2a;
|
|
132
|
+
--color-surface-elevated: #475536;
|
|
133
|
+
|
|
134
|
+
/* Borders */
|
|
135
|
+
--color-border-default: rgba(193, 196, 167, 0.20);
|
|
136
|
+
--color-border-strong: rgba(193, 196, 167, 0.35);
|
|
137
|
+
--color-border-subtle: rgba(193, 196, 167, 0.12);
|
|
138
|
+
|
|
139
|
+
/* Status */
|
|
140
|
+
--color-error: #c75c4a;
|
|
141
|
+
--color-warning: #c9a84c;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/* Optional: dark mode palette */
|
|
145
|
+
.dark {
|
|
146
|
+
--color-primary: #b89a73;
|
|
147
|
+
/* ...override as needed */
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### 2. Add the package to Tailwind's content config
|
|
152
|
+
|
|
153
|
+
Tailwind needs to detect the arbitrary-value utility classes (e.g. `bg-[var(--color-primary)]`) inside the package's compiled output:
|
|
154
|
+
|
|
155
|
+
```js
|
|
156
|
+
// tailwind.config.ts
|
|
157
|
+
export default {
|
|
158
|
+
content: [
|
|
159
|
+
"./app/**/*.{ts,tsx}",
|
|
160
|
+
"./src/**/*.{ts,tsx}",
|
|
161
|
+
"./node_modules/@pandait.tech/payment-nuvei/dist/**/*.{js,cjs}",
|
|
162
|
+
],
|
|
163
|
+
// ...
|
|
164
|
+
};
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### 3. Use the components
|
|
168
|
+
|
|
169
|
+
```tsx
|
|
170
|
+
"use client";
|
|
171
|
+
import { SavedCards, NuveiPaymentForm } from "@pandait.tech/payment-nuvei/ui";
|
|
172
|
+
|
|
173
|
+
export function PaymentMethodPicker() {
|
|
174
|
+
const [token, setToken] = useState<string | null>(null);
|
|
175
|
+
return (
|
|
176
|
+
<div>
|
|
177
|
+
<SavedCards
|
|
178
|
+
selectedToken={token}
|
|
179
|
+
onSelectCard={(card, cvc) => { /* ... */ }}
|
|
180
|
+
onAddNewCard={() => { /* show NuveiPaymentForm */ }}
|
|
181
|
+
/>
|
|
182
|
+
<NuveiPaymentForm
|
|
183
|
+
uid={user.uid}
|
|
184
|
+
email={user.email}
|
|
185
|
+
onTokenSuccess={(token, cardInfo, saveCard) => { /* call /api/payment/charge */ }}
|
|
186
|
+
onTokenError={(err) => { /* ... */ }}
|
|
187
|
+
/>
|
|
188
|
+
</div>
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
The `NuveiPaymentForm` reads `NEXT_PUBLIC_NUVEI_CLIENT_APP_CODE`, `NEXT_PUBLIC_NUVEI_CLIENT_APP_KEY`, and `NEXT_PUBLIC_NUVEI_ENV` from your env by default. You can override per-instance with the `nuveiAppCode` / `nuveiAppKey` / `nuveiEnv` props.
|
|
194
|
+
|
|
195
|
+
### Endpoints the UI components expect
|
|
196
|
+
|
|
197
|
+
The components POST/GET to fixed paths because the package's handler factories are designed to mount there:
|
|
198
|
+
|
|
199
|
+
| Component / call | Endpoint | Handler factory |
|
|
200
|
+
|---|---|---|
|
|
201
|
+
| `SavedCards` GET on mount | `/api/nuvei/cards` | `createCardsHandler` GET |
|
|
202
|
+
| `SavedCards` DELETE on remove | `/api/nuvei/cards` | `createCardsHandler` DELETE |
|
|
203
|
+
| `SavedCards` POST on verify | `/api/nuvei/verify` | `createVerifyHandler` POST |
|
|
204
|
+
| `NuveiPaymentForm` DELETE on duplicate | `/api/nuvei/cards` | `createCardsHandler` DELETE |
|
|
205
|
+
| `CardVisual` BIN lookup | `/api/bins` (overridable) | Consumer-provided JSON of `BinDatabase` |
|
|
206
|
+
|
|
207
|
+
The consumer must wire those routes — each `route.ts` is one or two lines re-exporting the factory result.
|
|
208
|
+
|
|
209
|
+
## Migration from `pauhenriques-website`
|
|
210
|
+
|
|
211
|
+
See per-file `Source: pauhenriques-website/...` headers throughout the package. The refactor preserves behavior with three intentional fixes vs. the original (documented in commit `4b0cb06` — coupon-reuse in webhook BY_CRES + card-delete on 3DS flows).
|