PayPal Sandbox Testing Multi-Vendor Commission Fee Not Found - paypal

I was playing with PayPal Sandbox to integrate to our platform.
This is what my body looks like when creating order.
Order was approved and captured successfully, but commission fees don't come to my sandbox account.Does anyone know what I did wrong?
"intent": "CAPTURE",
"purchase_units": [
{
"reference_id": "ORDER1",
"payee": {
"merchant_id": "YKSAWY4EFUQ9N",
"email_address": "markz#example.com"
},
"amount": {
"currency_code": "USD",
"value": "2000.00"
},
"payment_instruction": {
"disbursement_mode": "INSTANT",
"platform_fees": [
{
"amount": {
"currency_code": "USD",
"value": "200.00"
},
"payee": {
"email_address": "sb-3zuuc16985762#business.example.com",
"merchant_id": "VZBJPJUECRLUY"
}
}
]
}
},
{
"reference_id": "ORDER2",
"payee": {
"merchant_id": "P7P8DG5Z9YF54",
"email_address": "stevejobs#example.com"
},
"amount": {
"currency_code": "USD",
"value": "1000.00"
},
"payment_instruction": {
"disbursement_mode": "INSTANT",
"platform_fees": [
{
"amount": {
"currency_code": "USD",
"value": "100.00"
},
"payee": {
"email_address": "sb-3zuuc16985762#business.example.com",
"merchant_id": "VZBJPJUECRLUY"
}
}
]
}
}
]
}

platform_fees are not credited to a PayPal account, ever. In production, they will be deposited to the confirmed bank account associated with the account. The only place you will see them is in a financial detail report.
Also, in order to use platform_fees the receiver of the transaction must first be onboarded with a third_party_details set to PARTNER_FEE https://developer.paypal.com/docs/api/partner-referrals/v2/#definition-third_party_details

Related

PayPal REST Api not returning exchange_rate

I have got a PayPal Advanced Checkout Sandbox set up and capturing the order using the API call below:
/v2/checkout/orders/{{order_id}}/capture
Below are the transaction details I send to create the order:
{
"intent": "CAPTURE",
"payer": {
"address": {
"admin_area_2": "Downton",
"postal_code": "SP5",
"country_code": "GB"
}
},
"purchase_units": [
{
"description": "Test Item",
"custom_id": "12345",
"soft_descriptor": "Purchase Descriptior",
"amount": {
"currency_code": "USD",
"value": "58.80",
"breakdown": {
"item_total": {
"currency_code": "USD",
"value": "49.00"
},
"tax_total": {
"currency_code": "USD",
"value": "9.80"
}
}
},
"items": [
{
"name": "Test Item",
"unit_amount": {
"currency_code": "USD",
"value": "49.00"
},
"tax": {
"currency_code": "USD",
"value": "9.80"
},
"quantity": 1,
"category": "PHYSICAL_GOODS"
}
],
"shipping": {}
}
]
}
And then once it has been paid with a sandbox personal account the order capture response is below:
{
"id": "4FS9138999682320N",
"status": "COMPLETED",
"payment_source": {
"paypal": {
"email_address": "sb-bdd43g21513704#personal.example.com",
"account_id": "V7ZN4NEJRLGZA",
"name": {
"given_name": "John",
"surname": "Doe"
},
"address": {
"country_code": "GB"
}
}
},
"purchase_units": [
{
"reference_id": "default",
"shipping": {
"name": {
"full_name": "John Doe"
},
"address": {
"address_line_1": "Whittaker House",
"address_line_2": "2 Whittaker Avenue",
"admin_area_2": "Richmond",
"admin_area_1": "Surrey",
"postal_code": "TW9 1EH",
"country_code": "GB"
}
},
"payments": {
"captures": [
{
"id": "40V95236PS9814847",
"status": "COMPLETED",
"amount": {
"currency_code": "USD",
"value": "58.80"
},
"final_capture": true,
"seller_protection": {
"status": "ELIGIBLE",
"dispute_categories": [
"ITEM_NOT_RECEIVED",
"UNAUTHORIZED_TRANSACTION"
]
},
"seller_receivable_breakdown": {
"gross_amount": {
"currency_code": "USD",
"value": "58.80"
},
"paypal_fee": {
"currency_code": "USD",
"value": "2.30"
},
"net_amount": {
"currency_code": "USD",
"value": "56.50"
}
},
"custom_id": "12345",
"links": [
{
"href": "https://api.sandbox.paypal.com/v2/payments/captures/40V95236PS9814847",
"rel": "self",
"method": "GET"
},
{
"href": "https://api.sandbox.paypal.com/v2/payments/captures/40V95236PS9814847/refund",
"rel": "refund",
"method": "POST"
},
{
"href": "https://api.sandbox.paypal.com/v2/checkout/orders/4FS9138999682320N",
"rel": "up",
"method": "GET"
}
],
"create_time": "2022-10-31T16:42:07Z",
"update_time": "2022-10-31T16:42:07Z"
}
]
}
}
],
"payer": {
"name": {
"given_name": "John",
"surname": "Doe"
},
"email_address": "sb-bdd43g21513704#personal.example.com",
"payer_id": "V7ZN4NEJRLGZA",
"address": {
"country_code": "GB"
}
},
"links": [
{
"href": "https://api.sandbox.paypal.com/v2/checkout/orders/4FS9138999682320N",
"rel": "self",
"method": "GET"
}
]
}
I get a status: COMPLETED as the response but it is not returning the exchange_rate value even though the payer currency is different to the payee currency.
Does anyone know why this is?
The example is a USD transaction, the payee account received USD.
If the payer used a funding source of a different currency to fund the transaction, this will not be visible to the receiver or API facilitator. Any such sender currency conversion is between the payer and PayPal; all you know (and all you need to know) is you received the requested USD amount via PayPal.

