I saved my credit card in Stripe but why is it only in sources
And not under cards?
I have used stripe.customers.createSource as specified in the docs to save a card (https://stripe.com/docs/api#create_card)
I guess this is the reason why stripe.customers.listCards return nothing
The method stripe.customers.createSource in the library is just making a POST request to /v1/customers/cus_123/sources to add a source to it. The type of the source itself depends on what you have used to create it client-side.
If you create card Tokens client-side tok_123 you will get Card object card_123 on the customer. You could also get a Bank Account object if you use ACH debits in the US and created a bank account tokens btok_123. This is the legacy method that has existed for years in the API.
More recently, Stripe release a new high-level object called a Source and your can read more about Sources in the documentation. This allows you to have one unique object no matter the payment method used (card, SEPA debit, Alipay, Sofort, etc.). This makes handling the logic in your code a lot easier as the objects have the same shape and properties specific to each payment method live in a sub-hash that you know to handle differently. Those Source objects have an id in the format src_123.
Here, your customer has Sources attached to it. This means that client-side, when you collect the card details, you are actively creating a Source instead of a Token. This is due to the methods/calls you use to create it. In Elements you would be using createSource() instead of createToken() while in the mobile SDKs they would create Sources by default.
Ultimately, Sources are a better approach for a new integration as they are more scalable and can handle the growth of your business internationally in the future. I'd recommend keeping Sources moving forward.
Related
I am implementing the Stripe payment platform using JavaScript and the PHP SDK.
I don't have any issues with the implementation itself, but I am not sure whether I have to reuse an existing PaymentIntent or it's perfectly fine to have a bunch of them created and incomplete.
I searched for this in Stripe's documentation, but I can't seem to find anything related to this.
For example, in my test account I have this:
It's all for the same transaction, because I was changing some visuals and refreshing the browser.
I am aware that each PaymentIntent has an ID, but is it recommended to add it as a query parameter and retrieve it on refreshing, or is it better to always generate a new Payment Intent.
My main reasoning is to avoid having a huge collection of incomplete payment intents.
The default integration path for Stripe today is to create a PaymentIntent first so that you get a client_secret you can use client-side to render their UI via PaymentElement. This means that if your customers decide not to pay after all, you end up with an incomplete PaymentIntent which is expected.
This is not really a problem, other than appearing in the Payments list which can be confusing. You could also write a background job daily that would cancel any PaymentIntent via you know won't be completed because the customer left and you didn't have any data to contact them to upsell them for example but this isn't really needed.
Stripe also has a beta (docs) right now (Feb 2023) that changes the default integration path. This simplifies the experience because you can render the PaymentElement client-side with specific options such as amount and currency. You'd then only create the PaymentIntent at the end of the flow
when the customer is attempting to pay. That flow limits the number of incomplete PaymentIntents since you only create them when the customer really pays. You'd still get some, for example after a decline by the customer's bank though.
With the Sources API, every customer had a default_source, but when using SetupIntent (in order to be compliant with the PSD2/SCA directive), there doesn't seem to be any direct equivalent.
So my question is, how this can be properly represented API-side (without using metadata)?
The payment_methods listing seems to have a property called preferred for the card (which seems to be what I am looking for), but so far I have not found out, how to get/set this property.
There is no direct equivalent to the default_source for Payment Methods and the newer APIs like Setup Intents and Payment Intents. The closest thing is invoice_settings.default_payment_method, but it only applies to Invoices.
To answer your question directly, you have three choices:
Set and use the value of invoice_settings.default_payment_method, specifying the Payment Method stored there explicitly for each Setup and Payment Intent
Specify the default Payment Method in metadata as you suggested
Stored the default on your end in your own database
Regarding the preferred property, if you're referring to card.networks.preferred that is the preferred card network of the card in question and is not relevant to your question.
If you use Webhooks, you can listen for payment_method.attached or setup_intent.succeeded events and set it as default when they are fired.
For more info:
https://stripe.com/docs/api/events/types
Payment method object can be set to update Customer invoice_settings property with a default payment method.
https://stripe.com/docs/api/customers/update#update_customer-invoice_settings
I'm working on a SAAS system that allows purchases to be made through a clients own payment gateway. We have one client that wants to use Stripe as their gateway, however as they are using Corporate Purchase Cards (CPC), it is necessary to pass Level 3 transaction details through. I've been trying to get details from Stripe on how we ensure that Level 3 data can be passed through successfully, however I'm not really getting anywhere with this in terms of getting any definitive information we can work with.
Stripe say that their system supports level 3 data, we just need to provide the data in the first place, however there is nothing in their documentation about this and the example we have been provided only allows for a single item to be listed - we will need to support a basket of different items.
We are using the Payment Intents process and already support adding in Metadata to the transaction. We've been told that adding metadata for SKU, Unit of Measure, Unit Price and Extended Price will allow level 3 processing, however this does seem to fall short of the information list on other sources (not to mention does not allow listing multiple items in the order due to the metadata keys needing to be unique)
Baed on that, our Metadata population looks like this (values hard coded to example purposes)
Dictionary<string, string> nRetVar = new Dictionary<string, string>();
nRetVar.Add("Customer", "John Smith");
nRetVar.Add("Email", "John.Smith#example.com");
nRetVar.Add("Order Number", "12345");
nRetVar.Add("Order Date", "2020-02-06");
nRetVar.Add("SKU", "ABCD1234");
nRetVar.Add("Unit of Measure", "1 Pack");
nRetVar.Add("Unit Price", "$10.00");
nRetVar.Add("Extended Price", "$15.00");
Stripe support never seem to directly answer any of the questions we have been asking about this, so it's proving very hard to get any progress on this - does anyone have enough experience with this to confirm if this metadata is enough to class as level 3, or is there more that we need to be adding?
Stripe supports Level 3 data in their API on both Charge and PaymentIntent. This feature though is currently "gated" which means you need to get access to the feature on your specific account. It's a bit similar to a long running beta. You should contact their support team again and ask for them to enable Level 3 data on PaymentIntent for your account.
The fields they are expecting as specific to that feature. This does not go inside metadata. The documentation is also gated which means you can only see it once you get access to the feature, to avoid confusion for other developers who don't have access.
You can see what the shape looks like in stripe-java for example on Charge here. The feature is not directly supported on PaymentIntent in the library though as this is still private.
The Stripe API has a source object that has a status field that tells you whether the payment instrument is chargeable or not.
However, in Stripe.net, all of the Source-related properties on the Customer object are of type StripeCard, which does not have any Status property. In fact, I can't see any way to retrieve a Source object in Stripe.net.
I'd like to be able to know whether a customer has a chargeable (not expired, etc) payment instrument hooked up to their account. How can I do this?
Also, does Stripe.net not allow manipulation of non-card payment instruments?
Stripe.net is a third-party library which means it wasn't built by Stripe. They haven't added support for Sources just yet which is why you're not seeing this. You can either make your own pull-request for this or report the issue on their github repo
Separately, though, you don't need to implement any of this at the moment. Cards and Bank Accounts are always chargeable by default. This status field is new and has been added for other sources such as Bitcoin Receivers but this isn't fully supported by Stripe officially just yet.
I would like to know if this is possible to add new payment method for Bigcommerce. I tried to contact their support without any luck. If anyone is familiar with bigcommerce and know if this is possible, i would appreciate any advice.
I already read their API docs and didn't found anything useful - only method to obtain list of available payment methods.
I already tried to signup for their partner. Without any luck.
We've done this before for a couple stores to allow clients to process payments through their own processor. The way we achieved this, is essentially through the following high-level steps:
Allow payments by Check (or similar offline method). We are going to replace this with the custom processor.
You'll notice that if you attempt to checkout via Check, that BigCommerce automatically creates the order for you, but sets the order status to Awaiting Payment. Upon submission the user is automatically sent to a 'Thank You' Order Confirmation page that contains both the Order ID and some payment instructions (such as where to send the check to).
Here's the trick -- Modify this 'Order Thank You' page to prompt the user for her or his credit card information. A simple HTML form will suffice here, performing the actual request via JavaScript.
Once you have the user's credit card data, you can then POST it to your own external server, where you would connect to and send data to whichever processor you are using. Additionally, you should make sure to send the Order ID to this program, so that you can connect to the BigCommerce API to load billing information, and then subsequently adjust the order status to either approved or declined depending on the response from your processor. Finally, you should send back some sort of response to the client to inform of the result of the charge attempt.
That's pretty much it in a nutshell. The way you integrate with the payment processor (step 4) is unique to whichever processor you are using. I hope this makes sense.
Although opinion based, I'm a huge fan of serverless technologies, and would suggest looking into AWS Lambda + AWS API Gateway. The benefit here is that you don't need to worry about creating an infrastructure or the associated concerns of security and scale. Rather, AWS Lambda allows you to simply upload your software, and allows it to be executed via an HTTP request to some defined endpoint set through the API Gateway. Lambda will scale automatically for you, and you don't need to worry about system level security concerns - only security at the application level. It's truly a set and forget setup, and a bleeding edge technology. Not to mention dirt cheap!
Implementing a new payment method is unsupported and requires hacky workarounds since we implement payment gateways via the core app. You can do this on blueprint by using an offline payment method and then using the API to update payment statuses, etc. I'd recommend using ActiveMerchant if you do wish to go down this path.