@paykit-sdk/paypal 1.0.5 → 1.0.7

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.
@@ -1,29 +1,46 @@
1
1
  import { omitInternalMetadata } from '@paykit-sdk/core';
2
+ import { OrderStatus } from '@paypal/paypal-server-sdk';
2
3
 
3
4
  // src/utils/mapper.ts
4
- var paykitRefund$InboundSchema = (refund) => {
5
+ var Payee$inboundSchema = (payee) => {
6
+ if (typeof payee === "string") return { id: payee };
7
+ if (payee?.emailAddress) return { email: payee.emailAddress };
8
+ return null;
9
+ };
10
+ var Refund$inboundSchema = (refund) => {
5
11
  return {
6
12
  id: refund.id,
7
13
  amount: refund.amount?.value ? parseFloat(refund.amount.value) : 0,
8
14
  currency: refund.amount?.currencyCode || "USD",
9
- metadata: refund.customId ? omitInternalMetadata(JSON.parse(refund.customId)) : {},
15
+ metadata: omitInternalMetadata(
16
+ JSON.parse(refund.customId ?? "{}")
17
+ ),
10
18
  reason: refund.noteToPayer ?? null
11
19
  };
12
20
  };
13
- var paykitCheckout$InboundSchema = (order) => {
21
+ var Checkout$inboundSchema = (order) => {
14
22
  return {
15
23
  id: order.id,
16
24
  payment_url: order.links?.find((l) => l.rel === "approve")?.href || "",
17
- amount: parseFloat(order.purchaseUnits?.[0]?.amount?.value || "0"),
25
+ amount: parseFloat(
26
+ order.purchaseUnits?.[0]?.amount?.value || "0"
27
+ ),
18
28
  currency: order.purchaseUnits?.[0]?.amount?.currencyCode || "USD",
19
- customer: order.payer?.payerId ? order.payer?.payerId : { email: order.payer?.emailAddress ?? "" },
29
+ customer: Payee$inboundSchema(order.payer ?? {}),
20
30
  session_type: "one_time",
21
- products: [{ id: order.purchaseUnits?.[0]?.items?.[0]?.sku || "", quantity: 1 }],
22
- metadata: order.purchaseUnits?.[0]?.customId ? omitInternalMetadata(JSON.parse(order.purchaseUnits?.[0]?.customId)) : {},
31
+ products: [
32
+ {
33
+ id: order.purchaseUnits?.[0]?.items?.[0]?.sku || "",
34
+ quantity: 1
35
+ }
36
+ ],
37
+ metadata: omitInternalMetadata(
38
+ JSON.parse(order.purchaseUnits?.[0]?.customId ?? "{}")
39
+ ),
23
40
  subscription: null
24
41
  };
25
42
  };
26
- var paykitPayment$InboundSchema = (order) => {
43
+ var Payment$inboundSchema = (order) => {
27
44
  const statusMap = {
28
45
  CREATED: "pending",
29
46
  SAVED: "pending",
@@ -33,17 +50,29 @@ var paykitPayment$InboundSchema = (order) => {
33
50
  PAYER_ACTION_REQUIRED: "requires_action"
34
51
  };
35
52
  const status = statusMap[order.status ?? statusMap.CREATED];
53
+ const approveLink = order.links?.find((l) => l.rel === "approve")?.href ?? "";
54
+ const requiresAction = [
55
+ OrderStatus.PayerActionRequired,
56
+ OrderStatus.Created,
57
+ OrderStatus.Saved
58
+ ].includes(order.status);
36
59
  return {
37
60
  id: order.id,
38
61
  status,
39
- amount: parseFloat(order.purchaseUnits?.[0]?.amount?.value || "0"),
62
+ customer: Payee$inboundSchema(order.payer ?? {}),
63
+ amount: parseFloat(
64
+ order.purchaseUnits?.[0]?.amount?.value || "0"
65
+ ),
40
66
  currency: order.purchaseUnits?.[0]?.amount?.currencyCode || "USD",
41
- metadata: order.purchaseUnits?.[0]?.customId ? omitInternalMetadata(JSON.parse(order.purchaseUnits?.[0]?.customId)) : {},
42
- customer: order.payer?.payerId ? order.payer?.payerId : { email: order.payer?.emailAddress ?? "" },
43
- item_id: order.purchaseUnits?.[0]?.items?.[0]?.sku || ""
67
+ metadata: omitInternalMetadata(
68
+ JSON.parse(order.purchaseUnits?.[0]?.customId ?? "{}")
69
+ ),
70
+ item_id: order.purchaseUnits?.[0]?.items?.[0]?.sku || "",
71
+ requires_action: requiresAction,
72
+ payment_url: approveLink
44
73
  };
45
74
  };
46
- var paykitSubscription$InboundSchema = (subscription) => {
75
+ var Subscription$inboundSchema = (subscription) => {
47
76
  const statusMap = {
48
77
  APPROVAL_PENDING: "pending",
49
78
  APPROVED: "active",
@@ -53,20 +82,247 @@ var paykitSubscription$InboundSchema = (subscription) => {
53
82
  EXPIRED: "canceled"
54
83
  };
55
84
  const status = statusMap[subscription.status ?? statusMap.APPROVAL_PENDING];
85
+ const tenureType = subscription.billing_info?.cycle_executions?.[0]?.tenure_type?.toUpperCase();
86
+ const billingIntervalMap = {
87
+ DAY: "day",
88
+ WEEK: "week",
89
+ MONTH: "month",
90
+ YEAR: "year"
91
+ };
92
+ const billingInterval = tenureType && billingIntervalMap[tenureType] ? billingIntervalMap[tenureType] : "month";
93
+ const periodStart = subscription.start_time ? new Date(subscription.start_time) : /* @__PURE__ */ new Date();
94
+ const periodEnd = (() => {
95
+ if (!subscription.start_time) {
96
+ return /* @__PURE__ */ new Date();
97
+ }
98
+ const start = new Date(subscription.start_time);
99
+ const end = new Date(start);
100
+ switch (billingInterval) {
101
+ case "day":
102
+ end.setDate(end.getDate() + 1);
103
+ break;
104
+ case "week":
105
+ end.setDate(end.getDate() + 7);
106
+ break;
107
+ case "month":
108
+ end.setMonth(end.getMonth() + 1);
109
+ break;
110
+ case "year":
111
+ end.setFullYear(end.getFullYear() + 1);
112
+ break;
113
+ default:
114
+ end.setMonth(end.getMonth() + 1);
115
+ }
116
+ return end;
117
+ })();
118
+ const email = subscription.subscriber?.email_address;
56
119
  return {
57
120
  id: subscription.id,
58
- customer: { email: subscription.subscriber?.email_address ?? "" },
121
+ customer: email ? { email } : null,
59
122
  status,
60
123
  item_id: subscription.plan_id,
61
- current_period_start: subscription.start_time ? new Date(subscription.start_time) : /* @__PURE__ */ new Date(),
62
- current_period_end: subscription.status_update_time ? new Date(subscription.status_update_time) : /* @__PURE__ */ new Date(),
63
- // todo: Would need to calculate based on billing cycle
64
- metadata: subscription.customId ? omitInternalMetadata(JSON.parse(subscription.customId)) : {},
65
- billing_interval: "month",
124
+ current_period_start: periodStart,
125
+ current_period_end: periodEnd,
126
+ metadata: omitInternalMetadata(
127
+ JSON.parse(subscription?.customId ?? "{}")
128
+ ),
129
+ billing_interval: billingInterval,
66
130
  amount: 0,
67
131
  currency: "USD",
68
- custom_fields: null
132
+ custom_fields: null,
133
+ requires_action: false,
134
+ payment_url: null
135
+ };
136
+ };
137
+ var Invoice$inboundSchema = (order) => {
138
+ return {
139
+ id: order.id,
140
+ amount_paid: parseFloat(
141
+ order.purchaseUnits?.[0]?.amount?.value || "0"
142
+ ),
143
+ currency: order.purchaseUnits?.[0]?.amount?.currencyCode || "USD",
144
+ customer: Payee$inboundSchema(order.payer ?? {}),
145
+ status: "paid",
146
+ paid_at: (/* @__PURE__ */ new Date()).toISOString(),
147
+ metadata: omitInternalMetadata(
148
+ JSON.parse(order.purchaseUnits?.[0]?.customId ?? "{}")
149
+ ),
150
+ custom_fields: null,
151
+ subscription_id: null,
152
+ billing_mode: "one_time",
153
+ line_items: [
154
+ {
155
+ id: order.purchaseUnits?.[0]?.items?.[0]?.sku || "",
156
+ quantity: 1
157
+ }
158
+ ]
159
+ };
160
+ };
161
+ var PaymentWebhook$inboundSchema = (resource) => {
162
+ const statusMap = {
163
+ CREATED: "pending",
164
+ SAVED: "pending",
165
+ APPROVED: "requires_capture",
166
+ VOIDED: "canceled",
167
+ COMPLETED: "succeeded",
168
+ PAYER_ACTION_REQUIRED: "requires_action"
169
+ };
170
+ const status = statusMap[resource.status ?? "CREATED"] ?? "pending";
171
+ const payer = resource.payer;
172
+ let customer = null;
173
+ if (payer?.payer_id) {
174
+ customer = { id: payer.payer_id };
175
+ } else if (payer?.email_address) {
176
+ customer = { email: payer.email_address };
177
+ }
178
+ const purchaseUnits = resource.purchase_units ?? [];
179
+ const firstUnit = purchaseUnits[0] ?? {};
180
+ const amount = firstUnit.amount;
181
+ const items = firstUnit.items ?? [];
182
+ const metadata = (() => {
183
+ try {
184
+ const customId = firstUnit?.custom_id;
185
+ return customId ? JSON.parse(customId) : {};
186
+ } catch {
187
+ return {};
188
+ }
189
+ })();
190
+ const itemId = items[0]?.sku ?? firstUnit.reference_id ?? "";
191
+ return {
192
+ id: resource.id,
193
+ status,
194
+ customer,
195
+ amount: parseFloat(amount?.value ?? "0"),
196
+ currency: amount?.currency_code ?? "USD",
197
+ metadata: omitInternalMetadata(metadata),
198
+ item_id: itemId,
199
+ requires_action: false,
200
+ payment_url: null
201
+ };
202
+ };
203
+ var PaymentCaptureWebhook$inboundSchema = (capture) => {
204
+ const statusMap = {
205
+ COMPLETED: "succeeded",
206
+ PENDING: "pending",
207
+ REFUNDED: "succeeded",
208
+ PARTIALLY_REFUNDED: "succeeded"
209
+ };
210
+ const status = statusMap[capture.status ?? "PENDING"] ?? "pending";
211
+ const supplementaryData = capture.supplementary_data;
212
+ const relatedIds = supplementaryData?.related_ids;
213
+ const orderId = relatedIds?.order_id ?? capture.id;
214
+ const metadata = (() => {
215
+ try {
216
+ const customId = capture.custom_id;
217
+ return customId ? JSON.parse(customId) : {};
218
+ } catch {
219
+ return {};
220
+ }
221
+ })();
222
+ const amount = capture.amount;
223
+ return {
224
+ id: orderId,
225
+ status,
226
+ customer: null,
227
+ amount: parseFloat(amount?.value ?? "0"),
228
+ currency: amount?.currency_code ?? "USD",
229
+ metadata: omitInternalMetadata(metadata),
230
+ item_id: "",
231
+ requires_action: false,
232
+ payment_url: null
233
+ };
234
+ };
235
+ var RefundWebhook$inboundSchema = (refund) => {
236
+ const amount = refund.amount;
237
+ const refundAmount = amount?.total ? Math.abs(parseFloat(amount.total)) : 0;
238
+ return {
239
+ id: refund.id,
240
+ amount: refundAmount,
241
+ currency: amount?.currency ?? "USD",
242
+ metadata: omitInternalMetadata({}),
243
+ reason: null
244
+ };
245
+ };
246
+ var SubscriptionWebhook$inboundSchema = (agreement) => {
247
+ const state = agreement.state ?? "Pending";
248
+ const statusMap = {
249
+ Pending: "pending",
250
+ Active: "active",
251
+ Suspended: "past_due",
252
+ Cancelled: "canceled",
253
+ Expired: "canceled",
254
+ Completed: "active"
255
+ };
256
+ const status = statusMap[state] ?? "pending";
257
+ const plan = agreement.plan;
258
+ const paymentDefinitions = plan?.payment_definitions ?? [];
259
+ const regularDefinition = paymentDefinitions.find(
260
+ (def) => def.type === "REGULAR"
261
+ ) ?? paymentDefinitions[0];
262
+ const frequency = regularDefinition?.frequency ?? "Month";
263
+ const billingIntervalMap = {
264
+ Day: "day",
265
+ Days: "day",
266
+ Week: "week",
267
+ Weeks: "week",
268
+ Month: "month",
269
+ Months: "month",
270
+ Year: "year",
271
+ Years: "year"
272
+ };
273
+ const billingInterval = billingIntervalMap[frequency] ?? "month";
274
+ const startDate = agreement.start_date ?? (/* @__PURE__ */ new Date()).toISOString();
275
+ const periodStart = new Date(startDate);
276
+ const periodEnd = (() => {
277
+ const end = new Date(periodStart);
278
+ switch (billingInterval) {
279
+ case "day":
280
+ end.setDate(end.getDate() + 1);
281
+ break;
282
+ case "week":
283
+ end.setDate(end.getDate() + 7);
284
+ break;
285
+ case "month":
286
+ end.setMonth(end.getMonth() + 1);
287
+ break;
288
+ case "year":
289
+ end.setFullYear(end.getFullYear() + 1);
290
+ break;
291
+ default:
292
+ end.setMonth(end.getMonth() + 1);
293
+ }
294
+ return end;
295
+ })();
296
+ const payer = agreement.payer;
297
+ const payerInfo = payer?.payer_info;
298
+ const email = payerInfo?.email;
299
+ const planId = plan?.id ?? agreement.id;
300
+ const amount = regularDefinition?.amount;
301
+ const subscriptionAmount = amount?.value ? parseFloat(amount.value) : 0;
302
+ const currency = plan?.curr_code ?? "USD";
303
+ const metadata = (() => {
304
+ try {
305
+ const description = agreement.description;
306
+ return description ? JSON.parse(description) : {};
307
+ } catch {
308
+ return {};
309
+ }
310
+ })();
311
+ return {
312
+ id: agreement.id,
313
+ customer: email ? { email } : null,
314
+ status,
315
+ item_id: planId,
316
+ current_period_start: periodStart,
317
+ current_period_end: periodEnd,
318
+ metadata: omitInternalMetadata(metadata),
319
+ billing_interval: billingInterval,
320
+ amount: subscriptionAmount,
321
+ currency,
322
+ custom_fields: null,
323
+ requires_action: false,
324
+ payment_url: null
69
325
  };
70
326
  };
71
327
 
72
- export { paykitCheckout$InboundSchema, paykitPayment$InboundSchema, paykitRefund$InboundSchema, paykitSubscription$InboundSchema };
328
+ export { Checkout$inboundSchema, Invoice$inboundSchema, Payee$inboundSchema, Payment$inboundSchema, PaymentCaptureWebhook$inboundSchema, PaymentWebhook$inboundSchema, Refund$inboundSchema, RefundWebhook$inboundSchema, Subscription$inboundSchema, SubscriptionWebhook$inboundSchema };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paykit-sdk/paypal",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "PayPal provider for PayKit",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.esm.js",
@@ -8,6 +8,9 @@
8
8
  "files": [
9
9
  "dist"
10
10
  ],
11
+ "scripts": {
12
+ "build": "tsup"
13
+ },
11
14
  "keywords": [
12
15
  "paypal",
13
16
  "paykit",
@@ -17,16 +20,16 @@
17
20
  "author": "Emmanuel Odii",
18
21
  "license": "ISC",
19
22
  "devDependencies": {
23
+ "@paykit-sdk/core": "workspace:*",
20
24
  "tsup": "^8.5.0",
21
- "typescript": "^5.9.2",
22
- "zod": "^3.24.2",
23
- "@paykit-sdk/core": "1.1.97"
25
+ "typescript": "^5.9.2"
24
26
  },
25
27
  "dependencies": {
26
- "@paypal/paypal-server-sdk": "^1.1.0"
28
+ "@paypal/paypal-server-sdk": "^1.1.0",
29
+ "esbuild": "^0.25.11"
27
30
  },
28
31
  "peerDependencies": {
29
- "@paykit-sdk/core": ">=1.1.97"
32
+ "@paykit-sdk/core": ">=1.1.103"
30
33
  },
31
34
  "publishConfig": {
32
35
  "access": "public"
@@ -37,8 +40,5 @@
37
40
  },
38
41
  "bugs": {
39
42
  "url": "https://github.com/usepaykit/paykit-sdk/issues"
40
- },
41
- "scripts": {
42
- "build": "tsup"
43
43
  }
44
- }
44
+ }