How to configure PayPal Smart Payment Buttons for local pickup?

I want to use PayPal to pay at a restaurants website for local pickup or delivery. My code seems to work for delivery, but I could not figure out how to use local pickup.
The documentation mentions a property called shipping_type which could be set to PICKUP, but it isn't clear where to set that property.
When I call actions.order.create with the following JSON object, PayPal still tells the user to choose a delivery address:
{
shipping: {shipping_type: "PICKUP", type: "PICKUP"},
shipping_type: "PICKUP",
shipping_option: {type: "PICKUP"},
"application_context": {
"payment_method": { "payee_preferred": "IMMEDIATE_PAYMENT_REQUIRED" }
},
"purchase_units": [ {
"shipping": { "option": { "type": "PICKUP" } },
"shipping_option": { "type": "PICKUP" },
"application_context": { "payment_method": { "payee_preferred": "IMMEDIATE_PAYMENT_REQUIRED" } },
"items": [
{ "name": "XXL Hamburger", "unit_amount": { "currency_code": "EUR", "value": "11.50" }, "quantity": 1 },
{ "name": "XXL Rumpsteak", "unit_amount": { "currency_code": "EUR", "value": "24.90" }, "quantity": 1 }
],
"amount": {
"currency_code": "EUR",
"value": "36.40",
"breakdown": { "item_total": { "currency_code": "EUR", "value": "36.40" } }
}
} ]
}
Does anyone has a working example?
By the way: When testing my code, it is unclear if IMMEDIATE_PAYMENT_REQUIRED does do something.
PayPal still tells the user to choose a delivery address
To have no shipping address as part of a PayPal transaction, use:
application_context: {
shipping_preference: 'NO_SHIPPING'
}

Google Express - Orderinvoices: createchargeinvoice

