How to use paypal subscription revise - paypal

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.

Related

How to test failed transactions with the PayPal JS SDK

We are using the PayPal JS SDK ^5.1.0 and I'm using it to generate a pay button like described in the docs:
const paypal = await loadScript({
"client-id": conf.client_id,
"currency": conf.currency_code
});
await paypal.Buttons({
// Sets up the transaction when a payment button is clicked
createOrder: (coData, actions) => {
if (price.getTotal()) {
data.data.amount = price.getTotal();
return actions.order.create({
purchase_units: [{
description: config.registrationCenterDisplayName,
amount: {
value: price.getTotal().toFixed(2) // Can also reference a variable or function
},
}],
application_context: {
shipping_preference: 'NO_SHIPPING'
}
});
} else {
throw new Error('Amount can not be 0');
}
},
// Finalize the transaction after payer approval
onApprove: (oaData, 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];
data.data.id = transaction.id;
data.data.status = transaction.status;
dataValid = true;
submit();
});
}
}).render(buttonWrapper[0]);
It seems not to work well with error case i live. How can I provoke failed transactions or capture erros in sandbox mode?
I found the negative testing mode of a sandbox, but it does not change the behaviour for the button. I still get only positive responses.
I opened also an issue in the github repo: https://github.com/paypal/paypal-js/issues/273
Thx a lot for any help! I might overlook something very obvious...
For client-side captures, actions.order.capture().then( is only triggered when a capture is successful.
Failure cases are handled by the JS SDK itself, there is no need to test anything as it is not your code.
For server-side capturing (not your question) and using the JS SDK for approval, see the demo code here. Negative testing can be used from server API calls for failures if desired.

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 :)

How to reference a paypal webhook to a user?

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!

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

Paypal Smart Button Check Postal Code onApprove

The problem:
I am trying to figure out how to check the if postal code (entered during the paypal smart button check-out) meets specific requirements.
I have the createOrder, and onApprove object attributes I would like to check the postal code before i capture the payment so i can reject it, and cancel the order.
paypal.Buttons(
{
createOrder: function(data, actions) {
// This function sets up the details of the transaction, including the amount and line item details.
return actions.order.create({
purchase_units:
[
{
description: "Raffle Tickets",
custom_id: $('#cartID').val(),
soft_descriptor: "soft_descriptor",
amount: {
currency_code: "CAD",
value: cartVal,
breakdown: {
item_total: {
currency_code: "CAD",
value: cartVal
}
}
},
items: itemList
}
]
});
},
onApprove: function(data, actions) {
//id like to check the postal code here, or maybe do an ajax call then on success, call the
//capture function below to finalize the payment.
// This function captures the funds from the transaction.
return actions.order.capture().then(function(details) {
// This function shows a transaction success message to your buyer.
$('#details').val(JSON.stringify(details));
$('#frmConfirm').submit();
});
}
}).render('#paypal-button-container');
return actions.order.get().then(function(data,actions) {
console.log(data);
/* if logic on data.payer.address.postal_code goes here */
actions.order.capture().then(function(details) {
$('#details').val(JSON.stringify(details));
$('#frmConfirm').submit();
}
});
You mentioned AJAX; there are server-side equivalent APIs, if you want to switch from this client-side implementation to one that uses code on the server to validate. In that case the front-end would look more like this: https://developer.paypal.com/demo/checkout/#/pattern/server , and there is a v2/orders API call to get the details of the approved order before capturing it.