Creating sepa mandates with stripe - stripe-payments

I wanna create payment option for PaymentMethodType of ['sepa_debit', 'card'] to pay for subscriptions and as far as I know for sepa one needs a mandate to ensure there really is an agreement.
I wonder how to set that up. The api https://stripe.com/docs/api/mandates does not provide a method to create mandates, so I tried via setupIntent.create in my node app. I tried like this:
function createSI(mandateData, customer){
const setupIntent = await this.stripe.setupIntents.create({
customer: company.stripeCustomerId,
payment_method_types: ['sepa_debit', 'card'],
confirm: true,
mandate_data: {
customer_acceptance: {
type: 'online',
online: {
ip_address: mandateData.ip,
user_agent: mandateData.userAgent
}
}
}
});
return setupIntent.client_secret;
}
That however results in an error: "
You cannot confirm this SetupIntent because it's missing a payment
method. Update the SetupIntent with a payment method and then confirm
it again..
Now I am confused as to my understanding I need this setupIntent to get the client_secret to pass to stripe.elements in the frontend where the user chooses the payment method out of the two options I allow.
Any idea how to setup a proper sepa mandate if the customer picks sepa debit and still allow the customer the choice to choose between different payment options?
Cheers
Tom

You cannot create a SetupIntent while passing mandate_data without a payment method which is why you’re seeing the above error. The reference you should be looking at is this. Stripe Elements is a set of prebuilt UI components for collecting payment details. With Stripe Elements, you can collect the payment method details and mandate acknowledgement. This creates the accepted mandate, but you’ll need to communicate these terms to your customers in your form or through email.
Alternatively, you can use the Payment Element for setting up future payments. The Payment Element helps collect payment details for various payment methods. Depending on the payment method, it dynamically requests the necessary details and handles the mandate when needed.

Turns out that
confirm: true,
mandate_data: {
customer_acceptance: {
type: 'online',
online: {
ip_address: mandateData.ip,
user_agent: mandateData.userAgent
}
}
}
is not needed since without it I generate a payment method that is not linked to a mandate but the setupintent generated links to mandate that looks like this:
{
"id": "mandate_1MWGeHJgnOZBUP8a7CqJXatQ",
"object": "mandate",
"customer_acceptance": {
"accepted_at": 1675159269,
"online": {
"ip_address": "188.194.197.44",
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
},
"type": "online"
},
"livemode": false,
"multi_use": {},
"payment_method": "pm_1MWGeHJgnOZBUP8aMzlN7Th2",
"payment_method_details": {
"sepa_debit": {
"reference": "MMWMNDRP9PYNMEB8",
"url": "https://hooks.stripe.com/adapter/sepa_debit/file/src_1MWGeHJgnOZBUP8aiAIM8PUQ/src_client_secret_IkXKK4JdRHCGl8IO5ZudWIJn"
},
"type": "sepa_debit"
},
"status": "active",
"type": "multi_use"
}
Note: Seems one needs to search for a setupintent with the resulting paymentMethodId and that one then has the mandate info to get the mandate for the paymentmethod.

Related

Add Payment Method to an existing customer

