You've already forked AstralRinth
forked from didirus/AstralRinth
Add balance route (#3107)
This commit is contained in:
@@ -68,6 +68,9 @@ PAYPAL_API_URL=https://api-m.sandbox.paypal.com/v1/
|
||||
PAYPAL_WEBHOOK_ID=none
|
||||
PAYPAL_CLIENT_ID=none
|
||||
PAYPAL_CLIENT_SECRET=none
|
||||
PAYPAL_NVP_USERNAME=none
|
||||
PAYPAL_NVP_PASSWORD=none
|
||||
PAYPAL_NVP_SIGNATURE=none
|
||||
|
||||
STEAM_API_KEY=none
|
||||
|
||||
@@ -106,4 +109,7 @@ STRIPE_WEBHOOK_SECRET=none
|
||||
|
||||
ADITUDE_API_KEY=none
|
||||
|
||||
PYRO_API_KEY=none
|
||||
PYRO_API_KEY=none
|
||||
|
||||
BREX_API_URL=https://platform.brexapis.com/v2/
|
||||
BREX_API_KEY=none
|
||||
@@ -99,7 +99,7 @@
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
false
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "109b6307ff4b06297ddd45ac2385e6a445ee4a4d4f447816dfcd059892c8b68b"
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
false
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "6bcbb0c584804c492ccee49ba0449a8a1cd88fa5d85d4cd6533f65d4c8021634"
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
false
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "7fb6f7e0b2b993d4b89146fdd916dbd7efe31a42127f15c9617caa00d60b7bcc"
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
false
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "8f51f552d1c63fa818cbdba581691e97f693a187ed05224a44adeee68c6809d1"
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
false
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "99cca53fd3f35325e2da3b671532bf98b8c7ad8e7cb9158e4eb9c5bac66d20b2"
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
false
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "bfcbcadda1e323d56b6a21fc060c56bff2f38a54cf65dd1cc21f209240c7091b"
|
||||
|
||||
@@ -448,6 +448,9 @@ pub fn check_env_vars() -> bool {
|
||||
failed |= check_var::<String>("PAYPAL_WEBHOOK_ID");
|
||||
failed |= check_var::<String>("PAYPAL_CLIENT_ID");
|
||||
failed |= check_var::<String>("PAYPAL_CLIENT_SECRET");
|
||||
failed |= check_var::<String>("PAYPAL_NVP_USERNAME");
|
||||
failed |= check_var::<String>("PAYPAL_NVP_PASSWORD");
|
||||
failed |= check_var::<String>("PAYPAL_NVP_SIGNATURE");
|
||||
|
||||
failed |= check_var::<String>("HCAPTCHA_SECRET");
|
||||
|
||||
@@ -482,9 +485,11 @@ pub fn check_env_vars() -> bool {
|
||||
failed |= check_var::<String>("STRIPE_API_KEY");
|
||||
failed |= check_var::<String>("STRIPE_WEBHOOK_SECRET");
|
||||
|
||||
failed |= check_var::<u64>("ADITUDE_API_KEY");
|
||||
failed |= check_var::<String>("ADITUDE_API_KEY");
|
||||
|
||||
failed |= check_var::<String>("PYRO_API_KEY");
|
||||
|
||||
failed |= check_var::<String>("BREX_API_KEY");
|
||||
|
||||
failed
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ pub struct PayoutsQueue {
|
||||
payout_options: RwLock<Option<PayoutMethods>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Debug)]
|
||||
struct PayPalCredentials {
|
||||
access_token: String,
|
||||
token_type: String,
|
||||
@@ -36,6 +36,12 @@ struct PayoutMethods {
|
||||
expires: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct AccountBalance {
|
||||
pub available: Decimal,
|
||||
pub pending: Decimal,
|
||||
}
|
||||
|
||||
impl Default for PayoutsQueue {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
@@ -545,6 +551,136 @@ impl PayoutsQueue {
|
||||
|
||||
Ok(options.options)
|
||||
}
|
||||
|
||||
pub async fn get_brex_balance() -> Result<Option<AccountBalance>, ApiError>
|
||||
{
|
||||
#[derive(Deserialize)]
|
||||
struct BrexBalance {
|
||||
pub amount: i64,
|
||||
// pub currency: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct BrexAccount {
|
||||
pub current_balance: BrexBalance,
|
||||
pub available_balance: BrexBalance,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct BrexResponse {
|
||||
pub items: Vec<BrexAccount>,
|
||||
}
|
||||
|
||||
let client = reqwest::Client::new();
|
||||
let res = client
|
||||
.get(format!("{}accounts/cash", dotenvy::var("BREX_API_URL")?))
|
||||
.bearer_auth(&dotenvy::var("BREX_API_KEY")?)
|
||||
.send()
|
||||
.await?
|
||||
.json::<BrexResponse>()
|
||||
.await?;
|
||||
|
||||
Ok(Some(AccountBalance {
|
||||
available: Decimal::from(
|
||||
res.items
|
||||
.iter()
|
||||
.map(|x| x.available_balance.amount)
|
||||
.sum::<i64>(),
|
||||
) / Decimal::from(100),
|
||||
pending: Decimal::from(
|
||||
res.items
|
||||
.iter()
|
||||
.map(|x| {
|
||||
x.current_balance.amount - x.available_balance.amount
|
||||
})
|
||||
.sum::<i64>(),
|
||||
) / Decimal::from(100),
|
||||
}))
|
||||
}
|
||||
|
||||
pub async fn get_paypal_balance() -> Result<Option<AccountBalance>, ApiError>
|
||||
{
|
||||
let api_username = dotenvy::var("PAYPAL_NVP_USERNAME")?;
|
||||
let api_password = dotenvy::var("PAYPAL_NVP_PASSWORD")?;
|
||||
let api_signature = dotenvy::var("PAYPAL_NVP_SIGNATURE")?;
|
||||
|
||||
let mut params = HashMap::new();
|
||||
params.insert("METHOD", "GetBalance");
|
||||
params.insert("VERSION", "204");
|
||||
params.insert("USER", &api_username);
|
||||
params.insert("PWD", &api_password);
|
||||
params.insert("SIGNATURE", &api_signature);
|
||||
params.insert("RETURNALLCURRENCIES", "1");
|
||||
|
||||
let endpoint = "https://api-3t.paypal.com/nvp";
|
||||
|
||||
let client = reqwest::Client::new();
|
||||
let response = client.post(endpoint).form(¶ms).send().await?;
|
||||
|
||||
let text = response.text().await?;
|
||||
let body = urlencoding::decode(&text).unwrap_or_default();
|
||||
|
||||
let mut key_value_map = HashMap::new();
|
||||
|
||||
for pair in body.split('&') {
|
||||
let mut iter = pair.splitn(2, '=');
|
||||
if let (Some(key), Some(value)) = (iter.next(), iter.next()) {
|
||||
key_value_map.insert(key.to_string(), value.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(amount) = key_value_map
|
||||
.get("L_AMT0")
|
||||
.and_then(|x| Decimal::from_str_exact(x).ok())
|
||||
{
|
||||
Ok(Some(AccountBalance {
|
||||
available: amount,
|
||||
pending: Decimal::ZERO,
|
||||
}))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_tremendous_balance(
|
||||
&self,
|
||||
) -> Result<Option<AccountBalance>, ApiError> {
|
||||
#[derive(Deserialize)]
|
||||
struct FundingSourceMeta {
|
||||
available_cents: u64,
|
||||
pending_cents: u64,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct FundingSource {
|
||||
method: String,
|
||||
meta: FundingSourceMeta,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct FundingSourceRequest {
|
||||
pub funding_sources: Vec<FundingSource>,
|
||||
}
|
||||
|
||||
let val = self
|
||||
.make_tremendous_request::<(), FundingSourceRequest>(
|
||||
Method::GET,
|
||||
"funding_sources",
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(val
|
||||
.funding_sources
|
||||
.into_iter()
|
||||
.find(|x| x.method == "balance")
|
||||
.map(|x| AccountBalance {
|
||||
available: Decimal::from(x.meta.available_cents)
|
||||
/ Decimal::from(100),
|
||||
pending: Decimal::from(x.meta.pending_cents)
|
||||
/ Decimal::from(100),
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
||||
@@ -5,12 +5,13 @@ use crate::models::ids::ProjectId;
|
||||
use crate::models::pats::Scopes;
|
||||
use crate::queue::analytics::AnalyticsQueue;
|
||||
use crate::queue::maxmind::MaxMindIndexer;
|
||||
use crate::queue::payouts::PayoutsQueue;
|
||||
use crate::queue::session::AuthQueue;
|
||||
use crate::routes::ApiError;
|
||||
use crate::search::SearchConfig;
|
||||
use crate::util::date::get_current_tenths_of_ms;
|
||||
use crate::util::guards::admin_key_guard;
|
||||
use actix_web::{patch, post, web, HttpRequest, HttpResponse};
|
||||
use actix_web::{get, patch, post, web, HttpRequest, HttpResponse};
|
||||
use serde::Deserialize;
|
||||
use sqlx::PgPool;
|
||||
use std::collections::HashMap;
|
||||
@@ -21,7 +22,8 @@ pub fn config(cfg: &mut web::ServiceConfig) {
|
||||
cfg.service(
|
||||
web::scope("admin")
|
||||
.service(count_download)
|
||||
.service(force_reindex),
|
||||
.service(force_reindex)
|
||||
.service(get_balances),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -158,3 +160,21 @@ pub async fn force_reindex(
|
||||
index_projects(pool.as_ref().clone(), redis.clone(), &config).await?;
|
||||
Ok(HttpResponse::NoContent().finish())
|
||||
}
|
||||
|
||||
#[get("/_balances", guard = "admin_key_guard")]
|
||||
pub async fn get_balances(
|
||||
payouts: web::Data<PayoutsQueue>,
|
||||
) -> Result<HttpResponse, ApiError> {
|
||||
let (paypal, brex, tremendous) = futures::future::try_join3(
|
||||
PayoutsQueue::get_paypal_balance(),
|
||||
PayoutsQueue::get_brex_balance(),
|
||||
payouts.get_tremendous_balance(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(HttpResponse::Ok().json(serde_json::json!({
|
||||
"paypal": paypal,
|
||||
"brex": brex,
|
||||
"tremendous": tremendous,
|
||||
})))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user