@unifiedcommerce/adapter-stripe 0.2.1 → 0.2.4

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.
Files changed (2) hide show
  1. package/package.json +2 -1
  2. package/src/index.ts +143 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unifiedcommerce/adapter-stripe",
3
- "version": "0.2.1",
3
+ "version": "0.2.4",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -31,6 +31,7 @@
31
31
  "access": "public"
32
32
  },
33
33
  "files": [
34
+ "src",
34
35
  "dist",
35
36
  "README.md"
36
37
  ]
package/src/index.ts ADDED
@@ -0,0 +1,143 @@
1
+ import Stripe from "stripe";
2
+ import {
3
+ Err,
4
+ Ok,
5
+ type PaymentAdapter,
6
+ type PaymentCapture,
7
+ type PaymentIntent,
8
+ type PaymentRefund,
9
+ type PaymentWebhookEvent,
10
+ type Result,
11
+ } from "@unifiedcommerce/core";
12
+
13
+ export interface StripeAdapterOptions {
14
+ secretKey: string;
15
+ webhookSecret?: string;
16
+ apiVersion?: Stripe.LatestApiVersion;
17
+ }
18
+
19
+ export function stripePayment(options: StripeAdapterOptions): PaymentAdapter {
20
+ const stripe = new Stripe(options.secretKey, {
21
+ apiVersion: options.apiVersion ?? "2025-08-27.basil",
22
+ });
23
+
24
+ return {
25
+ providerId: "stripe",
26
+
27
+ async createPaymentIntent(params): Promise<Result<PaymentIntent>> {
28
+ try {
29
+ const intent = await stripe.paymentIntents.create({
30
+ amount: params.amount,
31
+ currency: params.currency.toLowerCase(),
32
+ metadata: {
33
+ orderId: params.orderId,
34
+ customerId: params.customerId ?? "",
35
+ ...params.metadata,
36
+ },
37
+ automatic_payment_methods: {
38
+ enabled: true,
39
+ },
40
+ });
41
+
42
+ return Ok({
43
+ id: intent.id,
44
+ status: intent.status,
45
+ amount: intent.amount,
46
+ currency: intent.currency,
47
+ clientSecret: intent.client_secret,
48
+ });
49
+ } catch (error) {
50
+ return Err({
51
+ code: "PAYMENT_INTENT_CREATE_FAILED",
52
+ message: error instanceof Error ? error.message : "Stripe payment intent creation failed.",
53
+ });
54
+ }
55
+ },
56
+
57
+ async capturePayment(paymentIntentId: string, amount?: number): Promise<Result<PaymentCapture>> {
58
+ try {
59
+ const captured = await stripe.paymentIntents.capture(paymentIntentId, amount ? { amount_to_capture: amount } : undefined);
60
+ return Ok({
61
+ id: captured.id,
62
+ status: captured.status,
63
+ amountCaptured: captured.amount_received,
64
+ });
65
+ } catch (error) {
66
+ return Err({
67
+ code: "PAYMENT_CAPTURE_FAILED",
68
+ message: error instanceof Error ? error.message : "Stripe capture failed.",
69
+ });
70
+ }
71
+ },
72
+
73
+ async refundPayment(paymentId: string, amount: number, reason?: string): Promise<Result<PaymentRefund>> {
74
+ try {
75
+ const params: Stripe.RefundCreateParams = {
76
+ payment_intent: paymentId,
77
+ amount,
78
+ };
79
+ if (reason != null) {
80
+ // Single-cast: `string` to Stripe's `Reason` enum — structurally compatible
81
+ (params as Record<string, unknown>).reason = reason;
82
+ }
83
+ const refund = await stripe.refunds.create(params);
84
+
85
+ return Ok({
86
+ id: refund.id,
87
+ status: refund.status ?? "pending",
88
+ amountRefunded: refund.amount,
89
+ });
90
+ } catch (error) {
91
+ return Err({
92
+ code: "PAYMENT_REFUND_FAILED",
93
+ message: error instanceof Error ? error.message : "Stripe refund failed.",
94
+ });
95
+ }
96
+ },
97
+
98
+ async cancelPaymentIntent(paymentIntentId: string): Promise<Result<void>> {
99
+ try {
100
+ await stripe.paymentIntents.cancel(paymentIntentId);
101
+ return Ok(undefined);
102
+ } catch (error) {
103
+ return Err({
104
+ code: "PAYMENT_CANCEL_FAILED",
105
+ message: error instanceof Error ? error.message : "Stripe cancellation failed.",
106
+ });
107
+ }
108
+ },
109
+
110
+ async verifyWebhook(request: Request): Promise<Result<PaymentWebhookEvent>> {
111
+ try {
112
+ if (!options.webhookSecret) {
113
+ return Err({
114
+ code: "WEBHOOK_SECRET_MISSING",
115
+ message: "Stripe webhook secret is not configured.",
116
+ });
117
+ }
118
+
119
+ const signature = request.headers.get("stripe-signature");
120
+ if (!signature) {
121
+ return Err({
122
+ code: "WEBHOOK_SIGNATURE_MISSING",
123
+ message: "Missing stripe-signature header.",
124
+ });
125
+ }
126
+
127
+ const body = await request.text();
128
+ const event = stripe.webhooks.constructEvent(body, signature, options.webhookSecret);
129
+
130
+ return Ok({
131
+ id: event.id,
132
+ type: event.type,
133
+ data: event.data.object,
134
+ });
135
+ } catch (error) {
136
+ return Err({
137
+ code: "WEBHOOK_VERIFICATION_FAILED",
138
+ message: error instanceof Error ? error.message : "Stripe webhook verification failed.",
139
+ });
140
+ }
141
+ },
142
+ };
143
+ }