0

Confirm the Order

by
Published Apr 8, 2025

Payer confirms their intent to pay for the the Order with the given payment source.

Script paypal Verified

The script

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

636
  const response = await fetch(url, {
637
    method: "POST",
638
    headers: {
639
      "PayPal-Client-Metadata-Id": PayPal_Client_Metadata_Id,
640
      Prefer: Prefer,
641
      "Content-Type": "application/json",
642
      Authorization: "Bearer " + token,
643
    },
644
    body: JSON.stringify(body),
645
  });
646
  if (!response.ok) {
647
    const text = await response.text();
648
    throw new Error(`${response.status} ${text}`);
649
  }
650
  return await response.json();
651
}
652