In a previous post I discussed the method I used to integrate Paypal's Encrypted Web Payments in generic SSL terms I hoped would make it easy to implement from scratch in any language. I've had a request from Ross Poulton to share the Python code that makes it work using the M2Crypto wrapper. So, here it is:
from M2Crypto import BIO, SMIME, X509
from django.conf import settings
class PaypalOrder(dict):
"""Acts as a dictionary which can be encrypted to Paypal's EWP service"""
def __init__(self):
dict.__init__(self)
self['cert_id']=settings.MY_CERT_ID
def setNotifyURL(self, notify_url):
self['notify_url']=notify_url
# snip more wrapper functions
def plaintext(self):
"""The plaintext for the cryptography operation."""
s=''
for k in self:
s+=u'%s=%s\n'%(k,self[k])
return s.encode('utf-8')
__str__=plaintext
def encrypt(self):
"""Return the contents of this order, encrypted to Paypal's
certificate and signed using the private key
configured in the Django settings."""
# Instantiate an SMIME object.
s = SMIME.SMIME()
# Load signer's key and cert. Sign the buffer.
s.load_key_bio(BIO.openfile(settings.MY_KEYPAIR), BIO.openfile(settings.MY_CERT))
p7 = s.sign(BIO.MemoryBuffer(self.plaintext()), flags=SMIME.PKCS7_BINARY)
# Load target cert to encrypt the signed message to.
x509 = X509.load_cert_bio(BIO.openfile(settings.PAYPAL_CERT))
sk = X509.X509_Stack()
sk.push(x509)
s.set_x509_stack(sk)
# Set cipher: 3-key triple-DES in CBC mode.
s.set_cipher(SMIME.Cipher('des_ede3_cbc'))
# Create a temporary buffer.
tmp = BIO.MemoryBuffer()
# Write the signed message into the temporary buffer.
p7.write_der(tmp)
# Encrypt the temporary buffer.
p7 = s.encrypt(tmp, flags=SMIME.PKCS7_BINARY)
# Output p7 in mail-friendly format.
out = BIO.MemoryBuffer()
p7.write(out)
return out.read()
The settings required are as follows:
MY_KEYPAIR='keys/keypair.pem' #path to keypair in PEM format
MY_CERT='keys/merchant.crt' #path to merchant certificate
MY_CERT_ID='ASDF12345' # code which Paypal assign to the certificate when you upload it
PAYPAL_CERT='keys/paypal.crt' #path to Paypal's own certificate