1 | |
2 | type Paypal = { |
3 | clientId: string; |
4 | clientSecret: string; |
5 | }; |
6 |
|
7 | async function getToken(auth: Paypal): Promise<string> { |
8 | const url = new URL(`https://api-m.paypal.com/v1/oauth2/token`); |
9 | const response = await fetch(url, { |
10 | method: "POST", |
11 | headers: { |
12 | Authorization: `Basic ${btoa(`${auth.clientId}:${auth.clientSecret}`)}`, |
13 | }, |
14 | body: new URLSearchParams({ |
15 | grant_type: "client_credentials", |
16 | }), |
17 | }); |
18 | if (!response.ok) { |
19 | const text = await response.text(); |
20 | throw new Error(`Could not get token: ${response.status} ${text}`); |
21 | } |
22 | const json = await response.json(); |
23 | return json.access_token; |
24 | } |
25 | |
26 | * Capture payment for order |
27 | * Captures payment for an order. To successfully capture payment for an order, the buyer must first approve the order or a valid payment_source must be provided in the request. A buyer can approve the order upon being redirected to the rel:approve URL that was returned in the HATEOAS links in the create order response.Note: For error handling and troubleshooting, see Orders v2 errors. |
28 | */ |
29 | export async function main( |
30 | auth: Paypal, |
31 | id: string, |
32 | PayPal_Request_Id: string, |
33 | Prefer: string, |
34 | PayPal_Client_Metadata_Id: string, |
35 | PayPal_Auth_Assertion: string, |
36 | body: { |
37 | payment_source?: { |
38 | card?: { |
39 | id?: string; |
40 | name?: string; |
41 | number?: string; |
42 | expiry?: string; |
43 | security_code?: string; |
44 | last_digits?: string; |
45 | card_type?: |
46 | | "VISA" |
47 | | "MASTERCARD" |
48 | | "DISCOVER" |
49 | | "AMEX" |
50 | | "SOLO" |
51 | | "JCB" |
52 | | "STAR" |
53 | | "DELTA" |
54 | | "SWITCH" |
55 | | "MAESTRO" |
56 | | "CB_NATIONALE" |
57 | | "CONFIGOGA" |
58 | | "CONFIDIS" |
59 | | "ELECTRON" |
60 | | "CETELEM" |
61 | | "CHINA_UNION_PAY"; |
62 | type?: "CREDIT" | "DEBIT" | "PREPAID" | "STORE" | "UNKNOWN"; |
63 | brand?: |
64 | | "VISA" |
65 | | "MASTERCARD" |
66 | | "DISCOVER" |
67 | | "AMEX" |
68 | | "SOLO" |
69 | | "JCB" |
70 | | "STAR" |
71 | | "DELTA" |
72 | | "SWITCH" |
73 | | "MAESTRO" |
74 | | "CB_NATIONALE" |
75 | | "CONFIGOGA" |
76 | | "CONFIDIS" |
77 | | "ELECTRON" |
78 | | "CETELEM" |
79 | | "CHINA_UNION_PAY"; |
80 | billing_address?: { |
81 | address_line_1?: string; |
82 | address_line_2?: string; |
83 | address_line_3?: string; |
84 | admin_area_4?: string; |
85 | admin_area_3?: string; |
86 | admin_area_2?: string; |
87 | admin_area_1?: string; |
88 | postal_code?: string; |
89 | country_code: string; |
90 | address_details?: { |
91 | street_number?: string; |
92 | street_name?: string; |
93 | street_type?: string; |
94 | delivery_service?: string; |
95 | building_name?: string; |
96 | sub_building?: string; |
97 | }; |
98 | }; |
99 | attributes?: { |
100 | customer?: { |
101 | id?: string; |
102 | email_address?: string; |
103 | phone?: { |
104 | phone_type?: "FAX" | "HOME" | "MOBILE" | "OTHER" | "PAGER"; |
105 | phone_number: { |
106 | country_code: string; |
107 | national_number: string; |
108 | extension_number?: string; |
109 | }; |
110 | }; |
111 | }; |
112 | vault?: { store_in_vault?: "ON_SUCCESS" }; |
113 | }; |
114 | } & { |
115 | vault_id?: string; |
116 | stored_credential?: { |
117 | payment_initiator: "CUSTOMER" | "MERCHANT"; |
118 | payment_type: "ONE_TIME" | "RECURRING" | "UNSCHEDULED"; |
119 | usage?: "FIRST" | "SUBSEQUENT" | "DERIVED"; |
120 | previous_network_transaction_reference?: { |
121 | id: string; |
122 | date?: string; |
123 | network?: |
124 | | "VISA" |
125 | | "MASTERCARD" |
126 | | "DISCOVER" |
127 | | "AMEX" |
128 | | "SOLO" |
129 | | "JCB" |
130 | | "STAR" |
131 | | "DELTA" |
132 | | "SWITCH" |
133 | | "MAESTRO" |
134 | | "CB_NATIONALE" |
135 | | "CONFIGOGA" |
136 | | "CONFIDIS" |
137 | | "ELECTRON" |
138 | | "CETELEM" |
139 | | "CHINA_UNION_PAY"; |
140 | acquirer_reference_number?: string; |
141 | }; |
142 | }; |
143 | network_token?: { |
144 | number: string; |
145 | expiry: string; |
146 | cryptogram?: string; |
147 | eci_flag?: |
148 | | "MASTERCARD_NON_3D_SECURE_TRANSACTION" |
149 | | "MASTERCARD_ATTEMPTED_AUTHENTICATION_TRANSACTION" |
150 | | "MASTERCARD_FULLY_AUTHENTICATED_TRANSACTION" |
151 | | "FULLY_AUTHENTICATED_TRANSACTION" |
152 | | "ATTEMPTED_AUTHENTICATION_TRANSACTION" |
153 | | "NON_3D_SECURE_TRANSACTION"; |
154 | token_requestor_id?: string; |
155 | }; |
156 | experience_context?: { return_url?: string; cancel_url?: string }; |
157 | }; |
158 | token?: { id: string; type: "BILLING_AGREEMENT" }; |
159 | paypal?: { |
160 | vault_id?: string; |
161 | email_address?: string; |
162 | name?: { |
163 | prefix?: string; |
164 | given_name?: string; |
165 | surname?: string; |
166 | middle_name?: string; |
167 | suffix?: string; |
168 | full_name?: string; |
169 | }; |
170 | phone?: { |
171 | phone_type?: "FAX" | "HOME" | "MOBILE" | "OTHER" | "PAGER"; |
172 | phone_number: { |
173 | country_code: string; |
174 | national_number: string; |
175 | extension_number?: string; |
176 | }; |
177 | }; |
178 | birth_date?: string; |
179 | tax_info?: { tax_id: string; tax_id_type: "BR_CPF" | "BR_CNPJ" }; |
180 | address?: { |
181 | address_line_1?: string; |
182 | address_line_2?: string; |
183 | address_line_3?: string; |
184 | admin_area_4?: string; |
185 | admin_area_3?: string; |
186 | admin_area_2?: string; |
187 | admin_area_1?: string; |
188 | postal_code?: string; |
189 | country_code: string; |
190 | address_details?: { |
191 | street_number?: string; |
192 | street_name?: string; |
193 | street_type?: string; |
194 | delivery_service?: string; |
195 | building_name?: string; |
196 | sub_building?: string; |
197 | }; |
198 | }; |
199 | attributes?: { |
200 | customer?: { |
201 | id?: string; |
202 | email_address?: string; |
203 | phone?: { |
204 | phone_type?: "FAX" | "HOME" | "MOBILE" | "OTHER" | "PAGER"; |
205 | phone_number: { |
206 | country_code: string; |
207 | national_number: string; |
208 | extension_number?: string; |
209 | }; |
210 | }; |
211 | } & {}; |
212 | vault?: { store_in_vault?: "ON_SUCCESS" } & { |
213 | description?: string; |
214 | usage_pattern?: |
215 | | "IMMEDIATE" |
216 | | "DEFERRED" |
217 | | "RECURRING_PREPAID" |
218 | | "RECURRING_POSTPAID" |
219 | | "THRESHOLD_PREPAID" |
220 | | "THRESHOLD_POSTPAID"; |
221 | shipping?: { |
222 | name?: { |
223 | prefix?: string; |
224 | given_name?: string; |
225 | surname?: string; |
226 | middle_name?: string; |
227 | suffix?: string; |
228 | alternate_full_name?: string; |
229 | full_name?: string; |
230 | }; |
231 | type?: |
232 | | "SHIPPING" |
233 | | "PICKUP_IN_PERSON" |
234 | | "PICKUP_IN_STORE" |
235 | | "PICKUP_FROM_PERSON"; |
236 | options?: { |
237 | id: string; |
238 | label: string; |
239 | type?: |
240 | | "SHIPPING" |
241 | | "PICKUP_IN_STORE" |
242 | | "PICKUP_FROM_PERSON" |
243 | | "PICKUP"; |
244 | amount?: { currency_code: string; value: string }; |
245 | selected: false | true; |
246 | }[]; |
247 | address?: { |
248 | address_line_1?: string; |
249 | address_line_2?: string; |
250 | address_line_3?: string; |
251 | admin_area_4?: string; |
252 | admin_area_3?: string; |
253 | admin_area_2?: string; |
254 | admin_area_1?: string; |
255 | postal_code?: string; |
256 | country_code: string; |
257 | address_details?: { |
258 | street_number?: string; |
259 | street_name?: string; |
260 | street_type?: string; |
261 | delivery_service?: string; |
262 | building_name?: string; |
263 | sub_building?: string; |
264 | }; |
265 | }; |
266 | }; |
267 | usage_type?: "MERCHANT" | "PLATFORM"; |
268 | owner_id?: unknown; |
269 | customer_type?: "CONSUMER" | "BUSINESS"; |
270 | permit_multiple_payment_tokens?: false | true; |
271 | }; |
272 | }; |
273 | experience_context?: { |
274 | brand_name?: string; |
275 | locale?: string; |
276 | shipping_preference?: |
277 | | "GET_FROM_FILE" |
278 | | "NO_SHIPPING" |
279 | | "SET_PROVIDED_ADDRESS"; |
280 | return_url?: string; |
281 | cancel_url?: string; |
282 | landing_page?: "LOGIN" | "GUEST_CHECKOUT" | "NO_PREFERENCE"; |
283 | user_action?: "CONTINUE" | "PAY_NOW"; |
284 | payment_method_preference?: |
285 | | "UNRESTRICTED" |
286 | | "IMMEDIATE_PAYMENT_REQUIRED"; |
287 | }; |
288 | billing_agreement_id?: string; |
289 | }; |
290 | bancontact?: { |
291 | name: string; |
292 | country_code: string; |
293 | experience_context?: { |
294 | brand_name?: string; |
295 | locale?: string; |
296 | shipping_preference?: |
297 | | "GET_FROM_FILE" |
298 | | "NO_SHIPPING" |
299 | | "SET_PROVIDED_ADDRESS"; |
300 | return_url?: string; |
301 | cancel_url?: string; |
302 | }; |
303 | attributes?: {}; |
304 | }; |
305 | blik?: { |
306 | name: string; |
307 | country_code: string; |
308 | email?: string; |
309 | experience_context?: { |
310 | brand_name?: string; |
311 | locale?: string; |
312 | shipping_preference?: |
313 | | "GET_FROM_FILE" |
314 | | "NO_SHIPPING" |
315 | | "SET_PROVIDED_ADDRESS"; |
316 | return_url?: string; |
317 | cancel_url?: string; |
318 | } & { consumer_ip?: string; consumer_user_agent?: string }; |
319 | level_0?: { auth_code: string }; |
320 | one_click?: { |
321 | auth_code?: string; |
322 | consumer_reference: string; |
323 | alias_label?: string; |
324 | alias_key?: string; |
325 | }; |
326 | }; |
327 | eps?: { |
328 | name: string; |
329 | country_code: string; |
330 | experience_context?: { |
331 | brand_name?: string; |
332 | locale?: string; |
333 | shipping_preference?: |
334 | | "GET_FROM_FILE" |
335 | | "NO_SHIPPING" |
336 | | "SET_PROVIDED_ADDRESS"; |
337 | return_url?: string; |
338 | cancel_url?: string; |
339 | }; |
340 | }; |
341 | giropay?: { |
342 | name: string; |
343 | country_code: string; |
344 | experience_context?: { |
345 | brand_name?: string; |
346 | locale?: string; |
347 | shipping_preference?: |
348 | | "GET_FROM_FILE" |
349 | | "NO_SHIPPING" |
350 | | "SET_PROVIDED_ADDRESS"; |
351 | return_url?: string; |
352 | cancel_url?: string; |
353 | }; |
354 | }; |
355 | ideal?: { |
356 | name: string; |
357 | country_code: string; |
358 | bic?: string; |
359 | experience_context?: { |
360 | brand_name?: string; |
361 | locale?: string; |
362 | shipping_preference?: |
363 | | "GET_FROM_FILE" |
364 | | "NO_SHIPPING" |
365 | | "SET_PROVIDED_ADDRESS"; |
366 | return_url?: string; |
367 | cancel_url?: string; |
368 | }; |
369 | attributes?: {}; |
370 | }; |
371 | mybank?: { |
372 | name: string; |
373 | country_code: string; |
374 | experience_context?: { |
375 | brand_name?: string; |
376 | locale?: string; |
377 | shipping_preference?: |
378 | | "GET_FROM_FILE" |
379 | | "NO_SHIPPING" |
380 | | "SET_PROVIDED_ADDRESS"; |
381 | return_url?: string; |
382 | cancel_url?: string; |
383 | }; |
384 | }; |
385 | p24?: { |
386 | name: string; |
387 | email: string; |
388 | country_code: string; |
389 | experience_context?: { |
390 | brand_name?: string; |
391 | locale?: string; |
392 | shipping_preference?: |
393 | | "GET_FROM_FILE" |
394 | | "NO_SHIPPING" |
395 | | "SET_PROVIDED_ADDRESS"; |
396 | return_url?: string; |
397 | cancel_url?: string; |
398 | }; |
399 | }; |
400 | sofort?: { |
401 | name: string; |
402 | country_code: string; |
403 | experience_context?: { |
404 | brand_name?: string; |
405 | locale?: string; |
406 | shipping_preference?: |
407 | | "GET_FROM_FILE" |
408 | | "NO_SHIPPING" |
409 | | "SET_PROVIDED_ADDRESS"; |
410 | return_url?: string; |
411 | cancel_url?: string; |
412 | }; |
413 | }; |
414 | trustly?: { |
415 | name: string; |
416 | country_code: string; |
417 | experience_context?: { |
418 | brand_name?: string; |
419 | locale?: string; |
420 | shipping_preference?: |
421 | | "GET_FROM_FILE" |
422 | | "NO_SHIPPING" |
423 | | "SET_PROVIDED_ADDRESS"; |
424 | return_url?: string; |
425 | cancel_url?: string; |
426 | }; |
427 | }; |
428 | apple_pay?: { |
429 | id?: string; |
430 | name?: string; |
431 | email_address?: string; |
432 | phone_number?: { |
433 | country_code: string; |
434 | national_number: string; |
435 | extension_number?: string; |
436 | }; |
437 | decrypted_token?: { |
438 | transaction_amount?: { currency_code: string; value: string }; |
439 | tokenized_card: { |
440 | id?: string; |
441 | name?: string; |
442 | number?: string; |
443 | expiry?: string; |
444 | security_code?: string; |
445 | last_digits?: string; |
446 | card_type?: |
447 | | "VISA" |
448 | | "MASTERCARD" |
449 | | "DISCOVER" |
450 | | "AMEX" |
451 | | "SOLO" |
452 | | "JCB" |
453 | | "STAR" |
454 | | "DELTA" |
455 | | "SWITCH" |
456 | | "MAESTRO" |
457 | | "CB_NATIONALE" |
458 | | "CONFIGOGA" |
459 | | "CONFIDIS" |
460 | | "ELECTRON" |
461 | | "CETELEM" |
462 | | "CHINA_UNION_PAY"; |
463 | type?: "CREDIT" | "DEBIT" | "PREPAID" | "STORE" | "UNKNOWN"; |
464 | brand?: |
465 | | "VISA" |
466 | | "MASTERCARD" |
467 | | "DISCOVER" |
468 | | "AMEX" |
469 | | "SOLO" |
470 | | "JCB" |
471 | | "STAR" |
472 | | "DELTA" |
473 | | "SWITCH" |
474 | | "MAESTRO" |
475 | | "CB_NATIONALE" |
476 | | "CONFIGOGA" |
477 | | "CONFIDIS" |
478 | | "ELECTRON" |
479 | | "CETELEM" |
480 | | "CHINA_UNION_PAY"; |
481 | billing_address?: { |
482 | address_line_1?: string; |
483 | address_line_2?: string; |
484 | address_line_3?: string; |
485 | admin_area_4?: string; |
486 | admin_area_3?: string; |
487 | admin_area_2?: string; |
488 | admin_area_1?: string; |
489 | postal_code?: string; |
490 | country_code: string; |
491 | address_details?: { |
492 | street_number?: string; |
493 | street_name?: string; |
494 | street_type?: string; |
495 | delivery_service?: string; |
496 | building_name?: string; |
497 | sub_building?: string; |
498 | }; |
499 | }; |
500 | attributes?: { |
501 | customer?: { |
502 | id?: string; |
503 | email_address?: string; |
504 | phone?: { |
505 | phone_type?: "FAX" | "HOME" | "MOBILE" | "OTHER" | "PAGER"; |
506 | phone_number: { |
507 | country_code: string; |
508 | national_number: string; |
509 | extension_number?: string; |
510 | }; |
511 | }; |
512 | }; |
513 | vault?: { store_in_vault?: "ON_SUCCESS" }; |
514 | }; |
515 | }; |
516 | device_manufacturer_id?: string; |
517 | payment_data_type?: "3DSECURE" | "EMV"; |
518 | payment_data?: { |
519 | cryptogram?: string; |
520 | eci_indicator?: string; |
521 | emv_data?: string; |
522 | pin?: string; |
523 | }; |
524 | }; |
525 | stored_credential?: { |
526 | payment_initiator: "CUSTOMER" | "MERCHANT"; |
527 | payment_type: "ONE_TIME" | "RECURRING" | "UNSCHEDULED"; |
528 | usage?: "FIRST" | "SUBSEQUENT" | "DERIVED"; |
529 | previous_network_transaction_reference?: { |
530 | id: string; |
531 | date?: string; |
532 | network?: |
533 | | "VISA" |
534 | | "MASTERCARD" |
535 | | "DISCOVER" |
536 | | "AMEX" |
537 | | "SOLO" |
538 | | "JCB" |
539 | | "STAR" |
540 | | "DELTA" |
541 | | "SWITCH" |
542 | | "MAESTRO" |
543 | | "CB_NATIONALE" |
544 | | "CONFIGOGA" |
545 | | "CONFIDIS" |
546 | | "ELECTRON" |
547 | | "CETELEM" |
548 | | "CHINA_UNION_PAY"; |
549 | acquirer_reference_number?: string; |
550 | }; |
551 | }; |
552 | vault_id?: string; |
553 | attributes?: unknown; |
554 | }; |
555 | google_pay?: {}; |
556 | venmo?: { |
557 | vault_id?: string; |
558 | email_address?: string; |
559 | experience_context?: { |
560 | brand_name?: string; |
561 | shipping_preference?: |
562 | | "GET_FROM_FILE" |
563 | | "NO_SHIPPING" |
564 | | "SET_PROVIDED_ADDRESS"; |
565 | }; |
566 | attributes?: { |
567 | customer?: { |
568 | id?: string; |
569 | email_address?: string; |
570 | phone?: { |
571 | phone_type?: "FAX" | "HOME" | "MOBILE" | "OTHER" | "PAGER"; |
572 | phone_number: { |
573 | country_code: string; |
574 | national_number: string; |
575 | extension_number?: string; |
576 | }; |
577 | }; |
578 | }; |
579 | vault?: { store_in_vault: "ON_SUCCESS" } & { |
580 | description?: string; |
581 | usage_pattern?: |
582 | | "IMMEDIATE" |
583 | | "DEFERRED" |
584 | | "RECURRING_PREPAID" |
585 | | "RECURRING_POSTPAID" |
586 | | "THRESHOLD_PREPAID" |
587 | | "THRESHOLD_POSTPAID"; |
588 | usage_type?: "MERCHANT" | "PLATFORM"; |
589 | customer_type?: "CONSUMER" | "BUSINESS"; |
590 | permit_multiple_payment_tokens?: false | true; |
591 | }; |
592 | }; |
593 | }; |
594 | }; |
595 | }, |
596 | ) { |
597 | const token = await getToken(auth); |
598 | const url = new URL( |
599 | `https://api-m.paypal.com/v2/checkout/orders/${id}/capture`, |
600 | ); |
601 |
|
602 | const response = await fetch(url, { |
603 | method: "POST", |
604 | headers: { |
605 | "PayPal-Request-Id": PayPal_Request_Id, |
606 | Prefer: Prefer, |
607 | "PayPal-Client-Metadata-Id": PayPal_Client_Metadata_Id, |
608 | "PayPal-Auth-Assertion": PayPal_Auth_Assertion, |
609 | "Content-Type": "application/json", |
610 | Authorization: "Bearer " + token, |
611 | }, |
612 | body: JSON.stringify(body), |
613 | }); |
614 | if (!response.ok) { |
615 | const text = await response.text(); |
616 | throw new Error(`${response.status} ${text}`); |
617 | } |
618 | return await response.json(); |
619 | } |
620 |
|