Stripe: How to set up recurring payments without plan? - javascript

First time working with Stripe API. Implementing it on WordPress using PHP and JS.
Working on a donation form. Donor should be able to choose a suggested amount (radio buttons-25,50,75,100) or pay as he/she wishes (text field after selecting 'other'). I was able to get this working.
There is a check box to set the amount up as a recurring payment. I created recurring payment plans for the fixed options like 25, 50, 100 etc.
How do I set up a recurring payment if the donor chooses a custom amount? Can't find the relevant API. Please help.

Another approach that Stripe suggests is to setup a plan with a recurring amount of $1 (or $0.01 for more flexibility) and then vary the quantity as needed.
e.g. Using the $0.01 plan approach, if I wanted to charge 12.50/month I could adjust the quantity like so:
$customer->subscriptions->create(array("plan" => "basic", "quantity" => "1250"));
Stripe Support
How can I create plans that don't have a fixed price?
Subscription Quantities

First, you'll need to create a new customer.
On submit, you could use the custom amount to create a new plan:
$current_time = time();
$plan_name = strval( $current_time );
Stripe_Plan::create(array(
"amount" => $_POST['custom-amount'],
"interval" => "month",
"name" => "Some Plan Name " . $_POST['customer-name'],
"currency" => "usd",
"id" => $plan_name
)
);
Keep in mind that the 'id' needs to be unique. You could use the customer's name, a time stamp, or some other random method to ensure that this is always the case.
You'd then just create the subscription on the newly-added customer:
$customer = Stripe_Customer::retrieve($customer_just_created);
$customer->subscriptions->create(array("plan" => $plan_name));
You probably will be able to omit the first line above, as you should already have a customer variable assigned from when the customer was actually created.

This is low tech, but the easiest thing I found was to use as little of the Stripe API as possible. Instead of creating subscription plans and products and things like that, you just:
Create a stripe customer.
Charge them with a cron job.
If you already know how to charge somebody, you just have to figure out how to create the customer, and then the rest is good to go.
This means you shift some of Stripe's cleverness to our own infrastructure, but I actually found this easier to think about/maintain than thinking through all of Stripe's API docs and features.

Related

Send Variable amount to Stripe without creating a product gives me Error : IntegrationError: lineItems.0.price_data is not an accepted parameter

Im trying to intergrate stripe to my app. basically what i really want to do is when a stripe checkout form is created I need to send variable amount by sending my own amount entered in lineItems array. I have tried using price_data but im getting this error:
Here is my code for creating invoice using LineItems array:
<button
onClick={() =>
checkout({
lineItems: [
{
// price: "price_1LXN8XJK5rJC1jE3jnJyjiT3",
price_data: {
currency: "cad",
unit_amount: 250,
unit_amount: 1,
product_data: {
name: "Interviewww",
},
},
},
],
})
}
>
Buy now!
</button>
Let me what am I doing wrong here. Thanks alot community!
Actually there are two ways of integrating with Stripe's Checkout Sessions. The first one is a client-only integration, the one you're currently using with the Stripe.js library. This requires for you to have pre-created prices/products since this is running on the customer's browser and it's more prone for user misusage or abuse. For more details on the accepted params you could take a look at the Stripe.js docs.
On the other hand, if you're looking for a more robust approach that allows varibale amounts with no pre-defined prices/products, than you will need to integrate with the more common server-side integration described here.
One last thing to note is that you were using the parameters of line_items described here which are related to the server-side integration and are not available in the Stripe.js library.

Stripe - Save customer payment method only if user ask for it

