You've already forked AstralRinth
forked from didirus/AstralRinth
Store method ID for payouts (#4752)
* Store method ID for payouts * Fixes
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"db_name": "PostgreSQL",
|
"db_name": "PostgreSQL",
|
||||||
"query": "\n SELECT id, user_id, created, amount, status, method, method_address, platform_id, fee\n FROM payouts\n WHERE id = ANY($1)\n ",
|
"query": "\n SELECT id, user_id, created, amount, status, method, method_id, method_address, platform_id, fee\n FROM payouts\n WHERE id = ANY($1)\n ",
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
@@ -35,16 +35,21 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ordinal": 6,
|
"ordinal": 6,
|
||||||
"name": "method_address",
|
"name": "method_id",
|
||||||
"type_info": "Text"
|
"type_info": "Text"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ordinal": 7,
|
"ordinal": 7,
|
||||||
"name": "platform_id",
|
"name": "method_address",
|
||||||
"type_info": "Text"
|
"type_info": "Text"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ordinal": 8,
|
"ordinal": 8,
|
||||||
|
"name": "platform_id",
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 9,
|
||||||
"name": "fee",
|
"name": "fee",
|
||||||
"type_info": "Numeric"
|
"type_info": "Numeric"
|
||||||
}
|
}
|
||||||
@@ -63,8 +68,9 @@
|
|||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
|
true,
|
||||||
true
|
true
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"hash": "83f8d3fcc4ba1544f593abaf29c79157bc35e3fca79cc93f6512ca01acd8e5ce"
|
"hash": "2aa9704c9ead520fb61b4ca1e94c7c70a245b0cc48ae3f4883393bfd57a685f1"
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"db_name": "PostgreSQL",
|
"db_name": "PostgreSQL",
|
||||||
"query": "\n INSERT INTO payouts (\n id, amount, fee, user_id, status, method, method_address, platform_id\n )\n VALUES (\n $1, $2, $3, $4, $5, $6, $7, $8\n )\n ",
|
"query": "\n INSERT INTO payouts (\n id, amount, fee, user_id, status, method, method_id, method_address, platform_id\n )\n VALUES (\n $1, $2, $3, $4, $5, $6, $7, $8, $9\n )\n ",
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
@@ -12,10 +12,11 @@
|
|||||||
"Varchar",
|
"Varchar",
|
||||||
"Text",
|
"Text",
|
||||||
"Text",
|
"Text",
|
||||||
|
"Text",
|
||||||
"Text"
|
"Text"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"nullable": []
|
"nullable": []
|
||||||
},
|
},
|
||||||
"hash": "285c089b43bf0225ba03e279f7a227c3483bae818d077efdc54e588b858c8760"
|
"hash": "c82bf13a2567f772a4c6eb3329971049791dab817ac07708873ac57986c17e2c"
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE payouts
|
||||||
|
ADD COLUMN method_id TEXT;
|
||||||
@@ -15,7 +15,11 @@ pub struct DBPayout {
|
|||||||
|
|
||||||
pub fee: Option<Decimal>,
|
pub fee: Option<Decimal>,
|
||||||
pub method: Option<PayoutMethodType>,
|
pub method: Option<PayoutMethodType>,
|
||||||
|
/// See [`crate::models::v3::payouts::Payout::method_id`].
|
||||||
|
pub method_id: Option<String>,
|
||||||
|
/// See [`crate::models::v3::payouts::Payout::method_address`].
|
||||||
pub method_address: Option<String>,
|
pub method_address: Option<String>,
|
||||||
|
/// See [`crate::models::v3::payouts::Payout::platform_id`].
|
||||||
pub platform_id: Option<String>,
|
pub platform_id: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,10 +31,10 @@ impl DBPayout {
|
|||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
"
|
"
|
||||||
INSERT INTO payouts (
|
INSERT INTO payouts (
|
||||||
id, amount, fee, user_id, status, method, method_address, platform_id
|
id, amount, fee, user_id, status, method, method_id, method_address, platform_id
|
||||||
)
|
)
|
||||||
VALUES (
|
VALUES (
|
||||||
$1, $2, $3, $4, $5, $6, $7, $8
|
$1, $2, $3, $4, $5, $6, $7, $8, $9
|
||||||
)
|
)
|
||||||
",
|
",
|
||||||
self.id.0,
|
self.id.0,
|
||||||
@@ -39,6 +43,7 @@ impl DBPayout {
|
|||||||
self.user_id.0,
|
self.user_id.0,
|
||||||
self.status.as_str(),
|
self.status.as_str(),
|
||||||
self.method.as_ref().map(|x| x.as_str()),
|
self.method.as_ref().map(|x| x.as_str()),
|
||||||
|
self.method_id,
|
||||||
self.method_address,
|
self.method_address,
|
||||||
self.platform_id,
|
self.platform_id,
|
||||||
)
|
)
|
||||||
@@ -71,7 +76,7 @@ impl DBPayout {
|
|||||||
|
|
||||||
let results = sqlx::query!(
|
let results = sqlx::query!(
|
||||||
"
|
"
|
||||||
SELECT id, user_id, created, amount, status, method, method_address, platform_id, fee
|
SELECT id, user_id, created, amount, status, method, method_id, method_address, platform_id, fee
|
||||||
FROM payouts
|
FROM payouts
|
||||||
WHERE id = ANY($1)
|
WHERE id = ANY($1)
|
||||||
",
|
",
|
||||||
@@ -85,6 +90,7 @@ impl DBPayout {
|
|||||||
status: PayoutStatus::from_string(&r.status),
|
status: PayoutStatus::from_string(&r.status),
|
||||||
amount: r.amount,
|
amount: r.amount,
|
||||||
method: r.method.and_then(|x| PayoutMethodType::from_string(&x)),
|
method: r.method.and_then(|x| PayoutMethodType::from_string(&x)),
|
||||||
|
method_id: r.method_id,
|
||||||
method_address: r.method_address,
|
method_address: r.method_address,
|
||||||
platform_id: r.platform_id,
|
platform_id: r.platform_id,
|
||||||
fee: r.fee,
|
fee: r.fee,
|
||||||
|
|||||||
@@ -18,8 +18,17 @@ pub struct Payout {
|
|||||||
#[serde(with = "rust_decimal::serde::float_option")]
|
#[serde(with = "rust_decimal::serde::float_option")]
|
||||||
pub fee: Option<Decimal>,
|
pub fee: Option<Decimal>,
|
||||||
pub method: Option<PayoutMethodType>,
|
pub method: Option<PayoutMethodType>,
|
||||||
/// the address this payout was sent to: ex: email, paypal email, venmo handle
|
/// Platform-dependent identifier for the submethod.
|
||||||
|
///
|
||||||
|
/// See [`crate::routes::v3::payouts::TransactionItem::Withdrawal::method_id`].
|
||||||
|
pub method_id: Option<String>,
|
||||||
|
/// Address this payout was sent to: ex: email, paypal email, venmo handle.
|
||||||
pub method_address: Option<String>,
|
pub method_address: Option<String>,
|
||||||
|
/// Platform-provided opaque identifier for the transaction linked to this payout.
|
||||||
|
///
|
||||||
|
/// - Tremendous: reward ID
|
||||||
|
/// - Mural: payout request UUID
|
||||||
|
/// - PayPal/Venmo: transaction ID
|
||||||
pub platform_id: Option<String>,
|
pub platform_id: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,6 +42,7 @@ impl Payout {
|
|||||||
amount: data.amount,
|
amount: data.amount,
|
||||||
fee: data.fee,
|
fee: data.fee,
|
||||||
method: data.method,
|
method: data.method,
|
||||||
|
method_id: data.method_id,
|
||||||
method_address: data.method_address,
|
method_address: data.method_address,
|
||||||
platform_id: data.platform_id,
|
platform_id: data.platform_id,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use crate::models::payouts::{
|
|||||||
MuralPayDetails, PayoutMethodRequest, PayoutMethodType, PayoutStatus,
|
MuralPayDetails, PayoutMethodRequest, PayoutMethodType, PayoutStatus,
|
||||||
TremendousDetails, TremendousForexResponse,
|
TremendousDetails, TremendousForexResponse,
|
||||||
};
|
};
|
||||||
|
use crate::queue::payouts::mural::MuralPayoutRequest;
|
||||||
use crate::queue::payouts::{PayoutFees, PayoutsQueue};
|
use crate::queue::payouts::{PayoutFees, PayoutsQueue};
|
||||||
use crate::queue::session::AuthQueue;
|
use crate::queue::session::AuthQueue;
|
||||||
use crate::routes::ApiError;
|
use crate::routes::ApiError;
|
||||||
@@ -772,6 +773,7 @@ async fn tremendous_payout(
|
|||||||
amount: amount_minus_fee,
|
amount: amount_minus_fee,
|
||||||
fee: Some(total_fee),
|
fee: Some(total_fee),
|
||||||
method: Some(PayoutMethodType::Tremendous),
|
method: Some(PayoutMethodType::Tremendous),
|
||||||
|
method_id: Some(body.method_id.clone()),
|
||||||
method_address: Some(user_email.to_string()),
|
method_address: Some(user_email.to_string()),
|
||||||
platform_id,
|
platform_id,
|
||||||
})
|
})
|
||||||
@@ -806,6 +808,16 @@ async fn mural_pay_payout(
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
let method_id = match &details.payout_details {
|
||||||
|
MuralPayoutRequest::Blockchain { .. } => {
|
||||||
|
"blockchain-usdc-polygon".to_string()
|
||||||
|
}
|
||||||
|
MuralPayoutRequest::Fiat {
|
||||||
|
fiat_and_rail_details,
|
||||||
|
..
|
||||||
|
} => fiat_and_rail_details.code().to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
Ok(DBPayout {
|
Ok(DBPayout {
|
||||||
id: payout_id,
|
id: payout_id,
|
||||||
user_id: user.id,
|
user_id: user.id,
|
||||||
@@ -814,6 +826,7 @@ async fn mural_pay_payout(
|
|||||||
amount: amount_minus_fee,
|
amount: amount_minus_fee,
|
||||||
fee: Some(total_fee),
|
fee: Some(total_fee),
|
||||||
method: Some(PayoutMethodType::MuralPay),
|
method: Some(PayoutMethodType::MuralPay),
|
||||||
|
method_id: Some(method_id),
|
||||||
method_address: Some(user_email.to_string()),
|
method_address: Some(user_email.to_string()),
|
||||||
platform_id: Some(payout_request.id.to_string()),
|
platform_id: Some(payout_request.id.to_string()),
|
||||||
})
|
})
|
||||||
@@ -883,18 +896,6 @@ async fn paypal_payout(
|
|||||||
pub links: Vec<PayPalLink>,
|
pub links: Vec<PayPalLink>,
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut payout_item = crate::database::models::payout_item::DBPayout {
|
|
||||||
id: payout_id,
|
|
||||||
user_id: user.id,
|
|
||||||
created: Utc::now(),
|
|
||||||
status: PayoutStatus::InTransit,
|
|
||||||
amount: amount_minus_fee,
|
|
||||||
fee: Some(total_fee),
|
|
||||||
method: Some(body.method.method_type()),
|
|
||||||
method_address: Some(display_address.clone()),
|
|
||||||
platform_id: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let res: PayoutsResponse = payouts_queue.make_paypal_request(
|
let res: PayoutsResponse = payouts_queue.make_paypal_request(
|
||||||
Method::POST,
|
Method::POST,
|
||||||
"payments/payouts",
|
"payments/payouts",
|
||||||
@@ -922,33 +923,50 @@ async fn paypal_payout(
|
|||||||
None
|
None
|
||||||
).await?;
|
).await?;
|
||||||
|
|
||||||
if let Some(link) = res.links.first() {
|
let link = res
|
||||||
#[derive(Deserialize)]
|
.links
|
||||||
struct PayoutItem {
|
.first()
|
||||||
pub payout_item_id: String,
|
.wrap_request_err("no PayPal links available")?;
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct PayoutData {
|
struct PayoutItem {
|
||||||
pub items: Vec<PayoutItem>,
|
pub payout_item_id: String,
|
||||||
}
|
|
||||||
|
|
||||||
if let Ok(res) = payouts_queue
|
|
||||||
.make_paypal_request::<(), PayoutData>(
|
|
||||||
Method::GET,
|
|
||||||
&link.href,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
Some(true),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
&& let Some(data) = res.items.first()
|
|
||||||
{
|
|
||||||
payout_item.platform_id = Some(data.payout_item_id.clone());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(payout_item)
|
#[derive(Deserialize)]
|
||||||
|
struct PayoutData {
|
||||||
|
pub items: Vec<PayoutItem>,
|
||||||
|
}
|
||||||
|
|
||||||
|
let res = payouts_queue
|
||||||
|
.make_paypal_request::<(), PayoutData>(
|
||||||
|
Method::GET,
|
||||||
|
&link.href,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
Some(true),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.wrap_internal_err("failed to make PayPal request")?;
|
||||||
|
let data = res
|
||||||
|
.items
|
||||||
|
.first()
|
||||||
|
.wrap_internal_err("no payout items returned from PayPal request")?;
|
||||||
|
|
||||||
|
let platform_id = Some(data.payout_item_id.clone());
|
||||||
|
|
||||||
|
Ok(DBPayout {
|
||||||
|
id: payout_id,
|
||||||
|
user_id: user.id,
|
||||||
|
created: Utc::now(),
|
||||||
|
status: PayoutStatus::InTransit,
|
||||||
|
amount: amount_minus_fee,
|
||||||
|
fee: Some(total_fee),
|
||||||
|
method: Some(body.method.method_type()),
|
||||||
|
method_id: Some(body.method_id.clone()),
|
||||||
|
method_address: Some(display_address.clone()),
|
||||||
|
platform_id,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// User performing a payout-related action.
|
/// User performing a payout-related action.
|
||||||
@@ -972,9 +990,11 @@ pub enum TransactionItem {
|
|||||||
/// Payout-method-specific ID for the type of payout the user got.
|
/// Payout-method-specific ID for the type of payout the user got.
|
||||||
///
|
///
|
||||||
/// - Tremendous: the rewarded gift card ID.
|
/// - Tremendous: the rewarded gift card ID.
|
||||||
/// - Mural: the payment rail used, i.e. crypto USDC or fiat USD.
|
/// - Mural: the payment rail code used.
|
||||||
/// - PayPal: `paypal_us`
|
/// - Blockchain: `blockchain-usdc-polygon`.
|
||||||
/// - Venmo: `venmo`
|
/// - Fiat: see [`muralpay::FiatAndRailCode`].
|
||||||
|
/// - PayPal: `paypal_us`.
|
||||||
|
/// - Venmo: `venmo`.
|
||||||
///
|
///
|
||||||
/// For legacy transactions, this may be [`None`] as we did not always
|
/// For legacy transactions, this may be [`None`] as we did not always
|
||||||
/// store this payout info.
|
/// store this payout info.
|
||||||
@@ -1061,9 +1081,7 @@ pub async fn transaction_history(
|
|||||||
amount: payout.amount,
|
amount: payout.amount,
|
||||||
fee: payout.fee,
|
fee: payout.fee,
|
||||||
method_type: payout.method,
|
method_type: payout.method,
|
||||||
// TODO: store the `method_id` in the database, and return it here
|
method_id: payout.method_id,
|
||||||
// don't use the `platform_id`, that's something else
|
|
||||||
method_id: None,
|
|
||||||
method_address: payout.method_address,
|
method_address: payout.method_address,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user