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 | * Fully update template |
27 | * Fully updates a template, by ID. In the JSON request body, include a complete `template` object. This call does not support partial updates. |
28 | */ |
29 | export async function main( |
30 | auth: Paypal, |
31 | template_id: string, |
32 | body: { |
33 | id?: string; |
34 | name?: string; |
35 | default_template?: false | true; |
36 | template_info?: { |
37 | detail?: { |
38 | reference?: string; |
39 | currency_code: string; |
40 | note?: string; |
41 | terms_and_conditions?: string; |
42 | memo?: string; |
43 | attachments?: { |
44 | id?: string; |
45 | reference_url?: string; |
46 | content_type?: string; |
47 | create_time?: string; |
48 | size?: string; |
49 | }[]; |
50 | } & { |
51 | payment_term?: { |
52 | term_type?: |
53 | | "DUE_ON_RECEIPT" |
54 | | "DUE_ON_DATE_SPECIFIED" |
55 | | "NET_10" |
56 | | "NET_15" |
57 | | "NET_30" |
58 | | "NET_45" |
59 | | "NET_60" |
60 | | "NET_90" |
61 | | "NO_DUE_DATE"; |
62 | }; |
63 | metadata?: { |
64 | create_time?: string; |
65 | created_by?: string; |
66 | last_update_time?: string; |
67 | last_updated_by?: string; |
68 | }; |
69 | }; |
70 | invoicer?: { business_name?: string } & { |
71 | name?: { |
72 | prefix?: string; |
73 | given_name?: string; |
74 | surname?: string; |
75 | middle_name?: string; |
76 | suffix?: string; |
77 | alternate_full_name?: string; |
78 | full_name?: string; |
79 | }; |
80 | 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 | } & { |
100 | email_address?: string; |
101 | phones?: { |
102 | country_code: string; |
103 | national_number: string; |
104 | extension_number?: string; |
105 | } & { phone_type?: "FAX" | "HOME" | "MOBILE" | "OTHER" | "PAGER" }[]; |
106 | website?: string; |
107 | tax_id?: string; |
108 | additional_notes?: string; |
109 | logo_url?: string; |
110 | }; |
111 | primary_recipients?: { |
112 | billing_info?: { business_name?: string } & { |
113 | name?: { |
114 | prefix?: string; |
115 | given_name?: string; |
116 | surname?: string; |
117 | middle_name?: string; |
118 | suffix?: string; |
119 | alternate_full_name?: string; |
120 | full_name?: string; |
121 | }; |
122 | address?: { |
123 | address_line_1?: string; |
124 | address_line_2?: string; |
125 | address_line_3?: string; |
126 | admin_area_4?: string; |
127 | admin_area_3?: string; |
128 | admin_area_2?: string; |
129 | admin_area_1?: string; |
130 | postal_code?: string; |
131 | country_code: string; |
132 | address_details?: { |
133 | street_number?: string; |
134 | street_name?: string; |
135 | street_type?: string; |
136 | delivery_service?: string; |
137 | building_name?: string; |
138 | sub_building?: string; |
139 | }; |
140 | }; |
141 | } & { |
142 | email_address?: string; |
143 | phones?: { |
144 | country_code: string; |
145 | national_number: string; |
146 | extension_number?: string; |
147 | } & { phone_type?: "FAX" | "HOME" | "MOBILE" | "OTHER" | "PAGER" }[]; |
148 | additional_info?: string; |
149 | language?: string; |
150 | }; |
151 | shipping_info?: { business_name?: string } & { |
152 | name?: { |
153 | prefix?: string; |
154 | given_name?: string; |
155 | surname?: string; |
156 | middle_name?: string; |
157 | suffix?: string; |
158 | alternate_full_name?: string; |
159 | full_name?: string; |
160 | }; |
161 | address?: { |
162 | address_line_1?: string; |
163 | address_line_2?: string; |
164 | address_line_3?: string; |
165 | admin_area_4?: string; |
166 | admin_area_3?: string; |
167 | admin_area_2?: string; |
168 | admin_area_1?: string; |
169 | postal_code?: string; |
170 | country_code: string; |
171 | address_details?: { |
172 | street_number?: string; |
173 | street_name?: string; |
174 | street_type?: string; |
175 | delivery_service?: string; |
176 | building_name?: string; |
177 | sub_building?: string; |
178 | }; |
179 | }; |
180 | }; |
181 | }[]; |
182 | additional_recipients?: string[]; |
183 | items?: { |
184 | id?: string; |
185 | name: string; |
186 | description?: string; |
187 | quantity: string; |
188 | unit_amount: { currency_code: string; value: string }; |
189 | tax?: { |
190 | name: string; |
191 | percent: string; |
192 | amount?: { currency_code: string; value: string }; |
193 | }; |
194 | item_date?: string; |
195 | discount?: { |
196 | percent?: string; |
197 | amount?: { currency_code: string; value: string }; |
198 | }; |
199 | unit_of_measure?: "QUANTITY" | "HOURS" | "AMOUNT"; |
200 | }[]; |
201 | configuration?: { |
202 | tax_calculated_after_discount?: false | true; |
203 | tax_inclusive?: false | true; |
204 | allow_tip?: false | true; |
205 | partial_payment?: { |
206 | allow_partial_payment?: false | true; |
207 | minimum_amount_due?: { currency_code: string; value: string }; |
208 | }; |
209 | }; |
210 | amount?: { |
211 | currency_code?: string; |
212 | value?: string; |
213 | breakdown?: { |
214 | item_total?: { currency_code: string; value: string }; |
215 | discount?: { |
216 | invoice_discount?: { |
217 | percent?: string; |
218 | amount?: { currency_code: string; value: string }; |
219 | }; |
220 | item_discount?: { currency_code: string; value: string }; |
221 | }; |
222 | tax_total?: { currency_code: string; value: string }; |
223 | shipping?: { |
224 | amount?: { currency_code: string; value: string }; |
225 | tax?: { |
226 | name: string; |
227 | percent: string; |
228 | amount?: { currency_code: string; value: string }; |
229 | }; |
230 | }; |
231 | custom?: { |
232 | label: string; |
233 | amount?: { currency_code: string; value: string }; |
234 | }; |
235 | }; |
236 | }; |
237 | due_amount?: { currency_code: string; value: string }; |
238 | }; |
239 | settings?: { |
240 | template_item_settings?: { |
241 | field_name?: |
242 | | "ITEMS_QUANTITY" |
243 | | "ITEMS_DESCRIPTION" |
244 | | "ITEMS_DATE" |
245 | | "ITEMS_DISCOUNT" |
246 | | "ITEMS_TAX"; |
247 | display_preference?: { hidden?: false | true }; |
248 | }[]; |
249 | template_subtotal_settings?: { |
250 | field_name?: "DISCOUNT" | "SHIPPING" | "CUSTOM"; |
251 | display_preference?: { hidden?: false | true }; |
252 | }[]; |
253 | }; |
254 | unit_of_measure?: "QUANTITY" | "HOURS" | "AMOUNT"; |
255 | standard_template?: false | true; |
256 | links?: { |
257 | href: string; |
258 | rel: string; |
259 | method?: |
260 | | "GET" |
261 | | "POST" |
262 | | "PUT" |
263 | | "DELETE" |
264 | | "HEAD" |
265 | | "CONNECT" |
266 | | "OPTIONS" |
267 | | "PATCH"; |
268 | }[]; |
269 | }, |
270 | ) { |
271 | const token = await getToken(auth); |
272 | const url = new URL( |
273 | `https://api-m.paypal.com/v2/invoicing/templates/${template_id}`, |
274 | ); |
275 |
|
276 | const response = await fetch(url, { |
277 | method: "PUT", |
278 | headers: { |
279 | "Content-Type": "application/json", |
280 | Authorization: "Bearer " + token, |
281 | }, |
282 | body: JSON.stringify(body), |
283 | }); |
284 | if (!response.ok) { |
285 | const text = await response.text(); |
286 | throw new Error(`${response.status} ${text}`); |
287 | } |
288 | return await response.json(); |
289 | } |
290 |
|