payPal subscription transactions not showing up immediately - node.js

I'm creating recurring payments through payPal subscriptions flow. On the frontend, I have a button auto-generated by payPal which redirects me to their domain. After that, it correctly returns the subscriptionID; after that, the frontend calls a backend API which should verify that subscriptionID, to check fields such "status" and so on.
In this backend API, I need to store some "paymentID" (one per month, always unique, if the subscription is automatically renewed monthly), which I found to be called "transactionID" on payPal. I use the REST API GET /v1/billing/subscriptions/{id}/transactions, which should returns an object with a field transactions, which should be an array of transactions. The problem is that sometimes, just after the successful payment, this array is empty. If I wait some time (from few ms to minutes), then every subscription has it's own transactions, in the end.
Is there a way to fix this? Or, alternatively, is there something like transactions on the PayPal environment which can uniquely represents a specific payment?

When a subscription starts it takes time for the first transaction to be created.
Instead of querying the subscriptions API, create a webhook to be notified of PAYMENT.SALE.COMPLETEDevents. This will be useful for the initial transaction as well as all future transactions.

Related

Stripe - Any way to migrate off older Charges API (Subscriptions) without creating a Customer beforehand?

I am updating my billing page which used Stripe JS V2 tokens and the Charges API (Subscriptions). The new(er) Payment Element looks slick from a future proofing standpoint, but am I understanding it correctly that the Customer object must be created prior to populating the payment form?
I only create the Customer once the payment token is obtained and a user has a clear intent to purchase after evaluating during a trial period. Otherwise my Stripe Dashboard is overrun with "empty" trial users that never sign up (I only have around a 10% signup rate from account creation). I guess this is mostly just a personal peeve, but I also just don't like to share user data and figured this way I would only be sharing with a third party once they become actual customers of mine.
Since a Subscription cannot be created without providing a Customer as part of the required parameters, am I stuck using the Card Element and the older Charges API if I don't create a Customer for every user in my system?
You really should just create a Customer up front. It will be required if you want to use trials with Subscriptions and will be cleaner in the long run.
For a workaround, which I would not overall recommend, you could use a SetupIntent with Payment Element to collect the customer's payment method without actually creating a Customer object. Then you can later create the Customer object and attach the PaymentMethod that was previously collected and then create the Subscription.

How to save card details (payment method) in Stripe using backend?

The docs only covers the case where the payment method is created by the frontend (JS). But there is a risk that the user leaves the website before the frontend sends the information to the backend that the card has been added (and its ID).
In order to make a payment, I need ID of the payment method. I don't want to query Stripe's API for user cards IDs every time before making a payment, so I want to save the payment method ID in my local database. I also want to allow the user to define more payment methods and choose the default one.
Is there a reason you are using the non-recommended workflow you linked to? The most up-to-date version can be found here
Have you checked out using webhook listeners? I use them to create/update my local records.
In the workflow you reference, 3 webhook events potentially fire. First the setup_intent.created event is triggered when your server code generates the SetupIntent and its client_secret. Then, when the user fills out whatever Payment or Card element you instantiate and your frontend code calls the stripe.confirmCardSetup() (or stripe.confirmSetup() in the case of a PaymentElement), both the setup_intent.succeeded and payment_method.attached events will fire.
This last one will POST the payment_method object that was just attached to your customer back to your system. This object will have both the Payment Method ID as well as the associated Customer ID. You can use these to update your local records to map payment methods to customers in your server and avoid unnecessary API calls.

With Stripe, make an hold on a payment and confirm it when the subscription starts

We are working on a service that can start a subscription later in the future: users say today they want the service, but it actually starts some days later.
We are now collecting the payment method through a SetupIntent, which allows the user to verify they own card, but it actually doesn't verify the credit availability. When we collected the payment method, we create a scheduled subscription with the verified payment method; then, when the subscription starts, Stripe uses that payment method to collect money.
It happens, sometimes, that users do not have enough credit to pay for the service when the subscription starts. Otherwise, it also happens that, when Stripe tries to get money, the customer's bank requires 3D-secure verification.
Since our subscriptions start at midnight, we would like to avoid having to involve users again in the payment process.
So, we thought: would it be possible to immediately collect the payment method through an hold on a PaymentIntent and confirm that hold only when the subscription starts? I can't find a way to do this with Stripe (don't know if it exists). It seems impossible, with Stripe, to generate a PaymentIntent (with capture_method set to manual) for a scheduled subscription.
Do you have some ideas on how we can avoid payment problems when the subscription starts?
Otherwise, it also happens that, when Stripe tries to get money, the
customer's bank requires 3D-secure verification.
This shouldn't be the case if you complete any required 3DS authentication as a part of the SetupIntent confirmation flow. Call confirmCardSetup whilst the user is present and that way the payment method is successfully verified and can be used to process off-session payments for your subscription as you need.
You can use Stripe to place a hold on a card, but this generally doesn't apply to the use case you've described.
I found a workaround for this by first creating a paymentIntent with setup_future_usage="off_session" and capture_method="manual" to first place a hold and save the paymentMethod, and then, only after capturing this paymentIntent, creating a subscription using the newly saved paymentMethod with billing_cycle_anchor that equals your subscription's interval from now.
This way it's like your customer has paid for the first interval using the paymentIntent, but will be charged from the second interval using the subscriptions API, which allows you to cancel the hold on the first payment and not create a subscription if something goes wrong.