I am integrating Google Express with Magento but the Create charge invoices API is failing for me. I tried to create the invoice from the "Try this API" option of Google merchant but it's throwing the following error:
{
"error": {
"errors": [
{
"domain": "content.ContentErrorDomain",
"reason": "invalid_transition",
"message": "The requested order is not supported by orderinvoices service"
}
],
"code": 400,
"message": "The requested order is not supported by orderinvoices service"
}
}
createchargeinvoice API doc: https://developers.google.com/shopping-content/v2/reference/v2/orderinvoices/createchargeinvoice
My request body:
{
"invoiceId": "invoice1",
"operationId": "charge1",
"shipmentGroupId": "shipmentgroup1",
"lineItemInvoices": [
{
"productId": "online:en:US:d3k3245",
"shipmentUnitIds": [
"2"
],
"unitInvoice": {
"unitPricePretax": {
"value": "140",
"currency": "USD"
},
"unitPriceTaxes": [
{
"taxType": "sales",
"taxAmount": {
"value": "14",
"currency": "USD"
}
}
],
"promotions": [
{
"promotionId": "111",
"promotionAmount": {
"tax": {
"currency": "USD",
"value": "0"
},
"pretax": {
"currency": "USD",
"value": "0"
}
}
}
],
"additionalCharges": [
{
"additionalChargeAmount": {
"pretax": {
"currency": "USD",
"value": "0"
},
"tax": {
"currency": "USD",
"value": "0"
}
},
"additionalChargePromotions": [
{
"promotionAmount": {
"pretax": {
"currency": "USD",
"value": "0"
},
"tax": {
"currency": "USD",
"value": "0"
}
},
"promotionId": "111"
}
],
"type": "shipping"
}
]
}
}
],
"invoiceSummary": {
"productTotal": {
"pretax": {
"value": "561.20",
"currency": "USD"
},
"tax": {
"value": "55.98",
"currency": "USD"
}
},
"additionalChargeSummaries": [
{
"totalAmount": {
"pretax": {
"value": "561.20",
"currency": "USD"
},
"tax": {
"value": "55.98",
"currency": "USD"
}
},
"type": "shipping"
}
],
"promotionSummaries": [
{
"promotionAmount": {
"pretax": {
"value": "561.20",
"currency": "USD"
},
"tax": {
"value": "55.98",
"currency": "USD"
}
},
"promotionId": "111"
}
],
"merchantBalance": {
"pretax": {
"value": "561.20",
"currency": "USD"
},
"tax": {
"value": "55.98",
"currency": "USD"
}
},
"customerBalance": {
"pretax": {
"value": "561.20",
"currency": "USD"
},
"tax": {
"value": "55.98",
"currency": "USD"
}
}
}
}
Has anyone faced this issue?
As per the google document (that you've shared), there are around 40 "Required" fields for the request body. In the current shared request body, you've less than half of the required fields.
Required fields:
invoiceId
operationId
shipmentGroupId
lineItemInvoices[]
lineItemInvoices[].shipmentUnitIds[]
lineItemInvoices[].unitInvoice
lineItemInvoices[].unitInvoice.unitPricePretax
lineItemInvoices[].unitInvoice.unitPriceTaxes[].taxType
lineItemInvoices[].unitInvoice.unitPriceTaxes[].taxAmount
lineItemInvoices[].unitInvoice.promotions[].promotionId
lineItemInvoices[].unitInvoice.promotions[].promotionAmount
lineItemInvoices[].unitInvoice.promotions[].promotionAmount.pretax
lineItemInvoices[].unitInvoice.promotions[].promotionAmount.tax
lineItemInvoices[].unitInvoice.additionalCharges[].type
lineItemInvoices[].unitInvoice.additionalCharges[].additionalChargeAmount
lineItemInvoices[].unitInvoice.additionalCharges[].additionalChargeAmount.pretax
lineItemInvoices[].unitInvoice.additionalCharges[].additionalChargeAmount.tax
lineItemInvoices[].unitInvoice.additionalCharges[].additionalChargePromotions[].promotionId
lineItemInvoices[].unitInvoice.additionalCharges[].additionalChargePromotions[].promotionAmount
lineItemInvoices[].unitInvoice.additionalCharges[].additionalChargePromotions[].promotionAmount.pretax
lineItemInvoices[].unitInvoice.additionalCharges[].additionalChargePromotions[].promotionAmount.tax
invoiceSummary
invoiceSummary.productTotal
invoiceSummary.productTotal.pretax
invoiceSummary.productTotal.tax
invoiceSummary.additionalChargeSummaries[].type
invoiceSummary.additionalChargeSummaries[].totalAmount
invoiceSummary.additionalChargeSummaries[].totalAmount.pretax
invoiceSummary.additionalChargeSummaries[].totalAmount.tax
invoiceSummary.promotionSummaries[].promotionId
invoiceSummary.promotionSummaries[].promotionAmount
invoiceSummary.promotionSummaries[].promotionAmount.pretax
invoiceSummary.promotionSummaries[].promotionAmount.tax
invoiceSummary.merchantBalance.pretax
invoiceSummary.merchantBalance.tax
invoiceSummary.customerBalance.pretax
invoiceSummary.customerBalance.tax
invoiceSummary.googleBalance.pretax
invoiceSummary.googleBalance.tax

PayPal Checkout - Set up the transaction shipping address and shipping amount

PayPal Checkout
Set up the transaction
allow to set parameters like mount.value: '0.01 and other things like so
<script>
paypal.Buttons({
createOrder: function(data, actions) {
// Set up the transaction
return actions.order.create({
purchase_units: [{
amount: {
value: '0.01'
}
}]
});
}
}).render('#paypal-button-container');
</script>
But I need to set up the shipping address and shipping amount. How can I do it?
PS
I found Orders API Integration Guide for Express Checkout. It has all the options
like details.shipping = 0.00 ...
and shipping_address, but it does not work with PayPal Checkout example. Is it because I'm testing in the sendbox?
Below is the full list of parameters you can set over:
{
"intent": "AUTHORIZE",
"application_context": {
"return_url": "https://example.com",
"cancel_url": "https://example.com",
"brand_name": "EXAMPLE INC",
"locale": "en-US",
"landing_page": "BILLING",
"shipping_preference": "SET_PROVIDED_ADDRESS",
"user_action": "CONTINUE"
},
"purchase_units": [
{
"reference_id": "PUHF",
"description": "Sporting Goods",
"custom_id": "CUST-HighFashions",
"soft_descriptor": "HighFashions",
"amount": {
"currency_code": "USD",
"value": "230.00",
"breakdown": {
"item_total": {
"currency_code": "USD",
"value": "180.00"
},
"shipping": {
"currency_code": "USD",
"value": "30.00"
},
"handling": {
"currency_code": "USD",
"value": "10.00"
},
"tax_total": {
"currency_code": "USD",
"value": "20.00"
},
"shipping_discount": {
"currency_code": "USD",
"value": "10"
}
}
},
"items": [
{
"name": "T-Shirt",
"description": "Green XL",
"sku": "sku01",
"unit_amount": {
"currency_code": "USD",
"value": "90.00"
},
"tax": {
"currency_code": "USD",
"value": "10.00"
},
"quantity": "1",
"category": "PHYSICAL_GOODS"
},
{
"name": "Shoes",
"description": "Running, Size 10.5",
"sku": "sku02",
"unit_amount": {
"currency_code": "USD",
"value": "45.00"
},
"tax": {
"currency_code": "USD",
"value": "5.00"
},
"quantity": "2",
"category": "PHYSICAL_GOODS"
}
],
"shipping": {
"method": "United States Postal Service",
"address": {
"name": {
"give_name":"John",
"surname":"Doe"
},
"address_line_1": "123 Townsend St",
"address_line_2": "Floor 6",
"admin_area_2": "San Francisco",
"admin_area_1": "CA",
"postal_code": "94107",
"country_code": "US"
}
}
}
]
}
basically, the whole idea of placing these details into <script> was a mistake. It should all go from server to server and html should only reflect the reference code.
for PHP users, look into
use PayPalCheckoutSdk\Core\PayPalHttpClient;
use PayPalCheckoutSdk\Core\PayPalEnvironment;
use PayPalCheckoutSdk\Orders\OrdersCreateRequest;

Paypal's transaction object with failing transactions

We are using Paypal Pro to do direct credit card processing. What happens when I put 2 transactions in a request, and the credit card approves one transaction object, but declines the other because of lack of funds. Does PayPal throw away the entire transaction and returns an error?
Take the following code straight from paypals rest api for node.js
var payment_details = {
"intent": "sale",
"payer": {
"payment_method": "credit_card",
"funding_instruments": [{
"credit_card": {
"type": "visa",
"number": "4417119669820331",
"expire_month": "11",
"expire_year": "2018",
"cvv2": "874",
"first_name": "Joe",
"last_name": "Shopper",
"billing_address": {
"line1": "52 N Main ST",
"city": "Johnstown",
"state": "OH",
"postal_code": "43210",
"country_code": "US" }}}]},
"transactions": [{
"amount": {
"total": "7.47",
"currency": "USD",
"details": {
"subtotal": "7.41",
"tax": "0.03",
"shipping": "0.03"}},
"description": "This is the payment transaction description." }]};
paypal_sdk.payment.create(payment_details, function(error, payment){
if(error){
console.error(error);
} else {
console.log(payment);
}
});
What happens when we put 2 transaction objects in there, will we have to handle the case of the credit card declining on the second transaction?
This is what we ended up using. We used the items feild to tell paypal about the multiple items in the transaction. Items is an array of items:
items.push({
quantity: "1",
name: classList[i].name,
price: price.toFixed(2),
currency: "USD"
});
var create_payment_json = {
"intent": "sale",
"payer": {
"payment_method": "paypal"
},
"redirect_urls": {
"return_url": "http://"+config.host+"/payment/success/"+paymentId,
"cancel_url": "http://"+config.host+"/payment/cancel/"+paymentId
},
"transactions": [{
"item_list": {
"items": items
},
"amount": {
"currency": "USD",
"total": (total.toFixed(2))
},
"description": description
}]
};