Stripe: Add default card and do not override old card - java

I am working with Stripe Customers, Subscription and Cards.
Now, I have a scenario where, Customer can have multiple cards.
Now, Customer adds a new card. And I have to mark that new added card as default_source.
So what I am doing is
Map<String, Object> params = new HashMap<String, Object>();
params.put("source", token.getId());
Customer customer = Customer.retrieve(user.getStripeId());
customerId = customer.getId();
Customer updatedCustomer = customer.update(params);
This piece of code is updating a customer and marking the current card as default_source which is as expected.
But if the Customer already has card then it overrides the old Card with new one. So the old card is deleted from that Customer.
Now what I want is, If Customer already have the card then I want to mark that card as secondary and then add new card and mark it default_source.
So how can i do that?

You'll want https://stripe.com/docs/api/sources/attach?lang=java and https://stripe.com/docs/api/customers/update?lang=java#update_customer-default_source :
Customer customer = Customer.retrieve(user.getStripeId());
// add a new payment source to the customer
Map<String, Object> params = new HashMap<String, Object>();
params.put("source", token.getId());
Source source = customer.getSources().create(params);
// make it the default
Map<String, Object> updateParams = new HashMap<String, Object>();
updateParams.put("default_source", source.getId());
customer.update(updateParams);

Related

Stripe Subscription Upgrade showing next Invoice Item

For example if I want to upgrade my user's package via Stripe API, from "59$ per month" package to "109$ per month" package and immediately charge (109-59=50$) / invoice the user. This is how I am doing:
prorationDate = (System.currentTimeMillis() + (30 * 1000)) / 1000L;
subscription = Subscription.retrieve(subscriptionId);
Map<String, Object> item1 = new HashMap<>();
item1.put("id", subscription.getItems().getData().get(0).getId());
item1.put("plan", newPlanId);
Map<String, Object> items1 = new HashMap<>();
items1.put("0", item1);
Map<String, Object> params1 = new HashMap<>();
params1.put("items", items1);
params1.put("proration_date", prorationDate);
// params1.put("prorate", true); deprecated and changed to the next line
params1.put("proration_behavior", "create_prorations");
params1.put("billing_cycle_anchor", "unchanged");
params1.put("payment_behavior", "pending_if_incomplete");
subscription = subscription.update(params1);
This is upgrading my user's package successfully but the invoice looks like this:
why it's also automatically subscribing for the next period ? even if I used set proration_behavior to always_invoice (when the subscription is updated to a new plan, a new invoice is paid automatically without the user paying).

Adding card source works in 19.45.0, fails in 20.0.0 and above

I am playing with Stripe-Java and I'm trying to add a card to a customer.
My code looks like this:
Customer stripeCustomer = Customer.retrieve("cus_xxxxxxx");
Map<String, Object> cardParam = new HashMap<String, Object>();
cardParam.put("number", "4242424242424242");
cardParam.put("exp_month", "11");
cardParam.put("exp_year", "2022");
cardParam.put("cvc", "123");
//token
Map<String, Object> tokenParam = new HashMap<String, Object>();
tokenParam.put("card", cardParam);
Token token = Token.create(tokenParam);
//user token
Map<String, Object> sourceParam = new HashMap<String, Object>();
sourceParam.put("source", token.getId());
//add to customer
stripeCustomer.getSources().create(sourceParam);
This works successfully on Stripe-Java version 19.45.0 but not on 20.0.0 or any versions above. Has the method to add a card changed?
A nullpointer exception is thrown
Thanks
This : stripeCustomer.getSources() will be null in v20.0.0 and above of the library because it pins to API version 2020-08-27 where customer.sources was removed by default. [0] [1]
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.
You would need to explicitly expand [2] "sources" when retrieving the Customer in order to populate customer.getSources()
CustomerRetrieveParams params = CustomerRetrieveParams.builder()
.addExpand("sources").build();
Customer stripeCustomer = Customer.retrieve("cus_xxxxxxx", params, null);
Also, your code uses the legacy Token API, and is passing raw card details from your server that puts you in PCI scope, you should look into the recommended integration paths : https://stripe.com/docs/payments/accept-a-payment
[0] https://github.com/stripe/stripe-java/blob/master/CHANGELOG.md#2000---2020-08-31
[1] https://stripe.com/docs/upgrades#2020-08-27
[2] https://stripe.com/docs/expand

Java Stripe API

