0

Cancel Subscription

by
Published Oct 30, 2023

Cancel a subscription now, or at the end of the current period when `at_period_end` is set (it stays active until then and can be resumed by updating `cancel_at_period_end`). `invoice_now` and `prorate` apply to immediate cancellation only.

Script stripe Verified

The script

Submitted by hugo989 Typescript (fetch-only)
Verified 2 hours ago
1
//native
2

3
/**
4
 * Cancel Subscription
5
 * Cancel a subscription now, or at the end of the current period when `at_period_end` is set (it stays active until then and can be resumed by updating `cancel_at_period_end`). `invoice_now` and `prorate` apply to immediate cancellation only.
6
 */
7
export async function main(
8
  auth: RT.Stripe,
9
  subscription_id: string,
10
  at_period_end: boolean | undefined,
11
  invoice_now: boolean | undefined,
12
  prorate: boolean | undefined,
13
  comment: string | undefined
14
) {
15
  const url = new URL(
16
    `https://api.stripe.com/v1/subscriptions/${subscription_id}`
17
  )
18
  const headers = {
19
    Authorization: `Bearer ${auth.token}`,
20
    Accept: "application/json",
21
    "Stripe-Version": "2025-03-31.basil",
22
  }
23

24
  let response: Response
25
  if (at_period_end) {
26
    response = await fetch(url, {
27
      method: "POST",
28
      headers: {
29
        ...headers,
30
        "Content-Type": "application/x-www-form-urlencoded",
31
      },
32
      body: toForm({
33
        cancel_at_period_end: true,
34
        cancellation_details: { comment },
35
      }),
36
    })
37
  } else {
38
    url.search = toForm({
39
      invoice_now: invoice_now || undefined,
40
      prorate: prorate || undefined,
41
      cancellation_details: { comment },
42
    }).toString()
43
    response = await fetch(url, { method: "DELETE", headers })
44
  }
45

46
  if (!response.ok) {
47
    throw new Error(`${response.status} ${await response.text()}`)
48
  }
49

50
  return await response.json()
51
}
52

53
// Stripe takes form-encoded params with bracketed nesting: metadata[key]=v, items[0][price]=p
54
function toForm(
55
  params: { [key: string]: any },
56
  prefix = "",
57
  out = new URLSearchParams()
58
) {
59
  for (const [key, value] of Object.entries(params)) {
60
    if (value == null || value === "") continue
61
    const name = prefix ? `${prefix}[${key}]` : key
62
    if (typeof value === "object") toForm(value, name, out)
63
    else out.append(name, String(value))
64
  }
65
  return out
66
}
67

Other submissions
  • Submitted by hugo697 Typescript (fetch-only)
    Created 528 days ago
    1
    type Stripe = {
    2
      token: string;
    3
    };
    4
    /**
    5
     * Delete subscriptions subscription exposed id
    6
     * Cancels a customer’s subscription immediately.
    7
     */
    8
    export async function main(
    9
      auth: Stripe,
    10
      subscription_exposed_id: string,
    11
      body: {
    12
        cancellation_details?: {
    13
          comment?: string | "";
    14
          feedback?:
    15
            | ""
    16
            | "customer_service"
    17
            | "low_quality"
    18
            | "missing_features"
    19
            | "other"
    20
            | "switched_service"
    21
            | "too_complex"
    22
            | "too_expensive"
    23
            | "unused";
    24
          [k: string]: unknown;
    25
        };
    26
        expand?: string[];
    27
        invoice_now?: boolean;
    28
        prorate?: boolean;
    29
      }
    30
    ) {
    31
      const url = new URL(
    32
        `https://api.stripe.com/v1/subscriptions/${subscription_exposed_id}`
    33
      );
    34
    
    
    35
      const response = await fetch(url, {
    36
        method: "DELETE",
    37
        headers: {
    38
          "Content-Type": "application/x-www-form-urlencoded",
    39
          Authorization: "Bearer " + auth.token,
    40
        },
    41
        body: encodeParams(body),
    42
      });
    43
      if (!response.ok) {
    44
        const text = await response.text();
    45
        throw new Error(`${response.status} ${text}`);
    46
      }
    47
      return await response.json();
    48
    }
    49
    
    
    50
    function encodeParams(o: any) {
    51
      function iter(o: any, path: string) {
    52
        if (Array.isArray(o)) {
    53
          o.forEach(function (a) {
    54
            iter(a, path + "[]");
    55
          });
    56
          return;
    57
        }
    58
        if (o !== null && typeof o === "object") {
    59
          Object.keys(o).forEach(function (k) {
    60
            iter(o[k], path + "[" + k + "]");
    61
          });
    62
          return;
    63
        }
    64
        data.push(path + "=" + o);
    65
      }
    66
      const data: string[] = [];
    67
      Object.keys(o).forEach(function (k) {
    68
        if (o[k] !== undefined) {
    69
          iter(o[k], k);
    70
        }
    71
      });
    72
      return new URLSearchParams(data.join("&"));
    73
    }
    74