@paykit-sdk/medusajs 1.0.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/dist/index.mjs ADDED
@@ -0,0 +1,306 @@
1
+ import { ModuleProvider, Modules, AbstractPaymentProvider, MedusaError, PaymentActions, PaymentSessionStatus } from '@medusajs/framework/utils';
2
+ import { providerSchema, PayKit, tryCatchAsync, validateRequiredKeys } from '@paykit-sdk/core';
3
+ import { z } from 'zod';
4
+
5
+ // src/index.ts
6
+ var medusaStatus$InboundSchema = (status) => {
7
+ switch (status) {
8
+ case "pending":
9
+ case "processing":
10
+ return PaymentSessionStatus.PENDING;
11
+ case "requires_action":
12
+ return PaymentSessionStatus.REQUIRES_MORE;
13
+ case "requires_capture":
14
+ return PaymentSessionStatus.AUTHORIZED;
15
+ case "succeeded":
16
+ return PaymentSessionStatus.CAPTURED;
17
+ case "canceled":
18
+ return PaymentSessionStatus.CANCELED;
19
+ case "failed":
20
+ return PaymentSessionStatus.ERROR;
21
+ default:
22
+ return PaymentSessionStatus.PENDING;
23
+ }
24
+ };
25
+
26
+ // src/providers/paykit-provider.ts
27
+ var optionsSchema = z.object({
28
+ /**
29
+ * The underlying PayKit provider instance (Stripe, PayPal, etc.)
30
+ * This is required and must be a valid PayKit provider instance
31
+ */
32
+ provider: providerSchema,
33
+ /**
34
+ * The webhook secret for the provider
35
+ * This is required and must be a valid webhook secret
36
+ */
37
+ webhookSecret: z.string(),
38
+ /**
39
+ * Whether to enable debug mode
40
+ * If enabled, the adapter will log debug information to the console
41
+ */
42
+ debug: z.boolean().optional()
43
+ });
44
+ var PaykitMedusaJSAdapter = class extends AbstractPaymentProvider {
45
+ /**
46
+ * The unique identifier for this payment provider
47
+ * Will be stored as `pp_paykit_{id}` in Medusa
48
+ */
49
+ static identifier = "paykit";
50
+ paykit;
51
+ provider;
52
+ options;
53
+ static validateOptions(options) {
54
+ const { error } = optionsSchema.safeParse(options);
55
+ if (error) {
56
+ throw new MedusaError(MedusaError.Types.INVALID_DATA, error.message);
57
+ }
58
+ return;
59
+ }
60
+ /**
61
+ * Constructor receives Medusa's container and provider options
62
+ *
63
+ * @param cradle - Medusa's dependency injection container
64
+ * @param options - PayKit provider configuration
65
+ */
66
+ constructor(cradle, options) {
67
+ super(cradle, options);
68
+ this.options = options;
69
+ this.provider = options.provider;
70
+ this.paykit = new PayKit(this.provider);
71
+ if (this.options.debug) {
72
+ console.info(`[PayKit] Initialized with provider: ${this.provider.providerName}`);
73
+ }
74
+ }
75
+ initiatePayment = async ({
76
+ context,
77
+ amount,
78
+ currency_code,
79
+ data
80
+ }) => {
81
+ if (this.options.debug) {
82
+ console.info("[PayKit] Initiating payment", { context, amount, currency_code, data });
83
+ }
84
+ const intent = {
85
+ status: "pending",
86
+ amount: Number(amount),
87
+ currency: currency_code,
88
+ metadata: { ...data?.metadata ?? {}, session_id: data?.session_id ?? "" },
89
+ provider_metadata: data?.provider_metadata ?? void 0
90
+ };
91
+ let customer;
92
+ if (context?.account_holder?.data?.id) {
93
+ customer = context.account_holder.data.id;
94
+ } else if (data?.email) {
95
+ customer = { email: data.email };
96
+ }
97
+ if (!customer) {
98
+ throw new MedusaError(MedusaError.Types.INVALID_DATA, "Required: customer ID (account_holder) or email (data)");
99
+ }
100
+ if (typeof customer === "object" && "email" in customer) {
101
+ await tryCatchAsync(
102
+ this.paykit.customers.create({
103
+ email: customer.email,
104
+ phone: data?.phone ?? "",
105
+ name: data?.name ? data.name : customer.email.split("@")[0],
106
+ metadata: { PAYKIT_METADATA_KEY: JSON.stringify({ source: "medusa" }) }
107
+ })
108
+ );
109
+ } else {
110
+ customer = customer;
111
+ }
112
+ intent.customer = customer;
113
+ const [paymentIntentResult, paymentIntentError] = await tryCatchAsync(
114
+ this.paykit.payments.create(intent)
115
+ );
116
+ if (paymentIntentError)
117
+ throw new MedusaError(MedusaError.Types.PAYMENT_AUTHORIZATION_ERROR, paymentIntentError.message);
118
+ return { id: paymentIntentResult.id, status: medusaStatus$InboundSchema(paymentIntentResult.status) };
119
+ };
120
+ capturePayment = async (input) => {
121
+ if (this.options.debug) {
122
+ console.info("[PayKit] Capturing payment", input);
123
+ }
124
+ const { id, amount } = validateRequiredKeys(
125
+ ["id", "amount"],
126
+ input?.data ?? {},
127
+ "Missing required payment ID"
128
+ );
129
+ if (!id) throw new MedusaError(MedusaError.Types.INVALID_DATA, "Missing required payment ID");
130
+ if (!amount) throw new MedusaError(MedusaError.Types.INVALID_DATA, "Missing required payment amount");
131
+ const [paymentIntentResult, paymentIntentError] = await tryCatchAsync(
132
+ this.paykit.payments.capture(id, { amount: Number(amount) })
133
+ );
134
+ if (paymentIntentError)
135
+ throw new MedusaError(MedusaError.Types.PAYMENT_AUTHORIZATION_ERROR, paymentIntentError.message);
136
+ return { data: paymentIntentResult };
137
+ };
138
+ authorizePayment = async (input) => {
139
+ if (this.options.debug) {
140
+ console.info("[PayKit] Authorizing payment", input);
141
+ }
142
+ return this.getPaymentStatus(input);
143
+ };
144
+ cancelPayment = async (input) => {
145
+ if (this.options.debug) {
146
+ console.info("[PayKit] Canceling payment", input);
147
+ }
148
+ const { id } = validateRequiredKeys(
149
+ ["id"],
150
+ input?.data ?? {},
151
+ "Missing required payment ID"
152
+ );
153
+ if (!id) throw new MedusaError(MedusaError.Types.INVALID_DATA, "Missing required payment ID");
154
+ const [paymentIntentResult, paymentIntentError] = await tryCatchAsync(this.paykit.payments.cancel(id));
155
+ if (paymentIntentError)
156
+ throw new MedusaError(MedusaError.Types.PAYMENT_AUTHORIZATION_ERROR, paymentIntentError.message);
157
+ return { data: paymentIntentResult };
158
+ };
159
+ deletePayment = async (input) => {
160
+ return this.cancelPayment(input);
161
+ };
162
+ getPaymentStatus = async (input) => {
163
+ const { id } = validateRequiredKeys(
164
+ ["id"],
165
+ input?.data ?? {},
166
+ "Missing required payment ID"
167
+ );
168
+ if (!id) throw new MedusaError(MedusaError.Types.INVALID_DATA, "Missing required payment ID");
169
+ const [paymentIntentResult, paymentIntentError] = await tryCatchAsync(this.paykit.payments.retrieve(id));
170
+ if (paymentIntentError)
171
+ throw new MedusaError(MedusaError.Types.PAYMENT_AUTHORIZATION_ERROR, paymentIntentError.message);
172
+ if (!paymentIntentResult) throw new MedusaError(MedusaError.Types.PAYMENT_AUTHORIZATION_ERROR, "Payment not found");
173
+ return {
174
+ status: medusaStatus$InboundSchema(paymentIntentResult.status),
175
+ data: paymentIntentResult
176
+ };
177
+ };
178
+ refundPayment = async (input) => {
179
+ if (this.options.debug) {
180
+ console.info("[PayKit] Refunding payment", input);
181
+ }
182
+ const { id: paymentId } = validateRequiredKeys(
183
+ ["id"],
184
+ input?.data ?? {},
185
+ "Missing required payment ID"
186
+ );
187
+ if (!paymentId) throw new MedusaError(MedusaError.Types.INVALID_DATA, "Missing required payment ID");
188
+ const [refundResult, refundError] = await tryCatchAsync(
189
+ this.paykit.refunds.create({
190
+ payment_id: paymentId,
191
+ amount: Number(input.amount),
192
+ reason: null,
193
+ metadata: input.data?.metadata ? input.data.metadata : null,
194
+ provider_metadata: input.data?.provider_metadata ? input.data.provider_metadata : void 0
195
+ })
196
+ );
197
+ if (refundError) throw new MedusaError(MedusaError.Types.PAYMENT_AUTHORIZATION_ERROR, refundError.message);
198
+ return { data: refundResult };
199
+ };
200
+ retrievePayment = async (input) => {
201
+ if (this.options.debug) {
202
+ console.info("[PayKit] Retrieving payment", input);
203
+ }
204
+ const { id } = validateRequiredKeys(
205
+ ["id"],
206
+ input?.data ?? {},
207
+ "Missing required payment ID"
208
+ );
209
+ if (!id) throw new MedusaError(MedusaError.Types.INVALID_DATA, "Missing required payment ID");
210
+ const [paymentIntentResult, paymentIntentError] = await tryCatchAsync(this.paykit.payments.retrieve(id));
211
+ if (paymentIntentError)
212
+ throw new MedusaError(MedusaError.Types.PAYMENT_AUTHORIZATION_ERROR, paymentIntentError.message);
213
+ return { data: paymentIntentResult };
214
+ };
215
+ updatePayment = async (input) => {
216
+ if (this.options.debug) {
217
+ console.info("[PayKit] Updating payment", input);
218
+ }
219
+ const { amount, currency_code } = validateRequiredKeys(
220
+ ["amount", "currency_code"],
221
+ input,
222
+ "Missing required payment ID"
223
+ );
224
+ if (!amount || !currency_code)
225
+ throw new MedusaError(MedusaError.Types.INVALID_DATA, "Missing required amount or currency code");
226
+ const { id: paymentId } = validateRequiredKeys(
227
+ ["id"],
228
+ input.data,
229
+ "Missing required payment ID"
230
+ );
231
+ if (!paymentId) throw new MedusaError(MedusaError.Types.INVALID_DATA, "Missing required payment ID");
232
+ const [paymentIntentResult, paymentIntentError] = await tryCatchAsync(
233
+ this.paykit.payments.update(paymentId, {
234
+ amount: Number(amount),
235
+ currency: currency_code,
236
+ metadata: input.data?.metadata ? input.data.metadata : {},
237
+ provider_metadata: input.data?.provider_metadata ? input.data.provider_metadata : void 0
238
+ })
239
+ );
240
+ if (paymentIntentError)
241
+ throw new MedusaError(MedusaError.Types.PAYMENT_AUTHORIZATION_ERROR, paymentIntentError.message);
242
+ return { data: paymentIntentResult };
243
+ };
244
+ getWebhookActionAndData = async (payload) => {
245
+ if (this.options.debug) {
246
+ console.info("[PayKit] Getting webhook action and data", payload);
247
+ }
248
+ const { rawData, headers } = payload;
249
+ const fullUrl = (() => {
250
+ if (headers["origin"]) {
251
+ return headers["origin"];
252
+ }
253
+ if (headers["x-forwarded-host"]) {
254
+ const protocol = headers["x-forwarded-proto"] || "https";
255
+ const host = headers["x-forwarded-host"];
256
+ const path = headers["x-forwarded-path"] || "";
257
+ return `${protocol}://${host}${path}`;
258
+ }
259
+ if (headers["host"]) {
260
+ const protocol = headers["x-forwarded-proto"] || (String(headers["host"]).includes("localhost") ? "http" : "https");
261
+ const host = headers["host"];
262
+ const path = headers["x-original-url"] || headers["x-forwarded-path"] || "";
263
+ return `${protocol}://${host}${path}`;
264
+ }
265
+ return "";
266
+ })();
267
+ const webhook = this.paykit.webhooks.setup({ webhookSecret: this.options.webhookSecret }).on("payment.created", async (event) => {
268
+ return {
269
+ action: PaymentActions.PENDING,
270
+ data: { session_id: event.data?.metadata?.session_id, amount: event.data?.amount }
271
+ };
272
+ }).on("payment.updated", async (event) => {
273
+ const statusActionMap = {
274
+ pending: PaymentActions.PENDING,
275
+ processing: PaymentActions.PENDING,
276
+ requires_action: PaymentActions.REQUIRES_MORE,
277
+ requires_capture: PaymentActions.AUTHORIZED,
278
+ succeeded: PaymentActions.SUCCESSFUL,
279
+ failed: PaymentActions.FAILED,
280
+ canceled: PaymentActions.CANCELED
281
+ };
282
+ return {
283
+ action: event.data?.status ? statusActionMap[event.data.status] : PaymentActions.PENDING,
284
+ data: { session_id: event.data?.metadata?.session_id, amount: event.data?.amount }
285
+ };
286
+ }).on("payment.canceled", async (event) => {
287
+ return {
288
+ action: PaymentActions.CANCELED,
289
+ data: { session_id: event.data?.metadata?.session_id, amount: event.data?.amount }
290
+ };
291
+ });
292
+ const webhookEvents = await webhook.handle({
293
+ body: rawData,
294
+ headers,
295
+ fullUrl
296
+ });
297
+ return webhookEvents;
298
+ };
299
+ };
300
+
301
+ // src/index.ts
302
+ var index_default = ModuleProvider(Modules.PAYMENT, {
303
+ services: [PaykitMedusaJSAdapter]
304
+ });
305
+
306
+ export { PaykitMedusaJSAdapter, index_default as default };
@@ -0,0 +1,61 @@
1
+ import { InitiatePaymentInput, InitiatePaymentOutput, CapturePaymentInput, CapturePaymentOutput, AuthorizePaymentInput, AuthorizePaymentOutput, CancelPaymentInput, CancelPaymentOutput, DeletePaymentInput, DeletePaymentOutput, GetPaymentStatusInput, GetPaymentStatusOutput, RefundPaymentInput, RefundPaymentOutput, RetrievePaymentInput, RetrievePaymentOutput, UpdatePaymentInput, UpdatePaymentOutput, ProviderWebhookPayload, WebhookActionResult } from '@medusajs/framework/types';
2
+ import { AbstractPaymentProvider } from '@medusajs/framework/utils';
3
+ import { PayKitProvider, PayKit } from '@paykit-sdk/core';
4
+ import { z } from 'zod';
5
+
6
+ declare const optionsSchema: z.ZodObject<{
7
+ /**
8
+ * The underlying PayKit provider instance (Stripe, PayPal, etc.)
9
+ * This is required and must be a valid PayKit provider instance
10
+ */
11
+ provider: z.ZodType<PayKitProvider, z.ZodTypeDef, PayKitProvider>;
12
+ /**
13
+ * The webhook secret for the provider
14
+ * This is required and must be a valid webhook secret
15
+ */
16
+ webhookSecret: z.ZodString;
17
+ /**
18
+ * Whether to enable debug mode
19
+ * If enabled, the adapter will log debug information to the console
20
+ */
21
+ debug: z.ZodOptional<z.ZodBoolean>;
22
+ }, "strip", z.ZodTypeAny, {
23
+ provider: PayKitProvider;
24
+ webhookSecret: string;
25
+ debug?: boolean | undefined;
26
+ }, {
27
+ provider: PayKitProvider;
28
+ webhookSecret: string;
29
+ debug?: boolean | undefined;
30
+ }>;
31
+ type PaykitMedusaJSAdapterOptions = z.infer<typeof optionsSchema>;
32
+ declare class PaykitMedusaJSAdapter extends AbstractPaymentProvider<PaykitMedusaJSAdapterOptions> {
33
+ /**
34
+ * The unique identifier for this payment provider
35
+ * Will be stored as `pp_paykit_{id}` in Medusa
36
+ */
37
+ static identifier: string;
38
+ protected readonly paykit: PayKit;
39
+ protected readonly provider: PayKitProvider;
40
+ protected readonly options: PaykitMedusaJSAdapterOptions;
41
+ static validateOptions(options: Record<string, any>): void | never;
42
+ /**
43
+ * Constructor receives Medusa's container and provider options
44
+ *
45
+ * @param cradle - Medusa's dependency injection container
46
+ * @param options - PayKit provider configuration
47
+ */
48
+ constructor(cradle: Record<string, unknown>, options: PaykitMedusaJSAdapterOptions);
49
+ initiatePayment: ({ context, amount, currency_code, data, }: InitiatePaymentInput) => Promise<InitiatePaymentOutput>;
50
+ capturePayment: (input: CapturePaymentInput) => Promise<CapturePaymentOutput>;
51
+ authorizePayment: (input: AuthorizePaymentInput) => Promise<AuthorizePaymentOutput>;
52
+ cancelPayment: (input: CancelPaymentInput) => Promise<CancelPaymentOutput>;
53
+ deletePayment: (input: DeletePaymentInput) => Promise<DeletePaymentOutput>;
54
+ getPaymentStatus: (input: GetPaymentStatusInput) => Promise<GetPaymentStatusOutput>;
55
+ refundPayment: (input: RefundPaymentInput) => Promise<RefundPaymentOutput>;
56
+ retrievePayment: (input: RetrievePaymentInput) => Promise<RetrievePaymentOutput>;
57
+ updatePayment: (input: UpdatePaymentInput) => Promise<UpdatePaymentOutput>;
58
+ getWebhookActionAndData: (payload: ProviderWebhookPayload["payload"]) => Promise<WebhookActionResult>;
59
+ }
60
+
61
+ export { PaykitMedusaJSAdapter, type PaykitMedusaJSAdapterOptions };
@@ -0,0 +1,61 @@
1
+ import { InitiatePaymentInput, InitiatePaymentOutput, CapturePaymentInput, CapturePaymentOutput, AuthorizePaymentInput, AuthorizePaymentOutput, CancelPaymentInput, CancelPaymentOutput, DeletePaymentInput, DeletePaymentOutput, GetPaymentStatusInput, GetPaymentStatusOutput, RefundPaymentInput, RefundPaymentOutput, RetrievePaymentInput, RetrievePaymentOutput, UpdatePaymentInput, UpdatePaymentOutput, ProviderWebhookPayload, WebhookActionResult } from '@medusajs/framework/types';
2
+ import { AbstractPaymentProvider } from '@medusajs/framework/utils';
3
+ import { PayKitProvider, PayKit } from '@paykit-sdk/core';
4
+ import { z } from 'zod';
5
+
6
+ declare const optionsSchema: z.ZodObject<{
7
+ /**
8
+ * The underlying PayKit provider instance (Stripe, PayPal, etc.)
9
+ * This is required and must be a valid PayKit provider instance
10
+ */
11
+ provider: z.ZodType<PayKitProvider, z.ZodTypeDef, PayKitProvider>;
12
+ /**
13
+ * The webhook secret for the provider
14
+ * This is required and must be a valid webhook secret
15
+ */
16
+ webhookSecret: z.ZodString;
17
+ /**
18
+ * Whether to enable debug mode
19
+ * If enabled, the adapter will log debug information to the console
20
+ */
21
+ debug: z.ZodOptional<z.ZodBoolean>;
22
+ }, "strip", z.ZodTypeAny, {
23
+ provider: PayKitProvider;
24
+ webhookSecret: string;
25
+ debug?: boolean | undefined;
26
+ }, {
27
+ provider: PayKitProvider;
28
+ webhookSecret: string;
29
+ debug?: boolean | undefined;
30
+ }>;
31
+ type PaykitMedusaJSAdapterOptions = z.infer<typeof optionsSchema>;
32
+ declare class PaykitMedusaJSAdapter extends AbstractPaymentProvider<PaykitMedusaJSAdapterOptions> {
33
+ /**
34
+ * The unique identifier for this payment provider
35
+ * Will be stored as `pp_paykit_{id}` in Medusa
36
+ */
37
+ static identifier: string;
38
+ protected readonly paykit: PayKit;
39
+ protected readonly provider: PayKitProvider;
40
+ protected readonly options: PaykitMedusaJSAdapterOptions;
41
+ static validateOptions(options: Record<string, any>): void | never;
42
+ /**
43
+ * Constructor receives Medusa's container and provider options
44
+ *
45
+ * @param cradle - Medusa's dependency injection container
46
+ * @param options - PayKit provider configuration
47
+ */
48
+ constructor(cradle: Record<string, unknown>, options: PaykitMedusaJSAdapterOptions);
49
+ initiatePayment: ({ context, amount, currency_code, data, }: InitiatePaymentInput) => Promise<InitiatePaymentOutput>;
50
+ capturePayment: (input: CapturePaymentInput) => Promise<CapturePaymentOutput>;
51
+ authorizePayment: (input: AuthorizePaymentInput) => Promise<AuthorizePaymentOutput>;
52
+ cancelPayment: (input: CancelPaymentInput) => Promise<CancelPaymentOutput>;
53
+ deletePayment: (input: DeletePaymentInput) => Promise<DeletePaymentOutput>;
54
+ getPaymentStatus: (input: GetPaymentStatusInput) => Promise<GetPaymentStatusOutput>;
55
+ refundPayment: (input: RefundPaymentInput) => Promise<RefundPaymentOutput>;
56
+ retrievePayment: (input: RetrievePaymentInput) => Promise<RetrievePaymentOutput>;
57
+ updatePayment: (input: UpdatePaymentInput) => Promise<UpdatePaymentOutput>;
58
+ getWebhookActionAndData: (payload: ProviderWebhookPayload["payload"]) => Promise<WebhookActionResult>;
59
+ }
60
+
61
+ export { PaykitMedusaJSAdapter, type PaykitMedusaJSAdapterOptions };