trial period in Checkout session in Stripe - stripe-payments

I would like to create trial period to be used with stripe checkout session:
session = stripe.checkout.Session.create(
customer=customer.stripe_id,
payment_method_types=['card'],
line_items=[{
'price': "price_1HjynjHdAhQwSUAK",
'quantity': 1,
'tax_rates': ["txr_1Hkntg4yXtzmX", ],
},
mode='payment',
allow_promotion_codes=True,
success_url=request.build_absolute_uri(reverse('thanks')) + '?session_id=CHECKOUT_SESSION_ID}',
cancel_url=request.build_absolute_uri(reverse('index_payment')),
)
in the tripe.Subscription.create looks like we just need to add trial_end=1605387163, but it doesnt work in checkout session. I cant seem to find the way to do it even though I am pretty sure it is doable as displayed in this demo:
I appreciate if someone can help.

You've got the right idea with trial_end, it just needs to be a child parameter under subscription_data.
// other parameters
subscription_data: {
trial_end=1605387163
}
https://stripe.com/docs/api/checkout/sessions/create#create_checkout_session-subscription_data-trial_end

Brendan's answer pointed me in the right direction, for PHP the syntax to add the trial_end would be for example:
$session = \Stripe\Checkout\Session::create([
.......
Your Other parameters
.......
'subscription_data' => ['trial_end' => 1624110173],
]);
Where 1624110173 is unix timestamp for the end of the free period. See this Stripe document for general explanation of checkout process and code:
Stripe Documents

Related

Stripe API - Passing a custom parameter does not work for subscription charges

I'm creating a new checkout session and creating a new subscription on that page.
return stripe.checkout.Session.create(
payment_method_types=['card'],
customer_email=payload['email'],
line_items=_get_checkout_products(payload),
mode='subscription',
success_url=host + '?session_id={CHECKOUT_SESSION_ID}&success=true',
cancel_url=host + '?canceled=true',
subscription_data={
"metadata": {
'user_id': get_account_id(event)
}
}
)
Unfortunately it only shows on subscription.created event but not in charges for said subscription for the next period.
Why is it not showing up in the next invoice.payment_succeeded or charge.succeeded?
If anyone is looking for this - currently there's no way to pass parameters reliably between all events.

How to set payment details with store-api in shopware 6

i want to use shopware as a headless shop with stripe payment provider. The payment works in shopware without problems.
Now im testing the order steps with api only. the last step is to handle the payment through the provider (stripe in this case).
in the shopware documentation its handled with the api call /store-api/handle-payment.
the payload looks like this:
{
"orderId": "string",
"finishUrl": "string",
"errorUrl": "string"
}
now when i request the api i get 500 error with message:
No credit card selected
My question is, how to send credit card data through this api so that Stripe can handle the payment. Is there anyone to solved this problem?
With the advice from Alex I was able to find the following solution:
Find error credit card not selected: This happens only when you try to pay per api request. The reason i found was, that Stripe saves the payment details (credit card id) in the session object. Per api you have no access to this as default and thatswhy u get the message credit card not selected
Take a look at the stripe plugin, especially in your PaymentMethods/Card/CardPaymentConfigurator.
i put the following in the configure method
from Line 46 - 62
$requestDataBag = $stripePaymentContext;
$paymentDetails = $requestDataBag->requestDataBag->get('paymentDetails');
if(!null == $paymentDetails) {
$card = $paymentDetails->get('creditCardId');
} else {
$card = null;
}
$selectedCard = $this->stripePaymentMethodSettings->getSelectedCard();
if ($selectedCard || isset($selectedCard['id'])) {
$selectedCard = $selectedCard['id'];
} elseif ($card) {
$selectedCard = $card;
} else {
throw PaymentIntentPaymentConfiguratorException::noCreditCardSelected();
}
send payment data per handle-payment request:
let payload = {
"orderId": event,
"finishUrl": "https://www.myfinishurl.de",
"errorUrl": "https://www.myurl.de/order/error",
"paymentDetails": {
"creditCardId": "creditcardid"
}
Now do this for all methods you need. It works. Maybe Stripe can implement this in the future.
You have the following options:
Check the local API documentation - it might have more information than the public one, because it honors installed modules (see https://stackoverflow.com/a/67649883/288568)
Contact their support for more information as this is not covered in the API Docs
Make a test-payment via the normal storefront and look at the requests which are made in the network panel of your browser's development tools

How to get PaymentIntent next_action.type = redirect_to_url instead of use_stripe_sdk for Subscription

I am working on the implementing Subscription*(which is SCA ready) using Stripe.
I try to handle https://stripe.com/docs/billing/subscriptions/payment#handling-action-required.
After the subscription is created on Stripe side, I have got the answer like in documentation above:
{
"id": "sub_XXXXXXXXXXXXXXXXXXX",
"object": "subscription",
"status": "incomplete",
...
"latest_invoice": {
...
"payment_intent": {
"status": "requires_action",
...
"next_action": {
"type": "use_stripe_sdk",
...
},
...
}
}
}
According to the documentation https://stripe.com/docs/api/payment_intents/object#payment_intent_object-next_action-type
next_action.type can have two values redirect_to_url and use_stripe_sdk
So my question is how to get next_action.type = redirect_to_url(instead of use_stripe_sdk) and how to force stripe to fill next_action.redirect_to_url(Because I want to handle it on my own in my UI)?
*There is already a similar question on SO:
https://stackoverflow.com/questions/56490033/how-to-handle-use-stripe-sdk-through-php
but my case is to create Subscription where I don't have control over PaymentIntent
In my understanding, the next_action.type will be equal to redirect_to_url only if you choose to manually handle 3D Secure authentication https://stripe.com/docs/payments/payment-intents/verifying-status#manual-3ds-auth
As per documentation:
To handle 3D Secure authentication manually, you can redirect the customer. This approach is used when you manually confirm the PaymentIntent and provide a return_url destination to indicate where the customer should be sent once authentication is complete. Manual PaymentIntent confirmation can be performed on the server or on the client with Stripe.js.
Example using Stripe.js:
stripe.confirmPaymentIntent(
'{PAYMENT_INTENT_CLIENT_SECRET}',
{
payment_method: '{PAYMENT_METHOD_ID}',
return_url: 'https://example.com/return_url'
}
).then(function(result) {
// Handle result.error or result.paymentIntent
});
Example using Stripe Python:
intent = stripe.PaymentIntent.confirm(
'{PAYMENT_INTENT_ID}',
payment_method='{PAYMENT_METHOD_ID}',
return_url='https://example.com/return_url'
)
EDIT: as per #karllekko's comment the {PAYMENT_INTENT_ID} will in your case be latest_invoice.payment_intent.id.
Please read https://stripe.com/docs/payments/3d-secure-iframe - it gives more details about the "return_url" flow - and describes also posibilities to customize it inside "iframe" etc
Probably this document is fairly recent - so at the time of this question (July) it was not existing yet

Announce a members role ADDED to a specific role in a specific channel

I'd like to have my bot announce in our specific channel called family-talk, which I do have the channel ID of as well but not sure where to put it, but I'd want this to only happen when a role has been added to a member, is my below code correct or wrong? I don't have a lot of good ways of testing this so i'm hoping for some big help here. I also would like to know where the best place would be to place the code. Thank you!
if(!oldMember.roles.has('539208166563643407') && newMember.roles.has('561773668439687179'))
client.channels.get("550197572178935809").send("This member got the special role!");
Your code should work, BUT you have 2 diffrent IDs in the if, so to make this a bit cleaner just do:
const roleID = '539208166563643407';
const channelID = '550197572178935809';
client.on('guildMemberUpdate', (oldMember, newMember) => {
if(!oldMember.roles.has(roleID) && newMember.roles.has(roleID)) {
client.channels.get(channelID).send(newMember.displayName + ' got the special role!');
}
});

Does toLocaleTimeString in Node.js support the hour12 option?

I can't seem to get hour12 time working in node.js, however in the browser (Chrome) it's working just fine.
Node.js in terminal
var date = new Date();
var d12 = date.toLocaleTimeString('en-US', {hour12:true});
var d24 = date.toLocaleTimeString('en-US', {hour12:false});
console.log(d12) // output 13:43:38
console.log(d24) // output 13:43:38
Both yeild the same result:
13:43:38
Update
Adding fiddle to prove it works in browser
Could someone point me to the docs that explain why, or tell me what I'm doing wrong?
It's not just you. I tried running the same chunk in Node.js and couldn't get a way to print it in 12 hour format easily.
After doing some Googling, it seems like Moment.js is a popular tool for manipulating and displaying time and days. If you need to manipulate a lot of time/dates, it may be worth checking out, Moment.js.
// with Moment
var moment = require('moment');
console.log(moment().format('hh:mm'));
Otherwise,
// just one of many ways to do it in Javascript
function hour12 (hour) {
var mod = hour % 12;
if (mod < 10) {
return '0'.concat(mod);
} else {
return mod;
}
}
console.log(new Date().toLocaleTimeString().replace(/[\d]+/, hour12(date.getHours())));
EDIT I answered this question late at night, and realized I sort of missed the mark on addressing the question.
Since Node.js is based off Chrome's v8 JavaScript engine, I started poking around in the source code. I can't see a place where it takes into account arguments passed to it.
Code is here, toLocaleTimeString is line 324. In comparison, I looked around Mozilla's SpiderMonkey engine and it at a glance, it seems to account for this.
You can use toLocaleDateString and toLocaleTimeString to format times and dates. The first parameter passed to these methods is a locale value, such as "en-us". The second parameter, where present, specifies formatting options, such as the long form for the weekday.
I've used Chrome and works well.
var date = new Date(Date.UTC(2016, 3, 7, 14, 30, 0));
var options = {
weekday: "long", year: "numeric", month: "short",
day: "numeric", hour: "2-digit", minute: "2-digit"
};
document.write(date.toLocaleTimeString("en-US", options));
https://msdn.microsoft.com/en-us/library/ff743760(v=vs.94).aspx

Resources