How to update a customer belonging to a connected account in Stripe? - ruby-on-rails

I am building a Rails 5.2 app. In this app I have integrated Stripe Connect.
I am currently building a feature where my customers can enroll their customers in subscriptions. The front end is Angular 11.
After the user have entered their payment data I need to attach this payment method to the created customer but I am not able too.
When I use this code it says that the customer is not found (even though I am using the correct ID). I guess it's because I created the Customer to a connected account.
The problem is I have no way of setting the stripe_account ID to the code.
customer = Stripe::Customer.update(
params[:customer],
invoice_settings: {
default_payment_method: params[:payment_method_id]
}
)
If I try this it says the stripe_account parameter is not valid.
"(Status 400) (Request req_sByQlJONJi0oHt) Received unknown parameter: stripe_account"
customer = Stripe::Customer.update(
params[:customer],
invoice_settings: {
default_payment_method: params[:payment_method_id]
}, stripe_account: params[:account]
)
So basically, how can I update a customer belonging to a Connected Account?

The update definition looks like this:
def update(id, params = {}, opts = {})
So in your case, the stripe_account is being passed in the params argument instead of the opts argument. Wrap the params in brackets ({}).
customer = Stripe::Customer.update(params[:customer],
{invoice_settings: {default_payment_method: params[:payment_method_id]}},
{stripe_account: params[:account]})

Related

Stripe checkout session seems to be adding a new customer even if they already exist

I have used the following code in .Net Core to create a Stripe checkout session, it seems to work fine for one customer buying one subscription.
I have a scenario though where a customer would be paying for subscriptions for other people, so may well use the checkout portal multiple times. When this happens Stripe will add the customer email address as a new customer each time, so rather than have one customer who can log in to the customer portal and see all subscriptions they have paid for, they can only log in to the 1st occurance of the customer with that email address.
Is there a way to use the checkout session so that if a customer email already exists it is not added again as a new customer?
var options = new SessionCreateOptions
{
SuccessUrl = successUrl+"&email=" + email,
CancelUrl = cancelUrl,
Mode = "subscription",
AllowPromotionCodes = true,
LineItems = new List<SessionLineItemOptions>
{
new SessionLineItemOptions
{
Price = priceId,
Quantity = 1,
},
}
};
var service = new SessionService(this.client);
try
{
var session = await service.CreateAsync(options);
Response.Headers.Add("Location", session.Url);
return new StatusCodeResult(303);
}
Checkout does not automatically de-duplicate customers for you. How your customer records are managed is up to you.
If you want to have a Checkout session associated with an existing customer, you need to provide that customer id when you create the session.
https://stripe.com/docs/api/checkout/sessions/create#create_checkout_session-customer

Unautorized API calls JwtCreator

I'm playing around with the DocuSign's Ruby Quickstart app and I've done the following:
have an Admin account
have an organization
created an Integration(Connected App) for which I've granted signature impersonation scopes in the Admin Dashboard(made RSA keys, put callback urls, etc)
even if I've done the above, I've also made the request to the consent URL in a browser: SERVER/oauth/auth?response_type=code &scope=signature%20impersonation&client_id=CLIENT_ID &redirect_uri=REDIRECT_URI
Integration appears to have everything enabled
Then in the JwtCreator class the check_jwt_token returns true, updates account info correctly.
But when I try the following(or any other API call):
envelope_api = create_envelope_api(#args)
options = DocuSign_eSign::ListStatusChangesOptions.new
options.from_date = (Date.today - 30).strftime('%Y/%m/%d')
results = envelope_api.list_status_changes #args[:account_id], options
The api call raises an exception with DocuSign_eSign::ApiError (Unauthorized):
Args are:
#args = {
account_id: session[:ds_account_id],
base_path: session[:ds_base_path],
access_token: session[:ds_access_token]
}
All with correct info.
What am I missing?
For clarity, I was using some classes from the Quickstart app(like JwtCreator, ApiCreator, etc) along my code.
Not sure at this point if it's my mistake or part of the Quickstart app but this call:
results = envelope_api.list_status_changes #args[:account_id], options
the account_id was something like this "82xxxx-xxxx-xxxx-xxxx-xxxxxxxx95e" and I was always getting Unauthorized responses.
On a medium.com tutorial the author used the 1xxxxxx account_id and with this form, it worked.

How to resolve "Stripe::InvalidRequestError, No such customer 'cus_XYZ....'" error for invoicing?

