I am using Paypal Smart Buttons (Javascript SDK) to create recurring subscriptions. My issue is that (very infrequently) a user manages to create a duplicate subscription and recurring payments.
When I look at my logs I can see the transactions are happening within 60 seconds so I assume it's an accidental double click on the Paypal pay button (or something).
I read the docs and saw that for standard payments you can add:
A unique
invoice_id
that hasn't been used for a previously-completed transaction to identify the order for accounting purposes and to prevent duplicate payments.
However there doesn't seem to be a way to stop duplicate subscriptions/recurring payments because the subscription API only supports custom_id
.
See documentation here and another similar question here.
Here is my code:
paypal.Buttons({
style: {
shape: 'rect',
color: 'silver',
label: 'subscribe'
},
onError: function (err) {
// show error message
},
onClick: function(data) {
// do something when the button is clicked
},
// Create the subscription
createSubscription: function(data, actions) {
return actions.subscription.create({
plan_id: "P-12345355RK523772MMDZIKUA",
start_time: "2022-01-17T09:00:00Z",
custom_id: order_reference,
plan: {
billing_cycles: [
{
frequency: {
interval_unit: "MONTH",
interval_count: 1
},
tenure_type: "REGULAR",
sequence: 1,
pricing_scheme: {
fixed_price: {
value: 149,
currency_code: "USD"
}
}
}]
},
application_context: {
shipping_preference: "NO_SHIPPING"
}
});
},
// Finalize the transaction
onApprove: function(details, actions) {
console.log("subscription_id: "+details.subscriptionID)
$('#thanks').load("/paypal/thanks?reference="+order_reference, details,
function(responseText, textStatus, request) {
if (textStatus == "error") {
// show error message
}
});
}
}).render('#paypal-button-container');
My current solution is to check in the paypal/thanks controller whether the order has already been associated with a subscription. If that happens I sent myself an error alert via email and have to manually fix the mess
Someone else suggested I automate that process, but I am hoping there's a better solution.
Thanks