skip to Main Content

I’m using the PayPal API to put payment options to my website. In the tutorial they have, they are rendering the button and setting up the transaction entirely at the client side with JavaScript. Here is the sample code:

<script>
  paypal.Buttons({
    createOrder: function(data, actions) {
      // This function sets up the details of the transaction, including the amount and line item details.
      return actions.order.create({
        purchase_units: [{
          amount: {
            value: '0.01'
          }
        }]
      });
    },
    onApprove: function(data, actions) {
      // This function captures the funds from the transaction.
      return actions.order.capture().then(function(details) {
        // This function shows a transaction success message to your buyer.
        alert('Transaction completed by ' + details.payer.name.given_name);
      });
    }
  }).render('#paypal-button-container');
  //This function displays Smart Payment Buttons on your web page.
</script>

Is this secure?

The user can just change the payment amount in the code on his side and pay less. Even if I set up client-side code to send transaction-id once the transaction is successful (ie. make a POST request at onApprove), so that I can have a server-side code check if the amount sent is correct, the client can still change the code on his side to send a fake transaction-id.

I basically need a mechanism to check if I definitely received the right amount, before delivering the product. I obviously need to make this check at the server-side but I can’t figure out a secure way to do it because I need to get some info from the client-side which might be fake. How do I prevent the user from pretending to have paid for example by sending a past transaction-id?

2

Answers


  1. You are correct that the user can always change the amount in client-side code, and send a payment for a lower amount. That’s how client side payments work.

    Any logic to keep track of which payments are real and for the correct amount must be on your server.

    For PayPal Checkout, here’s the front-end UI you should use: https://developer.paypal.com/demo/checkout/#/pattern/server

    You’ll need two corresponding routes on your server, one for ‘Create Order’ and one for ‘Capture Order’. You can use one of the Checkout-lanuagename-SDK‘s (edit:though these have been deprecated now) for the routes’ API calls to PayPal, or your own HTTPS implementation of first getting an access token and then doing the call (there is a full-stack example in node.js at the main PayPal Checkout guide, but it can be done with any backend server language).

    Both of the two routes should return only JSON data (no HTML or text). Inside the 2nd route, when the capture API is successful you should verify the amount was correct and store its resulting payment details in your database (particularly purchase_units[0].payments.captures[0].id, which is the PayPal transaction ID) and perform any necessary business logic (such as sending confirmation emails or reserving product) immediately before forwarding your return JSON to the frontend caller. In the event of an error forward the JSON details of it as well, since the frontend must handle such cases.

    Login or Signup to reply.
  2. I’m sorry but this still all seems to be very insecure to me. Once you have given your client-ID in the paypal javascript tag, then any good hacker can use devtools in Google or Firefox, etc. and replace your paypal.buttons code with their own paypal.buttons code and happily send the transaction along to paypal without using your client-side code or server code.

    I did some test of this theory and in five minutes or less I was able to redo the code in the client javascript and pay whatever I wanted for the product I was buying (this in a test environment).

    What am I missing here that doesn’t render the client side code totally insecure.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search