Search code examples
javaspring-bootstripe-payments

How can I retrieve product metadata from a session after completing checkout with Stripe in a Spring Boot application?


Using the Stripe SDK in Spring Boot, after creating a session and adding your product data, you have the option to use putAllMetadata, which accepts a map of <String, String>. The purpose of adding this metadata is to retrieve it after a successful payment, via the webhook.

I have implemented the webhook and received a Session object from it, but I am unable to find a method to retrieve this metadata.

 paramsBuilder.addLineItem(
       SessionCreateParams.LineItem.builder()
              .setQuantity(1L)
              .setPriceData(
                  PriceData.builder()
                       .setProductData(
                           PriceData.ProductData
                                .builder()
                                .putAllMetadata(metadata)
                                .setName("Book "))
                                .build())
                       .setCurrency(myDTO.getCurrency())
                       .setUnitAmountDecimal(BigDecimal.valueOf(myDTO.getPrice()* 100))
                       .build())
              .build());
                Session session = Session.create(paramsBuilder.build());
                return session.getUrl();

I have tried retrieving it from the session

 switch (event.getType()) {
        case "payment_intent.succeeded": {
            // System.out.println("done");
            // System.out.println("succeeded " + stripeObject.toJson());
            break;
         }
         case "charge.updated": {
             // System.out.println("upda " + stripeObject.toJson());
         }
         case "checkout.session.completed":
             Session sessionEvent = (Session) stripeObject;
             handleCheckoutSessionCompleted(sessionEvent);
             // System.out.print("sessiom " + sessionEvent.toJson());
             break;
             // ... handle other event types
         default:
             System.out.println("Unhandled event type: " + event.getType());
   }
return ResponseEntity.ok("");
}

private void handleCheckoutSessionCompleted(Session session) {
       try {
             SessionListLineItemsParams params = SessionListLineItemsParams.builder().build();
             List<LineItem> lineItems = session.listLineItems(params).getData();

             for (LineItem item : lineItems) {
                String this = item.getPrice().getMetadata()
                                                .get("this");
                System.out.println("this is "+ this);
             }
       } catch (StripeException e) {
              e.printStackTrace();
       } catch (Exception e) {
              e.printStackTrace();
       }
}

// System.out.print("sessiom " + sessionEvent.toJson()); This line of code correctly prints the session object.

My code prints this is null to the console.


Solution

  • The problem seems to be that to access the metadata you can only get it using the expand parameter. In this case, the metadata is under the data.price.product and can never be accessed from the session except explicitly requested. Stripe doesn't give you the full object.

    A big thanks to soma too for pointing out the correct method I was supposed to use. There is indeed metadata in both the price and product objects.

    SessionListLineItemsParams params = SessionListLineItemsParams.builder()
                 .addExpand("data.price.product") //can't get product data without this
                 .build();
    List<LineItem> lineItems = session.listLineItems(params).getData();
    
    String this = item.getPrice().getProductObject().getMetadata().get("this");
    

    https://docs.stripe.com/api/expanding_objects

    https://docs.stripe.com/expand

    You can’t receive webhook events with properties auto-expanded. Objects sent in events are always in their minimal form. To access nested values in expandable properties, you must retrieve the object in a separate call within your webhook handler.