17

I'm designing a Order Site using PHP & Mysql. In the final stage the user is given Paypal buttons to pay for the Orders he has made. So, the Item Name, Value are variables. These values being variables, I cannot use an encrypted button from Paypal. I'll have to use either a non-encrypted button or encrypt it before showing it to the user.

I wish to encrypt it for security reasons. I would like to know how to do it on my server.

Sandeep Chandy
  • 245
  • 1
  • 4
  • 7

6 Answers6

33

What you need to do is fairly complex, first, the intro, paypal encrypted buttons have the following layout:

    <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_s-xclick">
<input type="hidden" name="encrypted" value="-----BEGIN PKCS7-----MIIIEQYJKo...Encrypted stuff...IF5ioje8JH0LAA+5U7P+tabAMOL37k=-----END PKCS7-----">
<input type="image" src="https://www.paypalobjects.com/es_XC/MX/i/btn/btn_buynowCC_LG.gif" border="0" name="submit" alt="PayPal, la forma más segura y rápida de pagar en línea.">
<img alt="" border="0" src="https://www.paypalobjects.com/es_XC/i/scr/pixel.gif" width="1" height="1">
    </form>

The cmd field indicates an encrypted Buy Now button (check the values for the buttons you want to create), and the encrypted field is the actual content of the button in the following layout:

    cert_id=ZQCMJTZS27U4F
    cmd=_xclick
    business=contact@mybiz.com
    item_name=Handheld Computer
    item_number=1234
    custom=sc-id-789
    amount=500.00
    currency_code=USD
    tax=41.25
    shipping=20.00
    no_note=1
    cancel_return=http://www.company.com/cancel.htm 

Note, these are in the pair=value format, for a full reference look here: https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_html_Appx_websitestandard_htmlvariables.

Now the theory, to get the encrypted field, well encrypted, you need to sign these values with your certificate (x509 certificate) and you private key, then you need to encrypt this signed message with paypal's public certificate.

Going to the practice, for doing it you can (need) to use the following two PHP functions (part of the OpenSSL extension): openssl_pkcs7_sign and openssl_pkcs7_encrypt.

I found this last part very tricky to setup, so i recommend you to download the PHP SDK for PayPal avalaible here: https://www.x.com/community/ppx/sdks#WPST and directly here: https://cms.paypal.com/cms_content/US/en_US/files/developer/PP_PHP_WPS_Toolkit.zip, this SDK comes with the class EWPServices who contains the method encryptButton which gives you the encrypted button pretty easy; if you want to look at the bones then look in the PPCrypto class who offers you the signAndEncrypt method which give you only the encrypted string you need for the field and does show you the process of encrypting the button.

By the way, if you don't know how to get your certificate and your private key (and/or the Paypal's certificate) look here: https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_html_encryptedwebpayments#id08A3I0N30Y4

Rafael
  • 2,827
  • 1
  • 16
  • 17
  • 2
    By the way, if you don't know how to get your certificate and your private key (and/or the Paypal's certificate) look here: https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_html_encryptedwebpayments#id08A3I0N30Y4 – Rafael Jul 31 '11 at 01:30
  • This tutorial is also helpful: http://www.stellarwebsolutions.com/en/articles/paypal_button_encryption_php.php – Curtis Blackwell Jun 28 '13 at 08:21
  • 6
    Best solution. Should be marked as answer. Actually tells how to dynamically encrypt paypal buttons. – Stephen Smith Aug 28 '13 at 19:19
  • I' m using openssl to generate the encrypted parameter. The command I pass to the exe is: openssl smime -sign -signer public_cert.pem -inkey cert_key.pem -in invoice.txt -outform der -nodetach -binary | openssl smime -encrypt -des3 -binary -outform pem -out encrypted-contents.txt paypal_cert_pem.txt but when I submit the form I get: Some required information is missing or incomplete. Please correct your entries and try again. Any idea what I'm doing wrong – bob_saginowski Oct 27 '14 at 09:18
  • @mitko.berbatov, I never was able to make openssl to do the job correctly, so i strongly suggest you to use the built in functions in the SDK as they generate the correct data, if there is a good reason and you really want to do this by hand, i recommend you to see the last paragraph of my answer. – Rafael Oct 27 '14 at 17:49
  • @Rafael the problem is that I'm not using PHP – bob_saginowski Oct 29 '14 at 14:00
  • @mitko.berbatov, then I think you should make your own question about this, stating the technologies you use, also, the SDK comes in several languages, so you may find a suitable one that you can study to reverse engineer it. – Rafael Oct 30 '14 at 00:47
  • Any idea how PayPal knows who you are? The field is encrypted and it contains the info about your button, certificate and business. PayPal can't get at it unless it decrypts it first and can't do that without know who you are. – Guy Lowe Sep 03 '19 at 01:15
  • 1
    @GuyLowe Data is encrypted with PayPal's public certificate, which they're able to decrypt just fine because they hold the corresponding private key. – Rafael Sep 10 '19 at 16:32
  • Thanks @Rafael. The internal data however is encrypted with your public key. PayPal do have this because you upload it but how to they know which business it is from to use the correct key? – Guy Lowe Sep 11 '19 at 00:56
  • 1
    @GuyLowe data is signed with your private key, then encrypted, when PayPal decrypt it they get the data of the button in plain text along with a signature from your private key, to ensure the data was not tampered with, they use the public certificate you uploaded it to verify the signature, and they can know it's you because of the business field and use the correct certificate because of the cert_id field. – Rafael Sep 11 '19 at 17:04
  • 1
    @GuyLowe, if you're interested in the details, i recommend you to read about public key cryptography. – Rafael Sep 11 '19 at 17:05
  • Thanks @Rafael, I'll do that. There is certainly something I'm missing in my understanding of all this. – Guy Lowe Sep 13 '19 at 07:18