Just ran into a weird error I cannot seem to resolve. I am trying to send a one-off invoice to some of my Stripe customers. I have stored their customer id's on the server side, however each time I create a one-off invoice, I get the "No such customer error".
I have hard-coded their id's on the server side and Stripe will then say it will bill the supplier (it won't send the email however). When I manually create an invoice in the Stripe Dashboard everything works fine.
Stripe::InvoiceItem.create({
customer: stripe_supplier.to_s,
amount: 1000,
currency: 'usd',
description: 'Order fee from LocalVore!',
})
invoice = Stripe::Invoice.create({
customer: stripe_supplier.to_s,
billing: "send_invoice",
days_until_due: 10,
})
invoice.send_invoice
When I hit call this (from a parent function, of course) Stripe will say that the customer does not exist (parameter is stripe_supplier which represents our customer id).

Retrieve Customer's default and active card from Stripe

I am trying to retrieve the default and active card of a Customer. (Also keep in mind that with the coding I have, the customer can always have one card which means if there is a way around it it can help).
Some months ago I used this code segment which was working fine. It seems Stripe made some updates and I can't get it to work now.
current_user.stripe_card_id = customer.active_card.id
The error I get is
undefined method `active_card' for #Stripe::Customer
If you need any more information please let me know.
edit: customer.default_card.id does not work either.
I used customer.methods to check the methods and found this (default_source):
current_user.stripe_card_id = customer.default_source
Works fine now. Thank you
default card id will available in customer object's "default_source" key
{
"id": "cus_GACkqbqFD8RQw4",
"object": "customer",
"default_source": <DEFAULT CARD ID HERE>
...
}
read more here : https://stripe.com/docs/api/customers
[EDIT] Additionally,
It's worth noting that when you request a list of all the cards belonging to a particular customer, the default card is always at the top of the result. So you could also get the default card by requesting the customers cards and adding a limit of 1.
Information on how to achieve this: https://stripe.com/docs/api/cards/list
PaymentMethods API - 2020 update
If you have switched from old Sources API to the new Payment Methods API then you should know that unlike old Sources there's no default Payment Method for a Customer.
Now, you can attach a Payment Method as default one to a subscription object:
Stripe::Subscription.update(
'sub_8epEF0PuRhmltU',
{
default_payment_method: 'pm_1F0c9v2eZvKYlo2CJDeTrB4n',
}
)
or as a customer.invoice_settings.default_payment_method
Stripe::Customer.update(
'cus_FOcc5sbh3ZQpAU',
{
invoice_settings: {default_payment_method: 'pm_1vvc9v2eZvKYlo2CJDeTrB4n'},
}
)
Here is the whole Stripe documentation on that
Relying on customers' default_source is safe no matter the changes. You can see here that subscriptions will still use customers' default_source if both invoice_settings.default_payment_method and subscription.default_payment_method are not set.
customer = Stripe::Customer.retrieve(customer_id_on_stripe)
first_3_cards = customer.sources.all(limit: 3, object: 'card')[:data]
Will return array of cards, if you want to fetch bank_accounts
first_3_bank_accounts = customer.sources.all(limit: 3, object: 'bank_account')[:data]

Shopify API App Proxy with Rails verify Users

I am trying to configure an app proxy so users can submit a product for a Shopify store. I have seen multiple ways to so a signature and handle it so yet I am unable to get it working so the ShopifyAPI will work. The action is below, I noticed that:shopify_session filter only works for admin, not customers as well.
def submit_product
query_parameters = Rack::Utils.parse_query(request.query_string)
# Remove and save the "signature" entry
signature = query_parameters.delete("signature")
sorted_params = query_parameters.collect{ |k, v| "#{k}=#{Array(v).join(',')}" }.sort.join
calculated_signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('sha256'), ENV['SHOPIFY_SECRET'], sorted_params)
raise 'Invalid signature' if signature != calculated_signature
#store = Store.where(shopify_url: query_parameters['shop']).first
if #store.present?
#product = #store.products.new
#product.images.build
#product_types = ShopifyAPI::CustomCollection.find(#store.customizable_collection_id).products
end
end
Before you can connect to the ShopifyAPI you should first establish an API session. Otherwise the ShopifyAPI::CustomCollection.find method can't connect to Shopify. Steps 3 and 4 of the shopify_api README include the following example:
session = ShopifyAPI::Session.new("SHOP_NAME.myshopify.com", token)
ShopifyAPI::Base.activate_session(session)
product_types = ShopifyAPI::CustomCollection.find(id)
token is the permanent access token which you can request during the OAuth Authentication phase (the installation of the App into a shop).

Resources