1 | type Stripe = { |
2 | token: string; |
3 | }; |
4 | |
5 | * Post invoices invoice |
6 | * Draft invoices are fully editable. Once an invoice is finalized, |
7 | monetary values, as well as collection_method, become uneditable. |
8 |
|
9 | If you would like to stop the Stripe Billing engine from automatically finalizing, reattempting payments on, |
10 | sending reminders for, or automatically reconciling invoices, pass |
11 | auto_advance=false. |
12 | */ |
13 | export async function main( |
14 | auth: Stripe, |
15 | invoice: string, |
16 | body: { |
17 | account_tax_ids?: string[] | ""; |
18 | application_fee_amount?: number; |
19 | auto_advance?: boolean; |
20 | automatic_tax?: { |
21 | enabled: boolean; |
22 | liability?: { |
23 | account?: string; |
24 | type: "account" | "self"; |
25 | [k: string]: unknown; |
26 | }; |
27 | [k: string]: unknown; |
28 | }; |
29 | collection_method?: "charge_automatically" | "send_invoice"; |
30 | custom_fields?: |
31 | | { name: string; value: string; [k: string]: unknown }[] |
32 | | ""; |
33 | days_until_due?: number; |
34 | default_payment_method?: string; |
35 | default_source?: string | ""; |
36 | default_tax_rates?: string[] | ""; |
37 | description?: string; |
38 | discounts?: |
39 | | { coupon?: string; discount?: string; [k: string]: unknown }[] |
40 | | ""; |
41 | due_date?: number; |
42 | effective_at?: number | ""; |
43 | expand?: string[]; |
44 | footer?: string; |
45 | issuer?: { |
46 | account?: string; |
47 | type: "account" | "self"; |
48 | [k: string]: unknown; |
49 | }; |
50 | metadata?: { [k: string]: string } | ""; |
51 | number?: string | ""; |
52 | on_behalf_of?: string | ""; |
53 | payment_settings?: { |
54 | default_mandate?: string | ""; |
55 | payment_method_options?: { |
56 | acss_debit?: |
57 | | { |
58 | mandate_options?: { |
59 | transaction_type?: "business" | "personal"; |
60 | [k: string]: unknown; |
61 | }; |
62 | verification_method?: "automatic" | "instant" | "microdeposits"; |
63 | [k: string]: unknown; |
64 | } |
65 | | ""; |
66 | bancontact?: |
67 | | { |
68 | preferred_language?: "de" | "en" | "fr" | "nl"; |
69 | [k: string]: unknown; |
70 | } |
71 | | ""; |
72 | card?: |
73 | | { |
74 | installments?: { |
75 | enabled?: boolean; |
76 | plan?: |
77 | | { |
78 | count: number; |
79 | interval: "month"; |
80 | type: "fixed_count"; |
81 | [k: string]: unknown; |
82 | } |
83 | | ""; |
84 | [k: string]: unknown; |
85 | }; |
86 | request_three_d_secure?: "any" | "automatic" | "challenge"; |
87 | [k: string]: unknown; |
88 | } |
89 | | ""; |
90 | customer_balance?: |
91 | | { |
92 | bank_transfer?: { |
93 | eu_bank_transfer?: { country: string; [k: string]: unknown }; |
94 | type?: string; |
95 | [k: string]: unknown; |
96 | }; |
97 | funding_type?: string; |
98 | [k: string]: unknown; |
99 | } |
100 | | ""; |
101 | konbini?: { [k: string]: unknown } | ""; |
102 | us_bank_account?: |
103 | | { |
104 | financial_connections?: { |
105 | permissions?: ( |
106 | | "balances" |
107 | | "ownership" |
108 | | "payment_method" |
109 | | "transactions" |
110 | )[]; |
111 | prefetch?: ("balances" | "transactions")[]; |
112 | [k: string]: unknown; |
113 | }; |
114 | verification_method?: "automatic" | "instant" | "microdeposits"; |
115 | [k: string]: unknown; |
116 | } |
117 | | ""; |
118 | [k: string]: unknown; |
119 | }; |
120 | payment_method_types?: |
121 | | ( |
122 | | "ach_credit_transfer" |
123 | | "ach_debit" |
124 | | "acss_debit" |
125 | | "au_becs_debit" |
126 | | "bacs_debit" |
127 | | "bancontact" |
128 | | "boleto" |
129 | | "card" |
130 | | "cashapp" |
131 | | "customer_balance" |
132 | | "eps" |
133 | | "fpx" |
134 | | "giropay" |
135 | | "grabpay" |
136 | | "ideal" |
137 | | "konbini" |
138 | | "link" |
139 | | "p24" |
140 | | "paynow" |
141 | | "paypal" |
142 | | "promptpay" |
143 | | "sepa_debit" |
144 | | "sofort" |
145 | | "us_bank_account" |
146 | | "wechat_pay" |
147 | )[] |
148 | | ""; |
149 | [k: string]: unknown; |
150 | }; |
151 | rendering?: { |
152 | amount_tax_display?: "" | "exclude_tax" | "include_inclusive_tax"; |
153 | pdf?: { page_size?: "a4" | "auto" | "letter"; [k: string]: unknown }; |
154 | [k: string]: unknown; |
155 | }; |
156 | shipping_cost?: |
157 | | { |
158 | shipping_rate?: string; |
159 | shipping_rate_data?: { |
160 | delivery_estimate?: { |
161 | maximum?: { |
162 | unit: "business_day" | "day" | "hour" | "month" | "week"; |
163 | value: number; |
164 | [k: string]: unknown; |
165 | }; |
166 | minimum?: { |
167 | unit: "business_day" | "day" | "hour" | "month" | "week"; |
168 | value: number; |
169 | [k: string]: unknown; |
170 | }; |
171 | [k: string]: unknown; |
172 | }; |
173 | display_name: string; |
174 | fixed_amount?: { |
175 | amount: number; |
176 | currency: string; |
177 | currency_options?: { |
178 | [k: string]: { |
179 | amount: number; |
180 | tax_behavior?: "exclusive" | "inclusive" | "unspecified"; |
181 | [k: string]: unknown; |
182 | }; |
183 | }; |
184 | [k: string]: unknown; |
185 | }; |
186 | metadata?: { [k: string]: string }; |
187 | tax_behavior?: "exclusive" | "inclusive" | "unspecified"; |
188 | tax_code?: string; |
189 | type?: "fixed_amount"; |
190 | [k: string]: unknown; |
191 | }; |
192 | [k: string]: unknown; |
193 | } |
194 | | ""; |
195 | shipping_details?: |
196 | | { |
197 | address: { |
198 | city?: string; |
199 | country?: string; |
200 | line1?: string; |
201 | line2?: string; |
202 | postal_code?: string; |
203 | state?: string; |
204 | [k: string]: unknown; |
205 | }; |
206 | name: string; |
207 | phone?: string | ""; |
208 | [k: string]: unknown; |
209 | } |
210 | | ""; |
211 | statement_descriptor?: string; |
212 | transfer_data?: |
213 | | { amount?: number; destination: string; [k: string]: unknown } |
214 | | ""; |
215 | } |
216 | ) { |
217 | const url = new URL(`https://api.stripe.com/v1/invoices/${invoice}`); |
218 |
|
219 | const response = await fetch(url, { |
220 | method: "POST", |
221 | headers: { |
222 | "Content-Type": "application/x-www-form-urlencoded", |
223 | Authorization: "Bearer " + auth.token, |
224 | }, |
225 | body: encodeParams(body), |
226 | }); |
227 | if (!response.ok) { |
228 | const text = await response.text(); |
229 | throw new Error(`${response.status} ${text}`); |
230 | } |
231 | return await response.json(); |
232 | } |
233 |
|
234 | function encodeParams(o: any) { |
235 | function iter(o: any, path: string) { |
236 | if (Array.isArray(o)) { |
237 | o.forEach(function (a) { |
238 | iter(a, path + "[]"); |
239 | }); |
240 | return; |
241 | } |
242 | if (o !== null && typeof o === "object") { |
243 | Object.keys(o).forEach(function (k) { |
244 | iter(o[k], path + "[" + k + "]"); |
245 | }); |
246 | return; |
247 | } |
248 | data.push(path + "=" + o); |
249 | } |
250 | const data: string[] = []; |
251 | Object.keys(o).forEach(function (k) { |
252 | if (o[k] !== undefined) { |
253 | iter(o[k], k); |
254 | } |
255 | }); |
256 | return new URLSearchParams(data.join("&")); |
257 | } |
258 |
|