4

From your post you seem very confused about what encryption means and what to apply it to. What is the threat model? (i.e. how can it be subverted).

There is no way you should expect that paypal will always process the order you sent to the client's browser. You MUST check what Paypal did process.

You can be better assured of the integrity of the order after it leaves your site, e.g. by adding a hash of the order to the order number (and a salt!) you send to Paypal. This should allow you to verify the order without reference to the PLU/stored order (as long as the script processing the return from paypal knows the salt).

symcbean
  • 47,736
  • 6
  • 59
  • 94
  • Brilliant. I did not think of this when I posted this question that got closed on me (http://stackoverflow.com/q/14489512/105539). So simply use the 'custom' variable and, among other things one might need to put in there, add like md5($sSalt . $sProduct . $sPrice) and ensure they line up in the IPN process. – Volomike Jan 24 '13 at 12:57
  • 2
    This isn't the solution the asker is looking for. He is probably already doing this. The reason for an encrypted button would be to greatly reduce the threat in the first place by making it very difficult to send tampered payments in the first place. – Stephen Smith Aug 28 '13 at 19:21
1

maybe you could try putting those variables in a temporary table with a unique id. then use that id for the buttons. querying the variables from the table whenever the customer clicks the paypal buttons. I just hope i understood your statement right xD

kapitanluffy
  • 1,269
  • 7
  • 26
  • 54
1

The only way you can do this is by dynamically querying PayPal to encrypt the button each time.

However this method is not efficient, I think it would be much better to use PayPal IPN. There are many examples and classes online on how to do this.

Brad Larson
  • 170,088
  • 45
  • 397
  • 571
Chris Smith
  • 764
  • 1
  • 9
  • 22
  • I think IPN might be the way to solve this. Either that or the custom button. I'll look into it further... – Phillip Senn Aug 01 '11 at 18:08
  • 2
    Note: IPN checks after payments, so you will still have cases where you get sent a tampered payment. Although they don't get the product, it seems a little messy because you will have tampered payments getting sent to you every once in a while. – Stephen Smith Aug 28 '13 at 19:17
1

I developed a PHP integration toolkit with PayPal Website Payments Standard.

All the issues you mentioned here are handled inside by helper classes. Some basic configuration are provided for easy setup. For example, all encryption variables (your private key, public certificate, ...) and subject to configuration. The article explains in details how to use the classes.

PS: Only IPN confirmation is implemented by the helper classes.

user337620
  • 2,239
  • 3
  • 19
  • 19
0

Couldn't anyone with your paypal email adress send you a bogus invoice, asking for product names at the wrong prices? If they are going to go through the trouble of changing your js/html code to send you a bogus invoice... they could just write their own (just a form submit to 'paypal.com/cgi-bin/webscr'). All you really need is the seller's paypal email right?

So why all the trouble of encrypting buttons?

rikkitikkitumbo
  • 954
  • 3
  • 17
  • 38
  • 1
    Anyone can press the `F12` key at the payment page in their browser, then edit the HTML as required. Lowering the amount is an obvious one, and unless you check for a match before shipping (recommended by PayPal), they have got it cheaper. Even if you caught the discrepancy, you are stuck with having to dispute with the client and probably refund the money. With encrypted buttons, all the essential info is prevented from tampering, and in your PayPal preferences, you can only allow encrypted buttons, preventing your scenarios. – Patanjali Jan 27 '18 at 00:24