@paykit-sdk/medusajs 1.0.11 → 1.0.13
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 +1 -0
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +265 -240
- package/dist/index.mjs +266 -241
- package/dist/providers/paykit-provider.d.mts +19 -15
- package/dist/providers/paykit-provider.d.ts +19 -15
- package/dist/providers/paykit-provider.js +265 -240
- package/dist/providers/paykit-provider.mjs +266 -241
- package/dist/utils/mapper.d.mts +5 -2
- package/dist/utils/mapper.d.ts +5 -2
- package/dist/utils/mapper.js +2 -2
- package/dist/utils/mapper.mjs +2 -2
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ModuleProvider, Modules, AbstractPaymentProvider, MedusaError, PaymentSessionStatus, PaymentActions } from '@medusajs/framework/utils';
|
|
2
|
-
import { providerSchema, PayKit, tryCatchAsync,
|
|
2
|
+
import { providerSchema, PayKit, tryCatchAsync, isIdCustomer, isEmailCustomer, parseCustomerName, billingSchema, PAYKIT_METADATA_KEY, validateRequiredKeys, getURLFromHeaders } from '@paykit-sdk/core';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
|
|
5
5
|
// src/index.ts
|
|
6
|
-
var
|
|
6
|
+
var PaymentStatus$inboundSchema = (status) => {
|
|
7
7
|
switch (status) {
|
|
8
8
|
case "pending":
|
|
9
9
|
case "processing":
|
|
@@ -27,17 +27,20 @@ var medusaStatus$InboundSchema = (status) => {
|
|
|
27
27
|
var optionsSchema = z.object({
|
|
28
28
|
/**
|
|
29
29
|
* The underlying PayKit provider instance (Stripe, PayPal, etc.)
|
|
30
|
-
* This is required and must be a valid PayKit provider instance
|
|
31
30
|
*/
|
|
32
31
|
provider: providerSchema,
|
|
33
32
|
/**
|
|
34
|
-
* The webhook secret for the provider
|
|
35
|
-
* This is required and must be a valid webhook secret
|
|
33
|
+
* The webhook secret for the provider.
|
|
36
34
|
*/
|
|
37
|
-
webhookSecret: z.string(),
|
|
35
|
+
webhookSecret: z.string().nullable().default(null),
|
|
36
|
+
/**
|
|
37
|
+
* Multiplier applied to the amount before sending to the payment provider.
|
|
38
|
+
* Use this when your provider expects amounts in the smallest currency unit (e.g. cents)
|
|
39
|
+
* but Medusa is passing amounts in the major unit (e.g. euros).
|
|
40
|
+
*/
|
|
41
|
+
amountToCentsMultiplier: z.number().min(1).default(1),
|
|
38
42
|
/**
|
|
39
43
|
* Whether to enable debug mode
|
|
40
|
-
* If enabled, the adapter will log debug information to the console
|
|
41
44
|
*/
|
|
42
45
|
debug: z.boolean().optional()
|
|
43
46
|
});
|
|
@@ -48,30 +51,49 @@ var PaykitMedusaJSAdapter = class extends AbstractPaymentProvider {
|
|
|
48
51
|
*/
|
|
49
52
|
static identifier = "paykit";
|
|
50
53
|
paykit;
|
|
51
|
-
provider;
|
|
52
54
|
options;
|
|
53
55
|
static validateOptions(options) {
|
|
54
56
|
const { error } = optionsSchema.safeParse(options);
|
|
55
57
|
if (error) {
|
|
56
|
-
throw new MedusaError(
|
|
58
|
+
throw new MedusaError(
|
|
59
|
+
MedusaError.Types.INVALID_DATA,
|
|
60
|
+
error.message
|
|
61
|
+
);
|
|
57
62
|
}
|
|
58
63
|
return;
|
|
59
64
|
}
|
|
60
65
|
/**
|
|
61
|
-
* Constructor receives Medusa's container and provider options
|
|
62
|
-
*
|
|
63
66
|
* @param cradle - Medusa's dependency injection container
|
|
64
67
|
* @param options - PayKit provider configuration
|
|
65
68
|
*/
|
|
66
69
|
constructor(cradle, options) {
|
|
67
70
|
super(cradle, options);
|
|
68
71
|
this.options = options;
|
|
69
|
-
this.
|
|
70
|
-
this.paykit = new PayKit(this.provider);
|
|
72
|
+
this.paykit = new PayKit(options.provider);
|
|
71
73
|
if (this.options.debug) {
|
|
72
|
-
console.info(
|
|
74
|
+
console.info(
|
|
75
|
+
`[PayKit] Initialized with provider: ${this.paykit.providerName}`
|
|
76
|
+
);
|
|
73
77
|
}
|
|
74
78
|
}
|
|
79
|
+
async exec(promise, context, options) {
|
|
80
|
+
const [result, error] = await tryCatchAsync(promise);
|
|
81
|
+
if (error) {
|
|
82
|
+
if (options?.allowUnsupported && error.name === "ProviderNotSupportedError") {
|
|
83
|
+
if (this.options.debug) {
|
|
84
|
+
console.warn(
|
|
85
|
+
`[PayKit ${context}] Operation not supported by ${this.paykit.providerName}.`
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
throw new MedusaError(
|
|
91
|
+
MedusaError.Types.PAYMENT_AUTHORIZATION_ERROR,
|
|
92
|
+
`[PayKit ${context}] ${error.message}`
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
return result;
|
|
96
|
+
}
|
|
75
97
|
initiatePayment = async ({
|
|
76
98
|
context,
|
|
77
99
|
amount,
|
|
@@ -81,325 +103,338 @@ var PaykitMedusaJSAdapter = class extends AbstractPaymentProvider {
|
|
|
81
103
|
if (this.options.debug) {
|
|
82
104
|
console.info("[PayKit] Initiating payment", {
|
|
83
105
|
context,
|
|
84
|
-
amount,
|
|
106
|
+
amount: Number(amount) * this.options.amountToCentsMultiplier,
|
|
85
107
|
currency_code,
|
|
86
108
|
data
|
|
87
109
|
});
|
|
88
110
|
}
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
currency: currency_code,
|
|
92
|
-
metadata: { ...data?.metadata ?? {}, session_id: data?.session_id ?? null },
|
|
93
|
-
provider_metadata: data?.provider_metadata,
|
|
94
|
-
capture_method: "manual",
|
|
95
|
-
item_id: data?.item_id
|
|
96
|
-
};
|
|
97
|
-
let customer;
|
|
111
|
+
const hasProviderCustomer = !!context?.account_holder?.data?.id;
|
|
112
|
+
let customer = null;
|
|
98
113
|
if (context?.account_holder?.data?.id) {
|
|
99
|
-
customer = context.account_holder.data.id;
|
|
100
|
-
}
|
|
101
|
-
|
|
114
|
+
customer = { id: context.account_holder.data.id };
|
|
115
|
+
} else if (context?.customer?.email) {
|
|
116
|
+
customer = { email: context.customer.email };
|
|
117
|
+
} else if (data?.email) {
|
|
102
118
|
customer = { email: data.email };
|
|
103
119
|
}
|
|
104
|
-
if (!customer) {
|
|
120
|
+
if (!customer || !isIdCustomer(customer) && !isEmailCustomer(customer)) {
|
|
105
121
|
throw new MedusaError(
|
|
106
122
|
MedusaError.Types.INVALID_DATA,
|
|
107
|
-
"
|
|
123
|
+
"Customer ID (account_holder) or Email (context.customer or data.email) required"
|
|
108
124
|
);
|
|
109
125
|
}
|
|
110
|
-
if (
|
|
111
|
-
const
|
|
112
|
-
|
|
126
|
+
if (!hasProviderCustomer && isEmailCustomer(customer)) {
|
|
127
|
+
const { fullName } = parseCustomerName({
|
|
128
|
+
name: `${context?.customer?.first_name ?? ""} ${context?.customer?.last_name ?? ""}`.trim(),
|
|
129
|
+
email: customer.email
|
|
130
|
+
});
|
|
131
|
+
const billingInfo = billingSchema.safeParse(data?.billing);
|
|
132
|
+
if (data?.billing && !billingInfo.success) {
|
|
133
|
+
throw new MedusaError(
|
|
134
|
+
MedusaError.Types.INVALID_DATA,
|
|
135
|
+
`Invalid billing information, ${billingInfo.error.message} `
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
const created = await this.exec(
|
|
113
139
|
this.paykit.customers.create({
|
|
114
140
|
email: customer.email,
|
|
115
|
-
|
|
116
|
-
|
|
141
|
+
name: fullName,
|
|
142
|
+
phone: data?.phone ?? null,
|
|
143
|
+
billing: billingInfo.data ?? null,
|
|
117
144
|
metadata: {
|
|
118
|
-
PAYKIT_METADATA_KEY: JSON.stringify({
|
|
145
|
+
[PAYKIT_METADATA_KEY]: JSON.stringify({
|
|
146
|
+
source: "medusa-paykit-adapter"
|
|
147
|
+
})
|
|
119
148
|
}
|
|
120
|
-
})
|
|
149
|
+
}),
|
|
150
|
+
"Customer Creation",
|
|
151
|
+
{ allowUnsupported: true }
|
|
121
152
|
);
|
|
122
|
-
if (
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
);
|
|
128
|
-
}
|
|
129
|
-
} else {
|
|
130
|
-
throw new MedusaError(
|
|
131
|
-
MedusaError.Types.PAYMENT_AUTHORIZATION_ERROR,
|
|
132
|
-
`Failed to create customer: ${createError.message}`
|
|
133
|
-
);
|
|
134
|
-
}
|
|
135
|
-
} else {
|
|
136
|
-
customer = createdCustomer.id;
|
|
153
|
+
if (created) {
|
|
154
|
+
customer = {
|
|
155
|
+
..."id" in created ? { id: created.id } : {},
|
|
156
|
+
..."email" in created ? { email: created.email } : {}
|
|
157
|
+
};
|
|
137
158
|
}
|
|
138
|
-
} else {
|
|
139
|
-
customer = customer;
|
|
140
159
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
160
|
+
const payment = await this.exec(
|
|
161
|
+
this.paykit.payments.create({
|
|
162
|
+
amount: Number(amount) * this.options.amountToCentsMultiplier,
|
|
163
|
+
currency: currency_code.toUpperCase(),
|
|
164
|
+
customer,
|
|
165
|
+
item_id: data?.item_id ?? null,
|
|
166
|
+
capture_method: "manual",
|
|
167
|
+
metadata: {
|
|
168
|
+
...data?.metadata,
|
|
169
|
+
session_id: data?.session_id
|
|
170
|
+
},
|
|
171
|
+
...data?.billing ? { billing: data.billing } : {},
|
|
172
|
+
provider_metadata: data?.provider_metadata
|
|
173
|
+
}),
|
|
174
|
+
"Initiate"
|
|
144
175
|
);
|
|
145
|
-
if (paymentIntentError) {
|
|
146
|
-
throw new MedusaError(
|
|
147
|
-
MedusaError.Types.PAYMENT_AUTHORIZATION_ERROR,
|
|
148
|
-
paymentIntentError.message
|
|
149
|
-
);
|
|
150
|
-
}
|
|
151
|
-
if (paymentIntentResult.requires_action && paymentIntentResult.payment_url) {
|
|
152
|
-
return {
|
|
153
|
-
id: paymentIntentResult.id,
|
|
154
|
-
status: PaymentSessionStatus.REQUIRES_MORE,
|
|
155
|
-
data: {
|
|
156
|
-
payment_url: paymentIntentResult.payment_url
|
|
157
|
-
}
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
176
|
return {
|
|
161
|
-
id:
|
|
162
|
-
status:
|
|
177
|
+
id: payment.id,
|
|
178
|
+
status: payment.requires_action ? PaymentSessionStatus.REQUIRES_MORE : PaymentStatus$inboundSchema(payment.status),
|
|
179
|
+
data: { ...payment, payment_url: payment.payment_url }
|
|
163
180
|
};
|
|
164
181
|
};
|
|
165
182
|
capturePayment = async (input) => {
|
|
166
183
|
if (this.options.debug) {
|
|
167
184
|
console.info("[PayKit] Capturing payment", input);
|
|
168
185
|
}
|
|
169
|
-
const { id, amount } = validateRequiredKeys(
|
|
186
|
+
const { id: paymentId, amount } = validateRequiredKeys(
|
|
170
187
|
["id", "amount"],
|
|
171
|
-
input
|
|
188
|
+
input.data ?? {},
|
|
172
189
|
"Missing required fields: {keys}",
|
|
173
190
|
(message) => new MedusaError(MedusaError.Types.INVALID_DATA, message)
|
|
174
191
|
);
|
|
175
|
-
const
|
|
176
|
-
this.paykit.payments.capture(
|
|
192
|
+
const data = await this.exec(
|
|
193
|
+
this.paykit.payments.capture(paymentId, {
|
|
194
|
+
amount: Number(amount) * this.options.amountToCentsMultiplier
|
|
195
|
+
}),
|
|
196
|
+
"Capture"
|
|
177
197
|
);
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
paymentIntentError.message
|
|
182
|
-
);
|
|
183
|
-
return { data: paymentIntentResult };
|
|
198
|
+
return {
|
|
199
|
+
data
|
|
200
|
+
};
|
|
184
201
|
};
|
|
185
202
|
authorizePayment = async (input) => {
|
|
186
|
-
|
|
187
|
-
|
|
203
|
+
const { id: paymentId } = validateRequiredKeys(
|
|
204
|
+
["id"],
|
|
205
|
+
input.data ?? {},
|
|
206
|
+
"Missing required fields: {keys}",
|
|
207
|
+
(message) => new MedusaError(MedusaError.Types.INVALID_DATA, message)
|
|
208
|
+
);
|
|
209
|
+
const payment = await this.exec(
|
|
210
|
+
this.paykit.payments.retrieve(paymentId),
|
|
211
|
+
"Authorize"
|
|
212
|
+
);
|
|
213
|
+
if (!payment) {
|
|
214
|
+
throw new MedusaError(
|
|
215
|
+
MedusaError.Types.NOT_FOUND,
|
|
216
|
+
"Payment not found"
|
|
217
|
+
);
|
|
188
218
|
}
|
|
189
|
-
|
|
219
|
+
const resolvedStatus = (() => {
|
|
220
|
+
if (payment.requires_action)
|
|
221
|
+
return PaymentSessionStatus.REQUIRES_MORE;
|
|
222
|
+
if (payment.status === "succeeded")
|
|
223
|
+
return PaymentSessionStatus.AUTHORIZED;
|
|
224
|
+
return PaymentStatus$inboundSchema(payment.status);
|
|
225
|
+
})();
|
|
226
|
+
return {
|
|
227
|
+
status: resolvedStatus,
|
|
228
|
+
data: payment
|
|
229
|
+
};
|
|
190
230
|
};
|
|
191
231
|
cancelPayment = async (input) => {
|
|
192
232
|
if (this.options.debug) {
|
|
193
233
|
console.info("[PayKit] Canceling payment", input);
|
|
194
234
|
}
|
|
195
|
-
const { id } = validateRequiredKeys(
|
|
235
|
+
const { id: paymentId } = validateRequiredKeys(
|
|
196
236
|
["id"],
|
|
197
|
-
input
|
|
237
|
+
input.data ?? {},
|
|
198
238
|
"Missing required fields: {keys}",
|
|
199
239
|
(message) => new MedusaError(MedusaError.Types.INVALID_DATA, message)
|
|
200
240
|
);
|
|
201
|
-
const
|
|
202
|
-
this.paykit.payments.cancel(
|
|
241
|
+
const data = await this.exec(
|
|
242
|
+
this.paykit.payments.cancel(paymentId),
|
|
243
|
+
"Cancel"
|
|
203
244
|
);
|
|
204
|
-
|
|
205
|
-
throw new MedusaError(
|
|
206
|
-
MedusaError.Types.PAYMENT_AUTHORIZATION_ERROR,
|
|
207
|
-
paymentIntentError.message
|
|
208
|
-
);
|
|
209
|
-
return { data: paymentIntentResult };
|
|
245
|
+
return { data };
|
|
210
246
|
};
|
|
211
247
|
deletePayment = async (input) => {
|
|
212
|
-
|
|
248
|
+
if (this.options.debug) {
|
|
249
|
+
console.info(
|
|
250
|
+
"[PayKit] Deleting payment (attempting cancel)",
|
|
251
|
+
input
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
const paymentId = input.data?.id;
|
|
255
|
+
if (!paymentId) {
|
|
256
|
+
return {};
|
|
257
|
+
}
|
|
258
|
+
const data = await this.exec(
|
|
259
|
+
this.paykit.payments.cancel(paymentId),
|
|
260
|
+
"Cancel",
|
|
261
|
+
{ allowUnsupported: true }
|
|
262
|
+
);
|
|
263
|
+
return { data };
|
|
213
264
|
};
|
|
214
265
|
getPaymentStatus = async (input) => {
|
|
215
|
-
const { id } = validateRequiredKeys(
|
|
266
|
+
const { id: paymentId } = validateRequiredKeys(
|
|
216
267
|
["id"],
|
|
217
|
-
input
|
|
268
|
+
input.data ?? {},
|
|
218
269
|
"Missing required fields: {keys}",
|
|
219
270
|
(message) => new MedusaError(MedusaError.Types.INVALID_DATA, message)
|
|
220
271
|
);
|
|
221
|
-
const
|
|
222
|
-
this.paykit.payments.retrieve(
|
|
272
|
+
const payment = await this.exec(
|
|
273
|
+
this.paykit.payments.retrieve(paymentId),
|
|
274
|
+
"Status"
|
|
223
275
|
);
|
|
224
|
-
if (
|
|
225
|
-
throw new MedusaError(
|
|
226
|
-
MedusaError.Types.PAYMENT_AUTHORIZATION_ERROR,
|
|
227
|
-
paymentIntentError.message
|
|
228
|
-
);
|
|
229
|
-
if (!paymentIntentResult)
|
|
276
|
+
if (!payment)
|
|
230
277
|
throw new MedusaError(
|
|
231
|
-
MedusaError.Types.
|
|
278
|
+
MedusaError.Types.NOT_FOUND,
|
|
232
279
|
"Payment not found"
|
|
233
280
|
);
|
|
234
281
|
return {
|
|
235
|
-
status:
|
|
236
|
-
data:
|
|
282
|
+
status: PaymentStatus$inboundSchema(payment.status),
|
|
283
|
+
data: payment
|
|
237
284
|
};
|
|
238
285
|
};
|
|
239
286
|
refundPayment = async (input) => {
|
|
240
287
|
if (this.options.debug) {
|
|
241
288
|
console.info("[PayKit] Refunding payment", input);
|
|
242
289
|
}
|
|
243
|
-
const { id: paymentId } = validateRequiredKeys(
|
|
244
|
-
["id"],
|
|
245
|
-
input
|
|
290
|
+
const { id: paymentId, reason = "customer_request" } = validateRequiredKeys(
|
|
291
|
+
["id", "reason"],
|
|
292
|
+
input.data ?? {},
|
|
246
293
|
"Missing required fields: {keys}",
|
|
247
294
|
(message) => new MedusaError(MedusaError.Types.INVALID_DATA, message)
|
|
248
295
|
);
|
|
249
|
-
const
|
|
296
|
+
const refund = await this.exec(
|
|
250
297
|
this.paykit.refunds.create({
|
|
251
298
|
payment_id: paymentId,
|
|
252
|
-
amount: Number(input.amount),
|
|
253
|
-
reason
|
|
254
|
-
metadata: input.data?.metadata
|
|
255
|
-
provider_metadata: input.data?.provider_metadata
|
|
256
|
-
})
|
|
299
|
+
amount: Number(input.amount) * this.options.amountToCentsMultiplier,
|
|
300
|
+
reason,
|
|
301
|
+
metadata: input.data?.metadata ?? null,
|
|
302
|
+
provider_metadata: input.data?.provider_metadata ?? void 0
|
|
303
|
+
}),
|
|
304
|
+
"Refund"
|
|
257
305
|
);
|
|
258
|
-
|
|
259
|
-
throw new MedusaError(
|
|
260
|
-
MedusaError.Types.PAYMENT_AUTHORIZATION_ERROR,
|
|
261
|
-
refundError.message
|
|
262
|
-
);
|
|
263
|
-
return { data: refundResult };
|
|
306
|
+
return { data: refund };
|
|
264
307
|
};
|
|
265
308
|
retrievePayment = async (input) => {
|
|
266
309
|
if (this.options.debug) {
|
|
267
310
|
console.info("[PayKit] Retrieving payment", input);
|
|
268
311
|
}
|
|
269
|
-
const { id } = validateRequiredKeys(
|
|
312
|
+
const { id: paymentId } = validateRequiredKeys(
|
|
270
313
|
["id"],
|
|
271
|
-
input
|
|
314
|
+
input.data ?? {},
|
|
272
315
|
"Missing required fields: {keys}",
|
|
273
316
|
(message) => new MedusaError(MedusaError.Types.INVALID_DATA, message)
|
|
274
317
|
);
|
|
275
|
-
const
|
|
276
|
-
this.paykit.payments.retrieve(
|
|
318
|
+
const payment = await this.exec(
|
|
319
|
+
this.paykit.payments.retrieve(paymentId),
|
|
320
|
+
"Retrieve"
|
|
277
321
|
);
|
|
278
|
-
|
|
279
|
-
throw new MedusaError(
|
|
280
|
-
MedusaError.Types.PAYMENT_AUTHORIZATION_ERROR,
|
|
281
|
-
paymentIntentError.message
|
|
282
|
-
);
|
|
283
|
-
return { data: paymentIntentResult };
|
|
322
|
+
return { data: payment };
|
|
284
323
|
};
|
|
285
324
|
updatePayment = async (input) => {
|
|
286
325
|
if (this.options.debug) {
|
|
287
326
|
console.info("[PayKit] Updating payment", input);
|
|
288
327
|
}
|
|
289
|
-
const {
|
|
290
|
-
|
|
291
|
-
|
|
328
|
+
const {
|
|
329
|
+
amount,
|
|
330
|
+
id: paymentId,
|
|
331
|
+
currency_code: currencyCode
|
|
332
|
+
} = validateRequiredKeys(
|
|
333
|
+
["amount", "currency_code", "id"],
|
|
334
|
+
input.data ?? {},
|
|
292
335
|
"Missing required fields: {keys}",
|
|
293
336
|
(message) => new MedusaError(MedusaError.Types.INVALID_DATA, message)
|
|
294
337
|
);
|
|
295
|
-
const
|
|
296
|
-
["id"],
|
|
297
|
-
input.data,
|
|
298
|
-
"Missing required fields: {keys}",
|
|
299
|
-
(message) => new MedusaError(MedusaError.Types.INVALID_DATA, message)
|
|
300
|
-
);
|
|
301
|
-
const metadata = input.data?.metadata ?? {};
|
|
302
|
-
const [paymentIntentResult, paymentIntentError] = await tryCatchAsync(
|
|
338
|
+
const data = await this.exec(
|
|
303
339
|
this.paykit.payments.update(paymentId, {
|
|
304
|
-
amount: Number(amount),
|
|
305
|
-
currency:
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
340
|
+
amount: Number(amount) * this.options.amountToCentsMultiplier,
|
|
341
|
+
currency: currencyCode.toUpperCase(),
|
|
342
|
+
provider_metadata: input.data?.provider_metadata
|
|
343
|
+
}),
|
|
344
|
+
"Update"
|
|
309
345
|
);
|
|
310
|
-
|
|
311
|
-
throw new MedusaError(
|
|
312
|
-
MedusaError.Types.PAYMENT_AUTHORIZATION_ERROR,
|
|
313
|
-
paymentIntentError.message
|
|
314
|
-
);
|
|
315
|
-
return { data: paymentIntentResult };
|
|
346
|
+
return { data };
|
|
316
347
|
};
|
|
317
348
|
getWebhookActionAndData = async (payload) => {
|
|
318
349
|
if (this.options.debug) {
|
|
319
|
-
console.info(
|
|
350
|
+
console.info(
|
|
351
|
+
"[PayKit] Resolving webhook action and data",
|
|
352
|
+
payload
|
|
353
|
+
);
|
|
320
354
|
}
|
|
321
355
|
const { rawData, headers } = payload;
|
|
322
|
-
const
|
|
356
|
+
const body = Buffer.isBuffer(rawData) ? rawData.toString("utf8") : rawData;
|
|
357
|
+
const headersMap = Object.fromEntries(
|
|
358
|
+
Object.entries(headers).map(([k, v]) => [k, String(v)])
|
|
359
|
+
);
|
|
360
|
+
let result = {
|
|
361
|
+
action: PaymentActions.NOT_SUPPORTED
|
|
362
|
+
};
|
|
363
|
+
const statusMap = {
|
|
364
|
+
pending: PaymentActions.PENDING,
|
|
365
|
+
processing: PaymentActions.PENDING,
|
|
366
|
+
requires_action: PaymentActions.REQUIRES_MORE,
|
|
367
|
+
requires_capture: PaymentActions.AUTHORIZED,
|
|
368
|
+
succeeded: PaymentActions.SUCCESSFUL,
|
|
369
|
+
failed: PaymentActions.FAILED,
|
|
370
|
+
canceled: PaymentActions.CANCELED
|
|
371
|
+
};
|
|
323
372
|
const webhook = this.paykit.webhooks.setup({ webhookSecret: this.options.webhookSecret }).on("payment.created", async (event) => {
|
|
324
|
-
|
|
325
|
-
action:
|
|
373
|
+
result = {
|
|
374
|
+
action: statusMap[event?.data?.status ?? "pending"],
|
|
326
375
|
data: {
|
|
327
376
|
session_id: event.data?.metadata?.session_id,
|
|
328
|
-
amount: event.data?.amount
|
|
377
|
+
amount: event.data?.amount ? event.data?.amount * this.options.amountToCentsMultiplier : 0
|
|
329
378
|
}
|
|
330
379
|
};
|
|
331
380
|
}).on("payment.updated", async (event) => {
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
processing: PaymentActions.PENDING,
|
|
335
|
-
requires_action: PaymentActions.REQUIRES_MORE,
|
|
336
|
-
requires_capture: PaymentActions.AUTHORIZED,
|
|
337
|
-
succeeded: PaymentActions.SUCCESSFUL,
|
|
338
|
-
failed: PaymentActions.FAILED,
|
|
339
|
-
canceled: PaymentActions.CANCELED
|
|
340
|
-
};
|
|
341
|
-
return {
|
|
342
|
-
action: event.data?.status ? statusActionMap[event.data.status] : PaymentActions.PENDING,
|
|
381
|
+
result = {
|
|
382
|
+
action: statusMap[event?.data?.status ?? "pending"],
|
|
343
383
|
data: {
|
|
344
384
|
session_id: event.data?.metadata?.session_id,
|
|
345
|
-
amount: event.data?.amount
|
|
385
|
+
amount: event.data?.amount ? event.data?.amount * this.options.amountToCentsMultiplier : 0
|
|
346
386
|
}
|
|
347
387
|
};
|
|
348
|
-
}).on("payment.
|
|
349
|
-
|
|
388
|
+
}).on("payment.failed", async (event) => {
|
|
389
|
+
result = {
|
|
350
390
|
action: PaymentActions.CANCELED,
|
|
351
391
|
data: {
|
|
352
|
-
|
|
353
|
-
|
|
392
|
+
amount: event.data?.amount ? event.data?.amount * this.options.amountToCentsMultiplier : 0,
|
|
393
|
+
session_id: event.data?.metadata?.session_id
|
|
354
394
|
}
|
|
355
395
|
};
|
|
356
396
|
});
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
body: bodyString,
|
|
362
|
-
headers: new Headers(stringifiedHeaders),
|
|
363
|
-
fullUrl: getURLFromHeaders(stringifiedHeaders)
|
|
397
|
+
await webhook.handle({
|
|
398
|
+
body,
|
|
399
|
+
headersAsObject: headersMap,
|
|
400
|
+
fullUrl: getURLFromHeaders(headersMap)
|
|
364
401
|
});
|
|
365
|
-
return
|
|
402
|
+
return result;
|
|
366
403
|
};
|
|
367
404
|
createAccountHolder = async ({
|
|
368
405
|
context,
|
|
369
406
|
data
|
|
370
407
|
}) => {
|
|
408
|
+
if (context.account_holder?.data?.id) {
|
|
409
|
+
return { id: context.account_holder.data.id };
|
|
410
|
+
}
|
|
371
411
|
if (this.options.debug) {
|
|
372
412
|
console.info("[PayKit] Creating account holder", context, data);
|
|
373
413
|
}
|
|
374
|
-
const {
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
if (!
|
|
414
|
+
const { fullName } = parseCustomerName({
|
|
415
|
+
email: context.customer?.email
|
|
416
|
+
});
|
|
417
|
+
const billingInfo = billingSchema.safeParse(data?.billing);
|
|
418
|
+
if (data?.billing && !billingInfo.success) {
|
|
379
419
|
throw new MedusaError(
|
|
380
420
|
MedusaError.Types.INVALID_DATA,
|
|
381
|
-
|
|
421
|
+
`Invalid billing information, ${billingInfo.error.message} `
|
|
382
422
|
);
|
|
383
423
|
}
|
|
384
|
-
const
|
|
424
|
+
const res = await this.exec(
|
|
385
425
|
this.paykit.customers.create({
|
|
386
|
-
email: customer
|
|
387
|
-
name:
|
|
388
|
-
phone: customer
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
}
|
|
426
|
+
email: context.customer?.email,
|
|
427
|
+
name: fullName,
|
|
428
|
+
phone: context.customer?.phone ?? null,
|
|
429
|
+
billing: billingInfo.data ?? null
|
|
430
|
+
}),
|
|
431
|
+
"Create Account Holder",
|
|
432
|
+
{ allowUnsupported: true }
|
|
393
433
|
);
|
|
394
|
-
if (
|
|
395
|
-
throw new MedusaError(
|
|
396
|
-
MedusaError.Types.PAYMENT_AUTHORIZATION_ERROR,
|
|
397
|
-
accountHolderError.message
|
|
398
|
-
);
|
|
399
|
-
}
|
|
434
|
+
if (!res) return {};
|
|
400
435
|
return {
|
|
401
|
-
id:
|
|
402
|
-
data:
|
|
436
|
+
id: res.id,
|
|
437
|
+
data: res
|
|
403
438
|
};
|
|
404
439
|
};
|
|
405
440
|
updateAccountHolder = async ({
|
|
@@ -409,36 +444,32 @@ var PaykitMedusaJSAdapter = class extends AbstractPaymentProvider {
|
|
|
409
444
|
if (this.options.debug) {
|
|
410
445
|
console.info("[PayKit] Updating account holder", context, data);
|
|
411
446
|
}
|
|
412
|
-
const { account_holder, customer
|
|
447
|
+
const { account_holder, customer } = context;
|
|
413
448
|
if (!account_holder.data?.id) {
|
|
414
449
|
throw new MedusaError(
|
|
415
450
|
MedusaError.Types.INVALID_DATA,
|
|
416
451
|
"Account holder not found in context"
|
|
417
452
|
);
|
|
418
453
|
}
|
|
419
|
-
if (!customer) {
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
email:
|
|
426
|
-
name:
|
|
427
|
-
phone:
|
|
428
|
-
...data?.metadata
|
|
429
|
-
metadata:
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
454
|
+
if (!customer) return {};
|
|
455
|
+
const res = await this.exec(
|
|
456
|
+
this.paykit.customers.update(account_holder.data.id, {
|
|
457
|
+
...data?.billing != null ? {
|
|
458
|
+
billing: billingSchema.safeParse(data.billing).data ?? null
|
|
459
|
+
} : {},
|
|
460
|
+
...data?.email != null ? { email: data.email } : {},
|
|
461
|
+
...data?.name != null ? { name: data.name } : {},
|
|
462
|
+
...data?.phone != null ? { phone: data.phone } : {},
|
|
463
|
+
...data?.metadata != null ? {
|
|
464
|
+
metadata: data.metadata
|
|
465
|
+
} : {},
|
|
466
|
+
...data?.provider_metadata != null ? {
|
|
467
|
+
provider_metadata: data.provider_metadata
|
|
468
|
+
} : {}
|
|
469
|
+
}),
|
|
470
|
+
"Update Account Holder"
|
|
434
471
|
);
|
|
435
|
-
|
|
436
|
-
throw new MedusaError(
|
|
437
|
-
MedusaError.Types.PAYMENT_AUTHORIZATION_ERROR,
|
|
438
|
-
accountHolderError.message
|
|
439
|
-
);
|
|
440
|
-
}
|
|
441
|
-
return { data: accountHolderResult };
|
|
472
|
+
return { data: res };
|
|
442
473
|
};
|
|
443
474
|
deleteAccountHolder = async ({
|
|
444
475
|
context,
|
|
@@ -454,17 +485,11 @@ var PaykitMedusaJSAdapter = class extends AbstractPaymentProvider {
|
|
|
454
485
|
"Account holder not found in context"
|
|
455
486
|
);
|
|
456
487
|
}
|
|
457
|
-
const
|
|
458
|
-
|
|
459
|
-
|
|
488
|
+
const res = await this.exec(
|
|
489
|
+
this.paykit.customers.delete(account_holder.data.id),
|
|
490
|
+
"Delete Account Holder"
|
|
460
491
|
);
|
|
461
|
-
|
|
462
|
-
throw new MedusaError(
|
|
463
|
-
MedusaError.Types.PAYMENT_AUTHORIZATION_ERROR,
|
|
464
|
-
accountHolderError.message
|
|
465
|
-
);
|
|
466
|
-
}
|
|
467
|
-
return { data: accountHolderResult };
|
|
492
|
+
return { data: res };
|
|
468
493
|
};
|
|
469
494
|
};
|
|
470
495
|
|