Stripe: handle the first subscription and webhook event

My customer join a our subscripton plan at the first time, I create a transaction (called START-transaction) and use Stripe's API to create new subscription and store subscription object return within above transaction.
I also using webhook to catch Stripe's events. My bigest purpose is handle recurring payment (send notification on charge success or fail, and something for customer's interaction). I catch event invoice.payment_succeeded to detect it's a recuring billing. I create a transaction too (call RECURRENCE) and, of couse, I store event object within transaction. (base on subscription information in event invoice.payment_succceeded, I find out relative-START transaction and create a new transaction as long as RECURRENCE)
And the problem exposes, in the first time customer creates plan, there 6 event called back to my system: customer.created; charge.succeeded; invoice.created; invoice.payment_succeeded; customer.card.created; customer.subscription.created. So, my customer have 2-transactiona: 1-START and 1-RECURRENCE at the first time.
Do you suggest me any idea to remove RECURRENCE transaction?
Thank you.
It sounds like you want to be able to tell if the invoice.payment_succeeded event you receive is for the first payment (which you already processed in your "START transaction") or not (in which case you want to process it in a "RECURRENCE transaction").
The simplest way to do this is to look at the event object's request attribute. Because the first invoice is a direct consequence of your subscription creation request, the first invoice.payment_succeeded event will have a non-null value for the request attribute. Subsequent invoices are created in the background by Stripe, and so the events will have a null value for the request attribute.
You can use the Stripe Request's billing_reason to identify if it is a first-time subscription, a recurring payment, or an updated invoice payment. See https://stripe.com/docs/api/invoices/object#invoice_object-billing_reason

Does the Dwolla API Webhooks Notification send the wrong transaction id?

I think that the Dwolla API sends the wrong transaction ID in notifications. In a normal dwolla money transaction, two transaction IDs are created (this is weird to me, but that's how dwolla does it). Because these two are created at the same time, they are always (in my experience) consecutive numbers.
So e.g. if account X sends money to account Y, Y will see transaction id M, and X will see transaction id M+1.
But Dwolla's notification webhook will send Y details of the transaction with id M+1. While ID M+1 is still unique to this transaction, ID M+1 cannot be used by Y via the API - because M+1 is supposed to only be used by X.
Here is a specific example:
Via my webapp, I send money from my personal dwolla account to my organization's via the off-site gateway api.
My webapp is sent the transaction details in both callback and notification form. The transaction id generated by step 1 is 1431566. This is the transaction id sent to both callback and notification. My web app stores this Id for future use.
Via my webapp, I decide to refund my personal dwolla account from my organization's so:
My webapp tries to query dwolla about transaction 1431566, to get the SourceId, but this fails - dwolla reports "Transaction not found for account". My automatic refund cannot continue without an ugly kludge like subtracting one from the Id and trying again.
The manual workaround is to login to my organization's dwolla account via the web interface. Here I can look for the transaction based on datetime and I can see that the transaction ID is actually 1431565 (correctly reported in the web interface). If I go into my organization's database and replace 1431566 with 1431565, I can repeat step 4 and it works this time. After that I can initiate a send() and the refund goes through.
I reported the same problem here before dwolla moved support to stackoverflow: https://getsatisfaction.com/dwolla/topics/callback_and_webhook_notification_sent_wrong_transaction_id_off_by_one
I figure it will be fixed faster if other people have the same problem. Or maybe I'm missing something obvious and someone will point it out.
Thanks to Michael's help, we were able to get around this issue by using the receiver's OAuth token when getting the transaction details instead of the sender's OAuth token.
For example, say I send some money using the API and transactions 1202 for the money sender and 1201 for the money receiver get created. If you make the API call to get details for transaction 1202 but use the receiver's OAuth token, it will give you details for transaction 1201, including fee information.
I'm not sure if the situation is exactly the same since we are acting as the facilitator between two transactions, so no guarantees that this will work in your situation. But it's worth a try.
So, your application's key & secret can access the transaction ID posted to you by passing the transactionById() method your application's client_id and client_secret, as opposed to the oauth_token. Meaning, when you poll for the transaction, instead of querying this URL:
https://www.dwolla.com/oauth/rest/transactions/{transaction_id}?oauth_token=x
Query this url, instead:
https://www.dwolla.com/oauth/rest/transactions/{transaction_id}?client_id=x&client_secret=y
Makes sense?

Resources