5
votes

I tried to integrate PayPal Express Checkout to my webapp (server-side REST) and I managed to: get create-payment working

However, when I tried to login with a sandbox test buyer account, it failed to process the payment.

There's a 400 Bad request error for the POST request:

POST https://www.sandbox.paypal.com/webapps/hermes/api/batch/setbuyer 400 (Bad Request)

with the following response:

{
"ack": "success",
"data": {
    "buyerEligibility": {
        "ack": "success",
        "data": {
            "eligible": true,
            "clearedRT": false
        },
        "meta": {
            "calc": "8f7cc8e266c07",
            "rlog": "PVs6nBwuIQ9X2gSdIEqzR%2BxkmohYC3WlOiW4HauQ%2FY%2Fh%2BkWFfmr2pOeyxVs3sSiqXDydWuJ%2B6QWLAsZZVtRfIA_15d276b99bf"
        },
        "server": "xG7Ol-1A5r4xEqHEubzBtkj6LgLo88Z7UFOPmqsoK957Q11gkENbvzjGa02RjhyhvYG_ff2SZRFgHYp0Nq5rCCIdwQAwbwL-RkZ0piofvsP6-i9NmpkouuuH47EBynDbMencyfNKhT-cIewGtGK2jKUX_q0FaWq9Gx0MaRB6QBwINBmRQB5tAuklfWE8ooIwOO7szgPXVg9pOXWI2ukxup08j93HODToZ4DnSLuqCK6XM2M49-_DDSyS6GviI3gWrBy7BLOsHky"
    },
    "eConsent": {
        "ack": "success",
        "data": {
            "required": false
        },
        "meta": {
            "calc": "8f7cc8e266c07",
            "rlog": "PVs6nBwuIQ9X2gSdIEqzR%2BxkmohYC3WlOiW4HauQ%2FY%2Fh%2BkWFfmr2pOeyxVs3sSiqXDydWuJ%2B6QWLAsZZVtRfIA_15d276b99bf"
        },
        "server": "-bDk6FVAJFycsTL-R5q_CGdrJwDz9XbAF9KqMHpr6QIMACZ6IA5zQ_BVyqi3jy6w9pKC5SS4TBrpDB_OJC0rU1W5wz5XBgo3ze_iOG0gDEwxuzu7WtAT1Nv5_VmLhmUWIdMm7qtgfy1y11v18zXSxhATUDaRI8hNdlnArSlBtKVNGWkhCD4OTp4KvSBXQ3lLHm-wCSrJzhpEmBoNZmDQMrd4wv1YEYA0VFPG1cPHapq9t4xJMLfiZOad10irqxJP"
    },
    "createCheckoutSession": {
        "ack": "contingency",
        "contingency": "PAYER_CANNOT_PAY",
        "errorData": {
            "cause": "",
            "step_up_context": {}
        },
        "meta": {
            "calc": "8f7cc8e266c07",
            "rlog": "PVs6nBwuIQ9X2gSdIEqzR%2BxkmohYC3WlOiW4HauQ%2FY%2Fh%2BkWFfmr2pOeyxVs3sSiqXDydWuJ%2B6QWLAsZZVtRfIA_15d276b99bf"
        },
        "server": "-eKOVjOLP5i0k_9Et8_N5HyfLSVBzycsA2AE8UY8RD88MnM3729QBQoHY2eD3sMhSThBqdYmvFoARIAbkHNoOT9jsHzAUCk1CtbA717xHK5gSuYujf5mvuDJQFXWlPEDBk7XFlZSyhUWy8VGKvYWwWhuTSzcjMdKIzRI_XTjfA2hQpzIvkbRQ5jLMDIIKeNm1XrF3mEMN3gkHzZIc2OBiRaVEA2Q0se_uVgEEGIbSgN2aeSOeh4WiMC08zUCvmdCLyCP0ZyE24fzDvL4ZMUurG"
    }
},
"meta": {
    "calc": "8f7cc8e266c07",
    "rlog": "PVs6nBwuIQ9X2gSdIEqzR%2BxkmohYC3WlOiW4HauQ%2FY%2Fh%2BkWFfmr2pOeyxVs3sSiqXDydWuJ%2B6QWLAsZZVtRfIA_15d276b99bf"
},
"server": "JwJRYq2SF3kUujC16-VsiMQu8IDN_RxPNOz8wY8m8YD4P3PzhHZB73hNd_IM9PktfJcPPHx2RyVUk1PV8bC2lLtejwTFKzq-7QDM9nLmxJLw7os2tgLnGYAebFJAkmIt2fFvlncVMrAg9bAsMF9INhPqixaCEWn7ug9OcPCci_3autJi3cvmTLb_8XvTaGBpPxI0ASQnkXTSVJa2GPIptYhGVHFN5N92hFdxzwp2uYQhHeJrePmExV4NlLd0s_wa"

}

