@pandait.tech/payment-nuvei 0.2.1 → 0.4.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 +70 -18
- package/dist/handlers/index.cjs +2 -1
- package/dist/handlers/index.cjs.map +1 -1
- package/dist/handlers/index.js +2 -1
- package/dist/handlers/index.js.map +1 -1
- package/dist/ui/styles.css +2 -0
- package/package.json +16 -3
package/README.md
CHANGED
|
@@ -141,9 +141,44 @@ A production-validated implementation of both (`threeDSCallback` + `nuveiProxy`,
|
|
|
141
141
|
|
|
142
142
|
## UI components — usage
|
|
143
143
|
|
|
144
|
-
All `/ui` exports are client components (`"use client"`)
|
|
144
|
+
All `/ui` exports are client components (`"use client"`). They consume CSS variables for theming so the same components work for every white-label client with their own branding.
|
|
145
145
|
|
|
146
|
-
### 1.
|
|
146
|
+
### 1. Load the styles
|
|
147
|
+
|
|
148
|
+
You have two options. **Option A is recommended** — it works without Tailwind, on any Tailwind version, and doesn't require configuring your build to scan this package.
|
|
149
|
+
|
|
150
|
+
**Option A — import the prebuilt stylesheet (recommended, standalone):**
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
// once, e.g. in app/layout.tsx or your global entry
|
|
154
|
+
import "@pandait.tech/payment-nuvei/ui/styles.css";
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
This ships the exact utility classes the components use (no Tailwind Preflight/reset — it won't touch your page's base styles). You still define the brand tokens (step 2) for theming.
|
|
158
|
+
|
|
159
|
+
**Option B — let your own Tailwind build the classes (Tailwind v4 users):**
|
|
160
|
+
|
|
161
|
+
Skip the CSS import and instead point Tailwind at the package so it generates the classes itself. Tailwind **v4** (`@source` in your CSS):
|
|
162
|
+
|
|
163
|
+
```css
|
|
164
|
+
@import "tailwindcss";
|
|
165
|
+
@source "../node_modules/@pandait.tech/payment-nuvei/dist/**/*.{js,cjs}";
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Tailwind **v3** (`content` in `tailwind.config`):
|
|
169
|
+
|
|
170
|
+
```js
|
|
171
|
+
export default {
|
|
172
|
+
content: [
|
|
173
|
+
"./app/**/*.{ts,tsx}",
|
|
174
|
+
"./node_modules/@pandait.tech/payment-nuvei/dist/**/*.{js,cjs}",
|
|
175
|
+
],
|
|
176
|
+
};
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
> If components render unstyled, you forgot Option A's import or Option B's `@source`/`content` entry. Option A removes that failure mode entirely.
|
|
180
|
+
|
|
181
|
+
### 2. Define CSS variables in your global stylesheet
|
|
147
182
|
|
|
148
183
|
Add this to your `app/globals.css` (Next.js) or equivalent, in `:root`:
|
|
149
184
|
|
|
@@ -177,22 +212,6 @@ Add this to your `app/globals.css` (Next.js) or equivalent, in `:root`:
|
|
|
177
212
|
}
|
|
178
213
|
```
|
|
179
214
|
|
|
180
|
-
### 2. Add the package to Tailwind's content config
|
|
181
|
-
|
|
182
|
-
Tailwind needs to detect the arbitrary-value utility classes (e.g. `bg-[var(--color-primary)]`) inside the package's compiled output:
|
|
183
|
-
|
|
184
|
-
```js
|
|
185
|
-
// tailwind.config.ts
|
|
186
|
-
export default {
|
|
187
|
-
content: [
|
|
188
|
-
"./app/**/*.{ts,tsx}",
|
|
189
|
-
"./src/**/*.{ts,tsx}",
|
|
190
|
-
"./node_modules/@pandait.tech/payment-nuvei/dist/**/*.{js,cjs}",
|
|
191
|
-
],
|
|
192
|
-
// ...
|
|
193
|
-
};
|
|
194
|
-
```
|
|
195
|
-
|
|
196
215
|
### 3. Use the components
|
|
197
216
|
|
|
198
217
|
```tsx
|
|
@@ -235,6 +254,39 @@ The components POST/GET to fixed paths because the package's handler factories a
|
|
|
235
254
|
|
|
236
255
|
The consumer must wire those routes — each `route.ts` is one or two lines re-exporting the factory result.
|
|
237
256
|
|
|
257
|
+
`CardVisual` **degrades gracefully** if no BIN endpoint is served: it just renders without bank-specific colors. The endpoint is optional and overridable via the `binDatabaseEndpoint` prop (default `/api/bins`).
|
|
258
|
+
|
|
259
|
+
## Firestore data contract
|
|
260
|
+
|
|
261
|
+
The handlers read/write a single `orders` collection (plus `promotions` for coupon usage). Your Firestore schema must match these names, statuses, and fields:
|
|
262
|
+
|
|
263
|
+
**`orders/{orderId}`** — the document the charge/webhook/3DS/refund handlers operate on. `dev_reference` sent to Nuvei **is** the `orderId`.
|
|
264
|
+
|
|
265
|
+
| Field | Written by | Notes |
|
|
266
|
+
|---|---|---|
|
|
267
|
+
| `status` | all | lifecycle: `pending` → `3ds-pending` → `paid` \| `cancelled` \| `refunded`. Final statuses (`paid`/`delivered`/`shipped`) are never downgraded by the webhook. |
|
|
268
|
+
| `userId` | consumer (at create) | must match the `__session` cookie uid; handlers authorize against it. |
|
|
269
|
+
| `userEmail` | consumer | used for confirmation emails. |
|
|
270
|
+
| `items`, `subtotal`, `vat`, `total`, `discount` | consumer | echoed into emails. |
|
|
271
|
+
| `promotionId`, `couponCode` | consumer | if set, webhook/charge increment `promotions/{id}.currentUses` and write a `promotions/{id}/usages/{auto}` doc atomically. |
|
|
272
|
+
| `paymentTransactionId`, `authorizationCode`, `nuveiTransactionId` | charge/webhook | Nuvei refs; `paymentTransactionId` is required for refunds. |
|
|
273
|
+
| `threeDSCres`, `threeDSTransStatus` | 3DS callback / webhook | set during the challenge; cleared on completion. |
|
|
274
|
+
| `verifyCalledAt` | webhook | guards the BY_CRES verify path (single-fire). |
|
|
275
|
+
| `emailPending`, `missingAuthCodeFlagged` | charge/webhook | pending-email reconciliation when auth_code arrives late. |
|
|
276
|
+
| `deleteCardAfterPayment`, `paymentToken` | charge | "don't save card" opt-out, honored on 3DS/webhook completion. |
|
|
277
|
+
| `shippingAddress.fullName` | consumer | used as the email customer name. |
|
|
278
|
+
| `refundedAt` | refund | set on successful refund. |
|
|
279
|
+
|
|
280
|
+
**`promotions/{promotionId}`**: `currentUses` (incremented). **`promotions/{promotionId}/usages/{auto}`**: `{ userId, orderId, discountApplied, usedAt }`.
|
|
281
|
+
|
|
282
|
+
> Business-specific side effects (course enrollment, fulfillment, paymentLink usage) live in your `onPaymentSucceeded` callback — the package never assumes those collections. **`onPaymentSucceeded` fires once, on the transition into `paid`** (idempotent across Nuvei webhook retries), but you should still make it internally idempotent as defense-in-depth.
|
|
283
|
+
|
|
284
|
+
## API surface & stability
|
|
285
|
+
|
|
286
|
+
Public, supported entry points: the package root (SDK), `./handlers`, `./adapters`, `./payment-links`, `./ui`, and `./ui/styles.css`. Everything else (e.g. internal `http.ts`) is private and may change without notice.
|
|
287
|
+
|
|
288
|
+
Pre-1.0 the package follows semver with the caveat that **minor versions may make small breaking changes to handler `*HandlerDeps` interfaces** as the design settles. From **1.0.0** onward the public API is frozen under semver. See `CHANGELOG.md`.
|
|
289
|
+
|
|
238
290
|
## Migration from `pauhenriques-website`
|
|
239
291
|
|
|
240
292
|
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).
|
package/dist/handlers/index.cjs
CHANGED
|
@@ -900,7 +900,8 @@ function createWebhookHandler(deps) {
|
|
|
900
900
|
logger.log(
|
|
901
901
|
`Webhook: Order ${orderId} \u2192 ${newStatus} (status_detail: ${transaction.status_detail})`
|
|
902
902
|
);
|
|
903
|
-
|
|
903
|
+
const transitionedToPaid = newStatus === "paid" && !finalStatuses.includes(currentStatus);
|
|
904
|
+
if (transitionedToPaid && deps.onPaymentSucceeded) {
|
|
904
905
|
try {
|
|
905
906
|
await deps.onPaymentSucceeded({ ...orderData, id: orderId });
|
|
906
907
|
} catch (err) {
|