Skip to content

Commit 3f55711

Browse files
authored
More billing fixes (#4431)
* Only update the PaymentMethod ID if not using placeholder ID * comment * Create Anrok transactions for all charges * Fix comment * Prefer using payment method's address rather than customer address * chore: query cache, clippy, fmt * Retrieve stripe address from PM * chore: query cache, clippy, fmt * fmt * bring back the query cache
1 parent bb9ce52 commit 3f55711

File tree

1 file changed

+85
-58
lines changed

1 file changed

+85
-58
lines changed

apps/labrinth/src/queue/billing.rs

Lines changed: 85 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -199,14 +199,7 @@ pub async fn index_subscriptions(
199199
)
200200
})?;
201201

202-
let Ok(customer_id): Result<stripe::CustomerId, _> =
203-
stripe_customer_id.parse()
204-
else {
205-
return Err(ApiError::InvalidInput(
206-
"Charge's Stripe customer ID was invalid"
207-
.to_owned(),
208-
));
209-
};
202+
let customer_id = stripe_customer_id.parse().map_err(|e| ApiError::InvalidInput(format!("Charge's Stripe customer ID was invalid ({e})")))?;
210203

211204
let customer = stripe::Customer::retrieve(
212205
&stripe_client,
@@ -215,13 +208,12 @@ pub async fn index_subscriptions(
215208
)
216209
.await?;
217210

218-
let Some(stripe_address) = customer.address else {
219-
return Err(ApiError::InvalidInput(
220-
"Stripe customer had no address".to_owned(),
221-
));
222-
};
223-
224-
stripe_address
211+
customer.address.ok_or_else(|| {
212+
ApiError::InvalidInput(
213+
"Stripe customer had no address"
214+
.to_owned(),
215+
)
216+
})?
225217
};
226218

227219
let customer_address =
@@ -272,12 +264,13 @@ pub async fn index_subscriptions(
272264
// The price of the subscription has changed, we need to insert a notification
273265
// for this.
274266

275-
let Some(subscription_id) = charge.subscription_id
276-
else {
277-
return Err(ApiError::InvalidInput(
278-
"Charge has no subscription ID".to_owned(),
279-
));
280-
};
267+
let subscription_id =
268+
charge.subscription_id.ok_or_else(|| {
269+
ApiError::InvalidInput(
270+
"Charge has no subscription ID"
271+
.to_owned(),
272+
)
273+
})?;
281274

282275
NotificationBuilder {
283276
body: NotificationBody::TaxNotification {
@@ -361,20 +354,75 @@ pub async fn index_subscriptions(
361354
)
362355
})?;
363356

364-
let stripe_customer_id = DBUser::get_id(c.user_id, &pg, &redis)
365-
.await?
366-
.ok_or_else(|| {
367-
ApiError::from(DatabaseError::Database(
368-
sqlx::Error::RowNotFound,
369-
))
370-
})
371-
.and_then(|user| {
372-
user.stripe_customer_id.ok_or_else(|| {
357+
let customer_address = 'a: {
358+
let stripe_id: stripe::PaymentIntentId = c
359+
.payment_platform_id
360+
.as_ref()
361+
.and_then(|x| x.parse().ok())
362+
.ok_or_else(|| {
373363
ApiError::InvalidInput(
374-
"User has no Stripe customer ID".to_owned(),
364+
"Charge has no payment platform ID".to_owned(),
375365
)
376-
})
377-
})?;
366+
})?;
367+
368+
// Attempt retrieving the address via the payment intent's payment method
369+
370+
let pi = stripe::PaymentIntent::retrieve(
371+
&stripe_client,
372+
&stripe_id,
373+
&["payment_method"],
374+
)
375+
.await?;
376+
377+
let pi_stripe_address = pi
378+
.payment_method
379+
.and_then(|x| x.into_object())
380+
.and_then(|x| x.billing_details.address);
381+
382+
match pi_stripe_address {
383+
Some(address) => break 'a address,
384+
None => {
385+
warn!("PaymentMethod had no address");
386+
}
387+
};
388+
389+
let stripe_customer_id =
390+
DBUser::get_id(c.user_id, &pg, &redis)
391+
.await?
392+
.ok_or_else(|| {
393+
ApiError::from(DatabaseError::Database(
394+
sqlx::Error::RowNotFound,
395+
))
396+
})
397+
.and_then(|user| {
398+
user.stripe_customer_id.ok_or_else(|| {
399+
ApiError::InvalidInput(
400+
"User has no Stripe customer ID"
401+
.to_owned(),
402+
)
403+
})
404+
})?;
405+
406+
let customer_id =
407+
stripe_customer_id.parse().map_err(|e| {
408+
ApiError::InvalidInput(format!(
409+
"Charge's Stripe customer ID was invalid ({e})"
410+
))
411+
})?;
412+
413+
let customer = stripe::Customer::retrieve(
414+
&stripe_client,
415+
&customer_id,
416+
&[],
417+
)
418+
.await?;
419+
420+
customer.address.ok_or_else(|| {
421+
ApiError::InvalidInput(
422+
"Stripe customer had no address".to_owned(),
423+
)
424+
})?
425+
};
378426

379427
let tax_id =
380428
DBProductsTaxIdentifier::get_price(c.price_id, &pg)
@@ -383,30 +431,6 @@ pub async fn index_subscriptions(
383431
DatabaseError::Database(sqlx::Error::RowNotFound)
384432
})?;
385433

386-
let Ok(customer_id): Result<stripe::CustomerId, _> =
387-
stripe_customer_id.parse()
388-
else {
389-
return Err(ApiError::InvalidInput(
390-
"Charge's Stripe customer ID was invalid".to_owned(),
391-
));
392-
};
393-
394-
let customer = stripe::Customer::retrieve(
395-
&stripe_client,
396-
&customer_id,
397-
&[],
398-
)
399-
.await?;
400-
401-
let Some(stripe_address) = customer.address else {
402-
return Err(ApiError::InvalidInput(
403-
"Stripe customer had no address".to_owned(),
404-
));
405-
};
406-
407-
let customer_address =
408-
anrok::Address::from_stripe_address(&stripe_address);
409-
410434
let tax_platform_id =
411435
anrok::transaction_id_stripe_pi(&payment_intent_id);
412436

@@ -417,7 +441,10 @@ pub async fn index_subscriptions(
417441
.create_or_update_txn(&anrok::Transaction {
418442
id: tax_platform_id.clone(),
419443
fields: anrok::TransactionFields {
420-
customer_address,
444+
customer_address:
445+
anrok::Address::from_stripe_address(
446+
&customer_address,
447+
),
421448
currency_code: c.currency_code.clone(),
422449
accounting_time: c.due,
423450
accounting_time_zone:

0 commit comments

Comments
 (0)