My client side implementation for PayPal Express Checkout:

class PayPalButton extends Component {
render() {
    const Btn = paypal.Button.driver('react', {React, ReactDOM});
    const CREATE_PAYMENT_URL = `${ROOT_URL}/paypal/create-payment/${this.props.regId}`;
    const EXECUTE_PAYMENT_URL = `${ROOT_URL}/paypal/execute-payment/${this.props.regId}`;
    const token = localStorage.getItem('deotoken');

    let client = {
        sandbox: 'TO_BE_REPLACED_WITH_SANDBOX_CLIENT_ID'
    };

    let payment = () => {
  return paypal.request({
    method: 'post',
    url: CREATE_PAYMENT_URL,
    headers: {
        authorization: token
    }
  })
  .then(function(data) {
      return data.id;
  });
    };

    let onAuthorize = (data) => {
  return paypal.request({
    method: 'post',
    url: EXECUTE_PAYMENT_URL,
    headers: {
        authorization: token
    },
    json: {
                paymentID: data.paymentID,
      payerID:   data.payerID
    } 
  }).then(function() {
      // The payment is complete!
      // You can now show a confirmation message to the customer
      console.log('done');
  });
    };

return (
    <div>
    <Btn env={'sandbox'}
      client={client}
      payment={payment}
      commit={true}
      onAuthorize={onAuthorize}
    />
    </div>
);
}

My server side implementation):

module.exports = {
createPayment(req, res, next) {
    const { registration_id } = req.params;
    const { user } = req;

    Registration.findById(registration_id)
    .populate({ path: 'category', model: 'category' })
    .populate({ path: 'orders.meal', model: 'meal' })
    .then(reg => {
        if (reg) {
            const categoryItem = [{
                name: reg.category.name,
                sku: reg.category.name,
                price: reg.category.price,
                currency: 'MYR',
                quantity: 1
            }];
            const ordersItems = reg.orders.map(order => {
                return {
                    name: order.meal.name,
                    sku: order.meal.name,
                    price: order.meal.price,
                    currency: 'MYR',
                    quantity: order.quantity
                }
            });

            const create_payment_json = {
                intent: 'sale',
                payer: {
                    payment_method: 'paypal'
                },
                redirect_urls: {
                    return_url: 'http://localhost:8080/',
                    cancel_url: 'http://localhost:8080/'
                },
                transactions: [{
                    item_list: {
                        items: [...categoryItem, ...ordersItems]
                    },
                    amount: {
                        currency: 'MYR',
                        total: reg.totalBill
                    }
                }]
            };

            paypal.payment.create(create_payment_json, function(err, payment) {
                if (err) { 
                    next(err); 
                } else {
                    res.send(payment);
                }

            })
        } else {
            return res.status(422).send({error: 'Registration not found'});
        }
    })
    .catch(next);

},
executePayment(req, res, next) {
    const { registration_id } = req.params;
    const { paymentID, payerID } = req.body;

    const execute_payment_json = {
        payer_id: payerID
    }

    paypal.payment.execute(paymentID, execute_payment_json, function(err, paypalResponse) {
        if (err) {
            next(err);
        } else {
            if (paypalResponse.state === 'approved') {
                const payment = new Payment({
                    user: req.user._id,
                    registration: registration_id,
                    amount: paypalResponse.transactions[0].amount.total,
                    currency: paypalResponse.transactions[0].amount.currency,
                    paypalPaymentId: paypalResponse.id
                });

                payment.save()
                    .then(p => res.send(p))
                    .catch(next);
            } else {
                res.status(422).send({ error: 'Payment not approved' });
            }
        }
    });
}

};

What is the issue? How can I make this work?

1
I get the same error. have you found any solution for this? Please share.Priyal

1 Answers

2
votes

I have faced same issue. I have set INR as my currency in my paypal sandbox, but sending amount as USD from API call. So, I think we have to make transaction in currency that we set in sandbox.

Previous Payload:

transactions: [{
                item_list: {
                    items: [...categoryItem, ...ordersItems]
                },
                amount: {
                    currency: 'USD',
                    total: reg.totalBill
                }
            }]

After Change Payload:

transactions: [{
                item_list: {
                    items: [...categoryItem, ...ordersItems]
                },
                amount: {
                    currency: 'INR',
                    total: reg.totalBill
                }
            }]

After changing currency, my code works fine !!