How to reference a paypal webhook to a user? - paypal

I'm trying to figure out the best way to associate the webhook to a user of the webapp.
Upon a paypal transaction I receive the webhook from paypal
but it doesn't have a reliable reference that I can use
to associate with the user in the app.
My solution would be to:
On the onApprove function use javascript code to submit a form with the subscriptionID
hidden on an input and send it to the server.
After receiving the subscriptionID on the server, create the webhook database entry with the subscriptionID field of the user that made the transaction.
And when I receive the webhook from paypal I can reference the user through the
subcriptionID.
Anyone around went through this one with a better option?
I was thinking if there is a way to insert the userID of the webapp in the paypal webhook.
Would be more clean.
Havent' found anything tho.
Here is the paypal webhook client call:
<script>
paypal.Buttons({
style: {
shape: 'pill',
color: 'gold',
layout: 'vertical',
label: 'subscribe'
},
createSubscription: function(data, actions) {
return actions.subscription.create({
/* Creates the subscription */
plan_id: '************************'
});
},
onApprove: function(data, actions) {
alert(data.subscriptionID); // You can add optional success message for the subscriber here
}
}).render('#paypal-button-container-******************'); // Renders the PayPal button
</script>
Thanks

When you create the subscription, pass a unique custom_id

thanks Preston. This is defenitely the best option. I was having trouble because I was adding a new field with a random name to associate to the userID of the app. It turns out that you really need to use the custom_id key in order to receive it in the webhook calls.
Final solution was the following:
<script>
paypal.Buttons({
style: {
shape: 'pill',
color: 'gold',
layout: 'vertical',
label: 'subscribe'
},
createSubscription: function(data, actions) {
return actions.subscription.create({
/* Creates the subscription */
plan_id: '************************',
custom_id: 'appUserID'
});
},
onApprove: function(data, actions) {
alert(data.subscriptionID); // You can add optional success message for the subscriber here
}
}).render('#paypal-button-container-******************'); // Renders the PayPal button
</script>
Then the custom_id field will be available in all of the webhook calls. Perfect!

Related

Integrating PayPal Checkout - works on test, but not live

I am integrating PayPal checkout from a PayPal business account into my website.
I tried this with client_id set to "test", and it looks like it works.
This is the code I have, taken largely from PayPal's own website:
<!-- Replace "test" with your own sandbox Business account app client ID -->
<script src="https://www.paypal.com/sdk/js?client-id=XXXXXXXXXXXXXXXXXXXX&commit=true"></script>
<!-- Set up a container element for the button -->
<div id="paypal-button-container"></div>
And:
<script>
paypal.Buttons({
// Sets up the transaction when a payment button is clicked
createOrder: (data, actions) => {
return actions.order.create({
purchase_units: [{
amount: {
value: '77.44' // Can also reference a variable or function
}
}]
});
},
// Finalize the transaction after payer approval
onApprove: (data, actions) => {
return actions.order.capture().then(function(orderData) {
// Successful capture! For dev/demo purposes:
console.log('Capture result', orderData, JSON.stringify(orderData, null, 2));
const transaction = orderData.purchase_units[0].payments.captures[0];
alert(`Transaction ${transaction.status}: ${transaction.id}\n\nSee console for all available details`);
// When ready to go live, remove the alert and show a success message within this page. For example:
// const element = document.getElementById('paypal-button-container');
// element.innerHTML = '<h3>Thank you for your payment!</h3>';
// Or go to another URL: actions.redirect('thank_you.html');
});
}
}).render('#paypal-button-container');
</script>
When my code uses "client-id=test", then the PayPal pop-up payment window shows up as expected when you click on the payment button.
I have created a new REST API in my PayPal business account, and got a client ID and secret key.
I have no idea what to do with the secret key?
But if I change the "client-id=XXXXX" to use my client ID, when I click on the payment button, the pop-up window flashes up for less than a second and then disappears.
Am I missing something?

How to use paypal subscription revise

