[FIX] [IMP] paypal

- fixed controller: when using urlopen and read, the response is already a text (bug coming
from the removal of requests lib)
- cleaned and fixed paypal data validation, now working
- remove paypal_username field, not used; added paypal_seller_id that is the unique ID of the
seller, to check that paypal data is correct
- various code cleaning

bzr revid: tde@openerp.com-20131204160738-q9paazleyg5v5hjo
This commit is contained in:
Thibault Delavallée
2013-12-04 17:07:38 +01:00
parent 5e181a1694
commit e0d1233f48
4 changed files with 46 additions and 57 deletions
@@ -21,6 +21,14 @@ class PaypalController(http.Controller):
_return_url = '/payment/paypal/dpn/'
_cancel_url = '/payment/paypal/cancel/'
def _get_return_url(self, **post):
""" Extract the return URL from the data coming from paypal. """
return_url = post.pop('return_url', '')
if not return_url:
custom = json.loads(post.pop('custom', '{}'))
return_url = custom.get('return_url', '/')
return return_url
def paypal_validate_data(self, **post):
""" Paypal IPN: three steps validation to ensure data correctness
@@ -36,11 +44,11 @@ class PaypalController(http.Controller):
urequest = urllib2.Request("https://www.sandbox.paypal.com/cgi-bin/webscr", urllib.urlencode(new_post))
uopen = urllib2.urlopen(urequest)
resp = uopen.read()
if resp.text == 'VERIFIED':
if resp == 'VERIFIED':
_logger.info('Paypal: validated data')
cr, uid, context = request.cr, request.uid, request.context
res = request.registry['payment.transaction'].form_feedback(cr, uid, post, 'paypal', context=context)
elif resp.text == 'INVALID':
elif resp == 'INVALID':
_logger.warning('Paypal: answered INVALID on data verification')
else:
_logger.warning('Paypal: unrecognized paypal answer, received %s instead of VERIFIED or INVALID' % resp.text)
@@ -48,7 +56,7 @@ class PaypalController(http.Controller):
@website.route([
'/payment/paypal/ipn/',
], type='http', auth='public')
], type='http', auth='public', methods=['POST'])
def paypal_ipn(self, **post):
""" Paypal IPN. """
_logger.info('Beginning Paypal IPN form_feedback with post data %s', pprint.pformat(post)) # debug
@@ -57,14 +65,11 @@ class PaypalController(http.Controller):
@website.route([
'/payment/paypal/dpn',
], type='http', auth="public")
], type='http', auth="public", methods=['POST'])
def paypal_dpn(self, **post):
""" Paypal DPN """
_logger.info('Beginning Paypal DPN form_feedback with post data %s', pprint.pformat(post)) # debug
return_url = post.pop('return_url', '')
if not return_url:
custom = json.loads(post.pop('custom', '{}'))
return_url = custom.pop('return_url', '/')
return_url = self._get_return_url(**post)
self.paypal_validate_data(**post)
return request.redirect(return_url)
@@ -72,11 +77,8 @@ class PaypalController(http.Controller):
'/payment/paypal/cancel',
], type='http', auth="public")
def paypal_cancel(self, **post):
""" TODO
"""
""" When the user cancels its Paypal payment: GET on this route """
cr, uid, context = request.cr, request.uid, request.context
print 'Entering paypal_cancel with post', post
return_url = post.pop('return_url', '/')
print 'return_url', return_url
_logger.info('Beginning Paypal cancel with post data %s', pprint.pformat(post)) # debug
return_url = self._get_return_url(**post)
return request.redirect(return_url)
@@ -10,7 +10,7 @@
<p>You will be redirected to the Paypal website after cliking on the payment button.</p>]]></field>
<field name="paypal_tx_url">https://www.sandbox.paypal.com/cgi-bin/webscr</field>
<field name="paypal_email_id">dummy</field>
<field name="paypal_username">dummy</field>
<field name="paypal_seller_id">dummy</field>
<field name="paypal_api_username">dummy</field>
<field name="paypal_api_password">dummy</field>
</record>
+28 -41
View File
@@ -36,7 +36,7 @@ class AcquirerPaypal(osv.Model):
_columns = {
'paypal_email_id': fields.char('Email ID', required_if_provider='paypal'),
'paypal_username': fields.char('Username', required_if_provider='paypal'),
'paypal_seller_id': fields.char('Seller ID', required_if_provider='paypal'),
'paypal_use_ipn': fields.boolean('Use IPN'),
# Server 2 server
'paypal_api_enabled': fields.boolean('Use Rest API'),
@@ -168,9 +168,8 @@ class TxPaypal(osv.Model):
return self.browse(cr, uid, tx_ids[0], context=context)
def _paypal_form_get_invalid_parameters(self, cr, uid, tx, data, context=None):
# TODO: txn_id: shoudl be false at draft, set afterwards, and verified with txn details
invalid_parameters = []
if data.get('notify_version')[0] != '2.6':
if data.get('notify_version')[0] != '3.4':
_logger.warning(
'Received a notification from Paypal with version %s instead of 2.6. This could lead to issues when managing it.' %
data.get('notify_version')
@@ -179,60 +178,48 @@ class TxPaypal(osv.Model):
_logger.warning(
'Received a notification from Paypal using sandbox'
),
# TODO: txn_id: shoudl be false at draft, set afterwards, and verified with txn details
if tx.acquirer_reference and data.get('txn_id') != tx.acquirer_reference:
invalid_parameters.append(('txn_id', data.get('txn_id'), tx.acquirer_reference))
# check what is buyed
if float_compare(float(data.get('mc_gross', '0.0')), tx.amount, 2) != 0:
invalid_parameters.append(('mc_gross', data.get('mc_gross'), '%.2f' % tx.amount))
if float_compare(float(data.get('mc_gross', '0.0')), (tx.amount + tx.fees), 2) != 0:
invalid_parameters.append(('mc_gross', data.get('mc_gross'), '%.2f' % tx.amount)) # mc_gross is amount + fees
if data.get('mc_currency') != tx.currency_id.name:
invalid_parameters.append(('mc_currency', data.get('mc_currency'), tx.currency_id.name))
# if parameters.get('payment_fee') != tx.payment_fee:
# invalid_parameters.append(('payment_fee', tx.payment_fee))
# if parameters.get('quantity') != tx.quantity:
# invalid_parameters.append(('mc_currency', tx.quantity))
# if parameters.get('shipping') != tx.shipping:
# invalid_parameters.append(('shipping', tx.shipping))
invalid_parameters.append(('mc_currency', data.get('mc_currency'), tx.currency_id.name))
if 'handling_amount' in data and float_compare(float(data.get('handling_amount')), tx.fees, 2) != 0:
invalid_parameters.append(('handling_amount', data.get('handling_amount'), tx.fees))
# check buyer
# if parameters.get('payer_id') != tx.payer_id:
# invalid_parameters.append(('mc_gross', tx.payer_id))
# if parameters.get('payer_email') != tx.payer_email:
# invalid_parameters.append(('payer_email', tx.payer_email))
if tx.partner_reference and data.get('payer_id') != tx.partner_reference:
invalid_parameters.append(('payer_id', data.get('payer_id'), tx.partner_reference))
# check seller
# if parameters.get('receiver_email') != tx.receiver_email:
# invalid_parameters.append(('receiver_email', tx.receiver_email))
# if parameters.get('receiver_id') != tx.receiver_id:
# invalid_parameters.append(('receiver_id', tx.receiver_id))
if data.get('receiver_email') != tx.acquirer_id.paypal_email_id:
invalid_parameters.append(('receiver_email', data.get('receiver_email'), tx.acquirer_id.paypal_email_id))
if data.get('receiver_id') != tx.acquirer_id.paypal_seller_id:
invalid_parameters.append(('receiver_id', data.get('receiver_id'), tx.acquirer_id.paypal_seller_id))
return invalid_parameters
def _paypal_form_validate(self, cr, uid, tx, data, context=None):
status = data.get('payment_status')
data = {
'acquirer_reference': data.get('txn_id'),
'paypal_txn_type': data.get('payment_type'),
'partner_reference': data.get('payer_id')
}
if status in ['Completed', 'Processed']:
_logger.info('Validated Paypal payment for tx %s: set as done' % (tx.reference))
tx.write({
'state': 'done',
'date_validate': data.get('payment_date', fields.datetime.now()),
'paypal_txn_id': data['txn_id'],
'paypal_txn_type': data.get('express_checkout'),
})
return True
data.update(state='done', date_validate=data.get('payment_date', fields.datetime.now()))
return tx.write(data)
elif status in ['Pending', 'Expired']:
_logger.info('Received notification for Paypal payment %s: set as pending' % (tx.reference))
tx.write({
'state': 'pending',
'state_message': data.get('pending_reason', ''),
'paypal_txn_id': data['txn_id'],
'paypal_txn_type': data.get('express_checkout'),
})
return True
data.udpate(state='pending', state_message=data.get('pending_reason', ''))
return tx.write(data)
else:
error = 'Received unrecognized status for Paypal payment %s: %s, set as error' % (tx.reference, status)
_logger.info(error)
tx.write({
'state': 'error',
'state_message': error,
'paypal_txn_id': data['txn_id'],
'paypal_txn_type': data.get('express_checkout'),
})
return False
data.update(state='error', state_message=error)
return tx.write(data)
# --------------------------------------------------
# SERVER2SERVER RELATED METHODS
@@ -12,7 +12,7 @@
<group>
<group>
<field name="paypal_email_id"/>
<field name="paypal_username"/>
<field name="paypal_seller_id"/>
<field name="paypal_use_ipn"/>
<field name="paypal_api_enabled"/>
<field name="paypal_api_username"