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

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

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 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.

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 */
}
}
}

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!

Facebook Pay Dialog : There Was a issue Processing Your Payment

I have used the following code for open the Facebook Pay Dialog box for My application app on Facebook but getting error :
<div id="fb-root"></div>
<script src="http://connect.facebook.net/en_US/all.js"></script>
<p> <a onclick="placeOrder(); return false;">Buy</a></p>
<script>
FB.init({appId: 367311903326028, status: true, cookie: true});
function placeOrder() {
// If using mobile, this is where you place the
// iOS native app check for credits (see below)
// Assign an internal ID that points to a database record
var order_info = 'abc123';
// calling the API ...
var obj = {
method: 'pay',
order_info: order_info,
action: 'buy_item',
dev_purchase_params: {'oscif': true}
};
FB.ui(obj, callback);
}
var callback = function(data) {
if (data['order_id']) {
return true;
} else {
//handle errors here
return false;
}
};
function writeback(str) {
document.getElementById('output').innerHTML=str;
}
</script>
<br>
Error :
There Was a Problem Processing Your Payment
Sorry, but we're having trouble processing your payment.
You have not been charged for this transaction. Please try again.
Please can anyone suggest me what going wrong here.
Thanks
Without more information it's really hard to know what the issue is here. Specifically, what response are you supplying to the payments_status_update request? Can you show us the code that handles those requests, or an example of your response?
I've personally seen that error message in cases where our callback was responding incorrectly to the payments_status_update request, but it could be something else.
Seems to me that you are using the old currency payments, which is a bad idea as they are going to be deprecated in two months.
Check that in your FB App settings you are NOT using the new Local currency payments, as if you have it enabled (which is the default setting now), then the only way that you can make a purchase is with the new way. Using the old way will fail.
Deactivating the new payment method will allow you to use BOTH the new and the old method.