I use stripe payment element in client side. It sends a request to the server to retrieve the payment intent ID and the client secret.
I would like to be able to save the customer's payment method only if the customer has checked the box save this payment method for future purchases
But I would like the method to register only after I pass my complete flow in server side and be successful.
1- For this I set the capture method to "manual" when I create the
payment intent and I capture and update the payment intent when all
the server-side instructions have succeeded like this :
if (isWantSaveMethod) {
await stripe.paymentIntents.update(paymentIntent.id, { setup_future_usage: 'off_session' })
}
await stripe.paymentIntents.capture(paymentIntent.id)
=> The problem is that if I update the payment intent before it is captured, I get the error: You cannot provide a new payment method to a PaymentIntent when it has a status of requires_capture. You should either capture the remaining funds, or cancel this PaymentIntent and try again with a new PaymentIntent.
2- Then I tried to use an intent setup, which apparently allows us to
link a payment method to a customer
if (isWantSaveMethod) {
await stripe.setupIntents.create({
payment_method: paymentIntent.payment_method,
confirm: true,
customer: paymentIntent.customer,
})
}
await stripe.paymentIntents.capture(paymentIntent.id)
=> But : The provided PaymentMethod was previously used with a PaymentIntent without Customer attachment, shared with a connected account without Customer attachment, or was detached from a Customer. It may not be used again. To use a PaymentMethod multiple times, you must attach it to a Customer first.
3- Then I tried to attach the payment intent to a customer like this :
if (isWantSaveMethod) {
await stripe.paymentMethods.attach(paymentIntent.payment_method, {
customer: paymentIntent.customer,
})
await stripe.setupIntents.create({
payment_method: paymentIntent.payment_method,
confirm: true,
customer: paymentIntent.customer,
})
}
await stripe.paymentIntents.capture(paymentIntent.id)
=> But I remember that the documentation say : To attach a new PaymentMethod to a customer for future payments, we recommend you use a SetupIntent or a PaymentIntent with setup_future_usage. These approaches will perform any necessary steps to ensure that the PaymentMethod can be used in a future payment.
So finally I'm here to know what's the good way to do that ? How popular websites do this thing ?
I just want to make sure that all my instructions in the server side executed successfully before save the payment method and I want to be able to use this method later
How can I do that while respecting the recommendations that stripe gave in relation to the method attachment ?
When using Payment Element the intended user flow is that you would pass in setup_future_usage when the Payment Intent is created. Stripe wants to know if you intend to use setup_future_usage ahead of time so they can choose which Payment Method types to in the Payment Element (since not all of them can be used with setup_future_usage. You should either change your checkout flow to ask whether your customer wants to save their payment method before showing the Payment Element, or you can use the individual elements like Card element instead (each of theses elements should support passing in setup_future_usage with the client-side confirmation call - example here).
Alternatively (I really wouldn't recommend this), you can look into doing the following:
Make sure you haven't enabled any Payment Method types that do not support setup_future_usage (you can find the list here).
Change your client-side code to first send a request to your server to update the Payment Intent to set setup_future_usage, and wait for the response to be successful before continuing to call confirmPayment client-side.

Stripe / node.js : how retrieve stripe subscription safely + increment 1

I just started exploring Stripe for handling payments in node.js. I want to create a payment system that goes as following:
I create a workspace and I start a Stripe subscription of 10 dollars / month.
When someone joins my workspace it will cost me 10 dollar / month extra.
So, when I want to add a person to my subscription. How would I handle this? I found the below function, but I was wondering two things:
How do I add one person to this subscription? It now says quantity: 2, but how do I simply increment 1 with every user?
in the example below I use ID 'sub_6OZnwv0DZBrrPt' to retrieve this Stripe subscription. I was wondering from where I can get this ID? I could save this subscription ID in the workspace mongo database document after I created this subscription, but I'm not sure if it is safe to keep it like that in my database? Let me know if you have any suggestions.
this is the function to update a subscription
stripe.subscriptions.update(
'sub_6OZnwv0DZBryPt',
{ quantity: 2 },
(err, subscription) => {
// asynchronously called
}
);
On 1.) you need to retrieve the current subscription based on the stored ID. This can be done as:
stripe.subscriptions.retrieve(
"sub_6OZnwv0DZBryPt",
function(err, subscription) {
// asynchronously called
}
);
The subscription object will have information about the current quantity (see the example response and doc on the subscription object). Which leads to your second question.
To retrieve the subscription you need to store the ID only. It's safe to do so, the ID is meaningless to others unless they have your test / live keys as well. Be sure you secure those keys, and feel free to store IDs like subscription_id, customer_id, etc.

Using the Braintree drop-in UI to select the payment method for recurring billing -- or: finding the payment method of a paymentMethodNonce

I'm building a simple payment system using Braintree payments, PHP and JavaScript. I'm using Braintree's Drop-in UI, and would like to create subscriptions (i.e. recurring billing).
For this, I'm using:
// $_customer is a Braintree_Customer object; a customer stored in the Vault
$subscription_create = Braintree_Subscription::create([
'id' => $_customer->id,
'planId' => 'some_package',
'paymentMethodToken' => $_customer->defaultPaymentMethod()->token
]);
This works fine, and creates a subscription using the customer's 'default payment method'. However, I don't see any way for the customer to change his default payment method. There does not seem to be an option for this in the drop-in UI.
Does this mean I cannot use the drop-in UI for recurring billing? Should I write my own UI to allow customers to change their default payment method?
There is a way to make a payment method the default one. I could use that one, however, I only receive a paymentMethodNonce from the client. How do I find the paymentMethod linked to that nonce?
I work at Braintree. If you have more questions, you can always get in touch with our support team.
You don't need a special method for this, you can pass the nonce directly to Braintree_PaymentMethod::create:
$result = Braintree_PaymentMethod::create(array(
'customerId' => '12345',
'paymentMethodNonce' => 'nonce-from-the-client'
));

Prevent cheating in Rails/html5 game App (Rails 3.2/html5/javascript)

I'd like to know if it's possible to prevent cheating in the following case
I have a Ruby on Rails app and a Active Record database
I have Users (model User), that play Games(model Game) and there are Prizes (model Prize).
What I want is to :
1- prevent a player from cheating/hacking on the winnings (prizes he has won)
2- prevent a player from cheating on the nb of shots he has
As a user can win multiple prizes and prizes can belong to multiple users, I have a many_to_many relations: i use for this a table/model Winnings that lists all stuff won in the games by each User (a user has many winnings and a prize has many winnings)
Players have a certain number of shots, let's say 3 per user.
For 1-, basically, i guess everytime a user wins a prize in a Game, i'll send the server a url like:
mygame/com/?winning_id=1234;game_id=3;user_id=6;prize_id=4, telling the server the user with id 6 has won a prize with id4 in the game with id 6
I don't want players to be able to cheat that. how can I do this. Can any player just use that url above and send this way a message/action to my server (post) telling him he won? that would make it freaking easy to cheat?
Should I encrypt stuff/the url and make the url/message only understandable by my server?
For 2- (shots), I think I should send actions to server side every time and calculate scores at server side but still can't he cheat the same way as 1-?
In addition to using post as mentioned in the answer from palainum above, if needed, you could add a string (instead of an ID) in any place in your game where the URL could be edited and is visible.
Background - I had a similar problem in one of my apps (where if a URL was changed people could deduce / edit the number and cheat). The way I overcame it was to generate a unique code for the item in the URL.
To do this, I would add a string attribute to Winning model called url_code, make it required and indexable:
add_column :winning, string :url_code, :null => false, :index => true
in your model add an after_initialize callback:
Class Winning
validates :url_code, :uniqueness => true
after_initialize :create_url_code
def create_url_code
self.url_code=SecureRandom.hex(4) if self.url_code.nil?
end
And use that as a parameter in the cases using an ID is a problem (similar to this in your controller)...
#winning = Winning.find_by_url_code(params[:id])
Also, you could do the same thing for your users URL (or if you need to display it every in URL) by using the user.name as a friendly_id.
edit - just fixed a typo where I had offer_code instead of url_code.
There are at least two things you can do now:
Send POST request - it will be still possible to cheat, but it will require more work
Create a model Win - and create object of this class after winning a game. Then after making request (point 1) you can check if this object exists.
EDIT:
Sorry, you already mentioned Winning class. Just create object of this class after winning a game, then check if a user won a game (if the table contains a record with the user and the game).
You should also store shots of a user in a game and use unique validation to disallow for example shooting twice in one game.

Categories

Resources