I am just curious if it is possible to use the Paypal subscription Button revise method with a subscription that is of the status "APPROVAL_PENDING".
paypal.Buttons({
createSubscription: function(data, actions) {
return actions.subscription.revise("I-HAHWJUY845PE", {
'plan_id': 'P-6GE98585DE1334530MJ3IPDA',
});
},
onApprove: function(data, actions) {
alert('You have successfully created subscription ' + data.subscriptionID); // Optional message given to subscriber
}
}).render('#P-8B719909FS0268804MJ3IPDA'); // Replace with your plan ID
I have tried but it keeps failing, saying resource is not found!!
No. If approval is pending, create a new subscription rather than revising one that was never approved to begin with, and forget about it.

How to customise the amount of a Paypal subscription made using JS SDK

I'm trying to upgrade a legacy system that uses Paypal for subscriptions. The older way redirects to Paypal (Checkout?) and the new way is trying to use their JavaScript SDK:
https://developer.paypal.com/sdk/js/reference/
return actions.subscription.create({
'plan_id': 'P-2UF78835G6983425GLSM44MA'
});
The older system created Payment Plans on the fly, and so the payer was able to adjust the amount rather than sticking with the amount stored in a pre-made plan. I hope to replicate this behaviour using the JS sdk.
The above pages links to here: https://developer.paypal.com/api/subscriptions/v1/#subscriptions_create "for allowed options defined in the request body."
One of the parameters within the subscription creation is:
plan [object]
"An inline plan object to customise the subscription. You can override plan level default attributes by providing customised values for the subscription in this object."
This seems like the thing I am after but I am unable to get Papal to use anything I put inside there, ie:
plan_id: plan_id,
custom_id: "Does this thing work?",
plan_overridden: true,
plan: {name: "Testing ABC123 Special"}
"Does this thing work?" will carry but nothing within the plan.
One other thing of note is that the older system didn't pass a plan_id, which doesn't seem possible with the JS SDK.
I think the older way is using Checkout, are these two methods completely imcompatible?
Thank you so much!
name cannot be overridden.
Keys that can be overridden are documented in the plan_override object.
If you need to customize more plan details, create the subscription on the server side and return its id to the calling JS (within that server route, the plan_id can first be created on the fly if one doesn't already exist for the name you need)
<script src="https://www.paypal.com/sdk/js?client-id=XXXXXXXXXXXXX&vault=true&intent=subscription&currency=USD"></script>
<div id="paypal-button-container"></div>
<script>
paypal.Buttons({
style: {
label:'subscribe' //Optional text in button
},
createSubscription: function(data, actions) {
return fetch('/path/on/your/server/paypal/subscription/create/', {
method: 'post'
}).then(function(res) {
return res.json();
}).then(function(serverData) {
console.log(serverData);
return serverData.id;
});
},
onApprove: function(data, actions) {
/* Optional: At this point, notify your server of the activated subscription...
fetch('/path/on/your/server/paypal/subscription/activated/' + data.subscriptionID , {
method: 'post'
}).then(function(res) {
return res.json();
}).then(function(serverData) {
//
});
*/
//You could additionally subscribe to a webhook for the BILLING.SUBSCRIPTION.ACTIVATED event (just in case), as well as other future subscription events
//Ref: https://developer.paypal.com/docs/api-basics/notifications/webhooks/event-names/#subscriptions
// Show a message to the buyer, or redirect to a success page
alert('You successfully subscribed! ' + data.subscriptionID);
}
}).render('#paypal-button-container');
</script>
My answer was found on this page:
https://developer.paypal.com/docs/multiparty/subscriptions/customize/bill/
billing_cycles: [
{
sequence: 1,
total_cycles: 0,
pricing_scheme: {
fixed_price: {
value: "8",
currency_code: "USD",
},
},
},
],
It didn't make the name change but it did make the amount change which is actually all I care about :)

PayPal Subscription Button Coupons

I am using Paypal buttons to subscribe customers to a plan.
I am trying to apply coupons on the Paypal buttons without any luck.
This is the code that generate the Paypal button on the frontend:
paypal.Buttons({
style: {
shape: 'pill',
color: 'blue',
layout: 'vertical',
label: 'subscribe'
},
createSubscription: function (data, actions) {
return actions.subscription.create({
"plan_id": "<PAYPAL_PLAN_ID>"
});
},
onApprove: function (data, actions) {
console.log('success');
}
}).render('#paypal-button-container');
On the documentation I saw that I need to define a javascript variable and I tried
var discnt=10;
And:
var discount_amount=10;
None of this variables are working.
Even if the discount will work this way, I want to give the marketing team to define Coupons on their own, and give it to the customers.
Anyone might know how to add coupons to paypal.Buttons?
In addition to the plan_id , you can pass a plan object which overrides the provided plan's details with a different amount, and with a description that reflects the text "discount" or "coupon applied" somewhere.
Parameters for a subscription create call are documented here: https://developer.paypal.com/api/subscriptions/v1/#subscriptions-create-request-body
So for instance, something like
return actions.subscription.create({
"plan_id": "<PAYPAL_PLAN_ID>",
"plan" : {
"name" : "My Service - $10 coupon",
"billing_cycles" {
/* New billing cycles object with lower amount */
}
}
}

Paypal Smart Button Subscription Status

I am new to set up Subscription using Paypal Smart buttons. I have created a Paypal smart button subscribe from Paypal account and have pasted it in my html. Have added my OnInit and Onclick function to validate before user clicks.
I am checking if the subscription is Active or not after the user goes through the "agree and subscribe" page. (This is done in "notify.php" where I call using paypal REST api and get the subscription status)
<div id="paypal-button-container"></div>
<script src="https://www.paypal.com/sdk/js?client-id=XXXXXXXXXXXXXXXX&vault=true&intent=subscription" data-sdk-integration-source="button-factory"></script>
<script>
paypal.Buttons({
style: {
shape: 'pill',
color: 'gold',
layout: 'vertical',
label: 'subscribe'
},
// onInit is called when the button first renders
onInit: function(data, actions) {
// Disable the buttons
actions.disable();
// Listen for changes to the radio
var items = document.getElementsByName("settings");
[].forEach.call(items, function (item) {
item.addEventListener("change", function () {
// Enable or disable the button when it is checked or unchecked
if (event.target.checked) {
actions.enable();
} else {
actions.disable();
}
});
});
},
// onClick is called when the button is clicked
onClick: function() {
var radios=document.querySelectorAll('input[type="radio"]:checked').length;
// Show a validation error if the checkbox is not checked
if (radios == 0) {
document.querySelector('#error').classList.remove('hidden');
}
},
createSubscription: function(data, actions) {
return actions.subscription.create({
'plan_id': 'P-XXXXXXXXXXXX'
});
},
onApprove: function(data, actions) {
alert(data.subscriptionID);
alert(data.SubscriptionDate);
// You must return a promise from onClick to do async validation
return fetch("notify.php", {
method: 'post',
headers: {
'content-type': 'application/json'
},
body:JSON.stringify({
subscriptionID:data.subscriptionID
})
}).then(response => {
return response.text();
})
.then(data => {
console.log(data);
if(data == "ACTIVE"){
location.href = "validate.html?data=ACTIVE";
}
})
.catch(error => {console.log(error)
});
}
}).render('#paypal-button-container');
</script>
</div>
Q1. Could somebody please confirm when the subscription status returns as "ACTIVE", it means that the user has paid and has subscribed successfully. And thus I can update this information in my DB.
OR Do I need to capture the transaction in OnApprove as below:
onApprove: function (data, actions) {
// Capture the transaction funds
return actions.order.capture().then(function () {
Q2. Is this way of integrating the button on my web page is secure?
UPDATE:
(All this is for my personal webpage where I am providing a service to customers. I want to activate a subscription for them.)
I made a subscription plan from my Paypal account. Added the generated code on my webpage and now I want to check whether the user/customer has paid/subscribed successfully to my service so that I can enable service for them and also update their information in my DB.
An active PayPal subscription does not indicate the first payment has already been made.
Subscriptions bill on a batch schedule. To be notified when a successful payment is made, subscribe to the Webhook event PAYMENT.SALE.COMPLETED