I'm trying to bind a token as a customer card. So, this token has been created by Stripe.js. So, then I send this code on my backend service and I'm trying to set it up into a customer's cards:
Card card = Token.retrieve(id).getCard();
So, once I've got this token as a card, I'm trying it:
Customer.retrieve(this.customer).getSources().create(card.getMetadata())
Nevertheless, I'm getting this compilation error:
The method create(Map) in the type ExternalAccountCollection is not applicable for the arguments (Map)
Any ideas?
You can find the documentation for adding a card to an existing customer object here: https://stripe.com/docs/api/java#create_card.
The correct code would be:
Customer customer = Customer.retrieve(this.customer);
Map<String, Object> params = new HashMap<String, Object>();
params.put("source", id);
Card card = customer.getSources().create(params);
First, you load stripe.js and open stripe payment popup and submit, after stripe return token like(tok_kgkjfdskjfd) the this token pass as source into below api and stripe will automatically save the your card object.
Customer c = Customer.retrieve(this.customer);
Map<String, Object> params = new HashMap<String, Object>();
params.put("source", above_token);
Card card = customer.getSources().create(params);

Podio API - updating contact reference

I have an an Podio app that handles customer accounts where each customer has a manager (podio contact). All of this data resides in another system, and we are in the progress off writing software to synch the two. The software is written in java and using the podio api
I'm currently able to read and set all types of fields, except for the manager field (contact).
This is what is received from the API when a customer is loaded:
But how do you go about updating the manager reference to something else?
I've tried something like:
List<Map<String, Object>> list = new ArrayList<>();
HashMap<String, Object> values = new HashMap<>();
list.add(values);
HashMap<String, Object> value = new HashMap<>();
values.put("value", value);
value.put("mail", "employee#email.com");
//also tried user_id and profile_id
and then using the
ItemAPI.updateItemFieldValues(int itemId, int fieldId,
List<Map<String, Object>> values, boolean silent, boolean hook)
to update the field. Where am I going wrong?
Setup:
Podio app with 'Contact' field, configured to 'Workspace members / share when new address added' (like this screnshot)
Working example in Ruby
item_id = <some_item_id>
field_id = <contact_field_numeric_id>
field_external_id = <contact_field_external_id>
# set to empty value by field_id
empty_value = []
Podio::ItemField.update(item_id, field_id, single_value)
# set to single value by field_id
single_value = [{'value' => {'type' => 'user', 'id' => <Podio user id>}}]
Podio::ItemField.update(item_id, field_id, single_value)
# set to multiple values by external field id
multi_values = [{'value' => {'type' => 'user', 'id' => <Podio user id>}},
{'value' => {'type' => 'user', 'id' => <another Podio user id>}}]
Podio::ItemField.update(item_id, field_external_id, multi_values)
Will set this contact field to new value single_value or to list of new values multiple_value. Also, I'd strongly recommend to think again about your data architecture. It might be much more scalable to work with Podio Contact app type and use Reference field instead of using Contact field.
Java example:
HashMap<String, Object> pair = new HashMap<>();
HashMap<String, Object> value = new HashMap<>();
List<Map<String, Object>> list = new ArrayList<>();
// set to empty value
list = new ArrayList<>();
ItemAPI.updateItemFieldValues(<itemId>, <fieldId>, list, <silent>, <hook>)
// set to real value
value = new HashMap<>();
list = new ArrayList<>();
pair.put("id", <user_id>);
pair.put("type", "user");
value.put("value", pair);
list.add(value);
ItemAPI.updateItemFieldValues(<itemId>, <fieldId>, list, <silent>, <hook>)

Stripe API Update Customer Credit Card Details - Java

Cannot figure out for the life of me how to do this. I've tested the following which isn't working;
String stripeCustomerID = "123";
Customer cu = Customer.retrieve(stripeCustomerID);
cu.setDefaultSource(token);
Map<String, Object> updateParams = new HashMap<String, Object>();
updateParams.put("default_source", token);
enter code here`cu.update(updateParams);
This is the only place the Stripe API documentation hasn't had the answer.
Has anyone implemented this previously?
Regards,
Michael
default_source is expecting a card id not a token id. Thus you either need to:
1) Add the card to the customer and then update the default_source property
or
2) You can set the source property of the customer to the token. By setting source you will add the new card, delete the old default_source, and then set the new one as the default, all in the same API call.
Answer thanks to Matthew;
Customer cu = Customer.retrieve(stripeCustomerID);
Map<String, Object> updateParams = new HashMap<String, Object>();
updateParams.put("source", token);
cu.update(updateParams);

Categories