1 | type Stripe = { |
2 | token: string; |
3 | }; |
4 | |
5 | * Post subscriptions |
6 | * Creates a new subscription on an existing customer. |
7 | */ |
8 | export async function main( |
9 | auth: Stripe, |
10 | body: { |
11 | add_invoice_items?: { |
12 | price?: string; |
13 | price_data?: { |
14 | currency: string; |
15 | product: string; |
16 | tax_behavior?: "exclusive" | "inclusive" | "unspecified"; |
17 | unit_amount?: number; |
18 | unit_amount_decimal?: string; |
19 | [k: string]: unknown; |
20 | }; |
21 | quantity?: number; |
22 | tax_rates?: string[] | ""; |
23 | [k: string]: unknown; |
24 | }[]; |
25 | application_fee_percent?: number; |
26 | automatic_tax?: { |
27 | enabled: boolean; |
28 | liability?: { |
29 | account?: string; |
30 | type: "account" | "self"; |
31 | [k: string]: unknown; |
32 | }; |
33 | [k: string]: unknown; |
34 | }; |
35 | backdate_start_date?: number; |
36 | billing_cycle_anchor?: number; |
37 | billing_cycle_anchor_config?: { |
38 | day_of_month: number; |
39 | hour?: number; |
40 | minute?: number; |
41 | month?: number; |
42 | second?: number; |
43 | [k: string]: unknown; |
44 | }; |
45 | billing_thresholds?: |
46 | | { |
47 | amount_gte?: number; |
48 | reset_billing_cycle_anchor?: boolean; |
49 | [k: string]: unknown; |
50 | } |
51 | | ""; |
52 | cancel_at?: number; |
53 | cancel_at_period_end?: boolean; |
54 | collection_method?: "charge_automatically" | "send_invoice"; |
55 | coupon?: string; |
56 | currency?: string; |
57 | customer: string; |
58 | days_until_due?: number; |
59 | default_payment_method?: string; |
60 | default_source?: string; |
61 | default_tax_rates?: string[] | ""; |
62 | description?: string; |
63 | expand?: string[]; |
64 | invoice_settings?: { |
65 | account_tax_ids?: string[] | ""; |
66 | issuer?: { |
67 | account?: string; |
68 | type: "account" | "self"; |
69 | [k: string]: unknown; |
70 | }; |
71 | [k: string]: unknown; |
72 | }; |
73 | items?: { |
74 | billing_thresholds?: { usage_gte: number; [k: string]: unknown } | ""; |
75 | metadata?: { [k: string]: string }; |
76 | price?: string; |
77 | price_data?: { |
78 | currency: string; |
79 | product: string; |
80 | recurring: { |
81 | interval: "day" | "month" | "week" | "year"; |
82 | interval_count?: number; |
83 | [k: string]: unknown; |
84 | }; |
85 | tax_behavior?: "exclusive" | "inclusive" | "unspecified"; |
86 | unit_amount?: number; |
87 | unit_amount_decimal?: string; |
88 | [k: string]: unknown; |
89 | }; |
90 | quantity?: number; |
91 | tax_rates?: string[] | ""; |
92 | [k: string]: unknown; |
93 | }[]; |
94 | metadata?: { [k: string]: string } | ""; |
95 | off_session?: boolean; |
96 | on_behalf_of?: string | ""; |
97 | payment_behavior?: |
98 | | "allow_incomplete" |
99 | | "default_incomplete" |
100 | | "error_if_incomplete" |
101 | | "pending_if_incomplete"; |
102 | payment_settings?: { |
103 | payment_method_options?: { |
104 | acss_debit?: |
105 | | { |
106 | mandate_options?: { |
107 | transaction_type?: "business" | "personal"; |
108 | [k: string]: unknown; |
109 | }; |
110 | verification_method?: "automatic" | "instant" | "microdeposits"; |
111 | [k: string]: unknown; |
112 | } |
113 | | ""; |
114 | bancontact?: |
115 | | { |
116 | preferred_language?: "de" | "en" | "fr" | "nl"; |
117 | [k: string]: unknown; |
118 | } |
119 | | ""; |
120 | card?: |
121 | | { |
122 | mandate_options?: { |
123 | amount?: number; |
124 | amount_type?: "fixed" | "maximum"; |
125 | description?: string; |
126 | [k: string]: unknown; |
127 | }; |
128 | network?: |
129 | | "amex" |
130 | | "cartes_bancaires" |
131 | | "diners" |
132 | | "discover" |
133 | | "eftpos_au" |
134 | | "interac" |
135 | | "jcb" |
136 | | "mastercard" |
137 | | "unionpay" |
138 | | "unknown" |
139 | | "visa"; |
140 | request_three_d_secure?: "any" | "automatic" | "challenge"; |
141 | [k: string]: unknown; |
142 | } |
143 | | ""; |
144 | customer_balance?: |
145 | | { |
146 | bank_transfer?: { |
147 | eu_bank_transfer?: { country: string; [k: string]: unknown }; |
148 | type?: string; |
149 | [k: string]: unknown; |
150 | }; |
151 | funding_type?: string; |
152 | [k: string]: unknown; |
153 | } |
154 | | ""; |
155 | konbini?: { [k: string]: unknown } | ""; |
156 | us_bank_account?: |
157 | | { |
158 | financial_connections?: { |
159 | permissions?: ( |
160 | | "balances" |
161 | | "ownership" |
162 | | "payment_method" |
163 | | "transactions" |
164 | )[]; |
165 | prefetch?: ("balances" | "transactions")[]; |
166 | [k: string]: unknown; |
167 | }; |
168 | verification_method?: "automatic" | "instant" | "microdeposits"; |
169 | [k: string]: unknown; |
170 | } |
171 | | ""; |
172 | [k: string]: unknown; |
173 | }; |
174 | payment_method_types?: |
175 | | ( |
176 | | "ach_credit_transfer" |
177 | | "ach_debit" |
178 | | "acss_debit" |
179 | | "au_becs_debit" |
180 | | "bacs_debit" |
181 | | "bancontact" |
182 | | "boleto" |
183 | | "card" |
184 | | "cashapp" |
185 | | "customer_balance" |
186 | | "eps" |
187 | | "fpx" |
188 | | "giropay" |
189 | | "grabpay" |
190 | | "ideal" |
191 | | "konbini" |
192 | | "link" |
193 | | "p24" |
194 | | "paynow" |
195 | | "paypal" |
196 | | "promptpay" |
197 | | "sepa_debit" |
198 | | "sofort" |
199 | | "us_bank_account" |
200 | | "wechat_pay" |
201 | )[] |
202 | | ""; |
203 | save_default_payment_method?: "off" | "on_subscription"; |
204 | [k: string]: unknown; |
205 | }; |
206 | pending_invoice_item_interval?: |
207 | | { |
208 | interval: "day" | "month" | "week" | "year"; |
209 | interval_count?: number; |
210 | [k: string]: unknown; |
211 | } |
212 | | ""; |
213 | promotion_code?: string; |
214 | proration_behavior?: "always_invoice" | "create_prorations" | "none"; |
215 | transfer_data?: { |
216 | amount_percent?: number; |
217 | destination: string; |
218 | [k: string]: unknown; |
219 | }; |
220 | trial_end?: "now" | number; |
221 | trial_from_plan?: boolean; |
222 | trial_period_days?: number; |
223 | trial_settings?: { |
224 | end_behavior: { |
225 | missing_payment_method: "cancel" | "create_invoice" | "pause"; |
226 | [k: string]: unknown; |
227 | }; |
228 | [k: string]: unknown; |
229 | }; |
230 | } |
231 | ) { |
232 | const url = new URL(`https://api.stripe.com/v1/subscriptions`); |
233 |
|
234 | const response = await fetch(url, { |
235 | method: "POST", |
236 | headers: { |
237 | "Content-Type": "application/x-www-form-urlencoded", |
238 | Authorization: "Bearer " + auth.token, |
239 | }, |
240 | body: encodeParams(body), |
241 | }); |
242 | if (!response.ok) { |
243 | const text = await response.text(); |
244 | throw new Error(`${response.status} ${text}`); |
245 | } |
246 | return await response.json(); |
247 | } |
248 |
|
249 | function encodeParams(o: any) { |
250 | function iter(o: any, path: string) { |
251 | if (Array.isArray(o)) { |
252 | o.forEach(function (a) { |
253 | iter(a, path + "[]"); |
254 | }); |
255 | return; |
256 | } |
257 | if (o !== null && typeof o === "object") { |
258 | Object.keys(o).forEach(function (k) { |
259 | iter(o[k], path + "[" + k + "]"); |
260 | }); |
261 | return; |
262 | } |
263 | data.push(path + "=" + o); |
264 | } |
265 | const data: string[] = []; |
266 | Object.keys(o).forEach(function (k) { |
267 | if (o[k] !== undefined) { |
268 | iter(o[k], k); |
269 | } |
270 | }); |
271 | return new URLSearchParams(data.join("&")); |
272 | } |
273 |
|