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

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.

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>

PayPal Checkout Installment Plans

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)

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 create a Subscription payment using Paypal client-side rest api?

The Client-side REST integration documentaion describes about creating a express checkout for one or more items.
How can i use the same for creating a subscription or Recurring payment? How should the following be modified?
payment: function(data, actions) {
return actions.payment.create({
transactions: [
{
amount: { total: '1.00', currency: 'USD' }
}
]
});
},
I found a similar Rest api for Node. Not sure how it would be on JS.
First you need to create a billing plan:
billing_plan_attributes = {
"name": PLAN_NAME_HERE,
"description": PLAN_DESCRIPTION,
"merchant_preferences": {
"auto_bill_amount": "yes", # yes if you want auto bill
"cancel_url": "http://www.cancel.com", # redirect uri if user cancels payment
"initial_fail_amount_action": "continue",
"max_fail_attempts": "1",
"return_url": RETURN_URL,
"setup_fee": {
"currency": CURRENCY,
"value": VALUE # how much do you want to charge
}
},
"payment_definitions": [
{
"amount": {
"currency": request.form['currency'],
"value": request.form['amount']
},
"cycles": CYCLES, # how much time this subscription will charge user
"frequency": FREQ, # month, day
"frequency_interval": INTERVAL, # per month or per three month or so on
"name": NAME,
"type": TYPE
}
],
"type": TYPE
}
billing_plan = BillingPlan(billing_plan_attributes)
if billing_plan.create():
print("success")
The attributes used have literal meaning here. Now since you have created a billing plan you need to give users some interface so that they can subscribe with it. Below is a sample code for this:
billing_agreement = BillingAgreement({
"name": "Organization plan name",
"description": "Agreement for " + request.args.get('name', ''),
"start_date": (datetime.now() + timedelta(hours=1)).strftime('%Y-%m-%dT%H:%M:%SZ'),
"plan": {
"id": request.args.get('id', '')
},
"payer": {
"payment_method": "paypal"
},
"shipping_address": {
"line1": "StayBr111idge Suites",
"line2": "Cro12ok Street",
"city": "San Jose",
"state": "CA",
"postal_code": "95112",
"country_code": "US"
}
})
if billing_agreement.create():
for link in billing_agreement.links:
if link.rel == "approval_url":
approval_url = link.href
In the last line you get the approval link which can be given to user.
Next you have to setup an endpoint which will be the callback url if user approves the payment.
billing_agreement_response = BillingAgreement.execute(payment_token)
payment_token is sent by paypal to your callback url.