stripe sub cancellations
This commit is contained in:
+3
-1
@@ -146,6 +146,8 @@ fn main() {
|
||||
let pg_pool = pool.clone();
|
||||
let mailer = mail::listen(mail_rx);
|
||||
|
||||
let stripe = payments::stripe_client();
|
||||
|
||||
spawn(move || http::start(http_pool, mailer));
|
||||
spawn(move || warden.listen());
|
||||
spawn(move || warden::upkeep_tick(warden_tick_tx));
|
||||
@@ -154,5 +156,5 @@ fn main() {
|
||||
|
||||
// the main thread becomes this ws listener
|
||||
let rpc_pool = pool.clone();
|
||||
rpc::start(rpc_pool, rpc_events_tx);
|
||||
rpc::start(rpc_pool, rpc_events_tx, stripe);
|
||||
}
|
||||
|
||||
+47
-3
@@ -1,3 +1,4 @@
|
||||
use std::env;
|
||||
use std::io::Read;
|
||||
|
||||
use http::State;
|
||||
@@ -12,15 +13,16 @@ use postgres::transaction::Transaction;
|
||||
use failure::Error;
|
||||
use failure::err_msg;
|
||||
|
||||
use stripe::{Event, EventObject, CheckoutSession, SubscriptionStatus};
|
||||
use stripe::{Client, Event, EventObject, CheckoutSession, SubscriptionStatus};
|
||||
|
||||
use http::{MnmlHttpError};
|
||||
use pg::{PgPool};
|
||||
use account;
|
||||
use account::Account;
|
||||
|
||||
pub fn subscription_account(tx: &mut Transaction, sub: String) -> Result<Uuid, Error> {
|
||||
let query = "
|
||||
SELECT account
|
||||
SELECT account, customer, checkout, subscription
|
||||
FROM stripe_subscriptions
|
||||
WHERE subscription = $1;
|
||||
";
|
||||
@@ -34,6 +36,41 @@ pub fn subscription_account(tx: &mut Transaction, sub: String) -> Result<Uuid, E
|
||||
Ok(row.get(0))
|
||||
}
|
||||
|
||||
pub fn subscription_cancel(tx: &mut Transaction, client: &Client, account: &Account) -> Result<Option<String>, Error> {
|
||||
let query = "
|
||||
SELECT account, customer, checkout, subscription
|
||||
FROM stripe_subscriptions
|
||||
WHERE account = $1;
|
||||
";
|
||||
|
||||
let result = tx
|
||||
.query(query, &[&account.id])?;
|
||||
|
||||
let row = result.iter().next()
|
||||
.ok_or(err_msg("user not subscribed"))?;
|
||||
|
||||
let _customer: String = row.get(1);
|
||||
let _checkout: String = row.get(2);
|
||||
let subscription: String = row.get(3);
|
||||
|
||||
let id = subscription.parse()?;
|
||||
let mut params = stripe::UpdateSubscription::new();
|
||||
params.cancel_at_period_end = Some(true);
|
||||
|
||||
let updated = match stripe::Subscription::update(client, &id, params) {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
warn!("{:?}", e);
|
||||
return Err(err_msg("unable to cancel subscription"));
|
||||
}
|
||||
};
|
||||
|
||||
info!("subscription cancelled account={:?} subscription={:?}", account, updated);
|
||||
|
||||
Ok(Some(updated.status.to_string()))
|
||||
}
|
||||
|
||||
|
||||
// we use i64 because it is converted to BIGINT for pg
|
||||
// and we can losslessly pull it into u32 which is big
|
||||
// enough for the ballers
|
||||
@@ -45,7 +82,7 @@ const CREDITS_SUB_BONUS: i64 = 40;
|
||||
// we ensure that we store each object in pg with a link to the object
|
||||
// and to the account id in case of refunds
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
enum StripeData {
|
||||
pub enum StripeData {
|
||||
Customer { account: Uuid, customer: String, checkout: String },
|
||||
Subscription { account: Uuid, customer: String, checkout: String, subscription: String, },
|
||||
|
||||
@@ -211,6 +248,13 @@ pub fn stripe(req: &mut Request) -> IronResult<Response> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stripe_client() -> Client {
|
||||
let secret = env::var("STRIPE_SECRET")
|
||||
.expect("STRIPE_SECRET must be set");
|
||||
|
||||
stripe::Client::new(secret)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
+17
-3
@@ -11,6 +11,8 @@ use failure::err_msg;
|
||||
use serde_cbor::{from_slice, to_vec};
|
||||
use cookie::Cookie;
|
||||
|
||||
use stripe::Client as StripeClient;
|
||||
|
||||
use crossbeam_channel::{unbounded, Sender as CbSender};
|
||||
use ws::{listen, CloseCode, Message, Handler, Request, Response};
|
||||
|
||||
@@ -23,6 +25,7 @@ use instance::{Instance, instance_state, instance_practice, instance_ready};
|
||||
use item::{Item, ItemInfoCtr, item_info};
|
||||
use mtx;
|
||||
use mail;
|
||||
use payments;
|
||||
use mail::Email;
|
||||
use pg::{Db};
|
||||
use pg::{PgPool};
|
||||
@@ -37,6 +40,7 @@ pub enum RpcMessage {
|
||||
AccountTeam(Vec<Construct>),
|
||||
AccountInstances(Vec<Instance>),
|
||||
AccountShop(mtx::Shop),
|
||||
AccountSubscription(Option<String>),
|
||||
ConstructSpawn(Construct),
|
||||
EmailState(Email),
|
||||
GameState(Game),
|
||||
@@ -44,6 +48,7 @@ pub enum RpcMessage {
|
||||
|
||||
InstanceState(Instance),
|
||||
|
||||
|
||||
Pong(()),
|
||||
|
||||
DevResolutions(Resolutions),
|
||||
@@ -75,6 +80,8 @@ enum RpcRequest {
|
||||
AccountConstructs {},
|
||||
AccountSetTeam { ids: Vec<Uuid> },
|
||||
|
||||
SubscriptionCancel {},
|
||||
|
||||
InstanceQueue {},
|
||||
InstancePractice {},
|
||||
InstanceReady { instance_id: Uuid },
|
||||
@@ -92,6 +99,7 @@ struct Connection {
|
||||
pub id: usize,
|
||||
pub ws: CbSender<RpcMessage>,
|
||||
pool: PgPool,
|
||||
stripe: StripeClient,
|
||||
account: Option<Account>,
|
||||
events: CbSender<Event>,
|
||||
}
|
||||
@@ -192,6 +200,9 @@ impl Connection {
|
||||
RpcRequest::MtxBuy { mtx } =>
|
||||
Ok(RpcMessage::AccountShop(mtx::buy(&mut tx, account, mtx)?)),
|
||||
|
||||
RpcRequest::SubscriptionCancel { } =>
|
||||
Ok(RpcMessage::AccountSubscription(payments::subscription_cancel(&mut tx, &self.stripe, account)?)),
|
||||
|
||||
_ => Err(format_err!("unknown request request={:?}", request)),
|
||||
};
|
||||
|
||||
@@ -270,8 +281,10 @@ impl Handler for Connection {
|
||||
// if the user queries the state of something
|
||||
// we tell events to push updates to them
|
||||
match reply {
|
||||
RpcMessage::AccountState(ref v) =>
|
||||
self.events.send(Event::Subscribe(self.id, v.id)).unwrap(),
|
||||
RpcMessage::AccountState(ref v) => {
|
||||
self.account = Some(v.clone());
|
||||
self.events.send(Event::Subscribe(self.id, v.id)).unwrap()
|
||||
},
|
||||
RpcMessage::GameState(ref v) =>
|
||||
self.events.send(Event::Subscribe(self.id, v.id)).unwrap(),
|
||||
RpcMessage::InstanceState(ref v) =>
|
||||
@@ -332,7 +345,7 @@ impl Handler for Connection {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start(pool: PgPool, events_tx: CbSender<Event>) {
|
||||
pub fn start(pool: PgPool, events_tx: CbSender<Event>, stripe: StripeClient) {
|
||||
let mut rng = thread_rng();
|
||||
listen("127.0.0.1:40055", move |out| {
|
||||
|
||||
@@ -364,6 +377,7 @@ pub fn start(pool: PgPool, events_tx: CbSender<Event>) {
|
||||
account: None,
|
||||
ws: tx,
|
||||
pool: pool.clone(),
|
||||
stripe: stripe.clone(),
|
||||
events: events_tx.clone(),
|
||||
}
|
||||
}).unwrap();
|
||||
|
||||
Reference in New Issue
Block a user