stripe / stripe-java

Java library for the Stripe API.

Home Page:https://stripe.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

NullPointerException when adding source to new customer

barrychapman opened this issue · comments

Describe the bug

When attempting to create a customer and add a payment source, it results in a NullPointerException due to the fact it returns null instead of a PaymentSourceCollection.

To Reproduce

  1. Create a new Customer
  2. Create a Token for a card object
  3. Create the source parameter object
  4. Call the following:

Card card = (Card) customer.getSources().create(source);

Results in:

java.lang.NullPointerException: null
	at com.zev.installations.services.PaymentService.getCardSource(PaymentService.java:144) ~[classes/:0.0.1-SNAPSHOT]
	at com.zev.installations.services.PaymentService.doPayment(PaymentService.java:196) ~[classes/:0.0.1-SNAPSHOT]
	at com.zev.installations.controllers.Public.CheckoutController.submitPayment(CheckoutController.java:287) ~[classes/:0.0.1-SNAPSHOT]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-5.3.18.jar:5.3.18]
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) ~[spring-web-5.3.18.jar:5.3.18]
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) ~[spring-webmvc-5.3.18.jar:5.3.18]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.3.18.jar:5.3.18]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.18.jar:5.3.18]
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.18.jar:5.3.18]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067) ~[spring-webmvc-5.3.18.jar:5.3.18]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) ~[spring-webmvc-5.3.18.jar:5.3.18]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.18.jar:5.3.18]
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.18.jar:5.3.18]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:661) ~[servlet-api.jar:na]
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.18.jar:5.3.18]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) ~[servlet-api.jar:na]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[catalina.jar:8.5.37]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[catalina.jar:8.5.37]
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-websocket.jar:8.5.37]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[catalina.jar:8.5.37]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[catalina.jar:8.5.37]
	at com.zev.installations.auth.security.filter.XSSFilter.doFilter(XSSFilter.java:30) ~[classes/:0.0.1-SNAPSHOT]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[catalina.jar:8.5.37]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[catalina.jar:8.5.37]
	at com.zev.installations.auth.security.filter.ThrottleFilter.doFilter(ThrottleFilter.java:87) ~[classes/:0.0.1-SNAPSHOT]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[catalina.jar:8.5.37]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[catalina.jar:8.5.37]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:111) ~[spring-web-5.3.18.jar:5.3.18]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[catalina.jar:8.5.37]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[catalina.jar:8.5.37]

Expected behavior

customer.getSources() should return an instance of PaymentSourceCollection which contains the method create to add a payment source to that collection. Instead, it returns null - resulting in the NullPointerException when I call create()

Code snippets

private Card getCardSource(Customer customer, Token token) throws StripeException {
        Map<String, Object> source = new HashMap<String, Object>();   
        source.put("source", token.getId());   

        Card card = (Card) customer.getSources().create(source);   
        return card;
    }


### OS

Windows 11 / CentOS

### Java version

Java 17

### stripe-java version

v22.13.0

### API version

2022-11-15

### Additional context

How to approach this?

It should really be the PaymentSourceCollection that contains an empty data set - not a null on the collection object attached to the customer.

@barrychapman By default sources on Customer is not returned anymore. This changed back in 2020-08-27 where we say:

The sources property on Customers is no longer included by default. You can expand the list but for performance reasons we recommended against doing so unless needed.

For your code to work, you need to make sure that you expand the sources property at step #1. If you do, then getSources() will work as expected and let you call create() on it. This is what we document in our API Reference here.

Ultimately, this kind of integration has been considered deprecated for multiple years now. We replaces legacy Card card_123 objects or Source src_123 objects by the newer PaymentMethod API that is compatible with PaymentIntent and that's what we expect most integrations to rely on moving forward.

I'm going to close this out as it's not really a bug with the stripe-java library and more an integration support question. If you have any follow up questions, please contact our support team directly: https://support.stripe.com/contact

Is there any documentation about integration with PaymentMethod API? I was not able to find anything earlier

I'd recommend starting with the Accept a payment main doc. For any follow up questions, please work directly with our support team instead though: https://support.stripe.com/contact

We are not using any of the prebuilt pages, nor are we embedding anything. It would be nice if the docs detailed the correct flow for requests to follow instead of leaving us to guess. The help reps were less than helpful.

I'm sorry but this is not a support channel. Please work with our support team or talk to Stripe developers on our Discord server if you have follow up questions.