I am trying to establish until when (if at all - is the final payment prorated?) a user's subscription should persist beyond a cancellation.
Is the value in the "exp" field from the postback JSON the time at which the cancellation occurred, or the time until which their subscription benefits should persist?
exp is defined in the JWT spec. It refers to when the JWT should be treated as "expired" (e.g. to reject the JWT in its entirety because it's "outdated").
As defined in that link you get the cancellation postback whenever Google can't obtain payment - I'd interpret (defer to official Google support on this) that as being either the initial and/or renewal payment (because the user cancelled or some other reason - maybe expired card?).
If I'm not mistaken, the current frequency is only monthly, and the "prorated" value is something you define for initial payment. So you actually define what that initial payment is - a prorated value (e.g. first x days of subscription) or some initial fee and can make the "decision" on what a failed payment/cancellation postback means to you...
Related
I'm creating a web application where users earn points for using it (from time to time).
What is the best way to change the amount of points the user has in a safe way?
My first solution was to use a POST Request with the data in the body, but it would be easily circumvented since the user could open the console and send infinite copied requests and earn infinite points. And if I created a token, the user would copy that same token and reuse it until it is invalidated.
My second solution was to create a websocket that while the user maintains connection, he earns X points in X time but it would also be circumvented due to a false connection by the console
What to do in this situation?
Use a POST request, and validate that the request is authentic on the back-end (based upon the criteria in which it is deemed 'reasonable' to award the points).
For example, if a user could only earn 1 point every 30 minutes, store when the user was last awarded points in a database, and then ensure that 30 minutes had passed since that point in time (again, server side).
You could also ensure that the user isn't getting more points than the should by checking the value of the points that they are being awarded, in a similar manner. Want one point at a time? Check that their existing score equals their target score plus one.
With the charges API, a token would eventually be handed to the server that would allow you to charge against the customer's credit card, and the last step to complete the payment is handled by my server. This would allow you to do something like:
// Prevent anyone else from purchasing widget while we sell this one
lock(database){
if (widgetsAvailableCount > 0) {
widgetsAvailableCount--;
var charge = chargeService.Create(optionsForWidgetCharge);
}
else {
throw new Exception("Item is out of stock");
// Don't create charge against token in this case
}
}
This allows you to prevent a race condition where you sell the last remaining item to two people.
But with the PaymentIntents API, it seems that the final step in charging the credit card no longer happens on my server, but will happen when the client calls:
https://stripe.com/docs/js/payment_intents/confirm_card_payment
And it's not clear how long that will actually take (say, if a 3D Secure prompt is shown).
I'm trying to solve the same problem as above, avoiding the situation of accepting payment when there is no inventory left (where inventory was available at the time the payment process started but not when it was completed). I could mark in the database the item in a "reserved" state, but I'm wondering if I'm thinking about this the right way, and how others have addressed this if so.
My employer has challenged me to build him a custom Point of Sale system and stripe was my first thought for payment processing. I work in food-delivery, and as such our current (as well as every other) POS immediately charges the card (verifies it? whatever), and then at the end of the night when tips are counted (whether from the drivers or tipped receipts in the tip box) the charge changes to whatever the customer agreed to.
I see I can do a few similar things:
update metadata on a charge (not what I need)
capture a charge (not what I need - won't let you use a value higher than the initial)
do a second charge for the tip (would hope to avoid this)
save the card information with Stripe after creating a customer object and not do any charge until after I know the tip (would hope to avoid this)
But, can I verify the customer can pay the amount (that initial charge) and then increase it later once we know if/how much they tipped?
Simply put, I'd like my flow to be:
Customer orders
Charge is issued for 20$ of food (Stripe)
Food is delivered, 5$ tip secured on the receipt
Receipts are turned in, 5$ tip is entered into system
Charge is changed to reflect the added tip (now 25$) (Stripe)
Is this possible with Stripe? If so, how?
If not, do you know of any other payment system that could implement this flow?
Short answer: no, that's not possible.
You could do something like this:
Create an uncaptured charge for the base amount.
Once the customer confirms the tip, try to create a charge for the base amount + tip.
3a. If the charge succeeds, release the first uncaptured charge (by refunding it).
3b. If the charge fails, capture the first uncaptured charge (and maybe explain to your customer that they were only billed for the base amount).
According to Stripes documentation here if you add a Stripe object ID as the source when getting a list of balance transactions you should get all transactions related to that ID. (e.g. filtering by a charge ID will return all charge and refund transactions).
I have tried passing in a chargeId and do indeed get back the initial balance transaction that was created for that charge, however this charge also has 2 refunds associated with it that are not returned in the list. I have tried this with other charges and only ever seem to get back the initial balance transaction created, never any other transactions (particularly refunds which the docs say should be returned). I have my limit set to 100 items and I have tried using both the Stripe.Net API as well as PHP calls and get back the same results.
I've also attempted passing in customerId's to see if I could get back all balance transactions triggered by a Customer and in these cases I never get back any results at all. These are Customers that have triggered MANY transactions!
The arguments I am providing to the API are as follows:
Method: balance/list
Parameters: limit=100
source=[chargeId or customerId that has triggered multiple transactions]
My question is: Is this a bug in the API, is the documentation incorrect or is there an important parameter or aspect to this I am missing. I've also gone back to charges from 30+ days ago just to make sure it has nothing to do with the rolling transfer/pending/availability cycles.
Is the actual fact that you can only ever get back the initial transaction created by a chargeId, but nothing else. Anyone have any experience in this regard? Thanks in advance!
Looks like this is indeed either a bug or an error in the Stipe documentation. I've reported this to Stripe and just received the following message back from someone on the support team:
Hi there,
Thanks for reaching out and alerting us to this issue!
This does look like either a bug or an error in our documentation. I have shared this with my team and we are looking into this issue.
Thank you for using Stripe and please let me know if there's anything else we can do to help!
I will update this thread once I hear back from Stripe with either an update or a resolution.
My hunch is this isn't a bug: the Stripe behavior is technically correct. The BalanceTransaction API is returning all txns for that specific charge, which is only a single txn. The txns associated with the charge's refund are technically associated with those refund objects, not the charge. The same logic applied to disputes/chargebacks.
Here's some (untested!) ruby code demonstrating how to grab all of the txns for a charge:
def balance_transactions_for_charge(stripe_charge_id)
balance_transactions = []
charge = Stripe::Charge.retrieve(stripe_charge_id)
balance_transactions << charge.balance_transaction
balance_transactions += charge.refunds.data.map do |refund|
refund.balance_transaction
end
if charge.dispute
dispute = Stripe::Dispute.retrieve(charge.dispute)
# fairly certain that the dispute txn list includes the full object, not just IDs
balance_transactions += dispute.balance_transactions.data.map(&:id)
end
balance_transactions.map { |txn_id| Stripe::BalanceTransaction.retrieve(txn_id) }
end
I need to know is it possible to reserve or lock money with First Data API. Actually I don't know if process I am looking for is actually called "reservation", but I am thinking of standard procedure of locking certain amount of money on client CC so that client cannot spend it but I as a merchant, can return money without any cost to bank, client and myself if client or merchant wishes so. Kinda sorta like deposit. I just don't want to do full transaction and then return money with full transaction and pay every single step of it and then some for accounting nightmare.
1) Do an Authorization (a.k.a. Auth Only, Authorization hold) to freeze the maximum amount of funds you wish to access at a later date. Record the approval code from this transaction.
2) When it is time to charge the funds you wish to receive from the customer perform a Capture using the approval code received from the Authorization in step one.
Caveats:
1) You have a maximum of 30 days to capture the funds. This number may be lower for some credit cards.
2) You may only capture the funds set aside or less. You cannot capture more then the amount authorized.
3) You can only capture the funds once. This means if you capture an amount less then the total amount authorized and then you wish to go back later and get more you cannot do so. You would need to process another transaction with a fresh approval number to do so.
An Authorization hold may be what you need.