lumenwrites
lumenwrites

Reputation: 1507

How can I pass custom data to Stripe webhook?

I am creating and processing a stripe payment like this:

    // Create payment intent
    const { data } = await axios.post('/api/payments/get-payment-intent', { slug: post.slug })

    // Use payment intent to charge the card
    const result = await stripe.confirmCardPayment(data.paymentIntentSecert, {
      payment_method: {
        card: elements.getElement(CardElement),
      },
    })

To be able to fulfill the order, I need to be able to pass some data (id of the product and username of the buyer) to the webhook that gets executed after the payment has been successfully completed (payment_intent.succeeded event).

How can I do that?

I've tried adding a metadata key to the confirmCardPayment() like this:

    const result = await stripe.confirmCardPayment(data.paymentIntentSecert, {
      payment_method: {
        card: elements.getElement(CardElement),
        metadata: {
          username: user.username,
          postId: post.id
        }
      },
    })

But the metadata doesn't show up on the object received by the webhook.

Upvotes: 4

Views: 4890

Answers (4)

Mark Day
Mark Day

Reputation: 17

Sending custom meta data and obtaining it at your server webhook url

  1. Firstly, for a single payment, the word press PHP to add custom meta data is done like this

    if ( absint( $form_data[ 'id' ] ) !== 101212 ) {
    return;
    

    }

    if ( ! empty( $subscription->id ) ) { return; }

    if ( ! ( $payment instanceof \WPForms\Vendor\Stripe\PaymentIntent ) && ! ( $payment instanceof \WPForms\Vendor\Stripe\Charge ) ) { return; }

    //error_log($payment);

    $payment->metadata[ 'username' ] = wp_get_current_user()->user_login; $payment->save();

In this example above i'm storing metadata for the username

  1. Once you have submitted payment via stripe you will notice that the metadata does appear in the dashboard under payment intent but it does not show up in the web hook meta. This is simply because when the data was sent in the php by wordpress occurred after the web hook took place.

  2. Therefore, on your server side you must do a refresh of the payment intent object using your secret api key to get the meta data.

stripe.apiKey =

                try {

                var refreshPaymentIntent = PaymentIntent.retrieve(paymentIntent.getId());
                var meta = refreshPaymentIntent.getMetadata();
                for(var entry : meta.entrySet())
                    log.info("Key : {}  Value : {}", entry.getKey(), entry.getValue());
            } catch(StripeException e)
            {
                log.error(e.getMessage());
            }

Hope this helps someone

Upvotes: 0

Agu Dondo
Agu Dondo

Reputation: 13579

You can set the metadata under the key payment_intent_data when creating the checkout session. This metadata will be attached by stripe on every webhook call.

    const session = await stripe.checkout.sessions.create({
      line_items: [
        {
            price: 'price_1234567890',
            quantity: 1,
        },
      ],
      mode: 'payment',
      payment_intent_data:  {
          metadata: {
              userId: 123, // here you can set the metadata
          },
      },
      success_url: '',
      cancel_url: '',
    });

Upvotes: 5

Graphics Factory
Graphics Factory

Reputation: 246

This is how I do it for stripe.checkout.sessions.create. Here is the code...

const session = await stripe.checkout.sessions.create({
          line_items: [
            {
              price: 'price_example',
              quantity: 1,
            },
          ],
          mode: 'payment',
          success_url: `https://www.example.com/success?session_id={CHECKOUT_SESSION_ID}`,
          cancel_url: `https://www.example.com/?canceled=true`,
          automatic_tax: {enabled: true},
          metadata : {
            my_user: user,
            my_tokens: tokens,
          }
        });

To access the event data I did this in the webhook...

try {
...
    event = stripe.webhooks.constructEvent(buf.toString(), sig, webhookSecret);
}

then to get the metadata from event ...

  const gotTokens = event.data.object.metadata.my_tokens;
  const theUser = event.data.object.metadata.my_user;

Upvotes: 5

alex
alex

Reputation: 2784

It is not possible to update the PaymentIntent metadata using confirmCardPayment().

You would first want to pass the username and postId to your backend server.

Example

const { data } = await axios.post('/api/payments/get-payment-intent', { 
    username:user.username, 
    postId: post.Id 
});

And subsequently create the PaymentIntent with the metadata.

Node.js example to create a PaymentIntent

const paymentIntent = await stripe.paymentIntents.create({
  amount: 2000,
  currency: 'usd',
  metadata: {
      username,
      postId
  },
});

Upvotes: 4

Related Questions