1 | |
2 | type Paypal = { |
3 | clientId: string; |
4 | clientSecret: string; |
5 | }; |
6 | type Base64 = string; |
7 |
|
8 | async function getToken(auth: Paypal): Promise<string> { |
9 | const url = new URL(`https://api-m.paypal.com/v1/oauth2/token`); |
10 | const response = await fetch(url, { |
11 | method: "POST", |
12 | headers: { |
13 | Authorization: `Basic ${btoa(`${auth.clientId}:${auth.clientSecret}`)}`, |
14 | }, |
15 | body: new URLSearchParams({ |
16 | grant_type: "client_credentials", |
17 | }), |
18 | }); |
19 | if (!response.ok) { |
20 | const text = await response.text(); |
21 | throw new Error(`Could not get token: ${response.status} ${text}`); |
22 | } |
23 | const json = await response.json(); |
24 | return json.access_token; |
25 | } |
26 |
|
27 | |
28 | * Provide evidence |
29 | * Provides evidence for a dispute, by ID. |
30 | */ |
31 | export async function main( |
32 | auth: Paypal, |
33 | id: string, |
34 | body: { |
35 | "evidence-file"?: { |
36 | base64: Base64; |
37 | type: |
38 | | "image/png" |
39 | | "image/jpeg" |
40 | | "image/gif" |
41 | | "application/pdf" |
42 | | "appication/json" |
43 | | "text/csv" |
44 | | "text/plain" |
45 | | "audio/mpeg" |
46 | | "audio/wav" |
47 | | "video/mp4"; |
48 | name: string; |
49 | }; |
50 | } |
51 | ) { |
52 | const token = await getToken(auth); |
53 | const url = new URL( |
54 | `https://api-m.paypal.com/v1/customer/disputes/${id}/provide-evidence` |
55 | ); |
56 |
|
57 | const formData = new FormData(); |
58 | for (const [k, v] of Object.entries(body)) { |
59 | if (v !== undefined) { |
60 | if (["evidence-file"].includes(k)) { |
61 | const { base64, type, name } = v as { |
62 | base64: Base64; |
63 | type: string; |
64 | name: string; |
65 | }; |
66 | formData.append( |
67 | k, |
68 | new Blob([Uint8Array.from(atob(base64), (m) => m.codePointAt(0)!)], { |
69 | type, |
70 | }), |
71 | name |
72 | ); |
73 | } else { |
74 | formData.append(k, String(v)); |
75 | } |
76 | } |
77 | } |
78 | const response = await fetch(url, { |
79 | method: "POST", |
80 | headers: { |
81 | Authorization: "Bearer " + token, |
82 | }, |
83 | body: formData, |
84 | }); |
85 | if (!response.ok) { |
86 | const text = await response.text(); |
87 | throw new Error(`${response.status} ${text}`); |
88 | } |
89 | return await response.json(); |
90 | } |
91 |
|