PayPal Checkout Installment Plans - paypal

I'm using paypal to receive payments, but I would like to pass a form of installment to the user, but depending on the values, I wanted this to be variable, I didn't find anything in the documentation about it, is it possible?
this.paypalConfig = {
currency: 'BRL',
createOrder: function (data, actions) {
return actions.order.create({
intent: "CAPTURE",
purchase_units: [{
"amount":
{
"value": self.amount,
"currency_code": "BRL",
"description": self.name,
},
}]
});
},
onApprove: function (data, actions) {
return actions.order.capture().then(function (details) {
},
onCancel: function (data) {
// Show a cancel page, or return to cart
console.log(data);
},
onError: function (err) {
// Show an error page here, when an error occurs
console.log(err);
},
}

For BR payments in BRL, installments can be configured at the live PayPal Business account level
(and if you are testing in sandbox with a BR sandbox business account you can also log into Sandbox here to enable installments)
More information on PayPal.com (Portuguese)

Related

I called Paypal subscription API which returns success message but don't see any active subscription in the Paypal dashboard

I am trying to create Paypal subscription through its Rest API using live client and secret.
The API returns success message. The GET subscription API returns the active subscription created, however I don't see any active subscription in my Paypal dashbaord.
Paypal support says the subscription ID does not exist.
Has anyone encountered such issue with Paypal API?
I have attached API JSON response and snapshot herewith.
{
"plans": [
{
"id": "P-4UJ45561KJ704964LMJ2QDZQ",
"product_id": "PROD-4EX86934CR7151923",
"name": "Certified business economist IHK | VO 2022",
"status": "ACTIVE",
"description": "The business economist IHK is divided into the following five subjects with the new examination regulations 2022",
"usage_type": "LICENSED",
"create_time": "2022-05-06T11:09:26Z",
"links": [
{
"href": "https://api.paypal.com/v1/billing/plans/P-4UJ45561KJ704964LMJ2QDZQ",
"rel": "self",
"method": "GET",
"encType": "application/json"
}
]
}
],
"total_items": 1,
"total_pages": 1,
"links": [
{
"href": "https://api.paypal.com/v1/billing/plans?product_id=PROD-4EX86934CR7151923&page_size=2&page=1",
"rel": "self",
"method": "GET",
"encType": "application/json"
}
]
}
First of all, everything in your question shows creating a plan. A plan is not a subscription, it is the cycle details to be able to create a subscription.
Secondly, creating a subscription still will not do anything unless a payer signs in to approve it. For a payer to approve a subscription, use a PayPal button. This is detailed in the Subscriptions Integration Guide.
Note that the createSubscription function can create a subscription for approval itself, by passing it an object with a plan_id (and optionally a plan object to override some part of that plan_id). This is the most simple method.
Alternatively, the subscription can be created via API, at a route on your server which that function will fetch when the button is clicked. Something like:
<script src="https://www.paypal.com/sdk/js?client-id=YOUR_CLIENT_ID_GOES_HERE&vault=true&intent=subscription"></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/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>

Store custom metadata with Paypal transaction

I am extending an application that is currently having stripe as a Payment processor. The architecture is implemented in such a way that I am not storing any of the transaction and customer information in the application database in order to meet the compliances. So all of data is being stored in Stripe as transaction metadata.
Now I need to extend the application to add Paypal Payment Gateways, but after going through the documentation I can't find a metadata option available in the PayPal Transaction API just like its there in Stripe.
I have tried PayPal's create order API with metadata as suggested in v1
https://developer.paypal.com/docs/business/checkout/server-side-api-calls/create-order/
createOrder: function(data, actions) {
return actions.order.create({
metadata:{
"cid":1233,
"dgn":"AH-GHGJTTHHHJ",
"ct":"X-HGD898989","tfn":"xyz params",
"type":"2",
"lo":"lorem ipsum is a dummy text and hope it works"
},
purchase_units: [
{
"description":'xyz P30 Pro mobile',
"amount":{"currency_code":"USD","value":199}
}]
});
},
But on retrieving the transaction by TX_ID i donot get the metadata object back.
So anyone who faced this challenge in the past and can suggest a workaround to achieve this with payPal will be highly appricated.
Apart from a unique (never used before for a completed payment) invoice_id for the transaction, the only custom metadata field in PayPal is custom_id, documented here: https://developer.paypal.com/docs/api/orders/v2/#orders-create-request-body
If you need additional fields, store them locally based on your own order/invoice ID or the resulting PayPal Transaction ID and look them up later as needed. Your most sensitive data with compliance issues might possibly go into custom_id as a serialized JSON string, if it is small enough (127 chars)
Purchase item information can go in an "items" array, which requires the amount have a "breakdown" object. See the example within the docs,
createOrder: function(data, actions) {
return actions.order.create({
"purchase_units": [{
"amount": {
"currency_code": "USD",
"value": "100",
"breakdown": {
"item_total": { /* Required when including the `items` array */
"currency_code": "USD",
"value": "100"
}
}
},
"items": [
{
"name": "First Product Name", /* Shows within upper-right dropdown during payment approval */
"description": "Optional descriptive text..", /* Item details will also be in the completed paypal.com transaction view */
"unit_amount": {
"currency_code": "USD",
"value": "50"
},
"quantity": "2"
},
]
}]
});
},

Error on capture sandbox Paypal smart buttons COMPLIANCE_VIOLATION [duplicate]

This question already has an answer here:
PayPal Checkout UNPROCESSABLE_ENTITY: COMPLIANCE_VIOLATION
(1 answer)
Closed 1 year ago.
I'm trying to integrate a very basic Paypal smart button on client side, exactly as on docs page, here is my snippet:
<div id="smart-button-container">
<div style="text-align: center;">
<div id="paypal-button-container"></div>
</div>
</div>
<script src="https://www.paypal.com/sdk/js?client-id=[my_sandbox_app_id]&currency=USD" data-sdk-integration-source="button-factory"></script>
<script>
function initPayPalButton() {
paypal.Buttons({
style: {
shape: 'rect',
color: 'gold',
layout: 'vertical',
label: 'paypal',
},
createOrder: function (data, actions) {
return actions.order.create({
purchase_units: [{ "description": "first product", "amount": { "currency_code": "USD", "value": 5 } }]
});
},
onApprove: function (data, actions) {
return actions.order.capture().then(function (details) {
alert('Transaction completed by ' + details.payer.name.given_name + '!');
});
},
onError: function (err) {
console.log(err);
}
}).render('#paypal-button-container');
}
initPayPalButton();
</script>
But I get these errors 422 500 instead of approve:
By checking Networks tab I find these details about error 422:
How to come over this errors ?
{
"name": "UNPROCESSABLE_ENTITY",
"details": [
{
"issue": "COMPLIANCE_VIOLATION",
"description": "Transaction cannot be processed due to a possible compliance violation. To get more information about the transaction, call Customer Support."
}
],
"message": "The requested action could not be performed, semantically incorrect, or failed business validation.",
"debug_id": "19961f1d1be55",
"links": [
{
"href": "https://developer.paypal.com/docs/api/orders/v2/#error-COMPLIANCE_VIOLATION",
"rel": "information_link",
"method": "GET"
}
]
}
For Sandbox testing, create a Sandbox account and associated REST App for a different country -- for example US.

Paypal onShippingChange / patch not working as expected

I find that there is precious little Paypal help online when things are behaving badly, and I am having some trouble with onShippingChange() and actions.order.patching. When I run the following code with the new Paypal buttons, return actions.order.patch() doesn't seem to work properly.
My code is below:
<script src="https://www.paypal.com/sdk/js?commit=false&client-id={sandbox-merchant-id}&disable-funding=paylater&currency=USD"></script>
<script>
paypal.Buttons({
createOrder: function(data, actions) {
return actions.order.create({
"purchase_units": [{
"description": "Sporting Goods",
"amount": {
"currency_code": "USD",
"value": 12,
"breakdown": {
"item_total": {
"currency_code": "USD",
"value": 12
},
"shipping": {
"currency_code": "USD",
"value": 0
}
}
},
"items": [{
"name": "Arizona Christmas",
"sku": "sku01",
"quantity": "1",
"unit_amount": {
"currency_code": "USD",
"value": 12
}
}]
}]
});
},
onShippingChange: function(data, actions) {
const baseOrderAmount = '12.00';
if (data.shipping_address.state == "AZ") {
const shippingAmount = data.shipping_address.state === 'AZ' ? '50.00' : '60.00';
return actions.order.patch([{
op: 'replace',
path: '/purchase_units/#reference_id==\'default\'/amount',
value: {
currency_code: 'USD',
value: (parseFloat(baseOrderAmount) + parseFloat(shippingAmount)).toFixed(2),
breakdown: {
item_total: {
currency_code: 'USD',
value: baseOrderAmount
},
shipping: {
currency_code: 'USD',
value: shippingAmount
}
}
}
}]);
}
}
}).render('#paypal-button-container');
</script>
With the above code, when I change from a default California address to an Arizona address (in order to cause a change in shipping costs), the onShippingChange(...) event fires immediately, then the Paypal window shows the "processing" loader, then shows the new total in the upper right corner. The Paypal window itself shows $62 (as expected), but when I expand the total price breakdown, it shows $0 for shipping. Also, console.log(data) shows nothing updated... all the original dollar values. So it appears that the details of the .patch are not being applied completely.
But then there is a strange thing I notice. If I hit F5 to refresh the Paypal window, it refreshes, of course. The total cost and breakdown become correct (shows correct total, shipping, etc), and the console.log(data) shows the correct breakdown, but then the address is back to the original address (a California address; that is the default address for the sandbox personal account).
So... I'm not sure what to make of this. Am I doing something wrong with the code above? Or is Paypal's system just not quite refined enough to use the new Buttons Javascript-only based solution (vs. the server-side solution)? I can't do the server side solution, so I'm hoping to get this to work properly using the plain javascript sdk implementation.

How to send a Payment to Multiple Merchants using PayPal v2 JavaScript

I have an ecommerce platform that has multiple sellers selling products and I want to use PayPal checkout v2 Javascript to send a payment to multiple merchants.
Using v2 JavaScript API:
https://www.paypal.com/sdk/js?client-id=CLIENT_ID&disable-funding=credit,card
paypal.Buttons({
onInit: function(data, actions) {
},
createOrder: function(data, actions) {
return actions.order.create({
"purchase_units": [
{
"reference_id": "1",
"amount": {
"currency_code": "AUD",
"value": "20.00",
"breakdown": {
"item_total": {
"currency_code": "AUD",
"value": "20.00"
}
}
},
"payee": {
"email_address": "payee1#business.example.com"
}
},
{
"reference_id": "2",
"amount": {
"currency_code": "AUD",
"value": "10.00",
"breakdown": {
"item_total": {
"currency_code": "AUD",
"value": "10.00"
}
}
},
"payee": {
"email_address": "payee2#business.example.com"
}
}
]
});
},
onApprove: function(data, actions) {
return actions.order.capture().then(function(details) {
alert('Transaction completed by ' + details.payer.name.given_name);
});
},
onError: function (err) {
alert(err.message);
}
}).render('#paypal-button');
I can login as a payer and see total $30, when I click Pay Now it says error "Order can not be captured". If I remove the second purchase unit object (payee 2) the transaction is approved.
I read on PayPal forums and api documentations and see mostly deprecated methods. How do I send a payment to multiple merchants now adays?
There is no mechanism for approving multiple v2/checkout/orders purchase_units with the JS checkout.
The deprecated methods should also not be used
How do I send a payment to multiple merchants now adays?
You don't -- not simultaneously, anyway. Each is its own separate checkout/approval event.
You have to create app as platform in your sandbox or live account
its best user experience to use js integration with multi seller checkout
You have pass merchantids on url and in js section as below
if multiple seller use this
multiple seller
<script
src="https://www.paypal.com/sdk/js?client-id=client_id&intent=capture&disable-funding=credit&merchant-id=*&currency=USD"
data-partner-attribution-id="bn_code"
data-merchant-id="merchant_id1,merchant_id2"
>
</script>
single seller
<script
src="https://www.paypal.com/sdk/js?client-id=client_id&intent=capture&disable-funding=credit&merchant-id=merchant_id1&currency=USD"
data-partner-attribution-id="bn_code"
data-merchant-id="merchant_id1"
>
</script>
Then you have to use js sdk integration with div as below
paypal.Buttons({
style : {
color: 'gold',
shape: 'pill',
label: 'pay',
},
createOrder: function (data, actions) {
return actions.order.create(data.json);
},
onApprove: function (data, actions) {
return actions.order.capture().then(function (details) {
//redirect to your server
window.location.replace(base_url+'paypal/create_order/'+details.id)
})
},
onCancel: function (data) {
console.log(data);
},
onError: function (err) {
// For example, redirect to a specific error page
console.log(err);
}
}).render('#paypal-payment-button');
For how to create order please check the documentation.