mirror of
https://github.com/zulip/zulip.git
synced 2025-10-24 16:43:57 +00:00
Compare commits
916 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7b80af61e4 | ||
|
|
bc13f0ea37 | ||
|
|
bbd79120b5 | ||
|
|
910a8169bc | ||
|
|
e44ba3b1f1 | ||
|
|
92de3d11d2 | ||
|
|
fc9cfc03e6 | ||
|
|
eb2882d464 | ||
|
|
d25c375be9 | ||
|
|
f65478fb1f | ||
|
|
6d48e08ff7 | ||
|
|
5d7010c8a0 | ||
|
|
356d775d31 | ||
|
|
b377673190 | ||
|
|
8fb126505c | ||
|
|
48ee7506ba | ||
|
|
03323b0124 | ||
|
|
10862451ef | ||
|
|
9423ccecd4 | ||
|
|
97799b279b | ||
|
|
3aed22dcd0 | ||
|
|
2090a10aad | ||
|
|
ace8344b5a | ||
|
|
fb5137f8b5 | ||
|
|
8102519242 | ||
|
|
0fe725fdbd | ||
|
|
4b5e8971a3 | ||
|
|
1588f49b4f | ||
|
|
33e04362e1 | ||
|
|
53b7e956ea | ||
|
|
1f7b3d7a2d | ||
|
|
0f2cc383f6 | ||
|
|
63e5712837 | ||
|
|
f5aa88e165 | ||
|
|
c12a9eeb9c | ||
|
|
d351353126 | ||
|
|
53f40133eb | ||
|
|
b472d769d1 | ||
|
|
6e902defba | ||
|
|
11dff6b4d8 | ||
|
|
b4e92ecc48 | ||
|
|
ba80084ea7 | ||
|
|
8965f011fb | ||
|
|
94f0837b9c | ||
|
|
633ec698f5 | ||
|
|
bedb68b2fe | ||
|
|
9067220af6 | ||
|
|
83d6481f6f | ||
|
|
b8d05aea1b | ||
|
|
1757b88760 | ||
|
|
4ef93de128 | ||
|
|
863c1c28f7 | ||
|
|
036b1156f2 | ||
|
|
e02e0cd37e | ||
|
|
d795400b21 | ||
|
|
34a1be80a4 | ||
|
|
c7245d5f3b | ||
|
|
77a6f44455 | ||
|
|
d7d5b6c73e | ||
|
|
d893ff5ba8 | ||
|
|
92c1dfc248 | ||
|
|
8bce83709f | ||
|
|
651590c49a | ||
|
|
a13e42f18a | ||
|
|
10ef308848 | ||
|
|
a5311c8032 | ||
|
|
612f2c73d6 | ||
|
|
2863b5954e | ||
|
|
2de1a23721 | ||
|
|
791d66fe28 | ||
|
|
62e6b10ecd | ||
|
|
1229e38a0d | ||
|
|
bfa3d144eb | ||
|
|
b8deb44a05 | ||
|
|
d040664952 | ||
|
|
6308e07e53 | ||
|
|
89545891f6 | ||
|
|
a897d68d93 | ||
|
|
484c0df076 | ||
|
|
1abe22b0a1 | ||
|
|
f0d429d0f9 | ||
|
|
c43eb10224 | ||
|
|
09c32cbe30 | ||
|
|
68d117e60a | ||
|
|
e8500fbdb0 | ||
|
|
35b644c564 | ||
|
|
9efb236c35 | ||
|
|
081d94c4e8 | ||
|
|
039f6af79e | ||
|
|
998685f2e7 | ||
|
|
0c99420ceb | ||
|
|
c61b353b4b | ||
|
|
27d236fb52 | ||
|
|
95f4b31ce7 | ||
|
|
af83093a65 | ||
|
|
45a2f7eac1 | ||
|
|
7f26905fe0 | ||
|
|
f281199d2f | ||
|
|
63f4fc51de | ||
|
|
c2636354a5 | ||
|
|
19575b46f7 | ||
|
|
0d08fe90a8 | ||
|
|
180dd00d5f | ||
|
|
44e9171a46 | ||
|
|
aebafcc43f | ||
|
|
e9ce69aaf6 | ||
|
|
da74b9ade7 | ||
|
|
9cc0ded092 | ||
|
|
2b879e646c | ||
|
|
a2f72edc68 | ||
|
|
e515574b3e | ||
|
|
fa9e3fb35c | ||
|
|
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 |
@@ -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:
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -20,6 +20,7 @@
|
||||
/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
|
||||
|
||||
8
.mailmap
8
.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>
|
||||
@@ -92,6 +97,7 @@ Rishi Gupta <rishig@zulipchat.com> <rishig@users.noreply.github.com>
|
||||
Rixant Rokaha <rixantrokaha@gmail.com>
|
||||
Rixant Rokaha <rixantrokaha@gmail.com> <rishantrokaha@gmail.com>
|
||||
Rixant Rokaha <rixantrokaha@gmail.com> <rrokaha@caldwell.edu>
|
||||
Rohan Gudimetla <rohan.gudimetla07@gmail.com>
|
||||
Sahil Batra <sahil@zulip.com> <35494118+sahil839@users.noreply.github.com>
|
||||
Sahil Batra <sahil@zulip.com> <sahilbatra839@gmail.com>
|
||||
Satyam Bansal <sbansal1999@gmail.com>
|
||||
@@ -99,6 +105,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>
|
||||
@@ -114,6 +121,7 @@ Tim Abbott <tabbott@zulip.com> <tabbott@zulipchat.com>
|
||||
Ujjawal Modi <umodi2003@gmail.com> <99073049+Ujjawal3@users.noreply.github.com>
|
||||
umkay <ukhan@zulipchat.com> <umaimah.k@gmail.com>
|
||||
umkay <ukhan@zulipchat.com> <umkay@users.noreply.github.com>
|
||||
Viktor Illmer <1476338+v-ji@users.noreply.github.com>
|
||||
Vishnu KS <vishnu@zulip.com> <hackerkid@vishnuks.com>
|
||||
Vishnu KS <vishnu@zulip.com> <yo@vishnuks.com>
|
||||
Waseem Daher <wdaher@zulip.com> <wdaher@dropbox.com>
|
||||
|
||||
@@ -19,7 +19,6 @@ 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
|
||||
|
||||
@@ -31,10 +30,9 @@ if settings.ZILENCER_ENABLED:
|
||||
RemoteZulipServer,
|
||||
)
|
||||
|
||||
## Logging setup ##
|
||||
|
||||
logger = logging.getLogger("zulip.management")
|
||||
log_to_file(logger, settings.ANALYTICS_LOG_PATH)
|
||||
logger = logging.getLogger("zulip.analytics")
|
||||
|
||||
|
||||
# You can't subtract timedelta.max from a datetime, so use this instead
|
||||
TIMEDELTA_MAX = timedelta(days=365 * 1000)
|
||||
@@ -111,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 ##
|
||||
|
||||
@@ -199,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()
|
||||
@@ -220,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
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import hashlib
|
||||
import os
|
||||
import time
|
||||
from argparse import ArgumentParser
|
||||
@@ -12,7 +13,7 @@ from typing_extensions import override
|
||||
|
||||
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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,80 @@
|
||||
import uuid
|
||||
from datetime import timedelta
|
||||
from unittest import mock
|
||||
|
||||
from django.utils.timezone import now as timezone_now
|
||||
|
||||
from corporate.lib.stripe import add_months
|
||||
from corporate.models import Customer, CustomerPlan, LicenseLedger
|
||||
from zerver.lib.test_classes import ZulipTestCase
|
||||
from zerver.models import Client, UserActivity, UserProfile
|
||||
from zilencer.models import (
|
||||
RemoteRealmAuditLog,
|
||||
RemoteZulipServer,
|
||||
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):
|
||||
@@ -35,7 +106,32 @@ class ActivityTest(ZulipTestCase):
|
||||
result = self.client_get("/activity")
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
with self.assert_database_query_count(4):
|
||||
# Add data for remote activity page
|
||||
RemoteRealmAuditLog.objects.bulk_create([RemoteRealmAuditLog(**data) for data in data_list])
|
||||
remote_server = RemoteZulipServer.objects.get(id=1)
|
||||
customer = Customer.objects.create(remote_server=remote_server)
|
||||
plan = CustomerPlan.objects.create(
|
||||
customer=customer,
|
||||
billing_cycle_anchor=timezone_now(),
|
||||
billing_schedule=CustomerPlan.BILLING_SCHEDULE_ANNUAL,
|
||||
tier=CustomerPlan.TIER_SELF_HOSTED_BUSINESS,
|
||||
price_per_license=8000,
|
||||
next_invoice_date=add_months(timezone_now(), 12),
|
||||
)
|
||||
LicenseLedger.objects.create(
|
||||
licenses=10,
|
||||
licenses_at_next_renewal=10,
|
||||
event_time=timezone_now(),
|
||||
is_renewal=True,
|
||||
plan=plan,
|
||||
)
|
||||
RemoteZulipServer.objects.create(
|
||||
uuid=str(uuid.uuid4()),
|
||||
api_key="magic_secret_api_key",
|
||||
hostname="demo.example.com",
|
||||
contact_email="email@example.com",
|
||||
)
|
||||
with self.assert_database_query_count(10):
|
||||
result = self.client_get("/activity/remote")
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
@@ -51,3 +147,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)
|
||||
|
||||
@@ -116,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
|
||||
@@ -130,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
|
||||
@@ -1455,8 +1459,9 @@ class TestLoggingCountStats(AnalyticsTestCase):
|
||||
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
|
||||
), mock.patch("zilencer.views.send_apple_push_notification", return_value=1), mock.patch(
|
||||
"corporate.lib.stripe.RemoteServerBillingSession.current_count_for_billed_licenses",
|
||||
return_value=10,
|
||||
), self.assertLogs(
|
||||
"zilencer.views", level="INFO"
|
||||
):
|
||||
@@ -1515,8 +1520,9 @@ class TestLoggingCountStats(AnalyticsTestCase):
|
||||
}
|
||||
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
|
||||
), mock.patch("zilencer.views.send_apple_push_notification", return_value=1), mock.patch(
|
||||
"corporate.lib.stripe.RemoteServerBillingSession.current_count_for_billed_licenses",
|
||||
return_value=10,
|
||||
), self.assertLogs(
|
||||
"zilencer.views", level="INFO"
|
||||
):
|
||||
@@ -1574,8 +1580,9 @@ class TestLoggingCountStats(AnalyticsTestCase):
|
||||
|
||||
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
|
||||
), mock.patch("zilencer.views.send_apple_push_notification", return_value=1), mock.patch(
|
||||
"corporate.lib.stripe.RemoteServerBillingSession.current_count_for_billed_licenses",
|
||||
return_value=10,
|
||||
), self.assertLogs(
|
||||
"zilencer.views", level="INFO"
|
||||
):
|
||||
|
||||
@@ -1,14 +1,23 @@
|
||||
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
|
||||
from corporate.lib.support import update_realm_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,
|
||||
SponsoredPlanTypes,
|
||||
ZulipSponsorshipRequest,
|
||||
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
|
||||
@@ -16,6 +25,7 @@ from zerver.lib.test_classes import ZulipTestCase
|
||||
from zerver.lib.test_helpers import reset_email_visibility_to_everyone_in_zulip_realm
|
||||
from zerver.models import (
|
||||
MultiuseInvite,
|
||||
OrgTypeEnum,
|
||||
PreregistrationUser,
|
||||
Realm,
|
||||
UserMessage,
|
||||
@@ -36,6 +46,24 @@ from zilencer.models import RemoteZulipServer
|
||||
class TestRemoteServerSupportEndpoint(ZulipTestCase):
|
||||
@override
|
||||
def setUp(self) -> None:
|
||||
def add_sponsorship_request(
|
||||
hostname: str, org_type: int, website: str, paid_users: str, plan: str
|
||||
) -> None:
|
||||
remote_server = RemoteZulipServer.objects.get(hostname=hostname)
|
||||
customer = Customer.objects.create(
|
||||
remote_server=remote_server, sponsorship_pending=True
|
||||
)
|
||||
ZulipSponsorshipRequest.objects.create(
|
||||
customer=customer,
|
||||
org_type=org_type,
|
||||
org_website=website,
|
||||
org_description="We help people.",
|
||||
expected_total_users="20-35",
|
||||
paid_users_count=paid_users,
|
||||
paid_users_description="",
|
||||
requested_plan=plan,
|
||||
)
|
||||
|
||||
super().setUp()
|
||||
|
||||
# Set up some initial example data.
|
||||
@@ -45,6 +73,23 @@ class TestRemoteServerSupportEndpoint(ZulipTestCase):
|
||||
hostname=hostname, contact_email=f"admin@{hostname}", plan_type=1, uuid=uuid.uuid4()
|
||||
)
|
||||
|
||||
# Add example sponsorship request data
|
||||
add_sponsorship_request(
|
||||
hostname="zulip-1.example.com",
|
||||
org_type=OrgTypeEnum.Community.value,
|
||||
website="",
|
||||
paid_users="None",
|
||||
plan=SponsoredPlanTypes.BUSINESS.value,
|
||||
)
|
||||
|
||||
add_sponsorship_request(
|
||||
hostname="zulip-2.example.com",
|
||||
org_type=OrgTypeEnum.OpenSource.value,
|
||||
website="example.org",
|
||||
paid_users="",
|
||||
plan=SponsoredPlanTypes.COMMUNITY.value,
|
||||
)
|
||||
|
||||
def test_search(self) -> None:
|
||||
self.login("cordelia")
|
||||
|
||||
@@ -70,6 +115,19 @@ class TestRemoteServerSupportEndpoint(ZulipTestCase):
|
||||
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)
|
||||
|
||||
# Sponsorship request information
|
||||
self.assert_in_success_response(["<li><b>Organization type</b>: Community</li>"], result)
|
||||
self.assert_in_success_response(
|
||||
["<li><b>Organization website</b>: No website submitted</li>"], result
|
||||
)
|
||||
self.assert_in_success_response(["<li><b>Paid users</b>: None</li>"], result)
|
||||
self.assert_in_success_response(["<li><b>Requested plan</b>: Business</li>"], result)
|
||||
self.assert_in_success_response(
|
||||
["<li><b>Organization description</b>: We help people.</li>"], result
|
||||
)
|
||||
self.assert_in_success_response(["<li><b>Estimated total users</b>: 20-35</li>"], result)
|
||||
self.assert_in_success_response(["<li><b>Description of paid users</b>: </li>"], result)
|
||||
|
||||
with mock.patch(
|
||||
"analytics.views.support.compute_max_monthly_messages", side_effect=MissingDataError
|
||||
):
|
||||
@@ -89,6 +147,35 @@ class TestRemoteServerSupportEndpoint(ZulipTestCase):
|
||||
self.assert_in_success_response(["<b>Contact email</b>: admin@zulip-2.example.com"], result)
|
||||
self.assert_not_in_success_response(["<h3>zulip-1.example.com</h3>"], result)
|
||||
|
||||
# Sponsorship request information
|
||||
self.assert_in_success_response(
|
||||
["<li><b>Organization type</b>: Open-source project</li>"], result
|
||||
)
|
||||
self.assert_in_success_response(
|
||||
["<li><b>Organization website</b>: example.org</li>"], result
|
||||
)
|
||||
self.assert_in_success_response(["<li><b>Paid users</b>: </li>"], result)
|
||||
self.assert_in_success_response(["<li><b>Requested plan</b>: Community</li>"], result)
|
||||
self.assert_in_success_response(
|
||||
["<li><b>Organization description</b>: We help people.</li>"], result
|
||||
)
|
||||
self.assert_in_success_response(["<li><b>Estimated total users</b>: 20-35</li>"], result)
|
||||
self.assert_in_success_response(["<li><b>Description of paid users</b>: </li>"], result)
|
||||
|
||||
result = self.client_get("/activity/remote/support", {"q": "admin@zulip-3.example.com"})
|
||||
self.assert_in_success_response(["<h3>zulip-3.example.com</h3>"], result)
|
||||
self.assert_in_success_response(["<b>Contact email</b>: admin@zulip-3.example.com"], result)
|
||||
self.assert_not_in_success_response(["<h3>zulip-1.example.com</h3>"], result)
|
||||
|
||||
# Sponsorship request information
|
||||
self.assert_not_in_success_response(
|
||||
["<li><b>Organization description</b>: We help people.</li>"], result
|
||||
)
|
||||
self.assert_not_in_success_response(
|
||||
["<li><b>Estimated total users</b>: 20-35</li>"], result
|
||||
)
|
||||
self.assert_not_in_success_response(["<li><b>Description of paid users</b>: </li>"], result)
|
||||
|
||||
|
||||
class TestSupportEndpoint(ZulipTestCase):
|
||||
def test_search(self) -> None:
|
||||
@@ -191,7 +278,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)",
|
||||
@@ -291,8 +378,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),
|
||||
)
|
||||
@@ -356,55 +443,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")
|
||||
@@ -432,38 +520,50 @@ class TestSupportEndpoint(ZulipTestCase):
|
||||
result,
|
||||
)
|
||||
|
||||
@mock.patch("analytics.views.support.update_realm_billing_method")
|
||||
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")
|
||||
@@ -484,7 +584,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:
|
||||
@@ -493,7 +593,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:
|
||||
@@ -530,14 +630,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")
|
||||
@@ -574,7 +675,10 @@ class TestSupportEndpoint(ZulipTestCase):
|
||||
def test_approve_sponsorship(self) -> None:
|
||||
support_admin = self.example_user("iago")
|
||||
lear_realm = get_realm("lear")
|
||||
update_realm_sponsorship_status(lear_realm, True, acting_user=support_admin)
|
||||
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()
|
||||
@@ -689,73 +793,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)),
|
||||
|
||||
@@ -48,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]]:
|
||||
@@ -128,7 +104,7 @@ 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:
|
||||
@@ -137,13 +113,18 @@ def realm_url_link(realm_str: str) -> Markup:
|
||||
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]:
|
||||
|
||||
@@ -13,13 +13,16 @@ 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.models import Realm, get_org_type_display_name
|
||||
@@ -201,7 +204,7 @@ def realm_summary_table() -> str:
|
||||
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"]
|
||||
|
||||
@@ -327,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,17 @@ 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 corporate.lib.analytics import get_plan_data_by_remote_server
|
||||
from zerver.decorator import require_server_admin
|
||||
from zilencer.models import get_remote_server_guest_and_non_guest_count
|
||||
|
||||
|
||||
@require_server_admin
|
||||
@@ -12,32 +21,57 @@ 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
|
||||
where not deactivated
|
||||
order by latest_value DESC NULLS LAST, push_user_count DESC NULLS LAST
|
||||
"""
|
||||
)
|
||||
|
||||
@@ -45,15 +79,58 @@ def get_remote_server_activity(request: HttpRequest) -> HttpResponse:
|
||||
"ID",
|
||||
"Hostname",
|
||||
"Contact email",
|
||||
"Zulip version",
|
||||
"Analytics users",
|
||||
"Mobile users",
|
||||
"Last update time",
|
||||
"Mobile pushes forwarded",
|
||||
"Plan name",
|
||||
"Plan status",
|
||||
"ARR",
|
||||
"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]
|
||||
plan_data_by_remote_server = get_plan_data_by_remote_server()
|
||||
|
||||
for row in rows:
|
||||
# Add estimated revenue for server
|
||||
server_plan_data = plan_data_by_remote_server.get(row[0])
|
||||
if server_plan_data is None:
|
||||
row.append("---")
|
||||
row.append("---")
|
||||
row.append("---")
|
||||
else:
|
||||
row.append(server_plan_data.current_plan_name)
|
||||
row.append(server_plan_data.current_status)
|
||||
row.append(server_plan_data.annual_revenue)
|
||||
# Add user counts
|
||||
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)
|
||||
# Add links
|
||||
stats = remote_installation_stats_link(row[0])
|
||||
support = remote_installation_support_link(row[1])
|
||||
links = stats + " " + support
|
||||
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, Union
|
||||
from urllib.parse import urlencode
|
||||
from urllib.parse import urlencode, urlsplit
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ValidationError
|
||||
@@ -50,39 +48,40 @@ from zerver.views.invite import get_invitee_emails_set
|
||||
|
||||
if settings.ZILENCER_ENABLED:
|
||||
from zilencer.lib.remote_counts import MissingDataError, compute_max_monthly_messages
|
||||
from zilencer.models import RemoteZulipServer
|
||||
from zilencer.models import RemoteRealm, RemoteZulipServer
|
||||
|
||||
if settings.BILLING_ENABLED:
|
||||
from corporate.lib.stripe import (
|
||||
RealmBillingSession,
|
||||
downgrade_at_the_end_of_billing_cycle,
|
||||
downgrade_now_without_creating_additional_invoices,
|
||||
get_latest_seat_count,
|
||||
switch_realm_from_standard_to_plus_plan,
|
||||
void_all_open_invoices,
|
||||
RemoteRealmBillingSession,
|
||||
RemoteServerBillingSession,
|
||||
SupportType,
|
||||
SupportViewRequest,
|
||||
)
|
||||
from corporate.lib.support import (
|
||||
approve_realm_sponsorship,
|
||||
attach_discount_to_realm,
|
||||
get_discount_for_realm,
|
||||
update_realm_billing_method,
|
||||
update_realm_sponsorship_status,
|
||||
)
|
||||
from corporate.models import (
|
||||
Customer,
|
||||
CustomerPlan,
|
||||
get_current_plan_by_realm,
|
||||
get_customer_by_realm,
|
||||
PlanData,
|
||||
SupportData,
|
||||
get_current_plan_data_for_support_view,
|
||||
get_customer_discount_for_support_view,
|
||||
get_data_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_MANAGED: "Self-managed",
|
||||
RemoteZulipServer.PLAN_TYPE_SELF_MANAGED_LEGACY: CustomerPlan.name_from_tier(
|
||||
CustomerPlan.TIER_SELF_HOSTED_LEGACY
|
||||
),
|
||||
RemoteZulipServer.PLAN_TYPE_COMMUNITY: "Community",
|
||||
RemoteZulipServer.PLAN_TYPE_BUSINESS: "Business",
|
||||
RemoteZulipServer.PLAN_TYPE_ENTERPRISE: "Enterprise",
|
||||
}[plan_type]
|
||||
|
||||
|
||||
@@ -135,7 +134,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 = [
|
||||
@@ -143,20 +142,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(
|
||||
@@ -166,8 +157,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),
|
||||
@@ -199,22 +190,42 @@ def support(
|
||||
assert realm_id is not None
|
||||
realm = Realm.objects.get(id=realm_id)
|
||||
|
||||
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:
|
||||
@@ -238,51 +249,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_realm_billing_method(
|
||||
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_realm_billing_method(
|
||||
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_realm_sponsorship_status(realm, True, acting_user=acting_user)
|
||||
context["success_message"] = f"{realm.string_id} marked as pending sponsorship."
|
||||
else:
|
||||
update_realm_sponsorship_status(realm, False, acting_user=acting_user)
|
||||
context["success_message"] = f"{realm.string_id} is no longer pending sponsorship."
|
||||
elif approve_sponsorship:
|
||||
approve_realm_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."
|
||||
@@ -293,6 +259,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)
|
||||
|
||||
@@ -305,7 +278,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:
|
||||
@@ -369,23 +342,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:
|
||||
billing_session = RealmBillingSession(user=None, realm=realm)
|
||||
new_plan, last_ledger_entry = billing_session.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:
|
||||
@@ -404,7 +363,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
|
||||
@@ -421,7 +380,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:
|
||||
@@ -433,8 +394,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:
|
||||
@@ -447,7 +481,25 @@ def remote_servers_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_support_data: Dict[int, SupportData] = {}
|
||||
realm_support_data: Dict[int, SupportData] = {}
|
||||
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_data = get_data_for_support_view(realm_billing_session)
|
||||
realm_support_data[remote_realm.id] = remote_realm_data
|
||||
# Get plan data for remote server
|
||||
server_billing_session = RemoteServerBillingSession(remote_server=remote_server)
|
||||
remote_server_data = get_data_for_support_view(server_billing_session)
|
||||
server_support_data[remote_server.id] = remote_server_data
|
||||
# Get max monthly messages
|
||||
try:
|
||||
remote_server_to_max_monthly_messages[remote_server.id] = compute_max_monthly_messages(
|
||||
remote_server
|
||||
@@ -455,11 +507,17 @@ def remote_servers_support(
|
||||
except MissingDataError:
|
||||
remote_server_to_max_monthly_messages[remote_server.id] = "Recent data missing"
|
||||
|
||||
context["remote_servers"] = remote_servers
|
||||
context["remote_servers_support_data"] = server_support_data
|
||||
context["remote_server_to_max_monthly_messages"] = remote_server_to_max_monthly_messages
|
||||
context["remote_realms"] = remote_realms
|
||||
context["remote_realms_support_data"] = realm_support_data
|
||||
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,
|
||||
remote_server_to_max_monthly_messages=remote_server_to_max_monthly_messages,
|
||||
),
|
||||
context=context,
|
||||
)
|
||||
|
||||
@@ -18,8 +18,136 @@ clients should check the `zulip_feature_level` field, present in the
|
||||
/register`](/api/register-queue) responses, to determine the API
|
||||
format used by the Zulip server that they are interacting with.
|
||||
|
||||
## Changes in Zulip 9.0
|
||||
|
||||
Feature levels 238-239 are reserved for future use in 8.x maintenance
|
||||
releases.
|
||||
|
||||
## Changes in Zulip 8.0
|
||||
|
||||
**Feature level 237**
|
||||
|
||||
No changes; feature level used for Zulip 8.0 release.
|
||||
|
||||
**Feature level 236**
|
||||
|
||||
* [`POST /messages`](/api/send-message), [`POST
|
||||
/scheduled_messages`](/api/create-scheduled-message): The new
|
||||
`read_by_sender` parameter lets the client override the heuristic
|
||||
that determines whether the new message will be initially marked
|
||||
read by its sender.
|
||||
|
||||
**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 the 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),
|
||||
@@ -96,6 +224,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
|
||||
|
||||
@@ -179,6 +179,11 @@ Parameters accepted in the URL include:
|
||||
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
|
||||
@@ -189,5 +194,6 @@ Parameters accepted in the URL include:
|
||||
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/
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -1,13 +1,25 @@
|
||||
from dataclasses import dataclass
|
||||
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.lib.stripe import (
|
||||
RealmBillingSession,
|
||||
RemoteRealmBillingSession,
|
||||
RemoteServerBillingSession,
|
||||
)
|
||||
from corporate.models import Customer, CustomerPlan
|
||||
from zerver.lib.utils import assert_is_not_none
|
||||
|
||||
|
||||
@dataclass
|
||||
class RemoteActivityPlanData:
|
||||
current_status: str
|
||||
current_plan_name: str
|
||||
annual_revenue: int
|
||||
|
||||
|
||||
def get_realms_with_default_discount_dict() -> Dict[str, Decimal]:
|
||||
realms_with_default_discount: Dict[str, Any] = {}
|
||||
customers = (
|
||||
@@ -31,9 +43,52 @@ def estimate_annual_recurring_revenue_by_realm() -> Dict[str, int]: # nocoverag
|
||||
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.MONTHLY:
|
||||
renewal_cents = RealmBillingSession(
|
||||
realm=plan.customer.realm
|
||||
).get_customer_plan_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
|
||||
|
||||
|
||||
def get_plan_data_by_remote_server() -> Dict[int, RemoteActivityPlanData]: # nocoverage
|
||||
remote_server_plan_data: Dict[int, RemoteActivityPlanData] = {}
|
||||
for plan in CustomerPlan.objects.filter(
|
||||
status__lt=CustomerPlan.LIVE_STATUS_THRESHOLD, customer__realm__isnull=True
|
||||
).select_related("customer__remote_server", "customer__remote_realm"):
|
||||
renewal_cents = 0
|
||||
server_id = None
|
||||
|
||||
if plan.customer.remote_server is not None:
|
||||
server_id = plan.customer.remote_server.id
|
||||
renewal_cents = RemoteServerBillingSession(
|
||||
remote_server=plan.customer.remote_server
|
||||
).get_customer_plan_renewal_amount(plan, timezone_now())
|
||||
elif plan.customer.remote_realm is not None:
|
||||
server_id = plan.customer.remote_realm.server.id
|
||||
renewal_cents = RemoteRealmBillingSession(
|
||||
remote_realm=plan.customer.remote_realm
|
||||
).get_customer_plan_renewal_amount(plan, timezone_now())
|
||||
|
||||
assert server_id is not None
|
||||
|
||||
if plan.billing_schedule == CustomerPlan.BILLING_SCHEDULE_MONTHLY:
|
||||
renewal_cents *= 12
|
||||
|
||||
current_data = remote_server_plan_data.get(server_id)
|
||||
if current_data is not None:
|
||||
current_revenue = remote_server_plan_data[server_id].annual_revenue
|
||||
remote_server_plan_data[server_id] = RemoteActivityPlanData(
|
||||
current_status="Multiple plans",
|
||||
current_plan_name="See support view",
|
||||
annual_revenue=current_revenue + int(renewal_cents / 100),
|
||||
)
|
||||
else:
|
||||
remote_server_plan_data[server_id] = RemoteActivityPlanData(
|
||||
current_status=plan.get_plan_status_as_text(),
|
||||
current_plan_name=plan.name,
|
||||
annual_revenue=int(renewal_cents / 100),
|
||||
)
|
||||
return remote_server_plan_data
|
||||
|
||||
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 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,17 +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_customer_does_not_have_active_plan,
|
||||
)
|
||||
from corporate.models import CustomerPlan, 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")
|
||||
@@ -62,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,47 +85,18 @@ def handle_checkout_session_completed_event(
|
||||
session.save()
|
||||
|
||||
assert isinstance(stripe_session.setup_intent, str)
|
||||
stripe_setup_intent = stripe.SetupIntent.retrieve(stripe_session.setup_intent)
|
||||
assert session.customer.realm is not None
|
||||
assert stripe_session.metadata 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(int(user_id), session.customer.realm)
|
||||
billing_session = RealmBillingSession(user)
|
||||
stripe_setup_intent = stripe.SetupIntent.retrieve(stripe_session.setup_intent)
|
||||
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_customer_does_not_have_active_plan(session.customer)
|
||||
billing_session.update_or_create_stripe_customer(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_customer_does_not_have_active_plan(session.customer)
|
||||
billing_session.update_or_create_stripe_customer(payment_method)
|
||||
billing_session.process_initial_upgrade(
|
||||
CustomerPlan.STANDARD,
|
||||
int(stripe_session.metadata["licenses"]),
|
||||
stripe_session.metadata["license_management"] == "automatic",
|
||||
int(stripe_session.metadata["billing_schedule"]),
|
||||
charge_automatically=True,
|
||||
free_trial=True,
|
||||
)
|
||||
elif session.type in [Session.CARD_UPDATE_FROM_BILLING_PAGE]:
|
||||
billing_session.update_or_create_stripe_customer(payment_method)
|
||||
|
||||
|
||||
@@ -121,10 +107,6 @@ 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 = ""
|
||||
charge: stripe.Charge
|
||||
@@ -141,50 +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_customer_does_not_have_active_plan(payment_intent.customer)
|
||||
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="Cloud Standard Credit",
|
||||
statement_descriptor=CustomerPlan.name_from_tier(plan_tier).replace("Zulip ", "")
|
||||
+ " Credit",
|
||||
)
|
||||
stripe.Invoice.finalize_invoice(stripe_invoice)
|
||||
raise e
|
||||
|
||||
billing_session = RealmBillingSession(user)
|
||||
billing_session.process_initial_upgrade(
|
||||
CustomerPlan.STANDARD,
|
||||
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:
|
||||
assert stripe_payment_intent.last_payment_error is not 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,16 +1,58 @@
|
||||
from dataclasses import dataclass
|
||||
from decimal import Decimal
|
||||
from typing import Optional
|
||||
from typing import Optional, TypedDict
|
||||
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 RealmBillingSession
|
||||
from corporate.models import get_customer_by_realm
|
||||
from zerver.models import Realm, UserProfile, get_realm
|
||||
from corporate.lib.stripe import BillingSession
|
||||
from corporate.models import (
|
||||
Customer,
|
||||
CustomerPlan,
|
||||
ZulipSponsorshipRequest,
|
||||
get_current_plan_by_customer,
|
||||
)
|
||||
from zerver.models import Realm, get_org_type_display_name, get_realm
|
||||
from zilencer.lib.remote_counts import MissingDataError
|
||||
|
||||
|
||||
def get_support_url(realm: Realm) -> str:
|
||||
class SponsorshipRequestDict(TypedDict):
|
||||
org_type: str
|
||||
org_website: str
|
||||
org_description: str
|
||||
total_users: str
|
||||
paid_users: str
|
||||
paid_users_description: str
|
||||
requested_plan: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class SponsorshipData:
|
||||
sponsorship_pending: bool = False
|
||||
default_discount: Optional[Decimal] = None
|
||||
latest_sponsorship_request: Optional[SponsorshipRequestDict] = None
|
||||
|
||||
|
||||
@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
|
||||
|
||||
|
||||
@dataclass
|
||||
class SupportData:
|
||||
plan_data: PlanData
|
||||
sponsorship_data: SponsorshipData
|
||||
|
||||
|
||||
def get_realm_support_url(realm: Realm) -> str:
|
||||
support_realm_uri = get_realm(settings.STAFF_SUBDOMAIN).uri
|
||||
support_url = urljoin(
|
||||
support_realm_uri,
|
||||
@@ -19,32 +61,87 @@ def get_support_url(realm: Realm) -> str:
|
||||
return support_url
|
||||
|
||||
|
||||
def get_discount_for_realm(realm: Realm) -> Optional[Decimal]:
|
||||
customer = get_customer_by_realm(realm)
|
||||
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_customer_sponsorship_data(customer: Customer) -> SponsorshipData:
|
||||
pending = customer.sponsorship_pending
|
||||
discount = customer.default_discount
|
||||
sponsorship_request = None
|
||||
if pending:
|
||||
last_sponsorship_request = (
|
||||
ZulipSponsorshipRequest.objects.filter(customer=customer).order_by("id").last()
|
||||
)
|
||||
if last_sponsorship_request is not None:
|
||||
org_type_name = get_org_type_display_name(last_sponsorship_request.org_type)
|
||||
if (
|
||||
last_sponsorship_request.org_website is None
|
||||
or last_sponsorship_request.org_website == ""
|
||||
):
|
||||
website = "No website submitted"
|
||||
else:
|
||||
website = last_sponsorship_request.org_website
|
||||
sponsorship_request = SponsorshipRequestDict(
|
||||
org_type=org_type_name,
|
||||
org_website=website,
|
||||
org_description=last_sponsorship_request.org_description,
|
||||
total_users=last_sponsorship_request.expected_total_users,
|
||||
paid_users=last_sponsorship_request.paid_users_count,
|
||||
paid_users_description=last_sponsorship_request.paid_users_description,
|
||||
requested_plan=last_sponsorship_request.requested_plan,
|
||||
)
|
||||
|
||||
return SponsorshipData(
|
||||
sponsorship_pending=pending,
|
||||
default_discount=discount,
|
||||
latest_sponsorship_request=sponsorship_request,
|
||||
)
|
||||
|
||||
|
||||
def get_current_plan_data_for_support_view(billing_session: BillingSession) -> PlanData:
|
||||
customer = billing_session.get_customer()
|
||||
plan = None
|
||||
if customer is not None:
|
||||
return customer.default_discount
|
||||
return 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
|
||||
|
||||
|
||||
def attach_discount_to_realm(realm: Realm, discount: Decimal, *, acting_user: UserProfile) -> None:
|
||||
billing_session = RealmBillingSession(acting_user, realm)
|
||||
billing_session.attach_discount_to_customer(discount)
|
||||
def get_data_for_support_view(billing_session: BillingSession) -> SupportData:
|
||||
plan_data = get_current_plan_data_for_support_view(billing_session)
|
||||
customer = billing_session.get_customer()
|
||||
if customer is not None:
|
||||
sponsorship_data = get_customer_sponsorship_data(customer)
|
||||
else:
|
||||
sponsorship_data = SponsorshipData()
|
||||
|
||||
|
||||
def approve_realm_sponsorship(realm: Realm, *, acting_user: UserProfile) -> None:
|
||||
billing_session = RealmBillingSession(acting_user, realm)
|
||||
billing_session.approve_sponsorship()
|
||||
|
||||
|
||||
def update_realm_sponsorship_status(
|
||||
realm: Realm, sponsorship_pending: bool, *, acting_user: UserProfile
|
||||
) -> None:
|
||||
billing_session = RealmBillingSession(acting_user, realm)
|
||||
billing_session.update_customer_sponsorship_status(sponsorship_pending)
|
||||
|
||||
|
||||
def update_realm_billing_method(
|
||||
realm: Realm, charge_automatically: bool, *, acting_user: UserProfile
|
||||
) -> None:
|
||||
billing_session = RealmBillingSession(acting_user, realm)
|
||||
billing_session.update_billing_method_of_current_plan(charge_automatically)
|
||||
return SupportData(
|
||||
plan_data=plan_data,
|
||||
sponsorship_data=sponsorship_data,
|
||||
)
|
||||
|
||||
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,10 +35,13 @@ 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",
|
||||
)
|
||||
]
|
||||
|
||||
@@ -49,6 +57,14 @@ 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)
|
||||
|
||||
@@ -91,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]:
|
||||
@@ -121,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()
|
||||
@@ -167,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
|
||||
@@ -214,11 +224,11 @@ 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 = {
|
||||
ANNUAL: "Annual",
|
||||
MONTHLY: "Monthly",
|
||||
BILLING_SCHEDULE_ANNUAL: "Annual",
|
||||
BILLING_SCHEDULE_MONTHLY: "Monthly",
|
||||
}
|
||||
billing_schedule = models.SmallIntegerField()
|
||||
|
||||
@@ -239,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
|
||||
@@ -267,19 +289,37 @@ class CustomerPlan(models.Model):
|
||||
# TODO maybe override setattr to ensure billing_cycle_anchor, etc
|
||||
# are immutable.
|
||||
|
||||
@override
|
||||
def __str__(self) -> str:
|
||||
return f"{self.name} (status: {self.get_plan_status_as_text()})"
|
||||
|
||||
@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 (legacy plan)",
|
||||
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]
|
||||
@@ -290,7 +330,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
|
||||
@@ -347,9 +390,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"],
|
||||
@@ -363,3 +413,9 @@ class ZulipSponsorshipRequest(models.Model):
|
||||
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,
|
||||
)
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"plan_tier": "1",
|
||||
"price_per_license": "1200",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
@@ -63,7 +64,7 @@
|
||||
},
|
||||
"paid": true,
|
||||
"payment_intent": "pi_NORMALIZED00000000000001",
|
||||
"payment_method": "pm_1OAbiyDEQaroqDjs3ViUEwAQ",
|
||||
"payment_method": "pm_1OIlcUDEQaroqDjsqDT70KqK",
|
||||
"payment_method_details": {
|
||||
"card": {
|
||||
"amount_authorized": 7200,
|
||||
@@ -74,7 +75,7 @@
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 11,
|
||||
"exp_month": 12,
|
||||
"exp_year": 2024,
|
||||
"extended_authorization": {
|
||||
"status": "disabled"
|
||||
@@ -103,9 +104,10 @@
|
||||
},
|
||||
"type": "card"
|
||||
},
|
||||
"radar_options": {},
|
||||
"receipt_email": "hamlet@zulip.com",
|
||||
"receipt_number": null,
|
||||
"receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKLmktKoGMgYrcqQJ_XQ6LBZLSpoFwx3AcKTCrmps2vSpTYEuUPpKK37EcqScvxgnj4SR9xDWiSPE9-Ni",
|
||||
"receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKIr9qqsGMgaM-GKNpmc6LBZoWb7DJvCIVhczLJKOYXKROrzmBYTFtupIgmreHcTL1xLwXB0pQP-R7gBA",
|
||||
"refunded": false,
|
||||
"refunds": {
|
||||
"data": [],
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"plan_tier": "1",
|
||||
"price_per_license": "6000",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
@@ -63,7 +64,7 @@
|
||||
},
|
||||
"paid": true,
|
||||
"payment_intent": "pi_NORMALIZED00000000000002",
|
||||
"payment_method": "pm_1OAbjHDEQaroqDjsFfj8byC8",
|
||||
"payment_method": "pm_1OIlceDEQaroqDjshc2Y2l9b",
|
||||
"payment_method_details": {
|
||||
"card": {
|
||||
"amount_authorized": 36000,
|
||||
@@ -74,7 +75,7 @@
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 11,
|
||||
"exp_month": 12,
|
||||
"exp_year": 2024,
|
||||
"extended_authorization": {
|
||||
"status": "disabled"
|
||||
@@ -103,9 +104,10 @@
|
||||
},
|
||||
"type": "card"
|
||||
},
|
||||
"radar_options": {},
|
||||
"receipt_email": "hamlet@zulip.com",
|
||||
"receipt_number": null,
|
||||
"receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKMyktKoGMgY7jXPALx46LBZ93Aicbpv_SAI_VTk6csq3v1o-6Isr2CHYie17adWgts9dL_uZ8bLzxthw",
|
||||
"receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKJT9qqsGMgbmGcE2CPg6LBYt6tPCI7CnKaxaLVq3zjSaM7atoyWnbp6xDOd4JEAbIIuFCeKskEzYWUyb",
|
||||
"refunded": false,
|
||||
"refunds": {
|
||||
"data": [],
|
||||
@@ -166,6 +168,7 @@
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"plan_tier": "1",
|
||||
"price_per_license": "1200",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
@@ -187,7 +190,7 @@
|
||||
},
|
||||
"paid": true,
|
||||
"payment_intent": "pi_NORMALIZED00000000000001",
|
||||
"payment_method": "pm_1OAbiyDEQaroqDjs3ViUEwAQ",
|
||||
"payment_method": "pm_1OIlcUDEQaroqDjsqDT70KqK",
|
||||
"payment_method_details": {
|
||||
"card": {
|
||||
"amount_authorized": 7200,
|
||||
@@ -198,7 +201,7 @@
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 11,
|
||||
"exp_month": 12,
|
||||
"exp_year": 2024,
|
||||
"extended_authorization": {
|
||||
"status": "disabled"
|
||||
@@ -227,9 +230,10 @@
|
||||
},
|
||||
"type": "card"
|
||||
},
|
||||
"radar_options": {},
|
||||
"receipt_email": "hamlet@zulip.com",
|
||||
"receipt_number": null,
|
||||
"receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKMyktKoGMgYMbX-GnOM6LBagBjW6OMx9HAU5uMfOZ8snKne1PHYDc42XAxy7IdyNE7BH38b7vW-rIqLk",
|
||||
"receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKJT9qqsGMgZmMGKxY746LBarTbqnnWLLGRzmrQAWL3_ig-D1uUENWBVpjxcDGfuFmMRWLxqSgEkXJuqq",
|
||||
"refunded": false,
|
||||
"refunds": {
|
||||
"data": [],
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"invoice_prefix": "NORMA01",
|
||||
"invoice_settings": {
|
||||
"custom_fields": null,
|
||||
"default_payment_method": "pm_1OAbiyDEQaroqDjs3ViUEwAQ",
|
||||
"default_payment_method": "pm_1OIlcUDEQaroqDjsqDT70KqK",
|
||||
"footer": null,
|
||||
"rendering_options": null
|
||||
},
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"invoice_prefix": "NORMA01",
|
||||
"invoice_settings": {
|
||||
"custom_fields": null,
|
||||
"default_payment_method": "pm_1OAbjHDEQaroqDjsFfj8byC8",
|
||||
"default_payment_method": "pm_1OIlceDEQaroqDjshc2Y2l9b",
|
||||
"footer": null,
|
||||
"rendering_options": 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": 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,83 +5,53 @@
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"amount": 6400,
|
||||
"amount_capturable": 0,
|
||||
"amount_details": {
|
||||
"tip": {}
|
||||
},
|
||||
"amount_received": 0,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"automatic_payment_methods": null,
|
||||
"canceled_at": 1000000000,
|
||||
"cancellation_reason": "void_invoice",
|
||||
"capture_method": "automatic",
|
||||
"charges": {
|
||||
"data": [],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 0,
|
||||
"url": "/v1/charges?payment_intent=pi_NORMALIZED00000000000003"
|
||||
},
|
||||
"client_secret": "pi_NORMALIZED00000000000003_secret_fYThlYzmA6ZihKmrZLnmWcTvW",
|
||||
"confirmation_method": "automatic",
|
||||
"address": null,
|
||||
"balance": 0,
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"customer": "cus_NORMALIZED0002",
|
||||
"description": "Payment for Invoice",
|
||||
"id": "pi_NORMALIZED00000000000003",
|
||||
"invoice": "in_NORMALIZED00000000000001",
|
||||
"last_payment_error": null,
|
||||
"latest_charge": null,
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"next_action": null,
|
||||
"object": "payment_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": null,
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"installments": null,
|
||||
"mandate_options": null,
|
||||
"network": null,
|
||||
"request_three_d_secure": "automatic"
|
||||
},
|
||||
"cashapp": {},
|
||||
"wechat_pay": {
|
||||
"app_id": null,
|
||||
"client": null
|
||||
}
|
||||
"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": "pm_1OIlcUDEQaroqDjsqDT70KqK",
|
||||
"footer": null,
|
||||
"rendering_options": null
|
||||
},
|
||||
"payment_method_types": [
|
||||
"ach_credit_transfer",
|
||||
"card",
|
||||
"cashapp",
|
||||
"wechat_pay"
|
||||
],
|
||||
"processing": null,
|
||||
"receipt_email": "king@lear.org",
|
||||
"review": null,
|
||||
"setup_future_usage": null,
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip"
|
||||
},
|
||||
"name": null,
|
||||
"next_invoice_sequence": 1,
|
||||
"object": "customer",
|
||||
"phone": null,
|
||||
"preferred_locales": [],
|
||||
"shipping": null,
|
||||
"source": null,
|
||||
"statement_descriptor": "Zulip Cloud Standard",
|
||||
"statement_descriptor_suffix": null,
|
||||
"status": "canceled",
|
||||
"transfer_data": null,
|
||||
"transfer_group": null
|
||||
"tax_exempt": "none",
|
||||
"test_clock": null
|
||||
},
|
||||
"previous_attributes": {
|
||||
"invoice_settings": {
|
||||
"default_payment_method": null
|
||||
}
|
||||
}
|
||||
},
|
||||
"id": "evt_3OAbimDEQaroqDjs0BaEBsNX",
|
||||
"id": "evt_1OIlcWDEQaroqDjsDYC5kGA8",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0001",
|
||||
"idempotency_key": "25effa1f-8fed-45ea-a660-fd0b33abc23c"
|
||||
"idempotency_key": "ec0d8ceb-bc0b-4141-9ecf-9f91d42f5a7e"
|
||||
},
|
||||
"type": "payment_intent.canceled"
|
||||
"type": "customer.updated"
|
||||
}
|
||||
],
|
||||
"has_more": true,
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"plan_tier": "1",
|
||||
"price_per_license": "1200",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
@@ -82,7 +83,7 @@
|
||||
},
|
||||
"paid": true,
|
||||
"payment_intent": "pi_NORMALIZED00000000000001",
|
||||
"payment_method": "pm_1OAbiyDEQaroqDjs3ViUEwAQ",
|
||||
"payment_method": "pm_1OIlcUDEQaroqDjsqDT70KqK",
|
||||
"payment_method_details": {
|
||||
"card": {
|
||||
"amount_authorized": 7200,
|
||||
@@ -93,7 +94,7 @@
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 11,
|
||||
"exp_month": 12,
|
||||
"exp_year": 2024,
|
||||
"extended_authorization": {
|
||||
"status": "disabled"
|
||||
@@ -122,9 +123,10 @@
|
||||
},
|
||||
"type": "card"
|
||||
},
|
||||
"radar_options": {},
|
||||
"receipt_email": "hamlet@zulip.com",
|
||||
"receipt_number": null,
|
||||
"receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKLKktKoGMgZfETNIDN86LBY50xSk957U6AlRoP5-YOxSRkjaDyWZxvhpX5Lq7EfiLZlknEWX_xe2Db-Q",
|
||||
"receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKIf9qqsGMgZb20Gi7do6LBb8Nk4YXcMYuHylkNS09JAb63jzjtrknnoa60TiX-hHWdshgcroMLKDWN5c",
|
||||
"refunded": false,
|
||||
"refunds": {
|
||||
"data": [],
|
||||
@@ -149,7 +151,7 @@
|
||||
"total_count": 1,
|
||||
"url": "/v1/charges?payment_intent=pi_NORMALIZED00000000000001"
|
||||
},
|
||||
"client_secret": "pi_NORMALIZED00000000000001_secret_U9fLWaQ5foMLX6li0E7nIl4wX",
|
||||
"client_secret": "pi_NORMALIZED00000000000001_secret_TT71wq3meHmzTEd7mpZbqrDnP",
|
||||
"confirmation_method": "automatic",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
@@ -165,6 +167,7 @@
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"plan_tier": "1",
|
||||
"price_per_license": "1200",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
@@ -176,7 +179,7 @@
|
||||
"next_action": null,
|
||||
"object": "payment_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": "pm_1OAbiyDEQaroqDjs3ViUEwAQ",
|
||||
"payment_method": "pm_1OIlcUDEQaroqDjsqDT70KqK",
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
@@ -202,13 +205,13 @@
|
||||
"transfer_group": null
|
||||
}
|
||||
},
|
||||
"id": "evt_3OAbiwDEQaroqDjs1KG0PpkK",
|
||||
"id": "evt_3OIlcYDEQaroqDjs16WfiUYV",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"pending_webhooks": 2,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0002",
|
||||
"idempotency_key": "a6fbc05f-71a7-41dd-89d9-d83491088de5"
|
||||
"idempotency_key": "89f4d29d-4c41-4c1d-baf7-b33a1c7d25ff"
|
||||
},
|
||||
"type": "payment_intent.succeeded"
|
||||
},
|
||||
@@ -258,6 +261,7 @@
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"plan_tier": "1",
|
||||
"price_per_license": "1200",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
@@ -279,7 +283,7 @@
|
||||
},
|
||||
"paid": true,
|
||||
"payment_intent": "pi_NORMALIZED00000000000001",
|
||||
"payment_method": "pm_1OAbiyDEQaroqDjs3ViUEwAQ",
|
||||
"payment_method": "pm_1OIlcUDEQaroqDjsqDT70KqK",
|
||||
"payment_method_details": {
|
||||
"card": {
|
||||
"amount_authorized": 7200,
|
||||
@@ -290,7 +294,7 @@
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 11,
|
||||
"exp_month": 12,
|
||||
"exp_year": 2024,
|
||||
"extended_authorization": {
|
||||
"status": "disabled"
|
||||
@@ -319,9 +323,10 @@
|
||||
},
|
||||
"type": "card"
|
||||
},
|
||||
"radar_options": {},
|
||||
"receipt_email": "hamlet@zulip.com",
|
||||
"receipt_number": null,
|
||||
"receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKLKktKoGMgYmLI2wbBc6LBayDyiusyUGbOxDSVFnS4jnIBbaP5HhJCOa-jwmTSISDTAtkNQlQs2ntZKo",
|
||||
"receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKIf9qqsGMgaRG54HB6k6LBYbdkPPJRe4ZuuV5tR6SrHKPTGj9DFYvf8ZlOiAmw8lVKk8NDaGGFlsjRM8",
|
||||
"refunded": false,
|
||||
"refunds": {
|
||||
"data": [],
|
||||
@@ -341,412 +346,15 @@
|
||||
"transfer_group": null
|
||||
}
|
||||
},
|
||||
"id": "evt_3OAbiwDEQaroqDjs1MgkdMZv",
|
||||
"id": "evt_3OIlcYDEQaroqDjs1OA8t8hC",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0002",
|
||||
"idempotency_key": "a6fbc05f-71a7-41dd-89d9-d83491088de5"
|
||||
"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_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_1OAbiyDEQaroqDjs3ViUEwAQ",
|
||||
"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
|
||||
},
|
||||
"previous_attributes": {
|
||||
"invoice_settings": {
|
||||
"default_payment_method": null
|
||||
}
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbj2DEQaroqDjsdHXrdECt",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0003",
|
||||
"idempotency_key": "ba127619-d57d-424c-bc0d-e1b5d6e75b4f"
|
||||
},
|
||||
"type": "customer.updated"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"application": null,
|
||||
"automatic_payment_methods": null,
|
||||
"cancellation_reason": null,
|
||||
"client_secret": "seti_1OAbiyDEQaroqDjsEnpR1Onp_secret_OyYqFrkey3OlMfxWtyreL2AbO9RHVB4",
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": null,
|
||||
"flow_directions": null,
|
||||
"id": "seti_1OAbiyDEQaroqDjsEnpR1Onp",
|
||||
"last_setup_error": null,
|
||||
"latest_attempt": "setatt_1OAbiyDEQaroqDjsnLExjW56",
|
||||
"livemode": false,
|
||||
"mandate": null,
|
||||
"metadata": {},
|
||||
"next_action": null,
|
||||
"object": "setup_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": "pm_1OAbiyDEQaroqDjs3ViUEwAQ",
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"mandate_options": null,
|
||||
"network": null,
|
||||
"request_three_d_secure": "automatic"
|
||||
}
|
||||
},
|
||||
"payment_method_types": [
|
||||
"card"
|
||||
],
|
||||
"single_use_mandate": null,
|
||||
"status": "succeeded",
|
||||
"usage": "off_session"
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbizDEQaroqDjsMSKWCeS4",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0004",
|
||||
"idempotency_key": "b367784c-9178-4e50-ad4b-33271f44771f"
|
||||
},
|
||||
"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": 11,
|
||||
"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_1OAbiyDEQaroqDjs3ViUEwAQ",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "payment_method",
|
||||
"type": "card"
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbizDEQaroqDjs7C1ESMag",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0004",
|
||||
"idempotency_key": "b367784c-9178-4e50-ad4b-33271f44771f"
|
||||
},
|
||||
"type": "payment_method.attached"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"application": null,
|
||||
"automatic_payment_methods": null,
|
||||
"cancellation_reason": null,
|
||||
"client_secret": "seti_1OAbiyDEQaroqDjsEnpR1Onp_secret_OyYqFrkey3OlMfxWtyreL2AbO9RHVB4",
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": null,
|
||||
"flow_directions": null,
|
||||
"id": "seti_1OAbiyDEQaroqDjsEnpR1Onp",
|
||||
"last_setup_error": null,
|
||||
"latest_attempt": "setatt_1OAbiyDEQaroqDjsnLExjW56",
|
||||
"livemode": false,
|
||||
"mandate": null,
|
||||
"metadata": {},
|
||||
"next_action": null,
|
||||
"object": "setup_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": "pm_1OAbiyDEQaroqDjs3ViUEwAQ",
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"mandate_options": null,
|
||||
"network": null,
|
||||
"request_three_d_secure": "automatic"
|
||||
}
|
||||
},
|
||||
"payment_method_types": [
|
||||
"card"
|
||||
],
|
||||
"single_use_mandate": null,
|
||||
"status": "succeeded",
|
||||
"usage": "off_session"
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbizDEQaroqDjs12Wkj59b",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0004",
|
||||
"idempotency_key": "b367784c-9178-4e50-ad4b-33271f44771f"
|
||||
},
|
||||
"type": "setup_intent.created"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"application": null,
|
||||
"automatic_payment_methods": null,
|
||||
"cancellation_reason": null,
|
||||
"client_secret": "seti_1OAbixDEQaroqDjsZ13bFTzk_secret_OyYqTKT3uNo6hXb6nycNN82HUV4tLVa",
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": null,
|
||||
"flow_directions": null,
|
||||
"id": "seti_1OAbixDEQaroqDjsZ13bFTzk",
|
||||
"last_setup_error": null,
|
||||
"latest_attempt": null,
|
||||
"livemode": false,
|
||||
"mandate": null,
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"payment_method_types": [
|
||||
"card"
|
||||
],
|
||||
"single_use_mandate": null,
|
||||
"status": "requires_payment_method",
|
||||
"usage": "off_session"
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbixDEQaroqDjswQf5925l",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0005",
|
||||
"idempotency_key": "2f531396-87a0-4a7a-85f2-4cbeae89359b"
|
||||
},
|
||||
"type": "setup_intent.created"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"amount": 7200,
|
||||
"amount_capturable": 0,
|
||||
"amount_details": {
|
||||
"tip": {}
|
||||
},
|
||||
"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_U9fLWaQ5foMLX6li0E7nIl4wX",
|
||||
"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,
|
||||
"latest_charge": 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_configuration_details": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"installments": null,
|
||||
"mandate_options": null,
|
||||
"network": null,
|
||||
"request_three_d_secure": "automatic"
|
||||
}
|
||||
},
|
||||
"payment_method_types": [
|
||||
"card"
|
||||
],
|
||||
"processing": null,
|
||||
"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_3OAbiwDEQaroqDjs19zAFXo5",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0006",
|
||||
"idempotency_key": "dcb3c560-eb12-48b6-a8b1-c3781dc8dc47"
|
||||
},
|
||||
"type": "payment_intent.created"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"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": null,
|
||||
"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
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbivDEQaroqDjsBYwBWKGq",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0007",
|
||||
"idempotency_key": "d7e3039e-deb3-4b01-b0d4-cb3365326a0e"
|
||||
},
|
||||
"type": "customer.created"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
|
||||
@@ -46,9 +46,9 @@
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlxMmxZbXZoUnVicXBZajdsRFU4azJSWVppaDNSLDkwMDkwNTUy0200wEanKwxF?s=ap",
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlxMmxZbXZoUnVicXBZajdsRFU4azJSWVppaDNSLDkwMDkwNTUy0200wEanKwxF/pdf?s=ap",
|
||||
"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": {
|
||||
@@ -67,8 +67,8 @@
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
"end": 1357095845,
|
||||
"start": 1325473445
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
@@ -157,7 +157,7 @@
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000001/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
@@ -210,230 +210,7 @@
|
||||
"total_excluding_tax": 0,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": 1000000000
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbjADEQaroqDjswTbvBGJ7",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 2,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0008",
|
||||
"idempotency_key": "da0bb2e0-e63b-4ef2-8190-e4a898a67895"
|
||||
},
|
||||
"type": "invoice.finalized"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"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_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlxMmxZbXZoUnVicXBZajdsRFU4azJSWVppaDNSLDkwMDkwNTUx0200otAxmBG3?s=ap",
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlxMmxZbXZoUnVicXBZajdsRFU4azJSWVppaDNSLDkwMDkwNTUx0200otAxmBG3/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": 1000000000,
|
||||
"start": 1000000000
|
||||
},
|
||||
"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_NORMALIZED00000000000002/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"next_payment_attempt": null,
|
||||
"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
|
||||
},
|
||||
"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
|
||||
"webhooks_delivered_at": null
|
||||
},
|
||||
"previous_attributes": {
|
||||
"attempted": false,
|
||||
@@ -457,13 +234,13 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbjADEQaroqDjsSI8lFXJv",
|
||||
"id": "evt_1OIlcbDEQaroqDjs0RgNo7tS",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"pending_webhooks": 2,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0008",
|
||||
"idempotency_key": "da0bb2e0-e63b-4ef2-8190-e4a898a67895"
|
||||
"id": "req_NORMALIZED0003",
|
||||
"idempotency_key": "d8040535-2a29-417e-a8cd-313f534cb633"
|
||||
},
|
||||
"type": "invoice.updated"
|
||||
},
|
||||
@@ -514,7 +291,7 @@
|
||||
"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,
|
||||
@@ -534,8 +311,8 @@
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
"end": 1357095845,
|
||||
"start": 1325473445
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
@@ -624,7 +401,7 @@
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000001/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
@@ -680,13 +457,13 @@
|
||||
"webhooks_delivered_at": null
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbj8DEQaroqDjskFTdkB1y",
|
||||
"id": "evt_1OIlcaDEQaroqDjsgW8xhHxB",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0009",
|
||||
"idempotency_key": "54d61ab3-cd30-4b7a-ad40-0dce334dd232"
|
||||
"id": "req_NORMALIZED0004",
|
||||
"idempotency_key": "e1bdf299-f588-4704-ae2c-82d0debf6534"
|
||||
},
|
||||
"type": "invoice.created"
|
||||
},
|
||||
@@ -708,8 +485,8 @@
|
||||
"metadata": {},
|
||||
"object": "invoiceitem",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
"end": 1357095845,
|
||||
"start": 1325473445
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
@@ -742,13 +519,13 @@
|
||||
"unit_amount_decimal": "1200"
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbj7DEQaroqDjs4SWJFkYg",
|
||||
"id": "evt_1OIlcaDEQaroqDjsCma6I5rr",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0010",
|
||||
"idempotency_key": "2ae230b6-12fb-4c3a-b8b7-6ecd041a313c"
|
||||
"id": "req_NORMALIZED0005",
|
||||
"idempotency_key": "cfb4b441-f25a-4d95-a2f0-f0f950bd40fe"
|
||||
},
|
||||
"type": "invoiceitem.created"
|
||||
},
|
||||
@@ -804,13 +581,13 @@
|
||||
"unit_amount_decimal": "-7200"
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbj5DEQaroqDjsNe3rtI3x",
|
||||
"id": "evt_1OIlcZDEQaroqDjs6GyIO3FO",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0011",
|
||||
"idempotency_key": "22eeb342-33df-4bcb-8750-7c8649ef72e3"
|
||||
"id": "req_NORMALIZED0006",
|
||||
"idempotency_key": "13255827-b4d3-42fe-9f18-fbcb67305a04"
|
||||
},
|
||||
"type": "invoiceitem.created"
|
||||
},
|
||||
@@ -833,7 +610,7 @@
|
||||
"invoice_prefix": "NORMA01",
|
||||
"invoice_settings": {
|
||||
"custom_fields": null,
|
||||
"default_payment_method": "pm_1OAbiyDEQaroqDjs3ViUEwAQ",
|
||||
"default_payment_method": "pm_1OIlcUDEQaroqDjsqDT70KqK",
|
||||
"footer": null,
|
||||
"rendering_options": null
|
||||
},
|
||||
@@ -856,13 +633,13 @@
|
||||
"default_currency": null
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbj5DEQaroqDjsGpvAlLYX",
|
||||
"id": "evt_1OIlcZDEQaroqDjs2IZnZELZ",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0011",
|
||||
"idempotency_key": "22eeb342-33df-4bcb-8750-7c8649ef72e3"
|
||||
"id": "req_NORMALIZED0006",
|
||||
"idempotency_key": "13255827-b4d3-42fe-9f18-fbcb67305a04"
|
||||
},
|
||||
"type": "customer.updated"
|
||||
}
|
||||
|
||||
@@ -46,9 +46,9 @@
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlxMmxZbXZoUnVicXBZajdsRFU4azJSWVppaDNSLDkwMDkwNTUy0200wEanKwxF?s=ap",
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlxMmxZbXZoUnVicXBZajdsRFU4azJSWVppaDNSLDkwMDkwNTUy0200wEanKwxF/pdf?s=ap",
|
||||
"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": {
|
||||
@@ -67,8 +67,8 @@
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
"end": 1357095845,
|
||||
"start": 1325473445
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
@@ -157,7 +157,7 @@
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000001/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
@@ -210,16 +210,16 @@
|
||||
"total_excluding_tax": 0,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": 1000000000
|
||||
"webhooks_delivered_at": null
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbjADEQaroqDjsRFLyV68r",
|
||||
"id": "evt_1OIlccDEQaroqDjsArfDmoTy",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"pending_webhooks": 2,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0008",
|
||||
"idempotency_key": "da0bb2e0-e63b-4ef2-8190-e4a898a67895"
|
||||
"id": "req_NORMALIZED0003",
|
||||
"idempotency_key": "d8040535-2a29-417e-a8cd-313f534cb633"
|
||||
},
|
||||
"type": "invoice.payment_succeeded"
|
||||
},
|
||||
@@ -269,9 +269,9 @@
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlxMmxZbXZoUnVicXBZajdsRFU4azJSWVppaDNSLDkwMDkwNTUy0200wEanKwxF?s=ap",
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlxMmxZbXZoUnVicXBZajdsRFU4azJSWVppaDNSLDkwMDkwNTUy0200wEanKwxF/pdf?s=ap",
|
||||
"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": {
|
||||
@@ -290,8 +290,8 @@
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
"end": 1357095845,
|
||||
"start": 1325473445
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
@@ -380,7 +380,7 @@
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000001/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
@@ -433,18 +433,241 @@
|
||||
"total_excluding_tax": 0,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": 1000000000
|
||||
"webhooks_delivered_at": null
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbjADEQaroqDjsHfm4lKFu",
|
||||
"id": "evt_1OIlcbDEQaroqDjsn0Gh2ZXB",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 1,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0003",
|
||||
"idempotency_key": "d8040535-2a29-417e-a8cd-313f534cb633"
|
||||
},
|
||||
"type": "invoice.paid"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"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_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_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": null
|
||||
}
|
||||
},
|
||||
"id": "evt_1OIlcbDEQaroqDjshdrWm9Tg",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0008",
|
||||
"idempotency_key": "da0bb2e0-e63b-4ef2-8190-e4a898a67895"
|
||||
"id": "req_NORMALIZED0003",
|
||||
"idempotency_key": "d8040535-2a29-417e-a8cd-313f534cb633"
|
||||
},
|
||||
"type": "invoice.paid"
|
||||
"type": "invoice.finalized"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
|
||||
@@ -5,223 +5,53 @@
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"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",
|
||||
"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,
|
||||
"effective_at": 1000000000,
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlxMmxZbXZoUnVicXBZajdsRFU4azJSWVppaDNSLDkwMDkwNTUy0200wEanKwxF?s=ap",
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlxMmxZbXZoUnVicXBZajdsRFU4azJSWVppaDNSLDkwMDkwNTUy0200wEanKwxF/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": 1000000000,
|
||||
"start": 1000000000
|
||||
},
|
||||
"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_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-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
|
||||
"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,
|
||||
"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
|
||||
"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_1OAbjADEQaroqDjsRFLyV68r",
|
||||
"id": "evt_1OIlcgDEQaroqDjsPE8wVcBq",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0008",
|
||||
"idempotency_key": "da0bb2e0-e63b-4ef2-8190-e4a898a67895"
|
||||
"id": "req_NORMALIZED0007",
|
||||
"idempotency_key": "6e41d51b-0e25-4d1f-9da2-4472878eb45f"
|
||||
},
|
||||
"type": "invoice.payment_succeeded"
|
||||
"type": "customer.updated"
|
||||
}
|
||||
],
|
||||
"has_more": true,
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"plan_tier": "1",
|
||||
"price_per_license": "6000",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
@@ -82,7 +83,7 @@
|
||||
},
|
||||
"paid": true,
|
||||
"payment_intent": "pi_NORMALIZED00000000000002",
|
||||
"payment_method": "pm_1OAbjHDEQaroqDjsFfj8byC8",
|
||||
"payment_method": "pm_1OIlceDEQaroqDjshc2Y2l9b",
|
||||
"payment_method_details": {
|
||||
"card": {
|
||||
"amount_authorized": 36000,
|
||||
@@ -93,7 +94,7 @@
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 11,
|
||||
"exp_month": 12,
|
||||
"exp_year": 2024,
|
||||
"extended_authorization": {
|
||||
"status": "disabled"
|
||||
@@ -122,9 +123,10 @@
|
||||
},
|
||||
"type": "card"
|
||||
},
|
||||
"radar_options": {},
|
||||
"receipt_email": "hamlet@zulip.com",
|
||||
"receipt_number": null,
|
||||
"receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKMWktKoGMgbBejqty7k6LBay1D-S4hg39Q9UDIOGUp79dAR3ZWzowgod2EPK3yoyXY0CYXWsROxc7cuw",
|
||||
"receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKJH9qqsGMgbQjtDZqQM6LBZPz4stEfKrXRPEFZYCyclDAo2Dez80I8lUHYTVeT16LQpU7Ou6wGCFugiR",
|
||||
"refunded": false,
|
||||
"refunds": {
|
||||
"data": [],
|
||||
@@ -149,7 +151,7 @@
|
||||
"total_count": 1,
|
||||
"url": "/v1/charges?payment_intent=pi_NORMALIZED00000000000002"
|
||||
},
|
||||
"client_secret": "pi_NORMALIZED00000000000002_secret_IM9QK0XPBRsrtvMFpF1HVQGr3",
|
||||
"client_secret": "pi_NORMALIZED00000000000002_secret_6P4eLudA3uvQYCOoNiDTkNQEI",
|
||||
"confirmation_method": "automatic",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
@@ -165,6 +167,7 @@
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"plan_tier": "1",
|
||||
"price_per_license": "6000",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
@@ -176,7 +179,7 @@
|
||||
"next_action": null,
|
||||
"object": "payment_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": "pm_1OAbjHDEQaroqDjsFfj8byC8",
|
||||
"payment_method": "pm_1OIlceDEQaroqDjshc2Y2l9b",
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
@@ -202,13 +205,13 @@
|
||||
"transfer_group": null
|
||||
}
|
||||
},
|
||||
"id": "evt_3OAbjEDEQaroqDjs0Fdo8Gmm",
|
||||
"id": "evt_3OIlciDEQaroqDjs14Vw2Reo",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"pending_webhooks": 2,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0012",
|
||||
"idempotency_key": "ead047f4-390c-4143-bca4-b560cb2c76af"
|
||||
"id": "req_NORMALIZED0008",
|
||||
"idempotency_key": "f7ce8212-6677-40df-912b-4ac6c3765065"
|
||||
},
|
||||
"type": "payment_intent.succeeded"
|
||||
},
|
||||
@@ -258,6 +261,7 @@
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"plan_tier": "1",
|
||||
"price_per_license": "6000",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
@@ -279,7 +283,7 @@
|
||||
},
|
||||
"paid": true,
|
||||
"payment_intent": "pi_NORMALIZED00000000000002",
|
||||
"payment_method": "pm_1OAbjHDEQaroqDjsFfj8byC8",
|
||||
"payment_method": "pm_1OIlceDEQaroqDjshc2Y2l9b",
|
||||
"payment_method_details": {
|
||||
"card": {
|
||||
"amount_authorized": 36000,
|
||||
@@ -290,7 +294,7 @@
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 11,
|
||||
"exp_month": 12,
|
||||
"exp_year": 2024,
|
||||
"extended_authorization": {
|
||||
"status": "disabled"
|
||||
@@ -319,9 +323,10 @@
|
||||
},
|
||||
"type": "card"
|
||||
},
|
||||
"radar_options": {},
|
||||
"receipt_email": "hamlet@zulip.com",
|
||||
"receipt_number": null,
|
||||
"receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKMWktKoGMgYpVepO4vY6LBbu8Gdq5swMUKpN609lyeB_YsbAnOp7XAL-DHUMj7-nEPl0juPLx6Hv11vd",
|
||||
"receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKJH9qqsGMgYqjd-cSvE6LBaZocBeNc1j6HmSljaGjK9coB5-xRAyLYhQxqOON0JTW8MYWAJtnxrRxAiL",
|
||||
"refunded": false,
|
||||
"refunds": {
|
||||
"data": [],
|
||||
@@ -341,364 +346,15 @@
|
||||
"transfer_group": null
|
||||
}
|
||||
},
|
||||
"id": "evt_3OAbjEDEQaroqDjs0Jr4G9pD",
|
||||
"id": "evt_3OIlciDEQaroqDjs1zZA7DlT",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0012",
|
||||
"idempotency_key": "ead047f4-390c-4143-bca4-b560cb2c76af"
|
||||
"id": "req_NORMALIZED0008",
|
||||
"idempotency_key": "f7ce8212-6677-40df-912b-4ac6c3765065"
|
||||
},
|
||||
"type": "charge.succeeded"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"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": "pm_1OAbjHDEQaroqDjsFfj8byC8",
|
||||
"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
|
||||
},
|
||||
"previous_attributes": {
|
||||
"invoice_settings": {
|
||||
"default_payment_method": "pm_1OAbiyDEQaroqDjs3ViUEwAQ"
|
||||
}
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbjJDEQaroqDjsiVYBYR7z",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0013",
|
||||
"idempotency_key": "4ebda7fb-5c3a-4ce9-8abc-9cade78757d3"
|
||||
},
|
||||
"type": "customer.updated"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"application": null,
|
||||
"automatic_payment_methods": null,
|
||||
"cancellation_reason": null,
|
||||
"client_secret": "seti_1OAbjHDEQaroqDjsiyGUfkGg_secret_OyYq1ljcbx3AZiCSK143sZdt7S0n6pN",
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": null,
|
||||
"flow_directions": null,
|
||||
"id": "seti_1OAbjHDEQaroqDjsiyGUfkGg",
|
||||
"last_setup_error": null,
|
||||
"latest_attempt": "setatt_1OAbjHDEQaroqDjswrjSFGn9",
|
||||
"livemode": false,
|
||||
"mandate": null,
|
||||
"metadata": {},
|
||||
"next_action": null,
|
||||
"object": "setup_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": "pm_1OAbjHDEQaroqDjsFfj8byC8",
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"mandate_options": null,
|
||||
"network": null,
|
||||
"request_three_d_secure": "automatic"
|
||||
}
|
||||
},
|
||||
"payment_method_types": [
|
||||
"card"
|
||||
],
|
||||
"single_use_mandate": null,
|
||||
"status": "succeeded",
|
||||
"usage": "off_session"
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbjIDEQaroqDjsAq5yUHSA",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0014",
|
||||
"idempotency_key": "703bb85b-e5cd-4cde-9b55-b712437a5113"
|
||||
},
|
||||
"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": 11,
|
||||
"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_1OAbjHDEQaroqDjsFfj8byC8",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "payment_method",
|
||||
"type": "card"
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbjHDEQaroqDjs5X4eBOmU",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0014",
|
||||
"idempotency_key": "703bb85b-e5cd-4cde-9b55-b712437a5113"
|
||||
},
|
||||
"type": "payment_method.attached"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"application": null,
|
||||
"automatic_payment_methods": null,
|
||||
"cancellation_reason": null,
|
||||
"client_secret": "seti_1OAbjHDEQaroqDjsiyGUfkGg_secret_OyYq1ljcbx3AZiCSK143sZdt7S0n6pN",
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": null,
|
||||
"flow_directions": null,
|
||||
"id": "seti_1OAbjHDEQaroqDjsiyGUfkGg",
|
||||
"last_setup_error": null,
|
||||
"latest_attempt": "setatt_1OAbjHDEQaroqDjswrjSFGn9",
|
||||
"livemode": false,
|
||||
"mandate": null,
|
||||
"metadata": {},
|
||||
"next_action": null,
|
||||
"object": "setup_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": "pm_1OAbjHDEQaroqDjsFfj8byC8",
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"mandate_options": null,
|
||||
"network": null,
|
||||
"request_three_d_secure": "automatic"
|
||||
}
|
||||
},
|
||||
"payment_method_types": [
|
||||
"card"
|
||||
],
|
||||
"single_use_mandate": null,
|
||||
"status": "succeeded",
|
||||
"usage": "off_session"
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbjHDEQaroqDjsj1Jcj4L7",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0014",
|
||||
"idempotency_key": "703bb85b-e5cd-4cde-9b55-b712437a5113"
|
||||
},
|
||||
"type": "setup_intent.created"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"application": null,
|
||||
"automatic_payment_methods": null,
|
||||
"cancellation_reason": null,
|
||||
"client_secret": "seti_1OAbjFDEQaroqDjsOtWXOh3z_secret_OyYqDwZSEotDZcPqC8EEXDlXcWpwH0i",
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": null,
|
||||
"flow_directions": null,
|
||||
"id": "seti_1OAbjFDEQaroqDjsOtWXOh3z",
|
||||
"last_setup_error": null,
|
||||
"latest_attempt": null,
|
||||
"livemode": false,
|
||||
"mandate": null,
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"payment_method_types": [
|
||||
"card"
|
||||
],
|
||||
"single_use_mandate": null,
|
||||
"status": "requires_payment_method",
|
||||
"usage": "off_session"
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbjFDEQaroqDjslF0bckh4",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0015",
|
||||
"idempotency_key": "ab40363f-ed16-49a3-abcb-e0050fe97641"
|
||||
},
|
||||
"type": "setup_intent.created"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"amount": 36000,
|
||||
"amount_capturable": 0,
|
||||
"amount_details": {
|
||||
"tip": {}
|
||||
},
|
||||
"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_IM9QK0XPBRsrtvMFpF1HVQGr3",
|
||||
"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,
|
||||
"latest_charge": 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": null,
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"installments": null,
|
||||
"mandate_options": null,
|
||||
"network": null,
|
||||
"request_three_d_secure": "automatic"
|
||||
}
|
||||
},
|
||||
"payment_method_types": [
|
||||
"card"
|
||||
],
|
||||
"processing": null,
|
||||
"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_3OAbjEDEQaroqDjs04u0RIvp",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0016",
|
||||
"idempotency_key": "5e88c770-f3aa-4e2f-83fd-fa3bfb251535"
|
||||
},
|
||||
"type": "payment_intent.created"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
|
||||
@@ -46,9 +46,9 @@
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlyRHlaT1pCN2U0dG8xY2hwejVidFN6a3ZSMHRuLDkwMDkwNTcw0200rWnYu5C6?s=ap",
|
||||
"id": "in_NORMALIZED00000000000003",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlyRHlaT1pCN2U0dG8xY2hwejVidFN6a3ZSMHRuLDkwMDkwNTcw0200rWnYu5C6/pdf?s=ap",
|
||||
"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": {
|
||||
@@ -157,7 +157,7 @@
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000003/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
@@ -213,459 +213,13 @@
|
||||
"webhooks_delivered_at": null
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbjSDEQaroqDjsSMoBdCTk",
|
||||
"id": "evt_1OIlclDEQaroqDjslxJqiQFY",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"pending_webhooks": 2,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0017",
|
||||
"idempotency_key": "f5b1be17-0d94-4f03-b53e-ca7abb7ea36c"
|
||||
},
|
||||
"type": "invoice.payment_succeeded"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"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_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlyRHlaT1pCN2U0dG8xY2hwejVidFN6a3ZSMHRuLDkwMDkwNTcw0200rWnYu5C6?s=ap",
|
||||
"id": "in_NORMALIZED00000000000003",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlyRHlaT1pCN2U0dG8xY2hwejVidFN6a3ZSMHRuLDkwMDkwNTcw0200rWnYu5C6/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_NORMALIZED00000000000003",
|
||||
"invoice_item": "ii_NORMALIZED00000000000003",
|
||||
"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_NORMALIZED00000000000003",
|
||||
"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": 6000,
|
||||
"unit_amount_decimal": "6000"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"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_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",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"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": -36000,
|
||||
"unit_amount_decimal": "-36000"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "-36000"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000003/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"next_payment_attempt": null,
|
||||
"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
|
||||
},
|
||||
"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": null
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbjSDEQaroqDjsHvqUweFf",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0017",
|
||||
"idempotency_key": "f5b1be17-0d94-4f03-b53e-ca7abb7ea36c"
|
||||
},
|
||||
"type": "invoice.paid"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"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_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlyRHlaT1pCN2U0dG8xY2hwejVidFN6a3ZSMHRuLDkwMDkwNTcw0200rWnYu5C6?s=ap",
|
||||
"id": "in_NORMALIZED00000000000003",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlyRHlaT1pCN2U0dG8xY2hwejVidFN6a3ZSMHRuLDkwMDkwNTcw0200rWnYu5C6/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_NORMALIZED00000000000003",
|
||||
"invoice_item": "ii_NORMALIZED00000000000003",
|
||||
"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_NORMALIZED00000000000003",
|
||||
"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": 6000,
|
||||
"unit_amount_decimal": "6000"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"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_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",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"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": -36000,
|
||||
"unit_amount_decimal": "-36000"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "-36000"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000003/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"next_payment_attempt": null,
|
||||
"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
|
||||
},
|
||||
"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": null
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbjSDEQaroqDjs52kQBIea",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0017",
|
||||
"idempotency_key": "f5b1be17-0d94-4f03-b53e-ca7abb7ea36c"
|
||||
"id": "req_NORMALIZED0009",
|
||||
"idempotency_key": "5fb5bcd9-f037-402f-b67a-6f8eb89f3c11"
|
||||
},
|
||||
"type": "invoice.finalized"
|
||||
},
|
||||
@@ -715,9 +269,9 @@
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlyRHlaT1pCN2U0dG8xY2hwejVidFN6a3ZSMHRuLDkwMDkwNTcw0200rWnYu5C6?s=ap",
|
||||
"id": "in_NORMALIZED00000000000003",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlyRHlaT1pCN2U0dG8xY2hwejVidFN6a3ZSMHRuLDkwMDkwNTcw0200rWnYu5C6/pdf?s=ap",
|
||||
"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": {
|
||||
@@ -826,7 +380,7 @@
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000003/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
@@ -903,13 +457,13 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbjSDEQaroqDjsthbEfwPu",
|
||||
"id": "evt_1OIlclDEQaroqDjsbyHu8WF8",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"pending_webhooks": 1,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0017",
|
||||
"idempotency_key": "f5b1be17-0d94-4f03-b53e-ca7abb7ea36c"
|
||||
"id": "req_NORMALIZED0009",
|
||||
"idempotency_key": "5fb5bcd9-f037-402f-b67a-6f8eb89f3c11"
|
||||
},
|
||||
"type": "invoice.updated"
|
||||
},
|
||||
@@ -960,7 +514,7 @@
|
||||
"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,
|
||||
@@ -1070,7 +624,7 @@
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000003/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
@@ -1126,13 +680,13 @@
|
||||
"webhooks_delivered_at": null
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbjRDEQaroqDjsNjOr65Yz",
|
||||
"id": "evt_1OIlckDEQaroqDjsUsuf3ZOp",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0018",
|
||||
"idempotency_key": "361427f6-9d7d-4641-a46d-57e3878004d6"
|
||||
"id": "req_NORMALIZED0010",
|
||||
"idempotency_key": "a4d2ad76-c98a-446a-8236-ec43f0faf5fa"
|
||||
},
|
||||
"type": "invoice.created"
|
||||
},
|
||||
@@ -1188,13 +742,13 @@
|
||||
"unit_amount_decimal": "6000"
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbjRDEQaroqDjsFxUR9lEq",
|
||||
"id": "evt_1OIlckDEQaroqDjsYzRhmX8V",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0019",
|
||||
"idempotency_key": "d1af4863-6833-4171-81e4-d0d90b29ba5b"
|
||||
"id": "req_NORMALIZED0011",
|
||||
"idempotency_key": "0c11698d-33dd-4270-81bd-05e97ff35e0e"
|
||||
},
|
||||
"type": "invoiceitem.created"
|
||||
},
|
||||
@@ -1250,13 +804,13 @@
|
||||
"unit_amount_decimal": "-36000"
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbjPDEQaroqDjsuOddcwy8",
|
||||
"id": "evt_1OIlcjDEQaroqDjsWfKiiWQ1",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0020",
|
||||
"idempotency_key": "3120bbe1-9648-4af0-a7cb-70ac5bfc04a2"
|
||||
"id": "req_NORMALIZED0012",
|
||||
"idempotency_key": "e0683c69-8080-4a6a-b9e7-7750eba12988"
|
||||
},
|
||||
"type": "invoiceitem.created"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,452 @@
|
||||
{
|
||||
"data": [],
|
||||
"data": [
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"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_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_NORMALIZED00000000000003",
|
||||
"invoice_item": "ii_NORMALIZED00000000000003",
|
||||
"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_NORMALIZED00000000000003",
|
||||
"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": 6000,
|
||||
"unit_amount_decimal": "6000"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"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_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",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"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": -36000,
|
||||
"unit_amount_decimal": "-36000"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "-36000"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"next_payment_attempt": null,
|
||||
"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
|
||||
},
|
||||
"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": null
|
||||
}
|
||||
},
|
||||
"id": "evt_1OIlclDEQaroqDjsYQluU75w",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0009",
|
||||
"idempotency_key": "5fb5bcd9-f037-402f-b67a-6f8eb89f3c11"
|
||||
},
|
||||
"type": "invoice.payment_succeeded"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"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_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_NORMALIZED00000000000003",
|
||||
"invoice_item": "ii_NORMALIZED00000000000003",
|
||||
"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_NORMALIZED00000000000003",
|
||||
"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": 6000,
|
||||
"unit_amount_decimal": "6000"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 6,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"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_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",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"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": -36000,
|
||||
"unit_amount_decimal": "-36000"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "-36000"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"next_payment_attempt": null,
|
||||
"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
|
||||
},
|
||||
"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": null
|
||||
}
|
||||
},
|
||||
"id": "evt_1OIlclDEQaroqDjsWkTK3kjn",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0009",
|
||||
"idempotency_key": "5fb5bcd9-f037-402f-b67a-6f8eb89f3c11"
|
||||
},
|
||||
"type": "invoice.paid"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"url": "/v1/events"
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
"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,
|
||||
@@ -61,8 +61,8 @@
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
"end": 1357095845,
|
||||
"start": 1325473445
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
@@ -151,7 +151,7 @@
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000001/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
"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,
|
||||
@@ -151,7 +151,7 @@
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000003/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
"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,
|
||||
@@ -101,7 +101,7 @@
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 1,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000004/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000003/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
|
||||
@@ -40,9 +40,9 @@
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlxMmxZbXZoUnVicXBZajdsRFU4azJSWVppaDNSLDkwMDkwNTUx0200otAxmBG3?s=ap",
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlxMmxZbXZoUnVicXBZajdsRFU4azJSWVppaDNSLDkwMDkwNTUx0200otAxmBG3/pdf?s=ap",
|
||||
"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": {
|
||||
@@ -61,8 +61,8 @@
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
"end": 1357095845,
|
||||
"start": 1325473445
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
@@ -151,7 +151,7 @@
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000001/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
@@ -204,5 +204,5 @@
|
||||
"total_excluding_tax": 0,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": 1000000000
|
||||
"webhooks_delivered_at": null
|
||||
}
|
||||
|
||||
@@ -40,9 +40,9 @@
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlyRHlaT1pCN2U0dG8xY2hwejVidFN6a3ZSMHRuLDkwMDkwNTcw0200rWnYu5C6?s=ap",
|
||||
"id": "in_NORMALIZED00000000000003",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlyRHlaT1pCN2U0dG8xY2hwejVidFN6a3ZSMHRuLDkwMDkwNTcw0200rWnYu5C6/pdf?s=ap",
|
||||
"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": {
|
||||
@@ -151,7 +151,7 @@
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000003/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
|
||||
@@ -40,9 +40,9 @@
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlyM1ZjWEROSGJMNWtrMHFKNFY5ZW1DekRtM2cxLDkwMDkwNTc3020054DiyClm?s=ap",
|
||||
"id": "in_NORMALIZED00000000000004",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlyM1ZjWEROSGJMNWtrMHFKNFY5ZW1DekRtM2cxLDkwMDkwNTc3020054DiyClm/pdf?s=ap",
|
||||
"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": {
|
||||
@@ -101,7 +101,7 @@
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 1,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000004/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000003/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
@@ -111,7 +111,7 @@
|
||||
"on_behalf_of": null,
|
||||
"paid": false,
|
||||
"paid_out_of_band": false,
|
||||
"payment_intent": "pi_NORMALIZED00000000000004",
|
||||
"payment_intent": "pi_NORMALIZED00000000000003",
|
||||
"payment_settings": {
|
||||
"default_mandate": null,
|
||||
"payment_method_options": null,
|
||||
@@ -154,5 +154,5 @@
|
||||
"total_excluding_tax": 24000,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": 1000000000
|
||||
"webhooks_delivered_at": null
|
||||
}
|
||||
|
||||
@@ -42,9 +42,9 @@
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlxMmxZbXZoUnVicXBZajdsRFU4azJSWVppaDNSLDkwMDkwNTU00200ozOzXCq5?s=ap",
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlxMmxZbXZoUnVicXBZajdsRFU4azJSWVppaDNSLDkwMDkwNTU00200ozOzXCq5/pdf?s=ap",
|
||||
"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": {
|
||||
@@ -63,8 +63,8 @@
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
"end": 1357095845,
|
||||
"start": 1325473445
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
@@ -153,7 +153,7 @@
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000001/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
|
||||
@@ -42,9 +42,9 @@
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlyRHlaT1pCN2U0dG8xY2hwejVidFN6a3ZSMHRuLDkwMDkwNTcz0200NuJEg74w?s=ap",
|
||||
"id": "in_NORMALIZED00000000000003",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlyRHlaT1pCN2U0dG8xY2hwejVidFN6a3ZSMHRuLDkwMDkwNTcz0200NuJEg74w/pdf?s=ap",
|
||||
"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": {
|
||||
@@ -153,7 +153,7 @@
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000003/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
@@ -250,9 +250,9 @@
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlxMmxZbXZoUnVicXBZajdsRFU4azJSWVppaDNSLDkwMDkwNTcz0200z2u9pNME?s=ap",
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlxMmxZbXZoUnVicXBZajdsRFU4azJSWVppaDNSLDkwMDkwNTcz0200z2u9pNME/pdf?s=ap",
|
||||
"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": {
|
||||
@@ -271,8 +271,8 @@
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
"end": 1357095845,
|
||||
"start": 1325473445
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
@@ -361,7 +361,7 @@
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000001/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
|
||||
@@ -42,9 +42,9 @@
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlyM1ZjWEROSGJMNWtrMHFKNFY5ZW1DekRtM2cxLDkwMDkwNTc40200Sj4IFpmz?s=ap",
|
||||
"id": "in_NORMALIZED00000000000004",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlyM1ZjWEROSGJMNWtrMHFKNFY5ZW1DekRtM2cxLDkwMDkwNTc40200Sj4IFpmz/pdf?s=ap",
|
||||
"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": {
|
||||
@@ -103,7 +103,7 @@
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 1,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000004/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000003/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
@@ -113,7 +113,7 @@
|
||||
"on_behalf_of": null,
|
||||
"paid": false,
|
||||
"paid_out_of_band": false,
|
||||
"payment_intent": "pi_NORMALIZED00000000000004",
|
||||
"payment_intent": "pi_NORMALIZED00000000000003",
|
||||
"payment_settings": {
|
||||
"default_mandate": null,
|
||||
"payment_method_options": null,
|
||||
@@ -156,7 +156,7 @@
|
||||
"total_excluding_tax": 24000,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": 1000000000
|
||||
"webhooks_delivered_at": null
|
||||
},
|
||||
{
|
||||
"account_country": "US",
|
||||
@@ -200,9 +200,9 @@
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlyRHlaT1pCN2U0dG8xY2hwejVidFN6a3ZSMHRuLDkwMDkwNTc40200bk3mcbnW?s=ap",
|
||||
"id": "in_NORMALIZED00000000000003",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlyRHlaT1pCN2U0dG8xY2hwejVidFN6a3ZSMHRuLDkwMDkwNTc40200bk3mcbnW/pdf?s=ap",
|
||||
"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": {
|
||||
@@ -311,7 +311,7 @@
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000003/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
@@ -408,9 +408,9 @@
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlxMmxZbXZoUnVicXBZajdsRFU4azJSWVppaDNSLDkwMDkwNTc40200iIpWcfWk?s=ap",
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlxMmxZbXZoUnVicXBZajdsRFU4azJSWVppaDNSLDkwMDkwNTc40200iIpWcfWk/pdf?s=ap",
|
||||
"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": {
|
||||
@@ -429,8 +429,8 @@
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
"end": 1357095845,
|
||||
"start": 1325473445
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
@@ -519,7 +519,7 @@
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000001/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
"metadata": {},
|
||||
"object": "invoiceitem",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
"end": 1357095845,
|
||||
"start": 1325473445
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
|
||||
@@ -1,197 +0,0 @@
|
||||
{
|
||||
"amount": 7200,
|
||||
"amount_capturable": 0,
|
||||
"amount_details": {
|
||||
"tip": {}
|
||||
},
|
||||
"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 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",
|
||||
"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_1OAbiyDEQaroqDjs3ViUEwAQ",
|
||||
"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": 11,
|
||||
"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"
|
||||
},
|
||||
"receipt_email": "hamlet@zulip.com",
|
||||
"receipt_number": null,
|
||||
"receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKLKktKoGMgYimrXpHqA6LBbX51UEvwndRXqUkshrzze-vtY1kaBfu3kQ_cy4eOwD7ZOJ0MTItvKdslAN",
|
||||
"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_U9fLWaQ5foMLX6li0E7nIl4wX",
|
||||
"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,
|
||||
"latest_charge": "ch_NORMALIZED00000000000001",
|
||||
"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_1OAbiyDEQaroqDjs3ViUEwAQ",
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"installments": null,
|
||||
"mandate_options": null,
|
||||
"network": null,
|
||||
"request_three_d_secure": "automatic"
|
||||
}
|
||||
},
|
||||
"payment_method_types": [
|
||||
"card"
|
||||
],
|
||||
"processing": null,
|
||||
"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,197 +0,0 @@
|
||||
{
|
||||
"amount": 36000,
|
||||
"amount_capturable": 0,
|
||||
"amount_details": {
|
||||
"tip": {}
|
||||
},
|
||||
"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 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",
|
||||
"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_1OAbjHDEQaroqDjsFfj8byC8",
|
||||
"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": 11,
|
||||
"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"
|
||||
},
|
||||
"receipt_email": "hamlet@zulip.com",
|
||||
"receipt_number": null,
|
||||
"receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKMWktKoGMgb3nDVqmxw6LBbhC0PW9T-U53VSB9Q3DZCtbnQ72IGDALfDXWC-jcTkpT6EUGI9HGa9d-fo",
|
||||
"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_IM9QK0XPBRsrtvMFpF1HVQGr3",
|
||||
"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,
|
||||
"latest_charge": "ch_NORMALIZED00000000000002",
|
||||
"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_1OAbjHDEQaroqDjsFfj8byC8",
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"installments": null,
|
||||
"mandate_options": null,
|
||||
"network": null,
|
||||
"request_three_d_secure": "automatic"
|
||||
}
|
||||
},
|
||||
"payment_method_types": [
|
||||
"card"
|
||||
],
|
||||
"processing": null,
|
||||
"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
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
"amount_details": {
|
||||
"tip": {}
|
||||
},
|
||||
"amount_received": 0,
|
||||
"amount_received": 7200,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"automatic_payment_methods": null,
|
||||
@@ -12,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_U9fLWaQ5foMLX6li0E7nIl4wX",
|
||||
"client_secret": "pi_NORMALIZED00000000000001_secret_TT71wq3meHmzTEd7mpZbqrDnP",
|
||||
"confirmation_method": "automatic",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
@@ -27,13 +154,14 @@
|
||||
"id": "pi_NORMALIZED00000000000001",
|
||||
"invoice": null,
|
||||
"last_payment_error": null,
|
||||
"latest_charge": 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",
|
||||
@@ -45,7 +173,7 @@
|
||||
"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": {
|
||||
@@ -66,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
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"amount_details": {
|
||||
"tip": {}
|
||||
},
|
||||
"amount_received": 0,
|
||||
"amount_received": 36000,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"automatic_payment_methods": null,
|
||||
@@ -12,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_IM9QK0XPBRsrtvMFpF1HVQGr3",
|
||||
"client_secret": "pi_NORMALIZED00000000000002_secret_6P4eLudA3uvQYCOoNiDTkNQEI",
|
||||
"confirmation_method": "automatic",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
@@ -27,13 +154,14 @@
|
||||
"id": "pi_NORMALIZED00000000000002",
|
||||
"invoice": null,
|
||||
"last_payment_error": null,
|
||||
"latest_charge": 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",
|
||||
@@ -45,7 +173,7 @@
|
||||
"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": {
|
||||
@@ -66,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
|
||||
}
|
||||
|
||||
@@ -2,21 +2,21 @@
|
||||
"application": null,
|
||||
"automatic_payment_methods": null,
|
||||
"cancellation_reason": null,
|
||||
"client_secret": "seti_1OAbiyDEQaroqDjsEnpR1Onp_secret_OyYqFrkey3OlMfxWtyreL2AbO9RHVB4",
|
||||
"client_secret": "seti_1OIlcUDEQaroqDjsvk7SRRcH_secret_P6zbAgeO1YNtM2cmjYChSjYCWBsUOAB",
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": null,
|
||||
"flow_directions": null,
|
||||
"id": "seti_1OAbiyDEQaroqDjsEnpR1Onp",
|
||||
"id": "seti_1OIlcUDEQaroqDjsvk7SRRcH",
|
||||
"last_setup_error": null,
|
||||
"latest_attempt": "setatt_1OAbiyDEQaroqDjsnLExjW56",
|
||||
"latest_attempt": "setatt_1OIlcUDEQaroqDjsLAiOPmHx",
|
||||
"livemode": false,
|
||||
"mandate": null,
|
||||
"metadata": {},
|
||||
"next_action": null,
|
||||
"object": "setup_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": "pm_1OAbiyDEQaroqDjs3ViUEwAQ",
|
||||
"payment_method": "pm_1OIlcUDEQaroqDjsqDT70KqK",
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
|
||||
@@ -2,21 +2,21 @@
|
||||
"application": null,
|
||||
"automatic_payment_methods": null,
|
||||
"cancellation_reason": null,
|
||||
"client_secret": "seti_1OAbjHDEQaroqDjsiyGUfkGg_secret_OyYq1ljcbx3AZiCSK143sZdt7S0n6pN",
|
||||
"client_secret": "seti_1OIlceDEQaroqDjsF69R2WG0_secret_P6zbftiDh6C2B0Le8GK6ALVcHby9Gyu",
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": null,
|
||||
"flow_directions": null,
|
||||
"id": "seti_1OAbjHDEQaroqDjsiyGUfkGg",
|
||||
"id": "seti_1OIlceDEQaroqDjsF69R2WG0",
|
||||
"last_setup_error": null,
|
||||
"latest_attempt": "setatt_1OAbjHDEQaroqDjswrjSFGn9",
|
||||
"latest_attempt": "setatt_1OIlceDEQaroqDjs1hVqql0s",
|
||||
"livemode": false,
|
||||
"mandate": null,
|
||||
"metadata": {},
|
||||
"next_action": null,
|
||||
"object": "setup_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": "pm_1OAbjHDEQaroqDjsFfj8byC8",
|
||||
"payment_method": "pm_1OIlceDEQaroqDjshc2Y2l9b",
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
"application": null,
|
||||
"automatic_payment_methods": null,
|
||||
"cancellation_reason": null,
|
||||
"client_secret": "seti_1OAbixDEQaroqDjsZ13bFTzk_secret_OyYqTKT3uNo6hXb6nycNN82HUV4tLVa",
|
||||
"client_secret": "seti_1OIlcTDEQaroqDjs7K1pjsyq_secret_P6zb4X2b8va5VZDxRMR3CgIYMwreYzC",
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": null,
|
||||
"flow_directions": null,
|
||||
"id": "seti_1OAbixDEQaroqDjsZ13bFTzk",
|
||||
"id": "seti_1OIlcTDEQaroqDjs7K1pjsyq",
|
||||
"last_setup_error": null,
|
||||
"latest_attempt": null,
|
||||
"livemode": false,
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
"application": null,
|
||||
"automatic_payment_methods": null,
|
||||
"cancellation_reason": null,
|
||||
"client_secret": "seti_1OAbjFDEQaroqDjsOtWXOh3z_secret_OyYqDwZSEotDZcPqC8EEXDlXcWpwH0i",
|
||||
"client_secret": "seti_1OIlcdDEQaroqDjsB4ugOdVp_secret_P6zbipSmx7qqSUGMRGqVxyYPXoN42bP",
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": null,
|
||||
"flow_directions": null,
|
||||
"id": "seti_1OAbjFDEQaroqDjsOtWXOh3z",
|
||||
"id": "seti_1OIlcdDEQaroqDjsB4ugOdVp",
|
||||
"last_setup_error": null,
|
||||
"latest_attempt": null,
|
||||
"livemode": false,
|
||||
|
||||
@@ -2,21 +2,21 @@
|
||||
"application": null,
|
||||
"automatic_payment_methods": null,
|
||||
"cancellation_reason": null,
|
||||
"client_secret": "seti_1OAbiyDEQaroqDjsEnpR1Onp_secret_OyYqFrkey3OlMfxWtyreL2AbO9RHVB4",
|
||||
"client_secret": "seti_1OIlcUDEQaroqDjsvk7SRRcH_secret_P6zbAgeO1YNtM2cmjYChSjYCWBsUOAB",
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": null,
|
||||
"flow_directions": null,
|
||||
"id": "seti_1OAbiyDEQaroqDjsEnpR1Onp",
|
||||
"id": "seti_1OIlcUDEQaroqDjsvk7SRRcH",
|
||||
"last_setup_error": null,
|
||||
"latest_attempt": "setatt_1OAbiyDEQaroqDjsnLExjW56",
|
||||
"latest_attempt": "setatt_1OIlcUDEQaroqDjsLAiOPmHx",
|
||||
"livemode": false,
|
||||
"mandate": null,
|
||||
"metadata": {},
|
||||
"next_action": null,
|
||||
"object": "setup_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": "pm_1OAbiyDEQaroqDjs3ViUEwAQ",
|
||||
"payment_method": "pm_1OIlcUDEQaroqDjsqDT70KqK",
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
|
||||
@@ -2,21 +2,21 @@
|
||||
"application": null,
|
||||
"automatic_payment_methods": null,
|
||||
"cancellation_reason": null,
|
||||
"client_secret": "seti_1OAbjHDEQaroqDjsiyGUfkGg_secret_OyYq1ljcbx3AZiCSK143sZdt7S0n6pN",
|
||||
"client_secret": "seti_1OIlceDEQaroqDjsF69R2WG0_secret_P6zbftiDh6C2B0Le8GK6ALVcHby9Gyu",
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": null,
|
||||
"flow_directions": null,
|
||||
"id": "seti_1OAbjHDEQaroqDjsiyGUfkGg",
|
||||
"id": "seti_1OIlceDEQaroqDjsF69R2WG0",
|
||||
"last_setup_error": null,
|
||||
"latest_attempt": "setatt_1OAbjHDEQaroqDjswrjSFGn9",
|
||||
"latest_attempt": "setatt_1OIlceDEQaroqDjs1hVqql0s",
|
||||
"livemode": false,
|
||||
"mandate": null,
|
||||
"metadata": {},
|
||||
"next_action": null,
|
||||
"object": "setup_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": "pm_1OAbjHDEQaroqDjsFfj8byC8",
|
||||
"payment_method": "pm_1OIlceDEQaroqDjshc2Y2l9b",
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"status": null
|
||||
},
|
||||
"billing_address_collection": null,
|
||||
"cancel_url": "http://zulip.testserver/billing/",
|
||||
"cancel_url": "http://zulip.testserver/upgrade/",
|
||||
"client_reference_id": null,
|
||||
"client_secret": null,
|
||||
"consent": null,
|
||||
@@ -34,22 +34,13 @@
|
||||
},
|
||||
"customer_email": null,
|
||||
"expires_at": 1000000000,
|
||||
"id": "cs_test_NORMALIZED02Z5ZWoaj9BNmgBmGSOWkzCIOee3905mO0A4AaeSETi2qfDk",
|
||||
"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",
|
||||
@@ -67,7 +58,7 @@
|
||||
"enabled": false
|
||||
},
|
||||
"recovered_from": null,
|
||||
"setup_intent": "seti_1OAbixDEQaroqDjsZ13bFTzk",
|
||||
"setup_intent": "seti_1OIlcTDEQaroqDjs7K1pjsyq",
|
||||
"shipping": null,
|
||||
"shipping_address_collection": null,
|
||||
"shipping_options": [],
|
||||
@@ -78,5 +69,5 @@
|
||||
"success_url": "http://zulip.testserver/billing/event_status?stripe_session_id={CHECKOUT_SESSION_ID}",
|
||||
"total_details": null,
|
||||
"ui_mode": "hosted",
|
||||
"url": "https://checkout.stripe.com/c/pay/cs_test_NORMALIZED02Z5ZWoaj9BNmgBmGSOWkzCIOee3905mO0A4AaeSETi2qfDk#fidkdWxOYHwnPyd1blpxYHZxWl1UZjFOczZJXUE2PUpzUWNPV2ZpdlFzUCcpJ2N3amhWYHdzYHcnP3F3cGApJ2lkfGpwcVF8dWAnPyd2bGtiaWBaZmppcGhrJyknYGtkZ2lgVWlkZmBtamlhYHd2Jz9xd3BgeCUl"
|
||||
"url": "https://checkout.stripe.com/c/pay/cs_test_NORMALIZED02sb4yHaq28VHOZscOtqKWTLoGQJALldTi43GUE0P56ay9sU#fidkdWxOYHwnPyd1blpxYHZxWl1UZjFOczZJXUE2PUpzUWNPV2ZpdlFzUCcpJ2N3amhWYHdzYHcnP3F3cGApJ2lkfGpwcVF8dWAnPyd2bGtiaWBaZmppcGhrJyknYGtkZ2lgVWlkZmBtamlhYHd2Jz9xd3BgeCUl"
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"status": null
|
||||
},
|
||||
"billing_address_collection": null,
|
||||
"cancel_url": "http://zulip.testserver/billing/",
|
||||
"cancel_url": "http://zulip.testserver/upgrade/",
|
||||
"client_reference_id": null,
|
||||
"client_secret": null,
|
||||
"consent": null,
|
||||
@@ -34,22 +34,13 @@
|
||||
},
|
||||
"customer_email": null,
|
||||
"expires_at": 1000000000,
|
||||
"id": "cs_test_NORMALIZED03LS5wbvnBYGdnCEW5t1ot0jYJyM0nR7L9zyMjaPa4nlbim5",
|
||||
"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",
|
||||
@@ -67,7 +58,7 @@
|
||||
"enabled": false
|
||||
},
|
||||
"recovered_from": null,
|
||||
"setup_intent": "seti_1OAbjFDEQaroqDjsOtWXOh3z",
|
||||
"setup_intent": "seti_1OIlcdDEQaroqDjsB4ugOdVp",
|
||||
"shipping": null,
|
||||
"shipping_address_collection": null,
|
||||
"shipping_options": [],
|
||||
@@ -78,5 +69,5 @@
|
||||
"success_url": "http://zulip.testserver/billing/event_status?stripe_session_id={CHECKOUT_SESSION_ID}",
|
||||
"total_details": null,
|
||||
"ui_mode": "hosted",
|
||||
"url": "https://checkout.stripe.com/c/pay/cs_test_NORMALIZED03LS5wbvnBYGdnCEW5t1ot0jYJyM0nR7L9zyMjaPa4nlbim5#fidkdWxOYHwnPyd1blpxYHZxWl1UZjFOczZJXUE2PUpzUWNPV2ZpdlFzUCcpJ2N3amhWYHdzYHcnP3F3cGApJ2lkfGpwcVF8dWAnPyd2bGtiaWBaZmppcGhrJyknYGtkZ2lgVWlkZmBtamlhYHd2Jz9xd3BgeCUl"
|
||||
"url": "https://checkout.stripe.com/c/pay/cs_test_NORMALIZED03vZmJUBP0ybiRb1yrtpVKGaX0cm1V0nhnpM6e5pcI1y8CkG#fidkdWxOYHwnPyd1blpxYHZxWl1UZjFOczZJXUE2PUpzUWNPV2ZpdlFzUCcpJ2N3amhWYHdzYHcnP3F3cGApJ2lkfGpwcVF8dWAnPyd2bGtiaWBaZmppcGhrJyknYGtkZ2lgVWlkZmBtamlhYHd2Jz9xd3BgeCUl"
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"status": null
|
||||
},
|
||||
"billing_address_collection": null,
|
||||
"cancel_url": "http://zulip.testserver/billing/",
|
||||
"cancel_url": "http://zulip.testserver/upgrade/",
|
||||
"client_reference_id": null,
|
||||
"client_secret": null,
|
||||
"consent": null,
|
||||
@@ -36,22 +36,13 @@
|
||||
},
|
||||
"customer_email": null,
|
||||
"expires_at": 1000000000,
|
||||
"id": "cs_test_NORMALIZED02Z5ZWoaj9BNmgBmGSOWkzCIOee3905mO0A4AaeSETi2qfDk",
|
||||
"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",
|
||||
@@ -69,7 +60,7 @@
|
||||
"enabled": false
|
||||
},
|
||||
"recovered_from": null,
|
||||
"setup_intent": "seti_1OAbixDEQaroqDjsZ13bFTzk",
|
||||
"setup_intent": "seti_1OIlcTDEQaroqDjs7K1pjsyq",
|
||||
"shipping": null,
|
||||
"shipping_address_collection": null,
|
||||
"shipping_options": [],
|
||||
@@ -80,7 +71,7 @@
|
||||
"success_url": "http://zulip.testserver/billing/event_status?stripe_session_id={CHECKOUT_SESSION_ID}",
|
||||
"total_details": null,
|
||||
"ui_mode": "hosted",
|
||||
"url": "https://checkout.stripe.com/c/pay/cs_test_NORMALIZED02Z5ZWoaj9BNmgBmGSOWkzCIOee3905mO0A4AaeSETi2qfDk#fidkdWxOYHwnPyd1blpxYHZxWl1UZjFOczZJXUE2PUpzUWNPV2ZpdlFzUCcpJ2N3amhWYHdzYHcnP3F3cGApJ2lkfGpwcVF8dWAnPyd2bGtiaWBaZmppcGhrJyknYGtkZ2lgVWlkZmBtamlhYHd2Jz9xd3BgeCUl"
|
||||
"url": "https://checkout.stripe.com/c/pay/cs_test_NORMALIZED02sb4yHaq28VHOZscOtqKWTLoGQJALldTi43GUE0P56ay9sU#fidkdWxOYHwnPyd1blpxYHZxWl1UZjFOczZJXUE2PUpzUWNPV2ZpdlFzUCcpJ2N3amhWYHdzYHcnP3F3cGApJ2lkfGpwcVF8dWAnPyd2bGtiaWBaZmppcGhrJyknYGtkZ2lgVWlkZmBtamlhYHd2Jz9xd3BgeCUl"
|
||||
}
|
||||
],
|
||||
"has_more": true,
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"status": null
|
||||
},
|
||||
"billing_address_collection": null,
|
||||
"cancel_url": "http://zulip.testserver/billing/",
|
||||
"cancel_url": "http://zulip.testserver/upgrade/",
|
||||
"client_reference_id": null,
|
||||
"client_secret": null,
|
||||
"consent": null,
|
||||
@@ -36,22 +36,13 @@
|
||||
},
|
||||
"customer_email": null,
|
||||
"expires_at": 1000000000,
|
||||
"id": "cs_test_NORMALIZED03LS5wbvnBYGdnCEW5t1ot0jYJyM0nR7L9zyMjaPa4nlbim5",
|
||||
"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",
|
||||
@@ -69,7 +60,7 @@
|
||||
"enabled": false
|
||||
},
|
||||
"recovered_from": null,
|
||||
"setup_intent": "seti_1OAbjFDEQaroqDjsOtWXOh3z",
|
||||
"setup_intent": "seti_1OIlcdDEQaroqDjsB4ugOdVp",
|
||||
"shipping": null,
|
||||
"shipping_address_collection": null,
|
||||
"shipping_options": [],
|
||||
@@ -80,7 +71,7 @@
|
||||
"success_url": "http://zulip.testserver/billing/event_status?stripe_session_id={CHECKOUT_SESSION_ID}",
|
||||
"total_details": null,
|
||||
"ui_mode": "hosted",
|
||||
"url": "https://checkout.stripe.com/c/pay/cs_test_NORMALIZED03LS5wbvnBYGdnCEW5t1ot0jYJyM0nR7L9zyMjaPa4nlbim5#fidkdWxOYHwnPyd1blpxYHZxWl1UZjFOczZJXUE2PUpzUWNPV2ZpdlFzUCcpJ2N3amhWYHdzYHcnP3F3cGApJ2lkfGpwcVF8dWAnPyd2bGtiaWBaZmppcGhrJyknYGtkZ2lgVWlkZmBtamlhYHd2Jz9xd3BgeCUl"
|
||||
"url": "https://checkout.stripe.com/c/pay/cs_test_NORMALIZED03vZmJUBP0ybiRb1yrtpVKGaX0cm1V0nhnpM6e5pcI1y8CkG#fidkdWxOYHwnPyd1blpxYHZxWl1UZjFOczZJXUE2PUpzUWNPV2ZpdlFzUCcpJ2N3amhWYHdzYHcnP3F3cGApJ2lkfGpwcVF8dWAnPyd2bGtiaWBaZmppcGhrJyknYGtkZ2lgVWlkZmBtamlhYHd2Jz9xd3BgeCUl"
|
||||
}
|
||||
],
|
||||
"has_more": true,
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"delinquent": false,
|
||||
"description": "zulip (Zulip Dev)",
|
||||
"discount": null,
|
||||
"email": "hamlet@zulip.com",
|
||||
"email": "othello@zulip.com",
|
||||
"id": "cus_NORMALIZED0001",
|
||||
"invoice_prefix": "NORMA01",
|
||||
"invoice_settings": {
|
||||
|
||||
@@ -8,12 +8,12 @@
|
||||
"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": "pm_1OAbcFDEQaroqDjsNEmc1jWB",
|
||||
"default_payment_method": "pm_1OIlXhDEQaroqDjsm8crnb7t",
|
||||
"footer": null,
|
||||
"rendering_options": null
|
||||
},
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
"address": null,
|
||||
"balance": 0,
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"default_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": {
|
||||
@@ -35,7 +35,7 @@
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 11,
|
||||
"exp_month": 12,
|
||||
"exp_year": 2024,
|
||||
"fingerprint": "NORMALIZED000001",
|
||||
"funding": "credit",
|
||||
@@ -54,7 +54,7 @@
|
||||
},
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"id": "pm_1OAbcFDEQaroqDjsNEmc1jWB",
|
||||
"id": "pm_1OIlXhDEQaroqDjsm8crnb7t",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "payment_method",
|
||||
@@ -69,7 +69,7 @@
|
||||
"realm_str": "zulip"
|
||||
},
|
||||
"name": null,
|
||||
"next_invoice_sequence": 2,
|
||||
"next_invoice_sequence": 1,
|
||||
"object": "customer",
|
||||
"phone": null,
|
||||
"preferred_locales": [],
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
"address": null,
|
||||
"balance": 0,
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"default_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": {
|
||||
@@ -35,7 +35,7 @@
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 11,
|
||||
"exp_month": 12,
|
||||
"exp_year": 2024,
|
||||
"fingerprint": "NORMALIZED000001",
|
||||
"funding": "credit",
|
||||
@@ -54,7 +54,7 @@
|
||||
},
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"id": "pm_1OAbcFDEQaroqDjsNEmc1jWB",
|
||||
"id": "pm_1OIlXhDEQaroqDjsm8crnb7t",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "payment_method",
|
||||
@@ -69,7 +69,7 @@
|
||||
"realm_str": "zulip"
|
||||
},
|
||||
"name": null,
|
||||
"next_invoice_sequence": 2,
|
||||
"next_invoice_sequence": 1,
|
||||
"object": "customer",
|
||||
"phone": null,
|
||||
"preferred_locales": [],
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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": "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": 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": "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": 2,
|
||||
"object": "customer",
|
||||
"phone": null,
|
||||
"preferred_locales": [],
|
||||
"shipping": null,
|
||||
"tax_exempt": "none",
|
||||
"test_clock": null
|
||||
}
|
||||
@@ -5,273 +5,53 @@
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"account_country": "US",
|
||||
"account_name": "Kandra Labs, Inc.",
|
||||
"account_tax_ids": null,
|
||||
"amount_due": 80697,
|
||||
"amount_paid": 0,
|
||||
"amount_remaining": 80697,
|
||||
"amount_shipping": 0,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"attempt_count": 0,
|
||||
"attempted": false,
|
||||
"auto_advance": true,
|
||||
"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,
|
||||
"effective_at": 1000000000,
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlqaGQ3elJQNENCaVZHMVZqdGVyMzFmWFJZck1MLDkwMDkwMTE002002tYuWb47?s=ap",
|
||||
"id": "in_NORMALIZED00000000000001",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlqaGQ3elJQNENCaVZHMVZqdGVyMzFmWFJZck1MLDkwMDkwMTE002002tYuWb47/pdf?s=ap",
|
||||
"last_finalization_error": null,
|
||||
"latest_revision": null,
|
||||
"lines": {
|
||||
"data": [
|
||||
{
|
||||
"amount": 7255,
|
||||
"amount_excluding_tax": 7255,
|
||||
"currency": "usd",
|
||||
"description": "Additional license (Feb 5, 2013 - Jan 2, 2014)",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000001",
|
||||
"invoice_item": "ii_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
"period": {
|
||||
"end": 1388631845,
|
||||
"start": 1360033445
|
||||
},
|
||||
"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": 7255,
|
||||
"unit_amount_decimal": "7255"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 1,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "7255"
|
||||
},
|
||||
{
|
||||
"amount": 56000,
|
||||
"amount_excluding_tax": 56000,
|
||||
"currency": "usd",
|
||||
"description": "Zulip Cloud Standard - renewal",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000002",
|
||||
"invoice_item": "ii_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
"period": {
|
||||
"end": 1388631845,
|
||||
"start": 1357095845
|
||||
},
|
||||
"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": 8000,
|
||||
"unit_amount_decimal": "8000"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 7,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "8000"
|
||||
},
|
||||
{
|
||||
"amount": 17442,
|
||||
"amount_excluding_tax": 17442,
|
||||
"currency": "usd",
|
||||
"description": "Additional license (Apr 11, 2012 - Jan 2, 2013)",
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000003",
|
||||
"invoice_item": "ii_NORMALIZED00000000000003",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
"period": {
|
||||
"end": 1357095845,
|
||||
"start": 1334113445
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
"active": false,
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"custom_unit_amount": null,
|
||||
"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": 5814,
|
||||
"unit_amount_decimal": "5814"
|
||||
},
|
||||
"proration": false,
|
||||
"proration_details": {
|
||||
"credited_items": null
|
||||
},
|
||||
"quantity": 3,
|
||||
"subscription": null,
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "invoiceitem",
|
||||
"unit_amount_excluding_tax": "5814"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 3,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000001/lines"
|
||||
"email": "othello@zulip.com",
|
||||
"id": "cus_NORMALIZED0001",
|
||||
"invoice_prefix": "NORMA01",
|
||||
"invoice_settings": {
|
||||
"custom_fields": null,
|
||||
"default_payment_method": "pm_1OIlXhDEQaroqDjsm8crnb7t",
|
||||
"footer": null,
|
||||
"rendering_options": null
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"next_payment_attempt": 1000000000,
|
||||
"number": "NORMALI-0001",
|
||||
"object": "invoice",
|
||||
"on_behalf_of": null,
|
||||
"paid": false,
|
||||
"paid_out_of_band": false,
|
||||
"payment_intent": "pi_NORMALIZED00000000000001",
|
||||
"payment_settings": {
|
||||
"default_mandate": null,
|
||||
"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,
|
||||
"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",
|
||||
"status_transitions": {
|
||||
"finalized_at": 1000000000,
|
||||
"marked_uncollectible_at": null,
|
||||
"paid_at": null,
|
||||
"voided_at": null
|
||||
},
|
||||
"subscription": null,
|
||||
"subscription_details": {
|
||||
"metadata": null
|
||||
},
|
||||
"subtotal": 80697,
|
||||
"subtotal_excluding_tax": 80697,
|
||||
"tax": null,
|
||||
"test_clock": null,
|
||||
"total": 80697,
|
||||
"total_discount_amounts": [],
|
||||
"total_excluding_tax": 80697,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": 1000000000
|
||||
"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_1OAbc7DEQaroqDjsSb1CrgmS",
|
||||
"id": "evt_1OIlXjDEQaroqDjsLhrUEUe3",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0001",
|
||||
"idempotency_key": "7cd9d940-ede9-458e-b191-b3310133d9da"
|
||||
"idempotency_key": "12b7d34b-4958-462b-8fda-e2f6c17957bd"
|
||||
},
|
||||
"type": "invoice.finalized"
|
||||
"type": "customer.updated"
|
||||
}
|
||||
],
|
||||
"has_more": true,
|
||||
|
||||
@@ -61,13 +61,14 @@
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"plan_tier": "1",
|
||||
"price_per_license": "8000",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
"seat_count": "6",
|
||||
"type": "upgrade",
|
||||
"user_email": "hamlet@zulip.com",
|
||||
"user_id": "10"
|
||||
"user_email": "othello@zulip.com",
|
||||
"user_id": "12"
|
||||
},
|
||||
"object": "charge",
|
||||
"on_behalf_of": null,
|
||||
@@ -81,8 +82,8 @@
|
||||
"type": "authorized"
|
||||
},
|
||||
"paid": true,
|
||||
"payment_intent": "pi_NORMALIZED00000000000002",
|
||||
"payment_method": "pm_1OAbcFDEQaroqDjsNEmc1jWB",
|
||||
"payment_intent": "pi_NORMALIZED00000000000001",
|
||||
"payment_method": "pm_1OIlXhDEQaroqDjsm8crnb7t",
|
||||
"payment_method_details": {
|
||||
"card": {
|
||||
"amount_authorized": 48000,
|
||||
@@ -93,7 +94,7 @@
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 11,
|
||||
"exp_month": 12,
|
||||
"exp_year": 2024,
|
||||
"extended_authorization": {
|
||||
"status": "disabled"
|
||||
@@ -122,9 +123,10 @@
|
||||
},
|
||||
"type": "card"
|
||||
},
|
||||
"receipt_email": "hamlet@zulip.com",
|
||||
"radar_options": {},
|
||||
"receipt_email": "othello@zulip.com",
|
||||
"receipt_number": null,
|
||||
"receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKI6htKoGMgZEJv0Gk_M6LBbsy-cE95lt_YeePEQfQ75WiLgzUKjcC64s0_AWS2B4Sh8s6V3ZVbiZxriI",
|
||||
"receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKN76qqsGMgYgrE0XQWw6LBau_ilRx6BPEf5zlgCHW2ojzwBSlxtCQxmlmII5DkhOSXuAsc1VGTmDFZd6",
|
||||
"refunded": false,
|
||||
"refunds": {
|
||||
"data": [],
|
||||
@@ -147,15 +149,15 @@
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 1,
|
||||
"url": "/v1/charges?payment_intent=pi_NORMALIZED00000000000002"
|
||||
"url": "/v1/charges?payment_intent=pi_NORMALIZED00000000000001"
|
||||
},
|
||||
"client_secret": "pi_NORMALIZED00000000000002_secret_GjSC2H9KhGusuka7dHcnSXXMq",
|
||||
"client_secret": "pi_NORMALIZED00000000000001_secret_gaaXxocbBjOepNzIQyoHlMcVE",
|
||||
"confirmation_method": "automatic",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": "Upgrade to Zulip Cloud Standard, $80.0 x 6",
|
||||
"id": "pi_NORMALIZED00000000000002",
|
||||
"id": "pi_NORMALIZED00000000000001",
|
||||
"invoice": null,
|
||||
"last_payment_error": null,
|
||||
"latest_charge": "ch_NORMALIZED00000000000001",
|
||||
@@ -165,18 +167,19 @@
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"plan_tier": "1",
|
||||
"price_per_license": "8000",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
"seat_count": "6",
|
||||
"type": "upgrade",
|
||||
"user_email": "hamlet@zulip.com",
|
||||
"user_id": "10"
|
||||
"user_email": "othello@zulip.com",
|
||||
"user_id": "12"
|
||||
},
|
||||
"next_action": null,
|
||||
"object": "payment_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": "pm_1OAbcFDEQaroqDjsNEmc1jWB",
|
||||
"payment_method": "pm_1OIlXhDEQaroqDjsm8crnb7t",
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
@@ -190,7 +193,7 @@
|
||||
"card"
|
||||
],
|
||||
"processing": null,
|
||||
"receipt_email": "hamlet@zulip.com",
|
||||
"receipt_email": "othello@zulip.com",
|
||||
"review": null,
|
||||
"setup_future_usage": null,
|
||||
"shipping": null,
|
||||
@@ -202,13 +205,13 @@
|
||||
"transfer_group": null
|
||||
}
|
||||
},
|
||||
"id": "evt_3OAbcCDEQaroqDjs00CvOf1K",
|
||||
"id": "evt_3OIlXlDEQaroqDjs0FGYzTr9",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"pending_webhooks": 2,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0002",
|
||||
"idempotency_key": "c74e41ba-0d59-462f-901d-3653b9691ddd"
|
||||
"idempotency_key": "899e9bd5-f82b-4ed6-a09b-e04dba8c0edd"
|
||||
},
|
||||
"type": "payment_intent.succeeded"
|
||||
},
|
||||
@@ -258,13 +261,14 @@
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"plan_tier": "1",
|
||||
"price_per_license": "8000",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
"seat_count": "6",
|
||||
"type": "upgrade",
|
||||
"user_email": "hamlet@zulip.com",
|
||||
"user_id": "10"
|
||||
"user_email": "othello@zulip.com",
|
||||
"user_id": "12"
|
||||
},
|
||||
"object": "charge",
|
||||
"on_behalf_of": null,
|
||||
@@ -278,8 +282,8 @@
|
||||
"type": "authorized"
|
||||
},
|
||||
"paid": true,
|
||||
"payment_intent": "pi_NORMALIZED00000000000002",
|
||||
"payment_method": "pm_1OAbcFDEQaroqDjsNEmc1jWB",
|
||||
"payment_intent": "pi_NORMALIZED00000000000001",
|
||||
"payment_method": "pm_1OIlXhDEQaroqDjsm8crnb7t",
|
||||
"payment_method_details": {
|
||||
"card": {
|
||||
"amount_authorized": 48000,
|
||||
@@ -290,7 +294,7 @@
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 11,
|
||||
"exp_month": 12,
|
||||
"exp_year": 2024,
|
||||
"extended_authorization": {
|
||||
"status": "disabled"
|
||||
@@ -319,9 +323,10 @@
|
||||
},
|
||||
"type": "card"
|
||||
},
|
||||
"receipt_email": "hamlet@zulip.com",
|
||||
"radar_options": {},
|
||||
"receipt_email": "othello@zulip.com",
|
||||
"receipt_number": null,
|
||||
"receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKI6htKoGMgZcUtV8GJI6LBaeeZaDfZ9Pvd8H6r0A8x9w31_WpGcCgXdwg87kKfcDvl-uO4ENXJjqxjaC",
|
||||
"receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKN76qqsGMgYp5rJn4Pg6LBYAjHCItgf9iiKG_mmqSy1FuggXUU5fXaGzNuMWlKsIBYlUVnaYe37Fid2s",
|
||||
"refunded": false,
|
||||
"refunds": {
|
||||
"data": [],
|
||||
@@ -341,412 +346,15 @@
|
||||
"transfer_group": null
|
||||
}
|
||||
},
|
||||
"id": "evt_3OAbcCDEQaroqDjs0gbReOHa",
|
||||
"id": "evt_3OIlXlDEQaroqDjs0F5rvmUM",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0002",
|
||||
"idempotency_key": "c74e41ba-0d59-462f-901d-3653b9691ddd"
|
||||
"idempotency_key": "899e9bd5-f82b-4ed6-a09b-e04dba8c0edd"
|
||||
},
|
||||
"type": "charge.succeeded"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"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": "pm_1OAbcFDEQaroqDjsNEmc1jWB",
|
||||
"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
|
||||
},
|
||||
"previous_attributes": {
|
||||
"invoice_settings": {
|
||||
"default_payment_method": null
|
||||
}
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbcGDEQaroqDjs0wggukPI",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0003",
|
||||
"idempotency_key": "f914e846-173a-4145-b71c-c2deddb69419"
|
||||
},
|
||||
"type": "customer.updated"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"application": null,
|
||||
"automatic_payment_methods": null,
|
||||
"cancellation_reason": null,
|
||||
"client_secret": "seti_1OAbcFDEQaroqDjsQfMm42ws_secret_OyYjgcW1HC7Fs8iRLfn8iQ35FmvPJmH",
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": null,
|
||||
"flow_directions": null,
|
||||
"id": "seti_1OAbcFDEQaroqDjsQfMm42ws",
|
||||
"last_setup_error": null,
|
||||
"latest_attempt": "setatt_1OAbcFDEQaroqDjsJ6wKO7Zx",
|
||||
"livemode": false,
|
||||
"mandate": null,
|
||||
"metadata": {},
|
||||
"next_action": null,
|
||||
"object": "setup_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": "pm_1OAbcFDEQaroqDjsNEmc1jWB",
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"mandate_options": null,
|
||||
"network": null,
|
||||
"request_three_d_secure": "automatic"
|
||||
}
|
||||
},
|
||||
"payment_method_types": [
|
||||
"card"
|
||||
],
|
||||
"single_use_mandate": null,
|
||||
"status": "succeeded",
|
||||
"usage": "off_session"
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbcGDEQaroqDjsPyjXOCAc",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0004",
|
||||
"idempotency_key": "e1214b92-0e5f-42b2-a9ad-fa7d7b905542"
|
||||
},
|
||||
"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": 11,
|
||||
"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_1OAbcFDEQaroqDjsNEmc1jWB",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "payment_method",
|
||||
"type": "card"
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbcFDEQaroqDjs39qXJFeQ",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0004",
|
||||
"idempotency_key": "e1214b92-0e5f-42b2-a9ad-fa7d7b905542"
|
||||
},
|
||||
"type": "payment_method.attached"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"application": null,
|
||||
"automatic_payment_methods": null,
|
||||
"cancellation_reason": null,
|
||||
"client_secret": "seti_1OAbcFDEQaroqDjsQfMm42ws_secret_OyYjgcW1HC7Fs8iRLfn8iQ35FmvPJmH",
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": null,
|
||||
"flow_directions": null,
|
||||
"id": "seti_1OAbcFDEQaroqDjsQfMm42ws",
|
||||
"last_setup_error": null,
|
||||
"latest_attempt": "setatt_1OAbcFDEQaroqDjsJ6wKO7Zx",
|
||||
"livemode": false,
|
||||
"mandate": null,
|
||||
"metadata": {},
|
||||
"next_action": null,
|
||||
"object": "setup_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": "pm_1OAbcFDEQaroqDjsNEmc1jWB",
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"mandate_options": null,
|
||||
"network": null,
|
||||
"request_three_d_secure": "automatic"
|
||||
}
|
||||
},
|
||||
"payment_method_types": [
|
||||
"card"
|
||||
],
|
||||
"single_use_mandate": null,
|
||||
"status": "succeeded",
|
||||
"usage": "off_session"
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbcGDEQaroqDjsOY11fmt3",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0004",
|
||||
"idempotency_key": "e1214b92-0e5f-42b2-a9ad-fa7d7b905542"
|
||||
},
|
||||
"type": "setup_intent.created"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"application": null,
|
||||
"automatic_payment_methods": null,
|
||||
"cancellation_reason": null,
|
||||
"client_secret": "seti_1OAbcDDEQaroqDjs6URoWzLY_secret_OyYj6KwwzRa2rP52fvEQaNH3OWcEQfU",
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": null,
|
||||
"flow_directions": null,
|
||||
"id": "seti_1OAbcDDEQaroqDjs6URoWzLY",
|
||||
"last_setup_error": null,
|
||||
"latest_attempt": null,
|
||||
"livemode": false,
|
||||
"mandate": null,
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"payment_method_types": [
|
||||
"card"
|
||||
],
|
||||
"single_use_mandate": null,
|
||||
"status": "requires_payment_method",
|
||||
"usage": "off_session"
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbcDDEQaroqDjs40IfyFuo",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0005",
|
||||
"idempotency_key": "ef53c743-c734-4676-afd4-496344b54399"
|
||||
},
|
||||
"type": "setup_intent.created"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"amount": 48000,
|
||||
"amount_capturable": 0,
|
||||
"amount_details": {
|
||||
"tip": {}
|
||||
},
|
||||
"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_GjSC2H9KhGusuka7dHcnSXXMq",
|
||||
"confirmation_method": "automatic",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": "Upgrade to Zulip Cloud Standard, $80.0 x 6",
|
||||
"id": "pi_NORMALIZED00000000000002",
|
||||
"invoice": null,
|
||||
"last_payment_error": null,
|
||||
"latest_charge": null,
|
||||
"livemode": false,
|
||||
"metadata": {
|
||||
"billing_modality": "charge_automatically",
|
||||
"billing_schedule": "1",
|
||||
"license_management": "automatic",
|
||||
"licenses": "6",
|
||||
"price_per_license": "8000",
|
||||
"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_configuration_details": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"installments": null,
|
||||
"mandate_options": null,
|
||||
"network": null,
|
||||
"request_three_d_secure": "automatic"
|
||||
}
|
||||
},
|
||||
"payment_method_types": [
|
||||
"card"
|
||||
],
|
||||
"processing": null,
|
||||
"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_3OAbcCDEQaroqDjs0HuorQuk",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0006",
|
||||
"idempotency_key": "7c94e31e-d95d-4c8a-870f-222f7c739459"
|
||||
},
|
||||
"type": "payment_intent.created"
|
||||
},
|
||||
{
|
||||
"api_version": "2020-08-27",
|
||||
"created": 1000000000,
|
||||
"data": {
|
||||
"object": {
|
||||
"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": null,
|
||||
"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
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbcADEQaroqDjs9BctiGlP",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0007",
|
||||
"idempotency_key": "ed7dbb33-9d63-48ca-a4a8-d77bb716bb9f"
|
||||
},
|
||||
"type": "customer.created"
|
||||
}
|
||||
],
|
||||
"has_more": false,
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
"custom_fields": null,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"customer_address": null,
|
||||
"customer_email": "hamlet@zulip.com",
|
||||
"customer_email": "othello@zulip.com",
|
||||
"customer_name": null,
|
||||
"customer_phone": null,
|
||||
"customer_shipping": null,
|
||||
@@ -46,9 +46,9 @@
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlqR2NXRUhCcElNVjQxUkMxTVhsa3NTaTNqVklULDkwMDkwMTMy02005Nx2aWJ6?s=ap",
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlqR2NXRUhCcElNVjQxUkMxTVhsa3NTaTNqVklULDkwMDkwMTMy02005Nx2aWJ6/pdf?s=ap",
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpXWlpYcFFGQklGamtRUExacnBFdXlvU0I2dlZTLDkyMDM0OTEz0200nMuZd38e?s=ap",
|
||||
"id": "in_NORMALIZED00000000000001",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpXWlpYcFFGQklGamtRUExacnBFdXlvU0I2dlZTLDkyMDM0OTEz0200nMuZd38e/pdf?s=ap",
|
||||
"last_finalization_error": null,
|
||||
"latest_revision": null,
|
||||
"lines": {
|
||||
@@ -61,14 +61,14 @@
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000004",
|
||||
"invoice_item": "ii_NORMALIZED00000000000004",
|
||||
"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": {
|
||||
@@ -77,13 +77,13 @@
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"id": "price_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0004",
|
||||
"product": "prod_NORMALIZED0001",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -111,8 +111,8 @@
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000005",
|
||||
"invoice_item": "ii_NORMALIZED00000000000005",
|
||||
"id": "il_NORMALIZED00000000000002",
|
||||
"invoice_item": "ii_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -127,13 +127,13 @@
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000005",
|
||||
"id": "price_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0005",
|
||||
"product": "prod_NORMALIZED0002",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -157,12 +157,12 @@
|
||||
"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,
|
||||
@@ -210,7 +210,7 @@
|
||||
"total_excluding_tax": 0,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": 1000000000
|
||||
"webhooks_delivered_at": null
|
||||
},
|
||||
"previous_attributes": {
|
||||
"attempted": false,
|
||||
@@ -234,13 +234,13 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbcODEQaroqDjs31hyuOmh",
|
||||
"id": "evt_1OIlXpDEQaroqDjsFjFkC07g",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 2,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0008",
|
||||
"idempotency_key": "2541b338-2700-4407-bd3e-79c1c2740aca"
|
||||
"id": "req_NORMALIZED0003",
|
||||
"idempotency_key": "8b119345-6159-4607-9010-e8237d20823b"
|
||||
},
|
||||
"type": "invoice.updated"
|
||||
},
|
||||
@@ -273,7 +273,7 @@
|
||||
"custom_fields": null,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"customer_address": null,
|
||||
"customer_email": "hamlet@zulip.com",
|
||||
"customer_email": "othello@zulip.com",
|
||||
"customer_name": null,
|
||||
"customer_phone": null,
|
||||
"customer_shipping": null,
|
||||
@@ -291,7 +291,7 @@
|
||||
"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,
|
||||
@@ -305,14 +305,14 @@
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000004",
|
||||
"invoice_item": "ii_NORMALIZED00000000000004",
|
||||
"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": {
|
||||
@@ -321,13 +321,13 @@
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"id": "price_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0004",
|
||||
"product": "prod_NORMALIZED0001",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -355,8 +355,8 @@
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000005",
|
||||
"invoice_item": "ii_NORMALIZED00000000000005",
|
||||
"id": "il_NORMALIZED00000000000002",
|
||||
"invoice_item": "ii_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -371,13 +371,13 @@
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000005",
|
||||
"id": "price_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0005",
|
||||
"product": "prod_NORMALIZED0002",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -401,7 +401,7 @@
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000001/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
@@ -457,13 +457,13 @@
|
||||
"webhooks_delivered_at": null
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbcNDEQaroqDjsmnQWayuN",
|
||||
"id": "evt_1OIlXoDEQaroqDjsll2CgAs8",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0009",
|
||||
"idempotency_key": "39ea7e83-6ae7-458b-9e77-9cd5f6990425"
|
||||
"id": "req_NORMALIZED0004",
|
||||
"idempotency_key": "294b5729-e1c0-42e1-b77a-2545f8f7006c"
|
||||
},
|
||||
"type": "invoice.created"
|
||||
},
|
||||
@@ -479,14 +479,14 @@
|
||||
"description": "Zulip Cloud Standard",
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "ii_NORMALIZED00000000000004",
|
||||
"id": "ii_NORMALIZED00000000000001",
|
||||
"invoice": null,
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "invoiceitem",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
"end": 1357095845,
|
||||
"start": 1325473445
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
@@ -495,13 +495,13 @@
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"id": "price_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0004",
|
||||
"product": "prod_NORMALIZED0001",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -519,13 +519,13 @@
|
||||
"unit_amount_decimal": "8000"
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbcMDEQaroqDjstamLiIzo",
|
||||
"id": "evt_1OIlXnDEQaroqDjsoAX0aCzf",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0010",
|
||||
"idempotency_key": "c7cee662-36c4-4ef2-886d-4091ee4762fa"
|
||||
"id": "req_NORMALIZED0005",
|
||||
"idempotency_key": "4ead5392-1ff9-44e0-943e-cd705accc213"
|
||||
},
|
||||
"type": "invoiceitem.created"
|
||||
},
|
||||
@@ -541,7 +541,7 @@
|
||||
"description": "Payment (Card ending in 4242)",
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "ii_NORMALIZED00000000000005",
|
||||
"id": "ii_NORMALIZED00000000000002",
|
||||
"invoice": null,
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
@@ -557,13 +557,13 @@
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000005",
|
||||
"id": "price_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0005",
|
||||
"product": "prod_NORMALIZED0002",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -581,13 +581,13 @@
|
||||
"unit_amount_decimal": "-48000"
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbcKDEQaroqDjsEApMF8PG",
|
||||
"id": "evt_1OIlXnDEQaroqDjsQ5wMmZEb",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0011",
|
||||
"idempotency_key": "a5d39edf-e1d3-4ece-88e6-3ec255393b99"
|
||||
"id": "req_NORMALIZED0006",
|
||||
"idempotency_key": "e5d2c5ec-9f6f-4f28-b5b9-e43e3f58b653"
|
||||
},
|
||||
"type": "invoiceitem.created"
|
||||
},
|
||||
@@ -605,12 +605,12 @@
|
||||
"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": "pm_1OAbcFDEQaroqDjsNEmc1jWB",
|
||||
"default_payment_method": "pm_1OIlXhDEQaroqDjsm8crnb7t",
|
||||
"footer": null,
|
||||
"rendering_options": null
|
||||
},
|
||||
@@ -633,13 +633,13 @@
|
||||
"default_currency": null
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbcKDEQaroqDjsJsD9kXvM",
|
||||
"id": "evt_1OIlXnDEQaroqDjsKXCIWpVq",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0011",
|
||||
"idempotency_key": "a5d39edf-e1d3-4ece-88e6-3ec255393b99"
|
||||
"id": "req_NORMALIZED0006",
|
||||
"idempotency_key": "e5d2c5ec-9f6f-4f28-b5b9-e43e3f58b653"
|
||||
},
|
||||
"type": "customer.updated"
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
"custom_fields": null,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"customer_address": null,
|
||||
"customer_email": "hamlet@zulip.com",
|
||||
"customer_email": "othello@zulip.com",
|
||||
"customer_name": null,
|
||||
"customer_phone": null,
|
||||
"customer_shipping": null,
|
||||
@@ -46,9 +46,9 @@
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlqR2NXRUhCcElNVjQxUkMxTVhsa3NTaTNqVklULDkwMDkwMTMz0200p4BwL0Y9?s=ap",
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlqR2NXRUhCcElNVjQxUkMxTVhsa3NTaTNqVklULDkwMDkwMTMz0200p4BwL0Y9/pdf?s=ap",
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpXWlpYcFFGQklGamtRUExacnBFdXlvU0I2dlZTLDkyMDM0OTEz0200nMuZd38e?s=ap",
|
||||
"id": "in_NORMALIZED00000000000001",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpXWlpYcFFGQklGamtRUExacnBFdXlvU0I2dlZTLDkyMDM0OTEz0200nMuZd38e/pdf?s=ap",
|
||||
"last_finalization_error": null,
|
||||
"latest_revision": null,
|
||||
"lines": {
|
||||
@@ -61,14 +61,14 @@
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000004",
|
||||
"invoice_item": "ii_NORMALIZED00000000000004",
|
||||
"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": {
|
||||
@@ -77,13 +77,13 @@
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"id": "price_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0004",
|
||||
"product": "prod_NORMALIZED0001",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -111,8 +111,8 @@
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000005",
|
||||
"invoice_item": "ii_NORMALIZED00000000000005",
|
||||
"id": "il_NORMALIZED00000000000002",
|
||||
"invoice_item": "ii_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -127,13 +127,13 @@
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000005",
|
||||
"id": "price_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0005",
|
||||
"product": "prod_NORMALIZED0002",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -157,12 +157,12 @@
|
||||
"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,
|
||||
@@ -210,16 +210,16 @@
|
||||
"total_excluding_tax": 0,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": 1000000000
|
||||
"webhooks_delivered_at": null
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbcPDEQaroqDjsb2wdOfq8",
|
||||
"id": "evt_1OIlXpDEQaroqDjsMH9F6Vqj",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"pending_webhooks": 2,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0008",
|
||||
"idempotency_key": "2541b338-2700-4407-bd3e-79c1c2740aca"
|
||||
"id": "req_NORMALIZED0003",
|
||||
"idempotency_key": "8b119345-6159-4607-9010-e8237d20823b"
|
||||
},
|
||||
"type": "invoice.payment_succeeded"
|
||||
},
|
||||
@@ -252,7 +252,7 @@
|
||||
"custom_fields": null,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"customer_address": null,
|
||||
"customer_email": "hamlet@zulip.com",
|
||||
"customer_email": "othello@zulip.com",
|
||||
"customer_name": null,
|
||||
"customer_phone": null,
|
||||
"customer_shipping": null,
|
||||
@@ -269,9 +269,9 @@
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlqR2NXRUhCcElNVjQxUkMxTVhsa3NTaTNqVklULDkwMDkwMTMz0200p4BwL0Y9?s=ap",
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlqR2NXRUhCcElNVjQxUkMxTVhsa3NTaTNqVklULDkwMDkwMTMz0200p4BwL0Y9/pdf?s=ap",
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpXWlpYcFFGQklGamtRUExacnBFdXlvU0I2dlZTLDkyMDM0OTEz0200nMuZd38e?s=ap",
|
||||
"id": "in_NORMALIZED00000000000001",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpXWlpYcFFGQklGamtRUExacnBFdXlvU0I2dlZTLDkyMDM0OTEz0200nMuZd38e/pdf?s=ap",
|
||||
"last_finalization_error": null,
|
||||
"latest_revision": null,
|
||||
"lines": {
|
||||
@@ -284,14 +284,14 @@
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000004",
|
||||
"invoice_item": "ii_NORMALIZED00000000000004",
|
||||
"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": {
|
||||
@@ -300,13 +300,13 @@
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"id": "price_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0004",
|
||||
"product": "prod_NORMALIZED0001",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -334,8 +334,8 @@
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000005",
|
||||
"invoice_item": "ii_NORMALIZED00000000000005",
|
||||
"id": "il_NORMALIZED00000000000002",
|
||||
"invoice_item": "ii_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -350,13 +350,13 @@
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000005",
|
||||
"id": "price_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0005",
|
||||
"product": "prod_NORMALIZED0002",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -380,12 +380,12 @@
|
||||
"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,
|
||||
@@ -433,16 +433,16 @@
|
||||
"total_excluding_tax": 0,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": 1000000000
|
||||
"webhooks_delivered_at": null
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbcPDEQaroqDjstFj6KICr",
|
||||
"id": "evt_1OIlXpDEQaroqDjsuTbOhFCj",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0008",
|
||||
"idempotency_key": "2541b338-2700-4407-bd3e-79c1c2740aca"
|
||||
"id": "req_NORMALIZED0003",
|
||||
"idempotency_key": "8b119345-6159-4607-9010-e8237d20823b"
|
||||
},
|
||||
"type": "invoice.paid"
|
||||
},
|
||||
@@ -475,7 +475,7 @@
|
||||
"custom_fields": null,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"customer_address": null,
|
||||
"customer_email": "hamlet@zulip.com",
|
||||
"customer_email": "othello@zulip.com",
|
||||
"customer_name": null,
|
||||
"customer_phone": null,
|
||||
"customer_shipping": null,
|
||||
@@ -492,9 +492,9 @@
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlqR2NXRUhCcElNVjQxUkMxTVhsa3NTaTNqVklULDkwMDkwMTMz0200p4BwL0Y9?s=ap",
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlqR2NXRUhCcElNVjQxUkMxTVhsa3NTaTNqVklULDkwMDkwMTMz0200p4BwL0Y9/pdf?s=ap",
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpXWlpYcFFGQklGamtRUExacnBFdXlvU0I2dlZTLDkyMDM0OTEz0200nMuZd38e?s=ap",
|
||||
"id": "in_NORMALIZED00000000000001",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpXWlpYcFFGQklGamtRUExacnBFdXlvU0I2dlZTLDkyMDM0OTEz0200nMuZd38e/pdf?s=ap",
|
||||
"last_finalization_error": null,
|
||||
"latest_revision": null,
|
||||
"lines": {
|
||||
@@ -507,14 +507,14 @@
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000004",
|
||||
"invoice_item": "ii_NORMALIZED00000000000004",
|
||||
"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": {
|
||||
@@ -523,13 +523,13 @@
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"id": "price_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0004",
|
||||
"product": "prod_NORMALIZED0001",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -557,8 +557,8 @@
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000005",
|
||||
"invoice_item": "ii_NORMALIZED00000000000005",
|
||||
"id": "il_NORMALIZED00000000000002",
|
||||
"invoice_item": "ii_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -573,13 +573,13 @@
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000005",
|
||||
"id": "price_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0005",
|
||||
"product": "prod_NORMALIZED0002",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -603,12 +603,12 @@
|
||||
"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,
|
||||
@@ -656,16 +656,16 @@
|
||||
"total_excluding_tax": 0,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": 1000000000
|
||||
"webhooks_delivered_at": null
|
||||
}
|
||||
},
|
||||
"id": "evt_1OAbcPDEQaroqDjs83DzADF2",
|
||||
"id": "evt_1OIlXpDEQaroqDjs9DRA4TlG",
|
||||
"livemode": false,
|
||||
"object": "event",
|
||||
"pending_webhooks": 0,
|
||||
"request": {
|
||||
"id": "req_NORMALIZED0008",
|
||||
"idempotency_key": "2541b338-2700-4407-bd3e-79c1c2740aca"
|
||||
"id": "req_NORMALIZED0003",
|
||||
"idempotency_key": "8b119345-6159-4607-9010-e8237d20823b"
|
||||
},
|
||||
"type": "invoice.finalized"
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
"custom_fields": null,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"customer_address": null,
|
||||
"customer_email": "hamlet@zulip.com",
|
||||
"customer_email": "othello@zulip.com",
|
||||
"customer_name": null,
|
||||
"customer_phone": null,
|
||||
"customer_shipping": null,
|
||||
@@ -41,7 +41,7 @@
|
||||
"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,
|
||||
@@ -55,14 +55,14 @@
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000004",
|
||||
"invoice_item": "ii_NORMALIZED00000000000004",
|
||||
"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": {
|
||||
@@ -71,13 +71,13 @@
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"id": "price_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0004",
|
||||
"product": "prod_NORMALIZED0001",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -105,8 +105,8 @@
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000005",
|
||||
"invoice_item": "ii_NORMALIZED00000000000005",
|
||||
"id": "il_NORMALIZED00000000000002",
|
||||
"invoice_item": "ii_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -121,13 +121,13 @@
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000005",
|
||||
"id": "price_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0005",
|
||||
"product": "prod_NORMALIZED0002",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -151,7 +151,7 @@
|
||||
"has_more": false,
|
||||
"object": "list",
|
||||
"total_count": 2,
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||
"url": "/v1/invoices/in_NORMALIZED00000000000001/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
"custom_fields": null,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"customer_address": null,
|
||||
"customer_email": "hamlet@zulip.com",
|
||||
"customer_email": "othello@zulip.com",
|
||||
"customer_name": null,
|
||||
"customer_phone": null,
|
||||
"customer_shipping": null,
|
||||
@@ -40,9 +40,9 @@
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"from_invoice": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlqR2NXRUhCcElNVjQxUkMxTVhsa3NTaTNqVklULDkwMDkwMTMy02005Nx2aWJ6?s=ap",
|
||||
"id": "in_NORMALIZED00000000000002",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9PeVlqR2NXRUhCcElNVjQxUkMxTVhsa3NTaTNqVklULDkwMDkwMTMy02005Nx2aWJ6/pdf?s=ap",
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpXWlpYcFFGQklGamtRUExacnBFdXlvU0I2dlZTLDkyMDM0OTEy0200M1ADhNeL?s=ap",
|
||||
"id": "in_NORMALIZED00000000000001",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QNnpXWlpYcFFGQklGamtRUExacnBFdXlvU0I2dlZTLDkyMDM0OTEy0200M1ADhNeL/pdf?s=ap",
|
||||
"last_finalization_error": null,
|
||||
"latest_revision": null,
|
||||
"lines": {
|
||||
@@ -55,14 +55,14 @@
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000004",
|
||||
"invoice_item": "ii_NORMALIZED00000000000004",
|
||||
"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": {
|
||||
@@ -71,13 +71,13 @@
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"id": "price_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0004",
|
||||
"product": "prod_NORMALIZED0001",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -105,8 +105,8 @@
|
||||
"discount_amounts": [],
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "il_NORMALIZED00000000000005",
|
||||
"invoice_item": "ii_NORMALIZED00000000000005",
|
||||
"id": "il_NORMALIZED00000000000002",
|
||||
"invoice_item": "ii_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "line_item",
|
||||
@@ -121,13 +121,13 @@
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000005",
|
||||
"id": "price_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0005",
|
||||
"product": "prod_NORMALIZED0002",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
@@ -151,12 +151,12 @@
|
||||
"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,
|
||||
@@ -204,5 +204,5 @@
|
||||
"total_excluding_tax": 0,
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": 1000000000
|
||||
"webhooks_delivered_at": null
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"description": "Payment (Card ending in 4242)",
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "ii_NORMALIZED00000000000005",
|
||||
"id": "ii_NORMALIZED00000000000002",
|
||||
"invoice": null,
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
@@ -22,13 +22,13 @@
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000005",
|
||||
"id": "price_NORMALIZED00000000000002",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0005",
|
||||
"product": "prod_NORMALIZED0002",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
"description": "Zulip Cloud Standard",
|
||||
"discountable": false,
|
||||
"discounts": [],
|
||||
"id": "ii_NORMALIZED00000000000004",
|
||||
"id": "ii_NORMALIZED00000000000001",
|
||||
"invoice": null,
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"object": "invoiceitem",
|
||||
"period": {
|
||||
"end": 1000000000,
|
||||
"start": 1000000000
|
||||
"end": 1357095845,
|
||||
"start": 1325473445
|
||||
},
|
||||
"plan": null,
|
||||
"price": {
|
||||
@@ -22,13 +22,13 @@
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"custom_unit_amount": null,
|
||||
"id": "price_NORMALIZED00000000000004",
|
||||
"id": "price_NORMALIZED00000000000001",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"object": "price",
|
||||
"product": "prod_NORMALIZED0004",
|
||||
"product": "prod_NORMALIZED0001",
|
||||
"recurring": null,
|
||||
"tax_behavior": "unspecified",
|
||||
"tiers_mode": null,
|
||||
|
||||
@@ -1,197 +0,0 @@
|
||||
{
|
||||
"amount": 48000,
|
||||
"amount_capturable": 0,
|
||||
"amount_details": {
|
||||
"tip": {}
|
||||
},
|
||||
"amount_received": 48000,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"automatic_payment_methods": null,
|
||||
"canceled_at": null,
|
||||
"cancellation_reason": null,
|
||||
"capture_method": "automatic",
|
||||
"charges": {
|
||||
"data": [
|
||||
{
|
||||
"amount": 48000,
|
||||
"amount_captured": 48000,
|
||||
"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, $80.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",
|
||||
"price_per_license": "8000",
|
||||
"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_1OAbcFDEQaroqDjsNEmc1jWB",
|
||||
"payment_method_details": {
|
||||
"card": {
|
||||
"amount_authorized": 48000,
|
||||
"brand": "visa",
|
||||
"checks": {
|
||||
"address_line1_check": null,
|
||||
"address_postal_code_check": null,
|
||||
"cvc_check": "pass"
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 11,
|
||||
"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": 48000,
|
||||
"status": "unavailable"
|
||||
},
|
||||
"three_d_secure": null,
|
||||
"wallet": null
|
||||
},
|
||||
"type": "card"
|
||||
},
|
||||
"receipt_email": "hamlet@zulip.com",
|
||||
"receipt_number": null,
|
||||
"receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKI6htKoGMgZrRJa5p8c6LBaQqU9TvM6TLNfSG8xRaNTk2w014WdBATBpwnd2VeGr6-PH-_sGeCAZZwrq",
|
||||
"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_NORMALIZED00000000000002"
|
||||
},
|
||||
"client_secret": "pi_NORMALIZED00000000000002_secret_GjSC2H9KhGusuka7dHcnSXXMq",
|
||||
"confirmation_method": "automatic",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": "Upgrade to Zulip Cloud Standard, $80.0 x 6",
|
||||
"id": "pi_NORMALIZED00000000000002",
|
||||
"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",
|
||||
"price_per_license": "8000",
|
||||
"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_1OAbcFDEQaroqDjsNEmc1jWB",
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"installments": null,
|
||||
"mandate_options": null,
|
||||
"network": null,
|
||||
"request_three_d_secure": "automatic"
|
||||
}
|
||||
},
|
||||
"payment_method_types": [
|
||||
"card"
|
||||
],
|
||||
"processing": null,
|
||||
"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
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
"amount_details": {
|
||||
"tip": {}
|
||||
},
|
||||
"amount_received": 0,
|
||||
"amount_received": 48000,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"automatic_payment_methods": null,
|
||||
@@ -12,40 +12,168 @@
|
||||
"cancellation_reason": null,
|
||||
"capture_method": "automatic",
|
||||
"charges": {
|
||||
"data": [],
|
||||
"data": [
|
||||
{
|
||||
"amount": 48000,
|
||||
"amount_captured": 48000,
|
||||
"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, $80.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": "8000",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
"seat_count": "6",
|
||||
"type": "upgrade",
|
||||
"user_email": "othello@zulip.com",
|
||||
"user_id": "12"
|
||||
},
|
||||
"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_1OIlXhDEQaroqDjsm8crnb7t",
|
||||
"payment_method_details": {
|
||||
"card": {
|
||||
"amount_authorized": 48000,
|
||||
"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": 48000,
|
||||
"status": "unavailable"
|
||||
},
|
||||
"three_d_secure": null,
|
||||
"wallet": null
|
||||
},
|
||||
"type": "card"
|
||||
},
|
||||
"radar_options": {},
|
||||
"receipt_email": "othello@zulip.com",
|
||||
"receipt_number": null,
|
||||
"receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKN76qqsGMgZgaui54Nc6LBbpn6dtN1hXcAVR2ChXte8Ecqdu3cWtk6VikFLgoeo7xJBfgY0LR4CIhJhe",
|
||||
"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,
|
||||
"url": "/v1/charges?payment_intent=pi_NORMALIZED00000000000002"
|
||||
"total_count": 1,
|
||||
"url": "/v1/charges?payment_intent=pi_NORMALIZED00000000000001"
|
||||
},
|
||||
"client_secret": "pi_NORMALIZED00000000000002_secret_GjSC2H9KhGusuka7dHcnSXXMq",
|
||||
"client_secret": "pi_NORMALIZED00000000000001_secret_gaaXxocbBjOepNzIQyoHlMcVE",
|
||||
"confirmation_method": "automatic",
|
||||
"created": 1000000000,
|
||||
"currency": "usd",
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": "Upgrade to Zulip Cloud Standard, $80.0 x 6",
|
||||
"id": "pi_NORMALIZED00000000000002",
|
||||
"id": "pi_NORMALIZED00000000000001",
|
||||
"invoice": null,
|
||||
"last_payment_error": null,
|
||||
"latest_charge": 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": "8000",
|
||||
"realm_id": "1",
|
||||
"realm_str": "zulip",
|
||||
"seat_count": "6",
|
||||
"type": "upgrade",
|
||||
"user_email": "hamlet@zulip.com",
|
||||
"user_id": "10"
|
||||
"user_email": "othello@zulip.com",
|
||||
"user_id": "12"
|
||||
},
|
||||
"next_action": null,
|
||||
"object": "payment_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": null,
|
||||
"payment_method": "pm_1OIlXhDEQaroqDjsm8crnb7t",
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
@@ -59,14 +187,14 @@
|
||||
"card"
|
||||
],
|
||||
"processing": null,
|
||||
"receipt_email": "hamlet@zulip.com",
|
||||
"receipt_email": "othello@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",
|
||||
"status": "succeeded",
|
||||
"transfer_data": null,
|
||||
"transfer_group": null
|
||||
}
|
||||
|
||||
@@ -2,21 +2,21 @@
|
||||
"application": null,
|
||||
"automatic_payment_methods": null,
|
||||
"cancellation_reason": null,
|
||||
"client_secret": "seti_1OAbcFDEQaroqDjsQfMm42ws_secret_OyYjgcW1HC7Fs8iRLfn8iQ35FmvPJmH",
|
||||
"client_secret": "seti_1OIlXiDEQaroqDjsvI6zH6rR_secret_P6zWBPBOAxlXilaHazyONXX4vFcGI5s",
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": null,
|
||||
"flow_directions": null,
|
||||
"id": "seti_1OAbcFDEQaroqDjsQfMm42ws",
|
||||
"id": "seti_1OIlXiDEQaroqDjsvI6zH6rR",
|
||||
"last_setup_error": null,
|
||||
"latest_attempt": "setatt_1OAbcFDEQaroqDjsJ6wKO7Zx",
|
||||
"latest_attempt": "setatt_1OIlXiDEQaroqDjs8vqJZ53H",
|
||||
"livemode": false,
|
||||
"mandate": null,
|
||||
"metadata": {},
|
||||
"next_action": null,
|
||||
"object": "setup_intent",
|
||||
"on_behalf_of": null,
|
||||
"payment_method": "pm_1OAbcFDEQaroqDjsNEmc1jWB",
|
||||
"payment_method": "pm_1OIlXhDEQaroqDjsm8crnb7t",
|
||||
"payment_method_configuration_details": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
"application": null,
|
||||
"automatic_payment_methods": null,
|
||||
"cancellation_reason": null,
|
||||
"client_secret": "seti_1OAbcDDEQaroqDjs6URoWzLY_secret_OyYj6KwwzRa2rP52fvEQaNH3OWcEQfU",
|
||||
"client_secret": "seti_1OIlXhDEQaroqDjs1fXXuFlu_secret_P6zWkqWwRlOqpbP3JGSRFT1s92F1sUU",
|
||||
"created": 1000000000,
|
||||
"customer": "cus_NORMALIZED0001",
|
||||
"description": null,
|
||||
"flow_directions": null,
|
||||
"id": "seti_1OAbcDDEQaroqDjs6URoWzLY",
|
||||
"id": "seti_1OIlXhDEQaroqDjs1fXXuFlu",
|
||||
"last_setup_error": null,
|
||||
"latest_attempt": null,
|
||||
"livemode": false,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user