@paykit-sdk/medusajs 1.0.12 → 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 +264 -254
- package/dist/index.mjs +265 -255
- package/dist/providers/paykit-provider.d.mts +19 -15
- package/dist/providers/paykit-provider.d.ts +19 -15
- package/dist/providers/paykit-provider.js +264 -254
- package/dist/providers/paykit-provider.mjs +265 -255
- 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
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { AbstractPaymentProvider, MedusaError, PaymentSessionStatus, PaymentActions } from '@medusajs/framework/utils';
|
|
2
|
-
import { providerSchema, PayKit, billingSchema,
|
|
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/providers/paykit-provider.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,29 +51,48 @@ 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
|
+
);
|
|
77
|
+
}
|
|
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
|
+
);
|
|
73
94
|
}
|
|
95
|
+
return result;
|
|
74
96
|
}
|
|
75
97
|
initiatePayment = async ({
|
|
76
98
|
context,
|
|
@@ -81,341 +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
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
);
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
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(
|
|
120
139
|
this.paykit.customers.create({
|
|
121
140
|
email: customer.email,
|
|
122
|
-
|
|
123
|
-
|
|
141
|
+
name: fullName,
|
|
142
|
+
phone: data?.phone ?? null,
|
|
143
|
+
billing: billingInfo.data ?? null,
|
|
124
144
|
metadata: {
|
|
125
|
-
PAYKIT_METADATA_KEY: JSON.stringify({
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
})
|
|
129
|
-
);
|
|
130
|
-
if (createError) {
|
|
131
|
-
if (createError.name === "ProviderNotSupportedError") {
|
|
132
|
-
if (this.options.debug) {
|
|
133
|
-
console.info(
|
|
134
|
-
`[PayKit] Provider ${this.provider.providerName} doesn't support customer creation, using email object`
|
|
135
|
-
);
|
|
145
|
+
[PAYKIT_METADATA_KEY]: JSON.stringify({
|
|
146
|
+
source: "medusa-paykit-adapter"
|
|
147
|
+
})
|
|
136
148
|
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
149
|
+
}),
|
|
150
|
+
"Customer Creation",
|
|
151
|
+
{ allowUnsupported: true }
|
|
152
|
+
);
|
|
153
|
+
if (created) {
|
|
154
|
+
customer = {
|
|
155
|
+
..."id" in created ? { id: created.id } : {},
|
|
156
|
+
..."email" in created ? { email: created.email } : {}
|
|
157
|
+
};
|
|
145
158
|
}
|
|
146
|
-
} else {
|
|
147
|
-
customer = customer;
|
|
148
159
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
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"
|
|
152
175
|
);
|
|
153
|
-
if (paymentIntentError) {
|
|
154
|
-
throw new MedusaError(
|
|
155
|
-
MedusaError.Types.PAYMENT_AUTHORIZATION_ERROR,
|
|
156
|
-
paymentIntentError.message
|
|
157
|
-
);
|
|
158
|
-
}
|
|
159
|
-
if (paymentIntentResult.requires_action && paymentIntentResult.payment_url) {
|
|
160
|
-
return {
|
|
161
|
-
id: paymentIntentResult.id,
|
|
162
|
-
status: PaymentSessionStatus.REQUIRES_MORE,
|
|
163
|
-
data: {
|
|
164
|
-
payment_url: paymentIntentResult.payment_url
|
|
165
|
-
}
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
176
|
return {
|
|
169
|
-
id:
|
|
170
|
-
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 }
|
|
171
180
|
};
|
|
172
181
|
};
|
|
173
182
|
capturePayment = async (input) => {
|
|
174
183
|
if (this.options.debug) {
|
|
175
184
|
console.info("[PayKit] Capturing payment", input);
|
|
176
185
|
}
|
|
177
|
-
const { id, amount } = validateRequiredKeys(
|
|
186
|
+
const { id: paymentId, amount } = validateRequiredKeys(
|
|
178
187
|
["id", "amount"],
|
|
179
|
-
input
|
|
188
|
+
input.data ?? {},
|
|
180
189
|
"Missing required fields: {keys}",
|
|
181
190
|
(message) => new MedusaError(MedusaError.Types.INVALID_DATA, message)
|
|
182
191
|
);
|
|
183
|
-
const
|
|
184
|
-
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"
|
|
185
197
|
);
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
paymentIntentError.message
|
|
190
|
-
);
|
|
191
|
-
return { data: paymentIntentResult };
|
|
198
|
+
return {
|
|
199
|
+
data
|
|
200
|
+
};
|
|
192
201
|
};
|
|
193
202
|
authorizePayment = async (input) => {
|
|
194
|
-
|
|
195
|
-
|
|
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
|
+
);
|
|
196
218
|
}
|
|
197
|
-
|
|
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
|
+
};
|
|
198
230
|
};
|
|
199
231
|
cancelPayment = async (input) => {
|
|
200
232
|
if (this.options.debug) {
|
|
201
233
|
console.info("[PayKit] Canceling payment", input);
|
|
202
234
|
}
|
|
203
|
-
const { id } = validateRequiredKeys(
|
|
235
|
+
const { id: paymentId } = validateRequiredKeys(
|
|
204
236
|
["id"],
|
|
205
|
-
input
|
|
237
|
+
input.data ?? {},
|
|
206
238
|
"Missing required fields: {keys}",
|
|
207
239
|
(message) => new MedusaError(MedusaError.Types.INVALID_DATA, message)
|
|
208
240
|
);
|
|
209
|
-
const
|
|
210
|
-
this.paykit.payments.cancel(
|
|
241
|
+
const data = await this.exec(
|
|
242
|
+
this.paykit.payments.cancel(paymentId),
|
|
243
|
+
"Cancel"
|
|
211
244
|
);
|
|
212
|
-
|
|
213
|
-
throw new MedusaError(
|
|
214
|
-
MedusaError.Types.PAYMENT_AUTHORIZATION_ERROR,
|
|
215
|
-
paymentIntentError.message
|
|
216
|
-
);
|
|
217
|
-
return { data: paymentIntentResult };
|
|
245
|
+
return { data };
|
|
218
246
|
};
|
|
219
247
|
deletePayment = async (input) => {
|
|
220
|
-
|
|
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 };
|
|
221
264
|
};
|
|
222
265
|
getPaymentStatus = async (input) => {
|
|
223
|
-
const { id } = validateRequiredKeys(
|
|
266
|
+
const { id: paymentId } = validateRequiredKeys(
|
|
224
267
|
["id"],
|
|
225
|
-
input
|
|
268
|
+
input.data ?? {},
|
|
226
269
|
"Missing required fields: {keys}",
|
|
227
270
|
(message) => new MedusaError(MedusaError.Types.INVALID_DATA, message)
|
|
228
271
|
);
|
|
229
|
-
const
|
|
230
|
-
this.paykit.payments.retrieve(
|
|
272
|
+
const payment = await this.exec(
|
|
273
|
+
this.paykit.payments.retrieve(paymentId),
|
|
274
|
+
"Status"
|
|
231
275
|
);
|
|
232
|
-
if (
|
|
276
|
+
if (!payment)
|
|
233
277
|
throw new MedusaError(
|
|
234
|
-
MedusaError.Types.
|
|
235
|
-
paymentIntentError.message
|
|
236
|
-
);
|
|
237
|
-
if (!paymentIntentResult)
|
|
238
|
-
throw new MedusaError(
|
|
239
|
-
MedusaError.Types.PAYMENT_AUTHORIZATION_ERROR,
|
|
278
|
+
MedusaError.Types.NOT_FOUND,
|
|
240
279
|
"Payment not found"
|
|
241
280
|
);
|
|
242
281
|
return {
|
|
243
|
-
status:
|
|
244
|
-
data:
|
|
282
|
+
status: PaymentStatus$inboundSchema(payment.status),
|
|
283
|
+
data: payment
|
|
245
284
|
};
|
|
246
285
|
};
|
|
247
286
|
refundPayment = async (input) => {
|
|
248
287
|
if (this.options.debug) {
|
|
249
288
|
console.info("[PayKit] Refunding payment", input);
|
|
250
289
|
}
|
|
251
|
-
const { id: paymentId } = validateRequiredKeys(
|
|
252
|
-
["id"],
|
|
253
|
-
input
|
|
290
|
+
const { id: paymentId, reason = "customer_request" } = validateRequiredKeys(
|
|
291
|
+
["id", "reason"],
|
|
292
|
+
input.data ?? {},
|
|
254
293
|
"Missing required fields: {keys}",
|
|
255
294
|
(message) => new MedusaError(MedusaError.Types.INVALID_DATA, message)
|
|
256
295
|
);
|
|
257
|
-
const
|
|
296
|
+
const refund = await this.exec(
|
|
258
297
|
this.paykit.refunds.create({
|
|
259
298
|
payment_id: paymentId,
|
|
260
|
-
amount: Number(input.amount),
|
|
261
|
-
reason
|
|
262
|
-
metadata: input.data?.metadata
|
|
263
|
-
provider_metadata: input.data?.provider_metadata
|
|
264
|
-
})
|
|
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"
|
|
265
305
|
);
|
|
266
|
-
|
|
267
|
-
throw new MedusaError(
|
|
268
|
-
MedusaError.Types.PAYMENT_AUTHORIZATION_ERROR,
|
|
269
|
-
refundError.message
|
|
270
|
-
);
|
|
271
|
-
return { data: refundResult };
|
|
306
|
+
return { data: refund };
|
|
272
307
|
};
|
|
273
308
|
retrievePayment = async (input) => {
|
|
274
309
|
if (this.options.debug) {
|
|
275
310
|
console.info("[PayKit] Retrieving payment", input);
|
|
276
311
|
}
|
|
277
|
-
const { id } = validateRequiredKeys(
|
|
312
|
+
const { id: paymentId } = validateRequiredKeys(
|
|
278
313
|
["id"],
|
|
279
|
-
input
|
|
314
|
+
input.data ?? {},
|
|
280
315
|
"Missing required fields: {keys}",
|
|
281
316
|
(message) => new MedusaError(MedusaError.Types.INVALID_DATA, message)
|
|
282
317
|
);
|
|
283
|
-
const
|
|
284
|
-
this.paykit.payments.retrieve(
|
|
318
|
+
const payment = await this.exec(
|
|
319
|
+
this.paykit.payments.retrieve(paymentId),
|
|
320
|
+
"Retrieve"
|
|
285
321
|
);
|
|
286
|
-
|
|
287
|
-
throw new MedusaError(
|
|
288
|
-
MedusaError.Types.PAYMENT_AUTHORIZATION_ERROR,
|
|
289
|
-
paymentIntentError.message
|
|
290
|
-
);
|
|
291
|
-
return { data: paymentIntentResult };
|
|
322
|
+
return { data: payment };
|
|
292
323
|
};
|
|
293
324
|
updatePayment = async (input) => {
|
|
294
325
|
if (this.options.debug) {
|
|
295
326
|
console.info("[PayKit] Updating payment", input);
|
|
296
327
|
}
|
|
297
|
-
const {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
["id"],
|
|
305
|
-
input.data,
|
|
328
|
+
const {
|
|
329
|
+
amount,
|
|
330
|
+
id: paymentId,
|
|
331
|
+
currency_code: currencyCode
|
|
332
|
+
} = validateRequiredKeys(
|
|
333
|
+
["amount", "currency_code", "id"],
|
|
334
|
+
input.data ?? {},
|
|
306
335
|
"Missing required fields: {keys}",
|
|
307
336
|
(message) => new MedusaError(MedusaError.Types.INVALID_DATA, message)
|
|
308
337
|
);
|
|
309
|
-
const
|
|
310
|
-
const [paymentIntentResult, paymentIntentError] = await tryCatchAsync(
|
|
338
|
+
const data = await this.exec(
|
|
311
339
|
this.paykit.payments.update(paymentId, {
|
|
312
|
-
amount: Number(amount),
|
|
313
|
-
currency:
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
340
|
+
amount: Number(amount) * this.options.amountToCentsMultiplier,
|
|
341
|
+
currency: currencyCode.toUpperCase(),
|
|
342
|
+
provider_metadata: input.data?.provider_metadata
|
|
343
|
+
}),
|
|
344
|
+
"Update"
|
|
317
345
|
);
|
|
318
|
-
|
|
319
|
-
throw new MedusaError(
|
|
320
|
-
MedusaError.Types.PAYMENT_AUTHORIZATION_ERROR,
|
|
321
|
-
paymentIntentError.message
|
|
322
|
-
);
|
|
323
|
-
return { data: paymentIntentResult };
|
|
346
|
+
return { data };
|
|
324
347
|
};
|
|
325
348
|
getWebhookActionAndData = async (payload) => {
|
|
326
349
|
if (this.options.debug) {
|
|
327
|
-
console.info(
|
|
350
|
+
console.info(
|
|
351
|
+
"[PayKit] Resolving webhook action and data",
|
|
352
|
+
payload
|
|
353
|
+
);
|
|
328
354
|
}
|
|
329
355
|
const { rawData, headers } = payload;
|
|
330
|
-
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
|
+
};
|
|
331
372
|
const webhook = this.paykit.webhooks.setup({ webhookSecret: this.options.webhookSecret }).on("payment.created", async (event) => {
|
|
332
|
-
|
|
333
|
-
action:
|
|
373
|
+
result = {
|
|
374
|
+
action: statusMap[event?.data?.status ?? "pending"],
|
|
334
375
|
data: {
|
|
335
376
|
session_id: event.data?.metadata?.session_id,
|
|
336
|
-
amount: event.data?.amount
|
|
377
|
+
amount: event.data?.amount ? event.data?.amount * this.options.amountToCentsMultiplier : 0
|
|
337
378
|
}
|
|
338
379
|
};
|
|
339
380
|
}).on("payment.updated", async (event) => {
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
processing: PaymentActions.PENDING,
|
|
343
|
-
requires_action: PaymentActions.REQUIRES_MORE,
|
|
344
|
-
requires_capture: PaymentActions.AUTHORIZED,
|
|
345
|
-
succeeded: PaymentActions.SUCCESSFUL,
|
|
346
|
-
failed: PaymentActions.FAILED,
|
|
347
|
-
canceled: PaymentActions.CANCELED
|
|
348
|
-
};
|
|
349
|
-
return {
|
|
350
|
-
action: event.data?.status ? statusActionMap[event.data.status] : PaymentActions.PENDING,
|
|
381
|
+
result = {
|
|
382
|
+
action: statusMap[event?.data?.status ?? "pending"],
|
|
351
383
|
data: {
|
|
352
384
|
session_id: event.data?.metadata?.session_id,
|
|
353
|
-
amount: event.data?.amount
|
|
385
|
+
amount: event.data?.amount ? event.data?.amount * this.options.amountToCentsMultiplier : 0
|
|
354
386
|
}
|
|
355
387
|
};
|
|
356
|
-
}).on("payment.
|
|
357
|
-
|
|
388
|
+
}).on("payment.failed", async (event) => {
|
|
389
|
+
result = {
|
|
358
390
|
action: PaymentActions.CANCELED,
|
|
359
391
|
data: {
|
|
360
|
-
|
|
361
|
-
|
|
392
|
+
amount: event.data?.amount ? event.data?.amount * this.options.amountToCentsMultiplier : 0,
|
|
393
|
+
session_id: event.data?.metadata?.session_id
|
|
362
394
|
}
|
|
363
395
|
};
|
|
364
396
|
});
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
body: bodyString,
|
|
370
|
-
headers: new Headers(stringifiedHeaders),
|
|
371
|
-
fullUrl: getURLFromHeaders(stringifiedHeaders)
|
|
397
|
+
await webhook.handle({
|
|
398
|
+
body,
|
|
399
|
+
headersAsObject: headersMap,
|
|
400
|
+
fullUrl: getURLFromHeaders(headersMap)
|
|
372
401
|
});
|
|
373
|
-
return
|
|
402
|
+
return result;
|
|
374
403
|
};
|
|
375
404
|
createAccountHolder = async ({
|
|
376
405
|
context,
|
|
377
406
|
data
|
|
378
407
|
}) => {
|
|
408
|
+
if (context.account_holder?.data?.id) {
|
|
409
|
+
return { id: context.account_holder.data.id };
|
|
410
|
+
}
|
|
379
411
|
if (this.options.debug) {
|
|
380
412
|
console.info("[PayKit] Creating account holder", context, data);
|
|
381
413
|
}
|
|
382
|
-
const {
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
if (!
|
|
387
|
-
throw new MedusaError(
|
|
388
|
-
MedusaError.Types.INVALID_DATA,
|
|
389
|
-
"Customer not found in context"
|
|
390
|
-
);
|
|
391
|
-
}
|
|
392
|
-
const billingInfoParsed = billingSchema.safeParse(data?.billing);
|
|
393
|
-
if (data?.billing && !billingInfoParsed.success) {
|
|
414
|
+
const { fullName } = parseCustomerName({
|
|
415
|
+
email: context.customer?.email
|
|
416
|
+
});
|
|
417
|
+
const billingInfo = billingSchema.safeParse(data?.billing);
|
|
418
|
+
if (data?.billing && !billingInfo.success) {
|
|
394
419
|
throw new MedusaError(
|
|
395
420
|
MedusaError.Types.INVALID_DATA,
|
|
396
|
-
`Invalid billing information, ${
|
|
421
|
+
`Invalid billing information, ${billingInfo.error.message} `
|
|
397
422
|
);
|
|
398
423
|
}
|
|
399
|
-
const
|
|
424
|
+
const res = await this.exec(
|
|
400
425
|
this.paykit.customers.create({
|
|
401
|
-
email: customer
|
|
402
|
-
name:
|
|
403
|
-
phone: customer
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
})
|
|
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 }
|
|
409
433
|
);
|
|
410
|
-
if (
|
|
411
|
-
throw new MedusaError(
|
|
412
|
-
MedusaError.Types.PAYMENT_AUTHORIZATION_ERROR,
|
|
413
|
-
accountHolderError.message
|
|
414
|
-
);
|
|
415
|
-
}
|
|
434
|
+
if (!res) return {};
|
|
416
435
|
return {
|
|
417
|
-
id:
|
|
418
|
-
data:
|
|
436
|
+
id: res.id,
|
|
437
|
+
data: res
|
|
419
438
|
};
|
|
420
439
|
};
|
|
421
440
|
updateAccountHolder = async ({
|
|
@@ -433,27 +452,24 @@ var PaykitMedusaJSAdapter = class extends AbstractPaymentProvider {
|
|
|
433
452
|
);
|
|
434
453
|
}
|
|
435
454
|
if (!customer) return {};
|
|
436
|
-
const
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
...data?.
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
},
|
|
447
|
-
|
|
448
|
-
|
|
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"
|
|
449
471
|
);
|
|
450
|
-
|
|
451
|
-
throw new MedusaError(
|
|
452
|
-
MedusaError.Types.PAYMENT_AUTHORIZATION_ERROR,
|
|
453
|
-
accountHolderError.message
|
|
454
|
-
);
|
|
455
|
-
}
|
|
456
|
-
return { data: accountHolderResult };
|
|
472
|
+
return { data: res };
|
|
457
473
|
};
|
|
458
474
|
deleteAccountHolder = async ({
|
|
459
475
|
context,
|
|
@@ -469,17 +485,11 @@ var PaykitMedusaJSAdapter = class extends AbstractPaymentProvider {
|
|
|
469
485
|
"Account holder not found in context"
|
|
470
486
|
);
|
|
471
487
|
}
|
|
472
|
-
const
|
|
473
|
-
|
|
474
|
-
|
|
488
|
+
const res = await this.exec(
|
|
489
|
+
this.paykit.customers.delete(account_holder.data.id),
|
|
490
|
+
"Delete Account Holder"
|
|
475
491
|
);
|
|
476
|
-
|
|
477
|
-
throw new MedusaError(
|
|
478
|
-
MedusaError.Types.PAYMENT_AUTHORIZATION_ERROR,
|
|
479
|
-
accountHolderError.message
|
|
480
|
-
);
|
|
481
|
-
}
|
|
482
|
-
return { data: accountHolderResult };
|
|
492
|
+
return { data: res };
|
|
483
493
|
};
|
|
484
494
|
};
|
|
485
495
|
|