mirror of
https://github.com/zulip/zulip.git
synced 2025-10-24 16:43:57 +00:00
Compare commits
1277 Commits
buddy-list
...
8.0-beta2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
555cdd0a57 | ||
|
|
4ad03804cf | ||
|
|
1d515a57cd | ||
|
|
88fb3b735a | ||
|
|
88fe0a7561 | ||
|
|
cae11a60b6 | ||
|
|
cd65849f7e | ||
|
|
6d7037e867 | ||
|
|
fba49ca33d | ||
|
|
2e8aba2e83 | ||
|
|
ccaef86e20 | ||
|
|
7587ee2289 | ||
|
|
bd539d7d12 | ||
|
|
ed02b568e5 | ||
|
|
857630707a | ||
|
|
b0b6716892 | ||
|
|
7e1f212366 | ||
|
|
20a1037b92 | ||
|
|
4bf018f09f | ||
|
|
689aa12fce | ||
|
|
89a28f6577 | ||
|
|
fd7b61065d | ||
|
|
c61275cab2 | ||
|
|
e829e52c56 | ||
|
|
f60312b2da | ||
|
|
2b37a35f71 | ||
|
|
55b26da82b | ||
|
|
c1988a14a7 | ||
|
|
b09f3a2da1 | ||
|
|
cf68f8ae24 | ||
|
|
ab1a8a0151 | ||
|
|
449714245e | ||
|
|
89c2740342 | ||
|
|
59dc5d1f53 | ||
|
|
2e71ec78e3 | ||
|
|
c7c0b871c5 | ||
|
|
9d0375cac1 | ||
|
|
82191872a4 | ||
|
|
4df1692294 | ||
|
|
5e1d94f996 | ||
|
|
d0317a1792 | ||
|
|
c741c527d7 | ||
|
|
2da1bfcbd0 | ||
|
|
3bcfb9c005 | ||
|
|
2916a601b3 | ||
|
|
b82ea179ac | ||
|
|
dd8a33f03e | ||
|
|
4af00f61a8 | ||
|
|
b032b2a4da | ||
|
|
886a86866d | ||
|
|
c1daabd3c0 | ||
|
|
41ceae9c31 | ||
|
|
5c1a5a816f | ||
|
|
4fe02be825 | ||
|
|
b9af6c7962 | ||
|
|
d763fae9d0 | ||
|
|
6f93ab72c0 | ||
|
|
629492e63b | ||
|
|
1100d3be51 | ||
|
|
688c011a80 | ||
|
|
eb92b31e1d | ||
|
|
23d712391e | ||
|
|
64517a7ad3 | ||
|
|
b4e4ca14d5 | ||
|
|
8e617f5df8 | ||
|
|
df23701475 | ||
|
|
a8fd350630 | ||
|
|
e3878cf64a | ||
|
|
be31f7a5e6 | ||
|
|
10aad0a9f3 | ||
|
|
a2733c7bc3 | ||
|
|
27ca8b0360 | ||
|
|
a9e0871f59 | ||
|
|
b8fee4f176 | ||
|
|
8b128f4b59 | ||
|
|
069925b9a7 | ||
|
|
e5f2211397 | ||
|
|
1f417b6a43 | ||
|
|
48bbf1cc6c | ||
|
|
ca9b1060b7 | ||
|
|
ada73eb6e0 | ||
|
|
581d4ce3c5 | ||
|
|
fd97d87491 | ||
|
|
81a04b5bd8 | ||
|
|
144b2a9988 | ||
|
|
6f3e1cf653 | ||
|
|
7186f75b58 | ||
|
|
2684c21cca | ||
|
|
c2a76ccb3e | ||
|
|
f1ffb1f56e | ||
|
|
eb57b4c4f7 | ||
|
|
9e90afc504 | ||
|
|
da5e1146f5 | ||
|
|
c800951966 | ||
|
|
9c66b4a660 | ||
|
|
851f69c3ba | ||
|
|
c9d2ac1e1b | ||
|
|
d30b00d9f2 | ||
|
|
5792895c10 | ||
|
|
d6e30ee3e8 | ||
|
|
e525160021 | ||
|
|
d365c8739d | ||
|
|
ac8d5a5f0b | ||
|
|
82db8e7ac5 | ||
|
|
0abcfb7b72 | ||
|
|
93f53fa7fa | ||
|
|
fa6b1764cd | ||
|
|
3dc886a1cd | ||
|
|
f78db57c6b | ||
|
|
7d62471d0b | ||
|
|
a0ea14bdb1 | ||
|
|
1e6d9d28f8 | ||
|
|
423aebf98e | ||
|
|
18ec4cd198 | ||
|
|
50b7c5ad85 | ||
|
|
a45438619d | ||
|
|
49470af46e | ||
|
|
b2b36ff37b | ||
|
|
d1b60f322c | ||
|
|
9fd5ed27fe | ||
|
|
ce56e19d1c | ||
|
|
ccd60bc7e2 | ||
|
|
34704daee7 | ||
|
|
367afbb5be | ||
|
|
198568522a | ||
|
|
22d59f1132 | ||
|
|
72aa4b256d | ||
|
|
ac441b77fa | ||
|
|
7e12674e8c | ||
|
|
cf16ddd4d6 | ||
|
|
a1fa969693 | ||
|
|
3ff14dc018 | ||
|
|
ec86114330 | ||
|
|
121e5ad3dc | ||
|
|
e44f3d448d | ||
|
|
5d3eafcdd4 | ||
|
|
dca7e654ca | ||
|
|
67d4e8456d | ||
|
|
01c3c4dd4b | ||
|
|
f86becfc94 | ||
|
|
0400614a48 | ||
|
|
abdfdeffe4 | ||
|
|
bba02044f5 | ||
|
|
b4b9f29e21 | ||
|
|
91ddcd4e1d | ||
|
|
9bb90b7358 | ||
|
|
f355b76024 | ||
|
|
9f98e572f1 | ||
|
|
8f74d4529e | ||
|
|
c2dec1e152 | ||
|
|
bf4fdbff12 | ||
|
|
ed9b0d330d | ||
|
|
40621478cb | ||
|
|
bd99e37910 | ||
|
|
111df40e05 | ||
|
|
c5bfdaaeeb | ||
|
|
3d25c7372a | ||
|
|
12dec4234e | ||
|
|
76d9aff5a6 | ||
|
|
c49fc8c6fe | ||
|
|
0f163cedbc | ||
|
|
579bdc18f8 | ||
|
|
4989221b9e | ||
|
|
8eccb3af20 | ||
|
|
875622fe57 | ||
|
|
0109658238 | ||
|
|
9ab5f65cc4 | ||
|
|
134a05ff5e | ||
|
|
9594e635cd | ||
|
|
2639408171 | ||
|
|
386cef1b7e | ||
|
|
75ceba6600 | ||
|
|
55fd312379 | ||
|
|
cd94837d6b | ||
|
|
4695661ebd | ||
|
|
2364060a7c | ||
|
|
fef833008f | ||
|
|
bd1d0e6b46 | ||
|
|
a3495d4103 | ||
|
|
57c6d0323b | ||
|
|
abf7b9225f | ||
|
|
2da3bd2813 | ||
|
|
ce6dc40a42 | ||
|
|
d67717c0d7 | ||
|
|
0fb89e41f6 | ||
|
|
99f4f914e2 | ||
|
|
2c331f0664 | ||
|
|
30910a3403 | ||
|
|
8376728218 | ||
|
|
380ff91c0e | ||
|
|
8d76231dda | ||
|
|
60a4300db9 | ||
|
|
e1fab4a55a | ||
|
|
ca57d360e6 | ||
|
|
396e995502 | ||
|
|
202d00ebc6 | ||
|
|
a018f2611b | ||
|
|
2165486c88 | ||
|
|
825986ac3a | ||
|
|
00b7424d11 | ||
|
|
21e64887f1 | ||
|
|
bbacee7fe9 | ||
|
|
d29d132e8a | ||
|
|
19ac558d5f | ||
|
|
c94c194ea7 | ||
|
|
25899b1f7e | ||
|
|
1987894a2d | ||
|
|
7cad1f80be | ||
|
|
3d181a8ee1 | ||
|
|
17d25284a2 | ||
|
|
d43244313d | ||
|
|
a3af0250a0 | ||
|
|
c4ec18bc61 | ||
|
|
a97cf5d107 | ||
|
|
381670d2b6 | ||
|
|
34fd68c6b2 | ||
|
|
7d217f2ede | ||
|
|
bbfcb2dcb3 | ||
|
|
83bd9955e3 | ||
|
|
dde3d72100 | ||
|
|
df379b5e86 | ||
|
|
ac8af3d6de | ||
|
|
62bfc20ebc | ||
|
|
32a5c422e9 | ||
|
|
777398fc82 | ||
|
|
ec36fc5605 | ||
|
|
6b64929523 | ||
|
|
ffb9261eaf | ||
|
|
f1f41ab234 | ||
|
|
1062b64149 | ||
|
|
6b94b1183f | ||
|
|
8d5573b395 | ||
|
|
b8f364a345 | ||
|
|
1a60697bd5 | ||
|
|
9f1f292462 | ||
|
|
a15499fb98 | ||
|
|
860e4f6060 | ||
|
|
ec7fd94782 | ||
|
|
f5a96cba05 | ||
|
|
30f7d5e8df | ||
|
|
fec155ea9c | ||
|
|
0d3c68cefb | ||
|
|
74ef619412 | ||
|
|
f99214e866 | ||
|
|
f381fb1afd | ||
|
|
b8c0265d3a | ||
|
|
027df67fdc | ||
|
|
5bae7e5a33 | ||
|
|
906e667a70 | ||
|
|
46dab1beb9 | ||
|
|
ea725aaaf3 | ||
|
|
d079a13760 | ||
|
|
771f8a3542 | ||
|
|
24d6ae83c2 | ||
|
|
578f9fb77e | ||
|
|
6c3fbcc383 | ||
|
|
965869d3f8 | ||
|
|
3697df1971 | ||
|
|
244b150920 | ||
|
|
731799b726 | ||
|
|
2c7afa19ba | ||
|
|
cfb62e7ffa | ||
|
|
ca3569165a | ||
|
|
34730203b3 | ||
|
|
8d9a7679bc | ||
|
|
49908ba166 | ||
|
|
044cb820f8 | ||
|
|
8165f718d6 | ||
|
|
750f5c07b7 | ||
|
|
5e721f4605 | ||
|
|
bcc58edfda | ||
|
|
d631c76747 | ||
|
|
39b0628f09 | ||
|
|
937abb8ba2 | ||
|
|
223b626256 | ||
|
|
3853fa875a | ||
|
|
e5d71fe5ac | ||
|
|
133291ec2d | ||
|
|
ba3279e959 | ||
|
|
cfd61669e0 | ||
|
|
6c5b419267 | ||
|
|
f5ab9419d2 | ||
|
|
9f8fe7989a | ||
|
|
9d3ef7f589 | ||
|
|
8a7916f21a | ||
|
|
250b52e3dc | ||
|
|
04bb60a05e | ||
|
|
8b55d60f9e | ||
|
|
c23339f295 | ||
|
|
ebee57813c | ||
|
|
acbe843b09 | ||
|
|
2ea37a54a6 | ||
|
|
95b39bc8bf | ||
|
|
28d736d63b | ||
|
|
14b1539647 | ||
|
|
35ddb994e9 | ||
|
|
2f1ea2fe4e | ||
|
|
68ccb022ca | ||
|
|
44fa30e481 | ||
|
|
db753f7f90 | ||
|
|
e09761c0f9 | ||
|
|
c7e2306380 | ||
|
|
e2485b7ee8 | ||
|
|
c01e9b8071 | ||
|
|
14bb8708c6 | ||
|
|
885cb8dab9 | ||
|
|
31cc47cbd7 | ||
|
|
15b3ad7466 | ||
|
|
ab3650343f | ||
|
|
b676df0efe | ||
|
|
bd6886929a | ||
|
|
43d0965555 | ||
|
|
f020f9eee0 | ||
|
|
6696a47d3d | ||
|
|
78d767c1ee | ||
|
|
1c88cc481c | ||
|
|
7817e358f4 | ||
|
|
6d4f852dc4 | ||
|
|
78d4232fc4 | ||
|
|
2811f2fe0f | ||
|
|
f1a5fffae9 | ||
|
|
a8612ee9bc | ||
|
|
4d590f1f93 | ||
|
|
201a2bb9c8 | ||
|
|
00f4f8cb04 | ||
|
|
1a063986e3 | ||
|
|
cd45b6f6f8 | ||
|
|
9935f002ec | ||
|
|
f22ccd3125 | ||
|
|
7d83508235 | ||
|
|
c651c4f668 | ||
|
|
c3adfa2679 | ||
|
|
d85dd6bf2b | ||
|
|
b53836de03 | ||
|
|
dc0b8bcb6b | ||
|
|
a7c40748fd | ||
|
|
2d1b217441 | ||
|
|
45df5750ae | ||
|
|
5eabd51702 | ||
|
|
fbd8ed1425 | ||
|
|
f6c7eaf1e5 | ||
|
|
6aa911a9b2 | ||
|
|
895d76f6f0 | ||
|
|
271faaaa06 | ||
|
|
ec44722252 | ||
|
|
8a1630ee42 | ||
|
|
ff368e3240 | ||
|
|
a59245e932 | ||
|
|
7e7af6266d | ||
|
|
f942bbd70f | ||
|
|
785444b2b8 | ||
|
|
36532e9180 | ||
|
|
5835ef44fe | ||
|
|
c457ef2a07 | ||
|
|
69f6d3dcb1 | ||
|
|
2218e667a6 | ||
|
|
4250e9c1c9 | ||
|
|
38eaa4b958 | ||
|
|
1d685bd198 | ||
|
|
6d66248d3d | ||
|
|
8d992405a6 | ||
|
|
6621de6f07 | ||
|
|
5135acd9e3 | ||
|
|
4fb564026d | ||
|
|
97d33a4363 | ||
|
|
5d25cab42b | ||
|
|
0679bc044a | ||
|
|
42edb4416a | ||
|
|
544482eefb | ||
|
|
134e3bfa68 | ||
|
|
44ac99b8fc | ||
|
|
3d6863b5b9 | ||
|
|
ec7245d4e1 | ||
|
|
4987600edc | ||
|
|
7f33d6f0ea | ||
|
|
c9b0602320 | ||
|
|
a67dd6dc1f | ||
|
|
780d60a9ee | ||
|
|
0e4dfa04b3 | ||
|
|
875b7f1377 | ||
|
|
1efc6efd23 | ||
|
|
871054bd1e | ||
|
|
5eb86f3fbb | ||
|
|
056dde8618 | ||
|
|
94cf3b57a3 | ||
|
|
5bfe45b244 | ||
|
|
c5b4b452c1 | ||
|
|
6fb2e28cd2 | ||
|
|
abbf511322 | ||
|
|
854d2820d5 | ||
|
|
8529d86fc6 | ||
|
|
6f796e0cbd | ||
|
|
dbaef860bf | ||
|
|
4f8cc13417 | ||
|
|
b0db397ec6 | ||
|
|
29a09ca793 | ||
|
|
c9f33344e2 | ||
|
|
eb36256d7a | ||
|
|
52f8f56286 | ||
|
|
a6498ad666 | ||
|
|
9e4cda6ecc | ||
|
|
93aa5747d3 | ||
|
|
82895ff535 | ||
|
|
5d49e54d33 | ||
|
|
6b70be38b3 | ||
|
|
b35ea18829 | ||
|
|
8500eae87e | ||
|
|
42c0e2ca3e | ||
|
|
0888608fcc | ||
|
|
e949fb47ff | ||
|
|
c822e953be | ||
|
|
a2c1a2f4bb | ||
|
|
d0c0b11fbf | ||
|
|
e9bbb67035 | ||
|
|
9889dc38fe | ||
|
|
bb7b0b6731 | ||
|
|
222077804b | ||
|
|
0286f10816 | ||
|
|
25cf0f71a3 | ||
|
|
953f0f436e | ||
|
|
b32950d790 | ||
|
|
569c364392 | ||
|
|
9b1bdfefcd | ||
|
|
3b9bb7b2d2 | ||
|
|
7fad8f1f54 | ||
|
|
ea9e2ece49 | ||
|
|
5a198c639e | ||
|
|
8370268f89 | ||
|
|
04a6696e33 | ||
|
|
9c7453c11e | ||
|
|
bc2f1ab68c | ||
|
|
728737ef0e | ||
|
|
f84857959c | ||
|
|
d8b3c5581c | ||
|
|
7f96bed17b | ||
|
|
867ca61e86 | ||
|
|
8d485726e4 | ||
|
|
a39cb2bda3 | ||
|
|
d05315b051 | ||
|
|
e493d998ff | ||
|
|
05f2ad5299 | ||
|
|
4d60c3a96c | ||
|
|
5c9a10da31 | ||
|
|
cab0215f3f | ||
|
|
7540e70cc8 | ||
|
|
1df8e00d7c | ||
|
|
2c34dcf7dc | ||
|
|
4eea4d4717 | ||
|
|
08eb971523 | ||
|
|
fc83fc8017 | ||
|
|
2b0476f5d0 | ||
|
|
0e575a491f | ||
|
|
7b71ea3314 | ||
|
|
ebb02bad8f | ||
|
|
610338d192 | ||
|
|
5d6b635efe | ||
|
|
408a273ba0 | ||
|
|
91cf7ca36f | ||
|
|
af3956e1a9 | ||
|
|
7997af675b | ||
|
|
47cdffb5fb | ||
|
|
7834748dd7 | ||
|
|
c4b619af15 | ||
|
|
329370305f | ||
|
|
a01618d633 | ||
|
|
1691205306 | ||
|
|
e43b51b01e | ||
|
|
2795f11e3f | ||
|
|
405c28252a | ||
|
|
ba11d0fe5d | ||
|
|
5277ebb268 | ||
|
|
d8f8152f9b | ||
|
|
d999d18476 | ||
|
|
cd7893b1bf | ||
|
|
fd57a9033b | ||
|
|
63618e93f0 | ||
|
|
9b1a495e2c | ||
|
|
4ef6b7cc44 | ||
|
|
b71c5746ab | ||
|
|
7db15176f3 | ||
|
|
2765c63f56 | ||
|
|
d8cf12eaaa | ||
|
|
44d8dc66d2 | ||
|
|
78a75ab28c | ||
|
|
3cba6c4303 | ||
|
|
20fc71dd87 | ||
|
|
3c5ea3895f | ||
|
|
a376954a7a | ||
|
|
a6fa875c23 | ||
|
|
7da68259a6 | ||
|
|
d5d1540118 | ||
|
|
81a5977a6e | ||
|
|
26168728ca | ||
|
|
9180819a9e | ||
|
|
355114c976 | ||
|
|
550fb3022b | ||
|
|
5ece914377 | ||
|
|
4fc547cfdc | ||
|
|
2968eb2b04 | ||
|
|
db0476622a | ||
|
|
7bdafed635 | ||
|
|
c5ac75ce60 | ||
|
|
3b5bbbc5ee | ||
|
|
9b958b2634 | ||
|
|
a2da85631c | ||
|
|
db99b3f7fe | ||
|
|
e7dffc7cbe | ||
|
|
4c04675965 | ||
|
|
f9d2ab8bf3 | ||
|
|
9b03f0c1c8 | ||
|
|
311f72dd56 | ||
|
|
9191f1a7eb | ||
|
|
def4cf7f93 | ||
|
|
db6246fcc7 | ||
|
|
929d34ccd7 | ||
|
|
4416f2002b | ||
|
|
07bd1f28d1 | ||
|
|
3eb5b20c41 | ||
|
|
32c730e530 | ||
|
|
737de6d4cd | ||
|
|
037eaa07e2 | ||
|
|
f7990ad175 | ||
|
|
6ecfbd2ae8 | ||
|
|
b68cb5b049 | ||
|
|
e158877365 | ||
|
|
9d3a606bfb | ||
|
|
6cdf3d638b | ||
|
|
06c2b89525 | ||
|
|
33e335dbd1 | ||
|
|
ff9c15ea83 | ||
|
|
61fc838179 | ||
|
|
82c08dd153 | ||
|
|
0f132cef4d | ||
|
|
39fb1a0f70 | ||
|
|
8c8dbb3d66 | ||
|
|
319cfc7d7f | ||
|
|
98b68d7034 | ||
|
|
02d5740f0f | ||
|
|
e276812e42 | ||
|
|
6f2d4f1af2 | ||
|
|
2f91179c1e | ||
|
|
276ceb46e2 | ||
|
|
150c64ddd0 | ||
|
|
f4cbb494ac | ||
|
|
82960d9bc2 | ||
|
|
f9884af114 | ||
|
|
451ddf4c84 | ||
|
|
590d43f475 | ||
|
|
b86654d10f | ||
|
|
5f48abd57a | ||
|
|
4fc639cead | ||
|
|
4e577119b4 | ||
|
|
e8fed998ce | ||
|
|
28a49be161 | ||
|
|
fcd0783202 | ||
|
|
de95c0eb42 | ||
|
|
cf038eeba1 | ||
|
|
78440033dc | ||
|
|
06ebc39e04 | ||
|
|
8bd92fe801 | ||
|
|
a3f5332844 | ||
|
|
cc6ab527b4 | ||
|
|
0ef78c793e | ||
|
|
15d92225fd | ||
|
|
06fd0c9c4b | ||
|
|
9788e7514f | ||
|
|
585ed6c569 | ||
|
|
fa699032ca | ||
|
|
b35a792623 | ||
|
|
1f8d3fc48f | ||
|
|
482b5d8871 | ||
|
|
fe1a40279c | ||
|
|
22c333d135 | ||
|
|
d43a60eb9d | ||
|
|
30891bfc54 | ||
|
|
9f6d340536 | ||
|
|
6397df8b5b | ||
|
|
adc11e5ba2 | ||
|
|
d6a2bbc2ef | ||
|
|
72d46c71fb | ||
|
|
a96619639c | ||
|
|
6c4af3478f | ||
|
|
603aa3db01 | ||
|
|
7de061cf10 | ||
|
|
f8b0e16ff2 | ||
|
|
1b17626327 | ||
|
|
29f77bfd31 | ||
|
|
20cae359d1 | ||
|
|
3615fa4745 | ||
|
|
fce35fc53b | ||
|
|
9c5cfe83ba | ||
|
|
6f3b25d749 | ||
|
|
9fe1e38f98 | ||
|
|
79d1a1850c | ||
|
|
f526b7ba58 | ||
|
|
ede73fc2c6 | ||
|
|
354330d81b | ||
|
|
c79d116f8c | ||
|
|
2f935290f6 | ||
|
|
860f94e599 | ||
|
|
b167eeff08 | ||
|
|
a00e687d02 | ||
|
|
1f1f1b913b | ||
|
|
39bfab0ec4 | ||
|
|
30f0005799 | ||
|
|
2a65183991 | ||
|
|
3cfcd0efee | ||
|
|
caf2b7da26 | ||
|
|
6ad9217fbf | ||
|
|
6040ffb94b | ||
|
|
e3abd57dce | ||
|
|
053f30ca25 | ||
|
|
4844ef9810 | ||
|
|
ace14e5a7d | ||
|
|
f006be0cdf | ||
|
|
1089e13529 | ||
|
|
5659cc1b97 | ||
|
|
b74f6afeb1 | ||
|
|
8d633cc368 | ||
|
|
0c159c5f47 | ||
|
|
73152671e3 | ||
|
|
49388d5d3d | ||
|
|
31a731469d | ||
|
|
a2e6d6c7c4 | ||
|
|
189718dc64 | ||
|
|
c90d00faea | ||
|
|
28bc2b9bf9 | ||
|
|
26252fb821 | ||
|
|
fc92636bea | ||
|
|
505a591179 | ||
|
|
f107cf654f | ||
|
|
c55eaf2bec | ||
|
|
258c20564d | ||
|
|
95f5d8bdb8 | ||
|
|
07d29126fd | ||
|
|
003b29ba14 | ||
|
|
74d8a050e4 | ||
|
|
9edee65ea0 | ||
|
|
5422dd3661 | ||
|
|
ff19dda71c | ||
|
|
2acf3cbfa4 | ||
|
|
51b39cb682 | ||
|
|
efa423395f | ||
|
|
df9c1e085d | ||
|
|
d5306334d5 | ||
|
|
a872dbb260 | ||
|
|
1e7b4ae160 | ||
|
|
de767cc9ad | ||
|
|
861ac92747 | ||
|
|
1e4f938d82 | ||
|
|
44d0e5e23b | ||
|
|
dca032dd75 | ||
|
|
2c76ef9a73 | ||
|
|
59d56c5615 | ||
|
|
3958743b33 | ||
|
|
1ec0d5bd9d | ||
|
|
2149cd236f | ||
|
|
8187d6b963 | ||
|
|
8695ffba49 | ||
|
|
c79f667116 | ||
|
|
b9202ee1db | ||
|
|
bcb7c0a65a | ||
|
|
bc8809d45c | ||
|
|
f012e6dab0 | ||
|
|
411d0d7863 | ||
|
|
7bb1007884 | ||
|
|
9a6cfc1b82 | ||
|
|
26f7f9d3d8 | ||
|
|
b1d5cd6bf6 | ||
|
|
b392655cdb | ||
|
|
ad9d1c5380 | ||
|
|
2cb4210319 | ||
|
|
08d0516b4b | ||
|
|
bf2d216100 | ||
|
|
62ec51f715 | ||
|
|
9f01876de8 | ||
|
|
22fa5a7ee3 | ||
|
|
a4d1211ec6 | ||
|
|
f6e17fa972 | ||
|
|
d82efbd503 | ||
|
|
2218c49244 | ||
|
|
f75b4f65c1 | ||
|
|
4f58733d82 | ||
|
|
45e1b32447 | ||
|
|
58461660c3 | ||
|
|
3d96969398 | ||
|
|
32c15d67b5 | ||
|
|
e4a97dd3ac | ||
|
|
39a31170ee | ||
|
|
d394cfc4db | ||
|
|
dbcc9ea826 | ||
|
|
650e55fef8 | ||
|
|
6f14d105a7 | ||
|
|
a23eff20fe | ||
|
|
476b44ae67 | ||
|
|
cda7ed7101 | ||
|
|
d2589a5bd1 | ||
|
|
7ebf572b8e | ||
|
|
9eeeabf877 | ||
|
|
143db56992 | ||
|
|
084718b776 | ||
|
|
f74721d926 | ||
|
|
2db8563a7e | ||
|
|
df143137ef | ||
|
|
a872ab2a1a | ||
|
|
c83af7c304 | ||
|
|
63e5e05643 | ||
|
|
4ccbde23cc | ||
|
|
30933c5145 | ||
|
|
42fa4c0011 | ||
|
|
3471e84d7f | ||
|
|
5c82a923a9 | ||
|
|
49263ba69f | ||
|
|
8b0cecc7e4 | ||
|
|
2e818a071e | ||
|
|
8a0428ffa5 | ||
|
|
2702e09a98 | ||
|
|
b19f407569 | ||
|
|
ada0fcf299 | ||
|
|
dd954749be | ||
|
|
c6ae3e7242 | ||
|
|
ae836ae007 | ||
|
|
4f5a9d6a06 | ||
|
|
de267b964c | ||
|
|
554907d9ff | ||
|
|
221096fed1 | ||
|
|
2c318b680b | ||
|
|
4610c1a257 | ||
|
|
04b7095c28 | ||
|
|
19281b584e | ||
|
|
0d4a74b2c2 | ||
|
|
5ba178a54f | ||
|
|
b363999d19 | ||
|
|
85cc8b6a20 | ||
|
|
636afa0102 | ||
|
|
7233841171 | ||
|
|
efa9bf36eb | ||
|
|
626768f626 | ||
|
|
e4d3d4b31d | ||
|
|
2b68b300a1 | ||
|
|
69d8442ab4 | ||
|
|
6d80460425 | ||
|
|
768be7d46d | ||
|
|
33b164f63a | ||
|
|
ae146c3df7 | ||
|
|
bfaa328bd7 | ||
|
|
02845a1d59 | ||
|
|
1ddb38e583 | ||
|
|
6481771301 | ||
|
|
23ab667bbb | ||
|
|
4f06fc6a84 | ||
|
|
74e66b71ac | ||
|
|
aa9d69c728 | ||
|
|
87e824d43e | ||
|
|
5020c48e17 | ||
|
|
9bc41ca040 | ||
|
|
d404febb29 | ||
|
|
e3a3f36225 | ||
|
|
09009ab03a | ||
|
|
a9e9f54962 | ||
|
|
f7f5131aa8 | ||
|
|
c85c333c90 | ||
|
|
71ea6e8863 | ||
|
|
08b5bcbdb1 | ||
|
|
26c5149d31 | ||
|
|
8a875b119f | ||
|
|
b897be76b4 | ||
|
|
64a7810065 | ||
|
|
581092a964 | ||
|
|
100f91e1c9 | ||
|
|
c539b8ee46 | ||
|
|
295b4fc337 | ||
|
|
3e4f7108a0 | ||
|
|
357dceb05a | ||
|
|
8254b74019 | ||
|
|
ab633f4557 | ||
|
|
f0e9ab3447 | ||
|
|
9a0a7c1779 | ||
|
|
4740a58318 | ||
|
|
fa8504fffb | ||
|
|
cabbff73fd | ||
|
|
6d452dbe6e | ||
|
|
6271f4d6ba | ||
|
|
000299a323 | ||
|
|
1337b60738 | ||
|
|
74018c16be | ||
|
|
d707f10bb2 | ||
|
|
1800b2c797 | ||
|
|
cc934429fe | ||
|
|
34f4622091 | ||
|
|
11cb37c9a4 | ||
|
|
f916385cab | ||
|
|
c5940bd68f | ||
|
|
c86ad857ac | ||
|
|
95fdf82a53 | ||
|
|
cec11be7c1 | ||
|
|
6bc9092786 | ||
|
|
34fcb3a393 | ||
|
|
81f99dde55 | ||
|
|
c71f62089b | ||
|
|
13aa24a56a | ||
|
|
1dd386a65a | ||
|
|
a8bc7ceb15 | ||
|
|
044f65a052 | ||
|
|
a9cb0bcba6 | ||
|
|
3cfe4b720c | ||
|
|
43e9bbe31c | ||
|
|
94ef310106 | ||
|
|
a782aae78e | ||
|
|
c47ee4a296 | ||
|
|
528a76a419 | ||
|
|
40e5243c35 | ||
|
|
ff32d51700 | ||
|
|
1af1a6d7e9 | ||
|
|
d6e809d185 | ||
|
|
9ba5fe2805 | ||
|
|
5e4bb69498 | ||
|
|
dc98136346 | ||
|
|
d4fb244d2d | ||
|
|
3c8701ee36 | ||
|
|
432001656e | ||
|
|
e6102af351 | ||
|
|
21aa5d261a | ||
|
|
d87f47412b | ||
|
|
135d7c03cc | ||
|
|
b04dd62f8a | ||
|
|
0f157e7e2b | ||
|
|
56a6eee656 | ||
|
|
1819b85b85 | ||
|
|
49eed7540a | ||
|
|
7a6f288fab | ||
|
|
eabab840e9 | ||
|
|
d505a3c8b7 | ||
|
|
a3842584dd | ||
|
|
62f5806f42 | ||
|
|
0f01eae655 | ||
|
|
03f3e17a40 | ||
|
|
f17e4e7198 | ||
|
|
c8784634e1 | ||
|
|
2fc327b775 | ||
|
|
f4e7a11c35 | ||
|
|
a688e753de | ||
|
|
cb9a04d3e3 | ||
|
|
7a4ca3135d | ||
|
|
2c9c105bbb | ||
|
|
248ee82db0 | ||
|
|
9552014047 | ||
|
|
dd938911f7 | ||
|
|
681097fd43 | ||
|
|
4493ee346d | ||
|
|
b374b21171 | ||
|
|
6fe49f93ad | ||
|
|
ff9c931366 | ||
|
|
534683a3ff | ||
|
|
474dcf60a2 | ||
|
|
a929220d3c | ||
|
|
8bc12a4ee2 | ||
|
|
f1a79085eb | ||
|
|
6890c9d171 | ||
|
|
614abd58be | ||
|
|
335790dae8 | ||
|
|
2e2997bd7d | ||
|
|
f8a0035215 | ||
|
|
5accf36115 | ||
|
|
17e87c9a20 | ||
|
|
c5b7432cf2 | ||
|
|
bdba280c3d | ||
|
|
27ffcc6576 | ||
|
|
091e2f177b | ||
|
|
70b20e9d2b | ||
|
|
549dd8a4c4 | ||
|
|
cc4c672773 | ||
|
|
ee8e792588 | ||
|
|
ffaa8b9ced | ||
|
|
b2c2afe374 | ||
|
|
76a8c80b63 | ||
|
|
06600028a5 | ||
|
|
0a487e4f92 | ||
|
|
6f8cac8077 | ||
|
|
d45a2bf35b | ||
|
|
bbd49d4634 | ||
|
|
3de6ec0a59 | ||
|
|
5797381ea2 | ||
|
|
fd8711023d | ||
|
|
e82c875bc3 | ||
|
|
c76b3acce7 | ||
|
|
fb9e258a65 | ||
|
|
e18c180414 | ||
|
|
4e35c78fd5 | ||
|
|
994e29e1fc | ||
|
|
0c95772f4e | ||
|
|
3201c7dfb5 | ||
|
|
5bedbb14b4 | ||
|
|
acf5ba5432 | ||
|
|
41b61cfb3e | ||
|
|
93d6bcef0e | ||
|
|
be34c4c2ef | ||
|
|
71468492b7 | ||
|
|
d92a1e7ca8 | ||
|
|
4fe9e4e715 | ||
|
|
7209476b18 | ||
|
|
4fee51fc99 | ||
|
|
601faf8548 | ||
|
|
a6b3e74f7d | ||
|
|
609106e2d0 | ||
|
|
bf0e806fed | ||
|
|
f8fa47fa02 | ||
|
|
a3c1399924 | ||
|
|
ec38c7b5be | ||
|
|
9f00b513f7 | ||
|
|
e608a389af | ||
|
|
b4b71880e1 | ||
|
|
5e49804004 | ||
|
|
637e9c11ee | ||
|
|
67bddb3d72 | ||
|
|
c2e01f06a3 | ||
|
|
a2fc9fabd8 | ||
|
|
2997c269e1 | ||
|
|
17573cd1fb | ||
|
|
775a90771e | ||
|
|
0772f8011c | ||
|
|
7dc4983898 | ||
|
|
5429582892 | ||
|
|
2a70143050 | ||
|
|
b516ae75db | ||
|
|
067d820a8a | ||
|
|
874d4a7026 | ||
|
|
2ffae56efa | ||
|
|
a04204e47d | ||
|
|
6158411ecb | ||
|
|
7d10b3dcf7 | ||
|
|
5f0969f52b | ||
|
|
09db89a0c8 | ||
|
|
2f9a48cce7 | ||
|
|
dfe179bf0d | ||
|
|
e3f20cdb8a | ||
|
|
f5ba6fe03c | ||
|
|
6cadf333fb | ||
|
|
f273229b01 | ||
|
|
4638f67e4e | ||
|
|
d3363bab96 | ||
|
|
2570f7ce23 | ||
|
|
682ef235b5 | ||
|
|
532293c4cf | ||
|
|
30e2c14f4a | ||
|
|
1f3a53db2d | ||
|
|
5591d6f65c | ||
|
|
690b4efca8 | ||
|
|
8ad2e10cfe | ||
|
|
1f91db1d43 | ||
|
|
5ec26c6542 | ||
|
|
1b804cd0dd | ||
|
|
395cafcf46 | ||
|
|
bf53c70dd9 | ||
|
|
64005c03b6 | ||
|
|
07769aec4b | ||
|
|
554f33d033 | ||
|
|
b5a6742adc | ||
|
|
ed59316ff6 | ||
|
|
d1113b5371 | ||
|
|
8f79cec51a | ||
|
|
aedb9b23b4 | ||
|
|
c82bb3ec76 | ||
|
|
f20d427a4d | ||
|
|
df01d0725c | ||
|
|
060b94b71f | ||
|
|
b86022ea52 | ||
|
|
0ca6d58e23 | ||
|
|
3d874367fe | ||
|
|
72fbcfb5f6 | ||
|
|
6edf24b0f7 | ||
|
|
48db4bf854 | ||
|
|
2512e66c06 | ||
|
|
8a6d5b4997 | ||
|
|
1e08c5f3c6 | ||
|
|
fbbf626e8c | ||
|
|
c3c72cda6d | ||
|
|
e15f518ccc | ||
|
|
db9ac4b674 | ||
|
|
602d1d7323 | ||
|
|
f5bcf5d608 | ||
|
|
2f469ff830 | ||
|
|
4d1ade1f88 | ||
|
|
928cb7e09e | ||
|
|
3e550364c6 | ||
|
|
d29c454e80 | ||
|
|
26ad2e29c6 | ||
|
|
c597de6a1d | ||
|
|
24fa361f40 | ||
|
|
a7f02c89d7 | ||
|
|
69d59acc5a | ||
|
|
f191efce1b | ||
|
|
03dcb9c0e4 | ||
|
|
2557f90c01 | ||
|
|
f3887f1fa7 | ||
|
|
f8ce278e76 | ||
|
|
5f1c9ca107 | ||
|
|
d8d70d9e43 | ||
|
|
31f048d054 | ||
|
|
f2e8d2dc07 | ||
|
|
34475bf867 | ||
|
|
2235413c15 | ||
|
|
12bf754a8a | ||
|
|
3f36c52f41 | ||
|
|
ee32654723 | ||
|
|
df703f847c | ||
|
|
0f31f18744 | ||
|
|
b0fb5c33e9 | ||
|
|
9a186ac8d5 | ||
|
|
56eec2734c | ||
|
|
f85bd0234a | ||
|
|
bb557d5193 | ||
|
|
caa40ad2c6 | ||
|
|
a124374202 | ||
|
|
07990ad8f1 | ||
|
|
3d45e7ca64 | ||
|
|
e185e91581 | ||
|
|
8c4ef3e9aa | ||
|
|
cce5666e5d | ||
|
|
9d7e10950f | ||
|
|
a96cd44926 | ||
|
|
d79b59d3b1 | ||
|
|
f9aba9ba33 | ||
|
|
a75afe1462 | ||
|
|
a4425d26d2 | ||
|
|
9d3536ca2b | ||
|
|
2a6a7d2382 | ||
|
|
3adddaa643 | ||
|
|
68a117d490 | ||
|
|
e72df84396 | ||
|
|
ebc7cbaf39 | ||
|
|
3ad2cb8c9c | ||
|
|
2f532e49d1 | ||
|
|
c41a8317cf | ||
|
|
89003dcb25 | ||
|
|
5b97eb0445 | ||
|
|
b5b7fc9957 | ||
|
|
7c8eacfa12 | ||
|
|
6af9a91b9d | ||
|
|
6a53005074 | ||
|
|
717d40475e | ||
|
|
c09bfc136e | ||
|
|
1f28837bd7 | ||
|
|
4dd6f105a0 | ||
|
|
757675db80 | ||
|
|
6fb1af00f1 | ||
|
|
cc1e6c3e4b | ||
|
|
dadf035366 | ||
|
|
9b83dc1b79 | ||
|
|
dcdbb39c31 | ||
|
|
1312c7ccd7 | ||
|
|
76e0511481 | ||
|
|
e72a9fb814 | ||
|
|
0d525cf644 | ||
|
|
0c4ef58acd | ||
|
|
273081d0a6 | ||
|
|
e8fe6f873e | ||
|
|
fb80ecd9c3 | ||
|
|
acb4e9e783 | ||
|
|
f6516cba89 | ||
|
|
66276d88ef | ||
|
|
807de37561 | ||
|
|
eca6738b00 | ||
|
|
dc492867af | ||
|
|
c3bee2038a | ||
|
|
3cafdbdc1e | ||
|
|
617d2d509c | ||
|
|
2ab71fb67d | ||
|
|
deb8431a47 | ||
|
|
a568f0cf16 | ||
|
|
3a7ce432e5 | ||
|
|
f2deb8da46 | ||
|
|
0c1f340934 | ||
|
|
952c5e1865 | ||
|
|
7a0ebc0d18 | ||
|
|
f109e3b598 | ||
|
|
052eddbac8 | ||
|
|
be2a9a03d0 | ||
|
|
1b2178f558 | ||
|
|
9c2d53bcef | ||
|
|
9072ddda05 | ||
|
|
a9796ec503 | ||
|
|
fb3af7fbcb | ||
|
|
5d0d35d3f5 | ||
|
|
3893a70888 | ||
|
|
d1e4347cb2 | ||
|
|
137505e2ad | ||
|
|
ebd0dcd5d2 | ||
|
|
4dfb04d501 | ||
|
|
76024e479d | ||
|
|
a9cca4a9f6 | ||
|
|
b5351285b6 | ||
|
|
8fd631bf06 | ||
|
|
1618060a3e | ||
|
|
2da1b3307a | ||
|
|
b6fa00d4fd | ||
|
|
94679d590f | ||
|
|
c0f445294c | ||
|
|
ff5e389e9b | ||
|
|
dac56b4d08 | ||
|
|
24e8119350 | ||
|
|
25877114cf | ||
|
|
75960bba16 | ||
|
|
fff2c9e47b | ||
|
|
b45998a18e | ||
|
|
e6e156709a | ||
|
|
6e9da8ab2a | ||
|
|
a4b4b0ad38 | ||
|
|
c3fd7d837b | ||
|
|
8cf436370c | ||
|
|
b51da3bb9a | ||
|
|
ac0e03fe89 | ||
|
|
a764a3e66f | ||
|
|
1c03d5e5ce | ||
|
|
29f4150757 | ||
|
|
48c907e1a2 | ||
|
|
ce20325947 | ||
|
|
e8c70a71d9 | ||
|
|
be6f467f42 | ||
|
|
0012a52e88 | ||
|
|
0ffa207118 | ||
|
|
8da8a625a9 | ||
|
|
4fef63de52 | ||
|
|
073d9bf3c9 | ||
|
|
b5fd5f2f5e | ||
|
|
a3093fad97 | ||
|
|
ff5e1c3aee | ||
|
|
a75c8ee6f0 | ||
|
|
2466101fe1 | ||
|
|
349f6f8ab8 | ||
|
|
91d591046f | ||
|
|
e6bb291b8a | ||
|
|
00df9c6c18 | ||
|
|
3ba0fe4349 | ||
|
|
74b2d884c8 | ||
|
|
d7989417d5 | ||
|
|
1cefe9117b | ||
|
|
6f7b75c9a3 | ||
|
|
600fea23bb | ||
|
|
227645ab65 | ||
|
|
48d0bedda9 | ||
|
|
1a1c5863e4 | ||
|
|
6dc17fab57 | ||
|
|
eaf69dc9d5 | ||
|
|
b59e90d100 | ||
|
|
5697084832 | ||
|
|
3a8aac8c67 | ||
|
|
cf4b46d6f7 | ||
|
|
ec2b00e8c4 | ||
|
|
5d07666362 | ||
|
|
d06062c179 | ||
|
|
c8021925c8 | ||
|
|
ee19a9c274 | ||
|
|
63abf063b7 | ||
|
|
ce6f1f8c18 | ||
|
|
a2ae715226 | ||
|
|
56f725e39b | ||
|
|
ddab0e6cd2 | ||
|
|
c9a55941b0 | ||
|
|
ac8ad111de | ||
|
|
8ea49aa5b5 | ||
|
|
379c8d92ec | ||
|
|
5c73744aca | ||
|
|
9a9202e093 | ||
|
|
ac084ddb0e | ||
|
|
826f25744d | ||
|
|
322b06b364 | ||
|
|
2e4bd4639f | ||
|
|
9226e8bdca | ||
|
|
5d2d8f9215 | ||
|
|
4759fc9f69 | ||
|
|
00d00036fe | ||
|
|
556b61d778 | ||
|
|
339f85c308 | ||
|
|
14ef3a5464 | ||
|
|
666ac2c445 | ||
|
|
c2d45e4cf7 | ||
|
|
9ebb3f06b3 | ||
|
|
0b3f7a5a6b | ||
|
|
8b5110d218 | ||
|
|
c3eb17a411 | ||
|
|
434d156cbc | ||
|
|
bee8ce4e56 | ||
|
|
d08d287431 | ||
|
|
0c04246723 | ||
|
|
67fd391e3d | ||
|
|
9f70c531a8 | ||
|
|
2e3a8afe2a | ||
|
|
b3fa7b15fc | ||
|
|
d6be353299 | ||
|
|
daa34685c3 | ||
|
|
a01d670fb2 | ||
|
|
7c10775e96 | ||
|
|
3eb569f7b1 | ||
|
|
b40fcdff36 | ||
|
|
c486ae37d3 | ||
|
|
bbfe1c7e30 | ||
|
|
ac1f1e224b | ||
|
|
c56bd24715 | ||
|
|
6784dee775 | ||
|
|
65ed4d0ac2 | ||
|
|
b50a09f99e | ||
|
|
4e03209c76 | ||
|
|
b0ef76bf27 | ||
|
|
c37871ac3a | ||
|
|
5a44a6624b | ||
|
|
a0656a6c56 | ||
|
|
9ed74cbfcd | ||
|
|
519a2af2a4 | ||
|
|
8208776b47 | ||
|
|
341ba92f23 | ||
|
|
1c5321e57f | ||
|
|
bb15b2d708 | ||
|
|
5dc9b060d2 | ||
|
|
b8acfe08a4 | ||
|
|
8e2264b585 | ||
|
|
6819ecee92 | ||
|
|
b7117d51b2 | ||
|
|
183c775603 | ||
|
|
2ecd7abc0d | ||
|
|
c4fbb6319b | ||
|
|
21c94953c8 | ||
|
|
7eb24ff237 | ||
|
|
779268c3a4 | ||
|
|
784c599c7b | ||
|
|
ae7e105ce9 | ||
|
|
631a1def13 | ||
|
|
54605e54b6 | ||
|
|
646128db9e | ||
|
|
c756259094 | ||
|
|
47c8e369cf | ||
|
|
e458b73a01 | ||
|
|
2c43c2a4db | ||
|
|
08d41f9eb3 | ||
|
|
1112cbc822 | ||
|
|
9f0008372c | ||
|
|
cd48ee2152 | ||
|
|
1f8db236f5 | ||
|
|
beead8e614 | ||
|
|
e2a6d0f4b2 | ||
|
|
6671a4a3f5 | ||
|
|
afa5119303 | ||
|
|
ad26247247 | ||
|
|
9a6cf82adc | ||
|
|
71b8f49614 | ||
|
|
cdd15b4a69 | ||
|
|
4da7fca491 | ||
|
|
9af7fb9b05 | ||
|
|
2f6d3605d9 | ||
|
|
83e0f8bd33 | ||
|
|
f786b10403 | ||
|
|
803b7b4b93 | ||
|
|
37b261ef0f | ||
|
|
d1e2e2d857 | ||
|
|
85ab5b70e9 | ||
|
|
206c6862f9 | ||
|
|
05d8a65f75 | ||
|
|
9989365fe8 | ||
|
|
3f5764e5ba | ||
|
|
dcf45da09c | ||
|
|
951e31a154 | ||
|
|
e1960670ca | ||
|
|
825a7106c6 | ||
|
|
dcd891a176 | ||
|
|
01ca3e119b | ||
|
|
f496b40cd6 | ||
|
|
9062c75481 | ||
|
|
a175c3829c | ||
|
|
37b70a8e24 | ||
|
|
c996bb3c19 | ||
|
|
8b3f8d77b0 | ||
|
|
2d033c94d9 | ||
|
|
151d51acfa | ||
|
|
b19a7a8b8a | ||
|
|
01392a57dd | ||
|
|
0a33598f65 | ||
|
|
6563e621fd |
@@ -25,3 +25,4 @@ forin
|
||||
uper
|
||||
slac
|
||||
couldn
|
||||
ges
|
||||
|
||||
3
.github/workflows/production-suite.yml
vendored
3
.github/workflows/production-suite.yml
vendored
@@ -254,6 +254,9 @@ jobs:
|
||||
- docker_image: zulip/ci:bullseye-6.0
|
||||
name: 6.0 Version Upgrade
|
||||
os: bullseye
|
||||
- docker_image: zulip/ci:bookworm-7.0
|
||||
name: 7.0 Version Upgrade
|
||||
os: bookworm
|
||||
|
||||
name: ${{ matrix.name }}
|
||||
container:
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -17,7 +17,10 @@
|
||||
# See `git help ignore` for details on the format.
|
||||
|
||||
## Config files for the dev environment
|
||||
/zproject/apns-dev.pem
|
||||
/zproject/apns-dev-key.p8
|
||||
/zproject/dev-secrets.conf
|
||||
/zproject/custom_dev_settings.py
|
||||
/tools/conf.ini
|
||||
/tools/custom_provision
|
||||
/tools/droplets/conf.ini
|
||||
|
||||
6
.mailmap
6
.mailmap
@@ -29,6 +29,8 @@ Aman Agrawal <amanagr@zulip.com> <f2016561@pilani.bits-pilani.ac.in>
|
||||
Anders Kaseorg <anders@zulip.com> <anders@zulipchat.com>
|
||||
Anders Kaseorg <anders@zulip.com> <andersk@mit.edu>
|
||||
aparna-bhatt <aparnabhatt2001@gmail.com> <86338542+aparna-bhatt@users.noreply.github.com>
|
||||
Aryan Bhokare <aryan1bhokare@gmail.com>
|
||||
Aryan Bhokare <aryan1bhokare@gmail.com> <92683836+aryan-bhokare@users.noreply.github.com>
|
||||
Aryan Shridhar <aryanshridhar7@gmail.com>
|
||||
Aryan Shridhar <aryanshridhar7@gmail.com> <53977614+aryanshridhar@users.noreply.github.com>
|
||||
Ashwat Kumar Singh <ashwat.kumarsingh.met20@itbhu.ac.in>
|
||||
@@ -68,6 +70,7 @@ Kevin Mehall <km@kevinmehall.net> <kevin@humbughq.com>
|
||||
Kevin Mehall <km@kevinmehall.net> <kevin@zulip.com>
|
||||
Kevin Scott <kevin.scott.98@gmail.com>
|
||||
Lalit Kumar Singh <lalitkumarsingh3716@gmail.com>
|
||||
Lalit Kumar Singh <lalitkumarsingh3716@gmail.com> <lalits01@smartek21.com>
|
||||
Lauryn Menard <lauryn@zulip.com> <63245456+laurynmm@users.noreply.github.com>
|
||||
Lauryn Menard <lauryn@zulip.com> <lauryn.menard@gmail.com>
|
||||
m-e-l-u-h-a-n <purushottam.tiwari.cd.cse19@itbhu.ac.in>
|
||||
@@ -75,6 +78,8 @@ m-e-l-u-h-a-n <purushottam.tiwari.cd.cse19@itbhu.ac.in> <pururshottam.tiwari.cd.
|
||||
Mateusz Mandera <mateusz.mandera@zulip.com> <mateusz.mandera@protonmail.com>
|
||||
Matt Keller <matt@zulip.com>
|
||||
Matt Keller <matt@zulip.com> <m@cognusion.com>
|
||||
Nehal Sharma <bablinaneh@gmail.com>
|
||||
Nehal Sharma <bablinaneh@gmail.com> <68962290+N-Shar-ma@users.noreply.github.com>
|
||||
Noble Mittal <noblemittal@outlook.com> <62551163+beingnoble03@users.noreply.github.com>
|
||||
nzai <nzaih18@gmail.com> <70953556+nzaih1999@users.noreply.github.com>
|
||||
Palash Baderia <palash.baderia@outlook.com>
|
||||
@@ -99,6 +104,7 @@ Sayam Samal <samal.sayam@gmail.com>
|
||||
Scott Feeney <scott@oceanbase.org> <scott@humbughq.com>
|
||||
Scott Feeney <scott@oceanbase.org> <scott@zulip.com>
|
||||
Shlok Patel <shlokcpatel2001@gmail.com>
|
||||
Shu Chen <shu@zulip.com>
|
||||
Somesh Ranjan <somesh.ranjan.met20@itbhu.ac.in> <77766761+somesh202@users.noreply.github.com>
|
||||
Steve Howell <showell@zulip.com> <showell30@yahoo.com>
|
||||
Steve Howell <showell@zulip.com> <showell@yahoo.com>
|
||||
|
||||
@@ -19,14 +19,20 @@ from analytics.models import (
|
||||
UserCount,
|
||||
installation_epoch,
|
||||
)
|
||||
from zerver.lib.logging_util import log_to_file
|
||||
from zerver.lib.timestamp import ceiling_to_day, ceiling_to_hour, floor_to_hour, verify_UTC
|
||||
from zerver.models import Message, Realm, RealmAuditLog, Stream, UserActivityInterval, UserProfile
|
||||
|
||||
## Logging setup ##
|
||||
if settings.ZILENCER_ENABLED:
|
||||
from zilencer.models import (
|
||||
RemoteInstallationCount,
|
||||
RemoteRealm,
|
||||
RemoteRealmCount,
|
||||
RemoteZulipServer,
|
||||
)
|
||||
|
||||
|
||||
logger = logging.getLogger("zulip.analytics")
|
||||
|
||||
logger = logging.getLogger("zulip.management")
|
||||
log_to_file(logger, settings.ANALYTICS_LOG_PATH)
|
||||
|
||||
# You can't subtract timedelta.max from a datetime, so use this instead
|
||||
TIMEDELTA_MAX = timedelta(days=365 * 1000)
|
||||
@@ -103,6 +109,9 @@ class DataCollector:
|
||||
self.output_table = output_table
|
||||
self.pull_function = pull_function
|
||||
|
||||
def depends_on_realm(self) -> bool:
|
||||
return self.output_table in (UserCount, StreamCount)
|
||||
|
||||
|
||||
## CountStat-level operations ##
|
||||
|
||||
@@ -191,7 +200,7 @@ def do_fill_count_stat_at_hour(
|
||||
def do_delete_counts_at_hour(stat: CountStat, end_time: datetime) -> None:
|
||||
if isinstance(stat, LoggingCountStat):
|
||||
InstallationCount.objects.filter(property=stat.property, end_time=end_time).delete()
|
||||
if stat.data_collector.output_table in [UserCount, StreamCount]:
|
||||
if stat.data_collector.depends_on_realm():
|
||||
RealmCount.objects.filter(property=stat.property, end_time=end_time).delete()
|
||||
else:
|
||||
UserCount.objects.filter(property=stat.property, end_time=end_time).delete()
|
||||
@@ -212,7 +221,7 @@ def do_aggregate_to_summary_table(
|
||||
else:
|
||||
realm_clause = SQL("")
|
||||
|
||||
if output_table in (UserCount, StreamCount):
|
||||
if stat.data_collector.depends_on_realm():
|
||||
realmcount_query = SQL(
|
||||
"""
|
||||
INSERT INTO analytics_realmcount
|
||||
@@ -293,7 +302,7 @@ def do_aggregate_to_summary_table(
|
||||
|
||||
# called from zerver.actions; should not throw any errors
|
||||
def do_increment_logging_stat(
|
||||
zerver_object: Union[Realm, UserProfile, Stream],
|
||||
model_object_for_bucket: Union[Realm, UserProfile, Stream, "RemoteRealm", "RemoteZulipServer"],
|
||||
stat: CountStat,
|
||||
subgroup: Optional[Union[str, int, bool]],
|
||||
event_time: datetime,
|
||||
@@ -304,19 +313,35 @@ def do_increment_logging_stat(
|
||||
|
||||
table = stat.data_collector.output_table
|
||||
if table == RealmCount:
|
||||
assert isinstance(zerver_object, Realm)
|
||||
id_args: Dict[str, Union[Realm, UserProfile, Stream]] = {"realm": zerver_object}
|
||||
assert isinstance(model_object_for_bucket, Realm)
|
||||
id_args: Dict[
|
||||
str, Optional[Union[Realm, UserProfile, Stream, "RemoteRealm", "RemoteZulipServer"]]
|
||||
] = {"realm": model_object_for_bucket}
|
||||
elif table == UserCount:
|
||||
assert isinstance(zerver_object, UserProfile)
|
||||
id_args = {"realm": zerver_object.realm, "user": zerver_object}
|
||||
else: # StreamCount
|
||||
assert isinstance(zerver_object, Stream)
|
||||
id_args = {"realm": zerver_object.realm, "stream": zerver_object}
|
||||
assert isinstance(model_object_for_bucket, UserProfile)
|
||||
id_args = {"realm": model_object_for_bucket.realm, "user": model_object_for_bucket}
|
||||
elif table == StreamCount:
|
||||
assert isinstance(model_object_for_bucket, Stream)
|
||||
id_args = {"realm": model_object_for_bucket.realm, "stream": model_object_for_bucket}
|
||||
elif table == RemoteInstallationCount:
|
||||
assert isinstance(model_object_for_bucket, RemoteZulipServer)
|
||||
id_args = {"server": model_object_for_bucket, "remote_id": None}
|
||||
elif table == RemoteRealmCount:
|
||||
assert isinstance(model_object_for_bucket, RemoteRealm)
|
||||
id_args = {
|
||||
"server": model_object_for_bucket.server,
|
||||
"remote_realm": model_object_for_bucket,
|
||||
"remote_id": None,
|
||||
}
|
||||
else:
|
||||
raise AssertionError("Unsupported CountStat output_table")
|
||||
|
||||
if stat.frequency == CountStat.DAY:
|
||||
end_time = ceiling_to_day(event_time)
|
||||
else: # CountStat.HOUR:
|
||||
elif stat.frequency == CountStat.HOUR:
|
||||
end_time = ceiling_to_hour(event_time)
|
||||
else:
|
||||
raise AssertionError("Unsupported CountStat frequency")
|
||||
|
||||
row, created = table._default_manager.get_or_create(
|
||||
property=stat.property,
|
||||
@@ -817,6 +842,12 @@ def get_count_stats(realm: Optional[Realm] = None) -> Dict[str, CountStat]:
|
||||
CountStat(
|
||||
"minutes_active::day", DataCollector(UserCount, do_pull_minutes_active), CountStat.DAY
|
||||
),
|
||||
# Tracks the number of push notifications requested by the server.
|
||||
LoggingCountStat(
|
||||
"mobile_pushes_sent::day",
|
||||
RealmCount,
|
||||
CountStat.DAY,
|
||||
),
|
||||
# Rate limiting stats
|
||||
# Used to limit the number of invitation emails sent by a realm
|
||||
LoggingCountStat("invites_sent::day", RealmCount, CountStat.DAY),
|
||||
@@ -831,8 +862,65 @@ def get_count_stats(realm: Optional[Realm] = None) -> Dict[str, CountStat]:
|
||||
),
|
||||
]
|
||||
|
||||
if settings.ZILENCER_ENABLED:
|
||||
# See also the remote_installation versions of these in REMOTE_INSTALLATION_COUNT_STATS.
|
||||
count_stats_.append(
|
||||
LoggingCountStat(
|
||||
"mobile_pushes_received::day",
|
||||
RemoteRealmCount,
|
||||
CountStat.DAY,
|
||||
)
|
||||
)
|
||||
count_stats_.append(
|
||||
LoggingCountStat(
|
||||
"mobile_pushes_forwarded::day",
|
||||
RemoteRealmCount,
|
||||
CountStat.DAY,
|
||||
)
|
||||
)
|
||||
|
||||
return OrderedDict((stat.property, stat) for stat in count_stats_)
|
||||
|
||||
|
||||
# These properties are tracked by the bouncer itself and therefore syncing them
|
||||
# from a remote server should not be allowed - or the server would be able to interfere
|
||||
# with our data.
|
||||
BOUNCER_ONLY_REMOTE_COUNT_STAT_PROPERTIES = [
|
||||
"mobile_pushes_received::day",
|
||||
"mobile_pushes_forwarded::day",
|
||||
]
|
||||
|
||||
# To avoid refactoring for now COUNT_STATS can be used as before
|
||||
COUNT_STATS = get_count_stats()
|
||||
|
||||
REMOTE_INSTALLATION_COUNT_STATS = OrderedDict()
|
||||
|
||||
if settings.ZILENCER_ENABLED:
|
||||
# REMOTE_INSTALLATION_COUNT_STATS contains duplicates of the
|
||||
# RemoteRealmCount stats declared above; it is necessary because
|
||||
# pre-8.0 servers do not send the fields required to identify a
|
||||
# RemoteRealm.
|
||||
|
||||
# Tracks the number of push notifications requested to be sent
|
||||
# by a remote server.
|
||||
REMOTE_INSTALLATION_COUNT_STATS["mobile_pushes_received::day"] = LoggingCountStat(
|
||||
"mobile_pushes_received::day",
|
||||
RemoteInstallationCount,
|
||||
CountStat.DAY,
|
||||
)
|
||||
# Tracks the number of push notifications successfully sent to
|
||||
# mobile devices, as requested by the remote server. Therefore
|
||||
# this should be less than or equal to mobile_pushes_received -
|
||||
# with potential tiny offsets resulting from a request being
|
||||
# *received* by the bouncer right before midnight, but *sent* to
|
||||
# the mobile device right after midnight. This would cause the
|
||||
# increments to happen to CountStat records for different days.
|
||||
REMOTE_INSTALLATION_COUNT_STATS["mobile_pushes_forwarded::day"] = LoggingCountStat(
|
||||
"mobile_pushes_forwarded::day",
|
||||
RemoteInstallationCount,
|
||||
CountStat.DAY,
|
||||
)
|
||||
|
||||
ALL_COUNT_STATS = OrderedDict(
|
||||
list(COUNT_STATS.items()) + list(REMOTE_INSTALLATION_COUNT_STATS.items())
|
||||
)
|
||||
|
||||
@@ -7,7 +7,7 @@ from django.core.management.base import BaseCommand
|
||||
from django.utils.timezone import now as timezone_now
|
||||
from typing_extensions import override
|
||||
|
||||
from analytics.lib.counts import COUNT_STATS, CountStat
|
||||
from analytics.lib.counts import ALL_COUNT_STATS, CountStat
|
||||
from analytics.models import installation_epoch
|
||||
from zerver.lib.timestamp import TimeZoneNotUTCError, floor_to_day, floor_to_hour, verify_UTC
|
||||
from zerver.models import Realm
|
||||
@@ -44,7 +44,7 @@ class Command(BaseCommand):
|
||||
|
||||
warning_unfilled_properties = []
|
||||
critical_unfilled_properties = []
|
||||
for property, stat in COUNT_STATS.items():
|
||||
for property, stat in ALL_COUNT_STATS.items():
|
||||
last_fill = stat.last_successful_fill()
|
||||
if last_fill is None:
|
||||
last_fill = installation_epoch()
|
||||
|
||||
@@ -4,7 +4,7 @@ from typing import Any
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from typing_extensions import override
|
||||
|
||||
from analytics.lib.counts import COUNT_STATS, do_drop_single_stat
|
||||
from analytics.lib.counts import ALL_COUNT_STATS, do_drop_single_stat
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
@@ -18,7 +18,7 @@ class Command(BaseCommand):
|
||||
@override
|
||||
def handle(self, *args: Any, **options: Any) -> None:
|
||||
property = options["property"]
|
||||
if property not in COUNT_STATS:
|
||||
if property not in ALL_COUNT_STATS:
|
||||
raise CommandError(f"Invalid property: {property}")
|
||||
if not options["force"]:
|
||||
raise CommandError("No action taken. Use --force.")
|
||||
|
||||
@@ -32,6 +32,7 @@ from zerver.models import (
|
||||
Recipient,
|
||||
Stream,
|
||||
Subscription,
|
||||
SystemGroups,
|
||||
UserGroup,
|
||||
UserProfile,
|
||||
)
|
||||
@@ -114,7 +115,7 @@ class Command(BaseCommand):
|
||||
)
|
||||
|
||||
administrators_user_group = UserGroup.objects.get(
|
||||
name=UserGroup.ADMINISTRATORS_GROUP_NAME, realm=realm, is_system_group=True
|
||||
name=SystemGroups.ADMINISTRATORS, realm=realm, is_system_group=True
|
||||
)
|
||||
stream = Stream.objects.create(
|
||||
name="all",
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import hashlib
|
||||
import os
|
||||
import time
|
||||
from argparse import ArgumentParser
|
||||
@@ -10,9 +11,9 @@ from django.utils.dateparse import parse_datetime
|
||||
from django.utils.timezone import now as timezone_now
|
||||
from typing_extensions import override
|
||||
|
||||
from analytics.lib.counts import COUNT_STATS, logger, process_count_stat
|
||||
from analytics.lib.counts import ALL_COUNT_STATS, logger, process_count_stat
|
||||
from scripts.lib.zulip_tools import ENDC, WARNING
|
||||
from zerver.lib.remote_server import send_analytics_to_push_bouncer
|
||||
from zerver.lib.remote_server import send_server_data_to_push_bouncer
|
||||
from zerver.lib.timestamp import floor_to_hour
|
||||
from zerver.models import Realm
|
||||
|
||||
@@ -74,9 +75,9 @@ class Command(BaseCommand):
|
||||
fill_to_time = floor_to_hour(fill_to_time.astimezone(timezone.utc))
|
||||
|
||||
if options["stat"] is not None:
|
||||
stats = [COUNT_STATS[options["stat"]]]
|
||||
stats = [ALL_COUNT_STATS[options["stat"]]]
|
||||
else:
|
||||
stats = list(COUNT_STATS.values())
|
||||
stats = list(ALL_COUNT_STATS.values())
|
||||
|
||||
logger.info("Starting updating analytics counts through %s", fill_to_time)
|
||||
if options["verbose"]:
|
||||
@@ -95,5 +96,14 @@ class Command(BaseCommand):
|
||||
)
|
||||
logger.info("Finished updating analytics counts through %s", fill_to_time)
|
||||
|
||||
if settings.PUSH_NOTIFICATION_BOUNCER_URL and settings.SUBMIT_USAGE_STATISTICS:
|
||||
send_analytics_to_push_bouncer()
|
||||
if settings.PUSH_NOTIFICATION_BOUNCER_URL:
|
||||
# Skew 0-10 minutes based on a hash of settings.ZULIP_ORG_ID, so
|
||||
# that each server will report in at a somewhat consistent time.
|
||||
assert settings.ZULIP_ORG_ID
|
||||
delay = int.from_bytes(
|
||||
hashlib.sha256(settings.ZULIP_ORG_ID.encode()).digest(), byteorder="big"
|
||||
) % (60 * 10)
|
||||
logger.info("Sleeping %d seconds before reporting...", delay)
|
||||
time.sleep(delay)
|
||||
|
||||
send_server_data_to_push_bouncer(consider_usage_statistics=True)
|
||||
|
||||
114
analytics/migrations/0017_regenerate_partial_indexes.py
Normal file
114
analytics/migrations/0017_regenerate_partial_indexes.py
Normal file
@@ -0,0 +1,114 @@
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("analytics", "0016_unique_constraint_when_subgroup_null"),
|
||||
]
|
||||
|
||||
# If the server was installed between 7.0 and 7.4 (or main between
|
||||
# 2c20028aa451 and 7807bff52635), it contains indexes which (when
|
||||
# running 7.5 or 7807bff52635 or higher) are never used, because
|
||||
# they contain an improper cast
|
||||
# (https://code.djangoproject.com/ticket/34840).
|
||||
#
|
||||
# We regenerate the indexes here, by dropping and re-creating
|
||||
# them, so that we know that they are properly formed.
|
||||
operations = [
|
||||
migrations.RemoveConstraint(
|
||||
model_name="installationcount",
|
||||
name="unique_installation_count",
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name="installationcount",
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(subgroup__isnull=False),
|
||||
fields=("property", "subgroup", "end_time"),
|
||||
name="unique_installation_count",
|
||||
),
|
||||
),
|
||||
migrations.RemoveConstraint(
|
||||
model_name="installationcount",
|
||||
name="unique_installation_count_null_subgroup",
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name="installationcount",
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(subgroup__isnull=True),
|
||||
fields=("property", "end_time"),
|
||||
name="unique_installation_count_null_subgroup",
|
||||
),
|
||||
),
|
||||
migrations.RemoveConstraint(
|
||||
model_name="realmcount",
|
||||
name="unique_realm_count",
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name="realmcount",
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(subgroup__isnull=False),
|
||||
fields=("realm", "property", "subgroup", "end_time"),
|
||||
name="unique_realm_count",
|
||||
),
|
||||
),
|
||||
migrations.RemoveConstraint(
|
||||
model_name="realmcount",
|
||||
name="unique_realm_count_null_subgroup",
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name="realmcount",
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(subgroup__isnull=True),
|
||||
fields=("realm", "property", "end_time"),
|
||||
name="unique_realm_count_null_subgroup",
|
||||
),
|
||||
),
|
||||
migrations.RemoveConstraint(
|
||||
model_name="streamcount",
|
||||
name="unique_stream_count",
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name="streamcount",
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(subgroup__isnull=False),
|
||||
fields=("stream", "property", "subgroup", "end_time"),
|
||||
name="unique_stream_count",
|
||||
),
|
||||
),
|
||||
migrations.RemoveConstraint(
|
||||
model_name="streamcount",
|
||||
name="unique_stream_count_null_subgroup",
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name="streamcount",
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(subgroup__isnull=True),
|
||||
fields=("stream", "property", "end_time"),
|
||||
name="unique_stream_count_null_subgroup",
|
||||
),
|
||||
),
|
||||
migrations.RemoveConstraint(
|
||||
model_name="usercount",
|
||||
name="unique_user_count",
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name="usercount",
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(subgroup__isnull=False),
|
||||
fields=("user", "property", "subgroup", "end_time"),
|
||||
name="unique_user_count",
|
||||
),
|
||||
),
|
||||
migrations.RemoveConstraint(
|
||||
model_name="usercount",
|
||||
name="unique_user_count_null_subgroup",
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name="usercount",
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(subgroup__isnull=True),
|
||||
fields=("user", "property", "end_time"),
|
||||
name="unique_user_count_null_subgroup",
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -1,7 +1,7 @@
|
||||
# https://github.com/typeddjango/django-stubs/issues/1698
|
||||
# mypy: disable-error-code="explicit-override"
|
||||
|
||||
import datetime
|
||||
from datetime import datetime
|
||||
|
||||
from django.db import models
|
||||
from django.db.models import Q, UniqueConstraint
|
||||
@@ -27,7 +27,7 @@ class FillState(models.Model):
|
||||
|
||||
# The earliest/starting end_time in FillState
|
||||
# We assume there is at least one realm
|
||||
def installation_epoch() -> datetime.datetime:
|
||||
def installation_epoch() -> datetime:
|
||||
earliest_realm_creation = Realm.objects.aggregate(models.Min("date_created"))[
|
||||
"date_created__min"
|
||||
]
|
||||
|
||||
@@ -1,9 +1,73 @@
|
||||
from datetime import timedelta
|
||||
from unittest import mock
|
||||
|
||||
from django.utils.timezone import now as timezone_now
|
||||
|
||||
from zerver.lib.test_classes import ZulipTestCase
|
||||
from zerver.models import Client, UserActivity, UserProfile
|
||||
from zilencer.models import RemoteRealmAuditLog, get_remote_server_guest_and_non_guest_count
|
||||
|
||||
event_time = timezone_now() - timedelta(days=3)
|
||||
data_list = [
|
||||
{
|
||||
"server_id": 1,
|
||||
"realm_id": 1,
|
||||
"event_type": RemoteRealmAuditLog.USER_CREATED,
|
||||
"event_time": event_time,
|
||||
"extra_data": {
|
||||
RemoteRealmAuditLog.ROLE_COUNT: {
|
||||
RemoteRealmAuditLog.ROLE_COUNT_HUMANS: {
|
||||
UserProfile.ROLE_REALM_ADMINISTRATOR: 10,
|
||||
UserProfile.ROLE_REALM_OWNER: 10,
|
||||
UserProfile.ROLE_MODERATOR: 10,
|
||||
UserProfile.ROLE_MEMBER: 10,
|
||||
UserProfile.ROLE_GUEST: 10,
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
"server_id": 1,
|
||||
"realm_id": 1,
|
||||
"event_type": RemoteRealmAuditLog.USER_ROLE_CHANGED,
|
||||
"event_time": event_time,
|
||||
"extra_data": {
|
||||
RemoteRealmAuditLog.ROLE_COUNT: {
|
||||
RemoteRealmAuditLog.ROLE_COUNT_HUMANS: {
|
||||
UserProfile.ROLE_REALM_ADMINISTRATOR: 20,
|
||||
UserProfile.ROLE_REALM_OWNER: 0,
|
||||
UserProfile.ROLE_MODERATOR: 0,
|
||||
UserProfile.ROLE_MEMBER: 20,
|
||||
UserProfile.ROLE_GUEST: 10,
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
"server_id": 1,
|
||||
"realm_id": 2,
|
||||
"event_type": RemoteRealmAuditLog.USER_CREATED,
|
||||
"event_time": event_time,
|
||||
"extra_data": {
|
||||
RemoteRealmAuditLog.ROLE_COUNT: {
|
||||
RemoteRealmAuditLog.ROLE_COUNT_HUMANS: {
|
||||
UserProfile.ROLE_REALM_ADMINISTRATOR: 10,
|
||||
UserProfile.ROLE_REALM_OWNER: 10,
|
||||
UserProfile.ROLE_MODERATOR: 0,
|
||||
UserProfile.ROLE_MEMBER: 10,
|
||||
UserProfile.ROLE_GUEST: 5,
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
"server_id": 1,
|
||||
"realm_id": 2,
|
||||
"event_type": RemoteRealmAuditLog.USER_CREATED,
|
||||
"event_time": event_time,
|
||||
"extra_data": {},
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
class ActivityTest(ZulipTestCase):
|
||||
@@ -31,11 +95,12 @@ class ActivityTest(ZulipTestCase):
|
||||
user_profile.is_staff = True
|
||||
user_profile.save(update_fields=["is_staff"])
|
||||
|
||||
with self.assert_database_query_count(12):
|
||||
with self.assert_database_query_count(11):
|
||||
result = self.client_get("/activity")
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
with self.assert_database_query_count(4):
|
||||
RemoteRealmAuditLog.objects.bulk_create([RemoteRealmAuditLog(**data) for data in data_list])
|
||||
with self.assert_database_query_count(6):
|
||||
result = self.client_get("/activity/remote")
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
@@ -51,3 +116,12 @@ class ActivityTest(ZulipTestCase):
|
||||
with self.assert_database_query_count(5):
|
||||
result = self.client_get(f"/user_activity/{iago.id}/")
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
def test_get_remote_server_guest_and_non_guest_count(self) -> None:
|
||||
RemoteRealmAuditLog.objects.bulk_create([RemoteRealmAuditLog(**data) for data in data_list])
|
||||
|
||||
remote_server_counts = get_remote_server_guest_and_non_guest_count(
|
||||
server_id=1, event_time=timezone_now()
|
||||
)
|
||||
self.assertEqual(remote_server_counts.non_guest_user_count, 70)
|
||||
self.assertEqual(remote_server_counts.guest_user_count, 15)
|
||||
|
||||
@@ -3,9 +3,11 @@ from typing import Any, Dict, List, Optional, Tuple, Type
|
||||
from unittest import mock
|
||||
|
||||
import orjson
|
||||
import time_machine
|
||||
from django.apps import apps
|
||||
from django.db import models
|
||||
from django.db.models import Sum
|
||||
from django.test import override_settings
|
||||
from django.utils.timezone import now as timezone_now
|
||||
from psycopg2.sql import SQL, Literal
|
||||
from typing_extensions import override
|
||||
@@ -53,19 +55,26 @@ from zerver.actions.user_activity import update_user_activity_interval
|
||||
from zerver.actions.users import do_deactivate_user
|
||||
from zerver.lib.create_user import create_user
|
||||
from zerver.lib.exceptions import InvitationError
|
||||
from zerver.lib.push_notifications import (
|
||||
get_message_payload_apns,
|
||||
get_message_payload_gcm,
|
||||
hex_to_b64,
|
||||
)
|
||||
from zerver.lib.test_classes import ZulipTestCase
|
||||
from zerver.lib.timestamp import TimeZoneNotUTCError, floor_to_day
|
||||
from zerver.lib.timestamp import TimeZoneNotUTCError, ceiling_to_day, floor_to_day
|
||||
from zerver.lib.topic import DB_TOPIC_NAME
|
||||
from zerver.lib.utils import assert_is_not_none
|
||||
from zerver.models import (
|
||||
Client,
|
||||
Huddle,
|
||||
Message,
|
||||
NotificationTriggers,
|
||||
PreregistrationUser,
|
||||
Realm,
|
||||
RealmAuditLog,
|
||||
Recipient,
|
||||
Stream,
|
||||
SystemGroups,
|
||||
UserActivityInterval,
|
||||
UserGroup,
|
||||
UserProfile,
|
||||
@@ -73,6 +82,14 @@ from zerver.models import (
|
||||
get_user,
|
||||
is_cross_realm_bot_email,
|
||||
)
|
||||
from zilencer.models import (
|
||||
RemoteInstallationCount,
|
||||
RemotePushDeviceToken,
|
||||
RemoteRealm,
|
||||
RemoteRealmCount,
|
||||
RemoteZulipServer,
|
||||
)
|
||||
from zilencer.views import get_last_id_from_server
|
||||
|
||||
|
||||
class AnalyticsTestCase(ZulipTestCase):
|
||||
@@ -89,7 +106,9 @@ class AnalyticsTestCase(ZulipTestCase):
|
||||
string_id="realmtest", name="Realm Test", date_created=self.TIME_ZERO - 2 * self.DAY
|
||||
)
|
||||
self.administrators_user_group = UserGroup.objects.get(
|
||||
name=UserGroup.ADMINISTRATORS_GROUP_NAME, realm=self.default_realm, is_system_group=True
|
||||
name=SystemGroups.ADMINISTRATORS,
|
||||
realm=self.default_realm,
|
||||
is_system_group=True,
|
||||
)
|
||||
|
||||
# used to generate unique names in self.create_*
|
||||
@@ -97,6 +116,10 @@ class AnalyticsTestCase(ZulipTestCase):
|
||||
# used as defaults in self.assert_table_count
|
||||
self.current_property: Optional[str] = None
|
||||
|
||||
# Delete RemoteRealm registrations to have a clean slate - the relevant
|
||||
# tests want to construct this from scratch.
|
||||
RemoteRealm.objects.all().delete()
|
||||
|
||||
# Lightweight creation of users, streams, and messages
|
||||
def create_user(self, **kwargs: Any) -> UserProfile:
|
||||
self.name_counter += 1
|
||||
@@ -111,7 +134,7 @@ class AnalyticsTestCase(ZulipTestCase):
|
||||
for key, value in defaults.items():
|
||||
kwargs[key] = kwargs.get(key, value)
|
||||
kwargs["delivery_email"] = kwargs["email"]
|
||||
with mock.patch("zerver.lib.create_user.timezone_now", return_value=kwargs["date_joined"]):
|
||||
with time_machine.travel(kwargs["date_joined"], tick=False):
|
||||
pass_kwargs: Dict[str, Any] = {}
|
||||
if kwargs["is_bot"]:
|
||||
pass_kwargs["bot_type"] = UserProfile.DEFAULT_BOT
|
||||
@@ -231,7 +254,10 @@ class AnalyticsTestCase(ZulipTestCase):
|
||||
kwargs[arg_keys[i]] = values[i]
|
||||
for key, value in defaults.items():
|
||||
kwargs[key] = kwargs.get(key, value)
|
||||
if table is not InstallationCount and "realm" not in kwargs:
|
||||
if (
|
||||
table not in [InstallationCount, RemoteInstallationCount, RemoteRealmCount]
|
||||
and "realm" not in kwargs
|
||||
):
|
||||
if "user" in kwargs:
|
||||
kwargs["realm"] = kwargs["user"].realm
|
||||
elif "stream" in kwargs:
|
||||
@@ -1372,6 +1398,249 @@ class TestLoggingCountStats(AnalyticsTestCase):
|
||||
],
|
||||
)
|
||||
|
||||
@override_settings(PUSH_NOTIFICATION_BOUNCER_URL="https://push.zulip.org.example.com")
|
||||
def test_mobile_pushes_received_count(self) -> None:
|
||||
self.server_uuid = "6cde5f7a-1f7e-4978-9716-49f69ebfc9fe"
|
||||
self.server = RemoteZulipServer.objects.create(
|
||||
uuid=self.server_uuid,
|
||||
api_key="magic_secret_api_key",
|
||||
hostname="demo.example.com",
|
||||
last_updated=timezone_now(),
|
||||
)
|
||||
|
||||
hamlet = self.example_user("hamlet")
|
||||
token = "aaaa"
|
||||
|
||||
RemotePushDeviceToken.objects.create(
|
||||
kind=RemotePushDeviceToken.GCM,
|
||||
token=hex_to_b64(token),
|
||||
user_uuid=(hamlet.uuid),
|
||||
server=self.server,
|
||||
)
|
||||
RemotePushDeviceToken.objects.create(
|
||||
kind=RemotePushDeviceToken.GCM,
|
||||
token=hex_to_b64(token + "aa"),
|
||||
user_uuid=(hamlet.uuid),
|
||||
server=self.server,
|
||||
)
|
||||
RemotePushDeviceToken.objects.create(
|
||||
kind=RemotePushDeviceToken.APNS,
|
||||
token=hex_to_b64(token),
|
||||
user_uuid=str(hamlet.uuid),
|
||||
server=self.server,
|
||||
)
|
||||
|
||||
message = Message(
|
||||
sender=hamlet,
|
||||
recipient=self.example_user("othello").recipient,
|
||||
realm_id=hamlet.realm_id,
|
||||
content="This is test content",
|
||||
rendered_content="This is test content",
|
||||
date_sent=timezone_now(),
|
||||
sending_client=get_client("test"),
|
||||
)
|
||||
message.set_topic_name("Test topic")
|
||||
message.save()
|
||||
gcm_payload, gcm_options = get_message_payload_gcm(hamlet, message)
|
||||
apns_payload = get_message_payload_apns(
|
||||
hamlet, message, NotificationTriggers.DIRECT_MESSAGE
|
||||
)
|
||||
|
||||
# First we'll make a request without providing realm_uuid. That means
|
||||
# the bouncer can't increment the RemoteRealmCount stat, and only
|
||||
# RemoteInstallationCount will be incremented.
|
||||
payload = {
|
||||
"user_id": hamlet.id,
|
||||
"user_uuid": str(hamlet.uuid),
|
||||
"gcm_payload": gcm_payload,
|
||||
"apns_payload": apns_payload,
|
||||
"gcm_options": gcm_options,
|
||||
}
|
||||
now = timezone_now()
|
||||
with time_machine.travel(now, tick=False), mock.patch(
|
||||
"zilencer.views.send_android_push_notification", return_value=1
|
||||
), mock.patch(
|
||||
"zilencer.views.send_apple_push_notification", return_value=1
|
||||
), self.assertLogs(
|
||||
"zilencer.views", level="INFO"
|
||||
):
|
||||
result = self.uuid_post(
|
||||
self.server_uuid,
|
||||
"/api/v1/remotes/push/notify",
|
||||
payload,
|
||||
content_type="application/json",
|
||||
subdomain="",
|
||||
)
|
||||
self.assert_json_success(result)
|
||||
|
||||
# There are 3 devices we created for the user:
|
||||
# 1. The mobile_pushes_received increment should match that number.
|
||||
# 2. mobile_pushes_forwarded only counts successful deliveries, and we've set up
|
||||
# the mocks above to simulate 1 successful android and 1 successful apple delivery.
|
||||
# Thus the increment should be just 2.
|
||||
self.assertTableState(
|
||||
RemoteInstallationCount,
|
||||
["property", "value", "subgroup", "server", "remote_id", "end_time"],
|
||||
[
|
||||
[
|
||||
"mobile_pushes_received::day",
|
||||
3,
|
||||
None,
|
||||
self.server,
|
||||
None,
|
||||
ceiling_to_day(now),
|
||||
],
|
||||
[
|
||||
"mobile_pushes_forwarded::day",
|
||||
2,
|
||||
None,
|
||||
self.server,
|
||||
None,
|
||||
ceiling_to_day(now),
|
||||
],
|
||||
],
|
||||
)
|
||||
self.assertFalse(
|
||||
RemoteRealmCount.objects.filter(property="mobile_pushes_received::day").exists()
|
||||
)
|
||||
self.assertFalse(
|
||||
RemoteRealmCount.objects.filter(property="mobile_pushes_forwarded::day").exists()
|
||||
)
|
||||
|
||||
# Now provide the realm_uuid. However, the RemoteRealm record doesn't exist yet, so it'll
|
||||
# still be ignored.
|
||||
payload = {
|
||||
"user_id": hamlet.id,
|
||||
"user_uuid": str(hamlet.uuid),
|
||||
"realm_uuid": str(hamlet.realm.uuid),
|
||||
"gcm_payload": gcm_payload,
|
||||
"apns_payload": apns_payload,
|
||||
"gcm_options": gcm_options,
|
||||
}
|
||||
with time_machine.travel(now, tick=False), mock.patch(
|
||||
"zilencer.views.send_android_push_notification", return_value=1
|
||||
), mock.patch(
|
||||
"zilencer.views.send_apple_push_notification", return_value=1
|
||||
), self.assertLogs(
|
||||
"zilencer.views", level="INFO"
|
||||
):
|
||||
result = self.uuid_post(
|
||||
self.server_uuid,
|
||||
"/api/v1/remotes/push/notify",
|
||||
payload,
|
||||
content_type="application/json",
|
||||
subdomain="",
|
||||
)
|
||||
self.assert_json_success(result)
|
||||
|
||||
# The RemoteInstallationCount records get incremented again, but the RemoteRealmCount
|
||||
# remains ignored due to missing RemoteRealm record.
|
||||
self.assertTableState(
|
||||
RemoteInstallationCount,
|
||||
["property", "value", "subgroup", "server", "remote_id", "end_time"],
|
||||
[
|
||||
[
|
||||
"mobile_pushes_received::day",
|
||||
6,
|
||||
None,
|
||||
self.server,
|
||||
None,
|
||||
ceiling_to_day(now),
|
||||
],
|
||||
[
|
||||
"mobile_pushes_forwarded::day",
|
||||
4,
|
||||
None,
|
||||
self.server,
|
||||
None,
|
||||
ceiling_to_day(now),
|
||||
],
|
||||
],
|
||||
)
|
||||
self.assertFalse(
|
||||
RemoteRealmCount.objects.filter(property="mobile_pushes_received::day").exists()
|
||||
)
|
||||
self.assertFalse(
|
||||
RemoteRealmCount.objects.filter(property="mobile_pushes_forwarded::day").exists()
|
||||
)
|
||||
|
||||
# Create the RemoteRealm registration and repeat the above. This time RemoteRealmCount
|
||||
# stats should be collected.
|
||||
realm = hamlet.realm
|
||||
remote_realm = RemoteRealm.objects.create(
|
||||
server=self.server,
|
||||
uuid=realm.uuid,
|
||||
uuid_owner_secret=realm.uuid_owner_secret,
|
||||
host=realm.host,
|
||||
realm_deactivated=realm.deactivated,
|
||||
realm_date_created=realm.date_created,
|
||||
)
|
||||
|
||||
with time_machine.travel(now, tick=False), mock.patch(
|
||||
"zilencer.views.send_android_push_notification", return_value=1
|
||||
), mock.patch(
|
||||
"zilencer.views.send_apple_push_notification", return_value=1
|
||||
), self.assertLogs(
|
||||
"zilencer.views", level="INFO"
|
||||
):
|
||||
result = self.uuid_post(
|
||||
self.server_uuid,
|
||||
"/api/v1/remotes/push/notify",
|
||||
payload,
|
||||
content_type="application/json",
|
||||
subdomain="",
|
||||
)
|
||||
self.assert_json_success(result)
|
||||
|
||||
# The RemoteInstallationCount records get incremented again, and the RemoteRealmCount
|
||||
# gets collected.
|
||||
self.assertTableState(
|
||||
RemoteInstallationCount,
|
||||
["property", "value", "subgroup", "server", "remote_id", "end_time"],
|
||||
[
|
||||
[
|
||||
"mobile_pushes_received::day",
|
||||
9,
|
||||
None,
|
||||
self.server,
|
||||
None,
|
||||
ceiling_to_day(now),
|
||||
],
|
||||
[
|
||||
"mobile_pushes_forwarded::day",
|
||||
6,
|
||||
None,
|
||||
self.server,
|
||||
None,
|
||||
ceiling_to_day(now),
|
||||
],
|
||||
],
|
||||
)
|
||||
self.assertTableState(
|
||||
RemoteRealmCount,
|
||||
["property", "value", "subgroup", "server", "remote_realm", "remote_id", "end_time"],
|
||||
[
|
||||
[
|
||||
"mobile_pushes_received::day",
|
||||
3,
|
||||
None,
|
||||
self.server,
|
||||
remote_realm,
|
||||
None,
|
||||
ceiling_to_day(now),
|
||||
],
|
||||
[
|
||||
"mobile_pushes_forwarded::day",
|
||||
2,
|
||||
None,
|
||||
self.server,
|
||||
remote_realm,
|
||||
None,
|
||||
ceiling_to_day(now),
|
||||
],
|
||||
],
|
||||
)
|
||||
|
||||
def test_invites_sent(self) -> None:
|
||||
property = "invites_sent::day"
|
||||
|
||||
@@ -1849,3 +2118,26 @@ class TestRealmActiveHumans(AnalyticsTestCase):
|
||||
1,
|
||||
)
|
||||
self.assertEqual(RealmCount.objects.filter(property="realm_active_humans::day").count(), 1)
|
||||
|
||||
|
||||
class GetLastIdFromServerTest(ZulipTestCase):
|
||||
def test_get_last_id_from_server_ignores_null(self) -> None:
|
||||
"""
|
||||
Verifies that get_last_id_from_server ignores null remote_ids, since this goes
|
||||
against the default Postgres ordering behavior, which treats nulls as the largest value.
|
||||
"""
|
||||
self.server_uuid = "6cde5f7a-1f7e-4978-9716-49f69ebfc9fe"
|
||||
self.server = RemoteZulipServer.objects.create(
|
||||
uuid=self.server_uuid,
|
||||
api_key="magic_secret_api_key",
|
||||
hostname="demo.example.com",
|
||||
last_updated=timezone_now(),
|
||||
)
|
||||
first = RemoteInstallationCount.objects.create(
|
||||
end_time=timezone_now(), server=self.server, property="test", value=1, remote_id=1
|
||||
)
|
||||
RemoteInstallationCount.objects.create(
|
||||
end_time=timezone_now(), server=self.server, property="test2", value=1, remote_id=None
|
||||
)
|
||||
result = get_last_id_from_server(self.server, RemoteInstallationCount)
|
||||
self.assertEqual(result, first.remote_id)
|
||||
|
||||
@@ -1,13 +1,21 @@
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
from decimal import Decimal
|
||||
from typing import TYPE_CHECKING, Any, Optional
|
||||
from unittest import mock
|
||||
|
||||
import orjson
|
||||
import time_machine
|
||||
from django.utils.timezone import now as timezone_now
|
||||
from typing_extensions import override
|
||||
|
||||
from corporate.lib.stripe import add_months, update_sponsorship_status
|
||||
from corporate.models import Customer, CustomerPlan, LicenseLedger, get_customer_by_realm
|
||||
from corporate.lib.stripe import RealmBillingSession, add_months
|
||||
from corporate.models import (
|
||||
Customer,
|
||||
CustomerPlan,
|
||||
LicenseLedger,
|
||||
get_current_plan_by_realm,
|
||||
get_customer_by_realm,
|
||||
)
|
||||
from zerver.actions.invites import do_create_multiuse_invite_link
|
||||
from zerver.actions.realm_settings import do_change_realm_org_type, do_send_realm_reactivation_email
|
||||
from zerver.actions.user_settings import do_change_user_setting
|
||||
@@ -22,6 +30,7 @@ from zerver.models import (
|
||||
get_org_type_display_name,
|
||||
get_realm,
|
||||
)
|
||||
from zilencer.lib.remote_counts import MissingDataError
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from django.test.client import _MonkeyPatchedWSGIResponse as TestHttpResponse
|
||||
@@ -62,8 +71,20 @@ class TestRemoteServerSupportEndpoint(ZulipTestCase):
|
||||
result,
|
||||
)
|
||||
|
||||
result = self.client_get("/activity/remote/support", {"q": "zulip-1.example.com"})
|
||||
with mock.patch("analytics.views.support.compute_max_monthly_messages", return_value=1000):
|
||||
result = self.client_get("/activity/remote/support", {"q": "zulip-1.example.com"})
|
||||
self.assert_in_success_response(["<h3>zulip-1.example.com</h3>"], result)
|
||||
self.assert_in_success_response(["<b>Max monthly messages</b>: 1000"], result)
|
||||
self.assert_not_in_success_response(["<h3>zulip-2.example.com</h3>"], result)
|
||||
|
||||
with mock.patch(
|
||||
"analytics.views.support.compute_max_monthly_messages", side_effect=MissingDataError
|
||||
):
|
||||
result = self.client_get("/activity/remote/support", {"q": "zulip-1.example.com"})
|
||||
self.assert_in_success_response(["<h3>zulip-1.example.com</h3>"], result)
|
||||
self.assert_in_success_response(
|
||||
["<b>Max monthly messages</b>: Recent data missing"], result
|
||||
)
|
||||
self.assert_not_in_success_response(["<h3>zulip-2.example.com</h3>"], result)
|
||||
|
||||
result = self.client_get("/activity/remote/support", {"q": "example.com"})
|
||||
@@ -177,7 +198,7 @@ class TestSupportEndpoint(ZulipTestCase):
|
||||
'<option value="deactivated" >Deactivated</option>',
|
||||
'scrub-realm-button">',
|
||||
'data-string-id="lear"',
|
||||
"<b>Name</b>: Zulip Cloud Standard",
|
||||
"<b>Plan name</b>: Zulip Cloud Standard",
|
||||
"<b>Status</b>: Active",
|
||||
"<b>Billing schedule</b>: Annual",
|
||||
"<b>Licenses</b>: 2/10 (Manual)",
|
||||
@@ -277,8 +298,8 @@ class TestSupportEndpoint(ZulipTestCase):
|
||||
plan = CustomerPlan.objects.create(
|
||||
customer=customer,
|
||||
billing_cycle_anchor=now,
|
||||
billing_schedule=CustomerPlan.ANNUAL,
|
||||
tier=CustomerPlan.STANDARD,
|
||||
billing_schedule=CustomerPlan.BILLING_SCHEDULE_ANNUAL,
|
||||
tier=CustomerPlan.TIER_CLOUD_STANDARD,
|
||||
price_per_license=8000,
|
||||
next_invoice_date=add_months(now, 12),
|
||||
)
|
||||
@@ -342,55 +363,56 @@ class TestSupportEndpoint(ZulipTestCase):
|
||||
check_zulip_realm_query_result(result)
|
||||
check_lear_realm_query_result(result)
|
||||
|
||||
with mock.patch(
|
||||
"analytics.views.support.timezone_now",
|
||||
return_value=timezone_now() - timedelta(minutes=50),
|
||||
):
|
||||
self.client_post("/accounts/home/", {"email": self.nonreg_email("test")})
|
||||
self.login("iago")
|
||||
result = get_check_query_result(self.nonreg_email("test"), 1)
|
||||
check_preregistration_user_query_result(result, self.nonreg_email("test"))
|
||||
check_zulip_realm_query_result(result)
|
||||
self.client_post("/accounts/home/", {"email": self.nonreg_email("test")})
|
||||
self.login("iago")
|
||||
|
||||
create_invitation("Denmark", self.nonreg_email("test1"))
|
||||
result = get_check_query_result(self.nonreg_email("test1"), 1)
|
||||
check_preregistration_user_query_result(result, self.nonreg_email("test1"), invite=True)
|
||||
check_zulip_realm_query_result(result)
|
||||
def query_result_from_before(*args: Any) -> "TestHttpResponse":
|
||||
with time_machine.travel((timezone_now() - timedelta(minutes=50)), tick=False):
|
||||
return get_check_query_result(*args)
|
||||
|
||||
email = self.nonreg_email("alice")
|
||||
self.submit_realm_creation_form(
|
||||
email, realm_subdomain="custom-test", realm_name="Zulip test"
|
||||
)
|
||||
result = get_check_query_result(email, 1)
|
||||
check_realm_creation_query_result(result, email)
|
||||
result = query_result_from_before(self.nonreg_email("test"), 1)
|
||||
check_preregistration_user_query_result(result, self.nonreg_email("test"))
|
||||
check_zulip_realm_query_result(result)
|
||||
|
||||
invite_expires_in_minutes = 10 * 24 * 60
|
||||
do_create_multiuse_invite_link(
|
||||
self.example_user("hamlet"),
|
||||
invited_as=1,
|
||||
invite_expires_in_minutes=invite_expires_in_minutes,
|
||||
)
|
||||
result = get_check_query_result("zulip", 2)
|
||||
check_multiuse_invite_link_query_result(result)
|
||||
check_zulip_realm_query_result(result)
|
||||
MultiuseInvite.objects.all().delete()
|
||||
create_invitation("Denmark", self.nonreg_email("test1"))
|
||||
result = query_result_from_before(self.nonreg_email("test1"), 1)
|
||||
check_preregistration_user_query_result(result, self.nonreg_email("test1"), invite=True)
|
||||
check_zulip_realm_query_result(result)
|
||||
|
||||
do_send_realm_reactivation_email(get_realm("zulip"), acting_user=None)
|
||||
result = get_check_query_result("zulip", 2)
|
||||
check_realm_reactivation_link_query_result(result)
|
||||
check_zulip_realm_query_result(result)
|
||||
email = self.nonreg_email("alice")
|
||||
self.submit_realm_creation_form(
|
||||
email, realm_subdomain="custom-test", realm_name="Zulip test"
|
||||
)
|
||||
result = query_result_from_before(email, 1)
|
||||
check_realm_creation_query_result(result, email)
|
||||
|
||||
lear_nonreg_email = "newguy@lear.org"
|
||||
self.client_post("/accounts/home/", {"email": lear_nonreg_email}, subdomain="lear")
|
||||
result = get_check_query_result(lear_nonreg_email, 1)
|
||||
check_preregistration_user_query_result(result, lear_nonreg_email)
|
||||
check_lear_realm_query_result(result)
|
||||
invite_expires_in_minutes = 10 * 24 * 60
|
||||
do_create_multiuse_invite_link(
|
||||
self.example_user("hamlet"),
|
||||
invited_as=1,
|
||||
invite_expires_in_minutes=invite_expires_in_minutes,
|
||||
)
|
||||
result = query_result_from_before("zulip", 2)
|
||||
check_multiuse_invite_link_query_result(result)
|
||||
check_zulip_realm_query_result(result)
|
||||
MultiuseInvite.objects.all().delete()
|
||||
|
||||
self.login_user(lear_user)
|
||||
create_invitation("general", "newguy2@lear.org", lear_realm)
|
||||
result = get_check_query_result("newguy2@lear.org", 1, lear_realm.string_id)
|
||||
check_preregistration_user_query_result(result, "newguy2@lear.org", invite=True)
|
||||
check_lear_realm_query_result(result)
|
||||
do_send_realm_reactivation_email(get_realm("zulip"), acting_user=None)
|
||||
result = query_result_from_before("zulip", 2)
|
||||
check_realm_reactivation_link_query_result(result)
|
||||
check_zulip_realm_query_result(result)
|
||||
|
||||
lear_nonreg_email = "newguy@lear.org"
|
||||
self.client_post("/accounts/home/", {"email": lear_nonreg_email}, subdomain="lear")
|
||||
result = query_result_from_before(lear_nonreg_email, 1)
|
||||
check_preregistration_user_query_result(result, lear_nonreg_email)
|
||||
check_lear_realm_query_result(result)
|
||||
|
||||
self.login_user(lear_user)
|
||||
create_invitation("general", "newguy2@lear.org", lear_realm)
|
||||
result = query_result_from_before("newguy2@lear.org", 1, lear_realm.string_id)
|
||||
check_preregistration_user_query_result(result, "newguy2@lear.org", invite=True)
|
||||
check_lear_realm_query_result(result)
|
||||
|
||||
def test_get_org_type_display_name(self) -> None:
|
||||
self.assertEqual(get_org_type_display_name(Realm.ORG_TYPES["business"]["id"]), "Business")
|
||||
@@ -418,38 +440,50 @@ class TestSupportEndpoint(ZulipTestCase):
|
||||
result,
|
||||
)
|
||||
|
||||
@mock.patch("analytics.views.support.update_billing_method_of_current_plan")
|
||||
def test_change_billing_method(self, m: mock.Mock) -> None:
|
||||
def test_change_billing_modality(self) -> None:
|
||||
realm = get_realm("zulip")
|
||||
cordelia = self.example_user("cordelia")
|
||||
self.login_user(cordelia)
|
||||
|
||||
result = self.client_post(
|
||||
"/activity/support", {"realm_id": f"{cordelia.realm_id}", "plan_type": "2"}
|
||||
"/activity/support",
|
||||
{"realm_id": f"{realm.id}", "billing_method": "charge_automatically"},
|
||||
)
|
||||
self.assertEqual(result.status_code, 302)
|
||||
self.assertEqual(result["Location"], "/login/")
|
||||
|
||||
customer = Customer.objects.create(realm=realm, stripe_customer_id="cus_12345")
|
||||
CustomerPlan.objects.create(
|
||||
customer=customer,
|
||||
status=CustomerPlan.ACTIVE,
|
||||
billing_cycle_anchor=timezone_now(),
|
||||
billing_schedule=CustomerPlan.BILLING_SCHEDULE_ANNUAL,
|
||||
tier=CustomerPlan.TIER_CLOUD_STANDARD,
|
||||
)
|
||||
|
||||
iago = self.example_user("iago")
|
||||
self.login_user(iago)
|
||||
|
||||
result = self.client_post(
|
||||
"/activity/support",
|
||||
{"realm_id": f"{iago.realm_id}", "billing_method": "charge_automatically"},
|
||||
{"realm_id": f"{realm.id}", "billing_modality": "charge_automatically"},
|
||||
)
|
||||
m.assert_called_once_with(get_realm("zulip"), charge_automatically=True, acting_user=iago)
|
||||
self.assert_in_success_response(
|
||||
["Billing method of zulip updated to charge automatically"], result
|
||||
["Billing collection method of zulip updated to charge automatically"], result
|
||||
)
|
||||
|
||||
m.reset_mock()
|
||||
plan = get_current_plan_by_realm(realm)
|
||||
assert plan is not None
|
||||
self.assertEqual(plan.charge_automatically, True)
|
||||
|
||||
result = self.client_post(
|
||||
"/activity/support", {"realm_id": f"{iago.realm_id}", "billing_method": "send_invoice"}
|
||||
"/activity/support", {"realm_id": f"{realm.id}", "billing_modality": "send_invoice"}
|
||||
)
|
||||
m.assert_called_once_with(get_realm("zulip"), charge_automatically=False, acting_user=iago)
|
||||
self.assert_in_success_response(
|
||||
["Billing method of zulip updated to pay by invoice"], result
|
||||
["Billing collection method of zulip updated to send invoice"], result
|
||||
)
|
||||
realm.refresh_from_db()
|
||||
plan = get_current_plan_by_realm(realm)
|
||||
assert plan is not None
|
||||
self.assertEqual(plan.charge_automatically, False)
|
||||
|
||||
def test_change_realm_plan_type(self) -> None:
|
||||
cordelia = self.example_user("cordelia")
|
||||
@@ -470,7 +504,7 @@ class TestSupportEndpoint(ZulipTestCase):
|
||||
)
|
||||
m.assert_called_once_with(get_realm("zulip"), 2, acting_user=iago)
|
||||
self.assert_in_success_response(
|
||||
["Plan type of zulip changed from self-hosted to limited"], result
|
||||
["Plan type of zulip changed from Self-hosted to Limited"], result
|
||||
)
|
||||
|
||||
with mock.patch("analytics.views.support.do_change_realm_plan_type") as m:
|
||||
@@ -479,7 +513,7 @@ class TestSupportEndpoint(ZulipTestCase):
|
||||
)
|
||||
m.assert_called_once_with(get_realm("zulip"), 10, acting_user=iago)
|
||||
self.assert_in_success_response(
|
||||
["Plan type of zulip changed from self-hosted to plus"], result
|
||||
["Plan type of zulip changed from Self-hosted to Plus"], result
|
||||
)
|
||||
|
||||
def test_change_org_type(self) -> None:
|
||||
@@ -516,14 +550,15 @@ class TestSupportEndpoint(ZulipTestCase):
|
||||
self.assertEqual(result["Location"], "/login/")
|
||||
|
||||
iago = self.example_user("iago")
|
||||
self.login("iago")
|
||||
self.login_user(iago)
|
||||
|
||||
with mock.patch("analytics.views.support.attach_discount_to_realm") as m:
|
||||
result = self.client_post(
|
||||
"/activity/support", {"realm_id": f"{lear_realm.id}", "discount": "25"}
|
||||
)
|
||||
m.assert_called_once_with(get_realm("lear"), 25, acting_user=iago)
|
||||
self.assert_in_success_response(["Discount of lear changed to 25% from 0%"], result)
|
||||
result = self.client_post(
|
||||
"/activity/support", {"realm_id": f"{lear_realm.id}", "discount": "25"}
|
||||
)
|
||||
self.assert_in_success_response(["Discount for lear changed to 25% from 0%"], result)
|
||||
customer = get_customer_by_realm(lear_realm)
|
||||
assert customer is not None
|
||||
self.assertEqual(customer.default_discount, Decimal(25))
|
||||
|
||||
def test_change_sponsorship_status(self) -> None:
|
||||
lear_realm = get_realm("lear")
|
||||
@@ -558,8 +593,12 @@ class TestSupportEndpoint(ZulipTestCase):
|
||||
self.assertFalse(customer.sponsorship_pending)
|
||||
|
||||
def test_approve_sponsorship(self) -> None:
|
||||
support_admin = self.example_user("iago")
|
||||
lear_realm = get_realm("lear")
|
||||
update_sponsorship_status(lear_realm, True, acting_user=None)
|
||||
billing_session = RealmBillingSession(
|
||||
user=support_admin, realm=lear_realm, support_session=True
|
||||
)
|
||||
billing_session.update_customer_sponsorship_status(True)
|
||||
king_user = self.lear_user("king")
|
||||
king_user.role = UserProfile.ROLE_REALM_OWNER
|
||||
king_user.save()
|
||||
@@ -674,73 +713,84 @@ class TestSupportEndpoint(ZulipTestCase):
|
||||
["Subdomain reserved. Please choose a different one."], result
|
||||
)
|
||||
|
||||
def test_downgrade_realm(self) -> None:
|
||||
def test_modify_plan_for_downgrade_at_end_of_billing_cycle(self) -> None:
|
||||
realm = get_realm("zulip")
|
||||
cordelia = self.example_user("cordelia")
|
||||
self.login_user(cordelia)
|
||||
result = self.client_post(
|
||||
"/activity/support", {"realm_id": f"{cordelia.realm_id}", "plan_type": "2"}
|
||||
"/activity/support",
|
||||
{"realm_id": f"{realm.id}", "modify_plan": "downgrade_at_billing_cycle_end"},
|
||||
)
|
||||
self.assertEqual(result.status_code, 302)
|
||||
self.assertEqual(result["Location"], "/login/")
|
||||
|
||||
customer = Customer.objects.create(realm=realm, stripe_customer_id="cus_12345")
|
||||
CustomerPlan.objects.create(
|
||||
customer=customer,
|
||||
status=CustomerPlan.ACTIVE,
|
||||
billing_cycle_anchor=timezone_now(),
|
||||
billing_schedule=CustomerPlan.BILLING_SCHEDULE_ANNUAL,
|
||||
tier=CustomerPlan.TIER_CLOUD_STANDARD,
|
||||
)
|
||||
|
||||
iago = self.example_user("iago")
|
||||
self.login_user(iago)
|
||||
|
||||
with mock.patch("analytics.views.support.downgrade_at_the_end_of_billing_cycle") as m:
|
||||
with self.assertLogs("corporate.stripe", "INFO") as m:
|
||||
result = self.client_post(
|
||||
"/activity/support",
|
||||
{
|
||||
"realm_id": f"{iago.realm_id}",
|
||||
"realm_id": f"{realm.id}",
|
||||
"modify_plan": "downgrade_at_billing_cycle_end",
|
||||
},
|
||||
)
|
||||
m.assert_called_once_with(get_realm("zulip"))
|
||||
self.assert_in_success_response(
|
||||
["zulip marked for downgrade at the end of billing cycle"], result
|
||||
)
|
||||
plan = get_current_plan_by_realm(realm)
|
||||
assert plan is not None
|
||||
self.assertEqual(plan.status, CustomerPlan.DOWNGRADE_AT_END_OF_CYCLE)
|
||||
expected_log = f"INFO:corporate.stripe:Change plan status: Customer.id: {customer.id}, CustomerPlan.id: {plan.id}, status: {CustomerPlan.DOWNGRADE_AT_END_OF_CYCLE}"
|
||||
self.assertEqual(m.output[0], expected_log)
|
||||
|
||||
with mock.patch(
|
||||
"analytics.views.support.downgrade_now_without_creating_additional_invoices"
|
||||
) as m:
|
||||
result = self.client_post(
|
||||
"/activity/support",
|
||||
{
|
||||
"realm_id": f"{iago.realm_id}",
|
||||
"modify_plan": "downgrade_now_without_additional_licenses",
|
||||
},
|
||||
)
|
||||
m.assert_called_once_with(get_realm("zulip"))
|
||||
self.assert_in_success_response(
|
||||
["zulip downgraded without creating additional invoices"], result
|
||||
)
|
||||
def test_modify_plan_for_downgrade_now_without_additional_licenses(self) -> None:
|
||||
realm = get_realm("zulip")
|
||||
cordelia = self.example_user("cordelia")
|
||||
self.login_user(cordelia)
|
||||
result = self.client_post(
|
||||
"/activity/support",
|
||||
{"realm_id": f"{realm.id}", "modify_plan": "downgrade_now_without_additional_licenses"},
|
||||
)
|
||||
self.assertEqual(result.status_code, 302)
|
||||
self.assertEqual(result["Location"], "/login/")
|
||||
|
||||
with mock.patch(
|
||||
"analytics.views.support.downgrade_now_without_creating_additional_invoices"
|
||||
) as m1:
|
||||
with mock.patch("analytics.views.support.void_all_open_invoices", return_value=1) as m2:
|
||||
result = self.client_post(
|
||||
"/activity/support",
|
||||
{
|
||||
"realm_id": f"{iago.realm_id}",
|
||||
"modify_plan": "downgrade_now_void_open_invoices",
|
||||
},
|
||||
)
|
||||
m1.assert_called_once_with(get_realm("zulip"))
|
||||
m2.assert_called_once_with(get_realm("zulip"))
|
||||
self.assert_in_success_response(
|
||||
["zulip downgraded and voided 1 open invoices"], result
|
||||
)
|
||||
customer = Customer.objects.create(realm=realm, stripe_customer_id="cus_12345")
|
||||
plan = CustomerPlan.objects.create(
|
||||
customer=customer,
|
||||
status=CustomerPlan.ACTIVE,
|
||||
billing_cycle_anchor=timezone_now(),
|
||||
billing_schedule=CustomerPlan.BILLING_SCHEDULE_ANNUAL,
|
||||
tier=CustomerPlan.TIER_CLOUD_STANDARD,
|
||||
)
|
||||
|
||||
with mock.patch("analytics.views.support.switch_realm_from_standard_to_plus_plan") as m:
|
||||
result = self.client_post(
|
||||
"/activity/support",
|
||||
{
|
||||
"realm_id": f"{iago.realm_id}",
|
||||
"modify_plan": "upgrade_to_plus",
|
||||
},
|
||||
)
|
||||
m.assert_called_once_with(get_realm("zulip"))
|
||||
self.assert_in_success_response(["zulip upgraded to Plus"], result)
|
||||
iago = self.example_user("iago")
|
||||
self.login_user(iago)
|
||||
|
||||
result = self.client_post(
|
||||
"/activity/support",
|
||||
{
|
||||
"realm_id": f"{iago.realm_id}",
|
||||
"modify_plan": "downgrade_now_without_additional_licenses",
|
||||
},
|
||||
)
|
||||
self.assert_in_success_response(
|
||||
["zulip downgraded without creating additional invoices"], result
|
||||
)
|
||||
|
||||
plan.refresh_from_db()
|
||||
self.assertEqual(plan.status, CustomerPlan.ENDED)
|
||||
realm.refresh_from_db()
|
||||
self.assertEqual(realm.plan_type, Realm.PLAN_TYPE_LIMITED)
|
||||
|
||||
def test_scrub_realm(self) -> None:
|
||||
cordelia = self.example_user("cordelia")
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from typing import List, Union
|
||||
|
||||
from django.conf import settings
|
||||
from django.conf.urls import include
|
||||
from django.urls import path
|
||||
from django.urls.resolvers import URLPattern, URLResolver
|
||||
@@ -9,43 +10,47 @@ from analytics.views.installation_activity import (
|
||||
get_integrations_activity,
|
||||
)
|
||||
from analytics.views.realm_activity import get_realm_activity
|
||||
from analytics.views.remote_activity import get_remote_server_activity
|
||||
from analytics.views.stats import (
|
||||
get_chart_data,
|
||||
get_chart_data_for_installation,
|
||||
get_chart_data_for_realm,
|
||||
get_chart_data_for_remote_installation,
|
||||
get_chart_data_for_remote_realm,
|
||||
get_chart_data_for_stream,
|
||||
stats,
|
||||
stats_for_installation,
|
||||
stats_for_realm,
|
||||
stats_for_remote_installation,
|
||||
stats_for_remote_realm,
|
||||
)
|
||||
from analytics.views.support import remote_servers_support, support
|
||||
from analytics.views.support import support
|
||||
from analytics.views.user_activity import get_user_activity
|
||||
from zerver.lib.rest import rest_path
|
||||
|
||||
i18n_urlpatterns: List[Union[URLPattern, URLResolver]] = [
|
||||
# Server admin (user_profile.is_staff) visible stats pages
|
||||
path("activity", get_installation_activity),
|
||||
path("activity/remote", get_remote_server_activity),
|
||||
path("activity/integrations", get_integrations_activity),
|
||||
path("activity/support", support, name="support"),
|
||||
path("activity/remote/support", remote_servers_support, name="remote_servers_support"),
|
||||
path("realm_activity/<realm_str>/", get_realm_activity),
|
||||
path("user_activity/<user_profile_id>/", get_user_activity),
|
||||
path("stats/realm/<realm_str>/", stats_for_realm),
|
||||
path("stats/installation", stats_for_installation),
|
||||
path("stats/remote/<int:remote_server_id>/installation", stats_for_remote_installation),
|
||||
path(
|
||||
"stats/remote/<int:remote_server_id>/realm/<int:remote_realm_id>/", stats_for_remote_realm
|
||||
),
|
||||
# User-visible stats page
|
||||
path("stats", stats, name="stats"),
|
||||
]
|
||||
|
||||
if settings.ZILENCER_ENABLED:
|
||||
from analytics.views.remote_activity import get_remote_server_activity
|
||||
from analytics.views.stats import stats_for_remote_installation, stats_for_remote_realm
|
||||
from analytics.views.support import remote_servers_support
|
||||
|
||||
i18n_urlpatterns += [
|
||||
path("activity/remote", get_remote_server_activity),
|
||||
path("stats/remote/<int:remote_server_id>/installation", stats_for_remote_installation),
|
||||
path(
|
||||
"stats/remote/<int:remote_server_id>/realm/<int:remote_realm_id>/",
|
||||
stats_for_remote_realm,
|
||||
),
|
||||
path("activity/remote/support", remote_servers_support, name="remote_servers_support"),
|
||||
]
|
||||
|
||||
# These endpoints are a part of the API (V1), which uses:
|
||||
# * REST verbs
|
||||
# * Basic auth (username:password is email:apiKey)
|
||||
@@ -60,16 +65,25 @@ v1_api_and_json_patterns = [
|
||||
rest_path("analytics/chart_data/stream/<stream_id>", GET=get_chart_data_for_stream),
|
||||
rest_path("analytics/chart_data/realm/<realm_str>", GET=get_chart_data_for_realm),
|
||||
rest_path("analytics/chart_data/installation", GET=get_chart_data_for_installation),
|
||||
rest_path(
|
||||
"analytics/chart_data/remote/<int:remote_server_id>/installation",
|
||||
GET=get_chart_data_for_remote_installation,
|
||||
),
|
||||
rest_path(
|
||||
"analytics/chart_data/remote/<int:remote_server_id>/realm/<int:remote_realm_id>",
|
||||
GET=get_chart_data_for_remote_realm,
|
||||
),
|
||||
]
|
||||
|
||||
if settings.ZILENCER_ENABLED:
|
||||
from analytics.views.stats import (
|
||||
get_chart_data_for_remote_installation,
|
||||
get_chart_data_for_remote_realm,
|
||||
)
|
||||
|
||||
v1_api_and_json_patterns += [
|
||||
rest_path(
|
||||
"analytics/chart_data/remote/<int:remote_server_id>/installation",
|
||||
GET=get_chart_data_for_remote_installation,
|
||||
),
|
||||
rest_path(
|
||||
"analytics/chart_data/remote/<int:remote_server_id>/realm/<int:remote_realm_id>",
|
||||
GET=get_chart_data_for_remote_realm,
|
||||
),
|
||||
]
|
||||
|
||||
i18n_urlpatterns += [
|
||||
path("api/v1/", include(v1_api_and_json_patterns)),
|
||||
path("json/", include(v1_api_and_json_patterns)),
|
||||
|
||||
@@ -12,8 +12,9 @@ from django.urls import reverse
|
||||
from markupsafe import Markup
|
||||
from psycopg2.sql import Composable
|
||||
|
||||
from zerver.lib.pysa import mark_sanitized
|
||||
from zerver.lib.url_encoding import append_url_query_string
|
||||
from zerver.models import UserActivity, get_realm
|
||||
from zerver.models import Realm, UserActivity
|
||||
|
||||
if sys.version_info < (3, 9): # nocoverage
|
||||
from backports import zoneinfo
|
||||
@@ -47,46 +48,22 @@ def make_table(
|
||||
return content
|
||||
|
||||
|
||||
def get_page(
|
||||
query: Composable, cols: Sequence[str], title: str, totals_columns: Sequence[int] = []
|
||||
) -> Dict[str, str]:
|
||||
def fix_rows(
|
||||
rows: List[List[Any]],
|
||||
i: int,
|
||||
fixup_func: Union[Callable[[str], Markup], Callable[[datetime], str]],
|
||||
) -> None:
|
||||
for row in rows:
|
||||
row[i] = fixup_func(row[i])
|
||||
|
||||
|
||||
def get_query_data(query: Composable) -> List[List[Any]]:
|
||||
cursor = connection.cursor()
|
||||
cursor.execute(query)
|
||||
rows = cursor.fetchall()
|
||||
rows = list(map(list, rows))
|
||||
cursor.close()
|
||||
|
||||
def fix_rows(
|
||||
i: int, fixup_func: Union[Callable[[str], Markup], Callable[[datetime], str]]
|
||||
) -> None:
|
||||
for row in rows:
|
||||
row[i] = fixup_func(row[i])
|
||||
|
||||
total_row = []
|
||||
for i, col in enumerate(cols):
|
||||
if col == "Realm":
|
||||
fix_rows(i, realm_activity_link)
|
||||
elif col in ["Last time", "Last visit"]:
|
||||
fix_rows(i, format_date_for_activity_reports)
|
||||
elif col == "Hostname":
|
||||
for row in rows:
|
||||
row[i] = remote_installation_stats_link(row[0], row[i])
|
||||
if len(totals_columns) > 0:
|
||||
if i == 0:
|
||||
total_row.append("Total")
|
||||
elif i in totals_columns:
|
||||
total_row.append(str(sum(row[i] for row in rows if row[i] is not None)))
|
||||
else:
|
||||
total_row.append("")
|
||||
if len(totals_columns) > 0:
|
||||
rows.insert(0, total_row)
|
||||
|
||||
content = make_table(title, cols, rows)
|
||||
|
||||
return dict(
|
||||
content=content,
|
||||
title=title,
|
||||
)
|
||||
return rows
|
||||
|
||||
|
||||
def dictfetchall(cursor: CursorWrapper) -> List[Dict[str, Any]]:
|
||||
@@ -127,21 +104,27 @@ def realm_support_link(realm_str: str) -> Markup:
|
||||
support_url = reverse("support")
|
||||
query = urlencode({"q": realm_str})
|
||||
url = append_url_query_string(support_url, query)
|
||||
return Markup('<a href="{url}">{realm_str}</a>').format(url=url, realm_str=realm_str)
|
||||
return Markup('<a href="{url}"><i class="fa fa-gear"></i></a>').format(url=url)
|
||||
|
||||
|
||||
def realm_url_link(realm_str: str) -> Markup:
|
||||
url = get_realm(realm_str).uri
|
||||
host = Realm.host_for_subdomain(realm_str)
|
||||
url = settings.EXTERNAL_URI_SCHEME + mark_sanitized(host)
|
||||
return Markup('<a href="{url}"><i class="fa fa-home"></i></a>').format(url=url)
|
||||
|
||||
|
||||
def remote_installation_stats_link(server_id: int, hostname: str) -> Markup:
|
||||
def remote_installation_stats_link(server_id: int) -> Markup:
|
||||
from analytics.views.stats import stats_for_remote_installation
|
||||
|
||||
url = reverse(stats_for_remote_installation, kwargs=dict(remote_server_id=server_id))
|
||||
return Markup('<a href="{url}"><i class="fa fa-pie-chart"></i></a> {hostname}').format(
|
||||
url=url, hostname=hostname
|
||||
)
|
||||
return Markup('<a href="{url}"><i class="fa fa-pie-chart"></i></a>').format(url=url)
|
||||
|
||||
|
||||
def remote_installation_support_link(hostname: str) -> Markup:
|
||||
support_url = reverse("remote_servers_support")
|
||||
query = urlencode({"q": hostname})
|
||||
url = append_url_query_string(support_url, query)
|
||||
return Markup('<a href="{url}"><i class="fa fa-gear"></i></a>').format(url=url)
|
||||
|
||||
|
||||
def get_user_activity_summary(records: Collection[UserActivity]) -> Dict[str, Any]:
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
import itertools
|
||||
import time
|
||||
from collections import defaultdict
|
||||
from contextlib import suppress
|
||||
from datetime import timedelta
|
||||
from typing import Dict, Optional, Tuple
|
||||
from typing import Dict, Optional
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import connection
|
||||
@@ -17,22 +13,24 @@ from psycopg2.sql import SQL
|
||||
from analytics.lib.counts import COUNT_STATS
|
||||
from analytics.views.activity_common import (
|
||||
dictfetchall,
|
||||
get_page,
|
||||
fix_rows,
|
||||
format_date_for_activity_reports,
|
||||
get_query_data,
|
||||
make_table,
|
||||
realm_activity_link,
|
||||
realm_stats_link,
|
||||
realm_support_link,
|
||||
realm_url_link,
|
||||
)
|
||||
from analytics.views.support import get_plan_name
|
||||
from analytics.views.support import get_plan_type_string
|
||||
from zerver.decorator import require_server_admin
|
||||
from zerver.lib.request import has_request_variables
|
||||
from zerver.lib.timestamp import timestamp_to_datetime
|
||||
from zerver.models import Realm, UserActivityInterval, get_org_type_display_name
|
||||
from zerver.models import Realm, get_org_type_display_name
|
||||
|
||||
if settings.BILLING_ENABLED:
|
||||
from corporate.lib.stripe import (
|
||||
from corporate.lib.analytics import (
|
||||
estimate_annual_recurring_revenue_by_realm,
|
||||
get_realms_to_default_discount_dict,
|
||||
get_realms_with_default_discount_dict,
|
||||
)
|
||||
|
||||
|
||||
@@ -92,7 +90,7 @@ def get_realm_day_counts() -> Dict[str, Dict[str, Markup]]:
|
||||
return result
|
||||
|
||||
|
||||
def realm_summary_table(realm_minutes: Dict[str, float]) -> str:
|
||||
def realm_summary_table() -> str:
|
||||
now = timezone_now()
|
||||
|
||||
query = SQL(
|
||||
@@ -203,10 +201,10 @@ def realm_summary_table(realm_minutes: Dict[str, float]) -> str:
|
||||
total_arr = 0
|
||||
if settings.BILLING_ENABLED:
|
||||
estimated_arrs = estimate_annual_recurring_revenue_by_realm()
|
||||
realms_to_default_discount = get_realms_to_default_discount_dict()
|
||||
realms_with_default_discount = get_realms_with_default_discount_dict()
|
||||
|
||||
for row in rows:
|
||||
row["plan_type_string"] = get_plan_name(row["plan_type"])
|
||||
row["plan_type_string"] = get_plan_type_string(row["plan_type"])
|
||||
|
||||
string_id = row["string_id"]
|
||||
|
||||
@@ -214,14 +212,14 @@ def realm_summary_table(realm_minutes: Dict[str, float]) -> str:
|
||||
row["arr"] = estimated_arrs[string_id]
|
||||
|
||||
if row["plan_type"] in [Realm.PLAN_TYPE_STANDARD, Realm.PLAN_TYPE_PLUS]:
|
||||
row["effective_rate"] = 100 - int(realms_to_default_discount.get(string_id, 0))
|
||||
row["effective_rate"] = 100 - int(realms_with_default_discount.get(string_id, 0))
|
||||
elif row["plan_type"] == Realm.PLAN_TYPE_STANDARD_FREE:
|
||||
row["effective_rate"] = 0
|
||||
elif (
|
||||
row["plan_type"] == Realm.PLAN_TYPE_LIMITED
|
||||
and string_id in realms_to_default_discount
|
||||
and string_id in realms_with_default_discount
|
||||
):
|
||||
row["effective_rate"] = 100 - int(realms_to_default_discount[string_id])
|
||||
row["effective_rate"] = 100 - int(realms_with_default_discount[string_id])
|
||||
else:
|
||||
row["effective_rate"] = ""
|
||||
|
||||
@@ -230,17 +228,6 @@ def realm_summary_table(realm_minutes: Dict[str, float]) -> str:
|
||||
for row in rows:
|
||||
row["org_type_string"] = get_org_type_display_name(row["org_type"])
|
||||
|
||||
# augment data with realm_minutes
|
||||
total_hours = 0.0
|
||||
for row in rows:
|
||||
string_id = row["string_id"]
|
||||
minutes = realm_minutes.get(string_id, 0.0)
|
||||
hours = minutes / 60.0
|
||||
total_hours += hours
|
||||
row["hours"] = str(int(hours))
|
||||
with suppress(Exception):
|
||||
row["hours_per_user"] = "{:.1f}".format(hours / row["dau_count"])
|
||||
|
||||
# formatting
|
||||
for row in rows:
|
||||
row["realm_url"] = realm_url_link(row["string_id"])
|
||||
@@ -275,7 +262,6 @@ def realm_summary_table(realm_minutes: Dict[str, float]) -> str:
|
||||
dau_count=total_dau_count,
|
||||
user_profile_count=total_user_profile_count,
|
||||
bot_count=total_bot_count,
|
||||
hours=int(total_hours),
|
||||
wau_count=total_wau_count,
|
||||
)
|
||||
|
||||
@@ -293,79 +279,16 @@ def realm_summary_table(realm_minutes: Dict[str, float]) -> str:
|
||||
return content
|
||||
|
||||
|
||||
def user_activity_intervals() -> Tuple[Markup, Dict[str, float]]:
|
||||
day_end = timestamp_to_datetime(time.time())
|
||||
day_start = day_end - timedelta(hours=24)
|
||||
|
||||
output = Markup()
|
||||
output += "Per-user online duration for the last 24 hours:\n"
|
||||
total_duration = timedelta(0)
|
||||
|
||||
all_intervals = (
|
||||
UserActivityInterval.objects.filter(
|
||||
end__gte=day_start,
|
||||
start__lte=day_end,
|
||||
)
|
||||
.select_related(
|
||||
"user_profile",
|
||||
"user_profile__realm",
|
||||
)
|
||||
.only(
|
||||
"start",
|
||||
"end",
|
||||
"user_profile__delivery_email",
|
||||
"user_profile__realm__string_id",
|
||||
)
|
||||
.order_by(
|
||||
"user_profile__realm__string_id",
|
||||
"user_profile__delivery_email",
|
||||
)
|
||||
)
|
||||
|
||||
by_string_id = lambda row: row.user_profile.realm.string_id
|
||||
by_email = lambda row: row.user_profile.delivery_email
|
||||
|
||||
realm_minutes = {}
|
||||
|
||||
for string_id, realm_intervals in itertools.groupby(all_intervals, by_string_id):
|
||||
realm_duration = timedelta(0)
|
||||
output += Markup("<hr>") + f"{string_id}\n"
|
||||
for email, intervals in itertools.groupby(realm_intervals, by_email):
|
||||
duration = timedelta(0)
|
||||
for interval in intervals:
|
||||
start = max(day_start, interval.start)
|
||||
end = min(day_end, interval.end)
|
||||
duration += end - start
|
||||
|
||||
total_duration += duration
|
||||
realm_duration += duration
|
||||
output += f" {email:<37}{duration}\n"
|
||||
|
||||
realm_minutes[string_id] = realm_duration.total_seconds() / 60
|
||||
|
||||
output += f"\nTotal duration: {total_duration}\n"
|
||||
output += f"\nTotal duration in minutes: {total_duration.total_seconds() / 60.}\n"
|
||||
output += f"Total duration amortized to a month: {total_duration.total_seconds() * 30. / 60.}"
|
||||
content = Markup("<pre>{}</pre>").format(output)
|
||||
return content, realm_minutes
|
||||
|
||||
|
||||
@require_server_admin
|
||||
@has_request_variables
|
||||
def get_installation_activity(request: HttpRequest) -> HttpResponse:
|
||||
duration_content, realm_minutes = user_activity_intervals()
|
||||
counts_content: str = realm_summary_table(realm_minutes)
|
||||
data = [
|
||||
("Counts", counts_content),
|
||||
("Durations", duration_content),
|
||||
]
|
||||
|
||||
title = "Activity"
|
||||
content: str = realm_summary_table()
|
||||
title = "Installation activity"
|
||||
|
||||
return render(
|
||||
request,
|
||||
"analytics/activity.html",
|
||||
context=dict(data=data, title=title, is_home=True),
|
||||
"analytics/activity_details_template.html",
|
||||
context=dict(data=content, title=title, is_home=True),
|
||||
)
|
||||
|
||||
|
||||
@@ -407,14 +330,20 @@ def get_integrations_activity(request: HttpRequest) -> HttpResponse:
|
||||
"Last time",
|
||||
]
|
||||
|
||||
integrations_activity = get_page(query, cols, title)
|
||||
rows = get_query_data(query)
|
||||
for i, col in enumerate(cols):
|
||||
if col == "Realm":
|
||||
fix_rows(rows, i, realm_activity_link)
|
||||
elif col == "Last time":
|
||||
fix_rows(rows, i, format_date_for_activity_reports)
|
||||
|
||||
content = make_table(title, cols, rows)
|
||||
return render(
|
||||
request,
|
||||
"analytics/activity_details_template.html",
|
||||
context=dict(
|
||||
data=integrations_activity["content"],
|
||||
title=integrations_activity["title"],
|
||||
data=content,
|
||||
title=title,
|
||||
is_home=False,
|
||||
),
|
||||
)
|
||||
|
||||
@@ -2,8 +2,16 @@ from django.http import HttpRequest, HttpResponse
|
||||
from django.shortcuts import render
|
||||
from psycopg2.sql import SQL
|
||||
|
||||
from analytics.views.activity_common import get_page
|
||||
from analytics.views.activity_common import (
|
||||
fix_rows,
|
||||
format_date_for_activity_reports,
|
||||
get_query_data,
|
||||
make_table,
|
||||
remote_installation_stats_link,
|
||||
remote_installation_support_link,
|
||||
)
|
||||
from zerver.decorator import require_server_admin
|
||||
from zilencer.models import get_remote_server_guest_and_non_guest_count
|
||||
|
||||
|
||||
@require_server_admin
|
||||
@@ -12,32 +20,56 @@ def get_remote_server_activity(request: HttpRequest) -> HttpResponse:
|
||||
|
||||
query = SQL(
|
||||
"""
|
||||
with icount as (
|
||||
with icount_id as (
|
||||
select
|
||||
server_id,
|
||||
max(value) as max_value,
|
||||
max(end_time) as max_end_time
|
||||
max(id) as max_count_id
|
||||
from zilencer_remoteinstallationcount
|
||||
where
|
||||
property='active_users:is_bot:day'
|
||||
and subgroup='false'
|
||||
group by server_id
|
||||
),
|
||||
),
|
||||
icount as (
|
||||
select
|
||||
icount_id.server_id,
|
||||
value as latest_value,
|
||||
end_time as latest_end_time
|
||||
from icount_id
|
||||
join zilencer_remoteinstallationcount
|
||||
on max_count_id = zilencer_remoteinstallationcount.id
|
||||
),
|
||||
mobile_push_forwarded_count as (
|
||||
select
|
||||
server_id,
|
||||
sum(coalesce(value, 0)) as push_forwarded_count
|
||||
from zilencer_remoteinstallationcount
|
||||
where
|
||||
property = 'mobile_pushes_forwarded::day'
|
||||
and end_time >= current_timestamp(0) - interval '7 days'
|
||||
group by server_id
|
||||
),
|
||||
remote_push_devices as (
|
||||
select server_id, count(distinct(user_id)) as push_user_count from zilencer_remotepushdevicetoken
|
||||
select
|
||||
server_id,
|
||||
count(distinct(user_id, user_uuid)) as push_user_count
|
||||
from zilencer_remotepushdevicetoken
|
||||
group by server_id
|
||||
)
|
||||
select
|
||||
rserver.id,
|
||||
rserver.hostname,
|
||||
rserver.contact_email,
|
||||
max_value,
|
||||
rserver.last_version,
|
||||
latest_value,
|
||||
push_user_count,
|
||||
max_end_time
|
||||
latest_end_time,
|
||||
push_forwarded_count
|
||||
from zilencer_remotezulipserver rserver
|
||||
left join icount on icount.server_id = rserver.id
|
||||
left join mobile_push_forwarded_count on mobile_push_forwarded_count.server_id = rserver.id
|
||||
left join remote_push_devices on remote_push_devices.server_id = rserver.id
|
||||
order by max_value DESC NULLS LAST, push_user_count DESC NULLS LAST
|
||||
order by latest_value DESC NULLS LAST, push_user_count DESC NULLS LAST
|
||||
"""
|
||||
)
|
||||
|
||||
@@ -45,15 +77,41 @@ def get_remote_server_activity(request: HttpRequest) -> HttpResponse:
|
||||
"ID",
|
||||
"Hostname",
|
||||
"Contact email",
|
||||
"Zulip version",
|
||||
"Analytics users",
|
||||
"Mobile users",
|
||||
"Last update time",
|
||||
"Mobile pushes forwarded",
|
||||
"Non guest users",
|
||||
"Guest users",
|
||||
"Links",
|
||||
]
|
||||
|
||||
remote_servers = get_page(query, cols, title, totals_columns=[3, 4])
|
||||
rows = get_query_data(query)
|
||||
total_row = []
|
||||
totals_columns = [4, 5]
|
||||
for row in rows:
|
||||
stats = remote_installation_stats_link(row[0])
|
||||
support = remote_installation_support_link(row[1])
|
||||
links = stats + " " + support
|
||||
remote_server_counts = get_remote_server_guest_and_non_guest_count(row[0])
|
||||
row.append(remote_server_counts.non_guest_user_count)
|
||||
row.append(remote_server_counts.guest_user_count)
|
||||
row.append(links)
|
||||
for i, col in enumerate(cols):
|
||||
if col == "Last update time":
|
||||
fix_rows(rows, i, format_date_for_activity_reports)
|
||||
if i == 0:
|
||||
total_row.append("Total")
|
||||
elif i in totals_columns:
|
||||
total_row.append(str(sum(row[i] for row in rows if row[i] is not None)))
|
||||
else:
|
||||
total_row.append("")
|
||||
rows.insert(0, total_row)
|
||||
|
||||
content = make_table(title, cols, rows)
|
||||
return render(
|
||||
request,
|
||||
"analytics/activity_details_template.html",
|
||||
context=dict(data=remote_servers["content"], title=remote_servers["title"], is_home=False),
|
||||
context=dict(data=content, title=title, is_home=False),
|
||||
)
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import urllib
|
||||
from contextlib import suppress
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
from decimal import Decimal
|
||||
from typing import Any, Dict, Iterable, List, Optional
|
||||
from urllib.parse import urlencode
|
||||
from typing import Any, Dict, Iterable, List, Optional, Union
|
||||
from urllib.parse import urlencode, urlsplit
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ValidationError
|
||||
@@ -49,37 +47,36 @@ from zerver.models import (
|
||||
from zerver.views.invite import get_invitee_emails_set
|
||||
|
||||
if settings.ZILENCER_ENABLED:
|
||||
from zilencer.models import RemoteZulipServer
|
||||
from zilencer.lib.remote_counts import MissingDataError, compute_max_monthly_messages
|
||||
from zilencer.models import RemoteRealm, RemoteZulipServer
|
||||
|
||||
if settings.BILLING_ENABLED:
|
||||
from corporate.lib.stripe import approve_sponsorship as do_approve_sponsorship
|
||||
from corporate.lib.stripe import (
|
||||
attach_discount_to_realm,
|
||||
downgrade_at_the_end_of_billing_cycle,
|
||||
downgrade_now_without_creating_additional_invoices,
|
||||
get_discount_for_realm,
|
||||
get_latest_seat_count,
|
||||
make_end_of_cycle_updates_if_needed,
|
||||
switch_realm_from_standard_to_plus_plan,
|
||||
update_billing_method_of_current_plan,
|
||||
update_sponsorship_status,
|
||||
void_all_open_invoices,
|
||||
RealmBillingSession,
|
||||
RemoteRealmBillingSession,
|
||||
RemoteServerBillingSession,
|
||||
SupportType,
|
||||
SupportViewRequest,
|
||||
)
|
||||
from corporate.models import (
|
||||
Customer,
|
||||
CustomerPlan,
|
||||
get_current_plan_by_realm,
|
||||
get_customer_by_realm,
|
||||
from corporate.lib.support import (
|
||||
PlanData,
|
||||
get_current_plan_data_for_support_view,
|
||||
get_customer_discount_for_support_view,
|
||||
)
|
||||
from corporate.models import CustomerPlan
|
||||
|
||||
|
||||
def get_plan_name(plan_type: int) -> str:
|
||||
def get_plan_type_string(plan_type: int) -> str:
|
||||
return {
|
||||
Realm.PLAN_TYPE_SELF_HOSTED: "self-hosted",
|
||||
Realm.PLAN_TYPE_LIMITED: "limited",
|
||||
Realm.PLAN_TYPE_STANDARD: "standard",
|
||||
Realm.PLAN_TYPE_STANDARD_FREE: "open source",
|
||||
Realm.PLAN_TYPE_PLUS: "plus",
|
||||
Realm.PLAN_TYPE_SELF_HOSTED: "Self-hosted",
|
||||
Realm.PLAN_TYPE_LIMITED: "Limited",
|
||||
Realm.PLAN_TYPE_STANDARD: "Standard",
|
||||
Realm.PLAN_TYPE_STANDARD_FREE: "Standard free",
|
||||
Realm.PLAN_TYPE_PLUS: "Plus",
|
||||
RemoteZulipServer.PLAN_TYPE_SELF_HOSTED: "Self-hosted",
|
||||
RemoteZulipServer.PLAN_TYPE_COMMUNITY: "Community",
|
||||
RemoteZulipServer.PLAN_TYPE_BUSINESS: "Business",
|
||||
RemoteZulipServer.PLAN_TYPE_ENTERPRISE: "Enterprise",
|
||||
}[plan_type]
|
||||
|
||||
|
||||
@@ -132,7 +129,7 @@ VALID_MODIFY_PLAN_METHODS = [
|
||||
"downgrade_at_billing_cycle_end",
|
||||
"downgrade_now_without_additional_licenses",
|
||||
"downgrade_now_void_open_invoices",
|
||||
"upgrade_to_plus",
|
||||
"upgrade_plan_tier",
|
||||
]
|
||||
|
||||
VALID_STATUS_VALUES = [
|
||||
@@ -140,20 +137,12 @@ VALID_STATUS_VALUES = [
|
||||
"deactivated",
|
||||
]
|
||||
|
||||
VALID_BILLING_METHODS = [
|
||||
VALID_BILLING_MODALITY_VALUES = [
|
||||
"send_invoice",
|
||||
"charge_automatically",
|
||||
]
|
||||
|
||||
|
||||
@dataclass
|
||||
class PlanData:
|
||||
customer: Optional["Customer"] = None
|
||||
current_plan: Optional["CustomerPlan"] = None
|
||||
licenses: Optional[int] = None
|
||||
licenses_used: Optional[int] = None
|
||||
|
||||
|
||||
@require_server_admin
|
||||
@has_request_variables
|
||||
def support(
|
||||
@@ -163,8 +152,8 @@ def support(
|
||||
discount: Optional[Decimal] = REQ(default=None, converter=to_decimal),
|
||||
new_subdomain: Optional[str] = REQ(default=None),
|
||||
status: Optional[str] = REQ(default=None, str_validator=check_string_in(VALID_STATUS_VALUES)),
|
||||
billing_method: Optional[str] = REQ(
|
||||
default=None, str_validator=check_string_in(VALID_BILLING_METHODS)
|
||||
billing_modality: Optional[str] = REQ(
|
||||
default=None, str_validator=check_string_in(VALID_BILLING_MODALITY_VALUES)
|
||||
),
|
||||
sponsorship_pending: Optional[bool] = REQ(default=None, json_validator=check_bool),
|
||||
approve_sponsorship: bool = REQ(default=False, json_validator=check_bool),
|
||||
@@ -182,6 +171,8 @@ def support(
|
||||
context["success_message"] = request.session["success_message"]
|
||||
del request.session["success_message"]
|
||||
|
||||
acting_user = request.user
|
||||
assert isinstance(acting_user, UserProfile)
|
||||
if settings.BILLING_ENABLED and request.method == "POST":
|
||||
# We check that request.POST only has two keys in it: The
|
||||
# realm_id and a field to change.
|
||||
@@ -194,24 +185,42 @@ def support(
|
||||
assert realm_id is not None
|
||||
realm = Realm.objects.get(id=realm_id)
|
||||
|
||||
acting_user = request.user
|
||||
assert isinstance(acting_user, UserProfile)
|
||||
if plan_type is not None:
|
||||
support_view_request = None
|
||||
|
||||
if approve_sponsorship:
|
||||
support_view_request = SupportViewRequest(support_type=SupportType.approve_sponsorship)
|
||||
elif sponsorship_pending is not None:
|
||||
support_view_request = SupportViewRequest(
|
||||
support_type=SupportType.update_sponsorship_status,
|
||||
sponsorship_status=sponsorship_pending,
|
||||
)
|
||||
elif discount is not None:
|
||||
support_view_request = SupportViewRequest(
|
||||
support_type=SupportType.attach_discount,
|
||||
discount=discount,
|
||||
)
|
||||
elif billing_modality is not None:
|
||||
support_view_request = SupportViewRequest(
|
||||
support_type=SupportType.update_billing_modality,
|
||||
billing_modality=billing_modality,
|
||||
)
|
||||
elif modify_plan is not None:
|
||||
support_view_request = SupportViewRequest(
|
||||
support_type=SupportType.modify_plan,
|
||||
plan_modification=modify_plan,
|
||||
)
|
||||
if modify_plan == "upgrade_plan_tier":
|
||||
support_view_request["new_plan_tier"] = CustomerPlan.TIER_CLOUD_PLUS
|
||||
elif plan_type is not None:
|
||||
current_plan_type = realm.plan_type
|
||||
do_change_realm_plan_type(realm, plan_type, acting_user=acting_user)
|
||||
msg = f"Plan type of {realm.string_id} changed from {get_plan_name(current_plan_type)} to {get_plan_name(plan_type)} "
|
||||
msg = f"Plan type of {realm.string_id} changed from {get_plan_type_string(current_plan_type)} to {get_plan_type_string(plan_type)} "
|
||||
context["success_message"] = msg
|
||||
elif org_type is not None:
|
||||
current_realm_type = realm.org_type
|
||||
do_change_realm_org_type(realm, org_type, acting_user=acting_user)
|
||||
msg = f"Org type of {realm.string_id} changed from {get_org_type_display_name(current_realm_type)} to {get_org_type_display_name(org_type)} "
|
||||
context["success_message"] = msg
|
||||
elif discount is not None:
|
||||
current_discount = get_discount_for_realm(realm) or 0
|
||||
attach_discount_to_realm(realm, discount, acting_user=acting_user)
|
||||
context[
|
||||
"success_message"
|
||||
] = f"Discount of {realm.string_id} changed to {discount}% from {current_discount}%."
|
||||
elif new_subdomain is not None:
|
||||
old_subdomain = realm.string_id
|
||||
try:
|
||||
@@ -235,51 +244,6 @@ def support(
|
||||
elif status == "deactivated":
|
||||
do_deactivate_realm(realm, acting_user=acting_user)
|
||||
context["success_message"] = f"{realm.string_id} deactivated."
|
||||
elif billing_method is not None:
|
||||
if billing_method == "send_invoice":
|
||||
update_billing_method_of_current_plan(
|
||||
realm, charge_automatically=False, acting_user=acting_user
|
||||
)
|
||||
context[
|
||||
"success_message"
|
||||
] = f"Billing method of {realm.string_id} updated to pay by invoice."
|
||||
elif billing_method == "charge_automatically":
|
||||
update_billing_method_of_current_plan(
|
||||
realm, charge_automatically=True, acting_user=acting_user
|
||||
)
|
||||
context[
|
||||
"success_message"
|
||||
] = f"Billing method of {realm.string_id} updated to charge automatically."
|
||||
elif sponsorship_pending is not None:
|
||||
if sponsorship_pending:
|
||||
update_sponsorship_status(realm, True, acting_user=acting_user)
|
||||
context["success_message"] = f"{realm.string_id} marked as pending sponsorship."
|
||||
else:
|
||||
update_sponsorship_status(realm, False, acting_user=acting_user)
|
||||
context["success_message"] = f"{realm.string_id} is no longer pending sponsorship."
|
||||
elif approve_sponsorship:
|
||||
do_approve_sponsorship(realm, acting_user=acting_user)
|
||||
context["success_message"] = f"Sponsorship approved for {realm.string_id}"
|
||||
elif modify_plan is not None:
|
||||
if modify_plan == "downgrade_at_billing_cycle_end":
|
||||
downgrade_at_the_end_of_billing_cycle(realm)
|
||||
context[
|
||||
"success_message"
|
||||
] = f"{realm.string_id} marked for downgrade at the end of billing cycle"
|
||||
elif modify_plan == "downgrade_now_without_additional_licenses":
|
||||
downgrade_now_without_creating_additional_invoices(realm)
|
||||
context[
|
||||
"success_message"
|
||||
] = f"{realm.string_id} downgraded without creating additional invoices"
|
||||
elif modify_plan == "downgrade_now_void_open_invoices":
|
||||
downgrade_now_without_creating_additional_invoices(realm)
|
||||
voided_invoices_count = void_all_open_invoices(realm)
|
||||
context[
|
||||
"success_message"
|
||||
] = f"{realm.string_id} downgraded and voided {voided_invoices_count} open invoices"
|
||||
elif modify_plan == "upgrade_to_plus":
|
||||
switch_realm_from_standard_to_plus_plan(realm)
|
||||
context["success_message"] = f"{realm.string_id} upgraded to Plus"
|
||||
elif scrub_realm:
|
||||
do_scrub_realm(realm, acting_user=acting_user)
|
||||
context["success_message"] = f"{realm.string_id} scrubbed."
|
||||
@@ -290,6 +254,13 @@ def support(
|
||||
do_delete_user_preserving_messages(user_profile_for_deletion)
|
||||
context["success_message"] = f"{user_email} in {realm.subdomain} deleted."
|
||||
|
||||
if support_view_request is not None:
|
||||
billing_session = RealmBillingSession(
|
||||
user=acting_user, realm=realm, support_session=True
|
||||
)
|
||||
success_message = billing_session.process_support_view_request(support_view_request)
|
||||
context["success_message"] = success_message
|
||||
|
||||
if query:
|
||||
key_words = get_invitee_emails_set(query)
|
||||
|
||||
@@ -302,7 +273,7 @@ def support(
|
||||
for key_word in key_words:
|
||||
try:
|
||||
URLValidator()(key_word)
|
||||
parse_result = urllib.parse.urlparse(key_word)
|
||||
parse_result = urlsplit(key_word)
|
||||
hostname = parse_result.hostname
|
||||
assert hostname is not None
|
||||
if parse_result.port:
|
||||
@@ -366,22 +337,9 @@ def support(
|
||||
)
|
||||
plan_data: Dict[int, PlanData] = {}
|
||||
for realm in all_realms:
|
||||
current_plan = get_current_plan_by_realm(realm)
|
||||
plan_data[realm.id] = PlanData(
|
||||
customer=get_customer_by_realm(realm),
|
||||
current_plan=current_plan,
|
||||
)
|
||||
if current_plan is not None:
|
||||
new_plan, last_ledger_entry = make_end_of_cycle_updates_if_needed(
|
||||
current_plan, timezone_now()
|
||||
)
|
||||
if last_ledger_entry is not None:
|
||||
if new_plan is not None:
|
||||
plan_data[realm.id].current_plan = new_plan
|
||||
else:
|
||||
plan_data[realm.id].current_plan = current_plan
|
||||
plan_data[realm.id].licenses = last_ledger_entry.licenses
|
||||
plan_data[realm.id].licenses_used = get_latest_seat_count(realm)
|
||||
billing_session = RealmBillingSession(user=None, realm=realm)
|
||||
realm_plan_data = get_current_plan_data_for_support_view(billing_session)
|
||||
plan_data[realm.id] = realm_plan_data
|
||||
context["plan_data"] = plan_data
|
||||
|
||||
def get_realm_owner_emails_as_string(realm: Realm) -> str:
|
||||
@@ -400,7 +358,7 @@ def support(
|
||||
|
||||
context["get_realm_owner_emails_as_string"] = get_realm_owner_emails_as_string
|
||||
context["get_realm_admin_emails_as_string"] = get_realm_admin_emails_as_string
|
||||
context["get_discount_for_realm"] = get_discount_for_realm
|
||||
context["get_discount"] = get_customer_discount_for_support_view
|
||||
context["get_org_type_display_name"] = get_org_type_display_name
|
||||
context["realm_icon_url"] = realm_icon_url
|
||||
context["Confirmation"] = Confirmation
|
||||
@@ -417,7 +375,9 @@ def get_remote_servers_for_support(
|
||||
if not email_to_search and not hostname_to_search:
|
||||
return []
|
||||
|
||||
remote_servers_query = RemoteZulipServer.objects.order_by("id")
|
||||
remote_servers_query = RemoteZulipServer.objects.order_by("id").prefetch_related(
|
||||
"remoterealm_set"
|
||||
)
|
||||
if email_to_search:
|
||||
remote_servers_query = remote_servers_query.filter(contact_email__iexact=email_to_search)
|
||||
elif hostname_to_search:
|
||||
@@ -429,8 +389,81 @@ def get_remote_servers_for_support(
|
||||
@require_server_admin
|
||||
@has_request_variables
|
||||
def remote_servers_support(
|
||||
request: HttpRequest, query: Optional[str] = REQ("q", default=None)
|
||||
request: HttpRequest,
|
||||
query: Optional[str] = REQ("q", default=None),
|
||||
remote_server_id: Optional[int] = REQ(default=None, converter=to_non_negative_int),
|
||||
remote_realm_id: Optional[int] = REQ(default=None, converter=to_non_negative_int),
|
||||
discount: Optional[Decimal] = REQ(default=None, converter=to_decimal),
|
||||
sponsorship_pending: Optional[bool] = REQ(default=None, json_validator=check_bool),
|
||||
approve_sponsorship: bool = REQ(default=False, json_validator=check_bool),
|
||||
billing_modality: Optional[str] = REQ(
|
||||
default=None, str_validator=check_string_in(VALID_BILLING_MODALITY_VALUES)
|
||||
),
|
||||
modify_plan: Optional[str] = REQ(
|
||||
default=None, str_validator=check_string_in(VALID_MODIFY_PLAN_METHODS)
|
||||
),
|
||||
) -> HttpResponse:
|
||||
context: Dict[str, Any] = {}
|
||||
|
||||
if "success_message" in request.session:
|
||||
context["success_message"] = request.session["success_message"]
|
||||
del request.session["success_message"]
|
||||
|
||||
acting_user = request.user
|
||||
assert isinstance(acting_user, UserProfile)
|
||||
if settings.BILLING_ENABLED and request.method == "POST":
|
||||
# We check that request.POST only has two keys in it:
|
||||
# either the remote_server_id or a remote_realm_id,
|
||||
# and a field to change.
|
||||
keys = set(request.POST.keys())
|
||||
if "csrfmiddlewaretoken" in keys:
|
||||
keys.remove("csrfmiddlewaretoken")
|
||||
if len(keys) != 2:
|
||||
raise JsonableError(_("Invalid parameters"))
|
||||
|
||||
if remote_realm_id is not None:
|
||||
remote_realm_support_request = True
|
||||
remote_realm = RemoteRealm.objects.get(id=remote_realm_id)
|
||||
else:
|
||||
assert remote_server_id is not None
|
||||
remote_realm_support_request = False
|
||||
remote_server = RemoteZulipServer.objects.get(id=remote_server_id)
|
||||
|
||||
support_view_request = None
|
||||
|
||||
if approve_sponsorship:
|
||||
support_view_request = SupportViewRequest(support_type=SupportType.approve_sponsorship)
|
||||
elif sponsorship_pending is not None:
|
||||
support_view_request = SupportViewRequest(
|
||||
support_type=SupportType.update_sponsorship_status,
|
||||
sponsorship_status=sponsorship_pending,
|
||||
)
|
||||
elif discount is not None:
|
||||
support_view_request = SupportViewRequest(
|
||||
support_type=SupportType.attach_discount,
|
||||
discount=discount,
|
||||
)
|
||||
elif billing_modality is not None:
|
||||
support_view_request = SupportViewRequest(
|
||||
support_type=SupportType.update_billing_modality,
|
||||
billing_modality=billing_modality,
|
||||
)
|
||||
elif modify_plan is not None:
|
||||
support_view_request = SupportViewRequest(
|
||||
support_type=SupportType.modify_plan,
|
||||
plan_modification=modify_plan,
|
||||
)
|
||||
if support_view_request is not None:
|
||||
if remote_realm_support_request:
|
||||
success_message = RemoteRealmBillingSession(
|
||||
support_staff=acting_user, remote_realm=remote_realm
|
||||
).process_support_view_request(support_view_request)
|
||||
else:
|
||||
success_message = RemoteServerBillingSession(
|
||||
support_staff=acting_user, remote_server=remote_server
|
||||
).process_support_view_request(support_view_request)
|
||||
context["success_message"] = success_message
|
||||
|
||||
email_to_search = None
|
||||
hostname_to_search = None
|
||||
if query:
|
||||
@@ -442,10 +475,45 @@ def remote_servers_support(
|
||||
remote_servers = get_remote_servers_for_support(
|
||||
email_to_search=email_to_search, hostname_to_search=hostname_to_search
|
||||
)
|
||||
remote_server_to_max_monthly_messages: Dict[int, Union[int, str]] = dict()
|
||||
server_plan_data: Dict[int, PlanData] = {}
|
||||
realm_plan_data: Dict[int, PlanData] = {}
|
||||
remote_realms: Dict[int, List[RemoteRealm]] = {}
|
||||
for remote_server in remote_servers:
|
||||
# Get remote realms attached to remote server
|
||||
remote_realms_for_server = list(
|
||||
remote_server.remoterealm_set.exclude(is_system_bot_realm=True)
|
||||
)
|
||||
remote_realms[remote_server.id] = remote_realms_for_server
|
||||
# Get plan data for remote realms
|
||||
for remote_realm in remote_realms[remote_server.id]:
|
||||
realm_billing_session = RemoteRealmBillingSession(remote_realm=remote_realm)
|
||||
remote_realm_plan_data = get_current_plan_data_for_support_view(realm_billing_session)
|
||||
realm_plan_data[remote_realm.id] = remote_realm_plan_data
|
||||
# Get plan data for remote server
|
||||
server_billing_session = RemoteServerBillingSession(remote_server=remote_server)
|
||||
remote_server_plan_data = get_current_plan_data_for_support_view(server_billing_session)
|
||||
server_plan_data[remote_server.id] = remote_server_plan_data
|
||||
# Get max monthly messages
|
||||
try:
|
||||
remote_server_to_max_monthly_messages[remote_server.id] = compute_max_monthly_messages(
|
||||
remote_server
|
||||
)
|
||||
except MissingDataError:
|
||||
remote_server_to_max_monthly_messages[remote_server.id] = "Recent data missing"
|
||||
|
||||
context["remote_servers"] = remote_servers
|
||||
context["remote_servers_plan_data"] = server_plan_data
|
||||
context["remote_server_to_max_monthly_messages"] = remote_server_to_max_monthly_messages
|
||||
context["remote_realms"] = remote_realms
|
||||
context["remote_realms_plan_data"] = realm_plan_data
|
||||
context["get_discount"] = get_customer_discount_for_support_view
|
||||
context["get_plan_type_name"] = get_plan_type_string
|
||||
context["get_org_type_display_name"] = get_org_type_display_name
|
||||
context["SPONSORED_PLAN_TYPE"] = RemoteZulipServer.PLAN_TYPE_COMMUNITY
|
||||
|
||||
return render(
|
||||
request,
|
||||
"analytics/remote_server_support.html",
|
||||
context=dict(
|
||||
remote_servers=remote_servers,
|
||||
),
|
||||
context=context,
|
||||
)
|
||||
|
||||
@@ -20,6 +20,186 @@ format used by the Zulip server that they are interacting with.
|
||||
|
||||
## Changes in Zulip 8.0
|
||||
|
||||
**Feature level 235**
|
||||
|
||||
* [`PATCH /realm/user_settings_defaults`](/api/update-realm-user-settings-defaults),
|
||||
[`POST /register`](/api/register-queue), [`PATCH /settings`](/api/update-settings):
|
||||
Added a new user setting,`automatically_follow_topics_where_mentioned`
|
||||
that allows user to automatically follow topics where the user is mentioned.
|
||||
|
||||
**Feature level 234**
|
||||
|
||||
* Mobile push notifications now include a `realm_name` field.
|
||||
* [`POST /mobile_push/test_notification`](/api/test-notify) now sends
|
||||
a test notification with `test` rather than `test-by-device-token`
|
||||
in the `event` field.
|
||||
|
||||
**Feature level 233**
|
||||
|
||||
* [`POST /register`](/api/register-queue), [`GET /events`](/api/get-events):
|
||||
Renamed the event type `hotspots` and the `hotspots` array field in it
|
||||
to `onboarding_steps` as this event is sent to clients with remaining
|
||||
onboarding steps data that includes hotspots and one-time notices to display.
|
||||
Earlier, we had hotspots only. Added a `type` field to the objects in
|
||||
the renamed `onboarding_steps` array to distinguish between the two type
|
||||
of onboarding steps.
|
||||
|
||||
* `POST /users/me/onboarding_steps`: Added a new endpoint that
|
||||
deprecates the `/users/me/hotspots` endpoint. Added support for
|
||||
displaying one-time notices in addition to existing hotspots.
|
||||
This is now used as a common endpoint to mark both types of
|
||||
onboarding steps, i.e., 'hotspot' and 'one_time_notice'.
|
||||
There is no compatibility support for `/users/me/hotspots` as
|
||||
no client other than web app has this feature currently.
|
||||
|
||||
**Feature level 232**
|
||||
|
||||
* [`POST /register`](/api/register-queue): Added a new
|
||||
`user_list_incomplete` [client
|
||||
capability](/api/register-queue#parameter-client_capabilities)
|
||||
controlling whether `realm_users` contains "Unknown user"
|
||||
placeholder objects for users that the current user cannot access
|
||||
due to a `can_access_all_users_group` policy.
|
||||
|
||||
* [`GET /events`](/api/get-events): The new `user_list_incomplete`
|
||||
[client
|
||||
capability](/api/register-queue#parameter-client_capabilities)
|
||||
controls whether to send `realm_user` events with `op: "add"`
|
||||
containing "Unknown user" placeholder objects to clients when a new
|
||||
user is created that the client does not have access to due to a
|
||||
`can_access_all_users_group` policy.
|
||||
|
||||
**Feature level 231**
|
||||
|
||||
* [`POST /register`](/api/register-queue):
|
||||
`realm_push_notifications_enabled` now represents more accurately
|
||||
whether push notifications are actually enabled via the mobile push
|
||||
notifications service. Added
|
||||
`realm_push_notifications_enabled_end_timestamp` field to realm
|
||||
data.
|
||||
|
||||
* [`GET /events`](/api/get-events): A `realm` update event is now sent
|
||||
whenever `push_notifications_enabled` or
|
||||
`push_notifications_enabled_end_timestamp` changes.
|
||||
|
||||
**Feature level 230**
|
||||
|
||||
* [`GET /events`](/api/get-events): Added `has_trigger` field in
|
||||
hotspots events to identify if a hotspot will activate only when
|
||||
some specific event occurs.
|
||||
|
||||
**Feature level 229**
|
||||
|
||||
* [`PATCH /messages/{message_id}`](/api/update-message), [`POST
|
||||
/messages`](/api/send-message): Topic wildcard mentions involving
|
||||
large numbers of participants are now restricted by
|
||||
`wildcard_mention_policy`. The server now uses the
|
||||
`STREAM_WILDCARD_MENTION_NOT_ALLOWED` and
|
||||
`TOPIC_WILDCARD_MENTION_NOT_ALLOWED` error codes when a message is
|
||||
rejected because of `wildcard_mention_policy`.
|
||||
|
||||
**Feature level 228**
|
||||
|
||||
* [`GET /events`](/api/get-events): `realm_user` events with `op: "update"`
|
||||
are now only sent to users who can access the modified user.
|
||||
|
||||
* [`GET /events`](/api/get-events): `presence` events are now only sent to
|
||||
users who can access the user who comes back online if the
|
||||
`CAN_ACCESS_ALL_USERS_GROUP_LIMITS_PRESENCE` server setting is set
|
||||
to `true`.
|
||||
|
||||
* [`GET /events`](/api/get-events): `user_status` events are now only
|
||||
sent to users who can access the modified user.
|
||||
|
||||
* [`GET /realm/presence`](/api/get-presence): The endpoint now returns
|
||||
presence information of accessible users only if the
|
||||
`CAN_ACCESS_ALL_USERS_GROUP_LIMITS_PRESENCE` server setting is set
|
||||
to `true`.
|
||||
|
||||
* [`GET /events`](/api/get-events): `realm_user` events with `op: "add"`
|
||||
are now also sent when a guest user gains access to a user.
|
||||
|
||||
* [`GET /events`](/api/get-events): `realm_user` events with `op: "remove"`
|
||||
are now also sent when a guest user loses access to a user.
|
||||
|
||||
**Feature level 227**
|
||||
|
||||
* [`PATCH /realm/user_settings_defaults`](/api/update-realm-user-settings-defaults),
|
||||
[`POST /register`](/api/register-queue), [`PATCH /settings`](/api/update-settings):
|
||||
Added `DMs, mentions, and followed topics` option for `desktop_icon_count_display`
|
||||
setting, and renumbered the options.
|
||||
The total unread count of DMs, mentions, and followed topics appears in
|
||||
desktop sidebar and browser tab when this option is configured.
|
||||
|
||||
**Feature level 226**
|
||||
|
||||
* [`POST /register`](/api/register-queue), [`GET /events`](/api/get-events),
|
||||
[`GET /users/me/subscriptions`](/api/get-subscriptions): Removed
|
||||
`email_address` field from subscription objects.
|
||||
|
||||
* [`GET /streams/{stream_id}/email_address`](/api/get-stream-email-address):
|
||||
Added new endpoint to get email address of a stream.
|
||||
|
||||
**Feature level 225**
|
||||
|
||||
* `PATCH /realm`, [`POST /register`](/api/register-queue),
|
||||
[`GET /events`](/api/get-events): Added `can_access_all_users_group_id`
|
||||
realm setting, which is the ID of the user group whose members can
|
||||
access all the users in the oragnization.
|
||||
|
||||
* [`POST /register`](/api/register-queue): Added `allowed_system_groups`
|
||||
field to configuration data object of permission settings passed in
|
||||
`server_supported_permission_settings`.
|
||||
|
||||
**Feature level 224**
|
||||
|
||||
* [`GET /events`](/api/get-events), [`GET /messages`](/api/get-messages),
|
||||
[`GET /messages/{message_id}`](/api/get-message): The `wildcard_mentioned`
|
||||
flag was deprecated, replaced with `stream_wildcard_mentioned` and
|
||||
`topic_wildcard_mentioned`, but it is still available for backwards compatibility.
|
||||
|
||||
**Feature level 223**
|
||||
|
||||
* `POST /users/me/apns_device_token`:
|
||||
The `appid` parameter is now required.
|
||||
Previously it defaulted to the server setting `ZULIP_IOS_APP_ID`,
|
||||
defaulting to "org.zulip.Zulip".
|
||||
|
||||
* `POST /remotes/server/register`: The `ios_app_id` parameter is now
|
||||
required when `kind` is 1, i.e. when registering an APNs token.
|
||||
Previously it was ignored, and the push bouncer effectively
|
||||
assumed its value was the server setting `APNS_TOPIC`,
|
||||
defaulting to "org.zulip.Zulip".
|
||||
|
||||
**Feature level 222**
|
||||
|
||||
* [`GET /events`](/api/get-events): When a user is deactivated or
|
||||
reactivated, the server uses `realm_user` events with `op: "update"`
|
||||
updating the `is_active` field, instead of `realm_user` events with
|
||||
`op: "remove"` and `op: "add"`, respectively.
|
||||
|
||||
* [`GET /events`](/api/get-events): When a bot is deactivated or
|
||||
reactivated, the server sends `realm_bot` events with `op: "update"`
|
||||
updating the `is_active` field, instead of `realm_bot` events with
|
||||
`op: "remove"` and `op: "add"`, respectively.
|
||||
|
||||
**Feature level 221**
|
||||
|
||||
* [`POST /register`](/api/register-queue): Added `server_supported_permission_settings`
|
||||
field in the response which contains configuration data for various permission
|
||||
settings.
|
||||
|
||||
**Feature level 220**
|
||||
|
||||
* [`GET /events`](/api/get-events): Stream creation events for web-public
|
||||
streams are now sent to all guest users in the organization as well.
|
||||
|
||||
* [`GET /events`](/api/get-events): The `subscription` events for `op:
|
||||
"peer_add"` and `op: "peer_remove"` are now sent to subscribed guest
|
||||
users for public streams and to all the guest users for web-public
|
||||
streams; previously, they incorrectly only received these for
|
||||
private streams.
|
||||
|
||||
**Feature level 219**
|
||||
|
||||
* [`PATCH /realm/user_settings_defaults`](/api/update-realm-user-settings-defaults)
|
||||
@@ -27,6 +207,10 @@ format used by the Zulip server that they are interacting with.
|
||||
[`PATCH /settings`](/api/update-settings): Renamed `default_view` and
|
||||
`escape_navigates_to_default_view` settings to `web_home_view` and
|
||||
`web_escape_navigates_to_home_view` respectively.
|
||||
* [`POST /user_topics`](/api/update-user-topic), [`POST
|
||||
register`](/api/register-queue), [`GET /events`](/api/get-events):
|
||||
Added followed as a supported value for visibility policies in
|
||||
`user_topic` objects.
|
||||
|
||||
**Feature level 218**
|
||||
|
||||
|
||||
@@ -105,6 +105,12 @@ help center because they are primarily useful to API clients:
|
||||
* `dm-including:1234`: Search all direct messages (1-on-1 and group)
|
||||
that include you and user ID `1234`.
|
||||
|
||||
!!! tip ""
|
||||
|
||||
A user ID can be found by [viewing a user's profile][view-profile]
|
||||
in the web or desktop apps. A stream ID can be found when [browsing
|
||||
streams][browse-streams] in the web app via the URL.
|
||||
|
||||
The operands for these search options must be encoded either as an
|
||||
integer ID or a JSON list of integer IDs. For example, to query
|
||||
messages sent by a user 1234 to a direct message thread with yourself,
|
||||
@@ -122,3 +128,6 @@ user 1234, and user 5678, the correct JSON-encoded query is:
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
[view-profile]: /help/view-someones-profile
|
||||
[browse-streams]: /help/browse-and-subscribe-to-streams
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
* [Create a stream](/api/create-stream)
|
||||
* [Update a stream](/api/update-stream)
|
||||
* [Archive a stream](/api/archive-stream)
|
||||
* [Get stream's email address](/api/get-stream-email-address)
|
||||
* [Get topics in a stream](/api/get-stream-topics)
|
||||
* [Topic muting](/api/mute-topic)
|
||||
* [Update personal preferences for a topic](/api/update-user-topic)
|
||||
|
||||
@@ -155,3 +155,45 @@ below are for a webhook named `MyWebHook`.
|
||||
testing with live data from the service you're integrating and can help you
|
||||
spot why something isn't working or if the service is using custom HTTP
|
||||
headers.
|
||||
|
||||
## URLs
|
||||
|
||||
The base URL for an incoming webhook integration bot is
|
||||
`{{ api_url }}/v1/external/INTEGRATION_NAME?api_key=API_KEY` where
|
||||
`INTEGRATION_NAME` is the name of the specific webhook integration and
|
||||
`API_KEY` is the API key of the bot created by the user for the
|
||||
integration.
|
||||
|
||||
The list of existing webhook integrations can be found in
|
||||
`zerver/lib/integrations.py` (at `WEBHOOK_INTEGRATIONS`) or by browsing
|
||||
the [Integrations documentation](/integrations).
|
||||
|
||||
Parameters accepted in the URL include:
|
||||
|
||||
* `api_key`: **Required**. The API key of the bot created by the user
|
||||
for the integration. To get a bot's API key, see the [API
|
||||
keys](/api/api-keys) documentation.
|
||||
|
||||
* `stream`: The stream for the integration to send notifications to.
|
||||
Can be either the stream ID or the [URL-encoded][url-encoder] stream
|
||||
name. By default the integration will send direct messages to the
|
||||
bot's owner.
|
||||
|
||||
!!! tip ""
|
||||
|
||||
A stream ID can be found when [browsing streams][browse-streams]
|
||||
in the web app via the URL.
|
||||
|
||||
* `topic`: The topic in the specified stream for the integration to
|
||||
send notifications to. The topic should also be
|
||||
[URL-encoded][url-encoder]. By default the integration will have a
|
||||
topic configured for stream messages.
|
||||
|
||||
* `only_events`, `exclude_events`: Some incoming webhook integrations
|
||||
support these parameters to filter which events will trigger a
|
||||
notification. For details, see the integration's [integration
|
||||
documentation](/integrations) page.
|
||||
|
||||
[browse-streams]: /help/browse-and-subscribe-to-streams
|
||||
[add-bot]: /help/add-a-bot-or-integration
|
||||
[url-encoder]: https://www.urlencoder.org/
|
||||
|
||||
@@ -429,8 +429,9 @@ Learn how Zulip integrations work with this simple Hello World example!
|
||||
by default in the Zulip development environment. If you are running
|
||||
Zulip in production, you should make sure that this stream exists.
|
||||
|
||||
1. {!create-bot-construct-url.md!}
|
||||
1. {!create-an-incoming-webhook.md!}
|
||||
|
||||
1. {!generate-integration-url.md!}
|
||||
|
||||
1. To trigger a notification using this example webhook, you can use
|
||||
`send_webhook_fixture_message` from a [Zulip development
|
||||
@@ -455,7 +456,7 @@ Learn how Zulip integrations work with this simple Hello World example!
|
||||
|
||||
```
|
||||
|
||||
`{!create-bot-construct-url.md!}` and `{!congrats.md!}` are examples of
|
||||
`{!create-an-incoming-webhook.md!}` and `{!congrats.md!}` are examples of
|
||||
a Markdown macro. Zulip has a macro-based Markdown/Jinja2 framework that
|
||||
includes macros for common instructions in Zulip's webhooks/integrations
|
||||
documentation.
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# Copyright: (c) 2008, Jarek Zgoda <jarek.zgoda@gmail.com>
|
||||
|
||||
__revision__ = "$Id: models.py 28 2009-10-22 15:03:02Z jarek.zgoda $"
|
||||
import datetime
|
||||
import secrets
|
||||
from base64 import b32encode
|
||||
from typing import List, Mapping, Optional, Union
|
||||
from datetime import timedelta
|
||||
from typing import List, Mapping, Optional, Union, cast
|
||||
from urllib.parse import urljoin
|
||||
|
||||
from django.conf import settings
|
||||
@@ -30,6 +30,12 @@ from zerver.models import (
|
||||
UserProfile,
|
||||
)
|
||||
|
||||
if settings.ZILENCER_ENABLED:
|
||||
from zilencer.models import (
|
||||
PreregistrationRemoteRealmBillingUser,
|
||||
PreregistrationRemoteServerBillingUser,
|
||||
)
|
||||
|
||||
|
||||
class ConfirmationKeyError(Exception):
|
||||
WRONG_LENGTH = 1
|
||||
@@ -56,7 +62,7 @@ def generate_key() -> str:
|
||||
return b32encode(secrets.token_bytes(15)).decode().lower()
|
||||
|
||||
|
||||
ConfirmationObjT: TypeAlias = Union[
|
||||
NoZilencerConfirmationObjT: TypeAlias = Union[
|
||||
MultiuseInvite,
|
||||
PreregistrationRealm,
|
||||
PreregistrationUser,
|
||||
@@ -64,6 +70,13 @@ ConfirmationObjT: TypeAlias = Union[
|
||||
UserProfile,
|
||||
RealmReactivationStatus,
|
||||
]
|
||||
ZilencerConfirmationObjT: TypeAlias = Union[
|
||||
NoZilencerConfirmationObjT,
|
||||
"PreregistrationRemoteServerBillingUser",
|
||||
"PreregistrationRemoteRealmBillingUser",
|
||||
]
|
||||
|
||||
ConfirmationObjT = Union[NoZilencerConfirmationObjT, ZilencerConfirmationObjT]
|
||||
|
||||
|
||||
def get_object_from_key(
|
||||
@@ -117,15 +130,20 @@ def create_confirmation_link(
|
||||
*,
|
||||
validity_in_minutes: Union[Optional[int], UnspecifiedValue] = UnspecifiedValue(),
|
||||
url_args: Mapping[str, str] = {},
|
||||
realm_creation: bool = False,
|
||||
no_associated_realm_object: bool = False,
|
||||
) -> str:
|
||||
# validity_in_minutes is an override for the default values which are
|
||||
# determined by the confirmation_type - its main purpose is for use
|
||||
# in tests which may want to have control over the exact expiration time.
|
||||
key = generate_key()
|
||||
if realm_creation:
|
||||
|
||||
# Some confirmation objects, like those for realm creation or those used
|
||||
# for the self-hosted management flows, are not associated with a realm
|
||||
# hosted by this Zulip server.
|
||||
if no_associated_realm_object:
|
||||
realm = None
|
||||
else:
|
||||
obj = cast(NoZilencerConfirmationObjT, obj)
|
||||
assert not isinstance(obj, PreregistrationRealm)
|
||||
realm = obj.realm
|
||||
|
||||
@@ -136,11 +154,9 @@ def create_confirmation_link(
|
||||
expiry_date = None
|
||||
else:
|
||||
assert validity_in_minutes is not None
|
||||
expiry_date = current_time + datetime.timedelta(minutes=validity_in_minutes)
|
||||
expiry_date = current_time + timedelta(minutes=validity_in_minutes)
|
||||
else:
|
||||
expiry_date = current_time + datetime.timedelta(
|
||||
days=_properties[confirmation_type].validity_in_days
|
||||
)
|
||||
expiry_date = current_time + timedelta(days=_properties[confirmation_type].validity_in_days)
|
||||
|
||||
Confirmation.objects.create(
|
||||
content_object=obj,
|
||||
@@ -185,6 +201,8 @@ class Confirmation(models.Model):
|
||||
MULTIUSE_INVITE = 6
|
||||
REALM_CREATION = 7
|
||||
REALM_REACTIVATION = 8
|
||||
REMOTE_SERVER_BILLING_LEGACY_LOGIN = 9
|
||||
REMOTE_REALM_BILLING_LEGACY_LOGIN = 10
|
||||
type = models.PositiveSmallIntegerField()
|
||||
|
||||
class Meta:
|
||||
@@ -221,6 +239,13 @@ _properties = {
|
||||
Confirmation.REALM_CREATION: ConfirmationType("get_prereg_key_and_redirect"),
|
||||
Confirmation.REALM_REACTIVATION: ConfirmationType("realm_reactivation"),
|
||||
}
|
||||
if settings.ZILENCER_ENABLED:
|
||||
_properties[Confirmation.REMOTE_SERVER_BILLING_LEGACY_LOGIN] = ConfirmationType(
|
||||
"remote_billing_legacy_server_from_login_confirmation_link"
|
||||
)
|
||||
_properties[Confirmation.REMOTE_REALM_BILLING_LEGACY_LOGIN] = ConfirmationType(
|
||||
"remote_realm_billing_from_login_confirmation_link"
|
||||
)
|
||||
|
||||
|
||||
def one_click_unsubscribe_link(user_profile: UserProfile, email_type: str) -> str:
|
||||
|
||||
39
corporate/lib/analytics.py
Normal file
39
corporate/lib/analytics.py
Normal file
@@ -0,0 +1,39 @@
|
||||
from decimal import Decimal
|
||||
from typing import Any, Dict
|
||||
|
||||
from django.utils.timezone import now as timezone_now
|
||||
|
||||
from corporate.lib.stripe import renewal_amount
|
||||
from corporate.models import Customer, CustomerPlan
|
||||
from zerver.lib.utils import assert_is_not_none
|
||||
|
||||
|
||||
def get_realms_with_default_discount_dict() -> Dict[str, Decimal]:
|
||||
realms_with_default_discount: Dict[str, Any] = {}
|
||||
customers = (
|
||||
Customer.objects.exclude(default_discount=None)
|
||||
.exclude(default_discount=0)
|
||||
.exclude(realm=None)
|
||||
)
|
||||
for customer in customers:
|
||||
assert customer.realm is not None
|
||||
realms_with_default_discount[customer.realm.string_id] = assert_is_not_none(
|
||||
customer.default_discount
|
||||
)
|
||||
return realms_with_default_discount
|
||||
|
||||
|
||||
def estimate_annual_recurring_revenue_by_realm() -> Dict[str, int]: # nocoverage
|
||||
annual_revenue = {}
|
||||
for plan in CustomerPlan.objects.filter(status=CustomerPlan.ACTIVE).select_related(
|
||||
"customer__realm"
|
||||
):
|
||||
if plan.customer.realm is not None:
|
||||
# TODO: figure out what to do for plans that don't automatically
|
||||
# renew, but which probably will renew
|
||||
renewal_cents = renewal_amount(plan, timezone_now())
|
||||
if plan.billing_schedule == CustomerPlan.BILLING_SCHEDULE_MONTHLY:
|
||||
renewal_cents *= 12
|
||||
# TODO: Decimal stuff
|
||||
annual_revenue[plan.customer.realm.string_id] = int(renewal_cents / 100)
|
||||
return annual_revenue
|
||||
187
corporate/lib/decorator.py
Normal file
187
corporate/lib/decorator.py
Normal file
@@ -0,0 +1,187 @@
|
||||
from functools import wraps
|
||||
from typing import Callable, Optional
|
||||
from urllib.parse import urlencode, urljoin
|
||||
|
||||
from django.conf import settings
|
||||
from django.http import HttpRequest, HttpResponse, HttpResponseRedirect
|
||||
from django.shortcuts import render
|
||||
from django.urls import reverse
|
||||
from typing_extensions import Concatenate, ParamSpec
|
||||
|
||||
from corporate.lib.remote_billing_util import (
|
||||
RemoteBillingIdentityExpiredError,
|
||||
get_remote_realm_and_user_from_session,
|
||||
get_remote_server_and_user_from_session,
|
||||
)
|
||||
from corporate.lib.stripe import RemoteRealmBillingSession, RemoteServerBillingSession
|
||||
from zerver.lib.exceptions import RemoteBillingAuthenticationError
|
||||
from zerver.lib.subdomains import get_subdomain
|
||||
from zerver.lib.url_encoding import append_url_query_string
|
||||
from zilencer.models import RemoteRealm
|
||||
|
||||
ParamT = ParamSpec("ParamT")
|
||||
|
||||
|
||||
def is_self_hosting_management_subdomain(request: HttpRequest) -> bool:
|
||||
subdomain = get_subdomain(request)
|
||||
return settings.DEVELOPMENT and subdomain == settings.SELF_HOSTING_MANAGEMENT_SUBDOMAIN
|
||||
|
||||
|
||||
def self_hosting_management_endpoint(
|
||||
view_func: Callable[Concatenate[HttpRequest, ParamT], HttpResponse]
|
||||
) -> Callable[Concatenate[HttpRequest, ParamT], HttpResponse]:
|
||||
@wraps(view_func)
|
||||
def _wrapped_view_func(
|
||||
request: HttpRequest, /, *args: ParamT.args, **kwargs: ParamT.kwargs
|
||||
) -> HttpResponse:
|
||||
if not is_self_hosting_management_subdomain(request): # nocoverage
|
||||
return render(request, "404.html", status=404)
|
||||
return view_func(request, *args, **kwargs)
|
||||
|
||||
return _wrapped_view_func
|
||||
|
||||
|
||||
def authenticated_remote_realm_management_endpoint(
|
||||
view_func: Callable[Concatenate[HttpRequest, RemoteRealmBillingSession, ParamT], HttpResponse]
|
||||
) -> Callable[Concatenate[HttpRequest, ParamT], HttpResponse]:
|
||||
@wraps(view_func)
|
||||
def _wrapped_view_func(
|
||||
request: HttpRequest,
|
||||
/,
|
||||
*args: ParamT.args,
|
||||
**kwargs: ParamT.kwargs,
|
||||
) -> HttpResponse:
|
||||
if not is_self_hosting_management_subdomain(request): # nocoverage
|
||||
return render(request, "404.html", status=404)
|
||||
|
||||
realm_uuid = kwargs.get("realm_uuid")
|
||||
if realm_uuid is not None and not isinstance(realm_uuid, str): # nocoverage
|
||||
raise TypeError("realm_uuid must be a string or None")
|
||||
|
||||
try:
|
||||
remote_realm, remote_billing_user = get_remote_realm_and_user_from_session(
|
||||
request, realm_uuid
|
||||
)
|
||||
except RemoteBillingIdentityExpiredError as e:
|
||||
# The user had an authenticated session with an identity_dict,
|
||||
# but it expired.
|
||||
# We want to redirect back to the start of their login flow
|
||||
# at their {realm.host}/self-hosted-billing/ with a proper
|
||||
# next parameter to take them back to what they're trying
|
||||
# to access after re-authing.
|
||||
# Note: Theoretically we could take the realm_uuid from the request
|
||||
# path or params to figure out the remote_realm.host for the redirect,
|
||||
# but that would mean leaking that .host value to anyone who knows
|
||||
# the uuid. Therefore we limit ourselves to taking the realm_uuid
|
||||
# from the identity_dict - since that proves that the user at least
|
||||
# previously was successfully authenticated as a billing admin of that
|
||||
# realm.
|
||||
realm_uuid = e.realm_uuid
|
||||
server_uuid = e.server_uuid
|
||||
uri_scheme = e.uri_scheme
|
||||
if realm_uuid is None:
|
||||
# This doesn't make sense - if get_remote_realm_and_user_from_session
|
||||
# found an expired identity dict, it should have had a realm_uuid.
|
||||
raise AssertionError
|
||||
|
||||
assert server_uuid is not None, "identity_dict with realm_uuid must have server_uuid"
|
||||
assert uri_scheme is not None, "identity_dict with realm_uuid must have uri_scheme"
|
||||
|
||||
try:
|
||||
remote_realm = RemoteRealm.objects.get(uuid=realm_uuid, server__uuid=server_uuid)
|
||||
except RemoteRealm.DoesNotExist:
|
||||
# This should be impossible - unless the RemoteRealm existed and somehow the row
|
||||
# was deleted.
|
||||
raise AssertionError
|
||||
|
||||
# Using EXTERNAL_URI_SCHEME means we'll do https:// in production, which is
|
||||
# the sane default - while having http:// in development, which will allow
|
||||
# these redirects to work there for testing.
|
||||
url = urljoin(uri_scheme + remote_realm.host, "/self-hosted-billing/")
|
||||
|
||||
page_type = get_next_page_param_from_request_path(request)
|
||||
if page_type is not None:
|
||||
query = urlencode({"next_page": page_type})
|
||||
url = append_url_query_string(url, query)
|
||||
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
billing_session = RemoteRealmBillingSession(
|
||||
remote_realm, remote_billing_user=remote_billing_user
|
||||
)
|
||||
return view_func(request, billing_session)
|
||||
|
||||
return _wrapped_view_func
|
||||
|
||||
|
||||
def get_next_page_param_from_request_path(request: HttpRequest) -> Optional[str]:
|
||||
# Our endpoint URLs in this subsystem end with something like
|
||||
# /sponsorship or /plans etc.
|
||||
# Therefore we can use this nice property to figure out easily what
|
||||
# kind of page the user is trying to access and find the right value
|
||||
# for the `next` query parameter.
|
||||
path = request.path
|
||||
if path.endswith("/"):
|
||||
path = path[:-1]
|
||||
|
||||
page_type = path.split("/")[-1]
|
||||
|
||||
from corporate.views.remote_billing_page import (
|
||||
VALID_NEXT_PAGES as REMOTE_BILLING_VALID_NEXT_PAGES,
|
||||
)
|
||||
|
||||
if page_type in REMOTE_BILLING_VALID_NEXT_PAGES:
|
||||
return page_type
|
||||
|
||||
# Should be impossible to reach here. If this is reached, it must mean
|
||||
# we have a registered endpoint that doesn't have a VALID_NEXT_PAGES entry
|
||||
# or the parsing logic above is failing.
|
||||
raise AssertionError(f"Unknown page type: {page_type}")
|
||||
|
||||
|
||||
def authenticated_remote_server_management_endpoint(
|
||||
view_func: Callable[Concatenate[HttpRequest, RemoteServerBillingSession, ParamT], HttpResponse]
|
||||
) -> Callable[Concatenate[HttpRequest, ParamT], HttpResponse]:
|
||||
@wraps(view_func)
|
||||
def _wrapped_view_func(
|
||||
request: HttpRequest,
|
||||
/,
|
||||
*args: ParamT.args,
|
||||
**kwargs: ParamT.kwargs,
|
||||
) -> HttpResponse:
|
||||
if not is_self_hosting_management_subdomain(request): # nocoverage
|
||||
return render(request, "404.html", status=404)
|
||||
|
||||
server_uuid = kwargs.get("server_uuid")
|
||||
if not isinstance(server_uuid, str):
|
||||
raise TypeError("server_uuid must be a string") # nocoverage
|
||||
|
||||
try:
|
||||
remote_server, remote_billing_user = get_remote_server_and_user_from_session(
|
||||
request, server_uuid=server_uuid
|
||||
)
|
||||
if remote_billing_user is None:
|
||||
# This should only be possible if the user hasn't finished the confirmation flow
|
||||
# and doesn't have a fully authenticated session yet. They should not be attempting
|
||||
# to access this endpoint yet.
|
||||
raise RemoteBillingAuthenticationError
|
||||
except (RemoteBillingIdentityExpiredError, RemoteBillingAuthenticationError):
|
||||
# In this flow, we can only redirect to our local "legacy server flow login" page.
|
||||
# That means that we can do it universally whether the user has an expired
|
||||
# identity_dict, or just lacks any form of authentication info at all - there
|
||||
# are no security concerns since this is just a local redirect.
|
||||
url = reverse("remote_billing_legacy_server_login")
|
||||
page_type = get_next_page_param_from_request_path(request)
|
||||
if page_type is not None:
|
||||
query = urlencode({"next_page": page_type})
|
||||
url = append_url_query_string(url, query)
|
||||
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
assert remote_billing_user is not None
|
||||
billing_session = RemoteServerBillingSession(
|
||||
remote_server, remote_billing_user=remote_billing_user
|
||||
)
|
||||
return view_func(request, billing_session)
|
||||
|
||||
return _wrapped_view_func
|
||||
182
corporate/lib/remote_billing_util.py
Normal file
182
corporate/lib/remote_billing_util.py
Normal file
@@ -0,0 +1,182 @@
|
||||
import logging
|
||||
from typing import Literal, Optional, Tuple, TypedDict, Union, cast
|
||||
|
||||
from django.http import HttpRequest
|
||||
from django.utils.timezone import now as timezone_now
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from zerver.lib.exceptions import JsonableError, RemoteBillingAuthenticationError
|
||||
from zerver.lib.timestamp import datetime_to_timestamp
|
||||
from zilencer.models import (
|
||||
RemoteRealm,
|
||||
RemoteRealmBillingUser,
|
||||
RemoteServerBillingUser,
|
||||
RemoteZulipServer,
|
||||
)
|
||||
|
||||
billing_logger = logging.getLogger("corporate.stripe")
|
||||
|
||||
# The sessions are relatively short-lived, so that we can avoid issues
|
||||
# with users who have their privileges revoked on the remote server
|
||||
# maintaining access to the billing page for too long.
|
||||
REMOTE_BILLING_SESSION_VALIDITY_SECONDS = 2 * 60 * 60
|
||||
|
||||
|
||||
class RemoteBillingUserDict(TypedDict):
|
||||
user_uuid: str
|
||||
user_email: str
|
||||
user_full_name: str
|
||||
|
||||
|
||||
class RemoteBillingIdentityDict(TypedDict):
|
||||
user: RemoteBillingUserDict
|
||||
remote_server_uuid: str
|
||||
remote_realm_uuid: str
|
||||
|
||||
remote_billing_user_id: Optional[int]
|
||||
authenticated_at: int
|
||||
uri_scheme: Literal["http://", "https://"]
|
||||
|
||||
next_page: Optional[str]
|
||||
|
||||
|
||||
class LegacyServerIdentityDict(TypedDict):
|
||||
# Currently this has only one field. We can extend this
|
||||
# to add more information as appropriate.
|
||||
remote_server_uuid: str
|
||||
|
||||
remote_billing_user_id: Optional[int]
|
||||
authenticated_at: int
|
||||
|
||||
|
||||
class RemoteBillingIdentityExpiredError(Exception):
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
realm_uuid: Optional[str] = None,
|
||||
server_uuid: Optional[str] = None,
|
||||
uri_scheme: Optional[Literal["http://", "https://"]] = None,
|
||||
) -> None:
|
||||
self.realm_uuid = realm_uuid
|
||||
self.server_uuid = server_uuid
|
||||
self.uri_scheme = uri_scheme
|
||||
|
||||
|
||||
def get_identity_dict_from_session(
|
||||
request: HttpRequest,
|
||||
*,
|
||||
realm_uuid: Optional[str],
|
||||
server_uuid: Optional[str],
|
||||
) -> Optional[Union[RemoteBillingIdentityDict, LegacyServerIdentityDict]]:
|
||||
if not (realm_uuid or server_uuid):
|
||||
return None
|
||||
|
||||
identity_dicts = request.session.get("remote_billing_identities")
|
||||
if identity_dicts is None:
|
||||
return None
|
||||
|
||||
if realm_uuid is not None:
|
||||
result = identity_dicts.get(f"remote_realm:{realm_uuid}")
|
||||
else:
|
||||
assert server_uuid is not None
|
||||
result = identity_dicts.get(f"remote_server:{server_uuid}")
|
||||
|
||||
if result is None:
|
||||
return None
|
||||
if (
|
||||
datetime_to_timestamp(timezone_now()) - result["authenticated_at"]
|
||||
> REMOTE_BILLING_SESSION_VALIDITY_SECONDS
|
||||
):
|
||||
# In this case we raise, because callers want to catch this as an explicitly
|
||||
# different scenario from the user not being authenticated, to handle it nicely
|
||||
# by redirecting them to their login page.
|
||||
raise RemoteBillingIdentityExpiredError(
|
||||
realm_uuid=result.get("remote_realm_uuid"),
|
||||
server_uuid=result.get("remote_server_uuid"),
|
||||
uri_scheme=result.get("uri_scheme"),
|
||||
)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def get_remote_realm_and_user_from_session(
|
||||
request: HttpRequest,
|
||||
realm_uuid: Optional[str],
|
||||
) -> Tuple[RemoteRealm, RemoteRealmBillingUser]:
|
||||
# Cannot use isinstance with TypeDicts, to make mypy know
|
||||
# which of the TypedDicts in the Union this is - so just cast it.
|
||||
identity_dict = cast(
|
||||
Optional[RemoteBillingIdentityDict],
|
||||
get_identity_dict_from_session(request, realm_uuid=realm_uuid, server_uuid=None),
|
||||
)
|
||||
|
||||
if identity_dict is None:
|
||||
raise RemoteBillingAuthenticationError
|
||||
|
||||
remote_server_uuid = identity_dict["remote_server_uuid"]
|
||||
remote_realm_uuid = identity_dict["remote_realm_uuid"]
|
||||
|
||||
try:
|
||||
remote_realm = RemoteRealm.objects.get(
|
||||
uuid=remote_realm_uuid, server__uuid=remote_server_uuid
|
||||
)
|
||||
except RemoteRealm.DoesNotExist:
|
||||
raise AssertionError(
|
||||
"The remote realm is missing despite being in the RemoteBillingIdentityDict"
|
||||
)
|
||||
|
||||
if (
|
||||
remote_realm.registration_deactivated
|
||||
or remote_realm.realm_deactivated
|
||||
or remote_realm.server.deactivated
|
||||
):
|
||||
raise JsonableError(_("Registration is deactivated"))
|
||||
|
||||
remote_billing_user_id = identity_dict["remote_billing_user_id"]
|
||||
# We only put IdentityDicts with remote_billing_user_id in the session in this flow,
|
||||
# because the RemoteRealmBillingUser already exists when this is inserted into the session
|
||||
# at the end of authentication.
|
||||
assert remote_billing_user_id is not None
|
||||
|
||||
try:
|
||||
remote_billing_user = RemoteRealmBillingUser.objects.get(
|
||||
id=remote_billing_user_id, remote_realm=remote_realm
|
||||
)
|
||||
except RemoteRealmBillingUser.DoesNotExist:
|
||||
raise AssertionError
|
||||
|
||||
return remote_realm, remote_billing_user
|
||||
|
||||
|
||||
def get_remote_server_and_user_from_session(
|
||||
request: HttpRequest,
|
||||
server_uuid: str,
|
||||
) -> Tuple[RemoteZulipServer, Optional[RemoteServerBillingUser]]:
|
||||
identity_dict: Optional[LegacyServerIdentityDict] = get_identity_dict_from_session(
|
||||
request, realm_uuid=None, server_uuid=server_uuid
|
||||
)
|
||||
|
||||
if identity_dict is None:
|
||||
raise RemoteBillingAuthenticationError
|
||||
|
||||
remote_server_uuid = identity_dict["remote_server_uuid"]
|
||||
try:
|
||||
remote_server = RemoteZulipServer.objects.get(uuid=remote_server_uuid)
|
||||
except RemoteZulipServer.DoesNotExist:
|
||||
raise JsonableError(_("Invalid remote server."))
|
||||
|
||||
if remote_server.deactivated:
|
||||
raise JsonableError(_("Registration is deactivated"))
|
||||
|
||||
remote_billing_user_id = identity_dict.get("remote_billing_user_id")
|
||||
if remote_billing_user_id is None:
|
||||
return remote_server, None
|
||||
|
||||
try:
|
||||
remote_billing_user = RemoteServerBillingUser.objects.get(
|
||||
id=remote_billing_user_id, remote_server=remote_server
|
||||
)
|
||||
except RemoteServerBillingUser.DoesNotExist:
|
||||
remote_billing_user = None
|
||||
|
||||
return remote_server, remote_billing_user
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,18 +1,18 @@
|
||||
import logging
|
||||
from contextlib import suppress
|
||||
from typing import Any, Callable, Dict, Union
|
||||
from typing import Any, Callable, Dict, Optional, Union
|
||||
|
||||
import stripe
|
||||
from django.conf import settings
|
||||
|
||||
from corporate.lib.stripe import (
|
||||
BillingError,
|
||||
InvalidPlanUpgradeError,
|
||||
RealmBillingSession,
|
||||
RemoteRealmBillingSession,
|
||||
RemoteServerBillingSession,
|
||||
UpgradeWithExistingPlanError,
|
||||
ensure_realm_does_not_have_active_plan,
|
||||
process_initial_upgrade,
|
||||
update_or_create_stripe_customer,
|
||||
)
|
||||
from corporate.models import Event, PaymentIntent, Session
|
||||
from corporate.models import Customer, CustomerPlan, Event, PaymentIntent, Session
|
||||
from zerver.models import get_active_user_profile_by_id_in_realm
|
||||
|
||||
billing_logger = logging.getLogger("corporate.stripe")
|
||||
@@ -63,6 +63,20 @@ def error_handler(
|
||||
return wrapper
|
||||
|
||||
|
||||
def get_billing_session_for_stripe_webhook(
|
||||
customer: Customer, user_id: Optional[str]
|
||||
) -> Union[RealmBillingSession, RemoteRealmBillingSession, RemoteServerBillingSession]:
|
||||
if customer.remote_realm is not None: # nocoverage
|
||||
return RemoteRealmBillingSession(customer.remote_realm)
|
||||
elif customer.remote_server is not None: # nocoverage
|
||||
return RemoteServerBillingSession(customer.remote_server)
|
||||
else:
|
||||
assert user_id is not None
|
||||
assert customer.realm is not None
|
||||
user = get_active_user_profile_by_id_in_realm(int(user_id), customer.realm)
|
||||
return RealmBillingSession(user)
|
||||
|
||||
|
||||
@error_handler
|
||||
def handle_checkout_session_completed_event(
|
||||
stripe_session: stripe.checkout.Session, session: Session
|
||||
@@ -70,45 +84,20 @@ def handle_checkout_session_completed_event(
|
||||
session.status = Session.COMPLETED
|
||||
session.save()
|
||||
|
||||
assert isinstance(stripe_session.setup_intent, str)
|
||||
assert stripe_session.metadata is not None
|
||||
stripe_setup_intent = stripe.SetupIntent.retrieve(stripe_session.setup_intent)
|
||||
assert session.customer.realm is not None
|
||||
user_id = stripe_session.metadata.get("user_id")
|
||||
assert user_id is not None
|
||||
user = get_active_user_profile_by_id_in_realm(user_id, session.customer.realm)
|
||||
billing_session = get_billing_session_for_stripe_webhook(
|
||||
session.customer, stripe_session.metadata.get("user_id")
|
||||
)
|
||||
payment_method = stripe_setup_intent.payment_method
|
||||
assert isinstance(payment_method, (str, type(None)))
|
||||
|
||||
if session.type in [
|
||||
Session.UPGRADE_FROM_BILLING_PAGE,
|
||||
Session.RETRY_UPGRADE_WITH_ANOTHER_PAYMENT_METHOD,
|
||||
Session.CARD_UPDATE_FROM_BILLING_PAGE,
|
||||
Session.CARD_UPDATE_FROM_UPGRADE_PAGE,
|
||||
]:
|
||||
ensure_realm_does_not_have_active_plan(user.realm)
|
||||
update_or_create_stripe_customer(user, payment_method)
|
||||
assert session.payment_intent is not None
|
||||
session.payment_intent.status = PaymentIntent.PROCESSING
|
||||
session.payment_intent.last_payment_error = ()
|
||||
session.payment_intent.save(update_fields=["status", "last_payment_error"])
|
||||
with suppress(stripe.error.CardError):
|
||||
stripe.PaymentIntent.confirm(
|
||||
session.payment_intent.stripe_payment_intent_id,
|
||||
payment_method=payment_method,
|
||||
off_session=True,
|
||||
)
|
||||
elif session.type in [
|
||||
Session.FREE_TRIAL_UPGRADE_FROM_BILLING_PAGE,
|
||||
Session.FREE_TRIAL_UPGRADE_FROM_ONBOARDING_PAGE,
|
||||
]:
|
||||
ensure_realm_does_not_have_active_plan(user.realm)
|
||||
update_or_create_stripe_customer(user, payment_method)
|
||||
process_initial_upgrade(
|
||||
user,
|
||||
int(stripe_setup_intent.metadata["licenses"]),
|
||||
stripe_setup_intent.metadata["license_management"] == "automatic",
|
||||
int(stripe_setup_intent.metadata["billing_schedule"]),
|
||||
charge_automatically=True,
|
||||
free_trial=True,
|
||||
)
|
||||
elif session.type in [Session.CARD_UPDATE_FROM_BILLING_PAGE]:
|
||||
update_or_create_stripe_customer(user, payment_method)
|
||||
billing_session.update_or_create_stripe_customer(payment_method)
|
||||
|
||||
|
||||
@error_handler
|
||||
@@ -118,13 +107,12 @@ def handle_payment_intent_succeeded_event(
|
||||
payment_intent.status = PaymentIntent.SUCCEEDED
|
||||
payment_intent.save()
|
||||
metadata: Dict[str, Any] = stripe_payment_intent.metadata
|
||||
assert payment_intent.customer.realm is not None
|
||||
user_id = metadata.get("user_id")
|
||||
assert user_id is not None
|
||||
user = get_active_user_profile_by_id_in_realm(user_id, payment_intent.customer.realm)
|
||||
|
||||
description = ""
|
||||
for charge in stripe_payment_intent.charges:
|
||||
charge: stripe.Charge
|
||||
for charge in stripe_payment_intent.charges: # type: ignore[attr-defined] # https://stripe.com/docs/upgrades#2022-11-15
|
||||
assert charge.payment_method_details is not None
|
||||
assert charge.payment_method_details.card is not None
|
||||
description = f"Payment (Card ending in {charge.payment_method_details.card.last4})"
|
||||
break
|
||||
|
||||
@@ -135,48 +123,30 @@ def handle_payment_intent_succeeded_event(
|
||||
description=description,
|
||||
discountable=False,
|
||||
)
|
||||
billing_session = get_billing_session_for_stripe_webhook(
|
||||
payment_intent.customer, metadata.get("user_id")
|
||||
)
|
||||
plan_tier = int(metadata["plan_tier"])
|
||||
try:
|
||||
ensure_realm_does_not_have_active_plan(user.realm)
|
||||
except UpgradeWithExistingPlanError as e:
|
||||
billing_session.ensure_current_plan_is_upgradable(payment_intent.customer, plan_tier)
|
||||
except (UpgradeWithExistingPlanError, InvalidPlanUpgradeError) as e:
|
||||
stripe_invoice = stripe.Invoice.create(
|
||||
auto_advance=True,
|
||||
collection_method="charge_automatically",
|
||||
customer=stripe_payment_intent.customer,
|
||||
days_until_due=None,
|
||||
statement_descriptor="Zulip Cloud Standard Credit",
|
||||
statement_descriptor=CustomerPlan.name_from_tier(plan_tier).replace("Zulip ", "")
|
||||
+ " Credit",
|
||||
)
|
||||
stripe.Invoice.finalize_invoice(stripe_invoice)
|
||||
raise e
|
||||
|
||||
process_initial_upgrade(
|
||||
user,
|
||||
billing_session.process_initial_upgrade(
|
||||
plan_tier,
|
||||
int(metadata["licenses"]),
|
||||
metadata["license_management"] == "automatic",
|
||||
int(metadata["billing_schedule"]),
|
||||
True,
|
||||
False,
|
||||
billing_session.get_remote_server_legacy_plan(payment_intent.customer),
|
||||
)
|
||||
|
||||
|
||||
@error_handler
|
||||
def handle_payment_intent_payment_failed_event(
|
||||
stripe_payment_intent: stripe.PaymentIntent, payment_intent: PaymentIntent
|
||||
) -> None:
|
||||
payment_intent.status = PaymentIntent.get_status_integer_from_status_text(
|
||||
stripe_payment_intent.status
|
||||
)
|
||||
assert payment_intent.customer.realm is not None
|
||||
billing_logger.info(
|
||||
"Stripe payment intent failed: %s %s %s %s",
|
||||
payment_intent.customer.realm.string_id,
|
||||
stripe_payment_intent.last_payment_error.get("type"),
|
||||
stripe_payment_intent.last_payment_error.get("code"),
|
||||
stripe_payment_intent.last_payment_error.get("param"),
|
||||
)
|
||||
payment_intent.last_payment_error = {
|
||||
"description": stripe_payment_intent.last_payment_error.get("type"),
|
||||
}
|
||||
payment_intent.last_payment_error["message"] = stripe_payment_intent.last_payment_error.get(
|
||||
"message"
|
||||
)
|
||||
payment_intent.save(update_fields=["status", "last_payment_error"])
|
||||
|
||||
@@ -1,15 +1,71 @@
|
||||
from dataclasses import dataclass
|
||||
from decimal import Decimal
|
||||
from typing import Optional
|
||||
from urllib.parse import urlencode, urljoin, urlunsplit
|
||||
|
||||
from django.conf import settings
|
||||
from django.urls import reverse
|
||||
from django.utils.timezone import now as timezone_now
|
||||
|
||||
from corporate.lib.stripe import BillingSession
|
||||
from corporate.models import Customer, CustomerPlan, get_current_plan_by_customer
|
||||
from zerver.models import Realm, get_realm
|
||||
from zilencer.lib.remote_counts import MissingDataError
|
||||
|
||||
|
||||
def get_support_url(realm: Realm) -> str:
|
||||
@dataclass
|
||||
class PlanData:
|
||||
customer: Optional["Customer"] = None
|
||||
current_plan: Optional["CustomerPlan"] = None
|
||||
licenses: Optional[int] = None
|
||||
licenses_used: Optional[int] = None
|
||||
is_legacy_plan: bool = False
|
||||
has_fixed_price: bool = False
|
||||
warning: Optional[str] = None
|
||||
|
||||
|
||||
def get_realm_support_url(realm: Realm) -> str:
|
||||
support_realm_uri = get_realm(settings.STAFF_SUBDOMAIN).uri
|
||||
support_url = urljoin(
|
||||
support_realm_uri,
|
||||
urlunsplit(("", "", reverse("support"), urlencode({"q": realm.string_id}), "")),
|
||||
)
|
||||
return support_url
|
||||
|
||||
|
||||
def get_customer_discount_for_support_view(
|
||||
customer: Optional[Customer] = None,
|
||||
) -> Optional[Decimal]:
|
||||
if customer is None:
|
||||
return None
|
||||
return customer.default_discount
|
||||
|
||||
|
||||
def get_current_plan_data_for_support_view(billing_session: BillingSession) -> PlanData:
|
||||
customer = billing_session.get_customer()
|
||||
plan = None
|
||||
if customer is not None:
|
||||
plan = get_current_plan_by_customer(customer)
|
||||
plan_data = PlanData(
|
||||
customer=customer,
|
||||
current_plan=plan,
|
||||
)
|
||||
if plan is not None:
|
||||
new_plan, last_ledger_entry = billing_session.make_end_of_cycle_updates_if_needed(
|
||||
plan, timezone_now()
|
||||
)
|
||||
if last_ledger_entry is not None:
|
||||
if new_plan is not None:
|
||||
plan_data.current_plan = new_plan # nocoverage
|
||||
plan_data.licenses = last_ledger_entry.licenses
|
||||
try:
|
||||
plan_data.licenses_used = billing_session.current_count_for_billed_licenses()
|
||||
except MissingDataError: # nocoverage
|
||||
plan_data.warning = "Recent data missing: No information for used licenses"
|
||||
assert plan_data.current_plan is not None # for mypy
|
||||
plan_data.is_legacy_plan = (
|
||||
plan_data.current_plan.tier == CustomerPlan.TIER_SELF_HOSTED_LEGACY
|
||||
)
|
||||
plan_data.has_fixed_price = plan_data.current_plan.fixed_price is not None
|
||||
|
||||
return plan_data
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# Generated by Django 4.2.6 on 2023-11-11 14:16
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("corporate", "0018_customer_cloud_xor_self_hosted"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="zulipsponsorshiprequest",
|
||||
name="expected_total_users",
|
||||
field=models.TextField(default=""),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="zulipsponsorshiprequest",
|
||||
name="paid_users_count",
|
||||
field=models.TextField(default=""),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="zulipsponsorshiprequest",
|
||||
name="paid_users_description",
|
||||
field=models.TextField(default=""),
|
||||
),
|
||||
]
|
||||
37
corporate/migrations/0020_add_remote_realm_customers.py
Normal file
37
corporate/migrations/0020_add_remote_realm_customers.py
Normal file
@@ -0,0 +1,37 @@
|
||||
# Generated by Django 4.2.7 on 2023-11-17 20:11
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("zilencer", "0035_remoterealmcount_remote_realm_and_more"),
|
||||
("corporate", "0019_zulipsponsorshiprequest_expected_total_users_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveConstraint(
|
||||
model_name="customer",
|
||||
name="cloud_xor_self_hosted",
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="customer",
|
||||
name="remote_realm",
|
||||
field=models.OneToOneField(
|
||||
null=True, on_delete=django.db.models.deletion.CASCADE, to="zilencer.remoterealm"
|
||||
),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name="customer",
|
||||
constraint=models.CheckConstraint(
|
||||
check=models.Q(
|
||||
("realm__isnull", False),
|
||||
("remote_server__isnull", False),
|
||||
("remote_realm__isnull", False),
|
||||
_connector="OR",
|
||||
),
|
||||
name="has_associated_model_object",
|
||||
),
|
||||
),
|
||||
]
|
||||
16
corporate/migrations/0021_remove_session_payment_intent.py
Normal file
16
corporate/migrations/0021_remove_session_payment_intent.py
Normal file
@@ -0,0 +1,16 @@
|
||||
# Generated by Django 4.2.7 on 2023-11-18 14:54
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("corporate", "0020_add_remote_realm_customers"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name="session",
|
||||
name="payment_intent",
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,17 @@
|
||||
# Generated by Django 4.2.7 on 2023-11-21 11:20
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("corporate", "0021_remove_session_payment_intent"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="session",
|
||||
name="is_manual_license_management_upgrade_session",
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,20 @@
|
||||
# Generated by Django 4.2.7 on 2023-11-26 16:00
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("corporate", "0022_session_is_manual_license_management_upgrade_session"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="zulipsponsorshiprequest",
|
||||
name="customer",
|
||||
field=models.ForeignKey(
|
||||
null=True, on_delete=django.db.models.deletion.CASCADE, to="corporate.customer"
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("corporate", "0023_zulipsponsorshiprequest_customer"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunSQL(
|
||||
"""
|
||||
UPDATE corporate_zulipsponsorshiprequest
|
||||
SET customer_id = (
|
||||
SELECT id FROM corporate_customer WHERE corporate_customer.realm_id = corporate_zulipsponsorshiprequest.realm_id
|
||||
)
|
||||
"""
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,20 @@
|
||||
# Generated by Django 4.2.7 on 2023-11-26 16:13
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("corporate", "0024_zulipsponsorshiprequest_fill_customer_data"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="zulipsponsorshiprequest",
|
||||
name="customer",
|
||||
field=models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE, to="corporate.customer"
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,16 @@
|
||||
# Generated by Django 4.2.7 on 2023-11-26 16:14
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("corporate", "0025_alter_zulipsponsorshiprequest_customer"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name="zulipsponsorshiprequest",
|
||||
name="realm",
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,25 @@
|
||||
# Generated by Django 4.2.7 on 2023-11-28 16:00
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
("corporate", "0026_remove_zulipsponsorshiprequest_realm"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="zulipsponsorshiprequest",
|
||||
name="requested_by",
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,21 @@
|
||||
# Generated by Django 4.2.8 on 2023-12-08 18:03
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("corporate", "0027_alter_zulipsponsorshiprequest_requested_by"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="zulipsponsorshiprequest",
|
||||
name="requested_plan",
|
||||
field=models.CharField(
|
||||
choices=[("", "UNSPECIFIED"), ("Community", "COMMUNITY"), ("Business", "BUSINESS")],
|
||||
default="",
|
||||
max_length=50,
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -1,3 +1,4 @@
|
||||
from enum import Enum
|
||||
from typing import Any, Dict, Optional, Union
|
||||
|
||||
from django.contrib.contenttypes.fields import GenericForeignKey
|
||||
@@ -7,7 +8,7 @@ from django.db.models import CASCADE, Q
|
||||
from typing_extensions import override
|
||||
|
||||
from zerver.models import Realm, UserProfile
|
||||
from zilencer.models import RemoteZulipServer
|
||||
from zilencer.models import RemoteRealm, RemoteZulipServer
|
||||
|
||||
|
||||
class Customer(models.Model):
|
||||
@@ -17,8 +18,12 @@ class Customer(models.Model):
|
||||
and the active plan, if any.
|
||||
"""
|
||||
|
||||
# The actual model object that this customer is associated
|
||||
# with. Exactly one of the following will be non-null.
|
||||
realm = models.OneToOneField(Realm, on_delete=CASCADE, null=True)
|
||||
remote_realm = models.OneToOneField(RemoteRealm, on_delete=CASCADE, null=True)
|
||||
remote_server = models.OneToOneField(RemoteZulipServer, on_delete=CASCADE, null=True)
|
||||
|
||||
stripe_customer_id = models.CharField(max_length=255, null=True, unique=True)
|
||||
sponsorship_pending = models.BooleanField(default=False)
|
||||
# A percentage, like 85.
|
||||
@@ -30,22 +35,36 @@ class Customer(models.Model):
|
||||
exempt_from_license_number_check = models.BooleanField(default=False)
|
||||
|
||||
class Meta:
|
||||
# Enforce that at least one of these is set.
|
||||
constraints = [
|
||||
models.CheckConstraint(
|
||||
check=Q(realm__isnull=False) ^ Q(remote_server__isnull=False),
|
||||
name="cloud_xor_self_hosted",
|
||||
check=Q(realm__isnull=False)
|
||||
| Q(remote_server__isnull=False)
|
||||
| Q(remote_realm__isnull=False),
|
||||
name="has_associated_model_object",
|
||||
)
|
||||
]
|
||||
|
||||
@override
|
||||
def __str__(self) -> str:
|
||||
return f"{self.realm!r} {self.stripe_customer_id}"
|
||||
if self.realm is not None:
|
||||
return f"{self.realm!r} (with stripe_customer_id: {self.stripe_customer_id})"
|
||||
else:
|
||||
return f"{self.remote_server!r} (with stripe_customer_id: {self.stripe_customer_id})"
|
||||
|
||||
|
||||
def get_customer_by_realm(realm: Realm) -> Optional[Customer]:
|
||||
return Customer.objects.filter(realm=realm).first()
|
||||
|
||||
|
||||
def get_customer_by_remote_server(remote_server: RemoteZulipServer) -> Optional[Customer]:
|
||||
return Customer.objects.filter(remote_server=remote_server).first()
|
||||
|
||||
|
||||
def get_customer_by_remote_realm(remote_realm: RemoteRealm) -> Optional[Customer]: # nocoverage
|
||||
return Customer.objects.filter(remote_realm=remote_realm).first()
|
||||
|
||||
|
||||
class Event(models.Model):
|
||||
stripe_event_id = models.CharField(max_length=255)
|
||||
|
||||
@@ -88,29 +107,25 @@ def get_last_associated_event_by_type(
|
||||
class Session(models.Model):
|
||||
customer = models.ForeignKey(Customer, on_delete=CASCADE)
|
||||
stripe_session_id = models.CharField(max_length=255, unique=True)
|
||||
payment_intent = models.ForeignKey("PaymentIntent", null=True, on_delete=CASCADE)
|
||||
|
||||
UPGRADE_FROM_BILLING_PAGE = 1
|
||||
RETRY_UPGRADE_WITH_ANOTHER_PAYMENT_METHOD = 10
|
||||
FREE_TRIAL_UPGRADE_FROM_BILLING_PAGE = 20
|
||||
FREE_TRIAL_UPGRADE_FROM_ONBOARDING_PAGE = 30
|
||||
CARD_UPDATE_FROM_BILLING_PAGE = 40
|
||||
CARD_UPDATE_FROM_UPGRADE_PAGE = 50
|
||||
type = models.SmallIntegerField()
|
||||
|
||||
CREATED = 1
|
||||
COMPLETED = 10
|
||||
status = models.SmallIntegerField(default=CREATED)
|
||||
|
||||
# Did the user opt to manually manage licenses before clicking on update button?
|
||||
is_manual_license_management_upgrade_session = models.BooleanField(default=False)
|
||||
|
||||
def get_status_as_string(self) -> str:
|
||||
return {Session.CREATED: "created", Session.COMPLETED: "completed"}[self.status]
|
||||
|
||||
def get_type_as_string(self) -> str:
|
||||
return {
|
||||
Session.UPGRADE_FROM_BILLING_PAGE: "upgrade_from_billing_page",
|
||||
Session.RETRY_UPGRADE_WITH_ANOTHER_PAYMENT_METHOD: "retry_upgrade_with_another_payment_method",
|
||||
Session.FREE_TRIAL_UPGRADE_FROM_BILLING_PAGE: "free_trial_upgrade_from_billing_page",
|
||||
Session.FREE_TRIAL_UPGRADE_FROM_ONBOARDING_PAGE: "free_trial_upgrade_from_onboarding_page",
|
||||
Session.CARD_UPDATE_FROM_BILLING_PAGE: "card_update_from_billing_page",
|
||||
Session.CARD_UPDATE_FROM_UPGRADE_PAGE: "card_update_from_upgrade_page",
|
||||
}[self.type]
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
@@ -118,8 +133,9 @@ class Session(models.Model):
|
||||
|
||||
session_dict["status"] = self.get_status_as_string()
|
||||
session_dict["type"] = self.get_type_as_string()
|
||||
if self.payment_intent:
|
||||
session_dict["stripe_payment_intent_id"] = self.payment_intent.stripe_payment_intent_id
|
||||
session_dict[
|
||||
"is_manual_license_management_upgrade_session"
|
||||
] = self.is_manual_license_management_upgrade_session
|
||||
event = self.get_last_associated_event()
|
||||
if event is not None:
|
||||
session_dict["event_handler"] = event.get_event_handler_details_as_dict()
|
||||
@@ -164,18 +180,15 @@ class PaymentIntent(models.Model):
|
||||
def get_last_associated_event(self) -> Optional[Event]:
|
||||
if self.status == PaymentIntent.SUCCEEDED:
|
||||
event_type = "payment_intent.succeeded"
|
||||
elif self.status == PaymentIntent.REQUIRES_PAYMENT_METHOD:
|
||||
event_type = "payment_intent.payment_failed"
|
||||
else:
|
||||
return None
|
||||
# TODO: Add test for this case. Not sure how to trigger naturally.
|
||||
else: # nocoverage
|
||||
return None # nocoverage
|
||||
return get_last_associated_event_by_type(self, event_type)
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
payment_intent_dict: Dict[str, Any] = {}
|
||||
payment_intent_dict["status"] = self.get_status_as_string()
|
||||
event = self.get_last_associated_event()
|
||||
if self.last_payment_error:
|
||||
payment_intent_dict["last_payment_error"] = self.last_payment_error
|
||||
if event is not None:
|
||||
payment_intent_dict["event_handler"] = event.get_event_handler_details_as_dict()
|
||||
return payment_intent_dict
|
||||
@@ -211,8 +224,12 @@ class CustomerPlan(models.Model):
|
||||
# billing_cycle_anchor.
|
||||
billing_cycle_anchor = models.DateTimeField()
|
||||
|
||||
ANNUAL = 1
|
||||
MONTHLY = 2
|
||||
BILLING_SCHEDULE_ANNUAL = 1
|
||||
BILLING_SCHEDULE_MONTHLY = 2
|
||||
BILLING_SCHEDULES = {
|
||||
BILLING_SCHEDULE_ANNUAL: "Annual",
|
||||
BILLING_SCHEDULE_MONTHLY: "Monthly",
|
||||
}
|
||||
billing_schedule = models.SmallIntegerField()
|
||||
|
||||
# The next date the billing system should go through ledger
|
||||
@@ -232,24 +249,36 @@ class CustomerPlan(models.Model):
|
||||
)
|
||||
end_date = models.DateTimeField(null=True)
|
||||
|
||||
DONE = 1
|
||||
STARTED = 2
|
||||
INITIAL_INVOICE_TO_BE_SENT = 3
|
||||
INVOICING_STATUS_DONE = 1
|
||||
INVOICING_STATUS_STARTED = 2
|
||||
INVOICING_STATUS_INITIAL_INVOICE_TO_BE_SENT = 3
|
||||
# This status field helps ensure any errors encountered during the
|
||||
# invoicing process do not leave our invoicing system in a broken
|
||||
# state.
|
||||
invoicing_status = models.SmallIntegerField(default=DONE)
|
||||
invoicing_status = models.SmallIntegerField(default=INVOICING_STATUS_DONE)
|
||||
|
||||
STANDARD = 1
|
||||
PLUS = 2 # not available through self-serve signup
|
||||
ENTERPRISE = 10
|
||||
TIER_CLOUD_STANDARD = 1
|
||||
TIER_CLOUD_PLUS = 2
|
||||
# Reserved tier IDs for future use
|
||||
TIER_CLOUD_COMMUNITY = 3
|
||||
TIER_CLOUD_ENTERPRISE = 4
|
||||
|
||||
TIER_SELF_HOSTED_BASE = 100
|
||||
TIER_SELF_HOSTED_LEGACY = 101
|
||||
TIER_SELF_HOSTED_COMMUNITY = 102
|
||||
TIER_SELF_HOSTED_BUSINESS = 103
|
||||
TIER_SELF_HOSTED_PLUS = 104
|
||||
TIER_SELF_HOSTED_ENTERPRISE = 105
|
||||
tier = models.SmallIntegerField()
|
||||
|
||||
ACTIVE = 1
|
||||
DOWNGRADE_AT_END_OF_CYCLE = 2
|
||||
FREE_TRIAL = 3
|
||||
SWITCH_TO_ANNUAL_AT_END_OF_CYCLE = 4
|
||||
SWITCH_NOW_FROM_STANDARD_TO_PLUS = 5
|
||||
SWITCH_PLAN_TIER_NOW = 5
|
||||
SWITCH_TO_MONTHLY_AT_END_OF_CYCLE = 6
|
||||
DOWNGRADE_AT_END_OF_FREE_TRIAL = 7
|
||||
SWITCH_PLAN_TIER_AT_PLAN_END = 8
|
||||
# "Live" plans should have a value < LIVE_STATUS_THRESHOLD.
|
||||
# There should be at most one live plan per customer.
|
||||
LIVE_STATUS_THRESHOLD = 10
|
||||
@@ -260,19 +289,33 @@ class CustomerPlan(models.Model):
|
||||
# TODO maybe override setattr to ensure billing_cycle_anchor, etc
|
||||
# are immutable.
|
||||
|
||||
@staticmethod
|
||||
def name_from_tier(tier: int) -> str:
|
||||
# NOTE: Check `statement_descriptor` values after updating this.
|
||||
# Stripe has a 22 character limit on the statement descriptor length.
|
||||
# https://stripe.com/docs/payments/account/statement-descriptors
|
||||
return {
|
||||
CustomerPlan.TIER_CLOUD_STANDARD: "Zulip Cloud Standard",
|
||||
CustomerPlan.TIER_CLOUD_PLUS: "Zulip Cloud Plus",
|
||||
CustomerPlan.TIER_CLOUD_ENTERPRISE: "Zulip Enterprise",
|
||||
CustomerPlan.TIER_SELF_HOSTED_LEGACY: "Self-managed",
|
||||
CustomerPlan.TIER_SELF_HOSTED_BUSINESS: "Zulip Business",
|
||||
CustomerPlan.TIER_SELF_HOSTED_COMMUNITY: "Community",
|
||||
}[tier]
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return {
|
||||
CustomerPlan.STANDARD: "Zulip Cloud Standard",
|
||||
CustomerPlan.PLUS: "Zulip Plus",
|
||||
CustomerPlan.ENTERPRISE: "Zulip Enterprise",
|
||||
}[self.tier]
|
||||
return self.name_from_tier(self.tier)
|
||||
|
||||
def get_plan_status_as_text(self) -> str:
|
||||
return {
|
||||
self.ACTIVE: "Active",
|
||||
self.DOWNGRADE_AT_END_OF_CYCLE: "Scheduled for downgrade at end of cycle",
|
||||
self.FREE_TRIAL: "Free trial",
|
||||
self.SWITCH_TO_ANNUAL_AT_END_OF_CYCLE: "Scheduled for switch to annual at end of cycle",
|
||||
self.SWITCH_TO_MONTHLY_AT_END_OF_CYCLE: "Scheduled for switch to monthly at end of cycle",
|
||||
self.DOWNGRADE_AT_END_OF_FREE_TRIAL: "Scheduled for downgrade at end of free trial",
|
||||
self.SWITCH_PLAN_TIER_AT_PLAN_END: "Scheduled for switch to new plan at the end of plan",
|
||||
self.ENDED: "Ended",
|
||||
self.NEVER_STARTED: "Never started",
|
||||
}[self.status]
|
||||
@@ -283,7 +326,10 @@ class CustomerPlan(models.Model):
|
||||
return ledger_entry.licenses
|
||||
|
||||
def licenses_at_next_renewal(self) -> Optional[int]:
|
||||
if self.status == CustomerPlan.DOWNGRADE_AT_END_OF_CYCLE:
|
||||
if self.status in (
|
||||
CustomerPlan.DOWNGRADE_AT_END_OF_CYCLE,
|
||||
CustomerPlan.DOWNGRADE_AT_END_OF_FREE_TRIAL,
|
||||
):
|
||||
return None
|
||||
ledger_entry = LicenseLedger.objects.filter(plan=self).order_by("id").last()
|
||||
assert ledger_entry is not None
|
||||
@@ -340,9 +386,16 @@ class LicenseLedger(models.Model):
|
||||
licenses_at_next_renewal = models.IntegerField(null=True)
|
||||
|
||||
|
||||
class SponsoredPlanTypes(Enum):
|
||||
# unspecified used for cloud sponsorship requests
|
||||
UNSPECIFIED = ""
|
||||
COMMUNITY = "Community"
|
||||
BUSINESS = "Business"
|
||||
|
||||
|
||||
class ZulipSponsorshipRequest(models.Model):
|
||||
realm = models.ForeignKey(Realm, on_delete=CASCADE)
|
||||
requested_by = models.ForeignKey(UserProfile, on_delete=CASCADE)
|
||||
customer = models.ForeignKey(Customer, on_delete=CASCADE)
|
||||
requested_by = models.ForeignKey(UserProfile, on_delete=CASCADE, null=True, blank=True)
|
||||
|
||||
org_type = models.PositiveSmallIntegerField(
|
||||
default=Realm.ORG_TYPES["unspecified"]["id"],
|
||||
@@ -353,3 +406,12 @@ class ZulipSponsorshipRequest(models.Model):
|
||||
org_website = models.URLField(max_length=MAX_ORG_URL_LENGTH, blank=True, null=True)
|
||||
|
||||
org_description = models.TextField(default="")
|
||||
expected_total_users = models.TextField(default="")
|
||||
paid_users_count = models.TextField(default="")
|
||||
paid_users_description = models.TextField(default="")
|
||||
|
||||
requested_plan = models.CharField(
|
||||
max_length=50,
|
||||
choices=[(plan.value, plan.name) for plan in SponsoredPlanTypes],
|
||||
default=SponsoredPlanTypes.UNSPECIFIED.value,
|
||||
)
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
"name": null,
|
||||
"phone": null
|
||||
},
|
||||
"calculated_statement_descriptor": "ZULIP STANDARD",
|
||||
"calculated_statement_descriptor": "ZULIP CLOUD STANDARD",
|
||||
"captured": true,
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
@@ -30,6 +30,7 @@
|
||||
"destination": null,
|
||||
"dispute": null,
|
||||
"disputed": false,
|
||||
"failure_balance_transaction": null,
|
||||
"failure_code": null,
|
||||
"failure_message": null,
|
||||
"fraud_details": {},
|
||||
@@ -41,6 +42,7 @@
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"plan_tier": "1",
|
||||
"price_per_license": "1200",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
@@ -62,9 +64,10 @@
|
||||
},
|
||||
"paid": true,
|
||||
"payment_intent": "pi_NORMALIZED00000000000001",
|
||||
"payment_method": "pm_1K2OXoHSaWXyvFpKhrceNhbI",
|
||||
"payment_method": "pm_1OIlcUDEQaroqDjsqDT70KqK",
|
||||
"payment_method_details": {
|
||||
"card": {
|
||||
"amount_authorized": 7200,
|
||||
"brand": "visa",
|
||||
"checks": {
|
||||
"address_line1_check": null,
|
||||
@@ -72,21 +75,39 @@
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 3,
|
||||
"exp_year": 2033,
|
||||
"exp_month": 12,
|
||||
"exp_year": 2024,
|
||||
"extended_authorization": {
|
||||
"status": "disabled"
|
||||
},
|
||||
"fingerprint": "NORMALIZED000001",
|
||||
"funding": "credit",
|
||||
"incremental_authorization": {
|
||||
"status": "unavailable"
|
||||
},
|
||||
"installments": null,
|
||||
"last4": "4242",
|
||||
"mandate": null,
|
||||
"multicapture": {
|
||||
"status": "unavailable"
|
||||
},
|
||||
"network": "visa",
|
||||
"network_token": {
|
||||
"used": false
|
||||
},
|
||||
"overcapture": {
|
||||
"maximum_amount_capturable": 7200,
|
||||
"status": "unavailable"
|
||||
},
|
||||
"three_d_secure": null,
|
||||
"wallet": null
|
||||
},
|
||||
"type": "card"
|
||||
},
|
||||
"radar_options": {},
|
||||
"receipt_email": "hamlet@zulip.com",
|
||||
"receipt_number": null,
|
||||
"receipt_url": "https://pay.stripe.com/receipts/acct_NORMALIZED000001/ch_NORMALIZED00000000000001/rcpt_NORMALIZED000000000000000000001",
|
||||
"receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKIr9qqsGMgaM-GKNpmc6LBZoWb7DJvCIVhczLJKOYXKROrzmBYTFtupIgmreHcTL1xLwXB0pQP-R7gBA",
|
||||
"refunded": false,
|
||||
"refunds": {
|
||||
"data": [],
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
"name": null,
|
||||
"phone": null
|
||||
},
|
||||
"calculated_statement_descriptor": "ZULIP STANDARD",
|
||||
"calculated_statement_descriptor": "ZULIP CLOUD STANDARD",
|
||||
"captured": true,
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
@@ -30,6 +30,7 @@
|
||||
"destination": null,
|
||||
"dispute": null,
|
||||
"disputed": false,
|
||||
"failure_balance_transaction": null,
|
||||
"failure_code": null,
|
||||
"failure_message": null,
|
||||
"fraud_details": {},
|
||||
@@ -41,6 +42,7 @@
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"plan_tier": "1",
|
||||
"price_per_license": "6000",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
@@ -62,9 +64,10 @@
|
||||
},
|
||||
"paid": true,
|
||||
"payment_intent": "pi_NORMALIZED00000000000002",
|
||||
"payment_method": "pm_1K2OXyHSaWXyvFpKNE66Ex7T",
|
||||
"payment_method": "pm_1OIlceDEQaroqDjshc2Y2l9b",
|
||||
"payment_method_details": {
|
||||
"card": {
|
||||
"amount_authorized": 36000,
|
||||
"brand": "visa",
|
||||
"checks": {
|
||||
"address_line1_check": null,
|
||||
@@ -72,21 +75,39 @@
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 3,
|
||||
"exp_year": 2033,
|
||||
"exp_month": 12,
|
||||
"exp_year": 2024,
|
||||
"extended_authorization": {
|
||||
"status": "disabled"
|
||||
},
|
||||
"fingerprint": "NORMALIZED000001",
|
||||
"funding": "credit",
|
||||
"incremental_authorization": {
|
||||
"status": "unavailable"
|
||||
},
|
||||
"installments": null,
|
||||
"last4": "4242",
|
||||
"mandate": null,
|
||||
"multicapture": {
|
||||
"status": "unavailable"
|
||||
},
|
||||
"network": "visa",
|
||||
"network_token": {
|
||||
"used": false
|
||||
},
|
||||
"overcapture": {
|
||||
"maximum_amount_capturable": 36000,
|
||||
"status": "unavailable"
|
||||
},
|
||||
"three_d_secure": null,
|
||||
"wallet": null
|
||||
},
|
||||
"type": "card"
|
||||
},
|
||||
"radar_options": {},
|
||||
"receipt_email": "hamlet@zulip.com",
|
||||
"receipt_number": null,
|
||||
"receipt_url": "https://pay.stripe.com/receipts/acct_NORMALIZED000001/ch_NORMALIZED00000000000002/rcpt_NORMALIZED000000000000000000002",
|
||||
"receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKJT9qqsGMgbmGcE2CPg6LBYt6tPCI7CnKaxaLVq3zjSaM7atoyWnbp6xDOd4JEAbIIuFCeKskEzYWUyb",
|
||||
"refunded": false,
|
||||
"refunds": {
|
||||
"data": [],
|
||||
@@ -126,7 +147,7 @@
|
||||
"name": null,
|
||||
"phone": null
|
||||
},
|
||||
"calculated_statement_descriptor": "ZULIP STANDARD",
|
||||
"calculated_statement_descriptor": "ZULIP CLOUD STANDARD",
|
||||
"captured": true,
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
@@ -135,6 +156,7 @@
|
||||
"destination": null,
|
||||
"dispute": null,
|
||||
"disputed": false,
|
||||
"failure_balance_transaction": null,
|
||||
"failure_code": null,
|
||||
"failure_message": null,
|
||||
"fraud_details": {},
|
||||
@@ -146,6 +168,7 @@
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"plan_tier": "1",
|
||||
"price_per_license": "1200",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
@@ -167,9 +190,10 @@
|
||||
},
|
||||
"paid": true,
|
||||
"payment_intent": "pi_NORMALIZED00000000000001",
|
||||
"payment_method": "pm_1K2OXoHSaWXyvFpKhrceNhbI",
|
||||
"payment_method": "pm_1OIlcUDEQaroqDjsqDT70KqK",
|
||||
"payment_method_details": {
|
||||
"card": {
|
||||
"amount_authorized": 7200,
|
||||
"brand": "visa",
|
||||
"checks": {
|
||||
"address_line1_check": null,
|
||||
@@ -177,21 +201,39 @@
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 3,
|
||||
"exp_year": 2033,
|
||||
"exp_month": 12,
|
||||
"exp_year": 2024,
|
||||
"extended_authorization": {
|
||||
"status": "disabled"
|
||||
},
|
||||
"fingerprint": "NORMALIZED000001",
|
||||
"funding": "credit",
|
||||
"incremental_authorization": {
|
||||
"status": "unavailable"
|
||||
},
|
||||
"installments": null,
|
||||
"last4": "4242",
|
||||
"mandate": null,
|
||||
"multicapture": {
|
||||
"status": "unavailable"
|
||||
},
|
||||
"network": "visa",
|
||||
"network_token": {
|
||||
"used": false
|
||||
},
|
||||
"overcapture": {
|
||||
"maximum_amount_capturable": 7200,
|
||||
"status": "unavailable"
|
||||
},
|
||||
"three_d_secure": null,
|
||||
"wallet": null
|
||||
},
|
||||
"type": "card"
|
||||
},
|
||||
"radar_options": {},
|
||||
"receipt_email": "hamlet@zulip.com",
|
||||
"receipt_number": null,
|
||||
"receipt_url": "https://pay.stripe.com/receipts/acct_NORMALIZED000001/ch_NORMALIZED00000000000001/rcpt_NORMALIZED000000000000000000001",
|
||||
"receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKJT9qqsGMgZmMGKxY746LBarTbqnnWLLGRzmrQAWL3_ig-D1uUENWBVpjxcDGfuFmMRWLxqSgEkXJuqq",
|
||||
"refunded": false,
|
||||
"refunds": {
|
||||
"data": [],
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"balance": 0,
|
||||
"created": 1000000000,
|
||||
"currency": null,
|
||||
"default_currency": null,
|
||||
"default_source": null,
|
||||
"delinquent": false,
|
||||
"description": "zulip (Zulip Dev)",
|
||||
@@ -13,7 +14,8 @@
|
||||
"invoice_settings": {
|
||||
"custom_fields": null,
|
||||
"default_payment_method": null,
|
||||
"footer": null
|
||||
"footer": null,
|
||||
"rendering_options": null
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
@@ -26,5 +28,6 @@
|
||||
"phone": null,
|
||||
"preferred_locales": [],
|
||||
"shipping": null,
|
||||
"tax_exempt": "none"
|
||||
"tax_exempt": "none",
|
||||
"test_clock": null
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"balance": 0,
|
||||
"created": 1000000000,
|
||||
"currency": null,
|
||||
"default_currency": null,
|
||||
"default_source": null,
|
||||
"delinquent": false,
|
||||
"description": "zulip (Zulip Dev)",
|
||||
@@ -12,8 +13,9 @@
|
||||
"invoice_prefix": "NORMA01",
|
||||
"invoice_settings": {
|
||||
"custom_fields": null,
|
||||
"default_payment_method": null,
|
||||
"footer": null
|
||||
"default_payment_method": "pm_1OIlcUDEQaroqDjsqDT70KqK",
|
||||
"footer": null,
|
||||
"rendering_options": null
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
@@ -26,5 +28,6 @@
|
||||
"phone": null,
|
||||
"preferred_locales": [],
|
||||
"shipping": null,
|
||||
"tax_exempt": "none"
|
||||
"tax_exempt": "none",
|
||||
"test_clock": null
|
||||
}
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
"address": null,
|
||||
"balance": 0,
|
||||
"created": 1000000000,
|
||||
"currency": null,
|
||||
"currency": "usd",
|
||||
"default_currency": "usd",
|
||||
"default_source": null,
|
||||
"delinquent": false,
|
||||
"description": "zulip (Zulip Dev)",
|
||||
@@ -12,8 +13,9 @@
|
||||
"invoice_prefix": "NORMA01",
|
||||
"invoice_settings": {
|
||||
"custom_fields": null,
|
||||
"default_payment_method": "pm_1K2OXoHSaWXyvFpKhrceNhbI",
|
||||
"footer": null
|
||||
"default_payment_method": "pm_1OIlceDEQaroqDjshc2Y2l9b",
|
||||
"footer": null,
|
||||
"rendering_options": null
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
@@ -21,10 +23,11 @@
|
||||
"realm_str": "zulip"
|
||||
},
|
||||
"name": null,
|
||||
"next_invoice_sequence": 1,
|
||||
"next_invoice_sequence": 2,
|
||||
"object": "customer",
|
||||
"phone": null,
|
||||
"preferred_locales": [],
|
||||
"shipping": null,
|
||||
"tax_exempt": "none"
|
||||
"tax_exempt": "none",
|
||||
"test_clock": null
|
||||
}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
{
|
||||
"address": null,
|
||||
"balance": 0,
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"default_source": null,
|
||||
"delinquent": false,
|
||||
"description": "zulip (Zulip Dev)",
|
||||
"discount": null,
|
||||
"email": "hamlet@zulip.com",
|
||||
"id": "cus_NORMALIZED0001",
|
||||
"invoice_prefix": "NORMA01",
|
||||
"invoice_settings": {
|
||||
"custom_fields": null,
|
||||
"default_payment_method": "pm_1K2OXyHSaWXyvFpKNE66Ex7T",
|
||||
"footer": null
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip"
|
||||
},
|
||||
"name": null,
|
||||
"next_invoice_sequence": 2,
|
||||
"object": "customer",
|
||||
"phone": null,
|
||||
"preferred_locales": [],
|
||||
"shipping": null,
|
||||
"tax_exempt": "none"
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
"balance": 0,
|
||||
"created": 1000000000,
|
||||
"currency": null,
|
||||
"default_currency": null,
|
||||
"default_source": null,
|
||||
"delinquent": false,
|
||||
"description": "zulip (Zulip Dev)",
|
||||
@@ -34,12 +35,12 @@
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 3,
|
||||
"exp_year": 2033,
|
||||
"exp_month": 12,
|
||||
"exp_year": 2024,
|
||||
"fingerprint": "NORMALIZED000001",
|
||||
"funding": "credit",
|
||||
"generated_from": null,
|
||||
"last4": "0341",
|
||||
"last4": "4242",
|
||||
"networks": {
|
||||
"available": [
|
||||
"visa"
|
||||
@@ -53,13 +54,14 @@
|
||||
},
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"id": "pm_1K2ObQHSaWXyvFpK01Q0QnWB",
|
||||
"id": "pm_1OIlcUDEQaroqDjsqDT70KqK",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "payment_method",
|
||||
"type": "card"
|
||||
},
|
||||
"footer": null
|
||||
"footer": null,
|
||||
"rendering_options": null
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
@@ -72,5 +74,6 @@
|
||||
"phone": null,
|
||||
"preferred_locales": [],
|
||||
"shipping": null,
|
||||
"tax_exempt": "none"
|
||||
"tax_exempt": "none",
|
||||
"test_clock": null
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
"balance": 0,
|
||||
"created": 1000000000,
|
||||
"currency": null,
|
||||
"default_currency": null,
|
||||
"default_source": null,
|
||||
"delinquent": false,
|
||||
"description": "zulip (Zulip Dev)",
|
||||
@@ -34,12 +35,12 @@
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 3,
|
||||
"exp_year": 2033,
|
||||
"exp_month": 12,
|
||||
"exp_year": 2024,
|
||||
"fingerprint": "NORMALIZED000001",
|
||||
"funding": "credit",
|
||||
"generated_from": null,
|
||||
"last4": "0341",
|
||||
"last4": "4242",
|
||||
"networks": {
|
||||
"available": [
|
||||
"visa"
|
||||
@@ -53,13 +54,14 @@
|
||||
},
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"id": "pm_1K2Ob7HSaWXyvFpKia7kC5ud",
|
||||
"id": "pm_1OIlcUDEQaroqDjsqDT70KqK",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "payment_method",
|
||||
"type": "card"
|
||||
},
|
||||
"footer": null
|
||||
"footer": null,
|
||||
"rendering_options": null
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
@@ -72,5 +74,6 @@
|
||||
"phone": null,
|
||||
"preferred_locales": [],
|
||||
"shipping": null,
|
||||
"tax_exempt": "none"
|
||||
"tax_exempt": "none",
|
||||
"test_clock": null
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"address": null,
|
||||
"balance": 0,
|
||||
"created": 1000000000,
|
||||
"currency": null,
|
||||
"default_currency": null,
|
||||
"default_source": null,
|
||||
"delinquent": false,
|
||||
"description": "zulip (Zulip Dev)",
|
||||
"discount": null,
|
||||
"email": "hamlet@zulip.com",
|
||||
"id": "cus_NORMALIZED0001",
|
||||
"invoice_prefix": "NORMA01",
|
||||
"invoice_settings": {
|
||||
"custom_fields": null,
|
||||
"default_payment_method": {
|
||||
"billing_details": {
|
||||
"address": {
|
||||
"city": null,
|
||||
"country": null,
|
||||
"line1": null,
|
||||
"line2": null,
|
||||
"postal_code": null,
|
||||
"state": null
|
||||
},
|
||||
"email": null,
|
||||
"name": null,
|
||||
"phone": null
|
||||
},
|
||||
"card": {
|
||||
"brand": "visa",
|
||||
"checks": {
|
||||
"address_line1_check": null,
|
||||
"address_postal_code_check": null,
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 12,
|
||||
"exp_year": 2024,
|
||||
"fingerprint": "NORMALIZED000001",
|
||||
"funding": "credit",
|
||||
"generated_from": null,
|
||||
"last4": "4242",
|
||||
"networks": {
|
||||
"available": [
|
||||
"visa"
|
||||
],
|
||||
"preferred": null
|
||||
},
|
||||
"three_d_secure_usage": {
|
||||
"supported": true
|
||||
},
|
||||
"wallet": null
|
||||
},
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"id": "pm_1OIlcUDEQaroqDjsqDT70KqK",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "payment_method",
|
||||
"type": "card"
|
||||
},
|
||||
"footer": null,
|
||||
"rendering_options": null
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip"
|
||||
},
|
||||
"name": null,
|
||||
"next_invoice_sequence": 1,
|
||||
"object": "customer",
|
||||
"phone": null,
|
||||
"preferred_locales": [],
|
||||
"shipping": null,
|
||||
"tax_exempt": "none",
|
||||
"test_clock": null
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"address": null,
|
||||
"balance": 0,
|
||||
"created": 1000000000,
|
||||
"currency": null,
|
||||
"default_currency": null,
|
||||
"default_source": null,
|
||||
"delinquent": false,
|
||||
"description": "zulip (Zulip Dev)",
|
||||
"discount": null,
|
||||
"email": "hamlet@zulip.com",
|
||||
"id": "cus_NORMALIZED0001",
|
||||
"invoice_prefix": "NORMA01",
|
||||
"invoice_settings": {
|
||||
"custom_fields": null,
|
||||
"default_payment_method": {
|
||||
"billing_details": {
|
||||
"address": {
|
||||
"city": null,
|
||||
"country": null,
|
||||
"line1": null,
|
||||
"line2": null,
|
||||
"postal_code": null,
|
||||
"state": null
|
||||
},
|
||||
"email": null,
|
||||
"name": null,
|
||||
"phone": null
|
||||
},
|
||||
"card": {
|
||||
"brand": "visa",
|
||||
"checks": {
|
||||
"address_line1_check": null,
|
||||
"address_postal_code_check": null,
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 12,
|
||||
"exp_year": 2024,
|
||||
"fingerprint": "NORMALIZED000001",
|
||||
"funding": "credit",
|
||||
"generated_from": null,
|
||||
"last4": "4242",
|
||||
"networks": {
|
||||
"available": [
|
||||
"visa"
|
||||
],
|
||||
"preferred": null
|
||||
},
|
||||
"three_d_secure_usage": {
|
||||
"supported": true
|
||||
},
|
||||
"wallet": null
|
||||
},
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"id": "pm_1OIlcUDEQaroqDjsqDT70KqK",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "payment_method",
|
||||
"type": "card"
|
||||
},
|
||||
"footer": null,
|
||||
"rendering_options": null
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip"
|
||||
},
|
||||
"name": null,
|
||||
"next_invoice_sequence": 1,
|
||||
"object": "customer",
|
||||
"phone": null,
|
||||
"preferred_locales": [],
|
||||
"shipping": null,
|
||||
"tax_exempt": "none",
|
||||
"test_clock": null
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"address": null,
|
||||
"balance": 0,
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"default_currency": "usd",
|
||||
"default_source": null,
|
||||
"delinquent": false,
|
||||
"description": "zulip (Zulip Dev)",
|
||||
"discount": null,
|
||||
"email": "hamlet@zulip.com",
|
||||
"id": "cus_NORMALIZED0001",
|
||||
"invoice_prefix": "NORMA01",
|
||||
"invoice_settings": {
|
||||
"custom_fields": null,
|
||||
"default_payment_method": {
|
||||
"billing_details": {
|
||||
"address": {
|
||||
"city": null,
|
||||
"country": null,
|
||||
"line1": null,
|
||||
"line2": null,
|
||||
"postal_code": null,
|
||||
"state": null
|
||||
},
|
||||
"email": null,
|
||||
"name": null,
|
||||
"phone": null
|
||||
},
|
||||
"card": {
|
||||
"brand": "visa",
|
||||
"checks": {
|
||||
"address_line1_check": null,
|
||||
"address_postal_code_check": null,
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 12,
|
||||
"exp_year": 2024,
|
||||
"fingerprint": "NORMALIZED000001",
|
||||
"funding": "credit",
|
||||
"generated_from": null,
|
||||
"last4": "4242",
|
||||
"networks": {
|
||||
"available": [
|
||||
"visa"
|
||||
],
|
||||
"preferred": null
|
||||
},
|
||||
"three_d_secure_usage": {
|
||||
"supported": true
|
||||
},
|
||||
"wallet": null
|
||||
},
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"id": "pm_1OIlceDEQaroqDjshc2Y2l9b",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "payment_method",
|
||||
"type": "card"
|
||||
},
|
||||
"footer": null,
|
||||
"rendering_options": null
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip"
|
||||
},
|
||||
"name": null,
|
||||
"next_invoice_sequence": 2,
|
||||
"object": "customer",
|
||||
"phone": null,
|
||||
"preferred_locales": [],
|
||||
"shipping": null,
|
||||
"tax_exempt": "none",
|
||||
"test_clock": null
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"address": null,
|
||||
"balance": 0,
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"default_currency": "usd",
|
||||
"default_source": null,
|
||||
"delinquent": false,
|
||||
"description": "zulip (Zulip Dev)",
|
||||
"discount": null,
|
||||
"email": "hamlet@zulip.com",
|
||||
"id": "cus_NORMALIZED0001",
|
||||
"invoice_prefix": "NORMA01",
|
||||
"invoice_settings": {
|
||||
"custom_fields": null,
|
||||
"default_payment_method": {
|
||||
"billing_details": {
|
||||
"address": {
|
||||
"city": null,
|
||||
"country": null,
|
||||
"line1": null,
|
||||
"line2": null,
|
||||
"postal_code": null,
|
||||
"state": null
|
||||
},
|
||||
"email": null,
|
||||
"name": null,
|
||||
"phone": null
|
||||
},
|
||||
"card": {
|
||||
"brand": "visa",
|
||||
"checks": {
|
||||
"address_line1_check": null,
|
||||
"address_postal_code_check": null,
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 12,
|
||||
"exp_year": 2024,
|
||||
"fingerprint": "NORMALIZED000001",
|
||||
"funding": "credit",
|
||||
"generated_from": null,
|
||||
"last4": "4242",
|
||||
"networks": {
|
||||
"available": [
|
||||
"visa"
|
||||
],
|
||||
"preferred": null
|
||||
},
|
||||
"three_d_secure_usage": {
|
||||
"supported": true
|
||||
},
|
||||
"wallet": null
|
||||
},
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"id": "pm_1OIlceDEQaroqDjshc2Y2l9b",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "payment_method",
|
||||
"type": "card"
|
||||
},
|
||||
"footer": null,
|
||||
"rendering_options": null
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip"
|
||||
},
|
||||
"name": null,
|
||||
"next_invoice_sequence": 2,
|
||||
"object": "customer",
|
||||
"phone": null,
|
||||
"preferred_locales": [],
|
||||
"shipping": null,
|
||||
"tax_exempt": "none",
|
||||
"test_clock": null
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"address": null,
|
||||
"balance": 0,
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"default_currency": "usd",
|
||||
"default_source": null,
|
||||
"delinquent": false,
|
||||
"description": "zulip (Zulip Dev)",
|
||||
"discount": null,
|
||||
"email": "hamlet@zulip.com",
|
||||
"id": "cus_NORMALIZED0001",
|
||||
"invoice_prefix": "NORMA01",
|
||||
"invoice_settings": {
|
||||
"custom_fields": null,
|
||||
"default_payment_method": {
|
||||
"billing_details": {
|
||||
"address": {
|
||||
"city": null,
|
||||
"country": null,
|
||||
"line1": null,
|
||||
"line2": null,
|
||||
"postal_code": null,
|
||||
"state": null
|
||||
},
|
||||
"email": null,
|
||||
"name": null,
|
||||
"phone": null
|
||||
},
|
||||
"card": {
|
||||
"brand": "visa",
|
||||
"checks": {
|
||||
"address_line1_check": null,
|
||||
"address_postal_code_check": null,
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 12,
|
||||
"exp_year": 2024,
|
||||
"fingerprint": "NORMALIZED000001",
|
||||
"funding": "credit",
|
||||
"generated_from": null,
|
||||
"last4": "4242",
|
||||
"networks": {
|
||||
"available": [
|
||||
"visa"
|
||||
],
|
||||
"preferred": null
|
||||
},
|
||||
"three_d_secure_usage": {
|
||||
"supported": true
|
||||
},
|
||||
"wallet": null
|
||||
},
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"id": "pm_1OIlceDEQaroqDjshc2Y2l9b",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "payment_method",
|
||||
"type": "card"
|
||||
},
|
||||
"footer": null,
|
||||
"rendering_options": null
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip"
|
||||
},
|
||||
"name": null,
|
||||
"next_invoice_sequence": 2,
|
||||
"object": "customer",
|
||||
"phone": null,
|
||||
"preferred_locales": [],
|
||||
"shipping": null,
|
||||
"tax_exempt": "none",
|
||||
"test_clock": null
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"address": null,
|
||||
"balance": 0,
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"default_currency": "usd",
|
||||
"default_source": null,
|
||||
"delinquent": false,
|
||||
"description": "zulip (Zulip Dev)",
|
||||
"discount": null,
|
||||
"email": "hamlet@zulip.com",
|
||||
"id": "cus_NORMALIZED0001",
|
||||
"invoice_prefix": "NORMA01",
|
||||
"invoice_settings": {
|
||||
"custom_fields": null,
|
||||
"default_payment_method": {
|
||||
"billing_details": {
|
||||
"address": {
|
||||
"city": null,
|
||||
"country": null,
|
||||
"line1": null,
|
||||
"line2": null,
|
||||
"postal_code": null,
|
||||
"state": null
|
||||
},
|
||||
"email": null,
|
||||
"name": null,
|
||||
"phone": null
|
||||
},
|
||||
"card": {
|
||||
"brand": "visa",
|
||||
"checks": {
|
||||
"address_line1_check": null,
|
||||
"address_postal_code_check": null,
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 12,
|
||||
"exp_year": 2024,
|
||||
"fingerprint": "NORMALIZED000001",
|
||||
"funding": "credit",
|
||||
"generated_from": null,
|
||||
"last4": "4242",
|
||||
"networks": {
|
||||
"available": [
|
||||
"visa"
|
||||
],
|
||||
"preferred": null
|
||||
},
|
||||
"three_d_secure_usage": {
|
||||
"supported": true
|
||||
},
|
||||
"wallet": null
|
||||
},
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"id": "pm_1OIlceDEQaroqDjshc2Y2l9b",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "payment_method",
|
||||
"type": "card"
|
||||
},
|
||||
"footer": null,
|
||||
"rendering_options": null
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip"
|
||||
},
|
||||
"name": null,
|
||||
"next_invoice_sequence": 2,
|
||||
"object": "customer",
|
||||
"phone": null,
|
||||
"preferred_locales": [],
|
||||
"shipping": null,
|
||||
"tax_exempt": "none",
|
||||
"test_clock": null
|
||||
}
|
||||
@@ -5,189 +5,53 @@
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"account_country": "US",
|
||||
"account_name": "NORMALIZED-1",
|
||||
"account_tax_ids": null,
|
||||
"amount_due": 0,
|
||||
"amount_paid": 0,
|
||||
"amount_remaining": 0,
|
||||
"application_fee_amount": null,
|
||||
"attempt_count": 0,
|
||||
"attempted": true,
|
||||
"auto_advance": false,
|
||||
"automatic_tax": {
|
||||
"enabled": false,
|
||||
"status": null
|
||||
},
|
||||
"billing_reason": "manual",
|
||||
"charge": null,
|
||||
"collection_method": "charge_automatically",
|
||||
"address": null,
|
||||
"balance": 0,
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"custom_fields": null,
|
||||
"customer": "cus_NORMALIZED0002",
|
||||
"customer_address": null,
|
||||
"customer_email": "hamlet@zulip.com",
|
||||
"customer_name": null,
|
||||
"customer_phone": null,
|
||||
"customer_shipping": null,
|
||||
"customer_tax_exempt": "none",
|
||||
"customer_tax_ids": [],
|
||||
"default_payment_method": null,
|
||||
"currency": null,
|
||||
"default_currency": null,
|
||||
"default_source": null,
|
||||
"default_tax_rates": [],
|
||||
"description": null,
|
||||
"delinquent": false,
|
||||
"description": "zulip (Zulip Dev)",
|
||||
"discount": null,
|
||||
"discounts": [],
|
||||
"due_date": null,
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9BRzhHOXVXS0dTMk5hbEl2TEhOdnM1ZUF0dloz0100yY43uPHV",
|
||||
"id": "in_NORMALIZED00000000000001",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9BRzhHOXVXS0dTMk5hbEl2TEhOdnM1ZUF0dloz0100yY43uPHV/pdf",
|
||||
"last_finalization_error": null,
|
||||
"lines": {
|
||||
"data": [
|
||||
{
|
||||
"amount": 48000,
|
||||
"currency": "usd",
|
||||
"description": "Zulip Cloud Standard",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000001",
|
||||
"invoice_item": "ii_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
"active": false,
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0001",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
"transform_quantity": null,
|
||||
"type": "one_time",
|
||||
"unit_amount": 8000,
|
||||
"unit_amount_decimal": "8000"
|
||||
},
|
||||
"proration": false,
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
},
|
||||
{
|
||||
"amount": -48000,
|
||||
"currency": "usd",
|
||||
"description": "Payment (Card ending in 4242)",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000002",
|
||||
"invoice_item": "ii_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
"active": false,
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0002",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
"transform_quantity": null,
|
||||
"type": "one_time",
|
||||
"unit_amount": -48000,
|
||||
"unit_amount_decimal": "-48000"
|
||||
},
|
||||
"proration": false,
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000001/lines"
|
||||
"email": "hamlet@zulip.com",
|
||||
"id": "cus_NORMALIZED0001",
|
||||
"invoice_prefix": "NORMA01",
|
||||
"invoice_settings": {
|
||||
"custom_fields": null,
|
||||
"default_payment_method": "pm_1OIlcUDEQaroqDjsqDT70KqK",
|
||||
"footer": null,
|
||||
"rendering_options": null
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"next_payment_attempt": null,
|
||||
"number": "NORMALI-0001",
|
||||
"object": "invoice",
|
||||
"on_behalf_of": null,
|
||||
"paid": true,
|
||||
"payment_intent": null,
|
||||
"payment_settings": {
|
||||
"payment_method_options": null,
|
||||
"payment_method_types": null
|
||||
"metadata": {
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip"
|
||||
},
|
||||
"period_end": 1000000000,
|
||||
"period_start": 1000000000,
|
||||
"post_payment_credit_notes_amount": 0,
|
||||
"pre_payment_credit_notes_amount": 0,
|
||||
"quote": null,
|
||||
"receipt_number": null,
|
||||
"starting_balance": 0,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"status": "paid",
|
||||
"status_transitions": {
|
||||
"finalized_at": 1000000000,
|
||||
"marked_uncollectible_at": null,
|
||||
"paid_at": 1000000000,
|
||||
"voided_at": null
|
||||
},
|
||||
"subscription": null,
|
||||
"subtotal": 0,
|
||||
"tax": null,
|
||||
"total": 0,
|
||||
"total_discount_amounts": [],
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": null
|
||||
"name": null,
|
||||
"next_invoice_sequence": 1,
|
||||
"object": "customer",
|
||||
"phone": null,
|
||||
"preferred_locales": [],
|
||||
"shipping": null,
|
||||
"tax_exempt": "none",
|
||||
"test_clock": null
|
||||
},
|
||||
"previous_attributes": {
|
||||
"invoice_settings": {
|
||||
"default_payment_method": null
|
||||
}
|
||||
}
|
||||
},
|
||||
"id": "evt_1K2OXlHSaWXyvFpKIjChqmtl",
|
||||
"id": "evt_1OIlcWDEQaroqDjsDYC5kGA8",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0001",
|
||||
"idempotency_key": "cae8e48c-5622-4bdf-85a2-cb06a7ed12d4"
|
||||
"idempotency_key": "ec0d8ceb-bc0b-4141-9ecf-9f91d42f5a7e"
|
||||
},
|
||||
"type": "invoice.payment_succeeded"
|
||||
"type": "customer.updated"
|
||||
}
|
||||
],
|
||||
"has_more": true,
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
"object": {
|
||||
"amount": 7200,
|
||||
"amount_capturable": 0,
|
||||
"amount_details": {
|
||||
"tip": {}
|
||||
},
|
||||
"amount_received": 7200,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
@@ -37,7 +40,7 @@
|
||||
"name": null,
|
||||
"phone": null
|
||||
},
|
||||
"calculated_statement_descriptor": "ZULIP STANDARD",
|
||||
"calculated_statement_descriptor": "ZULIP CLOUD STANDARD",
|
||||
"captured": true,
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
@@ -46,6 +49,7 @@
|
||||
"destination": null,
|
||||
"dispute": null,
|
||||
"disputed": false,
|
||||
"failure_balance_transaction": null,
|
||||
"failure_code": null,
|
||||
"failure_message": null,
|
||||
"fraud_details": {},
|
||||
@@ -57,6 +61,7 @@
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"plan_tier": "1",
|
||||
"price_per_license": "1200",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
@@ -78,9 +83,10 @@
|
||||
},
|
||||
"paid": true,
|
||||
"payment_intent": "pi_NORMALIZED00000000000001",
|
||||
"payment_method": "pm_1K2OXoHSaWXyvFpKhrceNhbI",
|
||||
"payment_method": "pm_1OIlcUDEQaroqDjsqDT70KqK",
|
||||
"payment_method_details": {
|
||||
"card": {
|
||||
"amount_authorized": 7200,
|
||||
"brand": "visa",
|
||||
"checks": {
|
||||
"address_line1_check": null,
|
||||
@@ -88,21 +94,39 @@
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 3,
|
||||
"exp_year": 2033,
|
||||
"exp_month": 12,
|
||||
"exp_year": 2024,
|
||||
"extended_authorization": {
|
||||
"status": "disabled"
|
||||
},
|
||||
"fingerprint": "NORMALIZED000001",
|
||||
"funding": "credit",
|
||||
"incremental_authorization": {
|
||||
"status": "unavailable"
|
||||
},
|
||||
"installments": null,
|
||||
"last4": "4242",
|
||||
"mandate": null,
|
||||
"multicapture": {
|
||||
"status": "unavailable"
|
||||
},
|
||||
"network": "visa",
|
||||
"network_token": {
|
||||
"used": false
|
||||
},
|
||||
"overcapture": {
|
||||
"maximum_amount_capturable": 7200,
|
||||
"status": "unavailable"
|
||||
},
|
||||
"three_d_secure": null,
|
||||
"wallet": null
|
||||
},
|
||||
"type": "card"
|
||||
},
|
||||
"radar_options": {},
|
||||
"receipt_email": "hamlet@zulip.com",
|
||||
"receipt_number": null,
|
||||
"receipt_url": "https://pay.stripe.com/receipts/acct_NORMALIZED000001/ch_NORMALIZED00000000000001/rcpt_NORMALIZED000000000000000000001",
|
||||
"receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKIf9qqsGMgZb20Gi7do6LBb8Nk4YXcMYuHylkNS09JAb63jzjtrknnoa60TiX-hHWdshgcroMLKDWN5c",
|
||||
"refunded": false,
|
||||
"refunds": {
|
||||
"data": [],
|
||||
@@ -127,7 +151,7 @@
|
||||
"total_count": 1,
|
||||
"url": "/v1/charges?payment_intent=pi_NORMALIZED00000000000001"
|
||||
},
|
||||
"client_secret": "pi_NORMALIZED00000000000001_secret_fD7F9AdDLLYQt94Ii4rEflkYg",
|
||||
"client_secret": "pi_NORMALIZED00000000000001_secret_TT71wq3meHmzTEd7mpZbqrDnP",
|
||||
"confirmation_method": "automatic",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
@@ -136,12 +160,14 @@
|
||||
"id": "pi_NORMALIZED00000000000001",
|
||||
"invoice": null,
|
||||
"last_payment_error": null,
|
||||
"latest_charge": "ch_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
"billing_modality": "charge_automatically",
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"plan_tier": "1",
|
||||
"price_per_license": "1200",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
@@ -153,10 +179,12 @@
|
||||
"next_action": null,
|
||||
"object": "payment_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": "pm_1K2OXoHSaWXyvFpKhrceNhbI",
|
||||
"payment_method": "pm_1OIlcUDEQaroqDjsqDT70KqK",
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"installments": null,
|
||||
"mandate_options": null,
|
||||
"network": null,
|
||||
"request_three_d_secure": "automatic"
|
||||
}
|
||||
@@ -164,6 +192,7 @@
|
||||
"payment_method_types": [
|
||||
"card"
|
||||
],
|
||||
"processing": null,
|
||||
"receipt_email": "hamlet@zulip.com",
|
||||
"review": null,
|
||||
"setup_future_usage": null,
|
||||
@@ -176,13 +205,13 @@
|
||||
"transfer_group": null
|
||||
}
|
||||
},
|
||||
"id": "evt_3K2OXoHSaWXyvFpK1IgAmGCx",
|
||||
"id": "evt_3OIlcYDEQaroqDjs16WfiUYV",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"pending_webhooks": 2,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0002",
|
||||
"idempotency_key": "bbd6840b-375d-408a-a4b2-0353118fef83"
|
||||
"idempotency_key": "89f4d29d-4c41-4c1d-baf7-b33a1c7d25ff"
|
||||
},
|
||||
"type": "payment_intent.succeeded"
|
||||
},
|
||||
@@ -211,7 +240,7 @@
|
||||
"name": null,
|
||||
"phone": null
|
||||
},
|
||||
"calculated_statement_descriptor": "ZULIP STANDARD",
|
||||
"calculated_statement_descriptor": "ZULIP CLOUD STANDARD",
|
||||
"captured": true,
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
@@ -220,6 +249,7 @@
|
||||
"destination": null,
|
||||
"dispute": null,
|
||||
"disputed": false,
|
||||
"failure_balance_transaction": null,
|
||||
"failure_code": null,
|
||||
"failure_message": null,
|
||||
"fraud_details": {},
|
||||
@@ -231,6 +261,7 @@
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"plan_tier": "1",
|
||||
"price_per_license": "1200",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
@@ -252,9 +283,10 @@
|
||||
},
|
||||
"paid": true,
|
||||
"payment_intent": "pi_NORMALIZED00000000000001",
|
||||
"payment_method": "pm_1K2OXoHSaWXyvFpKhrceNhbI",
|
||||
"payment_method": "pm_1OIlcUDEQaroqDjsqDT70KqK",
|
||||
"payment_method_details": {
|
||||
"card": {
|
||||
"amount_authorized": 7200,
|
||||
"brand": "visa",
|
||||
"checks": {
|
||||
"address_line1_check": null,
|
||||
@@ -262,21 +294,39 @@
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 3,
|
||||
"exp_year": 2033,
|
||||
"exp_month": 12,
|
||||
"exp_year": 2024,
|
||||
"extended_authorization": {
|
||||
"status": "disabled"
|
||||
},
|
||||
"fingerprint": "NORMALIZED000001",
|
||||
"funding": "credit",
|
||||
"incremental_authorization": {
|
||||
"status": "unavailable"
|
||||
},
|
||||
"installments": null,
|
||||
"last4": "4242",
|
||||
"mandate": null,
|
||||
"multicapture": {
|
||||
"status": "unavailable"
|
||||
},
|
||||
"network": "visa",
|
||||
"network_token": {
|
||||
"used": false
|
||||
},
|
||||
"overcapture": {
|
||||
"maximum_amount_capturable": 7200,
|
||||
"status": "unavailable"
|
||||
},
|
||||
"three_d_secure": null,
|
||||
"wallet": null
|
||||
},
|
||||
"type": "card"
|
||||
},
|
||||
"radar_options": {},
|
||||
"receipt_email": "hamlet@zulip.com",
|
||||
"receipt_number": null,
|
||||
"receipt_url": "https://pay.stripe.com/receipts/acct_NORMALIZED000001/ch_NORMALIZED00000000000001/rcpt_NORMALIZED000000000000000000001",
|
||||
"receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKIf9qqsGMgaRG54HB6k6LBYbdkPPJRe4ZuuV5tR6SrHKPTGj9DFYvf8ZlOiAmw8lVKk8NDaGGFlsjRM8",
|
||||
"refunded": false,
|
||||
"refunds": {
|
||||
"data": [],
|
||||
@@ -296,420 +346,15 @@
|
||||
"transfer_group": null
|
||||
}
|
||||
},
|
||||
"id": "evt_3K2OXoHSaWXyvFpK1BCXNPsv",
|
||||
"id": "evt_3OIlcYDEQaroqDjs1OA8t8hC",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 2,
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0002",
|
||||
"idempotency_key": "bbd6840b-375d-408a-a4b2-0353118fef83"
|
||||
"idempotency_key": "89f4d29d-4c41-4c1d-baf7-b33a1c7d25ff"
|
||||
},
|
||||
"type": "charge.succeeded"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"address": null,
|
||||
"balance": 0,
|
||||
"created": 1000000000,
|
||||
"currency": null,
|
||||
"default_source": null,
|
||||
"delinquent": false,
|
||||
"description": "zulip (Zulip Dev)",
|
||||
"discount": null,
|
||||
"email": "hamlet@zulip.com",
|
||||
"id": "cus_NORMALIZED0001",
|
||||
"invoice_prefix": "NORMA01",
|
||||
"invoice_settings": {
|
||||
"custom_fields": null,
|
||||
"default_payment_method": "pm_1K2OXoHSaWXyvFpKhrceNhbI",
|
||||
"footer": null
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip"
|
||||
},
|
||||
"name": null,
|
||||
"next_invoice_sequence": 1,
|
||||
"object": "customer",
|
||||
"phone": null,
|
||||
"preferred_locales": [],
|
||||
"shipping": null,
|
||||
"tax_exempt": "none"
|
||||
},
|
||||
"previous_attributes": {
|
||||
"invoice_settings": {
|
||||
"default_payment_method": null
|
||||
}
|
||||
}
|
||||
},
|
||||
"id": "evt_1K2OXrHSaWXyvFpKTft9z8iM",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0003",
|
||||
"idempotency_key": "41855f8d-7eaf-45a3-8f4b-ebf23c527d2a"
|
||||
},
|
||||
"type": "customer.updated"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"application": null,
|
||||
"cancellation_reason": null,
|
||||
"client_secret": "seti_1K2OXpHSaWXyvFpKOq6F3F9K_secret_KhoAzpsEjV8G4oAeYDSFmGYMKv5BRkc",
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": null,
|
||||
"id": "seti_1K2OXpHSaWXyvFpKOq6F3F9K",
|
||||
"last_setup_error": null,
|
||||
"latest_attempt": "setatt_1K2OXpHSaWXyvFpKcauo7Bx8",
|
||||
"livemode": false,
|
||||
"mandate": null,
|
||||
"metadata": {
|
||||
"billing_modality": "charge_automatically",
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"price_per_license": "1200",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
"seat_count": "6",
|
||||
"type": "upgrade",
|
||||
"user_email": "hamlet@zulip.com",
|
||||
"user_id": "10"
|
||||
},
|
||||
"next_action": null,
|
||||
"object": "setup_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": "pm_1K2OXoHSaWXyvFpKhrceNhbI",
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"request_three_d_secure": "automatic"
|
||||
}
|
||||
},
|
||||
"payment_method_types": [
|
||||
"card"
|
||||
],
|
||||
"single_use_mandate": null,
|
||||
"status": "succeeded",
|
||||
"usage": "off_session"
|
||||
}
|
||||
},
|
||||
"id": "evt_1K2OXqHSaWXyvFpKyccpbqqf",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0004",
|
||||
"idempotency_key": "8c0e4f10-2995-45d3-9b35-aa76865e3557"
|
||||
},
|
||||
"type": "setup_intent.succeeded"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"billing_details": {
|
||||
"address": {
|
||||
"city": null,
|
||||
"country": null,
|
||||
"line1": null,
|
||||
"line2": null,
|
||||
"postal_code": null,
|
||||
"state": null
|
||||
},
|
||||
"email": null,
|
||||
"name": null,
|
||||
"phone": null
|
||||
},
|
||||
"card": {
|
||||
"brand": "visa",
|
||||
"checks": {
|
||||
"address_line1_check": null,
|
||||
"address_postal_code_check": null,
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 3,
|
||||
"exp_year": 2033,
|
||||
"fingerprint": "NORMALIZED000001",
|
||||
"funding": "credit",
|
||||
"generated_from": null,
|
||||
"last4": "4242",
|
||||
"networks": {
|
||||
"available": [
|
||||
"visa"
|
||||
],
|
||||
"preferred": null
|
||||
},
|
||||
"three_d_secure_usage": {
|
||||
"supported": true
|
||||
},
|
||||
"wallet": null
|
||||
},
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"id": "pm_1K2OXoHSaWXyvFpKhrceNhbI",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "payment_method",
|
||||
"type": "card"
|
||||
}
|
||||
},
|
||||
"id": "evt_1K2OXqHSaWXyvFpKUpLnWMHc",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0004",
|
||||
"idempotency_key": "8c0e4f10-2995-45d3-9b35-aa76865e3557"
|
||||
},
|
||||
"type": "payment_method.attached"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"application": null,
|
||||
"cancellation_reason": null,
|
||||
"client_secret": "seti_1K2OXpHSaWXyvFpKOq6F3F9K_secret_KhoAzpsEjV8G4oAeYDSFmGYMKv5BRkc",
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": null,
|
||||
"id": "seti_1K2OXpHSaWXyvFpKOq6F3F9K",
|
||||
"last_setup_error": null,
|
||||
"latest_attempt": "setatt_1K2OXpHSaWXyvFpKcauo7Bx8",
|
||||
"livemode": false,
|
||||
"mandate": null,
|
||||
"metadata": {
|
||||
"billing_modality": "charge_automatically",
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"price_per_license": "1200",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
"seat_count": "6",
|
||||
"type": "upgrade",
|
||||
"user_email": "hamlet@zulip.com",
|
||||
"user_id": "10"
|
||||
},
|
||||
"next_action": null,
|
||||
"object": "setup_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": "pm_1K2OXoHSaWXyvFpKhrceNhbI",
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"request_three_d_secure": "automatic"
|
||||
}
|
||||
},
|
||||
"payment_method_types": [
|
||||
"card"
|
||||
],
|
||||
"single_use_mandate": null,
|
||||
"status": "succeeded",
|
||||
"usage": "off_session"
|
||||
}
|
||||
},
|
||||
"id": "evt_1K2OXqHSaWXyvFpKZ0zBpGzN",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0004",
|
||||
"idempotency_key": "8c0e4f10-2995-45d3-9b35-aa76865e3557"
|
||||
},
|
||||
"type": "setup_intent.created"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"application": null,
|
||||
"cancellation_reason": null,
|
||||
"client_secret": "seti_1K2OXoHSaWXyvFpKLyy5ns16_secret_KhoANgFdO2YICL1Urfnax58nGUY0MeV",
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": null,
|
||||
"id": "seti_1K2OXoHSaWXyvFpKLyy5ns16",
|
||||
"last_setup_error": null,
|
||||
"latest_attempt": null,
|
||||
"livemode": false,
|
||||
"mandate": null,
|
||||
"metadata": {
|
||||
"billing_modality": "charge_automatically",
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"price_per_license": "1200",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
"seat_count": "6",
|
||||
"type": "upgrade",
|
||||
"user_email": "hamlet@zulip.com",
|
||||
"user_id": "10"
|
||||
},
|
||||
"next_action": null,
|
||||
"object": "setup_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"request_three_d_secure": "automatic"
|
||||
}
|
||||
},
|
||||
"payment_method_types": [
|
||||
"card"
|
||||
],
|
||||
"single_use_mandate": null,
|
||||
"status": "requires_payment_method",
|
||||
"usage": "off_session"
|
||||
}
|
||||
},
|
||||
"id": "evt_1K2OXoHSaWXyvFpKm8uayD4o",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0005",
|
||||
"idempotency_key": "1eca5c75-5177-4abb-94c1-4e6c39916bef"
|
||||
},
|
||||
"type": "setup_intent.created"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"amount": 7200,
|
||||
"amount_capturable": 0,
|
||||
"amount_received": 0,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"automatic_payment_methods": null,
|
||||
"canceled_at": null,
|
||||
"cancellation_reason": null,
|
||||
"capture_method": "automatic",
|
||||
"charges": {
|
||||
"data": [],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 0,
|
||||
"url": "/v1/charges?payment_intent=pi_NORMALIZED00000000000001"
|
||||
},
|
||||
"client_secret": "pi_NORMALIZED00000000000001_secret_fD7F9AdDLLYQt94Ii4rEflkYg",
|
||||
"confirmation_method": "automatic",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": "Upgrade to Zulip Cloud Standard, $12.0 x 6",
|
||||
"id": "pi_NORMALIZED00000000000001",
|
||||
"invoice": null,
|
||||
"last_payment_error": null,
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
"billing_modality": "charge_automatically",
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"price_per_license": "1200",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
"seat_count": "6",
|
||||
"type": "upgrade",
|
||||
"user_email": "hamlet@zulip.com",
|
||||
"user_id": "10"
|
||||
},
|
||||
"next_action": null,
|
||||
"object": "payment_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"installments": null,
|
||||
"network": null,
|
||||
"request_three_d_secure": "automatic"
|
||||
}
|
||||
},
|
||||
"payment_method_types": [
|
||||
"card"
|
||||
],
|
||||
"receipt_email": "hamlet@zulip.com",
|
||||
"review": null,
|
||||
"setup_future_usage": null,
|
||||
"shipping": null,
|
||||
"source": null,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"statement_descriptor_suffix": null,
|
||||
"status": "requires_payment_method",
|
||||
"transfer_data": null,
|
||||
"transfer_group": null
|
||||
}
|
||||
},
|
||||
"id": "evt_3K2OXoHSaWXyvFpK1tATyd2u",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0006",
|
||||
"idempotency_key": "d6ea8ee3-361c-451e-a3d7-e841957c3d25"
|
||||
},
|
||||
"type": "payment_intent.created"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"address": null,
|
||||
"balance": 0,
|
||||
"created": 1000000000,
|
||||
"currency": null,
|
||||
"default_source": null,
|
||||
"delinquent": false,
|
||||
"description": "zulip (Zulip Dev)",
|
||||
"discount": null,
|
||||
"email": "hamlet@zulip.com",
|
||||
"id": "cus_NORMALIZED0001",
|
||||
"invoice_prefix": "NORMA01",
|
||||
"invoice_settings": {
|
||||
"custom_fields": null,
|
||||
"default_payment_method": null,
|
||||
"footer": null
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip"
|
||||
},
|
||||
"name": null,
|
||||
"next_invoice_sequence": 1,
|
||||
"object": "customer",
|
||||
"phone": null,
|
||||
"preferred_locales": [],
|
||||
"shipping": null,
|
||||
"tax_exempt": "none"
|
||||
}
|
||||
},
|
||||
"id": "evt_1K2OXnHSaWXyvFpKsZOF5R1j",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0007",
|
||||
"idempotency_key": "d4faf9c7-d357-4870-b964-b1d993c5c058"
|
||||
},
|
||||
"type": "customer.created"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
|
||||
@@ -6,11 +6,13 @@
|
||||
"data": {
|
||||
"object": {
|
||||
"account_country": "US",
|
||||
"account_name": "NORMALIZED-1",
|
||||
"account_name": "Kandra Labs, Inc.",
|
||||
"account_tax_ids": null,
|
||||
"amount_due": 0,
|
||||
"amount_paid": 0,
|
||||
"amount_remaining": 0,
|
||||
"amount_shipping": 0,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"attempt_count": 0,
|
||||
"attempted": true,
|
||||
@@ -40,29 +42,33 @@
|
||||
"discount": null,
|
||||
"discounts": [],
|
||||
"due_date": null,
|
||||
"effective_at": 1000000000,
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9BNDRqUzlSeE5ZbkM2YXNhYmhHRDNCN0pTZ3E001000SGRn6zX",
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9BNDRqUzlSeE5ZbkM2YXNhYmhHRDNCN0pTZ3E001000SGRn6zX/pdf",
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpiMHNFNHp4OGxtTUNIclNiWWdZa0NQNmpqMVRJLDkyMDM1MjA502000hPybKLo?s=ap",
|
||||
"id": "in_NORMALIZED00000000000001",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpiMHNFNHp4OGxtTUNIclNiWWdZa0NQNmpqMVRJLDkyMDM1MjA502000hPybKLo/pdf?s=ap",
|
||||
"last_finalization_error": null,
|
||||
"latest_revision": null,
|
||||
"lines": {
|
||||
"data": [
|
||||
{
|
||||
"amount": 7200,
|
||||
"amount_excluding_tax": 7200,
|
||||
"currency": "usd",
|
||||
"description": "Zulip Cloud Standard",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000003",
|
||||
"invoice_item": "ii_NORMALIZED00000000000003",
|
||||
"id": "il_NORMALIZED00000000000001",
|
||||
"invoice_item": "ii_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
"end": 1357095845,
|
||||
"start": 1325473445
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
@@ -70,13 +76,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000003",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0003",
|
||||
"product": "prod_NORMALIZED0001",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -86,21 +93,26 @@
|
||||
"unit_amount_decimal": "1200"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "1200"
|
||||
},
|
||||
{
|
||||
"amount": -7200,
|
||||
"amount_excluding_tax": -7200,
|
||||
"currency": "usd",
|
||||
"description": "Payment (Card ending in 4242)",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000004",
|
||||
"invoice_item": "ii_NORMALIZED00000000000004",
|
||||
"id": "il_NORMALIZED00000000000002",
|
||||
"invoice_item": "ii_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -114,13 +126,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0004",
|
||||
"product": "prod_NORMALIZED0002",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -130,27 +143,33 @@
|
||||
"unit_amount_decimal": "-7200"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "-7200"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000001/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"next_payment_attempt": null,
|
||||
"number": "NORMALI-0002",
|
||||
"number": "NORMALI-0001",
|
||||
"object": "invoice",
|
||||
"on_behalf_of": null,
|
||||
"paid": true,
|
||||
"paid_out_of_band": false,
|
||||
"payment_intent": null,
|
||||
"payment_settings": {
|
||||
"default_mandate": null,
|
||||
"payment_method_options": null,
|
||||
"payment_method_types": null
|
||||
},
|
||||
@@ -160,6 +179,15 @@
|
||||
"pre_payment_credit_notes_amount": 0,
|
||||
"quote": null,
|
||||
"receipt_number": null,
|
||||
"rendering": {
|
||||
"amount_tax_display": null,
|
||||
"pdf": {
|
||||
"page_size": "letter"
|
||||
}
|
||||
},
|
||||
"rendering_options": null,
|
||||
"shipping_cost": null,
|
||||
"shipping_details": null,
|
||||
"starting_balance": 0,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"status": "paid",
|
||||
@@ -170,10 +198,16 @@
|
||||
"voided_at": null
|
||||
},
|
||||
"subscription": null,
|
||||
"subscription_details": {
|
||||
"metadata": null
|
||||
},
|
||||
"subtotal": 0,
|
||||
"subtotal_excluding_tax": 0,
|
||||
"tax": null,
|
||||
"test_clock": null,
|
||||
"total": 0,
|
||||
"total_discount_amounts": [],
|
||||
"total_excluding_tax": 0,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": null
|
||||
@@ -181,12 +215,18 @@
|
||||
"previous_attributes": {
|
||||
"attempted": false,
|
||||
"auto_advance": true,
|
||||
"effective_at": null,
|
||||
"ending_balance": null,
|
||||
"hosted_invoice_url": null,
|
||||
"invoice_pdf": null,
|
||||
"next_payment_attempt": 1000000000,
|
||||
"number": null,
|
||||
"paid": false,
|
||||
"rendering": {
|
||||
"pdf": {
|
||||
"page_size": "auto"
|
||||
}
|
||||
},
|
||||
"status": "draft",
|
||||
"status_transitions": {
|
||||
"finalized_at": null,
|
||||
@@ -194,13 +234,13 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"id": "evt_1K2OXvHSaWXyvFpKAxZLQePJ",
|
||||
"id": "evt_1OIlcbDEQaroqDjs0RgNo7tS",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 2,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0008",
|
||||
"idempotency_key": "f3d64bf5-ddf0-4933-86ee-96e9f6aa7149"
|
||||
"id": "req_NORMALIZED0003",
|
||||
"idempotency_key": "d8040535-2a29-417e-a8cd-313f534cb633"
|
||||
},
|
||||
"type": "invoice.updated"
|
||||
},
|
||||
@@ -210,11 +250,13 @@
|
||||
"data": {
|
||||
"object": {
|
||||
"account_country": "US",
|
||||
"account_name": "NORMALIZED-1",
|
||||
"account_name": "Kandra Labs, Inc.",
|
||||
"account_tax_ids": null,
|
||||
"amount_due": 0,
|
||||
"amount_paid": 0,
|
||||
"amount_remaining": 0,
|
||||
"amount_shipping": 0,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"attempt_count": 0,
|
||||
"attempted": false,
|
||||
@@ -244,29 +286,33 @@
|
||||
"discount": null,
|
||||
"discounts": [],
|
||||
"due_date": null,
|
||||
"effective_at": null,
|
||||
"ending_balance": null,
|
||||
"footer": null,
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": null,
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"id": "in_NORMALIZED00000000000001",
|
||||
"invoice_pdf": null,
|
||||
"last_finalization_error": null,
|
||||
"latest_revision": null,
|
||||
"lines": {
|
||||
"data": [
|
||||
{
|
||||
"amount": 7200,
|
||||
"amount_excluding_tax": 7200,
|
||||
"currency": "usd",
|
||||
"description": "Zulip Cloud Standard",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000003",
|
||||
"invoice_item": "ii_NORMALIZED00000000000003",
|
||||
"id": "il_NORMALIZED00000000000001",
|
||||
"invoice_item": "ii_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
"end": 1357095845,
|
||||
"start": 1325473445
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
@@ -274,13 +320,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000003",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0003",
|
||||
"product": "prod_NORMALIZED0001",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -290,21 +337,26 @@
|
||||
"unit_amount_decimal": "1200"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "1200"
|
||||
},
|
||||
{
|
||||
"amount": -7200,
|
||||
"amount_excluding_tax": -7200,
|
||||
"currency": "usd",
|
||||
"description": "Payment (Card ending in 4242)",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000004",
|
||||
"invoice_item": "ii_NORMALIZED00000000000004",
|
||||
"id": "il_NORMALIZED00000000000002",
|
||||
"invoice_item": "ii_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -318,13 +370,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0004",
|
||||
"product": "prod_NORMALIZED0002",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -334,17 +387,21 @@
|
||||
"unit_amount_decimal": "-7200"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "-7200"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000001/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
@@ -353,8 +410,10 @@
|
||||
"object": "invoice",
|
||||
"on_behalf_of": null,
|
||||
"paid": false,
|
||||
"paid_out_of_band": false,
|
||||
"payment_intent": null,
|
||||
"payment_settings": {
|
||||
"default_mandate": null,
|
||||
"payment_method_options": null,
|
||||
"payment_method_types": null
|
||||
},
|
||||
@@ -364,6 +423,15 @@
|
||||
"pre_payment_credit_notes_amount": 0,
|
||||
"quote": null,
|
||||
"receipt_number": null,
|
||||
"rendering": {
|
||||
"amount_tax_display": null,
|
||||
"pdf": {
|
||||
"page_size": "auto"
|
||||
}
|
||||
},
|
||||
"rendering_options": null,
|
||||
"shipping_cost": null,
|
||||
"shipping_details": null,
|
||||
"starting_balance": 0,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"status": "draft",
|
||||
@@ -374,88 +442,31 @@
|
||||
"voided_at": null
|
||||
},
|
||||
"subscription": null,
|
||||
"subscription_details": {
|
||||
"metadata": null
|
||||
},
|
||||
"subtotal": 0,
|
||||
"subtotal_excluding_tax": 0,
|
||||
"tax": null,
|
||||
"test_clock": null,
|
||||
"total": 0,
|
||||
"total_discount_amounts": [],
|
||||
"total_excluding_tax": 0,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": null
|
||||
}
|
||||
},
|
||||
"id": "evt_1K2OXvHSaWXyvFpKykfdKZvo",
|
||||
"id": "evt_1OIlcaDEQaroqDjsgW8xhHxB",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0009",
|
||||
"idempotency_key": "6f6f6557-9e62-418d-ac7f-8a0a1f602c00"
|
||||
"id": "req_NORMALIZED0004",
|
||||
"idempotency_key": "e1bdf299-f588-4704-ae2c-82d0debf6534"
|
||||
},
|
||||
"type": "invoice.created"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"amount": -7200,
|
||||
"currency": "usd",
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"date": 1000000000,
|
||||
"description": "Payment (Card ending in 4242)",
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "ii_NORMALIZED00000000000004",
|
||||
"invoice": "in_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "invoiceitem",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
"active": false,
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0004",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
"transform_quantity": null,
|
||||
"type": "one_time",
|
||||
"unit_amount": -7200,
|
||||
"unit_amount_decimal": "-7200"
|
||||
},
|
||||
"proration": false,
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_rates": [],
|
||||
"unit_amount": -7200,
|
||||
"unit_amount_decimal": "-7200"
|
||||
},
|
||||
"previous_attributes": {
|
||||
"invoice": null
|
||||
}
|
||||
},
|
||||
"id": "evt_1K2OXvHSaWXyvFpKRcyaG8m2",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0009",
|
||||
"idempotency_key": "6f6f6557-9e62-418d-ac7f-8a0a1f602c00"
|
||||
},
|
||||
"type": "invoiceitem.updated"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
@@ -468,77 +479,14 @@
|
||||
"description": "Zulip Cloud Standard",
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "ii_NORMALIZED00000000000003",
|
||||
"invoice": "in_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "invoiceitem",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
"active": false,
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000003",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0003",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
"transform_quantity": null,
|
||||
"type": "one_time",
|
||||
"unit_amount": 1200,
|
||||
"unit_amount_decimal": "1200"
|
||||
},
|
||||
"proration": false,
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_rates": [],
|
||||
"unit_amount": 1200,
|
||||
"unit_amount_decimal": "1200"
|
||||
},
|
||||
"previous_attributes": {
|
||||
"invoice": null
|
||||
}
|
||||
},
|
||||
"id": "evt_1K2OXvHSaWXyvFpKGZKUgbvc",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0009",
|
||||
"idempotency_key": "6f6f6557-9e62-418d-ac7f-8a0a1f602c00"
|
||||
},
|
||||
"type": "invoiceitem.updated"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"amount": 7200,
|
||||
"currency": "usd",
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"date": 1000000000,
|
||||
"description": "Zulip Cloud Standard",
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "ii_NORMALIZED00000000000003",
|
||||
"id": "ii_NORMALIZED00000000000001",
|
||||
"invoice": null,
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "invoiceitem",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
"end": 1357095845,
|
||||
"start": 1325473445
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
@@ -546,13 +494,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000003",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0003",
|
||||
"product": "prod_NORMALIZED0001",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -565,17 +514,18 @@
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_rates": [],
|
||||
"test_clock": null,
|
||||
"unit_amount": 1200,
|
||||
"unit_amount_decimal": "1200"
|
||||
}
|
||||
},
|
||||
"id": "evt_1K2OXuHSaWXyvFpK7gSvsu8e",
|
||||
"id": "evt_1OIlcaDEQaroqDjsCma6I5rr",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0010",
|
||||
"idempotency_key": "b60066b7-cf3e-4569-aa2e-8050562cedb4"
|
||||
"id": "req_NORMALIZED0005",
|
||||
"idempotency_key": "cfb4b441-f25a-4d95-a2f0-f0f950bd40fe"
|
||||
},
|
||||
"type": "invoiceitem.created"
|
||||
},
|
||||
@@ -591,7 +541,7 @@
|
||||
"description": "Payment (Card ending in 4242)",
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "ii_NORMALIZED00000000000004",
|
||||
"id": "ii_NORMALIZED00000000000002",
|
||||
"invoice": null,
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
@@ -606,13 +556,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0004",
|
||||
"product": "prod_NORMALIZED0002",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -625,17 +576,18 @@
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_rates": [],
|
||||
"test_clock": null,
|
||||
"unit_amount": -7200,
|
||||
"unit_amount_decimal": "-7200"
|
||||
}
|
||||
},
|
||||
"id": "evt_1K2OXuHSaWXyvFpK4K7m30wK",
|
||||
"id": "evt_1OIlcZDEQaroqDjs6GyIO3FO",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0011",
|
||||
"idempotency_key": "cd6054f5-d831-4874-9ed9-d7b0e3b24336"
|
||||
"id": "req_NORMALIZED0006",
|
||||
"idempotency_key": "13255827-b4d3-42fe-9f18-fbcb67305a04"
|
||||
},
|
||||
"type": "invoiceitem.created"
|
||||
},
|
||||
@@ -648,6 +600,7 @@
|
||||
"balance": 0,
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"default_currency": "usd",
|
||||
"default_source": null,
|
||||
"delinquent": false,
|
||||
"description": "zulip (Zulip Dev)",
|
||||
@@ -657,8 +610,9 @@
|
||||
"invoice_prefix": "NORMA01",
|
||||
"invoice_settings": {
|
||||
"custom_fields": null,
|
||||
"default_payment_method": "pm_1K2OXoHSaWXyvFpKhrceNhbI",
|
||||
"footer": null
|
||||
"default_payment_method": "pm_1OIlcUDEQaroqDjsqDT70KqK",
|
||||
"footer": null,
|
||||
"rendering_options": null
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
@@ -671,19 +625,21 @@
|
||||
"phone": null,
|
||||
"preferred_locales": [],
|
||||
"shipping": null,
|
||||
"tax_exempt": "none"
|
||||
"tax_exempt": "none",
|
||||
"test_clock": null
|
||||
},
|
||||
"previous_attributes": {
|
||||
"currency": null
|
||||
"currency": null,
|
||||
"default_currency": null
|
||||
}
|
||||
},
|
||||
"id": "evt_1K2OXtHSaWXyvFpKaZ6mOKiF",
|
||||
"id": "evt_1OIlcZDEQaroqDjs2IZnZELZ",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0011",
|
||||
"idempotency_key": "cd6054f5-d831-4874-9ed9-d7b0e3b24336"
|
||||
"id": "req_NORMALIZED0006",
|
||||
"idempotency_key": "13255827-b4d3-42fe-9f18-fbcb67305a04"
|
||||
},
|
||||
"type": "customer.updated"
|
||||
}
|
||||
|
||||
@@ -6,11 +6,13 @@
|
||||
"data": {
|
||||
"object": {
|
||||
"account_country": "US",
|
||||
"account_name": "NORMALIZED-1",
|
||||
"account_name": "Kandra Labs, Inc.",
|
||||
"account_tax_ids": null,
|
||||
"amount_due": 0,
|
||||
"amount_paid": 0,
|
||||
"amount_remaining": 0,
|
||||
"amount_shipping": 0,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"attempt_count": 0,
|
||||
"attempted": true,
|
||||
@@ -40,29 +42,33 @@
|
||||
"discount": null,
|
||||
"discounts": [],
|
||||
"due_date": null,
|
||||
"effective_at": 1000000000,
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9BNDRqUzlSeE5ZbkM2YXNhYmhHRDNCN0pTZ3E001000SGRn6zX",
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9BNDRqUzlSeE5ZbkM2YXNhYmhHRDNCN0pTZ3E001000SGRn6zX/pdf",
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpiMHNFNHp4OGxtTUNIclNiWWdZa0NQNmpqMVRJLDkyMDM1MjEw0200uGqIV7uQ?s=ap",
|
||||
"id": "in_NORMALIZED00000000000001",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpiMHNFNHp4OGxtTUNIclNiWWdZa0NQNmpqMVRJLDkyMDM1MjEw0200uGqIV7uQ/pdf?s=ap",
|
||||
"last_finalization_error": null,
|
||||
"latest_revision": null,
|
||||
"lines": {
|
||||
"data": [
|
||||
{
|
||||
"amount": 7200,
|
||||
"amount_excluding_tax": 7200,
|
||||
"currency": "usd",
|
||||
"description": "Zulip Cloud Standard",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000003",
|
||||
"invoice_item": "ii_NORMALIZED00000000000003",
|
||||
"id": "il_NORMALIZED00000000000001",
|
||||
"invoice_item": "ii_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
"end": 1357095845,
|
||||
"start": 1325473445
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
@@ -70,13 +76,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000003",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0003",
|
||||
"product": "prod_NORMALIZED0001",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -86,21 +93,26 @@
|
||||
"unit_amount_decimal": "1200"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "1200"
|
||||
},
|
||||
{
|
||||
"amount": -7200,
|
||||
"amount_excluding_tax": -7200,
|
||||
"currency": "usd",
|
||||
"description": "Payment (Card ending in 4242)",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000004",
|
||||
"invoice_item": "ii_NORMALIZED00000000000004",
|
||||
"id": "il_NORMALIZED00000000000002",
|
||||
"invoice_item": "ii_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -114,13 +126,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0004",
|
||||
"product": "prod_NORMALIZED0002",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -130,27 +143,33 @@
|
||||
"unit_amount_decimal": "-7200"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "-7200"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000001/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"next_payment_attempt": null,
|
||||
"number": "NORMALI-0003",
|
||||
"number": "NORMALI-0002",
|
||||
"object": "invoice",
|
||||
"on_behalf_of": null,
|
||||
"paid": true,
|
||||
"paid_out_of_band": false,
|
||||
"payment_intent": null,
|
||||
"payment_settings": {
|
||||
"default_mandate": null,
|
||||
"payment_method_options": null,
|
||||
"payment_method_types": null
|
||||
},
|
||||
@@ -160,6 +179,15 @@
|
||||
"pre_payment_credit_notes_amount": 0,
|
||||
"quote": null,
|
||||
"receipt_number": null,
|
||||
"rendering": {
|
||||
"amount_tax_display": null,
|
||||
"pdf": {
|
||||
"page_size": "letter"
|
||||
}
|
||||
},
|
||||
"rendering_options": null,
|
||||
"shipping_cost": null,
|
||||
"shipping_details": null,
|
||||
"starting_balance": 0,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"status": "paid",
|
||||
@@ -170,22 +198,28 @@
|
||||
"voided_at": null
|
||||
},
|
||||
"subscription": null,
|
||||
"subscription_details": {
|
||||
"metadata": null
|
||||
},
|
||||
"subtotal": 0,
|
||||
"subtotal_excluding_tax": 0,
|
||||
"tax": null,
|
||||
"test_clock": null,
|
||||
"total": 0,
|
||||
"total_discount_amounts": [],
|
||||
"total_excluding_tax": 0,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": null
|
||||
}
|
||||
},
|
||||
"id": "evt_1K2OXwHSaWXyvFpKr5uez7KF",
|
||||
"id": "evt_1OIlccDEQaroqDjsArfDmoTy",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"pending_webhooks": 2,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0008",
|
||||
"idempotency_key": "f3d64bf5-ddf0-4933-86ee-96e9f6aa7149"
|
||||
"id": "req_NORMALIZED0003",
|
||||
"idempotency_key": "d8040535-2a29-417e-a8cd-313f534cb633"
|
||||
},
|
||||
"type": "invoice.payment_succeeded"
|
||||
},
|
||||
@@ -195,11 +229,13 @@
|
||||
"data": {
|
||||
"object": {
|
||||
"account_country": "US",
|
||||
"account_name": "NORMALIZED-1",
|
||||
"account_name": "Kandra Labs, Inc.",
|
||||
"account_tax_ids": null,
|
||||
"amount_due": 0,
|
||||
"amount_paid": 0,
|
||||
"amount_remaining": 0,
|
||||
"amount_shipping": 0,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"attempt_count": 0,
|
||||
"attempted": true,
|
||||
@@ -229,29 +265,33 @@
|
||||
"discount": null,
|
||||
"discounts": [],
|
||||
"due_date": null,
|
||||
"effective_at": 1000000000,
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9BNDRqUzlSeE5ZbkM2YXNhYmhHRDNCN0pTZ3E001000SGRn6zX",
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9BNDRqUzlSeE5ZbkM2YXNhYmhHRDNCN0pTZ3E001000SGRn6zX/pdf",
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpiMHNFNHp4OGxtTUNIclNiWWdZa0NQNmpqMVRJLDkyMDM1MjA502000hPybKLo?s=ap",
|
||||
"id": "in_NORMALIZED00000000000001",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpiMHNFNHp4OGxtTUNIclNiWWdZa0NQNmpqMVRJLDkyMDM1MjA502000hPybKLo/pdf?s=ap",
|
||||
"last_finalization_error": null,
|
||||
"latest_revision": null,
|
||||
"lines": {
|
||||
"data": [
|
||||
{
|
||||
"amount": 7200,
|
||||
"amount_excluding_tax": 7200,
|
||||
"currency": "usd",
|
||||
"description": "Zulip Cloud Standard",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000003",
|
||||
"invoice_item": "ii_NORMALIZED00000000000003",
|
||||
"id": "il_NORMALIZED00000000000001",
|
||||
"invoice_item": "ii_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
"end": 1357095845,
|
||||
"start": 1325473445
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
@@ -259,13 +299,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000003",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0003",
|
||||
"product": "prod_NORMALIZED0001",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -275,21 +316,26 @@
|
||||
"unit_amount_decimal": "1200"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "1200"
|
||||
},
|
||||
{
|
||||
"amount": -7200,
|
||||
"amount_excluding_tax": -7200,
|
||||
"currency": "usd",
|
||||
"description": "Payment (Card ending in 4242)",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000004",
|
||||
"invoice_item": "ii_NORMALIZED00000000000004",
|
||||
"id": "il_NORMALIZED00000000000002",
|
||||
"invoice_item": "ii_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -303,13 +349,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0004",
|
||||
"product": "prod_NORMALIZED0002",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -319,27 +366,33 @@
|
||||
"unit_amount_decimal": "-7200"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "-7200"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000001/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"next_payment_attempt": null,
|
||||
"number": "NORMALI-0003",
|
||||
"number": "NORMALI-0002",
|
||||
"object": "invoice",
|
||||
"on_behalf_of": null,
|
||||
"paid": true,
|
||||
"paid_out_of_band": false,
|
||||
"payment_intent": null,
|
||||
"payment_settings": {
|
||||
"default_mandate": null,
|
||||
"payment_method_options": null,
|
||||
"payment_method_types": null
|
||||
},
|
||||
@@ -349,6 +402,15 @@
|
||||
"pre_payment_credit_notes_amount": 0,
|
||||
"quote": null,
|
||||
"receipt_number": null,
|
||||
"rendering": {
|
||||
"amount_tax_display": null,
|
||||
"pdf": {
|
||||
"page_size": "letter"
|
||||
}
|
||||
},
|
||||
"rendering_options": null,
|
||||
"shipping_cost": null,
|
||||
"shipping_details": null,
|
||||
"starting_balance": 0,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"status": "paid",
|
||||
@@ -359,22 +421,28 @@
|
||||
"voided_at": null
|
||||
},
|
||||
"subscription": null,
|
||||
"subscription_details": {
|
||||
"metadata": null
|
||||
},
|
||||
"subtotal": 0,
|
||||
"subtotal_excluding_tax": 0,
|
||||
"tax": null,
|
||||
"test_clock": null,
|
||||
"total": 0,
|
||||
"total_discount_amounts": [],
|
||||
"total_excluding_tax": 0,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": null
|
||||
}
|
||||
},
|
||||
"id": "evt_1K2OXvHSaWXyvFpKbgniTOEt",
|
||||
"id": "evt_1OIlcbDEQaroqDjsn0Gh2ZXB",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"pending_webhooks": 1,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0008",
|
||||
"idempotency_key": "f3d64bf5-ddf0-4933-86ee-96e9f6aa7149"
|
||||
"id": "req_NORMALIZED0003",
|
||||
"idempotency_key": "d8040535-2a29-417e-a8cd-313f534cb633"
|
||||
},
|
||||
"type": "invoice.paid"
|
||||
},
|
||||
@@ -384,11 +452,13 @@
|
||||
"data": {
|
||||
"object": {
|
||||
"account_country": "US",
|
||||
"account_name": "NORMALIZED-1",
|
||||
"account_name": "Kandra Labs, Inc.",
|
||||
"account_tax_ids": null,
|
||||
"amount_due": 0,
|
||||
"amount_paid": 0,
|
||||
"amount_remaining": 0,
|
||||
"amount_shipping": 0,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"attempt_count": 0,
|
||||
"attempted": true,
|
||||
@@ -418,29 +488,33 @@
|
||||
"discount": null,
|
||||
"discounts": [],
|
||||
"due_date": null,
|
||||
"effective_at": 1000000000,
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9BNDRqUzlSeE5ZbkM2YXNhYmhHRDNCN0pTZ3E001000SGRn6zX",
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9BNDRqUzlSeE5ZbkM2YXNhYmhHRDNCN0pTZ3E001000SGRn6zX/pdf",
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpiMHNFNHp4OGxtTUNIclNiWWdZa0NQNmpqMVRJLDkyMDM1MjA502000hPybKLo?s=ap",
|
||||
"id": "in_NORMALIZED00000000000001",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpiMHNFNHp4OGxtTUNIclNiWWdZa0NQNmpqMVRJLDkyMDM1MjA502000hPybKLo/pdf?s=ap",
|
||||
"last_finalization_error": null,
|
||||
"latest_revision": null,
|
||||
"lines": {
|
||||
"data": [
|
||||
{
|
||||
"amount": 7200,
|
||||
"amount_excluding_tax": 7200,
|
||||
"currency": "usd",
|
||||
"description": "Zulip Cloud Standard",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000003",
|
||||
"invoice_item": "ii_NORMALIZED00000000000003",
|
||||
"id": "il_NORMALIZED00000000000001",
|
||||
"invoice_item": "ii_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
"end": 1357095845,
|
||||
"start": 1325473445
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
@@ -448,13 +522,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000003",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0003",
|
||||
"product": "prod_NORMALIZED0001",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -464,21 +539,26 @@
|
||||
"unit_amount_decimal": "1200"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "1200"
|
||||
},
|
||||
{
|
||||
"amount": -7200,
|
||||
"amount_excluding_tax": -7200,
|
||||
"currency": "usd",
|
||||
"description": "Payment (Card ending in 4242)",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000004",
|
||||
"invoice_item": "ii_NORMALIZED00000000000004",
|
||||
"id": "il_NORMALIZED00000000000002",
|
||||
"invoice_item": "ii_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -492,13 +572,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0004",
|
||||
"product": "prod_NORMALIZED0002",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -508,27 +589,33 @@
|
||||
"unit_amount_decimal": "-7200"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "-7200"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000001/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"next_payment_attempt": null,
|
||||
"number": "NORMALI-0003",
|
||||
"number": "NORMALI-0002",
|
||||
"object": "invoice",
|
||||
"on_behalf_of": null,
|
||||
"paid": true,
|
||||
"paid_out_of_band": false,
|
||||
"payment_intent": null,
|
||||
"payment_settings": {
|
||||
"default_mandate": null,
|
||||
"payment_method_options": null,
|
||||
"payment_method_types": null
|
||||
},
|
||||
@@ -538,6 +625,15 @@
|
||||
"pre_payment_credit_notes_amount": 0,
|
||||
"quote": null,
|
||||
"receipt_number": null,
|
||||
"rendering": {
|
||||
"amount_tax_display": null,
|
||||
"pdf": {
|
||||
"page_size": "letter"
|
||||
}
|
||||
},
|
||||
"rendering_options": null,
|
||||
"shipping_cost": null,
|
||||
"shipping_details": null,
|
||||
"starting_balance": 0,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"status": "paid",
|
||||
@@ -548,22 +644,28 @@
|
||||
"voided_at": null
|
||||
},
|
||||
"subscription": null,
|
||||
"subscription_details": {
|
||||
"metadata": null
|
||||
},
|
||||
"subtotal": 0,
|
||||
"subtotal_excluding_tax": 0,
|
||||
"tax": null,
|
||||
"test_clock": null,
|
||||
"total": 0,
|
||||
"total_discount_amounts": [],
|
||||
"total_excluding_tax": 0,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": null
|
||||
}
|
||||
},
|
||||
"id": "evt_1K2OXvHSaWXyvFpKPFo4dPYw",
|
||||
"id": "evt_1OIlcbDEQaroqDjshdrWm9Tg",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0008",
|
||||
"idempotency_key": "f3d64bf5-ddf0-4933-86ee-96e9f6aa7149"
|
||||
"id": "req_NORMALIZED0003",
|
||||
"idempotency_key": "d8040535-2a29-417e-a8cd-313f534cb633"
|
||||
},
|
||||
"type": "invoice.finalized"
|
||||
}
|
||||
|
||||
@@ -5,189 +5,53 @@
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"account_country": "US",
|
||||
"account_name": "NORMALIZED-1",
|
||||
"account_tax_ids": null,
|
||||
"amount_due": 0,
|
||||
"amount_paid": 0,
|
||||
"amount_remaining": 0,
|
||||
"application_fee_amount": null,
|
||||
"attempt_count": 0,
|
||||
"attempted": true,
|
||||
"auto_advance": false,
|
||||
"automatic_tax": {
|
||||
"enabled": false,
|
||||
"status": null
|
||||
},
|
||||
"billing_reason": "manual",
|
||||
"charge": null,
|
||||
"collection_method": "charge_automatically",
|
||||
"address": null,
|
||||
"balance": 0,
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"custom_fields": null,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"customer_address": null,
|
||||
"customer_email": "hamlet@zulip.com",
|
||||
"customer_name": null,
|
||||
"customer_phone": null,
|
||||
"customer_shipping": null,
|
||||
"customer_tax_exempt": "none",
|
||||
"customer_tax_ids": [],
|
||||
"default_payment_method": null,
|
||||
"default_currency": "usd",
|
||||
"default_source": null,
|
||||
"default_tax_rates": [],
|
||||
"description": null,
|
||||
"delinquent": false,
|
||||
"description": "zulip (Zulip Dev)",
|
||||
"discount": null,
|
||||
"discounts": [],
|
||||
"due_date": null,
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9BNDRqUzlSeE5ZbkM2YXNhYmhHRDNCN0pTZ3E001000SGRn6zX",
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9BNDRqUzlSeE5ZbkM2YXNhYmhHRDNCN0pTZ3E001000SGRn6zX/pdf",
|
||||
"last_finalization_error": null,
|
||||
"lines": {
|
||||
"data": [
|
||||
{
|
||||
"amount": 7200,
|
||||
"currency": "usd",
|
||||
"description": "Zulip Cloud Standard",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000003",
|
||||
"invoice_item": "ii_NORMALIZED00000000000003",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
"active": false,
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000003",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0003",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
"transform_quantity": null,
|
||||
"type": "one_time",
|
||||
"unit_amount": 1200,
|
||||
"unit_amount_decimal": "1200"
|
||||
},
|
||||
"proration": false,
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
},
|
||||
{
|
||||
"amount": -7200,
|
||||
"currency": "usd",
|
||||
"description": "Payment (Card ending in 4242)",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000004",
|
||||
"invoice_item": "ii_NORMALIZED00000000000004",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
"active": false,
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0004",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
"transform_quantity": null,
|
||||
"type": "one_time",
|
||||
"unit_amount": -7200,
|
||||
"unit_amount_decimal": "-7200"
|
||||
},
|
||||
"proration": false,
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
"email": "hamlet@zulip.com",
|
||||
"id": "cus_NORMALIZED0001",
|
||||
"invoice_prefix": "NORMA01",
|
||||
"invoice_settings": {
|
||||
"custom_fields": null,
|
||||
"default_payment_method": "pm_1OIlceDEQaroqDjshc2Y2l9b",
|
||||
"footer": null,
|
||||
"rendering_options": null
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"next_payment_attempt": null,
|
||||
"number": "NORMALI-0003",
|
||||
"object": "invoice",
|
||||
"on_behalf_of": null,
|
||||
"paid": true,
|
||||
"payment_intent": null,
|
||||
"payment_settings": {
|
||||
"payment_method_options": null,
|
||||
"payment_method_types": null
|
||||
"metadata": {
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip"
|
||||
},
|
||||
"period_end": 1000000000,
|
||||
"period_start": 1000000000,
|
||||
"post_payment_credit_notes_amount": 0,
|
||||
"pre_payment_credit_notes_amount": 0,
|
||||
"quote": null,
|
||||
"receipt_number": null,
|
||||
"starting_balance": 0,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"status": "paid",
|
||||
"status_transitions": {
|
||||
"finalized_at": 1000000000,
|
||||
"marked_uncollectible_at": null,
|
||||
"paid_at": 1000000000,
|
||||
"voided_at": null
|
||||
},
|
||||
"subscription": null,
|
||||
"subtotal": 0,
|
||||
"tax": null,
|
||||
"total": 0,
|
||||
"total_discount_amounts": [],
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": null
|
||||
"name": null,
|
||||
"next_invoice_sequence": 2,
|
||||
"object": "customer",
|
||||
"phone": null,
|
||||
"preferred_locales": [],
|
||||
"shipping": null,
|
||||
"tax_exempt": "none",
|
||||
"test_clock": null
|
||||
},
|
||||
"previous_attributes": {
|
||||
"invoice_settings": {
|
||||
"default_payment_method": "pm_1OIlcUDEQaroqDjsqDT70KqK"
|
||||
}
|
||||
}
|
||||
},
|
||||
"id": "evt_1K2OXwHSaWXyvFpKr5uez7KF",
|
||||
"id": "evt_1OIlcgDEQaroqDjsPE8wVcBq",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0008",
|
||||
"idempotency_key": "f3d64bf5-ddf0-4933-86ee-96e9f6aa7149"
|
||||
"id": "req_NORMALIZED0007",
|
||||
"idempotency_key": "6e41d51b-0e25-4d1f-9da2-4472878eb45f"
|
||||
},
|
||||
"type": "invoice.payment_succeeded"
|
||||
"type": "customer.updated"
|
||||
}
|
||||
],
|
||||
"has_more": true,
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
"object": {
|
||||
"amount": 36000,
|
||||
"amount_capturable": 0,
|
||||
"amount_details": {
|
||||
"tip": {}
|
||||
},
|
||||
"amount_received": 36000,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
@@ -37,7 +40,7 @@
|
||||
"name": null,
|
||||
"phone": null
|
||||
},
|
||||
"calculated_statement_descriptor": "ZULIP STANDARD",
|
||||
"calculated_statement_descriptor": "ZULIP CLOUD STANDARD",
|
||||
"captured": true,
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
@@ -46,6 +49,7 @@
|
||||
"destination": null,
|
||||
"dispute": null,
|
||||
"disputed": false,
|
||||
"failure_balance_transaction": null,
|
||||
"failure_code": null,
|
||||
"failure_message": null,
|
||||
"fraud_details": {},
|
||||
@@ -57,6 +61,7 @@
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"plan_tier": "1",
|
||||
"price_per_license": "6000",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
@@ -78,9 +83,10 @@
|
||||
},
|
||||
"paid": true,
|
||||
"payment_intent": "pi_NORMALIZED00000000000002",
|
||||
"payment_method": "pm_1K2OXyHSaWXyvFpKNE66Ex7T",
|
||||
"payment_method": "pm_1OIlceDEQaroqDjshc2Y2l9b",
|
||||
"payment_method_details": {
|
||||
"card": {
|
||||
"amount_authorized": 36000,
|
||||
"brand": "visa",
|
||||
"checks": {
|
||||
"address_line1_check": null,
|
||||
@@ -88,21 +94,39 @@
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 3,
|
||||
"exp_year": 2033,
|
||||
"exp_month": 12,
|
||||
"exp_year": 2024,
|
||||
"extended_authorization": {
|
||||
"status": "disabled"
|
||||
},
|
||||
"fingerprint": "NORMALIZED000001",
|
||||
"funding": "credit",
|
||||
"incremental_authorization": {
|
||||
"status": "unavailable"
|
||||
},
|
||||
"installments": null,
|
||||
"last4": "4242",
|
||||
"mandate": null,
|
||||
"multicapture": {
|
||||
"status": "unavailable"
|
||||
},
|
||||
"network": "visa",
|
||||
"network_token": {
|
||||
"used": false
|
||||
},
|
||||
"overcapture": {
|
||||
"maximum_amount_capturable": 36000,
|
||||
"status": "unavailable"
|
||||
},
|
||||
"three_d_secure": null,
|
||||
"wallet": null
|
||||
},
|
||||
"type": "card"
|
||||
},
|
||||
"radar_options": {},
|
||||
"receipt_email": "hamlet@zulip.com",
|
||||
"receipt_number": null,
|
||||
"receipt_url": "https://pay.stripe.com/receipts/acct_NORMALIZED000001/ch_NORMALIZED00000000000002/rcpt_NORMALIZED000000000000000000002",
|
||||
"receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKJH9qqsGMgbQjtDZqQM6LBZPz4stEfKrXRPEFZYCyclDAo2Dez80I8lUHYTVeT16LQpU7Ou6wGCFugiR",
|
||||
"refunded": false,
|
||||
"refunds": {
|
||||
"data": [],
|
||||
@@ -127,7 +151,7 @@
|
||||
"total_count": 1,
|
||||
"url": "/v1/charges?payment_intent=pi_NORMALIZED00000000000002"
|
||||
},
|
||||
"client_secret": "pi_NORMALIZED00000000000002_secret_KPTN4Jk0sR9DrnVymxUmd0o0F",
|
||||
"client_secret": "pi_NORMALIZED00000000000002_secret_6P4eLudA3uvQYCOoNiDTkNQEI",
|
||||
"confirmation_method": "automatic",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
@@ -136,12 +160,14 @@
|
||||
"id": "pi_NORMALIZED00000000000002",
|
||||
"invoice": null,
|
||||
"last_payment_error": null,
|
||||
"latest_charge": "ch_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
"billing_modality": "charge_automatically",
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"plan_tier": "1",
|
||||
"price_per_license": "6000",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
@@ -153,10 +179,12 @@
|
||||
"next_action": null,
|
||||
"object": "payment_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": "pm_1K2OXyHSaWXyvFpKNE66Ex7T",
|
||||
"payment_method": "pm_1OIlceDEQaroqDjshc2Y2l9b",
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"installments": null,
|
||||
"mandate_options": null,
|
||||
"network": null,
|
||||
"request_three_d_secure": "automatic"
|
||||
}
|
||||
@@ -164,6 +192,7 @@
|
||||
"payment_method_types": [
|
||||
"card"
|
||||
],
|
||||
"processing": null,
|
||||
"receipt_email": "hamlet@zulip.com",
|
||||
"review": null,
|
||||
"setup_future_usage": null,
|
||||
@@ -176,13 +205,13 @@
|
||||
"transfer_group": null
|
||||
}
|
||||
},
|
||||
"id": "evt_3K2OXxHSaWXyvFpK152vEHml",
|
||||
"id": "evt_3OIlciDEQaroqDjs14Vw2Reo",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 2,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0012",
|
||||
"idempotency_key": "5169e60e-793c-4161-9873-1ba5c523737f"
|
||||
"id": "req_NORMALIZED0008",
|
||||
"idempotency_key": "f7ce8212-6677-40df-912b-4ac6c3765065"
|
||||
},
|
||||
"type": "payment_intent.succeeded"
|
||||
},
|
||||
@@ -191,112 +220,13 @@
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"address": null,
|
||||
"balance": 0,
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"default_source": null,
|
||||
"delinquent": false,
|
||||
"description": "zulip (Zulip Dev)",
|
||||
"discount": null,
|
||||
"email": "hamlet@zulip.com",
|
||||
"id": "cus_NORMALIZED0001",
|
||||
"invoice_prefix": "NORMA01",
|
||||
"invoice_settings": {
|
||||
"custom_fields": null,
|
||||
"default_payment_method": "pm_1K2OXyHSaWXyvFpKNE66Ex7T",
|
||||
"footer": null
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip"
|
||||
},
|
||||
"name": null,
|
||||
"next_invoice_sequence": 2,
|
||||
"object": "customer",
|
||||
"phone": null,
|
||||
"preferred_locales": [],
|
||||
"shipping": null,
|
||||
"tax_exempt": "none"
|
||||
},
|
||||
"previous_attributes": {
|
||||
"invoice_settings": {
|
||||
"default_payment_method": "pm_1K2OXoHSaWXyvFpKhrceNhbI"
|
||||
}
|
||||
}
|
||||
},
|
||||
"id": "evt_1K2OY1HSaWXyvFpKNFkX6Ye6",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0013",
|
||||
"idempotency_key": "196311c6-d3ab-40d0-aefc-f770c1411cf5"
|
||||
},
|
||||
"type": "customer.updated"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"amount": 36000,
|
||||
"amount_captured": 36000,
|
||||
"amount_refunded": 0,
|
||||
"application": null,
|
||||
"cancellation_reason": null,
|
||||
"client_secret": "seti_1K2OXzHSaWXyvFpKzkPjM4k7_secret_KhoALa8Xt6eK1ATCOPGurJLxmo2y6xh",
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": null,
|
||||
"id": "seti_1K2OXzHSaWXyvFpKzkPjM4k7",
|
||||
"last_setup_error": null,
|
||||
"latest_attempt": "setatt_1K2OXzHSaWXyvFpKG0BonJhW",
|
||||
"livemode": false,
|
||||
"mandate": null,
|
||||
"metadata": {
|
||||
"billing_modality": "charge_automatically",
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"price_per_license": "6000",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
"seat_count": "6",
|
||||
"type": "upgrade",
|
||||
"user_email": "hamlet@zulip.com",
|
||||
"user_id": "10"
|
||||
},
|
||||
"next_action": null,
|
||||
"object": "setup_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": "pm_1K2OXyHSaWXyvFpKNE66Ex7T",
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"request_three_d_secure": "automatic"
|
||||
}
|
||||
},
|
||||
"payment_method_types": [
|
||||
"card"
|
||||
],
|
||||
"single_use_mandate": null,
|
||||
"status": "succeeded",
|
||||
"usage": "off_session"
|
||||
}
|
||||
},
|
||||
"id": "evt_1K2OY0HSaWXyvFpKOGS3PDsC",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0014",
|
||||
"idempotency_key": "415ae25a-0c46-48f9-8299-d873f9fc51f1"
|
||||
},
|
||||
"type": "setup_intent.succeeded"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"application_fee": null,
|
||||
"application_fee_amount": null,
|
||||
"balance_transaction": "txn_NORMALIZED00000000000002",
|
||||
"billing_details": {
|
||||
"address": {
|
||||
"city": null,
|
||||
@@ -310,198 +240,28 @@
|
||||
"name": null,
|
||||
"phone": null
|
||||
},
|
||||
"card": {
|
||||
"brand": "visa",
|
||||
"checks": {
|
||||
"address_line1_check": null,
|
||||
"address_postal_code_check": null,
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 3,
|
||||
"exp_year": 2033,
|
||||
"fingerprint": "NORMALIZED000001",
|
||||
"funding": "credit",
|
||||
"generated_from": null,
|
||||
"last4": "4242",
|
||||
"networks": {
|
||||
"available": [
|
||||
"visa"
|
||||
],
|
||||
"preferred": null
|
||||
},
|
||||
"three_d_secure_usage": {
|
||||
"supported": true
|
||||
},
|
||||
"wallet": null
|
||||
},
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"id": "pm_1K2OXyHSaWXyvFpKNE66Ex7T",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "payment_method",
|
||||
"type": "card"
|
||||
}
|
||||
},
|
||||
"id": "evt_1K2OY0HSaWXyvFpKHdeiTg2r",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0014",
|
||||
"idempotency_key": "415ae25a-0c46-48f9-8299-d873f9fc51f1"
|
||||
},
|
||||
"type": "payment_method.attached"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"application": null,
|
||||
"cancellation_reason": null,
|
||||
"client_secret": "seti_1K2OXzHSaWXyvFpKzkPjM4k7_secret_KhoALa8Xt6eK1ATCOPGurJLxmo2y6xh",
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": null,
|
||||
"id": "seti_1K2OXzHSaWXyvFpKzkPjM4k7",
|
||||
"last_setup_error": null,
|
||||
"latest_attempt": "setatt_1K2OXzHSaWXyvFpKG0BonJhW",
|
||||
"livemode": false,
|
||||
"mandate": null,
|
||||
"metadata": {
|
||||
"billing_modality": "charge_automatically",
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"price_per_license": "6000",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
"seat_count": "6",
|
||||
"type": "upgrade",
|
||||
"user_email": "hamlet@zulip.com",
|
||||
"user_id": "10"
|
||||
},
|
||||
"next_action": null,
|
||||
"object": "setup_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": "pm_1K2OXyHSaWXyvFpKNE66Ex7T",
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"request_three_d_secure": "automatic"
|
||||
}
|
||||
},
|
||||
"payment_method_types": [
|
||||
"card"
|
||||
],
|
||||
"single_use_mandate": null,
|
||||
"status": "succeeded",
|
||||
"usage": "off_session"
|
||||
}
|
||||
},
|
||||
"id": "evt_1K2OY0HSaWXyvFpKuYHMv2vM",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0014",
|
||||
"idempotency_key": "415ae25a-0c46-48f9-8299-d873f9fc51f1"
|
||||
},
|
||||
"type": "setup_intent.created"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"application": null,
|
||||
"cancellation_reason": null,
|
||||
"client_secret": "seti_1K2OXyHSaWXyvFpKvIhWI0JW_secret_KhoAlunPkSHQPGu7zyaTpT81wBUPhqc",
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": null,
|
||||
"id": "seti_1K2OXyHSaWXyvFpKvIhWI0JW",
|
||||
"last_setup_error": null,
|
||||
"latest_attempt": null,
|
||||
"livemode": false,
|
||||
"mandate": null,
|
||||
"metadata": {
|
||||
"billing_modality": "charge_automatically",
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"price_per_license": "6000",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
"seat_count": "6",
|
||||
"type": "upgrade",
|
||||
"user_email": "hamlet@zulip.com",
|
||||
"user_id": "10"
|
||||
},
|
||||
"next_action": null,
|
||||
"object": "setup_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"request_three_d_secure": "automatic"
|
||||
}
|
||||
},
|
||||
"payment_method_types": [
|
||||
"card"
|
||||
],
|
||||
"single_use_mandate": null,
|
||||
"status": "requires_payment_method",
|
||||
"usage": "off_session"
|
||||
}
|
||||
},
|
||||
"id": "evt_1K2OXyHSaWXyvFpK5sw7382A",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0015",
|
||||
"idempotency_key": "de8b28ae-b3f1-416b-bae0-43f9af477f33"
|
||||
},
|
||||
"type": "setup_intent.created"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"amount": 36000,
|
||||
"amount_capturable": 0,
|
||||
"amount_received": 0,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"automatic_payment_methods": null,
|
||||
"canceled_at": null,
|
||||
"cancellation_reason": null,
|
||||
"capture_method": "automatic",
|
||||
"charges": {
|
||||
"data": [],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 0,
|
||||
"url": "/v1/charges?payment_intent=pi_NORMALIZED00000000000002"
|
||||
},
|
||||
"client_secret": "pi_NORMALIZED00000000000002_secret_KPTN4Jk0sR9DrnVymxUmd0o0F",
|
||||
"confirmation_method": "automatic",
|
||||
"calculated_statement_descriptor": "ZULIP CLOUD STANDARD",
|
||||
"captured": true,
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": "Upgrade to Zulip Cloud Standard, $60.0 x 6",
|
||||
"id": "pi_NORMALIZED00000000000002",
|
||||
"destination": null,
|
||||
"dispute": null,
|
||||
"disputed": false,
|
||||
"failure_balance_transaction": null,
|
||||
"failure_code": null,
|
||||
"failure_message": null,
|
||||
"fraud_details": {},
|
||||
"id": "ch_NORMALIZED00000000000002",
|
||||
"invoice": null,
|
||||
"last_payment_error": null,
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
"billing_modality": "charge_automatically",
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"plan_tier": "1",
|
||||
"price_per_license": "6000",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
@@ -510,41 +270,91 @@
|
||||
"user_email": "hamlet@zulip.com",
|
||||
"user_id": "10"
|
||||
},
|
||||
"next_action": null,
|
||||
"object": "payment_intent",
|
||||
"object": "charge",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"installments": null,
|
||||
"network": null,
|
||||
"request_three_d_secure": "automatic"
|
||||
}
|
||||
"order": null,
|
||||
"outcome": {
|
||||
"network_status": "approved_by_network",
|
||||
"reason": null,
|
||||
"risk_level": "normal",
|
||||
"risk_score": 0,
|
||||
"seller_message": "Payment complete.",
|
||||
"type": "authorized"
|
||||
},
|
||||
"payment_method_types": [
|
||||
"card"
|
||||
],
|
||||
"paid": true,
|
||||
"payment_intent": "pi_NORMALIZED00000000000002",
|
||||
"payment_method": "pm_1OIlceDEQaroqDjshc2Y2l9b",
|
||||
"payment_method_details": {
|
||||
"card": {
|
||||
"amount_authorized": 36000,
|
||||
"brand": "visa",
|
||||
"checks": {
|
||||
"address_line1_check": null,
|
||||
"address_postal_code_check": null,
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 12,
|
||||
"exp_year": 2024,
|
||||
"extended_authorization": {
|
||||
"status": "disabled"
|
||||
},
|
||||
"fingerprint": "NORMALIZED000001",
|
||||
"funding": "credit",
|
||||
"incremental_authorization": {
|
||||
"status": "unavailable"
|
||||
},
|
||||
"installments": null,
|
||||
"last4": "4242",
|
||||
"mandate": null,
|
||||
"multicapture": {
|
||||
"status": "unavailable"
|
||||
},
|
||||
"network": "visa",
|
||||
"network_token": {
|
||||
"used": false
|
||||
},
|
||||
"overcapture": {
|
||||
"maximum_amount_capturable": 36000,
|
||||
"status": "unavailable"
|
||||
},
|
||||
"three_d_secure": null,
|
||||
"wallet": null
|
||||
},
|
||||
"type": "card"
|
||||
},
|
||||
"radar_options": {},
|
||||
"receipt_email": "hamlet@zulip.com",
|
||||
"receipt_number": null,
|
||||
"receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKJH9qqsGMgYqjd-cSvE6LBaZocBeNc1j6HmSljaGjK9coB5-xRAyLYhQxqOON0JTW8MYWAJtnxrRxAiL",
|
||||
"refunded": false,
|
||||
"refunds": {
|
||||
"data": [],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 0,
|
||||
"url": "/v1/charges/ch_NORMALIZED00000000000002/refunds"
|
||||
},
|
||||
"review": null,
|
||||
"setup_future_usage": null,
|
||||
"shipping": null,
|
||||
"source": null,
|
||||
"source_transfer": null,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"statement_descriptor_suffix": null,
|
||||
"status": "requires_payment_method",
|
||||
"status": "succeeded",
|
||||
"transfer_data": null,
|
||||
"transfer_group": null
|
||||
}
|
||||
},
|
||||
"id": "evt_3K2OXxHSaWXyvFpK1GA2kN6r",
|
||||
"id": "evt_3OIlciDEQaroqDjs1zZA7DlT",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0016",
|
||||
"idempotency_key": "d8d89509-f2c5-433c-b8ca-1ae78f192ee5"
|
||||
"id": "req_NORMALIZED0008",
|
||||
"idempotency_key": "f7ce8212-6677-40df-912b-4ac6c3765065"
|
||||
},
|
||||
"type": "payment_intent.created"
|
||||
"type": "charge.succeeded"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
|
||||
@@ -6,11 +6,13 @@
|
||||
"data": {
|
||||
"object": {
|
||||
"account_country": "US",
|
||||
"account_name": "NORMALIZED-1",
|
||||
"account_name": "Kandra Labs, Inc.",
|
||||
"account_tax_ids": null,
|
||||
"amount_due": 0,
|
||||
"amount_paid": 0,
|
||||
"amount_remaining": 0,
|
||||
"amount_shipping": 0,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"attempt_count": 0,
|
||||
"attempted": true,
|
||||
@@ -40,23 +42,27 @@
|
||||
"discount": null,
|
||||
"discounts": [],
|
||||
"due_date": null,
|
||||
"effective_at": 1000000000,
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9Ba2NPMVJlTGJDNXlwMEFBVU1sY01VTDNHTHNk0100ARPvAEt8",
|
||||
"id": "in_NORMALIZED00000000000003",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9Ba2NPMVJlTGJDNXlwMEFBVU1sY01VTDNHTHNk0100ARPvAEt8/pdf",
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpiZG84bnRuUUtrVXRnN0pvOEFlUkJqY0ZBZFhCLDkyMDM1MjE502004xw8zwol?s=ap",
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpiZG84bnRuUUtrVXRnN0pvOEFlUkJqY0ZBZFhCLDkyMDM1MjE502004xw8zwol/pdf?s=ap",
|
||||
"last_finalization_error": null,
|
||||
"latest_revision": null,
|
||||
"lines": {
|
||||
"data": [
|
||||
{
|
||||
"amount": 36000,
|
||||
"amount_excluding_tax": 36000,
|
||||
"currency": "usd",
|
||||
"description": "Zulip Cloud Standard",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000005",
|
||||
"invoice_item": "ii_NORMALIZED00000000000005",
|
||||
"id": "il_NORMALIZED00000000000003",
|
||||
"invoice_item": "ii_NORMALIZED00000000000003",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -70,13 +76,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000005",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000003",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0005",
|
||||
"product": "prod_NORMALIZED0001",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -86,21 +93,26 @@
|
||||
"unit_amount_decimal": "6000"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "6000"
|
||||
},
|
||||
{
|
||||
"amount": -36000,
|
||||
"amount_excluding_tax": -36000,
|
||||
"currency": "usd",
|
||||
"description": "Payment (Card ending in 4242)",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000006",
|
||||
"invoice_item": "ii_NORMALIZED00000000000006",
|
||||
"id": "il_NORMALIZED00000000000004",
|
||||
"invoice_item": "ii_NORMALIZED00000000000004",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -114,13 +126,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000006",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0006",
|
||||
"product": "prod_NORMALIZED0002",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -130,27 +143,33 @@
|
||||
"unit_amount_decimal": "-36000"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "-36000"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000003/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"next_payment_attempt": null,
|
||||
"number": "NORMALI-0004",
|
||||
"number": "NORMALI-0003",
|
||||
"object": "invoice",
|
||||
"on_behalf_of": null,
|
||||
"paid": true,
|
||||
"paid_out_of_band": false,
|
||||
"payment_intent": null,
|
||||
"payment_settings": {
|
||||
"default_mandate": null,
|
||||
"payment_method_options": null,
|
||||
"payment_method_types": null
|
||||
},
|
||||
@@ -160,6 +179,15 @@
|
||||
"pre_payment_credit_notes_amount": 0,
|
||||
"quote": null,
|
||||
"receipt_number": null,
|
||||
"rendering": {
|
||||
"amount_tax_display": null,
|
||||
"pdf": {
|
||||
"page_size": "letter"
|
||||
}
|
||||
},
|
||||
"rendering_options": null,
|
||||
"shipping_cost": null,
|
||||
"shipping_details": null,
|
||||
"starting_balance": 0,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"status": "paid",
|
||||
@@ -170,22 +198,28 @@
|
||||
"voided_at": null
|
||||
},
|
||||
"subscription": null,
|
||||
"subscription_details": {
|
||||
"metadata": null
|
||||
},
|
||||
"subtotal": 0,
|
||||
"subtotal_excluding_tax": 0,
|
||||
"tax": null,
|
||||
"test_clock": null,
|
||||
"total": 0,
|
||||
"total_discount_amounts": [],
|
||||
"total_excluding_tax": 0,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": null
|
||||
}
|
||||
},
|
||||
"id": "evt_1K2OY5HSaWXyvFpK1LOtVUsj",
|
||||
"id": "evt_1OIlclDEQaroqDjslxJqiQFY",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 2,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0017",
|
||||
"idempotency_key": "c3e3b8e3-19f0-4bab-865b-d2d621dd254b"
|
||||
"id": "req_NORMALIZED0009",
|
||||
"idempotency_key": "5fb5bcd9-f037-402f-b67a-6f8eb89f3c11"
|
||||
},
|
||||
"type": "invoice.finalized"
|
||||
},
|
||||
@@ -195,11 +229,13 @@
|
||||
"data": {
|
||||
"object": {
|
||||
"account_country": "US",
|
||||
"account_name": "NORMALIZED-1",
|
||||
"account_name": "Kandra Labs, Inc.",
|
||||
"account_tax_ids": null,
|
||||
"amount_due": 0,
|
||||
"amount_paid": 0,
|
||||
"amount_remaining": 0,
|
||||
"amount_shipping": 0,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"attempt_count": 0,
|
||||
"attempted": true,
|
||||
@@ -229,23 +265,27 @@
|
||||
"discount": null,
|
||||
"discounts": [],
|
||||
"due_date": null,
|
||||
"effective_at": 1000000000,
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9Ba2NPMVJlTGJDNXlwMEFBVU1sY01VTDNHTHNk0100ARPvAEt8",
|
||||
"id": "in_NORMALIZED00000000000003",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9Ba2NPMVJlTGJDNXlwMEFBVU1sY01VTDNHTHNk0100ARPvAEt8/pdf",
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpiZG84bnRuUUtrVXRnN0pvOEFlUkJqY0ZBZFhCLDkyMDM1MjE502004xw8zwol?s=ap",
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpiZG84bnRuUUtrVXRnN0pvOEFlUkJqY0ZBZFhCLDkyMDM1MjE502004xw8zwol/pdf?s=ap",
|
||||
"last_finalization_error": null,
|
||||
"latest_revision": null,
|
||||
"lines": {
|
||||
"data": [
|
||||
{
|
||||
"amount": 36000,
|
||||
"amount_excluding_tax": 36000,
|
||||
"currency": "usd",
|
||||
"description": "Zulip Cloud Standard",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000005",
|
||||
"invoice_item": "ii_NORMALIZED00000000000005",
|
||||
"id": "il_NORMALIZED00000000000003",
|
||||
"invoice_item": "ii_NORMALIZED00000000000003",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -259,13 +299,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000005",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000003",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0005",
|
||||
"product": "prod_NORMALIZED0001",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -275,21 +316,26 @@
|
||||
"unit_amount_decimal": "6000"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "6000"
|
||||
},
|
||||
{
|
||||
"amount": -36000,
|
||||
"amount_excluding_tax": -36000,
|
||||
"currency": "usd",
|
||||
"description": "Payment (Card ending in 4242)",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000006",
|
||||
"invoice_item": "ii_NORMALIZED00000000000006",
|
||||
"id": "il_NORMALIZED00000000000004",
|
||||
"invoice_item": "ii_NORMALIZED00000000000004",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -303,13 +349,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000006",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0006",
|
||||
"product": "prod_NORMALIZED0002",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -319,27 +366,33 @@
|
||||
"unit_amount_decimal": "-36000"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "-36000"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000003/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"next_payment_attempt": null,
|
||||
"number": "NORMALI-0004",
|
||||
"number": "NORMALI-0003",
|
||||
"object": "invoice",
|
||||
"on_behalf_of": null,
|
||||
"paid": true,
|
||||
"paid_out_of_band": false,
|
||||
"payment_intent": null,
|
||||
"payment_settings": {
|
||||
"default_mandate": null,
|
||||
"payment_method_options": null,
|
||||
"payment_method_types": null
|
||||
},
|
||||
@@ -349,6 +402,15 @@
|
||||
"pre_payment_credit_notes_amount": 0,
|
||||
"quote": null,
|
||||
"receipt_number": null,
|
||||
"rendering": {
|
||||
"amount_tax_display": null,
|
||||
"pdf": {
|
||||
"page_size": "letter"
|
||||
}
|
||||
},
|
||||
"rendering_options": null,
|
||||
"shipping_cost": null,
|
||||
"shipping_details": null,
|
||||
"starting_balance": 0,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"status": "paid",
|
||||
@@ -359,10 +421,16 @@
|
||||
"voided_at": null
|
||||
},
|
||||
"subscription": null,
|
||||
"subscription_details": {
|
||||
"metadata": null
|
||||
},
|
||||
"subtotal": 0,
|
||||
"subtotal_excluding_tax": 0,
|
||||
"tax": null,
|
||||
"test_clock": null,
|
||||
"total": 0,
|
||||
"total_discount_amounts": [],
|
||||
"total_excluding_tax": 0,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": null
|
||||
@@ -370,12 +438,18 @@
|
||||
"previous_attributes": {
|
||||
"attempted": false,
|
||||
"auto_advance": true,
|
||||
"effective_at": null,
|
||||
"ending_balance": null,
|
||||
"hosted_invoice_url": null,
|
||||
"invoice_pdf": null,
|
||||
"next_payment_attempt": 1000000000,
|
||||
"number": null,
|
||||
"paid": false,
|
||||
"rendering": {
|
||||
"pdf": {
|
||||
"page_size": "auto"
|
||||
}
|
||||
},
|
||||
"status": "draft",
|
||||
"status_transitions": {
|
||||
"finalized_at": null,
|
||||
@@ -383,13 +457,13 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"id": "evt_1K2OY5HSaWXyvFpKAdaAGCmF",
|
||||
"id": "evt_1OIlclDEQaroqDjsbyHu8WF8",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 1,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0017",
|
||||
"idempotency_key": "c3e3b8e3-19f0-4bab-865b-d2d621dd254b"
|
||||
"id": "req_NORMALIZED0009",
|
||||
"idempotency_key": "5fb5bcd9-f037-402f-b67a-6f8eb89f3c11"
|
||||
},
|
||||
"type": "invoice.updated"
|
||||
},
|
||||
@@ -399,11 +473,13 @@
|
||||
"data": {
|
||||
"object": {
|
||||
"account_country": "US",
|
||||
"account_name": "NORMALIZED-1",
|
||||
"account_name": "Kandra Labs, Inc.",
|
||||
"account_tax_ids": null,
|
||||
"amount_due": 0,
|
||||
"amount_paid": 0,
|
||||
"amount_remaining": 0,
|
||||
"amount_shipping": 0,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"attempt_count": 0,
|
||||
"attempted": false,
|
||||
@@ -433,23 +509,27 @@
|
||||
"discount": null,
|
||||
"discounts": [],
|
||||
"due_date": null,
|
||||
"effective_at": null,
|
||||
"ending_balance": null,
|
||||
"footer": null,
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": null,
|
||||
"id": "in_NORMALIZED00000000000003",
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"invoice_pdf": null,
|
||||
"last_finalization_error": null,
|
||||
"latest_revision": null,
|
||||
"lines": {
|
||||
"data": [
|
||||
{
|
||||
"amount": 36000,
|
||||
"amount_excluding_tax": 36000,
|
||||
"currency": "usd",
|
||||
"description": "Zulip Cloud Standard",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000005",
|
||||
"invoice_item": "ii_NORMALIZED00000000000005",
|
||||
"id": "il_NORMALIZED00000000000003",
|
||||
"invoice_item": "ii_NORMALIZED00000000000003",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -463,13 +543,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000005",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000003",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0005",
|
||||
"product": "prod_NORMALIZED0001",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -479,21 +560,26 @@
|
||||
"unit_amount_decimal": "6000"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "6000"
|
||||
},
|
||||
{
|
||||
"amount": -36000,
|
||||
"amount_excluding_tax": -36000,
|
||||
"currency": "usd",
|
||||
"description": "Payment (Card ending in 4242)",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000006",
|
||||
"invoice_item": "ii_NORMALIZED00000000000006",
|
||||
"id": "il_NORMALIZED00000000000004",
|
||||
"invoice_item": "ii_NORMALIZED00000000000004",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -507,13 +593,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000006",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0006",
|
||||
"product": "prod_NORMALIZED0002",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -523,17 +610,21 @@
|
||||
"unit_amount_decimal": "-36000"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "-36000"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000003/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
@@ -542,8 +633,10 @@
|
||||
"object": "invoice",
|
||||
"on_behalf_of": null,
|
||||
"paid": false,
|
||||
"paid_out_of_band": false,
|
||||
"payment_intent": null,
|
||||
"payment_settings": {
|
||||
"default_mandate": null,
|
||||
"payment_method_options": null,
|
||||
"payment_method_types": null
|
||||
},
|
||||
@@ -553,6 +646,15 @@
|
||||
"pre_payment_credit_notes_amount": 0,
|
||||
"quote": null,
|
||||
"receipt_number": null,
|
||||
"rendering": {
|
||||
"amount_tax_display": null,
|
||||
"pdf": {
|
||||
"page_size": "auto"
|
||||
}
|
||||
},
|
||||
"rendering_options": null,
|
||||
"shipping_cost": null,
|
||||
"shipping_details": null,
|
||||
"starting_balance": 0,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"status": "draft",
|
||||
@@ -563,88 +665,31 @@
|
||||
"voided_at": null
|
||||
},
|
||||
"subscription": null,
|
||||
"subscription_details": {
|
||||
"metadata": null
|
||||
},
|
||||
"subtotal": 0,
|
||||
"subtotal_excluding_tax": 0,
|
||||
"tax": null,
|
||||
"test_clock": null,
|
||||
"total": 0,
|
||||
"total_discount_amounts": [],
|
||||
"total_excluding_tax": 0,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": null
|
||||
}
|
||||
},
|
||||
"id": "evt_1K2OY4HSaWXyvFpK5WkKkAff",
|
||||
"id": "evt_1OIlckDEQaroqDjsUsuf3ZOp",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0018",
|
||||
"idempotency_key": "f117a125-002e-4795-b38a-dd9babcf6f10"
|
||||
"id": "req_NORMALIZED0010",
|
||||
"idempotency_key": "a4d2ad76-c98a-446a-8236-ec43f0faf5fa"
|
||||
},
|
||||
"type": "invoice.created"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"amount": -36000,
|
||||
"currency": "usd",
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"date": 1000000000,
|
||||
"description": "Payment (Card ending in 4242)",
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "ii_NORMALIZED00000000000006",
|
||||
"invoice": "in_NORMALIZED00000000000003",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "invoiceitem",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
"active": false,
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000006",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0006",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
"transform_quantity": null,
|
||||
"type": "one_time",
|
||||
"unit_amount": -36000,
|
||||
"unit_amount_decimal": "-36000"
|
||||
},
|
||||
"proration": false,
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_rates": [],
|
||||
"unit_amount": -36000,
|
||||
"unit_amount_decimal": "-36000"
|
||||
},
|
||||
"previous_attributes": {
|
||||
"invoice": null
|
||||
}
|
||||
},
|
||||
"id": "evt_1K2OY4HSaWXyvFpKtk38Nrov",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0018",
|
||||
"idempotency_key": "f117a125-002e-4795-b38a-dd9babcf6f10"
|
||||
},
|
||||
"type": "invoiceitem.updated"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
@@ -657,70 +702,7 @@
|
||||
"description": "Zulip Cloud Standard",
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "ii_NORMALIZED00000000000005",
|
||||
"invoice": "in_NORMALIZED00000000000003",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "invoiceitem",
|
||||
"period": {
|
||||
"end": 1357095845,
|
||||
"start": 1325473445
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
"active": false,
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000005",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0005",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
"transform_quantity": null,
|
||||
"type": "one_time",
|
||||
"unit_amount": 6000,
|
||||
"unit_amount_decimal": "6000"
|
||||
},
|
||||
"proration": false,
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_rates": [],
|
||||
"unit_amount": 6000,
|
||||
"unit_amount_decimal": "6000"
|
||||
},
|
||||
"previous_attributes": {
|
||||
"invoice": null
|
||||
}
|
||||
},
|
||||
"id": "evt_1K2OY4HSaWXyvFpK7ju3WXQp",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0018",
|
||||
"idempotency_key": "f117a125-002e-4795-b38a-dd9babcf6f10"
|
||||
},
|
||||
"type": "invoiceitem.updated"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"amount": 36000,
|
||||
"currency": "usd",
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"date": 1000000000,
|
||||
"description": "Zulip Cloud Standard",
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "ii_NORMALIZED00000000000005",
|
||||
"id": "ii_NORMALIZED00000000000003",
|
||||
"invoice": null,
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
@@ -735,13 +717,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000005",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000003",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0005",
|
||||
"product": "prod_NORMALIZED0001",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -754,17 +737,18 @@
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_rates": [],
|
||||
"test_clock": null,
|
||||
"unit_amount": 6000,
|
||||
"unit_amount_decimal": "6000"
|
||||
}
|
||||
},
|
||||
"id": "evt_1K2OY4HSaWXyvFpKxihqsHVn",
|
||||
"id": "evt_1OIlckDEQaroqDjsYzRhmX8V",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0019",
|
||||
"idempotency_key": "613148af-3c2d-4206-968d-e4ed39a3d02e"
|
||||
"id": "req_NORMALIZED0011",
|
||||
"idempotency_key": "0c11698d-33dd-4270-81bd-05e97ff35e0e"
|
||||
},
|
||||
"type": "invoiceitem.created"
|
||||
},
|
||||
@@ -780,7 +764,7 @@
|
||||
"description": "Payment (Card ending in 4242)",
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "ii_NORMALIZED00000000000006",
|
||||
"id": "ii_NORMALIZED00000000000004",
|
||||
"invoice": null,
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
@@ -795,13 +779,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000006",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0006",
|
||||
"product": "prod_NORMALIZED0002",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -814,17 +799,18 @@
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_rates": [],
|
||||
"test_clock": null,
|
||||
"unit_amount": -36000,
|
||||
"unit_amount_decimal": "-36000"
|
||||
}
|
||||
},
|
||||
"id": "evt_1K2OY3HSaWXyvFpKc0mBnhSo",
|
||||
"id": "evt_1OIlcjDEQaroqDjsWfKiiWQ1",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0020",
|
||||
"idempotency_key": "14c29b95-ba26-4fee-afc1-97ad8a540ebb"
|
||||
"id": "req_NORMALIZED0012",
|
||||
"idempotency_key": "e0683c69-8080-4a6a-b9e7-7750eba12988"
|
||||
},
|
||||
"type": "invoiceitem.created"
|
||||
}
|
||||
|
||||
@@ -6,11 +6,13 @@
|
||||
"data": {
|
||||
"object": {
|
||||
"account_country": "US",
|
||||
"account_name": "NORMALIZED-1",
|
||||
"account_name": "Kandra Labs, Inc.",
|
||||
"account_tax_ids": null,
|
||||
"amount_due": 0,
|
||||
"amount_paid": 0,
|
||||
"amount_remaining": 0,
|
||||
"amount_shipping": 0,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"attempt_count": 0,
|
||||
"attempted": true,
|
||||
@@ -40,23 +42,27 @@
|
||||
"discount": null,
|
||||
"discounts": [],
|
||||
"due_date": null,
|
||||
"effective_at": 1000000000,
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9Ba2NPMVJlTGJDNXlwMEFBVU1sY01VTDNHTHNk0100ARPvAEt8",
|
||||
"id": "in_NORMALIZED00000000000003",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9Ba2NPMVJlTGJDNXlwMEFBVU1sY01VTDNHTHNk0100ARPvAEt8/pdf",
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpiZG84bnRuUUtrVXRnN0pvOEFlUkJqY0ZBZFhCLDkyMDM1MjE502004xw8zwol?s=ap",
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpiZG84bnRuUUtrVXRnN0pvOEFlUkJqY0ZBZFhCLDkyMDM1MjE502004xw8zwol/pdf?s=ap",
|
||||
"last_finalization_error": null,
|
||||
"latest_revision": null,
|
||||
"lines": {
|
||||
"data": [
|
||||
{
|
||||
"amount": 36000,
|
||||
"amount_excluding_tax": 36000,
|
||||
"currency": "usd",
|
||||
"description": "Zulip Cloud Standard",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000005",
|
||||
"invoice_item": "ii_NORMALIZED00000000000005",
|
||||
"id": "il_NORMALIZED00000000000003",
|
||||
"invoice_item": "ii_NORMALIZED00000000000003",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -70,13 +76,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000005",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000003",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0005",
|
||||
"product": "prod_NORMALIZED0001",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -86,21 +93,26 @@
|
||||
"unit_amount_decimal": "6000"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "6000"
|
||||
},
|
||||
{
|
||||
"amount": -36000,
|
||||
"amount_excluding_tax": -36000,
|
||||
"currency": "usd",
|
||||
"description": "Payment (Card ending in 4242)",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000006",
|
||||
"invoice_item": "ii_NORMALIZED00000000000006",
|
||||
"id": "il_NORMALIZED00000000000004",
|
||||
"invoice_item": "ii_NORMALIZED00000000000004",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -114,13 +126,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000006",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0006",
|
||||
"product": "prod_NORMALIZED0002",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -130,27 +143,33 @@
|
||||
"unit_amount_decimal": "-36000"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "-36000"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000003/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"next_payment_attempt": null,
|
||||
"number": "NORMALI-0004",
|
||||
"number": "NORMALI-0003",
|
||||
"object": "invoice",
|
||||
"on_behalf_of": null,
|
||||
"paid": true,
|
||||
"paid_out_of_band": false,
|
||||
"payment_intent": null,
|
||||
"payment_settings": {
|
||||
"default_mandate": null,
|
||||
"payment_method_options": null,
|
||||
"payment_method_types": null
|
||||
},
|
||||
@@ -160,6 +179,15 @@
|
||||
"pre_payment_credit_notes_amount": 0,
|
||||
"quote": null,
|
||||
"receipt_number": null,
|
||||
"rendering": {
|
||||
"amount_tax_display": null,
|
||||
"pdf": {
|
||||
"page_size": "letter"
|
||||
}
|
||||
},
|
||||
"rendering_options": null,
|
||||
"shipping_cost": null,
|
||||
"shipping_details": null,
|
||||
"starting_balance": 0,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"status": "paid",
|
||||
@@ -170,22 +198,28 @@
|
||||
"voided_at": null
|
||||
},
|
||||
"subscription": null,
|
||||
"subscription_details": {
|
||||
"metadata": null
|
||||
},
|
||||
"subtotal": 0,
|
||||
"subtotal_excluding_tax": 0,
|
||||
"tax": null,
|
||||
"test_clock": null,
|
||||
"total": 0,
|
||||
"total_discount_amounts": [],
|
||||
"total_excluding_tax": 0,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": null
|
||||
}
|
||||
},
|
||||
"id": "evt_1K2OY5HSaWXyvFpK4UZiVK2B",
|
||||
"id": "evt_1OIlclDEQaroqDjsYQluU75w",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0017",
|
||||
"idempotency_key": "c3e3b8e3-19f0-4bab-865b-d2d621dd254b"
|
||||
"id": "req_NORMALIZED0009",
|
||||
"idempotency_key": "5fb5bcd9-f037-402f-b67a-6f8eb89f3c11"
|
||||
},
|
||||
"type": "invoice.payment_succeeded"
|
||||
},
|
||||
@@ -195,11 +229,13 @@
|
||||
"data": {
|
||||
"object": {
|
||||
"account_country": "US",
|
||||
"account_name": "NORMALIZED-1",
|
||||
"account_name": "Kandra Labs, Inc.",
|
||||
"account_tax_ids": null,
|
||||
"amount_due": 0,
|
||||
"amount_paid": 0,
|
||||
"amount_remaining": 0,
|
||||
"amount_shipping": 0,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"attempt_count": 0,
|
||||
"attempted": true,
|
||||
@@ -229,23 +265,27 @@
|
||||
"discount": null,
|
||||
"discounts": [],
|
||||
"due_date": null,
|
||||
"effective_at": 1000000000,
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9Ba2NPMVJlTGJDNXlwMEFBVU1sY01VTDNHTHNk0100ARPvAEt8",
|
||||
"id": "in_NORMALIZED00000000000003",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9Ba2NPMVJlTGJDNXlwMEFBVU1sY01VTDNHTHNk0100ARPvAEt8/pdf",
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpiZG84bnRuUUtrVXRnN0pvOEFlUkJqY0ZBZFhCLDkyMDM1MjE502004xw8zwol?s=ap",
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpiZG84bnRuUUtrVXRnN0pvOEFlUkJqY0ZBZFhCLDkyMDM1MjE502004xw8zwol/pdf?s=ap",
|
||||
"last_finalization_error": null,
|
||||
"latest_revision": null,
|
||||
"lines": {
|
||||
"data": [
|
||||
{
|
||||
"amount": 36000,
|
||||
"amount_excluding_tax": 36000,
|
||||
"currency": "usd",
|
||||
"description": "Zulip Cloud Standard",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000005",
|
||||
"invoice_item": "ii_NORMALIZED00000000000005",
|
||||
"id": "il_NORMALIZED00000000000003",
|
||||
"invoice_item": "ii_NORMALIZED00000000000003",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -259,13 +299,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000005",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000003",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0005",
|
||||
"product": "prod_NORMALIZED0001",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -275,21 +316,26 @@
|
||||
"unit_amount_decimal": "6000"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "6000"
|
||||
},
|
||||
{
|
||||
"amount": -36000,
|
||||
"amount_excluding_tax": -36000,
|
||||
"currency": "usd",
|
||||
"description": "Payment (Card ending in 4242)",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000006",
|
||||
"invoice_item": "ii_NORMALIZED00000000000006",
|
||||
"id": "il_NORMALIZED00000000000004",
|
||||
"invoice_item": "ii_NORMALIZED00000000000004",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -303,13 +349,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000006",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0006",
|
||||
"product": "prod_NORMALIZED0002",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -319,27 +366,33 @@
|
||||
"unit_amount_decimal": "-36000"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "-36000"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000003/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"next_payment_attempt": null,
|
||||
"number": "NORMALI-0004",
|
||||
"number": "NORMALI-0003",
|
||||
"object": "invoice",
|
||||
"on_behalf_of": null,
|
||||
"paid": true,
|
||||
"paid_out_of_band": false,
|
||||
"payment_intent": null,
|
||||
"payment_settings": {
|
||||
"default_mandate": null,
|
||||
"payment_method_options": null,
|
||||
"payment_method_types": null
|
||||
},
|
||||
@@ -349,6 +402,15 @@
|
||||
"pre_payment_credit_notes_amount": 0,
|
||||
"quote": null,
|
||||
"receipt_number": null,
|
||||
"rendering": {
|
||||
"amount_tax_display": null,
|
||||
"pdf": {
|
||||
"page_size": "letter"
|
||||
}
|
||||
},
|
||||
"rendering_options": null,
|
||||
"shipping_cost": null,
|
||||
"shipping_details": null,
|
||||
"starting_balance": 0,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"status": "paid",
|
||||
@@ -359,22 +421,28 @@
|
||||
"voided_at": null
|
||||
},
|
||||
"subscription": null,
|
||||
"subscription_details": {
|
||||
"metadata": null
|
||||
},
|
||||
"subtotal": 0,
|
||||
"subtotal_excluding_tax": 0,
|
||||
"tax": null,
|
||||
"test_clock": null,
|
||||
"total": 0,
|
||||
"total_discount_amounts": [],
|
||||
"total_excluding_tax": 0,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": null
|
||||
}
|
||||
},
|
||||
"id": "evt_1K2OY5HSaWXyvFpKy72Pl7GJ",
|
||||
"id": "evt_1OIlclDEQaroqDjsWkTK3kjn",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0017",
|
||||
"idempotency_key": "c3e3b8e3-19f0-4bab-865b-d2d621dd254b"
|
||||
"id": "req_NORMALIZED0009",
|
||||
"idempotency_key": "5fb5bcd9-f037-402f-b67a-6f8eb89f3c11"
|
||||
},
|
||||
"type": "invoice.paid"
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
{
|
||||
"account_country": "US",
|
||||
"account_name": "NORMALIZED-1",
|
||||
"account_name": "Kandra Labs, Inc.",
|
||||
"account_tax_ids": null,
|
||||
"amount_due": 0,
|
||||
"amount_paid": 0,
|
||||
"amount_remaining": 0,
|
||||
"amount_shipping": 0,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"attempt_count": 0,
|
||||
"attempted": false,
|
||||
@@ -34,29 +36,33 @@
|
||||
"discount": null,
|
||||
"discounts": [],
|
||||
"due_date": null,
|
||||
"effective_at": null,
|
||||
"ending_balance": null,
|
||||
"footer": null,
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": null,
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"id": "in_NORMALIZED00000000000001",
|
||||
"invoice_pdf": null,
|
||||
"last_finalization_error": null,
|
||||
"latest_revision": null,
|
||||
"lines": {
|
||||
"data": [
|
||||
{
|
||||
"amount": 7200,
|
||||
"amount_excluding_tax": 7200,
|
||||
"currency": "usd",
|
||||
"description": "Zulip Cloud Standard",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000003",
|
||||
"invoice_item": "ii_NORMALIZED00000000000003",
|
||||
"id": "il_NORMALIZED00000000000001",
|
||||
"invoice_item": "ii_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
"end": 1357095845,
|
||||
"start": 1325473445
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
@@ -64,13 +70,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000003",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0003",
|
||||
"product": "prod_NORMALIZED0001",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -80,21 +87,26 @@
|
||||
"unit_amount_decimal": "1200"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "1200"
|
||||
},
|
||||
{
|
||||
"amount": -7200,
|
||||
"amount_excluding_tax": -7200,
|
||||
"currency": "usd",
|
||||
"description": "Payment (Card ending in 4242)",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000004",
|
||||
"invoice_item": "ii_NORMALIZED00000000000004",
|
||||
"id": "il_NORMALIZED00000000000002",
|
||||
"invoice_item": "ii_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -108,13 +120,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0004",
|
||||
"product": "prod_NORMALIZED0002",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -124,17 +137,21 @@
|
||||
"unit_amount_decimal": "-7200"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "-7200"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000001/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
@@ -143,8 +160,10 @@
|
||||
"object": "invoice",
|
||||
"on_behalf_of": null,
|
||||
"paid": false,
|
||||
"paid_out_of_band": false,
|
||||
"payment_intent": null,
|
||||
"payment_settings": {
|
||||
"default_mandate": null,
|
||||
"payment_method_options": null,
|
||||
"payment_method_types": null
|
||||
},
|
||||
@@ -154,6 +173,15 @@
|
||||
"pre_payment_credit_notes_amount": 0,
|
||||
"quote": null,
|
||||
"receipt_number": null,
|
||||
"rendering": {
|
||||
"amount_tax_display": null,
|
||||
"pdf": {
|
||||
"page_size": "auto"
|
||||
}
|
||||
},
|
||||
"rendering_options": null,
|
||||
"shipping_cost": null,
|
||||
"shipping_details": null,
|
||||
"starting_balance": 0,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"status": "draft",
|
||||
@@ -164,10 +192,16 @@
|
||||
"voided_at": null
|
||||
},
|
||||
"subscription": null,
|
||||
"subscription_details": {
|
||||
"metadata": null
|
||||
},
|
||||
"subtotal": 0,
|
||||
"subtotal_excluding_tax": 0,
|
||||
"tax": null,
|
||||
"test_clock": null,
|
||||
"total": 0,
|
||||
"total_discount_amounts": [],
|
||||
"total_excluding_tax": 0,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": null
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
{
|
||||
"account_country": "US",
|
||||
"account_name": "NORMALIZED-1",
|
||||
"account_name": "Kandra Labs, Inc.",
|
||||
"account_tax_ids": null,
|
||||
"amount_due": 0,
|
||||
"amount_paid": 0,
|
||||
"amount_remaining": 0,
|
||||
"amount_shipping": 0,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"attempt_count": 0,
|
||||
"attempted": false,
|
||||
@@ -34,23 +36,27 @@
|
||||
"discount": null,
|
||||
"discounts": [],
|
||||
"due_date": null,
|
||||
"effective_at": null,
|
||||
"ending_balance": null,
|
||||
"footer": null,
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": null,
|
||||
"id": "in_NORMALIZED00000000000003",
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"invoice_pdf": null,
|
||||
"last_finalization_error": null,
|
||||
"latest_revision": null,
|
||||
"lines": {
|
||||
"data": [
|
||||
{
|
||||
"amount": 36000,
|
||||
"amount_excluding_tax": 36000,
|
||||
"currency": "usd",
|
||||
"description": "Zulip Cloud Standard",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000005",
|
||||
"invoice_item": "ii_NORMALIZED00000000000005",
|
||||
"id": "il_NORMALIZED00000000000003",
|
||||
"invoice_item": "ii_NORMALIZED00000000000003",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -64,13 +70,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000005",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000003",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0005",
|
||||
"product": "prod_NORMALIZED0001",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -80,21 +87,26 @@
|
||||
"unit_amount_decimal": "6000"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "6000"
|
||||
},
|
||||
{
|
||||
"amount": -36000,
|
||||
"amount_excluding_tax": -36000,
|
||||
"currency": "usd",
|
||||
"description": "Payment (Card ending in 4242)",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000006",
|
||||
"invoice_item": "ii_NORMALIZED00000000000006",
|
||||
"id": "il_NORMALIZED00000000000004",
|
||||
"invoice_item": "ii_NORMALIZED00000000000004",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -108,13 +120,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000006",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0006",
|
||||
"product": "prod_NORMALIZED0002",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -124,17 +137,21 @@
|
||||
"unit_amount_decimal": "-36000"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "-36000"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000003/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
@@ -143,8 +160,10 @@
|
||||
"object": "invoice",
|
||||
"on_behalf_of": null,
|
||||
"paid": false,
|
||||
"paid_out_of_band": false,
|
||||
"payment_intent": null,
|
||||
"payment_settings": {
|
||||
"default_mandate": null,
|
||||
"payment_method_options": null,
|
||||
"payment_method_types": null
|
||||
},
|
||||
@@ -154,6 +173,15 @@
|
||||
"pre_payment_credit_notes_amount": 0,
|
||||
"quote": null,
|
||||
"receipt_number": null,
|
||||
"rendering": {
|
||||
"amount_tax_display": null,
|
||||
"pdf": {
|
||||
"page_size": "auto"
|
||||
}
|
||||
},
|
||||
"rendering_options": null,
|
||||
"shipping_cost": null,
|
||||
"shipping_details": null,
|
||||
"starting_balance": 0,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"status": "draft",
|
||||
@@ -164,10 +192,16 @@
|
||||
"voided_at": null
|
||||
},
|
||||
"subscription": null,
|
||||
"subscription_details": {
|
||||
"metadata": null
|
||||
},
|
||||
"subtotal": 0,
|
||||
"subtotal_excluding_tax": 0,
|
||||
"tax": null,
|
||||
"test_clock": null,
|
||||
"total": 0,
|
||||
"total_discount_amounts": [],
|
||||
"total_excluding_tax": 0,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": null
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
{
|
||||
"account_country": "US",
|
||||
"account_name": "NORMALIZED-1",
|
||||
"account_name": "Kandra Labs, Inc.",
|
||||
"account_tax_ids": null,
|
||||
"amount_due": 24000,
|
||||
"amount_paid": 0,
|
||||
"amount_remaining": 24000,
|
||||
"amount_shipping": 0,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"attempt_count": 0,
|
||||
"attempted": false,
|
||||
@@ -34,23 +36,27 @@
|
||||
"discount": null,
|
||||
"discounts": [],
|
||||
"due_date": null,
|
||||
"effective_at": null,
|
||||
"ending_balance": null,
|
||||
"footer": null,
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": null,
|
||||
"id": "in_NORMALIZED00000000000004",
|
||||
"id": "in_NORMALIZED00000000000003",
|
||||
"invoice_pdf": null,
|
||||
"last_finalization_error": null,
|
||||
"latest_revision": null,
|
||||
"lines": {
|
||||
"data": [
|
||||
{
|
||||
"amount": 24000,
|
||||
"amount_excluding_tax": 24000,
|
||||
"currency": "usd",
|
||||
"description": "Zulip Cloud Standard - renewal",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000007",
|
||||
"invoice_item": "ii_NORMALIZED00000000000007",
|
||||
"id": "il_NORMALIZED00000000000005",
|
||||
"invoice_item": "ii_NORMALIZED00000000000005",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -64,13 +70,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000007",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000005",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0007",
|
||||
"product": "prod_NORMALIZED0003",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -80,17 +87,21 @@
|
||||
"unit_amount_decimal": "4000"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "4000"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 1,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000004/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000003/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
@@ -99,8 +110,10 @@
|
||||
"object": "invoice",
|
||||
"on_behalf_of": null,
|
||||
"paid": false,
|
||||
"paid_out_of_band": false,
|
||||
"payment_intent": null,
|
||||
"payment_settings": {
|
||||
"default_mandate": null,
|
||||
"payment_method_options": null,
|
||||
"payment_method_types": null
|
||||
},
|
||||
@@ -110,6 +123,15 @@
|
||||
"pre_payment_credit_notes_amount": 0,
|
||||
"quote": null,
|
||||
"receipt_number": null,
|
||||
"rendering": {
|
||||
"amount_tax_display": null,
|
||||
"pdf": {
|
||||
"page_size": "auto"
|
||||
}
|
||||
},
|
||||
"rendering_options": null,
|
||||
"shipping_cost": null,
|
||||
"shipping_details": null,
|
||||
"starting_balance": 0,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"status": "draft",
|
||||
@@ -120,10 +142,16 @@
|
||||
"voided_at": null
|
||||
},
|
||||
"subscription": null,
|
||||
"subscription_details": {
|
||||
"metadata": null
|
||||
},
|
||||
"subtotal": 24000,
|
||||
"subtotal_excluding_tax": 24000,
|
||||
"tax": null,
|
||||
"test_clock": null,
|
||||
"total": 24000,
|
||||
"total_discount_amounts": [],
|
||||
"total_excluding_tax": 24000,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": null
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
{
|
||||
"account_country": "US",
|
||||
"account_name": "NORMALIZED-1",
|
||||
"account_name": "Kandra Labs, Inc.",
|
||||
"account_tax_ids": null,
|
||||
"amount_due": 0,
|
||||
"amount_paid": 0,
|
||||
"amount_remaining": 0,
|
||||
"amount_shipping": 0,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"attempt_count": 0,
|
||||
"attempted": true,
|
||||
@@ -34,29 +36,33 @@
|
||||
"discount": null,
|
||||
"discounts": [],
|
||||
"due_date": null,
|
||||
"effective_at": 1000000000,
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9BNDRqUzlSeE5ZbkM2YXNhYmhHRDNCN0pTZ3E001000SGRn6zX",
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9BNDRqUzlSeE5ZbkM2YXNhYmhHRDNCN0pTZ3E001000SGRn6zX/pdf",
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpiMHNFNHp4OGxtTUNIclNiWWdZa0NQNmpqMVRJLDkyMDM1MjA502000hPybKLo?s=ap",
|
||||
"id": "in_NORMALIZED00000000000001",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpiMHNFNHp4OGxtTUNIclNiWWdZa0NQNmpqMVRJLDkyMDM1MjA502000hPybKLo/pdf?s=ap",
|
||||
"last_finalization_error": null,
|
||||
"latest_revision": null,
|
||||
"lines": {
|
||||
"data": [
|
||||
{
|
||||
"amount": 7200,
|
||||
"amount_excluding_tax": 7200,
|
||||
"currency": "usd",
|
||||
"description": "Zulip Cloud Standard",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000003",
|
||||
"invoice_item": "ii_NORMALIZED00000000000003",
|
||||
"id": "il_NORMALIZED00000000000001",
|
||||
"invoice_item": "ii_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
"end": 1357095845,
|
||||
"start": 1325473445
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
@@ -64,13 +70,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000003",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0003",
|
||||
"product": "prod_NORMALIZED0001",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -80,21 +87,26 @@
|
||||
"unit_amount_decimal": "1200"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "1200"
|
||||
},
|
||||
{
|
||||
"amount": -7200,
|
||||
"amount_excluding_tax": -7200,
|
||||
"currency": "usd",
|
||||
"description": "Payment (Card ending in 4242)",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000004",
|
||||
"invoice_item": "ii_NORMALIZED00000000000004",
|
||||
"id": "il_NORMALIZED00000000000002",
|
||||
"invoice_item": "ii_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -108,13 +120,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0004",
|
||||
"product": "prod_NORMALIZED0002",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -124,27 +137,33 @@
|
||||
"unit_amount_decimal": "-7200"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "-7200"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000001/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"next_payment_attempt": null,
|
||||
"number": "NORMALI-0003",
|
||||
"number": "NORMALI-0002",
|
||||
"object": "invoice",
|
||||
"on_behalf_of": null,
|
||||
"paid": true,
|
||||
"paid_out_of_band": false,
|
||||
"payment_intent": null,
|
||||
"payment_settings": {
|
||||
"default_mandate": null,
|
||||
"payment_method_options": null,
|
||||
"payment_method_types": null
|
||||
},
|
||||
@@ -154,6 +173,15 @@
|
||||
"pre_payment_credit_notes_amount": 0,
|
||||
"quote": null,
|
||||
"receipt_number": null,
|
||||
"rendering": {
|
||||
"amount_tax_display": null,
|
||||
"pdf": {
|
||||
"page_size": "letter"
|
||||
}
|
||||
},
|
||||
"rendering_options": null,
|
||||
"shipping_cost": null,
|
||||
"shipping_details": null,
|
||||
"starting_balance": 0,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"status": "paid",
|
||||
@@ -164,10 +192,16 @@
|
||||
"voided_at": null
|
||||
},
|
||||
"subscription": null,
|
||||
"subscription_details": {
|
||||
"metadata": null
|
||||
},
|
||||
"subtotal": 0,
|
||||
"subtotal_excluding_tax": 0,
|
||||
"tax": null,
|
||||
"test_clock": null,
|
||||
"total": 0,
|
||||
"total_discount_amounts": [],
|
||||
"total_excluding_tax": 0,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": null
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
{
|
||||
"account_country": "US",
|
||||
"account_name": "NORMALIZED-1",
|
||||
"account_name": "Kandra Labs, Inc.",
|
||||
"account_tax_ids": null,
|
||||
"amount_due": 0,
|
||||
"amount_paid": 0,
|
||||
"amount_remaining": 0,
|
||||
"amount_shipping": 0,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"attempt_count": 0,
|
||||
"attempted": true,
|
||||
@@ -34,23 +36,27 @@
|
||||
"discount": null,
|
||||
"discounts": [],
|
||||
"due_date": null,
|
||||
"effective_at": 1000000000,
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9Ba2NPMVJlTGJDNXlwMEFBVU1sY01VTDNHTHNk0100ARPvAEt8",
|
||||
"id": "in_NORMALIZED00000000000003",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9Ba2NPMVJlTGJDNXlwMEFBVU1sY01VTDNHTHNk0100ARPvAEt8/pdf",
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpiZG84bnRuUUtrVXRnN0pvOEFlUkJqY0ZBZFhCLDkyMDM1MjE502004xw8zwol?s=ap",
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpiZG84bnRuUUtrVXRnN0pvOEFlUkJqY0ZBZFhCLDkyMDM1MjE502004xw8zwol/pdf?s=ap",
|
||||
"last_finalization_error": null,
|
||||
"latest_revision": null,
|
||||
"lines": {
|
||||
"data": [
|
||||
{
|
||||
"amount": 36000,
|
||||
"amount_excluding_tax": 36000,
|
||||
"currency": "usd",
|
||||
"description": "Zulip Cloud Standard",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000005",
|
||||
"invoice_item": "ii_NORMALIZED00000000000005",
|
||||
"id": "il_NORMALIZED00000000000003",
|
||||
"invoice_item": "ii_NORMALIZED00000000000003",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -64,13 +70,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000005",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000003",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0005",
|
||||
"product": "prod_NORMALIZED0001",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -80,21 +87,26 @@
|
||||
"unit_amount_decimal": "6000"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "6000"
|
||||
},
|
||||
{
|
||||
"amount": -36000,
|
||||
"amount_excluding_tax": -36000,
|
||||
"currency": "usd",
|
||||
"description": "Payment (Card ending in 4242)",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000006",
|
||||
"invoice_item": "ii_NORMALIZED00000000000006",
|
||||
"id": "il_NORMALIZED00000000000004",
|
||||
"invoice_item": "ii_NORMALIZED00000000000004",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -108,13 +120,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000006",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0006",
|
||||
"product": "prod_NORMALIZED0002",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -124,27 +137,33 @@
|
||||
"unit_amount_decimal": "-36000"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "-36000"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000003/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"next_payment_attempt": null,
|
||||
"number": "NORMALI-0004",
|
||||
"number": "NORMALI-0003",
|
||||
"object": "invoice",
|
||||
"on_behalf_of": null,
|
||||
"paid": true,
|
||||
"paid_out_of_band": false,
|
||||
"payment_intent": null,
|
||||
"payment_settings": {
|
||||
"default_mandate": null,
|
||||
"payment_method_options": null,
|
||||
"payment_method_types": null
|
||||
},
|
||||
@@ -154,6 +173,15 @@
|
||||
"pre_payment_credit_notes_amount": 0,
|
||||
"quote": null,
|
||||
"receipt_number": null,
|
||||
"rendering": {
|
||||
"amount_tax_display": null,
|
||||
"pdf": {
|
||||
"page_size": "letter"
|
||||
}
|
||||
},
|
||||
"rendering_options": null,
|
||||
"shipping_cost": null,
|
||||
"shipping_details": null,
|
||||
"starting_balance": 0,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"status": "paid",
|
||||
@@ -164,10 +192,16 @@
|
||||
"voided_at": null
|
||||
},
|
||||
"subscription": null,
|
||||
"subscription_details": {
|
||||
"metadata": null
|
||||
},
|
||||
"subtotal": 0,
|
||||
"subtotal_excluding_tax": 0,
|
||||
"tax": null,
|
||||
"test_clock": null,
|
||||
"total": 0,
|
||||
"total_discount_amounts": [],
|
||||
"total_excluding_tax": 0,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": null
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
{
|
||||
"account_country": "US",
|
||||
"account_name": "NORMALIZED-1",
|
||||
"account_name": "Kandra Labs, Inc.",
|
||||
"account_tax_ids": null,
|
||||
"amount_due": 24000,
|
||||
"amount_paid": 0,
|
||||
"amount_remaining": 24000,
|
||||
"amount_shipping": 0,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"attempt_count": 0,
|
||||
"attempted": false,
|
||||
@@ -34,23 +36,27 @@
|
||||
"discount": null,
|
||||
"discounts": [],
|
||||
"due_date": null,
|
||||
"effective_at": 1000000000,
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9BZ1A2VnVzRGRzR1BIS3V5YWJtejhEYVd1Z0xO0100PL5hiifd",
|
||||
"id": "in_NORMALIZED00000000000004",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9BZ1A2VnVzRGRzR1BIS3V5YWJtejhEYVd1Z0xO0100PL5hiifd/pdf",
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpjd2l4VnY1aGVsY1Ztb3BRODN5dGRHbGhpNk02LDkyMDM1MjIy0200dqk7fzRz?s=ap",
|
||||
"id": "in_NORMALIZED00000000000003",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpjd2l4VnY1aGVsY1Ztb3BRODN5dGRHbGhpNk02LDkyMDM1MjIy0200dqk7fzRz/pdf?s=ap",
|
||||
"last_finalization_error": null,
|
||||
"latest_revision": null,
|
||||
"lines": {
|
||||
"data": [
|
||||
{
|
||||
"amount": 24000,
|
||||
"amount_excluding_tax": 24000,
|
||||
"currency": "usd",
|
||||
"description": "Zulip Cloud Standard - renewal",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000007",
|
||||
"invoice_item": "ii_NORMALIZED00000000000007",
|
||||
"id": "il_NORMALIZED00000000000005",
|
||||
"invoice_item": "ii_NORMALIZED00000000000005",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -64,13 +70,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000007",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000005",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0007",
|
||||
"product": "prod_NORMALIZED0003",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -80,27 +87,33 @@
|
||||
"unit_amount_decimal": "4000"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "4000"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 1,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000004/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000003/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"next_payment_attempt": 1000000000,
|
||||
"number": "NORMALI-0005",
|
||||
"number": "NORMALI-0004",
|
||||
"object": "invoice",
|
||||
"on_behalf_of": null,
|
||||
"paid": false,
|
||||
"paid_out_of_band": false,
|
||||
"payment_intent": "pi_NORMALIZED00000000000003",
|
||||
"payment_settings": {
|
||||
"default_mandate": null,
|
||||
"payment_method_options": null,
|
||||
"payment_method_types": null
|
||||
},
|
||||
@@ -110,6 +123,15 @@
|
||||
"pre_payment_credit_notes_amount": 0,
|
||||
"quote": null,
|
||||
"receipt_number": null,
|
||||
"rendering": {
|
||||
"amount_tax_display": null,
|
||||
"pdf": {
|
||||
"page_size": "letter"
|
||||
}
|
||||
},
|
||||
"rendering_options": null,
|
||||
"shipping_cost": null,
|
||||
"shipping_details": null,
|
||||
"starting_balance": 0,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"status": "open",
|
||||
@@ -120,10 +142,16 @@
|
||||
"voided_at": null
|
||||
},
|
||||
"subscription": null,
|
||||
"subscription_details": {
|
||||
"metadata": null
|
||||
},
|
||||
"subtotal": 24000,
|
||||
"subtotal_excluding_tax": 24000,
|
||||
"tax": null,
|
||||
"test_clock": null,
|
||||
"total": 24000,
|
||||
"total_discount_amounts": [],
|
||||
"total_excluding_tax": 24000,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": null
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
"data": [
|
||||
{
|
||||
"account_country": "US",
|
||||
"account_name": "NORMALIZED-1",
|
||||
"account_name": "Kandra Labs, Inc.",
|
||||
"account_tax_ids": null,
|
||||
"amount_due": 0,
|
||||
"amount_paid": 0,
|
||||
"amount_remaining": 0,
|
||||
"amount_shipping": 0,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"attempt_count": 0,
|
||||
"attempted": true,
|
||||
@@ -36,29 +38,33 @@
|
||||
"discount": null,
|
||||
"discounts": [],
|
||||
"due_date": null,
|
||||
"effective_at": 1000000000,
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9BNDRqUzlSeE5ZbkM2YXNhYmhHRDNCN0pTZ3E001000SGRn6zX",
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9BNDRqUzlSeE5ZbkM2YXNhYmhHRDNCN0pTZ3E001000SGRn6zX/pdf",
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpiMHNFNHp4OGxtTUNIclNiWWdZa0NQNmpqMVRJLDkyMDM1MjEx0200eb8tuh13?s=ap",
|
||||
"id": "in_NORMALIZED00000000000001",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpiMHNFNHp4OGxtTUNIclNiWWdZa0NQNmpqMVRJLDkyMDM1MjEx0200eb8tuh13/pdf?s=ap",
|
||||
"last_finalization_error": null,
|
||||
"latest_revision": null,
|
||||
"lines": {
|
||||
"data": [
|
||||
{
|
||||
"amount": 7200,
|
||||
"amount_excluding_tax": 7200,
|
||||
"currency": "usd",
|
||||
"description": "Zulip Cloud Standard",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000003",
|
||||
"invoice_item": "ii_NORMALIZED00000000000003",
|
||||
"id": "il_NORMALIZED00000000000001",
|
||||
"invoice_item": "ii_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
"end": 1357095845,
|
||||
"start": 1325473445
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
@@ -66,13 +72,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000003",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0003",
|
||||
"product": "prod_NORMALIZED0001",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -82,21 +89,26 @@
|
||||
"unit_amount_decimal": "1200"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "1200"
|
||||
},
|
||||
{
|
||||
"amount": -7200,
|
||||
"amount_excluding_tax": -7200,
|
||||
"currency": "usd",
|
||||
"description": "Payment (Card ending in 4242)",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000004",
|
||||
"invoice_item": "ii_NORMALIZED00000000000004",
|
||||
"id": "il_NORMALIZED00000000000002",
|
||||
"invoice_item": "ii_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -110,13 +122,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0004",
|
||||
"product": "prod_NORMALIZED0002",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -126,27 +139,33 @@
|
||||
"unit_amount_decimal": "-7200"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "-7200"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000001/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"next_payment_attempt": null,
|
||||
"number": "NORMALI-0003",
|
||||
"number": "NORMALI-0002",
|
||||
"object": "invoice",
|
||||
"on_behalf_of": null,
|
||||
"paid": true,
|
||||
"paid_out_of_band": false,
|
||||
"payment_intent": null,
|
||||
"payment_settings": {
|
||||
"default_mandate": null,
|
||||
"payment_method_options": null,
|
||||
"payment_method_types": null
|
||||
},
|
||||
@@ -156,6 +175,15 @@
|
||||
"pre_payment_credit_notes_amount": 0,
|
||||
"quote": null,
|
||||
"receipt_number": null,
|
||||
"rendering": {
|
||||
"amount_tax_display": null,
|
||||
"pdf": {
|
||||
"page_size": "letter"
|
||||
}
|
||||
},
|
||||
"rendering_options": null,
|
||||
"shipping_cost": null,
|
||||
"shipping_details": null,
|
||||
"starting_balance": 0,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"status": "paid",
|
||||
@@ -166,10 +194,16 @@
|
||||
"voided_at": null
|
||||
},
|
||||
"subscription": null,
|
||||
"subscription_details": {
|
||||
"metadata": null
|
||||
},
|
||||
"subtotal": 0,
|
||||
"subtotal_excluding_tax": 0,
|
||||
"tax": null,
|
||||
"test_clock": null,
|
||||
"total": 0,
|
||||
"total_discount_amounts": [],
|
||||
"total_excluding_tax": 0,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": 1000000000
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
"data": [
|
||||
{
|
||||
"account_country": "US",
|
||||
"account_name": "NORMALIZED-1",
|
||||
"account_name": "Kandra Labs, Inc.",
|
||||
"account_tax_ids": null,
|
||||
"amount_due": 0,
|
||||
"amount_paid": 0,
|
||||
"amount_remaining": 0,
|
||||
"amount_shipping": 0,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"attempt_count": 0,
|
||||
"attempted": true,
|
||||
@@ -36,23 +38,27 @@
|
||||
"discount": null,
|
||||
"discounts": [],
|
||||
"due_date": null,
|
||||
"effective_at": 1000000000,
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9Ba2NPMVJlTGJDNXlwMEFBVU1sY01VTDNHTHNk0100ARPvAEt8",
|
||||
"id": "in_NORMALIZED00000000000003",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9Ba2NPMVJlTGJDNXlwMEFBVU1sY01VTDNHTHNk0100ARPvAEt8/pdf",
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpiZG84bnRuUUtrVXRnN0pvOEFlUkJqY0ZBZFhCLDkyMDM1MjIx0200OMBLJkxA?s=ap",
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpiZG84bnRuUUtrVXRnN0pvOEFlUkJqY0ZBZFhCLDkyMDM1MjIx0200OMBLJkxA/pdf?s=ap",
|
||||
"last_finalization_error": null,
|
||||
"latest_revision": null,
|
||||
"lines": {
|
||||
"data": [
|
||||
{
|
||||
"amount": 36000,
|
||||
"amount_excluding_tax": 36000,
|
||||
"currency": "usd",
|
||||
"description": "Zulip Cloud Standard",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000005",
|
||||
"invoice_item": "ii_NORMALIZED00000000000005",
|
||||
"id": "il_NORMALIZED00000000000003",
|
||||
"invoice_item": "ii_NORMALIZED00000000000003",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -66,13 +72,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000005",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000003",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0005",
|
||||
"product": "prod_NORMALIZED0001",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -82,188 +89,19 @@
|
||||
"unit_amount_decimal": "6000"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "6000"
|
||||
},
|
||||
{
|
||||
"amount": -36000,
|
||||
"currency": "usd",
|
||||
"description": "Payment (Card ending in 4242)",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000006",
|
||||
"invoice_item": "ii_NORMALIZED00000000000006",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
"active": false,
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000006",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0006",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
"transform_quantity": null,
|
||||
"type": "one_time",
|
||||
"unit_amount": -36000,
|
||||
"unit_amount_decimal": "-36000"
|
||||
},
|
||||
"proration": false,
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000003/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"next_payment_attempt": null,
|
||||
"number": "NORMALI-0004",
|
||||
"object": "invoice",
|
||||
"on_behalf_of": null,
|
||||
"paid": true,
|
||||
"payment_intent": null,
|
||||
"payment_settings": {
|
||||
"payment_method_options": null,
|
||||
"payment_method_types": null
|
||||
},
|
||||
"period_end": 1000000000,
|
||||
"period_start": 1000000000,
|
||||
"post_payment_credit_notes_amount": 0,
|
||||
"pre_payment_credit_notes_amount": 0,
|
||||
"quote": null,
|
||||
"receipt_number": null,
|
||||
"starting_balance": 0,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"status": "paid",
|
||||
"status_transitions": {
|
||||
"finalized_at": 1000000000,
|
||||
"marked_uncollectible_at": null,
|
||||
"paid_at": 1000000000,
|
||||
"voided_at": null
|
||||
},
|
||||
"subscription": null,
|
||||
"subtotal": 0,
|
||||
"tax": null,
|
||||
"total": 0,
|
||||
"total_discount_amounts": [],
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": 1000000000
|
||||
},
|
||||
{
|
||||
"account_country": "US",
|
||||
"account_name": "NORMALIZED-1",
|
||||
"account_tax_ids": null,
|
||||
"amount_due": 0,
|
||||
"amount_paid": 0,
|
||||
"amount_remaining": 0,
|
||||
"application_fee_amount": null,
|
||||
"attempt_count": 0,
|
||||
"attempted": true,
|
||||
"auto_advance": false,
|
||||
"automatic_tax": {
|
||||
"enabled": false,
|
||||
"status": null
|
||||
},
|
||||
"billing_reason": "manual",
|
||||
"charge": null,
|
||||
"collection_method": "charge_automatically",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"custom_fields": null,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"customer_address": null,
|
||||
"customer_email": "hamlet@zulip.com",
|
||||
"customer_name": null,
|
||||
"customer_phone": null,
|
||||
"customer_shipping": null,
|
||||
"customer_tax_exempt": "none",
|
||||
"customer_tax_ids": [],
|
||||
"default_payment_method": null,
|
||||
"default_source": null,
|
||||
"default_tax_rates": [],
|
||||
"description": null,
|
||||
"discount": null,
|
||||
"discounts": [],
|
||||
"due_date": null,
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9BNDRqUzlSeE5ZbkM2YXNhYmhHRDNCN0pTZ3E001000SGRn6zX",
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9BNDRqUzlSeE5ZbkM2YXNhYmhHRDNCN0pTZ3E001000SGRn6zX/pdf",
|
||||
"last_finalization_error": null,
|
||||
"lines": {
|
||||
"data": [
|
||||
{
|
||||
"amount": 7200,
|
||||
"currency": "usd",
|
||||
"description": "Zulip Cloud Standard",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000003",
|
||||
"invoice_item": "ii_NORMALIZED00000000000003",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
"active": false,
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000003",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0003",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
"transform_quantity": null,
|
||||
"type": "one_time",
|
||||
"unit_amount": 1200,
|
||||
"unit_amount_decimal": "1200"
|
||||
},
|
||||
"proration": false,
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
},
|
||||
{
|
||||
"amount": -7200,
|
||||
"amount_excluding_tax": -36000,
|
||||
"currency": "usd",
|
||||
"description": "Payment (Card ending in 4242)",
|
||||
"discount_amounts": [],
|
||||
@@ -284,27 +122,32 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0004",
|
||||
"product": "prod_NORMALIZED0002",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
"transform_quantity": null,
|
||||
"type": "one_time",
|
||||
"unit_amount": -7200,
|
||||
"unit_amount_decimal": "-7200"
|
||||
"unit_amount": -36000,
|
||||
"unit_amount_decimal": "-36000"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "-36000"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
@@ -319,8 +162,10 @@
|
||||
"object": "invoice",
|
||||
"on_behalf_of": null,
|
||||
"paid": true,
|
||||
"paid_out_of_band": false,
|
||||
"payment_intent": null,
|
||||
"payment_settings": {
|
||||
"default_mandate": null,
|
||||
"payment_method_options": null,
|
||||
"payment_method_types": null
|
||||
},
|
||||
@@ -330,6 +175,15 @@
|
||||
"pre_payment_credit_notes_amount": 0,
|
||||
"quote": null,
|
||||
"receipt_number": null,
|
||||
"rendering": {
|
||||
"amount_tax_display": null,
|
||||
"pdf": {
|
||||
"page_size": "letter"
|
||||
}
|
||||
},
|
||||
"rendering_options": null,
|
||||
"shipping_cost": null,
|
||||
"shipping_details": null,
|
||||
"starting_balance": 0,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"status": "paid",
|
||||
@@ -340,10 +194,224 @@
|
||||
"voided_at": null
|
||||
},
|
||||
"subscription": null,
|
||||
"subscription_details": {
|
||||
"metadata": null
|
||||
},
|
||||
"subtotal": 0,
|
||||
"subtotal_excluding_tax": 0,
|
||||
"tax": null,
|
||||
"test_clock": null,
|
||||
"total": 0,
|
||||
"total_discount_amounts": [],
|
||||
"total_excluding_tax": 0,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": 1000000000
|
||||
},
|
||||
{
|
||||
"account_country": "US",
|
||||
"account_name": "Kandra Labs, Inc.",
|
||||
"account_tax_ids": null,
|
||||
"amount_due": 0,
|
||||
"amount_paid": 0,
|
||||
"amount_remaining": 0,
|
||||
"amount_shipping": 0,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"attempt_count": 0,
|
||||
"attempted": true,
|
||||
"auto_advance": false,
|
||||
"automatic_tax": {
|
||||
"enabled": false,
|
||||
"status": null
|
||||
},
|
||||
"billing_reason": "manual",
|
||||
"charge": null,
|
||||
"collection_method": "charge_automatically",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"custom_fields": null,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"customer_address": null,
|
||||
"customer_email": "hamlet@zulip.com",
|
||||
"customer_name": null,
|
||||
"customer_phone": null,
|
||||
"customer_shipping": null,
|
||||
"customer_tax_exempt": "none",
|
||||
"customer_tax_ids": [],
|
||||
"default_payment_method": null,
|
||||
"default_source": null,
|
||||
"default_tax_rates": [],
|
||||
"description": null,
|
||||
"discount": null,
|
||||
"discounts": [],
|
||||
"due_date": null,
|
||||
"effective_at": 1000000000,
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpiMHNFNHp4OGxtTUNIclNiWWdZa0NQNmpqMVRJLDkyMDM1MjIx02006mE2ERoT?s=ap",
|
||||
"id": "in_NORMALIZED00000000000001",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpiMHNFNHp4OGxtTUNIclNiWWdZa0NQNmpqMVRJLDkyMDM1MjIx02006mE2ERoT/pdf?s=ap",
|
||||
"last_finalization_error": null,
|
||||
"latest_revision": null,
|
||||
"lines": {
|
||||
"data": [
|
||||
{
|
||||
"amount": 7200,
|
||||
"amount_excluding_tax": 7200,
|
||||
"currency": "usd",
|
||||
"description": "Zulip Cloud Standard",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000001",
|
||||
"invoice_item": "ii_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
"period": {
|
||||
"end": 1357095845,
|
||||
"start": 1325473445
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
"active": false,
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0001",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
"transform_quantity": null,
|
||||
"type": "one_time",
|
||||
"unit_amount": 1200,
|
||||
"unit_amount_decimal": "1200"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "1200"
|
||||
},
|
||||
{
|
||||
"amount": -7200,
|
||||
"amount_excluding_tax": -7200,
|
||||
"currency": "usd",
|
||||
"description": "Payment (Card ending in 4242)",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000002",
|
||||
"invoice_item": "ii_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
"active": false,
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0002",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
"transform_quantity": null,
|
||||
"type": "one_time",
|
||||
"unit_amount": -7200,
|
||||
"unit_amount_decimal": "-7200"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "-7200"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000001/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"next_payment_attempt": null,
|
||||
"number": "NORMALI-0002",
|
||||
"object": "invoice",
|
||||
"on_behalf_of": null,
|
||||
"paid": true,
|
||||
"paid_out_of_band": false,
|
||||
"payment_intent": null,
|
||||
"payment_settings": {
|
||||
"default_mandate": null,
|
||||
"payment_method_options": null,
|
||||
"payment_method_types": null
|
||||
},
|
||||
"period_end": 1000000000,
|
||||
"period_start": 1000000000,
|
||||
"post_payment_credit_notes_amount": 0,
|
||||
"pre_payment_credit_notes_amount": 0,
|
||||
"quote": null,
|
||||
"receipt_number": null,
|
||||
"rendering": {
|
||||
"amount_tax_display": null,
|
||||
"pdf": {
|
||||
"page_size": "letter"
|
||||
}
|
||||
},
|
||||
"rendering_options": null,
|
||||
"shipping_cost": null,
|
||||
"shipping_details": null,
|
||||
"starting_balance": 0,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"status": "paid",
|
||||
"status_transitions": {
|
||||
"finalized_at": 1000000000,
|
||||
"marked_uncollectible_at": null,
|
||||
"paid_at": 1000000000,
|
||||
"voided_at": null
|
||||
},
|
||||
"subscription": null,
|
||||
"subscription_details": {
|
||||
"metadata": null
|
||||
},
|
||||
"subtotal": 0,
|
||||
"subtotal_excluding_tax": 0,
|
||||
"tax": null,
|
||||
"test_clock": null,
|
||||
"total": 0,
|
||||
"total_discount_amounts": [],
|
||||
"total_excluding_tax": 0,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": 1000000000
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
"data": [
|
||||
{
|
||||
"account_country": "US",
|
||||
"account_name": "NORMALIZED-1",
|
||||
"account_name": "Kandra Labs, Inc.",
|
||||
"account_tax_ids": null,
|
||||
"amount_due": 24000,
|
||||
"amount_paid": 0,
|
||||
"amount_remaining": 24000,
|
||||
"amount_shipping": 0,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"attempt_count": 0,
|
||||
"attempted": false,
|
||||
@@ -36,23 +38,27 @@
|
||||
"discount": null,
|
||||
"discounts": [],
|
||||
"due_date": null,
|
||||
"effective_at": 1000000000,
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9BZ1A2VnVzRGRzR1BIS3V5YWJtejhEYVd1Z0xO0100PL5hiifd",
|
||||
"id": "in_NORMALIZED00000000000004",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9BZ1A2VnVzRGRzR1BIS3V5YWJtejhEYVd1Z0xO0100PL5hiifd/pdf",
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpjd2l4VnY1aGVsY1Ztb3BRODN5dGRHbGhpNk02LDkyMDM1MjIz02008PWTxXb7?s=ap",
|
||||
"id": "in_NORMALIZED00000000000003",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpjd2l4VnY1aGVsY1Ztb3BRODN5dGRHbGhpNk02LDkyMDM1MjIz02008PWTxXb7/pdf?s=ap",
|
||||
"last_finalization_error": null,
|
||||
"latest_revision": null,
|
||||
"lines": {
|
||||
"data": [
|
||||
{
|
||||
"amount": 24000,
|
||||
"amount_excluding_tax": 24000,
|
||||
"currency": "usd",
|
||||
"description": "Zulip Cloud Standard - renewal",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000007",
|
||||
"invoice_item": "ii_NORMALIZED00000000000007",
|
||||
"id": "il_NORMALIZED00000000000005",
|
||||
"invoice_item": "ii_NORMALIZED00000000000005",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -66,13 +72,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000007",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000005",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0007",
|
||||
"product": "prod_NORMALIZED0003",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -82,27 +89,33 @@
|
||||
"unit_amount_decimal": "4000"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "4000"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 1,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000004/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000003/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"next_payment_attempt": 1000000000,
|
||||
"number": "NORMALI-0005",
|
||||
"number": "NORMALI-0004",
|
||||
"object": "invoice",
|
||||
"on_behalf_of": null,
|
||||
"paid": false,
|
||||
"paid_out_of_band": false,
|
||||
"payment_intent": "pi_NORMALIZED00000000000003",
|
||||
"payment_settings": {
|
||||
"default_mandate": null,
|
||||
"payment_method_options": null,
|
||||
"payment_method_types": null
|
||||
},
|
||||
@@ -112,6 +125,15 @@
|
||||
"pre_payment_credit_notes_amount": 0,
|
||||
"quote": null,
|
||||
"receipt_number": null,
|
||||
"rendering": {
|
||||
"amount_tax_display": null,
|
||||
"pdf": {
|
||||
"page_size": "letter"
|
||||
}
|
||||
},
|
||||
"rendering_options": null,
|
||||
"shipping_cost": null,
|
||||
"shipping_details": null,
|
||||
"starting_balance": 0,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"status": "open",
|
||||
@@ -122,21 +144,29 @@
|
||||
"voided_at": null
|
||||
},
|
||||
"subscription": null,
|
||||
"subscription_details": {
|
||||
"metadata": null
|
||||
},
|
||||
"subtotal": 24000,
|
||||
"subtotal_excluding_tax": 24000,
|
||||
"tax": null,
|
||||
"test_clock": null,
|
||||
"total": 24000,
|
||||
"total_discount_amounts": [],
|
||||
"total_excluding_tax": 24000,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": 1000000000
|
||||
"webhooks_delivered_at": null
|
||||
},
|
||||
{
|
||||
"account_country": "US",
|
||||
"account_name": "NORMALIZED-1",
|
||||
"account_name": "Kandra Labs, Inc.",
|
||||
"account_tax_ids": null,
|
||||
"amount_due": 0,
|
||||
"amount_paid": 0,
|
||||
"amount_remaining": 0,
|
||||
"amount_shipping": 0,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"attempt_count": 0,
|
||||
"attempted": true,
|
||||
@@ -166,23 +196,27 @@
|
||||
"discount": null,
|
||||
"discounts": [],
|
||||
"due_date": null,
|
||||
"effective_at": 1000000000,
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9Ba2NPMVJlTGJDNXlwMEFBVU1sY01VTDNHTHNk0100ARPvAEt8",
|
||||
"id": "in_NORMALIZED00000000000003",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9Ba2NPMVJlTGJDNXlwMEFBVU1sY01VTDNHTHNk0100ARPvAEt8/pdf",
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpiZG84bnRuUUtrVXRnN0pvOEFlUkJqY0ZBZFhCLDkyMDM1MjIz0200JbHnRP6C?s=ap",
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpiZG84bnRuUUtrVXRnN0pvOEFlUkJqY0ZBZFhCLDkyMDM1MjIz0200JbHnRP6C/pdf?s=ap",
|
||||
"last_finalization_error": null,
|
||||
"latest_revision": null,
|
||||
"lines": {
|
||||
"data": [
|
||||
{
|
||||
"amount": 36000,
|
||||
"amount_excluding_tax": 36000,
|
||||
"currency": "usd",
|
||||
"description": "Zulip Cloud Standard",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000005",
|
||||
"invoice_item": "ii_NORMALIZED00000000000005",
|
||||
"id": "il_NORMALIZED00000000000003",
|
||||
"invoice_item": "ii_NORMALIZED00000000000003",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -196,13 +230,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000005",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000003",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0005",
|
||||
"product": "prod_NORMALIZED0001",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -212,188 +247,19 @@
|
||||
"unit_amount_decimal": "6000"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "6000"
|
||||
},
|
||||
{
|
||||
"amount": -36000,
|
||||
"currency": "usd",
|
||||
"description": "Payment (Card ending in 4242)",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000006",
|
||||
"invoice_item": "ii_NORMALIZED00000000000006",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
"active": false,
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000006",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0006",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
"transform_quantity": null,
|
||||
"type": "one_time",
|
||||
"unit_amount": -36000,
|
||||
"unit_amount_decimal": "-36000"
|
||||
},
|
||||
"proration": false,
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000003/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"next_payment_attempt": null,
|
||||
"number": "NORMALI-0004",
|
||||
"object": "invoice",
|
||||
"on_behalf_of": null,
|
||||
"paid": true,
|
||||
"payment_intent": null,
|
||||
"payment_settings": {
|
||||
"payment_method_options": null,
|
||||
"payment_method_types": null
|
||||
},
|
||||
"period_end": 1000000000,
|
||||
"period_start": 1000000000,
|
||||
"post_payment_credit_notes_amount": 0,
|
||||
"pre_payment_credit_notes_amount": 0,
|
||||
"quote": null,
|
||||
"receipt_number": null,
|
||||
"starting_balance": 0,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"status": "paid",
|
||||
"status_transitions": {
|
||||
"finalized_at": 1000000000,
|
||||
"marked_uncollectible_at": null,
|
||||
"paid_at": 1000000000,
|
||||
"voided_at": null
|
||||
},
|
||||
"subscription": null,
|
||||
"subtotal": 0,
|
||||
"tax": null,
|
||||
"total": 0,
|
||||
"total_discount_amounts": [],
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": 1000000000
|
||||
},
|
||||
{
|
||||
"account_country": "US",
|
||||
"account_name": "NORMALIZED-1",
|
||||
"account_tax_ids": null,
|
||||
"amount_due": 0,
|
||||
"amount_paid": 0,
|
||||
"amount_remaining": 0,
|
||||
"application_fee_amount": null,
|
||||
"attempt_count": 0,
|
||||
"attempted": true,
|
||||
"auto_advance": false,
|
||||
"automatic_tax": {
|
||||
"enabled": false,
|
||||
"status": null
|
||||
},
|
||||
"billing_reason": "manual",
|
||||
"charge": null,
|
||||
"collection_method": "charge_automatically",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"custom_fields": null,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"customer_address": null,
|
||||
"customer_email": "hamlet@zulip.com",
|
||||
"customer_name": null,
|
||||
"customer_phone": null,
|
||||
"customer_shipping": null,
|
||||
"customer_tax_exempt": "none",
|
||||
"customer_tax_ids": [],
|
||||
"default_payment_method": null,
|
||||
"default_source": null,
|
||||
"default_tax_rates": [],
|
||||
"description": null,
|
||||
"discount": null,
|
||||
"discounts": [],
|
||||
"due_date": null,
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9BNDRqUzlSeE5ZbkM2YXNhYmhHRDNCN0pTZ3E001000SGRn6zX",
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01cDVIU2FXWHl2RnBLLF9LaG9BNDRqUzlSeE5ZbkM2YXNhYmhHRDNCN0pTZ3E001000SGRn6zX/pdf",
|
||||
"last_finalization_error": null,
|
||||
"lines": {
|
||||
"data": [
|
||||
{
|
||||
"amount": 7200,
|
||||
"currency": "usd",
|
||||
"description": "Zulip Cloud Standard",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000003",
|
||||
"invoice_item": "ii_NORMALIZED00000000000003",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
"active": false,
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000003",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0003",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
"transform_quantity": null,
|
||||
"type": "one_time",
|
||||
"unit_amount": 1200,
|
||||
"unit_amount_decimal": "1200"
|
||||
},
|
||||
"proration": false,
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
},
|
||||
{
|
||||
"amount": -7200,
|
||||
"amount_excluding_tax": -36000,
|
||||
"currency": "usd",
|
||||
"description": "Payment (Card ending in 4242)",
|
||||
"discount_amounts": [],
|
||||
@@ -414,27 +280,32 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0004",
|
||||
"product": "prod_NORMALIZED0002",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
"transform_quantity": null,
|
||||
"type": "one_time",
|
||||
"unit_amount": -7200,
|
||||
"unit_amount_decimal": "-7200"
|
||||
"unit_amount": -36000,
|
||||
"unit_amount_decimal": "-36000"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem"
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "-36000"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
@@ -449,8 +320,10 @@
|
||||
"object": "invoice",
|
||||
"on_behalf_of": null,
|
||||
"paid": true,
|
||||
"paid_out_of_band": false,
|
||||
"payment_intent": null,
|
||||
"payment_settings": {
|
||||
"default_mandate": null,
|
||||
"payment_method_options": null,
|
||||
"payment_method_types": null
|
||||
},
|
||||
@@ -460,6 +333,15 @@
|
||||
"pre_payment_credit_notes_amount": 0,
|
||||
"quote": null,
|
||||
"receipt_number": null,
|
||||
"rendering": {
|
||||
"amount_tax_display": null,
|
||||
"pdf": {
|
||||
"page_size": "letter"
|
||||
}
|
||||
},
|
||||
"rendering_options": null,
|
||||
"shipping_cost": null,
|
||||
"shipping_details": null,
|
||||
"starting_balance": 0,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"status": "paid",
|
||||
@@ -470,10 +352,224 @@
|
||||
"voided_at": null
|
||||
},
|
||||
"subscription": null,
|
||||
"subscription_details": {
|
||||
"metadata": null
|
||||
},
|
||||
"subtotal": 0,
|
||||
"subtotal_excluding_tax": 0,
|
||||
"tax": null,
|
||||
"test_clock": null,
|
||||
"total": 0,
|
||||
"total_discount_amounts": [],
|
||||
"total_excluding_tax": 0,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": 1000000000
|
||||
},
|
||||
{
|
||||
"account_country": "US",
|
||||
"account_name": "Kandra Labs, Inc.",
|
||||
"account_tax_ids": null,
|
||||
"amount_due": 0,
|
||||
"amount_paid": 0,
|
||||
"amount_remaining": 0,
|
||||
"amount_shipping": 0,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"attempt_count": 0,
|
||||
"attempted": true,
|
||||
"auto_advance": false,
|
||||
"automatic_tax": {
|
||||
"enabled": false,
|
||||
"status": null
|
||||
},
|
||||
"billing_reason": "manual",
|
||||
"charge": null,
|
||||
"collection_method": "charge_automatically",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"custom_fields": null,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"customer_address": null,
|
||||
"customer_email": "hamlet@zulip.com",
|
||||
"customer_name": null,
|
||||
"customer_phone": null,
|
||||
"customer_shipping": null,
|
||||
"customer_tax_exempt": "none",
|
||||
"customer_tax_ids": [],
|
||||
"default_payment_method": null,
|
||||
"default_source": null,
|
||||
"default_tax_rates": [],
|
||||
"description": null,
|
||||
"discount": null,
|
||||
"discounts": [],
|
||||
"due_date": null,
|
||||
"effective_at": 1000000000,
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpiMHNFNHp4OGxtTUNIclNiWWdZa0NQNmpqMVRJLDkyMDM1MjIz0200ykr4PqiR?s=ap",
|
||||
"id": "in_NORMALIZED00000000000001",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpiMHNFNHp4OGxtTUNIclNiWWdZa0NQNmpqMVRJLDkyMDM1MjIz0200ykr4PqiR/pdf?s=ap",
|
||||
"last_finalization_error": null,
|
||||
"latest_revision": null,
|
||||
"lines": {
|
||||
"data": [
|
||||
{
|
||||
"amount": 7200,
|
||||
"amount_excluding_tax": 7200,
|
||||
"currency": "usd",
|
||||
"description": "Zulip Cloud Standard",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000001",
|
||||
"invoice_item": "ii_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
"period": {
|
||||
"end": 1357095845,
|
||||
"start": 1325473445
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
"active": false,
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0001",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
"transform_quantity": null,
|
||||
"type": "one_time",
|
||||
"unit_amount": 1200,
|
||||
"unit_amount_decimal": "1200"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "1200"
|
||||
},
|
||||
{
|
||||
"amount": -7200,
|
||||
"amount_excluding_tax": -7200,
|
||||
"currency": "usd",
|
||||
"description": "Payment (Card ending in 4242)",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000002",
|
||||
"invoice_item": "ii_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
"active": false,
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0002",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
"transform_quantity": null,
|
||||
"type": "one_time",
|
||||
"unit_amount": -7200,
|
||||
"unit_amount_decimal": "-7200"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "-7200"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000001/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"next_payment_attempt": null,
|
||||
"number": "NORMALI-0002",
|
||||
"object": "invoice",
|
||||
"on_behalf_of": null,
|
||||
"paid": true,
|
||||
"paid_out_of_band": false,
|
||||
"payment_intent": null,
|
||||
"payment_settings": {
|
||||
"default_mandate": null,
|
||||
"payment_method_options": null,
|
||||
"payment_method_types": null
|
||||
},
|
||||
"period_end": 1000000000,
|
||||
"period_start": 1000000000,
|
||||
"post_payment_credit_notes_amount": 0,
|
||||
"pre_payment_credit_notes_amount": 0,
|
||||
"quote": null,
|
||||
"receipt_number": null,
|
||||
"rendering": {
|
||||
"amount_tax_display": null,
|
||||
"pdf": {
|
||||
"page_size": "letter"
|
||||
}
|
||||
},
|
||||
"rendering_options": null,
|
||||
"shipping_cost": null,
|
||||
"shipping_details": null,
|
||||
"starting_balance": 0,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"status": "paid",
|
||||
"status_transitions": {
|
||||
"finalized_at": 1000000000,
|
||||
"marked_uncollectible_at": null,
|
||||
"paid_at": 1000000000,
|
||||
"voided_at": null
|
||||
},
|
||||
"subscription": null,
|
||||
"subscription_details": {
|
||||
"metadata": null
|
||||
},
|
||||
"subtotal": 0,
|
||||
"subtotal_excluding_tax": 0,
|
||||
"tax": null,
|
||||
"test_clock": null,
|
||||
"total": 0,
|
||||
"total_discount_amounts": [],
|
||||
"total_excluding_tax": 0,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": 1000000000
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"description": "Payment (Card ending in 4242)",
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "ii_NORMALIZED00000000000004",
|
||||
"id": "ii_NORMALIZED00000000000002",
|
||||
"invoice": null,
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
@@ -21,13 +21,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0004",
|
||||
"product": "prod_NORMALIZED0002",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -40,6 +41,7 @@
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_rates": [],
|
||||
"test_clock": null,
|
||||
"unit_amount": -7200,
|
||||
"unit_amount_decimal": "-7200"
|
||||
}
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
"description": "Zulip Cloud Standard",
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "ii_NORMALIZED00000000000003",
|
||||
"id": "ii_NORMALIZED00000000000001",
|
||||
"invoice": null,
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "invoiceitem",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
"end": 1357095845,
|
||||
"start": 1325473445
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
@@ -21,13 +21,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000003",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0003",
|
||||
"product": "prod_NORMALIZED0001",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -40,6 +41,7 @@
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_rates": [],
|
||||
"test_clock": null,
|
||||
"unit_amount": 1200,
|
||||
"unit_amount_decimal": "1200"
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"description": "Payment (Card ending in 4242)",
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "ii_NORMALIZED00000000000006",
|
||||
"id": "ii_NORMALIZED00000000000004",
|
||||
"invoice": null,
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
@@ -21,13 +21,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000006",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0006",
|
||||
"product": "prod_NORMALIZED0002",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -40,6 +41,7 @@
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_rates": [],
|
||||
"test_clock": null,
|
||||
"unit_amount": -36000,
|
||||
"unit_amount_decimal": "-36000"
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"description": "Zulip Cloud Standard",
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "ii_NORMALIZED00000000000005",
|
||||
"id": "ii_NORMALIZED00000000000003",
|
||||
"invoice": null,
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
@@ -21,13 +21,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000005",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000003",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0005",
|
||||
"product": "prod_NORMALIZED0001",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -40,6 +41,7 @@
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_rates": [],
|
||||
"test_clock": null,
|
||||
"unit_amount": 6000,
|
||||
"unit_amount_decimal": "6000"
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"description": "Zulip Cloud Standard - renewal",
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "ii_NORMALIZED00000000000007",
|
||||
"id": "ii_NORMALIZED00000000000005",
|
||||
"invoice": null,
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
@@ -21,13 +21,14 @@
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"id": "price_NORMALIZED00000000000007",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000005",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0007",
|
||||
"product": "prod_NORMALIZED0003",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -40,6 +41,7 @@
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_rates": [],
|
||||
"test_clock": null,
|
||||
"unit_amount": 4000,
|
||||
"unit_amount_decimal": "4000"
|
||||
}
|
||||
|
||||
@@ -1,171 +0,0 @@
|
||||
{
|
||||
"amount": 7200,
|
||||
"amount_capturable": 0,
|
||||
"amount_received": 7200,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"automatic_payment_methods": null,
|
||||
"canceled_at": null,
|
||||
"cancellation_reason": null,
|
||||
"capture_method": "automatic",
|
||||
"charges": {
|
||||
"data": [
|
||||
{
|
||||
"amount": 7200,
|
||||
"amount_captured": 7200,
|
||||
"amount_refunded": 0,
|
||||
"application": null,
|
||||
"application_fee": null,
|
||||
"application_fee_amount": null,
|
||||
"balance_transaction": "txn_NORMALIZED00000000000001",
|
||||
"billing_details": {
|
||||
"address": {
|
||||
"city": null,
|
||||
"country": null,
|
||||
"line1": null,
|
||||
"line2": null,
|
||||
"postal_code": null,
|
||||
"state": null
|
||||
},
|
||||
"email": null,
|
||||
"name": null,
|
||||
"phone": null
|
||||
},
|
||||
"calculated_statement_descriptor": "ZULIP STANDARD",
|
||||
"captured": true,
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": "Upgrade to Zulip Cloud Standard, $12.0 x 6",
|
||||
"destination": null,
|
||||
"dispute": null,
|
||||
"disputed": false,
|
||||
"failure_code": null,
|
||||
"failure_message": null,
|
||||
"fraud_details": {},
|
||||
"id": "ch_NORMALIZED00000000000001",
|
||||
"invoice": null,
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
"billing_modality": "charge_automatically",
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"price_per_license": "1200",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
"seat_count": "6",
|
||||
"type": "upgrade",
|
||||
"user_email": "hamlet@zulip.com",
|
||||
"user_id": "10"
|
||||
},
|
||||
"object": "charge",
|
||||
"on_behalf_of": null,
|
||||
"order": null,
|
||||
"outcome": {
|
||||
"network_status": "approved_by_network",
|
||||
"reason": null,
|
||||
"risk_level": "normal",
|
||||
"risk_score": 0,
|
||||
"seller_message": "Payment complete.",
|
||||
"type": "authorized"
|
||||
},
|
||||
"paid": true,
|
||||
"payment_intent": "pi_NORMALIZED00000000000001",
|
||||
"payment_method": "pm_1K2OXoHSaWXyvFpKhrceNhbI",
|
||||
"payment_method_details": {
|
||||
"card": {
|
||||
"brand": "visa",
|
||||
"checks": {
|
||||
"address_line1_check": null,
|
||||
"address_postal_code_check": null,
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 3,
|
||||
"exp_year": 2033,
|
||||
"fingerprint": "NORMALIZED000001",
|
||||
"funding": "credit",
|
||||
"installments": null,
|
||||
"last4": "4242",
|
||||
"network": "visa",
|
||||
"three_d_secure": null,
|
||||
"wallet": null
|
||||
},
|
||||
"type": "card"
|
||||
},
|
||||
"receipt_email": "hamlet@zulip.com",
|
||||
"receipt_number": null,
|
||||
"receipt_url": "https://pay.stripe.com/receipts/acct_NORMALIZED000001/ch_NORMALIZED00000000000001/rcpt_NORMALIZED000000000000000000001",
|
||||
"refunded": false,
|
||||
"refunds": {
|
||||
"data": [],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 0,
|
||||
"url": "/v1/charges/ch_NORMALIZED00000000000001/refunds"
|
||||
},
|
||||
"review": null,
|
||||
"shipping": null,
|
||||
"source": null,
|
||||
"source_transfer": null,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"statement_descriptor_suffix": null,
|
||||
"status": "succeeded",
|
||||
"transfer_data": null,
|
||||
"transfer_group": null
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 1,
|
||||
"url": "/v1/charges?payment_intent=pi_NORMALIZED00000000000001"
|
||||
},
|
||||
"client_secret": "pi_NORMALIZED00000000000001_secret_fD7F9AdDLLYQt94Ii4rEflkYg",
|
||||
"confirmation_method": "automatic",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": "Upgrade to Zulip Cloud Standard, $12.0 x 6",
|
||||
"id": "pi_NORMALIZED00000000000001",
|
||||
"invoice": null,
|
||||
"last_payment_error": null,
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
"billing_modality": "charge_automatically",
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"price_per_license": "1200",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
"seat_count": "6",
|
||||
"type": "upgrade",
|
||||
"user_email": "hamlet@zulip.com",
|
||||
"user_id": "10"
|
||||
},
|
||||
"next_action": null,
|
||||
"object": "payment_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": "pm_1K2OXoHSaWXyvFpKhrceNhbI",
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"installments": null,
|
||||
"network": null,
|
||||
"request_three_d_secure": "automatic"
|
||||
}
|
||||
},
|
||||
"payment_method_types": [
|
||||
"card"
|
||||
],
|
||||
"receipt_email": "hamlet@zulip.com",
|
||||
"review": null,
|
||||
"setup_future_usage": null,
|
||||
"shipping": null,
|
||||
"source": null,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"statement_descriptor_suffix": null,
|
||||
"status": "succeeded",
|
||||
"transfer_data": null,
|
||||
"transfer_group": null
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
{
|
||||
"amount": 36000,
|
||||
"amount_capturable": 0,
|
||||
"amount_received": 36000,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"automatic_payment_methods": null,
|
||||
"canceled_at": null,
|
||||
"cancellation_reason": null,
|
||||
"capture_method": "automatic",
|
||||
"charges": {
|
||||
"data": [
|
||||
{
|
||||
"amount": 36000,
|
||||
"amount_captured": 36000,
|
||||
"amount_refunded": 0,
|
||||
"application": null,
|
||||
"application_fee": null,
|
||||
"application_fee_amount": null,
|
||||
"balance_transaction": "txn_NORMALIZED00000000000002",
|
||||
"billing_details": {
|
||||
"address": {
|
||||
"city": null,
|
||||
"country": null,
|
||||
"line1": null,
|
||||
"line2": null,
|
||||
"postal_code": null,
|
||||
"state": null
|
||||
},
|
||||
"email": null,
|
||||
"name": null,
|
||||
"phone": null
|
||||
},
|
||||
"calculated_statement_descriptor": "ZULIP STANDARD",
|
||||
"captured": true,
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": "Upgrade to Zulip Cloud Standard, $60.0 x 6",
|
||||
"destination": null,
|
||||
"dispute": null,
|
||||
"disputed": false,
|
||||
"failure_code": null,
|
||||
"failure_message": null,
|
||||
"fraud_details": {},
|
||||
"id": "ch_NORMALIZED00000000000002",
|
||||
"invoice": null,
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
"billing_modality": "charge_automatically",
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"price_per_license": "6000",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
"seat_count": "6",
|
||||
"type": "upgrade",
|
||||
"user_email": "hamlet@zulip.com",
|
||||
"user_id": "10"
|
||||
},
|
||||
"object": "charge",
|
||||
"on_behalf_of": null,
|
||||
"order": null,
|
||||
"outcome": {
|
||||
"network_status": "approved_by_network",
|
||||
"reason": null,
|
||||
"risk_level": "normal",
|
||||
"risk_score": 0,
|
||||
"seller_message": "Payment complete.",
|
||||
"type": "authorized"
|
||||
},
|
||||
"paid": true,
|
||||
"payment_intent": "pi_NORMALIZED00000000000002",
|
||||
"payment_method": "pm_1K2OXyHSaWXyvFpKNE66Ex7T",
|
||||
"payment_method_details": {
|
||||
"card": {
|
||||
"brand": "visa",
|
||||
"checks": {
|
||||
"address_line1_check": null,
|
||||
"address_postal_code_check": null,
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 3,
|
||||
"exp_year": 2033,
|
||||
"fingerprint": "NORMALIZED000001",
|
||||
"funding": "credit",
|
||||
"installments": null,
|
||||
"last4": "4242",
|
||||
"network": "visa",
|
||||
"three_d_secure": null,
|
||||
"wallet": null
|
||||
},
|
||||
"type": "card"
|
||||
},
|
||||
"receipt_email": "hamlet@zulip.com",
|
||||
"receipt_number": null,
|
||||
"receipt_url": "https://pay.stripe.com/receipts/acct_NORMALIZED000001/ch_NORMALIZED00000000000002/rcpt_NORMALIZED000000000000000000002",
|
||||
"refunded": false,
|
||||
"refunds": {
|
||||
"data": [],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 0,
|
||||
"url": "/v1/charges/ch_NORMALIZED00000000000002/refunds"
|
||||
},
|
||||
"review": null,
|
||||
"shipping": null,
|
||||
"source": null,
|
||||
"source_transfer": null,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"statement_descriptor_suffix": null,
|
||||
"status": "succeeded",
|
||||
"transfer_data": null,
|
||||
"transfer_group": null
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 1,
|
||||
"url": "/v1/charges?payment_intent=pi_NORMALIZED00000000000002"
|
||||
},
|
||||
"client_secret": "pi_NORMALIZED00000000000002_secret_KPTN4Jk0sR9DrnVymxUmd0o0F",
|
||||
"confirmation_method": "automatic",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": "Upgrade to Zulip Cloud Standard, $60.0 x 6",
|
||||
"id": "pi_NORMALIZED00000000000002",
|
||||
"invoice": null,
|
||||
"last_payment_error": null,
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
"billing_modality": "charge_automatically",
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"price_per_license": "6000",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
"seat_count": "6",
|
||||
"type": "upgrade",
|
||||
"user_email": "hamlet@zulip.com",
|
||||
"user_id": "10"
|
||||
},
|
||||
"next_action": null,
|
||||
"object": "payment_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": "pm_1K2OXyHSaWXyvFpKNE66Ex7T",
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"installments": null,
|
||||
"network": null,
|
||||
"request_three_d_secure": "automatic"
|
||||
}
|
||||
},
|
||||
"payment_method_types": [
|
||||
"card"
|
||||
],
|
||||
"receipt_email": "hamlet@zulip.com",
|
||||
"review": null,
|
||||
"setup_future_usage": null,
|
||||
"shipping": null,
|
||||
"source": null,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"statement_descriptor_suffix": null,
|
||||
"status": "succeeded",
|
||||
"transfer_data": null,
|
||||
"transfer_group": null
|
||||
}
|
||||
@@ -1,7 +1,10 @@
|
||||
{
|
||||
"amount": 7200,
|
||||
"amount_capturable": 0,
|
||||
"amount_received": 0,
|
||||
"amount_details": {
|
||||
"tip": {}
|
||||
},
|
||||
"amount_received": 7200,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"automatic_payment_methods": null,
|
||||
@@ -9,13 +12,140 @@
|
||||
"cancellation_reason": null,
|
||||
"capture_method": "automatic",
|
||||
"charges": {
|
||||
"data": [],
|
||||
"data": [
|
||||
{
|
||||
"amount": 7200,
|
||||
"amount_captured": 7200,
|
||||
"amount_refunded": 0,
|
||||
"application": null,
|
||||
"application_fee": null,
|
||||
"application_fee_amount": null,
|
||||
"balance_transaction": "txn_NORMALIZED00000000000001",
|
||||
"billing_details": {
|
||||
"address": {
|
||||
"city": null,
|
||||
"country": null,
|
||||
"line1": null,
|
||||
"line2": null,
|
||||
"postal_code": null,
|
||||
"state": null
|
||||
},
|
||||
"email": null,
|
||||
"name": null,
|
||||
"phone": null
|
||||
},
|
||||
"calculated_statement_descriptor": "ZULIP CLOUD STANDARD",
|
||||
"captured": true,
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": "Upgrade to Zulip Cloud Standard, $12.0 x 6",
|
||||
"destination": null,
|
||||
"dispute": null,
|
||||
"disputed": false,
|
||||
"failure_balance_transaction": null,
|
||||
"failure_code": null,
|
||||
"failure_message": null,
|
||||
"fraud_details": {},
|
||||
"id": "ch_NORMALIZED00000000000001",
|
||||
"invoice": null,
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
"billing_modality": "charge_automatically",
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"plan_tier": "1",
|
||||
"price_per_license": "1200",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
"seat_count": "6",
|
||||
"type": "upgrade",
|
||||
"user_email": "hamlet@zulip.com",
|
||||
"user_id": "10"
|
||||
},
|
||||
"object": "charge",
|
||||
"on_behalf_of": null,
|
||||
"order": null,
|
||||
"outcome": {
|
||||
"network_status": "approved_by_network",
|
||||
"reason": null,
|
||||
"risk_level": "normal",
|
||||
"risk_score": 0,
|
||||
"seller_message": "Payment complete.",
|
||||
"type": "authorized"
|
||||
},
|
||||
"paid": true,
|
||||
"payment_intent": "pi_NORMALIZED00000000000001",
|
||||
"payment_method": "pm_1OIlcUDEQaroqDjsqDT70KqK",
|
||||
"payment_method_details": {
|
||||
"card": {
|
||||
"amount_authorized": 7200,
|
||||
"brand": "visa",
|
||||
"checks": {
|
||||
"address_line1_check": null,
|
||||
"address_postal_code_check": null,
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 12,
|
||||
"exp_year": 2024,
|
||||
"extended_authorization": {
|
||||
"status": "disabled"
|
||||
},
|
||||
"fingerprint": "NORMALIZED000001",
|
||||
"funding": "credit",
|
||||
"incremental_authorization": {
|
||||
"status": "unavailable"
|
||||
},
|
||||
"installments": null,
|
||||
"last4": "4242",
|
||||
"mandate": null,
|
||||
"multicapture": {
|
||||
"status": "unavailable"
|
||||
},
|
||||
"network": "visa",
|
||||
"network_token": {
|
||||
"used": false
|
||||
},
|
||||
"overcapture": {
|
||||
"maximum_amount_capturable": 7200,
|
||||
"status": "unavailable"
|
||||
},
|
||||
"three_d_secure": null,
|
||||
"wallet": null
|
||||
},
|
||||
"type": "card"
|
||||
},
|
||||
"radar_options": {},
|
||||
"receipt_email": "hamlet@zulip.com",
|
||||
"receipt_number": null,
|
||||
"receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKIf9qqsGMgYln1CvRQg6LBas64aXppcCqDXm8lE0Sbd6BM7omStVTXKhathHXWOU3wC8kyUuXRRePlvZ",
|
||||
"refunded": false,
|
||||
"refunds": {
|
||||
"data": [],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 0,
|
||||
"url": "/v1/charges/ch_NORMALIZED00000000000001/refunds"
|
||||
},
|
||||
"review": null,
|
||||
"shipping": null,
|
||||
"source": null,
|
||||
"source_transfer": null,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"statement_descriptor_suffix": null,
|
||||
"status": "succeeded",
|
||||
"transfer_data": null,
|
||||
"transfer_group": null
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 0,
|
||||
"total_count": 1,
|
||||
"url": "/v1/charges?payment_intent=pi_NORMALIZED00000000000001"
|
||||
},
|
||||
"client_secret": "pi_NORMALIZED00000000000001_secret_fD7F9AdDLLYQt94Ii4rEflkYg",
|
||||
"client_secret": "pi_NORMALIZED00000000000001_secret_TT71wq3meHmzTEd7mpZbqrDnP",
|
||||
"confirmation_method": "automatic",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
@@ -24,12 +154,14 @@
|
||||
"id": "pi_NORMALIZED00000000000001",
|
||||
"invoice": null,
|
||||
"last_payment_error": null,
|
||||
"latest_charge": "ch_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
"billing_modality": "charge_automatically",
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"plan_tier": "1",
|
||||
"price_per_license": "1200",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
@@ -41,10 +173,12 @@
|
||||
"next_action": null,
|
||||
"object": "payment_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": null,
|
||||
"payment_method": "pm_1OIlcUDEQaroqDjsqDT70KqK",
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"installments": null,
|
||||
"mandate_options": null,
|
||||
"network": null,
|
||||
"request_three_d_secure": "automatic"
|
||||
}
|
||||
@@ -52,6 +186,7 @@
|
||||
"payment_method_types": [
|
||||
"card"
|
||||
],
|
||||
"processing": null,
|
||||
"receipt_email": "hamlet@zulip.com",
|
||||
"review": null,
|
||||
"setup_future_usage": null,
|
||||
@@ -59,7 +194,7 @@
|
||||
"source": null,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"statement_descriptor_suffix": null,
|
||||
"status": "requires_payment_method",
|
||||
"status": "succeeded",
|
||||
"transfer_data": null,
|
||||
"transfer_group": null
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
{
|
||||
"amount": 36000,
|
||||
"amount_capturable": 0,
|
||||
"amount_received": 0,
|
||||
"amount_details": {
|
||||
"tip": {}
|
||||
},
|
||||
"amount_received": 36000,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"automatic_payment_methods": null,
|
||||
@@ -9,13 +12,140 @@
|
||||
"cancellation_reason": null,
|
||||
"capture_method": "automatic",
|
||||
"charges": {
|
||||
"data": [],
|
||||
"data": [
|
||||
{
|
||||
"amount": 36000,
|
||||
"amount_captured": 36000,
|
||||
"amount_refunded": 0,
|
||||
"application": null,
|
||||
"application_fee": null,
|
||||
"application_fee_amount": null,
|
||||
"balance_transaction": "txn_NORMALIZED00000000000002",
|
||||
"billing_details": {
|
||||
"address": {
|
||||
"city": null,
|
||||
"country": null,
|
||||
"line1": null,
|
||||
"line2": null,
|
||||
"postal_code": null,
|
||||
"state": null
|
||||
},
|
||||
"email": null,
|
||||
"name": null,
|
||||
"phone": null
|
||||
},
|
||||
"calculated_statement_descriptor": "ZULIP CLOUD STANDARD",
|
||||
"captured": true,
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": "Upgrade to Zulip Cloud Standard, $60.0 x 6",
|
||||
"destination": null,
|
||||
"dispute": null,
|
||||
"disputed": false,
|
||||
"failure_balance_transaction": null,
|
||||
"failure_code": null,
|
||||
"failure_message": null,
|
||||
"fraud_details": {},
|
||||
"id": "ch_NORMALIZED00000000000002",
|
||||
"invoice": null,
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
"billing_modality": "charge_automatically",
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"plan_tier": "1",
|
||||
"price_per_license": "6000",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
"seat_count": "6",
|
||||
"type": "upgrade",
|
||||
"user_email": "hamlet@zulip.com",
|
||||
"user_id": "10"
|
||||
},
|
||||
"object": "charge",
|
||||
"on_behalf_of": null,
|
||||
"order": null,
|
||||
"outcome": {
|
||||
"network_status": "approved_by_network",
|
||||
"reason": null,
|
||||
"risk_level": "normal",
|
||||
"risk_score": 0,
|
||||
"seller_message": "Payment complete.",
|
||||
"type": "authorized"
|
||||
},
|
||||
"paid": true,
|
||||
"payment_intent": "pi_NORMALIZED00000000000002",
|
||||
"payment_method": "pm_1OIlceDEQaroqDjshc2Y2l9b",
|
||||
"payment_method_details": {
|
||||
"card": {
|
||||
"amount_authorized": 36000,
|
||||
"brand": "visa",
|
||||
"checks": {
|
||||
"address_line1_check": null,
|
||||
"address_postal_code_check": null,
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 12,
|
||||
"exp_year": 2024,
|
||||
"extended_authorization": {
|
||||
"status": "disabled"
|
||||
},
|
||||
"fingerprint": "NORMALIZED000001",
|
||||
"funding": "credit",
|
||||
"incremental_authorization": {
|
||||
"status": "unavailable"
|
||||
},
|
||||
"installments": null,
|
||||
"last4": "4242",
|
||||
"mandate": null,
|
||||
"multicapture": {
|
||||
"status": "unavailable"
|
||||
},
|
||||
"network": "visa",
|
||||
"network_token": {
|
||||
"used": false
|
||||
},
|
||||
"overcapture": {
|
||||
"maximum_amount_capturable": 36000,
|
||||
"status": "unavailable"
|
||||
},
|
||||
"three_d_secure": null,
|
||||
"wallet": null
|
||||
},
|
||||
"type": "card"
|
||||
},
|
||||
"radar_options": {},
|
||||
"receipt_email": "hamlet@zulip.com",
|
||||
"receipt_number": null,
|
||||
"receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKJD9qqsGMgahoOxs2tY6LBYE_7mVLMS2-_xQ_C_j9KSayaWsbJ6jjdpSQjsrQImBFFAZjT-6A-PbNsDv",
|
||||
"refunded": false,
|
||||
"refunds": {
|
||||
"data": [],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 0,
|
||||
"url": "/v1/charges/ch_NORMALIZED00000000000002/refunds"
|
||||
},
|
||||
"review": null,
|
||||
"shipping": null,
|
||||
"source": null,
|
||||
"source_transfer": null,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"statement_descriptor_suffix": null,
|
||||
"status": "succeeded",
|
||||
"transfer_data": null,
|
||||
"transfer_group": null
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 0,
|
||||
"total_count": 1,
|
||||
"url": "/v1/charges?payment_intent=pi_NORMALIZED00000000000002"
|
||||
},
|
||||
"client_secret": "pi_NORMALIZED00000000000002_secret_KPTN4Jk0sR9DrnVymxUmd0o0F",
|
||||
"client_secret": "pi_NORMALIZED00000000000002_secret_6P4eLudA3uvQYCOoNiDTkNQEI",
|
||||
"confirmation_method": "automatic",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
@@ -24,12 +154,14 @@
|
||||
"id": "pi_NORMALIZED00000000000002",
|
||||
"invoice": null,
|
||||
"last_payment_error": null,
|
||||
"latest_charge": "ch_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
"billing_modality": "charge_automatically",
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"plan_tier": "1",
|
||||
"price_per_license": "6000",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
@@ -41,10 +173,12 @@
|
||||
"next_action": null,
|
||||
"object": "payment_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": null,
|
||||
"payment_method": "pm_1OIlceDEQaroqDjshc2Y2l9b",
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"installments": null,
|
||||
"mandate_options": null,
|
||||
"network": null,
|
||||
"request_three_d_secure": "automatic"
|
||||
}
|
||||
@@ -52,6 +186,7 @@
|
||||
"payment_method_types": [
|
||||
"card"
|
||||
],
|
||||
"processing": null,
|
||||
"receipt_email": "hamlet@zulip.com",
|
||||
"review": null,
|
||||
"setup_future_usage": null,
|
||||
@@ -59,7 +194,7 @@
|
||||
"source": null,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"statement_descriptor_suffix": null,
|
||||
"status": "requires_payment_method",
|
||||
"status": "succeeded",
|
||||
"transfer_data": null,
|
||||
"transfer_group": null
|
||||
}
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
{
|
||||
"billing_details": {
|
||||
"address": {
|
||||
"city": null,
|
||||
"country": null,
|
||||
"line1": null,
|
||||
"line2": null,
|
||||
"postal_code": null,
|
||||
"state": null
|
||||
},
|
||||
"email": null,
|
||||
"name": null,
|
||||
"phone": null
|
||||
},
|
||||
"card": {
|
||||
"brand": "visa",
|
||||
"checks": {
|
||||
"address_line1_check": null,
|
||||
"address_postal_code_check": null,
|
||||
"cvc_check": "unchecked"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 3,
|
||||
"exp_year": 2033,
|
||||
"fingerprint": "NORMALIZED000001",
|
||||
"funding": "credit",
|
||||
"generated_from": null,
|
||||
"last4": "4242",
|
||||
"networks": {
|
||||
"available": [
|
||||
"visa"
|
||||
],
|
||||
"preferred": null
|
||||
},
|
||||
"three_d_secure_usage": {
|
||||
"supported": true
|
||||
},
|
||||
"wallet": null
|
||||
},
|
||||
"created": 1000000000,
|
||||
"customer": null,
|
||||
"id": "pm_1K2OXoHSaWXyvFpKhrceNhbI",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "payment_method",
|
||||
"type": "card"
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
{
|
||||
"billing_details": {
|
||||
"address": {
|
||||
"city": null,
|
||||
"country": null,
|
||||
"line1": null,
|
||||
"line2": null,
|
||||
"postal_code": null,
|
||||
"state": null
|
||||
},
|
||||
"email": null,
|
||||
"name": null,
|
||||
"phone": null
|
||||
},
|
||||
"card": {
|
||||
"brand": "visa",
|
||||
"checks": {
|
||||
"address_line1_check": null,
|
||||
"address_postal_code_check": null,
|
||||
"cvc_check": "unchecked"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 3,
|
||||
"exp_year": 2033,
|
||||
"fingerprint": "NORMALIZED000001",
|
||||
"funding": "credit",
|
||||
"generated_from": null,
|
||||
"last4": "4242",
|
||||
"networks": {
|
||||
"available": [
|
||||
"visa"
|
||||
],
|
||||
"preferred": null
|
||||
},
|
||||
"three_d_secure_usage": {
|
||||
"supported": true
|
||||
},
|
||||
"wallet": null
|
||||
},
|
||||
"created": 1000000000,
|
||||
"customer": null,
|
||||
"id": "pm_1K2OXyHSaWXyvFpKNE66Ex7T",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "payment_method",
|
||||
"type": "card"
|
||||
}
|
||||
@@ -1,34 +1,27 @@
|
||||
{
|
||||
"application": null,
|
||||
"automatic_payment_methods": null,
|
||||
"cancellation_reason": null,
|
||||
"client_secret": "seti_1K2OXpHSaWXyvFpKOq6F3F9K_secret_KhoAzpsEjV8G4oAeYDSFmGYMKv5BRkc",
|
||||
"client_secret": "seti_1OIlcUDEQaroqDjsvk7SRRcH_secret_P6zbAgeO1YNtM2cmjYChSjYCWBsUOAB",
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": null,
|
||||
"id": "seti_1K2OXpHSaWXyvFpKOq6F3F9K",
|
||||
"flow_directions": null,
|
||||
"id": "seti_1OIlcUDEQaroqDjsvk7SRRcH",
|
||||
"last_setup_error": null,
|
||||
"latest_attempt": "setatt_1K2OXpHSaWXyvFpKcauo7Bx8",
|
||||
"latest_attempt": "setatt_1OIlcUDEQaroqDjsLAiOPmHx",
|
||||
"livemode": false,
|
||||
"mandate": null,
|
||||
"metadata": {
|
||||
"billing_modality": "charge_automatically",
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"price_per_license": "1200",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
"seat_count": "6",
|
||||
"type": "upgrade",
|
||||
"user_email": "hamlet@zulip.com",
|
||||
"user_id": "10"
|
||||
},
|
||||
"metadata": {},
|
||||
"next_action": null,
|
||||
"object": "setup_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": "pm_1K2OXoHSaWXyvFpKhrceNhbI",
|
||||
"payment_method": "pm_1OIlcUDEQaroqDjsqDT70KqK",
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"mandate_options": null,
|
||||
"network": null,
|
||||
"request_three_d_secure": "automatic"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,34 +1,27 @@
|
||||
{
|
||||
"application": null,
|
||||
"automatic_payment_methods": null,
|
||||
"cancellation_reason": null,
|
||||
"client_secret": "seti_1K2OXzHSaWXyvFpKzkPjM4k7_secret_KhoALa8Xt6eK1ATCOPGurJLxmo2y6xh",
|
||||
"client_secret": "seti_1OIlceDEQaroqDjsF69R2WG0_secret_P6zbftiDh6C2B0Le8GK6ALVcHby9Gyu",
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": null,
|
||||
"id": "seti_1K2OXzHSaWXyvFpKzkPjM4k7",
|
||||
"flow_directions": null,
|
||||
"id": "seti_1OIlceDEQaroqDjsF69R2WG0",
|
||||
"last_setup_error": null,
|
||||
"latest_attempt": "setatt_1K2OXzHSaWXyvFpKG0BonJhW",
|
||||
"latest_attempt": "setatt_1OIlceDEQaroqDjs1hVqql0s",
|
||||
"livemode": false,
|
||||
"mandate": null,
|
||||
"metadata": {
|
||||
"billing_modality": "charge_automatically",
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"price_per_license": "6000",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
"seat_count": "6",
|
||||
"type": "upgrade",
|
||||
"user_email": "hamlet@zulip.com",
|
||||
"user_id": "10"
|
||||
},
|
||||
"metadata": {},
|
||||
"next_action": null,
|
||||
"object": "setup_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": "pm_1K2OXyHSaWXyvFpKNE66Ex7T",
|
||||
"payment_method": "pm_1OIlceDEQaroqDjshc2Y2l9b",
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"mandate_options": null,
|
||||
"network": null,
|
||||
"request_three_d_secure": "automatic"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -2,35 +2,28 @@
|
||||
"data": [
|
||||
{
|
||||
"application": null,
|
||||
"automatic_payment_methods": null,
|
||||
"cancellation_reason": null,
|
||||
"client_secret": "seti_1K2OXoHSaWXyvFpKLyy5ns16_secret_KhoANgFdO2YICL1Urfnax58nGUY0MeV",
|
||||
"client_secret": "seti_1OIlcTDEQaroqDjs7K1pjsyq_secret_P6zb4X2b8va5VZDxRMR3CgIYMwreYzC",
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": null,
|
||||
"id": "seti_1K2OXoHSaWXyvFpKLyy5ns16",
|
||||
"flow_directions": null,
|
||||
"id": "seti_1OIlcTDEQaroqDjs7K1pjsyq",
|
||||
"last_setup_error": null,
|
||||
"latest_attempt": null,
|
||||
"livemode": false,
|
||||
"mandate": null,
|
||||
"metadata": {
|
||||
"billing_modality": "charge_automatically",
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"price_per_license": "1200",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
"seat_count": "6",
|
||||
"type": "upgrade",
|
||||
"user_email": "hamlet@zulip.com",
|
||||
"user_id": "10"
|
||||
},
|
||||
"metadata": {},
|
||||
"next_action": null,
|
||||
"object": "setup_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": null,
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"mandate_options": null,
|
||||
"network": null,
|
||||
"request_three_d_secure": "automatic"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -2,35 +2,28 @@
|
||||
"data": [
|
||||
{
|
||||
"application": null,
|
||||
"automatic_payment_methods": null,
|
||||
"cancellation_reason": null,
|
||||
"client_secret": "seti_1K2OXyHSaWXyvFpKvIhWI0JW_secret_KhoAlunPkSHQPGu7zyaTpT81wBUPhqc",
|
||||
"client_secret": "seti_1OIlcdDEQaroqDjsB4ugOdVp_secret_P6zbipSmx7qqSUGMRGqVxyYPXoN42bP",
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": null,
|
||||
"id": "seti_1K2OXyHSaWXyvFpKvIhWI0JW",
|
||||
"flow_directions": null,
|
||||
"id": "seti_1OIlcdDEQaroqDjsB4ugOdVp",
|
||||
"last_setup_error": null,
|
||||
"latest_attempt": null,
|
||||
"livemode": false,
|
||||
"mandate": null,
|
||||
"metadata": {
|
||||
"billing_modality": "charge_automatically",
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"price_per_license": "6000",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
"seat_count": "6",
|
||||
"type": "upgrade",
|
||||
"user_email": "hamlet@zulip.com",
|
||||
"user_id": "10"
|
||||
},
|
||||
"metadata": {},
|
||||
"next_action": null,
|
||||
"object": "setup_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": null,
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"mandate_options": null,
|
||||
"network": null,
|
||||
"request_three_d_secure": "automatic"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,34 +1,27 @@
|
||||
{
|
||||
"application": null,
|
||||
"automatic_payment_methods": null,
|
||||
"cancellation_reason": null,
|
||||
"client_secret": "seti_1K2OXpHSaWXyvFpKOq6F3F9K_secret_KhoAzpsEjV8G4oAeYDSFmGYMKv5BRkc",
|
||||
"client_secret": "seti_1OIlcUDEQaroqDjsvk7SRRcH_secret_P6zbAgeO1YNtM2cmjYChSjYCWBsUOAB",
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": null,
|
||||
"id": "seti_1K2OXpHSaWXyvFpKOq6F3F9K",
|
||||
"flow_directions": null,
|
||||
"id": "seti_1OIlcUDEQaroqDjsvk7SRRcH",
|
||||
"last_setup_error": null,
|
||||
"latest_attempt": "setatt_1K2OXpHSaWXyvFpKcauo7Bx8",
|
||||
"latest_attempt": "setatt_1OIlcUDEQaroqDjsLAiOPmHx",
|
||||
"livemode": false,
|
||||
"mandate": null,
|
||||
"metadata": {
|
||||
"billing_modality": "charge_automatically",
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"price_per_license": "1200",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
"seat_count": "6",
|
||||
"type": "upgrade",
|
||||
"user_email": "hamlet@zulip.com",
|
||||
"user_id": "10"
|
||||
},
|
||||
"metadata": {},
|
||||
"next_action": null,
|
||||
"object": "setup_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": "pm_1K2OXoHSaWXyvFpKhrceNhbI",
|
||||
"payment_method": "pm_1OIlcUDEQaroqDjsqDT70KqK",
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"mandate_options": null,
|
||||
"network": null,
|
||||
"request_three_d_secure": "automatic"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,34 +1,27 @@
|
||||
{
|
||||
"application": null,
|
||||
"automatic_payment_methods": null,
|
||||
"cancellation_reason": null,
|
||||
"client_secret": "seti_1K2OXzHSaWXyvFpKzkPjM4k7_secret_KhoALa8Xt6eK1ATCOPGurJLxmo2y6xh",
|
||||
"client_secret": "seti_1OIlceDEQaroqDjsF69R2WG0_secret_P6zbftiDh6C2B0Le8GK6ALVcHby9Gyu",
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": null,
|
||||
"id": "seti_1K2OXzHSaWXyvFpKzkPjM4k7",
|
||||
"flow_directions": null,
|
||||
"id": "seti_1OIlceDEQaroqDjsF69R2WG0",
|
||||
"last_setup_error": null,
|
||||
"latest_attempt": "setatt_1K2OXzHSaWXyvFpKG0BonJhW",
|
||||
"latest_attempt": "setatt_1OIlceDEQaroqDjs1hVqql0s",
|
||||
"livemode": false,
|
||||
"mandate": null,
|
||||
"metadata": {
|
||||
"billing_modality": "charge_automatically",
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"price_per_license": "6000",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
"seat_count": "6",
|
||||
"type": "upgrade",
|
||||
"user_email": "hamlet@zulip.com",
|
||||
"user_id": "10"
|
||||
},
|
||||
"metadata": {},
|
||||
"next_action": null,
|
||||
"object": "setup_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": "pm_1K2OXyHSaWXyvFpKNE66Ex7T",
|
||||
"payment_method": "pm_1OIlceDEQaroqDjshc2Y2l9b",
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"mandate_options": null,
|
||||
"network": null,
|
||||
"request_three_d_secure": "automatic"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -10,32 +10,45 @@
|
||||
"billing_address_collection": null,
|
||||
"cancel_url": "http://zulip.testserver/upgrade/",
|
||||
"client_reference_id": null,
|
||||
"client_secret": null,
|
||||
"consent": null,
|
||||
"consent_collection": null,
|
||||
"created": 1000000000,
|
||||
"currency": null,
|
||||
"currency_conversion": null,
|
||||
"custom_fields": [],
|
||||
"custom_text": {
|
||||
"shipping_address": null,
|
||||
"submit": null,
|
||||
"terms_of_service_acceptance": null
|
||||
},
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"customer_details": null,
|
||||
"customer_creation": null,
|
||||
"customer_details": {
|
||||
"address": null,
|
||||
"email": "hamlet@zulip.com",
|
||||
"name": null,
|
||||
"phone": null,
|
||||
"tax_exempt": null,
|
||||
"tax_ids": null
|
||||
},
|
||||
"customer_email": null,
|
||||
"expires_at": 1000000000,
|
||||
"id": "cs_test_NORMALIZED02JXoyt8JsWg6jjuoI58GyCaB4aDXDWB7D0FqdiqlF6JDHjM",
|
||||
"id": "cs_test_NORMALIZED02sb4yHaq28VHOZscOtqKWTLoGQJALldTi43GUE0P56ay9sU",
|
||||
"invoice": null,
|
||||
"invoice_creation": null,
|
||||
"livemode": false,
|
||||
"locale": null,
|
||||
"metadata": {
|
||||
"billing_modality": "charge_automatically",
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"price_per_license": "1200",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
"seat_count": "6",
|
||||
"type": "upgrade",
|
||||
"user_email": "hamlet@zulip.com",
|
||||
"type": "card_update",
|
||||
"user_id": "10"
|
||||
},
|
||||
"mode": "setup",
|
||||
"object": "checkout.session",
|
||||
"payment_intent": null,
|
||||
"payment_link": null,
|
||||
"payment_method_collection": "always",
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {},
|
||||
"payment_method_types": [
|
||||
"card"
|
||||
@@ -45,7 +58,7 @@
|
||||
"enabled": false
|
||||
},
|
||||
"recovered_from": null,
|
||||
"setup_intent": "seti_1K2OXoHSaWXyvFpKLyy5ns16",
|
||||
"setup_intent": "seti_1OIlcTDEQaroqDjs7K1pjsyq",
|
||||
"shipping": null,
|
||||
"shipping_address_collection": null,
|
||||
"shipping_options": [],
|
||||
@@ -55,5 +68,6 @@
|
||||
"subscription": null,
|
||||
"success_url": "http://zulip.testserver/billing/event_status?stripe_session_id={CHECKOUT_SESSION_ID}",
|
||||
"total_details": null,
|
||||
"url": "https://checkout.stripe.com/pay/cs_test_NORMALIZED02JXoyt8JsWg6jjuoI58GyCaB4aDXDWB7D0FqdiqlF6JDHjM#fidkdWxOYHwnPyd1blpxYHZxWnZkQk5DYTNqTGNxQl9JQjJIf2B1Y05BdScpJ2N3amhWYHdzYHcnP3F3cGApJ2lkfGpwcVF8dWAnPyd2bGtiaWBaZmppcGhrJyknYGtkZ2lgVWlkZmBtamlhYHd2Jz9xd3BgeCUl"
|
||||
"ui_mode": "hosted",
|
||||
"url": "https://checkout.stripe.com/c/pay/cs_test_NORMALIZED02sb4yHaq28VHOZscOtqKWTLoGQJALldTi43GUE0P56ay9sU#fidkdWxOYHwnPyd1blpxYHZxWl1UZjFOczZJXUE2PUpzUWNPV2ZpdlFzUCcpJ2N3amhWYHdzYHcnP3F3cGApJ2lkfGpwcVF8dWAnPyd2bGtiaWBaZmppcGhrJyknYGtkZ2lgVWlkZmBtamlhYHd2Jz9xd3BgeCUl"
|
||||
}
|
||||
|
||||
@@ -10,32 +10,45 @@
|
||||
"billing_address_collection": null,
|
||||
"cancel_url": "http://zulip.testserver/upgrade/",
|
||||
"client_reference_id": null,
|
||||
"client_secret": null,
|
||||
"consent": null,
|
||||
"consent_collection": null,
|
||||
"created": 1000000000,
|
||||
"currency": null,
|
||||
"currency_conversion": null,
|
||||
"custom_fields": [],
|
||||
"custom_text": {
|
||||
"shipping_address": null,
|
||||
"submit": null,
|
||||
"terms_of_service_acceptance": null
|
||||
},
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"customer_details": null,
|
||||
"customer_creation": null,
|
||||
"customer_details": {
|
||||
"address": null,
|
||||
"email": "hamlet@zulip.com",
|
||||
"name": null,
|
||||
"phone": null,
|
||||
"tax_exempt": null,
|
||||
"tax_ids": null
|
||||
},
|
||||
"customer_email": null,
|
||||
"expires_at": 1000000000,
|
||||
"id": "cs_test_NORMALIZED03qjdrziUfZOYhaTIKoiuAENHHbecsfYggKZ4kWegRShmXDo",
|
||||
"id": "cs_test_NORMALIZED03vZmJUBP0ybiRb1yrtpVKGaX0cm1V0nhnpM6e5pcI1y8CkG",
|
||||
"invoice": null,
|
||||
"invoice_creation": null,
|
||||
"livemode": false,
|
||||
"locale": null,
|
||||
"metadata": {
|
||||
"billing_modality": "charge_automatically",
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"price_per_license": "6000",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
"seat_count": "6",
|
||||
"type": "upgrade",
|
||||
"user_email": "hamlet@zulip.com",
|
||||
"type": "card_update",
|
||||
"user_id": "10"
|
||||
},
|
||||
"mode": "setup",
|
||||
"object": "checkout.session",
|
||||
"payment_intent": null,
|
||||
"payment_link": null,
|
||||
"payment_method_collection": "always",
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {},
|
||||
"payment_method_types": [
|
||||
"card"
|
||||
@@ -45,7 +58,7 @@
|
||||
"enabled": false
|
||||
},
|
||||
"recovered_from": null,
|
||||
"setup_intent": "seti_1K2OXyHSaWXyvFpKvIhWI0JW",
|
||||
"setup_intent": "seti_1OIlcdDEQaroqDjsB4ugOdVp",
|
||||
"shipping": null,
|
||||
"shipping_address_collection": null,
|
||||
"shipping_options": [],
|
||||
@@ -55,5 +68,6 @@
|
||||
"subscription": null,
|
||||
"success_url": "http://zulip.testserver/billing/event_status?stripe_session_id={CHECKOUT_SESSION_ID}",
|
||||
"total_details": null,
|
||||
"url": "https://checkout.stripe.com/pay/cs_test_NORMALIZED03qjdrziUfZOYhaTIKoiuAENHHbecsfYggKZ4kWegRShmXDo#fidkdWxOYHwnPyd1blpxYHZxWnZkQk5DYTNqTGNxQl9JQjJIf2B1Y05BdScpJ2N3amhWYHdzYHcnP3F3cGApJ2lkfGpwcVF8dWAnPyd2bGtiaWBaZmppcGhrJyknYGtkZ2lgVWlkZmBtamlhYHd2Jz9xd3BgeCUl"
|
||||
"ui_mode": "hosted",
|
||||
"url": "https://checkout.stripe.com/c/pay/cs_test_NORMALIZED03vZmJUBP0ybiRb1yrtpVKGaX0cm1V0nhnpM6e5pcI1y8CkG#fidkdWxOYHwnPyd1blpxYHZxWl1UZjFOczZJXUE2PUpzUWNPV2ZpdlFzUCcpJ2N3amhWYHdzYHcnP3F3cGApJ2lkfGpwcVF8dWAnPyd2bGtiaWBaZmppcGhrJyknYGtkZ2lgVWlkZmBtamlhYHd2Jz9xd3BgeCUl"
|
||||
}
|
||||
|
||||
@@ -12,32 +12,45 @@
|
||||
"billing_address_collection": null,
|
||||
"cancel_url": "http://zulip.testserver/upgrade/",
|
||||
"client_reference_id": null,
|
||||
"client_secret": null,
|
||||
"consent": null,
|
||||
"consent_collection": null,
|
||||
"created": 1000000000,
|
||||
"currency": null,
|
||||
"currency_conversion": null,
|
||||
"custom_fields": [],
|
||||
"custom_text": {
|
||||
"shipping_address": null,
|
||||
"submit": null,
|
||||
"terms_of_service_acceptance": null
|
||||
},
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"customer_details": null,
|
||||
"customer_creation": null,
|
||||
"customer_details": {
|
||||
"address": null,
|
||||
"email": "hamlet@zulip.com",
|
||||
"name": null,
|
||||
"phone": null,
|
||||
"tax_exempt": null,
|
||||
"tax_ids": null
|
||||
},
|
||||
"customer_email": null,
|
||||
"expires_at": 1000000000,
|
||||
"id": "cs_test_NORMALIZED02JXoyt8JsWg6jjuoI58GyCaB4aDXDWB7D0FqdiqlF6JDHjM",
|
||||
"id": "cs_test_NORMALIZED02sb4yHaq28VHOZscOtqKWTLoGQJALldTi43GUE0P56ay9sU",
|
||||
"invoice": null,
|
||||
"invoice_creation": null,
|
||||
"livemode": false,
|
||||
"locale": null,
|
||||
"metadata": {
|
||||
"billing_modality": "charge_automatically",
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"price_per_license": "1200",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
"seat_count": "6",
|
||||
"type": "upgrade",
|
||||
"user_email": "hamlet@zulip.com",
|
||||
"type": "card_update",
|
||||
"user_id": "10"
|
||||
},
|
||||
"mode": "setup",
|
||||
"object": "checkout.session",
|
||||
"payment_intent": null,
|
||||
"payment_link": null,
|
||||
"payment_method_collection": "always",
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {},
|
||||
"payment_method_types": [
|
||||
"card"
|
||||
@@ -47,7 +60,7 @@
|
||||
"enabled": false
|
||||
},
|
||||
"recovered_from": null,
|
||||
"setup_intent": "seti_1K2OXoHSaWXyvFpKLyy5ns16",
|
||||
"setup_intent": "seti_1OIlcTDEQaroqDjs7K1pjsyq",
|
||||
"shipping": null,
|
||||
"shipping_address_collection": null,
|
||||
"shipping_options": [],
|
||||
@@ -57,7 +70,8 @@
|
||||
"subscription": null,
|
||||
"success_url": "http://zulip.testserver/billing/event_status?stripe_session_id={CHECKOUT_SESSION_ID}",
|
||||
"total_details": null,
|
||||
"url": "https://checkout.stripe.com/pay/cs_test_NORMALIZED02JXoyt8JsWg6jjuoI58GyCaB4aDXDWB7D0FqdiqlF6JDHjM#fidkdWxOYHwnPyd1blpxYHZxWnZkQk5DYTNqTGNxQl9JQjJIf2B1Y05BdScpJ2N3amhWYHdzYHcnP3F3cGApJ2lkfGpwcVF8dWAnPyd2bGtiaWBaZmppcGhrJyknYGtkZ2lgVWlkZmBtamlhYHd2Jz9xd3BgeCUl"
|
||||
"ui_mode": "hosted",
|
||||
"url": "https://checkout.stripe.com/c/pay/cs_test_NORMALIZED02sb4yHaq28VHOZscOtqKWTLoGQJALldTi43GUE0P56ay9sU#fidkdWxOYHwnPyd1blpxYHZxWl1UZjFOczZJXUE2PUpzUWNPV2ZpdlFzUCcpJ2N3amhWYHdzYHcnP3F3cGApJ2lkfGpwcVF8dWAnPyd2bGtiaWBaZmppcGhrJyknYGtkZ2lgVWlkZmBtamlhYHd2Jz9xd3BgeCUl"
|
||||
}
|
||||
],
|
||||
"has_more": true,
|
||||
|
||||
@@ -12,32 +12,45 @@
|
||||
"billing_address_collection": null,
|
||||
"cancel_url": "http://zulip.testserver/upgrade/",
|
||||
"client_reference_id": null,
|
||||
"client_secret": null,
|
||||
"consent": null,
|
||||
"consent_collection": null,
|
||||
"created": 1000000000,
|
||||
"currency": null,
|
||||
"currency_conversion": null,
|
||||
"custom_fields": [],
|
||||
"custom_text": {
|
||||
"shipping_address": null,
|
||||
"submit": null,
|
||||
"terms_of_service_acceptance": null
|
||||
},
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"customer_details": null,
|
||||
"customer_creation": null,
|
||||
"customer_details": {
|
||||
"address": null,
|
||||
"email": "hamlet@zulip.com",
|
||||
"name": null,
|
||||
"phone": null,
|
||||
"tax_exempt": null,
|
||||
"tax_ids": null
|
||||
},
|
||||
"customer_email": null,
|
||||
"expires_at": 1000000000,
|
||||
"id": "cs_test_NORMALIZED03qjdrziUfZOYhaTIKoiuAENHHbecsfYggKZ4kWegRShmXDo",
|
||||
"id": "cs_test_NORMALIZED03vZmJUBP0ybiRb1yrtpVKGaX0cm1V0nhnpM6e5pcI1y8CkG",
|
||||
"invoice": null,
|
||||
"invoice_creation": null,
|
||||
"livemode": false,
|
||||
"locale": null,
|
||||
"metadata": {
|
||||
"billing_modality": "charge_automatically",
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"price_per_license": "6000",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
"seat_count": "6",
|
||||
"type": "upgrade",
|
||||
"user_email": "hamlet@zulip.com",
|
||||
"type": "card_update",
|
||||
"user_id": "10"
|
||||
},
|
||||
"mode": "setup",
|
||||
"object": "checkout.session",
|
||||
"payment_intent": null,
|
||||
"payment_link": null,
|
||||
"payment_method_collection": "always",
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {},
|
||||
"payment_method_types": [
|
||||
"card"
|
||||
@@ -47,7 +60,7 @@
|
||||
"enabled": false
|
||||
},
|
||||
"recovered_from": null,
|
||||
"setup_intent": "seti_1K2OXyHSaWXyvFpKvIhWI0JW",
|
||||
"setup_intent": "seti_1OIlcdDEQaroqDjsB4ugOdVp",
|
||||
"shipping": null,
|
||||
"shipping_address_collection": null,
|
||||
"shipping_options": [],
|
||||
@@ -57,7 +70,8 @@
|
||||
"subscription": null,
|
||||
"success_url": "http://zulip.testserver/billing/event_status?stripe_session_id={CHECKOUT_SESSION_ID}",
|
||||
"total_details": null,
|
||||
"url": "https://checkout.stripe.com/pay/cs_test_NORMALIZED03qjdrziUfZOYhaTIKoiuAENHHbecsfYggKZ4kWegRShmXDo#fidkdWxOYHwnPyd1blpxYHZxWnZkQk5DYTNqTGNxQl9JQjJIf2B1Y05BdScpJ2N3amhWYHdzYHcnP3F3cGApJ2lkfGpwcVF8dWAnPyd2bGtiaWBaZmppcGhrJyknYGtkZ2lgVWlkZmBtamlhYHd2Jz9xd3BgeCUl"
|
||||
"ui_mode": "hosted",
|
||||
"url": "https://checkout.stripe.com/c/pay/cs_test_NORMALIZED03vZmJUBP0ybiRb1yrtpVKGaX0cm1V0nhnpM6e5pcI1y8CkG#fidkdWxOYHwnPyd1blpxYHZxWl1UZjFOczZJXUE2PUpzUWNPV2ZpdlFzUCcpJ2N3amhWYHdzYHcnP3F3cGApJ2lkfGpwcVF8dWAnPyd2bGtiaWBaZmppcGhrJyknYGtkZ2lgVWlkZmBtamlhYHd2Jz9xd3BgeCUl"
|
||||
}
|
||||
],
|
||||
"has_more": true,
|
||||
|
||||
@@ -3,17 +3,19 @@
|
||||
"balance": 0,
|
||||
"created": 1000000000,
|
||||
"currency": null,
|
||||
"default_currency": null,
|
||||
"default_source": null,
|
||||
"delinquent": false,
|
||||
"description": "zulip (Zulip Dev)",
|
||||
"discount": null,
|
||||
"email": "hamlet@zulip.com",
|
||||
"email": "othello@zulip.com",
|
||||
"id": "cus_NORMALIZED0001",
|
||||
"invoice_prefix": "NORMA01",
|
||||
"invoice_settings": {
|
||||
"custom_fields": null,
|
||||
"default_payment_method": null,
|
||||
"footer": null
|
||||
"footer": null,
|
||||
"rendering_options": null
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
@@ -26,5 +28,6 @@
|
||||
"phone": null,
|
||||
"preferred_locales": [],
|
||||
"shipping": null,
|
||||
"tax_exempt": "none"
|
||||
"tax_exempt": "none",
|
||||
"test_clock": null
|
||||
}
|
||||
|
||||
@@ -3,17 +3,19 @@
|
||||
"balance": 0,
|
||||
"created": 1000000000,
|
||||
"currency": null,
|
||||
"default_currency": null,
|
||||
"default_source": null,
|
||||
"delinquent": false,
|
||||
"description": "zulip (Zulip Dev)",
|
||||
"discount": null,
|
||||
"email": "hamlet@zulip.com",
|
||||
"email": "othello@zulip.com",
|
||||
"id": "cus_NORMALIZED0001",
|
||||
"invoice_prefix": "NORMA01",
|
||||
"invoice_settings": {
|
||||
"custom_fields": null,
|
||||
"default_payment_method": null,
|
||||
"footer": null
|
||||
"default_payment_method": "pm_1OIlXhDEQaroqDjsm8crnb7t",
|
||||
"footer": null,
|
||||
"rendering_options": null
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
@@ -26,5 +28,6 @@
|
||||
"phone": null,
|
||||
"preferred_locales": [],
|
||||
"shipping": null,
|
||||
"tax_exempt": "none"
|
||||
"tax_exempt": "none",
|
||||
"test_clock": null
|
||||
}
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
"address": null,
|
||||
"balance": 0,
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"currency": null,
|
||||
"default_currency": null,
|
||||
"default_source": null,
|
||||
"delinquent": false,
|
||||
"description": "zulip (Zulip Dev)",
|
||||
"discount": null,
|
||||
"email": "hamlet@zulip.com",
|
||||
"email": "othello@zulip.com",
|
||||
"id": "cus_NORMALIZED0001",
|
||||
"invoice_prefix": "NORMA01",
|
||||
"invoice_settings": {
|
||||
@@ -34,8 +35,8 @@
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 3,
|
||||
"exp_year": 2033,
|
||||
"exp_month": 12,
|
||||
"exp_year": 2024,
|
||||
"fingerprint": "NORMALIZED000001",
|
||||
"funding": "credit",
|
||||
"generated_from": null,
|
||||
@@ -53,13 +54,14 @@
|
||||
},
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"id": "pm_1K2OXeHSaWXyvFpKfQsNmKNC",
|
||||
"id": "pm_1OIlXhDEQaroqDjsm8crnb7t",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "payment_method",
|
||||
"type": "card"
|
||||
},
|
||||
"footer": null
|
||||
"footer": null,
|
||||
"rendering_options": null
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
@@ -67,10 +69,11 @@
|
||||
"realm_str": "zulip"
|
||||
},
|
||||
"name": null,
|
||||
"next_invoice_sequence": 2,
|
||||
"next_invoice_sequence": 1,
|
||||
"object": "customer",
|
||||
"phone": null,
|
||||
"preferred_locales": [],
|
||||
"shipping": null,
|
||||
"tax_exempt": "none"
|
||||
"tax_exempt": "none",
|
||||
"test_clock": null
|
||||
}
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
"address": null,
|
||||
"balance": 0,
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"currency": null,
|
||||
"default_currency": null,
|
||||
"default_source": null,
|
||||
"delinquent": false,
|
||||
"description": "zulip (Zulip Dev)",
|
||||
"discount": null,
|
||||
"email": "hamlet@zulip.com",
|
||||
"email": "othello@zulip.com",
|
||||
"id": "cus_NORMALIZED0001",
|
||||
"invoice_prefix": "NORMA01",
|
||||
"invoice_settings": {
|
||||
@@ -34,8 +35,8 @@
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 3,
|
||||
"exp_year": 2033,
|
||||
"exp_month": 12,
|
||||
"exp_year": 2024,
|
||||
"fingerprint": "NORMALIZED000001",
|
||||
"funding": "credit",
|
||||
"generated_from": null,
|
||||
@@ -53,13 +54,14 @@
|
||||
},
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"id": "pm_1K2OXeHSaWXyvFpKfQsNmKNC",
|
||||
"id": "pm_1OIlXhDEQaroqDjsm8crnb7t",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "payment_method",
|
||||
"type": "card"
|
||||
},
|
||||
"footer": null
|
||||
"footer": null,
|
||||
"rendering_options": null
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
@@ -67,10 +69,11 @@
|
||||
"realm_str": "zulip"
|
||||
},
|
||||
"name": null,
|
||||
"next_invoice_sequence": 2,
|
||||
"next_invoice_sequence": 1,
|
||||
"object": "customer",
|
||||
"phone": null,
|
||||
"preferred_locales": [],
|
||||
"shipping": null,
|
||||
"tax_exempt": "none"
|
||||
"tax_exempt": "none",
|
||||
"test_clock": null
|
||||
}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"address": null,
|
||||
"balance": 0,
|
||||
"created": 1000000000,
|
||||
"currency": null,
|
||||
"default_currency": null,
|
||||
"default_source": null,
|
||||
"delinquent": false,
|
||||
"description": "zulip (Zulip Dev)",
|
||||
"discount": null,
|
||||
"email": "othello@zulip.com",
|
||||
"id": "cus_NORMALIZED0001",
|
||||
"invoice_prefix": "NORMA01",
|
||||
"invoice_settings": {
|
||||
"custom_fields": null,
|
||||
"default_payment_method": {
|
||||
"billing_details": {
|
||||
"address": {
|
||||
"city": null,
|
||||
"country": null,
|
||||
"line1": null,
|
||||
"line2": null,
|
||||
"postal_code": null,
|
||||
"state": null
|
||||
},
|
||||
"email": null,
|
||||
"name": null,
|
||||
"phone": null
|
||||
},
|
||||
"card": {
|
||||
"brand": "visa",
|
||||
"checks": {
|
||||
"address_line1_check": null,
|
||||
"address_postal_code_check": null,
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 12,
|
||||
"exp_year": 2024,
|
||||
"fingerprint": "NORMALIZED000001",
|
||||
"funding": "credit",
|
||||
"generated_from": null,
|
||||
"last4": "4242",
|
||||
"networks": {
|
||||
"available": [
|
||||
"visa"
|
||||
],
|
||||
"preferred": null
|
||||
},
|
||||
"three_d_secure_usage": {
|
||||
"supported": true
|
||||
},
|
||||
"wallet": null
|
||||
},
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"id": "pm_1OIlXhDEQaroqDjsm8crnb7t",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "payment_method",
|
||||
"type": "card"
|
||||
},
|
||||
"footer": null,
|
||||
"rendering_options": null
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip"
|
||||
},
|
||||
"name": null,
|
||||
"next_invoice_sequence": 1,
|
||||
"object": "customer",
|
||||
"phone": null,
|
||||
"preferred_locales": [],
|
||||
"shipping": null,
|
||||
"tax_exempt": "none",
|
||||
"test_clock": null
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"address": null,
|
||||
"balance": 0,
|
||||
"created": 1000000000,
|
||||
"currency": null,
|
||||
"default_currency": null,
|
||||
"default_source": null,
|
||||
"delinquent": false,
|
||||
"description": "zulip (Zulip Dev)",
|
||||
"discount": null,
|
||||
"email": "othello@zulip.com",
|
||||
"id": "cus_NORMALIZED0001",
|
||||
"invoice_prefix": "NORMA01",
|
||||
"invoice_settings": {
|
||||
"custom_fields": null,
|
||||
"default_payment_method": {
|
||||
"billing_details": {
|
||||
"address": {
|
||||
"city": null,
|
||||
"country": null,
|
||||
"line1": null,
|
||||
"line2": null,
|
||||
"postal_code": null,
|
||||
"state": null
|
||||
},
|
||||
"email": null,
|
||||
"name": null,
|
||||
"phone": null
|
||||
},
|
||||
"card": {
|
||||
"brand": "visa",
|
||||
"checks": {
|
||||
"address_line1_check": null,
|
||||
"address_postal_code_check": null,
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 12,
|
||||
"exp_year": 2024,
|
||||
"fingerprint": "NORMALIZED000001",
|
||||
"funding": "credit",
|
||||
"generated_from": null,
|
||||
"last4": "4242",
|
||||
"networks": {
|
||||
"available": [
|
||||
"visa"
|
||||
],
|
||||
"preferred": null
|
||||
},
|
||||
"three_d_secure_usage": {
|
||||
"supported": true
|
||||
},
|
||||
"wallet": null
|
||||
},
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"id": "pm_1OIlXhDEQaroqDjsm8crnb7t",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "payment_method",
|
||||
"type": "card"
|
||||
},
|
||||
"footer": null,
|
||||
"rendering_options": null
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip"
|
||||
},
|
||||
"name": null,
|
||||
"next_invoice_sequence": 1,
|
||||
"object": "customer",
|
||||
"phone": null,
|
||||
"preferred_locales": [],
|
||||
"shipping": null,
|
||||
"tax_exempt": "none",
|
||||
"test_clock": null
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user