Skip to content

Commit 98b4970

Browse files
authored
Store method ID for payouts (#4752)
* Store method ID for payouts * Fixes
1 parent 9706f15 commit 98b4970

File tree

6 files changed

+94
-51
lines changed

6 files changed

+94
-51
lines changed

apps/labrinth/.sqlx/query-83f8d3fcc4ba1544f593abaf29c79157bc35e3fca79cc93f6512ca01acd8e5ce.json renamed to apps/labrinth/.sqlx/query-2aa9704c9ead520fb61b4ca1e94c7c70a245b0cc48ae3f4883393bfd57a685f1.json

Lines changed: 10 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apps/labrinth/.sqlx/query-285c089b43bf0225ba03e279f7a227c3483bae818d077efdc54e588b858c8760.json renamed to apps/labrinth/.sqlx/query-c82bf13a2567f772a4c6eb3329971049791dab817ac07708873ac57986c17e2c.json

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ALTER TABLE payouts
2+
ADD COLUMN method_id TEXT;

apps/labrinth/src/database/models/payout_item.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@ pub struct DBPayout {
1515

1616
pub fee: Option<Decimal>,
1717
pub method: Option<PayoutMethodType>,
18+
/// See [`crate::models::v3::payouts::Payout::method_id`].
19+
pub method_id: Option<String>,
20+
/// See [`crate::models::v3::payouts::Payout::method_address`].
1821
pub method_address: Option<String>,
22+
/// See [`crate::models::v3::payouts::Payout::platform_id`].
1923
pub platform_id: Option<String>,
2024
}
2125

@@ -27,10 +31,10 @@ impl DBPayout {
2731
sqlx::query!(
2832
"
2933
INSERT INTO payouts (
30-
id, amount, fee, user_id, status, method, method_address, platform_id
34+
id, amount, fee, user_id, status, method, method_id, method_address, platform_id
3135
)
3236
VALUES (
33-
$1, $2, $3, $4, $5, $6, $7, $8
37+
$1, $2, $3, $4, $5, $6, $7, $8, $9
3438
)
3539
",
3640
self.id.0,
@@ -39,6 +43,7 @@ impl DBPayout {
3943
self.user_id.0,
4044
self.status.as_str(),
4145
self.method.as_ref().map(|x| x.as_str()),
46+
self.method_id,
4247
self.method_address,
4348
self.platform_id,
4449
)
@@ -71,7 +76,7 @@ impl DBPayout {
7176

7277
let results = sqlx::query!(
7378
"
74-
SELECT id, user_id, created, amount, status, method, method_address, platform_id, fee
79+
SELECT id, user_id, created, amount, status, method, method_id, method_address, platform_id, fee
7580
FROM payouts
7681
WHERE id = ANY($1)
7782
",
@@ -85,6 +90,7 @@ impl DBPayout {
8590
status: PayoutStatus::from_string(&r.status),
8691
amount: r.amount,
8792
method: r.method.and_then(|x| PayoutMethodType::from_string(&x)),
93+
method_id: r.method_id,
8894
method_address: r.method_address,
8995
platform_id: r.platform_id,
9096
fee: r.fee,

apps/labrinth/src/models/v3/payouts.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,17 @@ pub struct Payout {
1818
#[serde(with = "rust_decimal::serde::float_option")]
1919
pub fee: Option<Decimal>,
2020
pub method: Option<PayoutMethodType>,
21-
/// the address this payout was sent to: ex: email, paypal email, venmo handle
21+
/// Platform-dependent identifier for the submethod.
22+
///
23+
/// See [`crate::routes::v3::payouts::TransactionItem::Withdrawal::method_id`].
24+
pub method_id: Option<String>,
25+
/// Address this payout was sent to: ex: email, paypal email, venmo handle.
2226
pub method_address: Option<String>,
27+
/// Platform-provided opaque identifier for the transaction linked to this payout.
28+
///
29+
/// - Tremendous: reward ID
30+
/// - Mural: payout request UUID
31+
/// - PayPal/Venmo: transaction ID
2332
pub platform_id: Option<String>,
2433
}
2534

@@ -33,6 +42,7 @@ impl Payout {
3342
amount: data.amount,
3443
fee: data.fee,
3544
method: data.method,
45+
method_id: data.method_id,
3646
method_address: data.method_address,
3747
platform_id: data.platform_id,
3848
}

apps/labrinth/src/routes/v3/payouts.rs

Lines changed: 59 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use crate::models::payouts::{
1010
MuralPayDetails, PayoutMethodRequest, PayoutMethodType, PayoutStatus,
1111
TremendousDetails, TremendousForexResponse,
1212
};
13+
use crate::queue::payouts::mural::MuralPayoutRequest;
1314
use crate::queue::payouts::{PayoutFees, PayoutsQueue};
1415
use crate::queue::session::AuthQueue;
1516
use crate::routes::ApiError;
@@ -772,6 +773,7 @@ async fn tremendous_payout(
772773
amount: amount_minus_fee,
773774
fee: Some(total_fee),
774775
method: Some(PayoutMethodType::Tremendous),
776+
method_id: Some(body.method_id.clone()),
775777
method_address: Some(user_email.to_string()),
776778
platform_id,
777779
})
@@ -806,6 +808,16 @@ async fn mural_pay_payout(
806808
)
807809
.await?;
808810

811+
let method_id = match &details.payout_details {
812+
MuralPayoutRequest::Blockchain { .. } => {
813+
"blockchain-usdc-polygon".to_string()
814+
}
815+
MuralPayoutRequest::Fiat {
816+
fiat_and_rail_details,
817+
..
818+
} => fiat_and_rail_details.code().to_string(),
819+
};
820+
809821
Ok(DBPayout {
810822
id: payout_id,
811823
user_id: user.id,
@@ -814,6 +826,7 @@ async fn mural_pay_payout(
814826
amount: amount_minus_fee,
815827
fee: Some(total_fee),
816828
method: Some(PayoutMethodType::MuralPay),
829+
method_id: Some(method_id),
817830
method_address: Some(user_email.to_string()),
818831
platform_id: Some(payout_request.id.to_string()),
819832
})
@@ -883,18 +896,6 @@ async fn paypal_payout(
883896
pub links: Vec<PayPalLink>,
884897
}
885898

886-
let mut payout_item = crate::database::models::payout_item::DBPayout {
887-
id: payout_id,
888-
user_id: user.id,
889-
created: Utc::now(),
890-
status: PayoutStatus::InTransit,
891-
amount: amount_minus_fee,
892-
fee: Some(total_fee),
893-
method: Some(body.method.method_type()),
894-
method_address: Some(display_address.clone()),
895-
platform_id: None,
896-
};
897-
898899
let res: PayoutsResponse = payouts_queue.make_paypal_request(
899900
Method::POST,
900901
"payments/payouts",
@@ -922,33 +923,50 @@ async fn paypal_payout(
922923
None
923924
).await?;
924925

925-
if let Some(link) = res.links.first() {
926-
#[derive(Deserialize)]
927-
struct PayoutItem {
928-
pub payout_item_id: String,
929-
}
926+
let link = res
927+
.links
928+
.first()
929+
.wrap_request_err("no PayPal links available")?;
930930

931-
#[derive(Deserialize)]
932-
struct PayoutData {
933-
pub items: Vec<PayoutItem>,
934-
}
931+
#[derive(Deserialize)]
932+
struct PayoutItem {
933+
pub payout_item_id: String,
934+
}
935935

936-
if let Ok(res) = payouts_queue
937-
.make_paypal_request::<(), PayoutData>(
938-
Method::GET,
939-
&link.href,
940-
None,
941-
None,
942-
Some(true),
943-
)
944-
.await
945-
&& let Some(data) = res.items.first()
946-
{
947-
payout_item.platform_id = Some(data.payout_item_id.clone());
948-
}
936+
#[derive(Deserialize)]
937+
struct PayoutData {
938+
pub items: Vec<PayoutItem>,
949939
}
950940

951-
Ok(payout_item)
941+
let res = payouts_queue
942+
.make_paypal_request::<(), PayoutData>(
943+
Method::GET,
944+
&link.href,
945+
None,
946+
None,
947+
Some(true),
948+
)
949+
.await
950+
.wrap_internal_err("failed to make PayPal request")?;
951+
let data = res
952+
.items
953+
.first()
954+
.wrap_internal_err("no payout items returned from PayPal request")?;
955+
956+
let platform_id = Some(data.payout_item_id.clone());
957+
958+
Ok(DBPayout {
959+
id: payout_id,
960+
user_id: user.id,
961+
created: Utc::now(),
962+
status: PayoutStatus::InTransit,
963+
amount: amount_minus_fee,
964+
fee: Some(total_fee),
965+
method: Some(body.method.method_type()),
966+
method_id: Some(body.method_id.clone()),
967+
method_address: Some(display_address.clone()),
968+
platform_id,
969+
})
952970
}
953971

954972
/// User performing a payout-related action.
@@ -972,9 +990,11 @@ pub enum TransactionItem {
972990
/// Payout-method-specific ID for the type of payout the user got.
973991
///
974992
/// - Tremendous: the rewarded gift card ID.
975-
/// - Mural: the payment rail used, i.e. crypto USDC or fiat USD.
976-
/// - PayPal: `paypal_us`
977-
/// - Venmo: `venmo`
993+
/// - Mural: the payment rail code used.
994+
/// - Blockchain: `blockchain-usdc-polygon`.
995+
/// - Fiat: see [`muralpay::FiatAndRailCode`].
996+
/// - PayPal: `paypal_us`.
997+
/// - Venmo: `venmo`.
978998
///
979999
/// For legacy transactions, this may be [`None`] as we did not always
9801000
/// store this payout info.
@@ -1061,9 +1081,7 @@ pub async fn transaction_history(
10611081
amount: payout.amount,
10621082
fee: payout.fee,
10631083
method_type: payout.method,
1064-
// TODO: store the `method_id` in the database, and return it here
1065-
// don't use the `platform_id`, that's something else
1066-
method_id: None,
1084+
method_id: payout.method_id,
10671085
method_address: payout.method_address,
10681086
});
10691087

0 commit comments

Comments
 (0)