In my angular app I want to use the stripe-API. I want to add a payment method to the customer. e.g. SEPA
My first Problem is to choose the right endpoint. I think it is the "create source"-endpoint.
My second problem is to pass the correct params. My postman body looks like
{
type: 'sepa_debit',
sepa_debit: {iban: 'DE12345678901234567890'},
currency: 'eur',
customer: 'cus_Jjg6mhSRHZuXYZ'
owner: {
name: 'Max Mustermann',
}
Response:
"error": {
"code": "parameter_unknown",
"doc_url": "https://stripe.com/docs/error-codes/parameter-unknown",
"message": "Received unknown parameters: type, sepa_debit",
"param": "type",
"type": "invalid_request_error"
}
the docs says that type can be 'sepa_debit'...?
Can someone pls hepl me?
You should use Payment Methods API instead of Sources API. If you have an existing Payment Method, you can attach it to a Customer.
You can also create a Payment Method, attach it and start a new payment flow at the same time when creating a Payment Intent.

Stripe Node.js - How to split a payment between several beneficiaries (connected accounts)?

For my first implementation, I transfer the amount of the transaction directly to a beneficiary from a paymentMethod Id retrieved from my app (Flutter). Now my goal would be to split the payment between several beneficiaries on the same transaction.
First implementation code:
var clonedPaymentMethod = await stripe.paymentMethods.create(
{
payment_method: paym,
},
{
stripeAccount: stripeVendorAccount,
}
);
var paymentIntent = await stripe.paymentIntents.create(
{
amount: amount,
currency: currency,
payment_method: clonedPaymentMethod.id,
confirmation_method: "automatic",
confirm: true,
application_fee_amount: fee,
description: "desc",
},
{
stripeAccount: stripeVendorAccount,
}
);
const paymentIntentReference = paymentIntent;
By checking the documentation, I noticed that the stripe.paymentMethods.create method was no longer specified, and that the stripe.transfers.create methods were added.
This code is attempting to clone a payment method to a connected account and then create a direct charge on that account. In order to create charges and then to split the funds of that charge to separate connected accounts a different approach would be needed. The model would be closer to "Separate charges and transfers", where the charge is made on that platform and then some amounts are shared among the connected accounts using transfers. A full description is outlined here [1].
[1] https://stripe.com/docs/connect/charges-transfers

Stripe v3 - SetupIntents and Subscriptions

I'm trying to use SetupIntents to validate and save a Payment Method and then create a Subscription using it to charge the customer (inmediately and then monthly) for the required amount.
This appears to be working fine:
The Card is validated (including SCA if needed)
The Payment Method is created, attached to customer as default and enabled for future usage with the status SUCEEDED.
The Subscription is created and uses the above payment method
The problem is that Stripe then generates the corresponding Invoice and Payment Intent but the latter with the status "requires_action" whenever the provided Card requires Secure Customer Authorization (SCA), even though the right payment method (enabled for future usage) is being used and the card validation has been already performed.
I thought the whole point of using SetupIntents was precisely to validate the payment method beforehand and be able to charge the customer afterwards.
Is my assumption simply wrong or this is actually possible and I might just be missing something?
Thanks in advance
EDIT: This is the subscription creation code in the backend:
# Set the default payment method on the customer
Stripe::Customer.update(
stripe_customer_id,
invoice_settings: {
default_payment_method: #requested_source
}
)
subscription = Stripe::Subscription.create({
"customer" => stripe_customer_id,
"proration_behavior" => 'create_prorations',
"items" => [
[
"plan" => "#{#stripe_plan_api_id}",
],
],
'default_tax_rates' => [
"#{#stripe_tax_rate_id}",
],
"expand" => ["latest_invoice.payment_intent"]
});
Thanks for the question, Eduardo.
There are a couple ways to create a Subscription while gaining the Customers SCA authentication and permission to charge the card later. Assuming we already have a Stripe Customer object created and their ID is stored in stripe_customer_id. With the flow you have now there are a couple steps:
Create the SetupIntent. Note that if you create it with usage: 'off_session' and the Customer it'll attach the resulting PaymentMethod when confirmed.
setup_intent = Stripe::SetupIntent.create({
customer: stripe_customer_id,
usage: 'off_session',
})
Collect payment details and confirm the SetupIntent using its client_secret on the client which will attach the PaymentMethod to the customer. Note that it will attach but will not be set as the invoice_settings.default_payment_method by default, so you'll need to make a separate API call later to update the Customer (see step 3).
stripe.confirmCardSetup(
'{{setup_intent.client_secret}}',
{
payment_method: {
card: cardElement,
},
}
).then(function(result) {
// Handle result.error or result.setupIntent
});
Update the Customer and set its invoice_settings.default_payment_method equal to the ID of the PaymentMethod on the successfully confirmed SetupIntent.
Stripe::Customer.update(
stripe_customer_id, {
invoice_settings: {
default_payment_method: 'pm_xxxx', # passed to server from client. On the client this is available on the result of confirmCardSetup
}
})
Create the Subscription with off_session: true
subscription = Stripe::Subscription.create({
customer: stripe_customer_id,
proration_behavior: 'create_prorations',
items: [{
plan: "#{#stripe_plan_api_id}",
}],
default_tax_rates: [
"#{#stripe_tax_rate_id}",
],
expand: ["latest_invoice.payment_intent"],
off_session: true,
})
This uses what's called a "Merchant Initiated Transaction" (MIT) for the Subscription's first payment. This is technically okay if the Subscription is created later after the Customer leaves and should technically work.
If the customer is on your site/app when you create the Subscription, there's another flow that is a bit more correct and doesn't require using a MIT exemption for SCA. The flow is the following for a Subscription without a trial:
Collect card details with createPaymentMethod on the client (no SetupIntent)
stripe.createPaymentMethod({
type: 'card',
card: cardElement,
}).then(function(result) {
//pass result to your server.
})
Attach those card details to the Customer
Stripe::PaymentMethod.attach(
"pm_xxx", {
customer: stripe_customer_id
}
)
Update the Customer's invoice_settings.default_payment_method
Stripe::Customer.update(
stripe_customer_id,
invoice_settings: {
default_payment_method: #requested_source
}
)
Create the Subscription (without off_session: true)
subscription = Stripe::Subscription.create(
customer: data['customerId'],
items: [
{
price: 'price_H1NlVtpo6ubk0m'
}
],
expand: ['latest_invoice.payment_intent']
)
Use the Subscription's latest_invoice's payment_intent's client_secret to collect payment details and confirm on the client.
stripe.confirmCardPayment(
'{{subscription.latest_invoice.payment_intent.client_secret}}', { ......
This second payment flow is a bit more correct from an SCA standpoint for getting authorization to charge the card. The second approach is outlined in the guide here: https://stripe.com/docs/billing/subscriptions/fixed-price
We also have a Stripe Sample you can use to experiment here: https://github.com/stripe-samples/subscription-use-cases/tree/master/fixed-price-subscriptions

Self-defined Function while creating a Digital twin?

It is possible to add a self-defined function while creating a digital Twin in Ditto as shown below.
"attributes": {
"location": "Germany"
},
"features": {
"temperature": {
"properties": {
"value": 100
}
},
"humidity": {
"properties": {
"value": 100
}
}
},
"BuiltinFuntion": {
if(Temparature > 20){
alert("Some message")
}
}
Note: One solution is to constantly check with Ditto HTTP APIs value and give alert message whenever it cross the threshold value. But I do not want to hit the APIs everytime. So please let me know if there is any alternate solution.
In order not to poll Ditto's API for changes, there are various other APIs supporting push-notifications.
For example, you can use the WebSocket API and use an filter expression defining filter=gt(features/temperature/properties/value,20) when subscribing for events.
Or you can use the SSE (Server Sent Events) API to do the same.
Both, the WebSocket and SSE API may directly be used in the browser - I suppose your alert you want to show is JavaScript, so I assumed your target environment for receiving push notifications is a browser.

Balanced Payments API call.meteor.js

Hi I am currently using balanced payments in my meteor application. I can create cards and customers just fine and I can associate the cards to the customers just fine. I run into a problem though when I try to create a debit. Here is the code that I have written which is pretty much taken directly from the balanced docs.
var customer = balanced.Customers.get(user.customer.uri, function (err, customer) {
console.error(err);
console.log(customer);
var customerContext = balanced.Customers.nbalanced(customer);
var debitInfo = {
amount: amount,
appears_on_statement_as: "Statement text",
description: "Some descriptive text for the debit in the dashboard"
};
customerContext.Debits.create(debitInfo, function(err, result) {
console.error(err);
console.log(result);
});
});
I get the error "The requested URL was not found on the server" whenever the above code runs. I found the problem but I'm not entirely sure how to solve it. I went to the balanced dashboard to check the logs and what I found was this.
Date: Fri, 27 Sep 2013, 6:46 AM
Method: POST
URI: /v1/marketplaces/TEST-MPFj4MYWjZc9xt2IjTIni7/v1/customers/CU6jgv9FlavhPyYQ6ObZKDny/debits
Status: 404 NOT FOUND
The request body is here:
{
"appears_on_statement_as": "Statement text",
"amount": 1200,
"description": "Some descriptive text for the debit in the dashboard"
}
Here is the response body:
{
"status": "Not Found",
"category_code": "not-found",
"description": "<p>The requested URL was not found on the server.</p><p>If you entered the URL manually please check your spelling and try again.</p> Your request id is OHM38291020277b11e38b38026ba7cac9da.",
"status_code": 404,
"category_type": "request",
"_uris": {},
"request_id": "OHM38291020277b11e38b38026ba7cac9da"
}
I see that the URI has the marketplace and customer url but I don't know why or what could have caused that to happen because like I said the customer creation, card creation and card association calls all work perfectly.
Any advice would be appreciated.
The balanced api documentation over at https://docs.balancedpayments.com/current/api#create-a-new-debit suggests there is an issue with the requested URL.
The URL in the api module you're using requests
/v1/marketplaces/TEST-MPFj4MYWjZc9xt2IjTIni7/v1/customers/CU6jgv9FlavhPyYQ6ObZKDny/debits
when it should be
/v1/customers/CU6jgv9FlavhPyYQ6ObZKDny/debits
It could also be that it needs the marketplaces uri in there, but there isn't a specification in the docs that matches this type of pattern, plus the '/v1/` suggests its being appended unnecessarily
You haven't given details on the type of package you're using but the issue for this lies in the package in the portion that creates the request URI, or if its not validated perhaps in one of the parameters you've provided.

Resources