CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
sagemathinc

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/frontend/client/stripe.ts
Views: 687
1
/*
2
* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
/*
7
stripe payments api via backend hub
8
*/
9
10
import { callback2 } from "@cocalc/util/async-utils";
11
import * as message from "@cocalc/util/message";
12
import { PurchaseInfo } from "@cocalc/util/licenses/purchase/types";
13
import { HubClient } from "./hub";
14
15
export class StripeClient {
16
private call_api: typeof HubClient.prototype.call;
17
18
constructor(call_api) {
19
this.call_api = call_api;
20
}
21
22
private async call(mesg): Promise<any> {
23
return await callback2(this.call_api, {
24
message: mesg,
25
error_event: true,
26
timeout: 15,
27
});
28
}
29
30
// gets custormer info (if any) and stripe public api key
31
// for this user, if they are logged in
32
public async get_customer(): Promise<{
33
stripe_publishable_key?: string;
34
customer: any;
35
}> {
36
const mesg = await this.call(message.stripe_get_customer());
37
if (mesg == null) {
38
// evidently this happened -- see
39
// https://github.com/sagemathinc/cocalc/issues/3711
40
throw Error("mesg must be defined");
41
} else {
42
return {
43
stripe_publishable_key: mesg.stripe_publishable_key,
44
customer: mesg.customer,
45
};
46
}
47
}
48
49
public async create_source(token: string): Promise<any> {
50
return await this.call(message.stripe_create_source({ token }));
51
}
52
53
public async delete_source(card_id: string): Promise<any> {
54
return await this.call(message.stripe_delete_source({ card_id }));
55
}
56
57
public async update_source(card_id: string, info: any): Promise<any> {
58
return await this.call(message.stripe_update_source({ card_id, info }));
59
}
60
61
public async set_default_source(card_id: string): Promise<any> {
62
return await this.call(message.stripe_set_default_source({ card_id }));
63
}
64
65
// gets list of past stripe charges for this account.
66
public async get_charges(opts: {
67
limit?: number; // between 1 and 100 (default: 10)
68
ending_before?: any;
69
starting_after?: any;
70
}): Promise<any> {
71
return (
72
await this.call(
73
message.stripe_get_charges({
74
limit: opts.limit,
75
ending_before: opts.ending_before,
76
starting_after: opts.starting_after,
77
})
78
)
79
).charges;
80
}
81
82
public async create_subscription(opts: {
83
plan: string;
84
quantity?: number;
85
coupon_id?: string;
86
}): Promise<any> {
87
if (opts.quantity == null) {
88
opts.quantity = 1;
89
}
90
return await this.call(message.stripe_create_subscription(opts));
91
}
92
93
public async cancel_subscription(opts: {
94
subscription_id: string;
95
at_period_end?: boolean; // default is *true*
96
}) {
97
if (opts.at_period_end == null) {
98
opts.at_period_end = true;
99
}
100
return await this.call(message.stripe_cancel_subscription(opts));
101
}
102
103
public async update_subscription(opts: {
104
subscription_id: string;
105
quantity?: number; // if given, must be >= number of projects
106
coupon_id?: string;
107
projects?: string[]; // ids of projects that subscription applies to (TOD: what?)
108
plan?: string;
109
}) {
110
return await this.call(message.stripe_update_subscription(opts));
111
}
112
113
// gets list of past stripe charges for this account.
114
public async get_subscriptions(opts: {
115
limit?: number; // between 1 and 100 (default: 10)
116
ending_before?: any; // see https://stripe.com/docs/api/node#list_subscriptions
117
starting_after?: any;
118
}) {
119
return (await this.call(message.stripe_get_subscriptions(opts)))
120
.subscriptions;
121
}
122
123
// Gets the coupon for this account. Returns an error if invalid
124
// https://stripe.com/docs/api#retrieve_coupon
125
public async get_coupon(coupon_id: string) {
126
return (await this.call(message.stripe_get_coupon({ coupon_id }))).coupon;
127
}
128
129
// gets list of invoices for this account.
130
public async get_invoices(opts: {
131
limit?: number; // between 1 and 100 (default: 10)
132
ending_before?: any; // see https://stripe.com/docs/api/node#list_charges
133
starting_after?: any;
134
}) {
135
return (
136
await this.call(
137
message.stripe_get_invoices({
138
limit: opts.limit,
139
ending_before: opts.ending_before,
140
starting_after: opts.starting_after,
141
})
142
)
143
).invoices;
144
}
145
146
public async admin_create_invoice_item(
147
opts:
148
| {
149
account_id: string;
150
email_address?: string;
151
amount?: number; // in US dollars -- if amount/description *not* given, then merely ensures user has stripe account and updats info about them
152
description?: string;
153
}
154
| {
155
account_id?: string;
156
email_address: string;
157
amount?: number;
158
description?: string;
159
}
160
) {
161
return await this.call(message.stripe_admin_create_invoice_item(opts));
162
}
163
164
// Make it so the SMC user with the given email address has a corresponding stripe
165
// identity, even if they have never entered a credit card. May only be used by
166
// admin users.
167
public async admin_create_customer(
168
opts:
169
| { account_id: string; email_address?: string }
170
| { account_id?: string; email_address: string }
171
) {
172
return await this.admin_create_invoice_item(opts);
173
}
174
175
// Purchase a license (technically this may or may not involve "stripe").
176
public async purchase_license(info: PurchaseInfo): Promise<string> {
177
return (await this.call(message.purchase_license({ info }))).resp;
178
}
179
180
}
181
182