After a successful order placement, paid with Stripe, the order.payments.data maps which contains all the stripe data is missing ANY info on the payment method that can be directly displayed to the user.
I should probably use the "payment_method": "pm_1NdaNIHom7EScpqgc48SfMNn" to get the readable name but that feels like uneccesary extra work on the server. Am I missing something?
#Stripe payment, missing payment method type in `data`
45 messages ยท Page 1 of 1 (latest)
What do you want to show to the customer?
Well in the frontend I'm building and on the invoice I want to show a readable payment method.
This is payment intent data like here: https://stripe.com/docs/api/payment_intents/retrieve
So you get what Stripe gives you in the intent.
Okay, I get it. Thank you.
Do you see a way I can modify this data or add the readable name to the metadata object of the payment?
If I could add it here that would be great
This is a snippet of the GET order response.
You can try to use this, not sure : https://docs.medusajs.com/modules/carts-and-checkout/storefront/implement-checkout-flow#update-payment-session
Hmm, it states it should be done before the purchase.
What about this?
https://docs.medusajs.com/references/services/classes/PaymentProviderService#updatepayment
Would that work? Then where to best excecute this
Before you do any storing of the payment method, be sure it's PCI compliant
Yeah but I first need to find a good way to store it in the first place.
I think if you use PaymentElement from Stripe then it's kinda hidden for medusa. All happens on the Stripe side and medusa doesn't know much about which method is chosen
All that is recieved from Stripe is in the intent in data property
Yeah that makes sense. But if I told a way to set the metadata in the screenshot above, I can make a one time call to a stripe API to get the readable string and save it.
But I dont know how to edit that metadata field
You would need to update the payment intent I think: https://stripe.com/docs/api/payment_intents/update
But that can be only made from the backend (it needs the secret stripe key from backend).
And for that you would need to create your own endpoint I guess.
const stripe = require('stripe')('your stripe test key');
const paymentIntent = await stripe.paymentIntents.update(
'pi_3L5Yh3LJMdQkx7dY14aYXXLM',
{metadata: {paymentMethodName: 'Sofort'}}
);
But how will you get what method is chosen?
Ah thats smart, and that would be automatically available in Medusa?
Hmm, there is payment_method in the intent which represents the method I suppose
Yes but then we get to your first original question where you never wanted to make extra work on the server ๐
Hmm I will play a bit with this in the near future
By the way I don't see a readable name even when you get a Payment Method: https://stripe.com/docs/api/payment_methods/retrieve
And get back
Do you happen to have time to look at my Project organisation & import and export ts files post as well? That would be awesome
I will ask Stripe support for a solution, maybe they have a neat one.
Stripe devs are active on Stripe Discord
I think I'm wrong here. It won't be updated in the medusa payment method.
Okay! thanks for getting back at it.
But one more time, to ask directly, do you know how to update the metadata from my screenshot? That would help a lot.
Or this one, this is a payment_session on a draft order from the {{medusa-host}}/admin/draft-orders/dorder_01H8MDB0856HMBVXP2EFS4GYV5 response.
I don't know. I thik the only way is to update the payment session data: https://docs.medusajs.com/references/services/classes/PaymentProviderService#updatesessiondata
But you still need to get the used payment method from Stripe.
Honestly I would just go with Paid with Stripe on the invoice ๐
Or just retrieve the PaymentMethod from Stripe when creating invoice and use the "type"
Got it!
I created a custom endpoint:
// Payment sessions
router.put("/store/carts/:id/payment-sessions/update-data", authenticate(), (req, res) => {
const paymentProviderService = req.scope.resolve("paymentProviderService")
paymentProviderService.updateSessionData(req.body.payment_session, {
data: req.body.data,
})
.then((paymentSession) => {
res.json({
payment_session: paymentSession,
})
})
.catch((e) => {
if (e) {
res.status(400).send({
error: e?.message,
})
}
})
})
And when I call it with the following body like so:
{
"payment_session": {
"id": "ps_01H8MJK22XA9KPFF31DHJTARNN",
"provider_id": "manual"
},
"data": {
"payment_term": "afterpay_30"
}
}
I get back the follwoing response:
{
"payment_session": {
"id": "ps_01H8MJK22XA9KPFF31DHJTARNN",
"created_at": "2023-08-24T20:08:22.347Z",
"updated_at": "2023-08-24T20:18:56.488Z",
"cart_id": "cart_01H8MJJT16V3F9ZE7JCW6N1N6M",
"provider_id": "manual",
"is_selected": true,
"is_initiated": true,
"data": {
"status": "pending",
"payment_term": "afterpay_30"
},
"idempotency_key": null,
"amount": 48600,
"payment_authorized_at": null
}
}
As you can see the payment_term is now there (which I need as well). I can do the same with the readable stripe payment method. I can call this in the frontend when I finalise the cart.
Okay this is not a solution either as the data in the payment_session is emptied somehow when you go from a draft order to an order.....
I tried with this one
https://docs.medusajs.com/references/services/classes/PaymentService#update
But that only allows updates of the order_id or swap_id....
So still no solution here.
Yeah I feel you'll need to fetch the payment method from Stripe for the invoice generation. Or just just dump a "Paid with Stripe" if that suits you.
Have you asked on Stripe Discord? I think there's nothing in the intent about the method, so you'll need the payment method.
I did it the following way. In my order.completed notifier I did the following:
orderCreated = async (data) => {
const config = {
relations: ['payments'],
}
this.orderService.retrieve(data.id, config)
.then((order) => {
// Copy the cart's context to the order's metadata for convenience reasons
this.cartService.retrieve(order.cart_id)
.then(async (cart) => {
// Get the payment method and save it to the order's context
let paymentMethod = null
if (order.payments?.[0]?.data?.payment_method) {
const paymentMethodResponse = await axios.get('https://api.stripe.com/v1/payment_methods/' + order.payments?.[0]?.data?.payment_method, {
headers: {
Authorization: `bearer ${process.env.STRIPE_API_KEY}`,
}
})
paymentMethod = paymentMethodResponse.data
}
this.orderService.update(data.id, {
metadata: {
...cart.context,
stripe_payment_method: paymentMethod,
}
})
...........
So it one-time fetches the stripe API and sets the stripe_payment_method in my order.metadata.
I can then easily acces it anytime.