[IMP] payment_acquirer_paypal: improvements
- cleaned feedback: same method naming as ogone, cleaned method, now called by the controller. IPN basically works. - cleaned controllers - cleaned test module website_payment a bit about paypal - added support of custom, to give and receive back custom values with paypal bzr revid: tde@openerp.com-20131118123314-jkfomek10ncq7mlu
This commit is contained in:
parent
d4064d82c3
commit
7c372e8f28
|
@ -192,7 +192,7 @@ class PaymentTxOgone(osv.Model):
|
|||
context=context
|
||||
)
|
||||
|
||||
def _ogone_form_get_tx_from_shasign_out(self, cr, uid, data, context=None):
|
||||
def _ogone_form_get_tx_from_data(self, cr, uid, data, context=None):
|
||||
""" Given a data dict coming from ogone, verify it and find the related
|
||||
transaction record. """
|
||||
reference, pay_id, shasign = data.get('orderID'), data.get('PAYID'), data.get('SHASIGN')
|
||||
|
@ -223,7 +223,7 @@ class PaymentTxOgone(osv.Model):
|
|||
return tx
|
||||
|
||||
def ogone_form_feedback(self, cr, uid, data, context=None):
|
||||
tx = self._ogone_form_get_tx_from_shasign_out(cr, uid, data, context)
|
||||
tx = self._ogone_form_get_tx_from_data(cr, uid, data, context)
|
||||
if not tx:
|
||||
raise ValidationError('Ogone: feedback: tx not found')
|
||||
if tx.state == 'done':
|
||||
|
|
|
@ -37,9 +37,8 @@ class PaypalController(http.Controller):
|
|||
_cancel_url = '/payment/paypal/cancel/'
|
||||
|
||||
@website.route([
|
||||
'/payment/paypal/test/ipn/'
|
||||
'/payment/paypal/ipn/',
|
||||
], type='http', auth='admin')
|
||||
], type='http', auth='public')
|
||||
def paypal_ipn(self, **post):
|
||||
print 'Entering paypal_ipn with post', post
|
||||
# step 1: return an empty HTTP 200 response -> will be done at the end by returning ''
|
||||
|
@ -52,21 +51,19 @@ class PaypalController(http.Controller):
|
|||
|
||||
# step 3: paypal send either VERIFIED or INVALID (single word)
|
||||
if resp.text == 'VERIFIED':
|
||||
# _logger.warning('')
|
||||
_logger.info('Paypal: received verified IPN')
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
# payment_transaction = request.registry['payment.transaction']
|
||||
# payment_transaction.validate()
|
||||
payment_transaction = request.registry['payment.transaction']
|
||||
res = payment_transaction.paypal_form_feedback(cr, uid, post, context=context)
|
||||
print '\tValidation result', res
|
||||
elif resp.text == 'INVALID':
|
||||
# _logger.warning('')
|
||||
pass
|
||||
_logger.warning('Paypal: received invalid IPN with post %s' % post)
|
||||
else:
|
||||
# _logger.warning('') -> something went wrong
|
||||
pass
|
||||
_logger.warning('Paypal: received unrecognized IPN with post %s' % post)
|
||||
|
||||
return ''
|
||||
|
||||
@website.route([
|
||||
'/payment/paypal/test/dpn',
|
||||
'/payment/paypal/dpn',
|
||||
], type='http', auth="public")
|
||||
def paypal_dpn(self, **post):
|
||||
|
@ -74,10 +71,9 @@ class PaypalController(http.Controller):
|
|||
"""
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
print 'Entering paypal_dpn with post', post
|
||||
return ''
|
||||
return request.redirect('/')
|
||||
|
||||
@website.route([
|
||||
'/payment/paypal/test/cancel',
|
||||
'/payment/paypal/cancel',
|
||||
], type='http', auth="public")
|
||||
def paypal_cancel(self, **post):
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
from openerp.addons.payment_acquirer.models.payment_acquirer import ValidationError
|
||||
from openerp.addons.payment_acquirer_paypal.controllers.main import PaypalController
|
||||
from openerp.osv import osv, fields
|
||||
from openerp.tools.float_utils import float_compare
|
||||
|
||||
import logging
|
||||
import requests
|
||||
|
@ -75,6 +76,8 @@ class AcquirerPaypal(osv.Model):
|
|||
'notify_url': '%s' % urlparse.urljoin(base_url, PaypalController._notify_url),
|
||||
'cancel_return': '%s' % urlparse.urljoin(base_url, PaypalController._cancel_url),
|
||||
}
|
||||
if tx_custom_values and tx_custom_values.get('return_url'):
|
||||
tx_values['custom'] = 'return_url=%s' % tx_custom_values.pop('return_url')
|
||||
if tx_custom_values:
|
||||
tx_values.update(tx_custom_values)
|
||||
return tx_values
|
||||
|
@ -85,6 +88,7 @@ class TxPaypal(osv.Model):
|
|||
|
||||
_columns = {
|
||||
'paypal_txn_id': fields.char('Transaction ID'),
|
||||
'paypal_txn_type': fields.char('Transaction type'),
|
||||
}
|
||||
|
||||
# --------------------------------------------------
|
||||
|
@ -113,48 +117,46 @@ class TxPaypal(osv.Model):
|
|||
context=context
|
||||
)
|
||||
|
||||
def _paypal_get_tx_from_data(self, cr, uid, data, context=None):
|
||||
reference, txn_id = data.get('item_number'), data.get('txn_id')
|
||||
if not reference or not txn_id:
|
||||
error_msg = 'Paypal: received data with missing reference (%s) or txn_id (%s)' % (reference, txn_id)
|
||||
_logger.error(error_msg)
|
||||
raise ValidationError(error_msg)
|
||||
|
||||
# find tx -> @TDENOTE use txn_id ?
|
||||
tx_ids = self.pool['payment.transaction'].search(cr, uid, [('reference', '=', reference)], context=context)
|
||||
if not tx_ids or len(tx_ids) > 1:
|
||||
error_msg = 'Paypal: received data for reference %s' % (reference)
|
||||
if not tx_ids:
|
||||
error_msg += '; no order found'
|
||||
else:
|
||||
error_msg += '; multiple order found'
|
||||
_logger.error(error_msg)
|
||||
raise ValidationError(error_msg)
|
||||
tx = self.pool['payment.transaction'].browse(cr, uid, tx_ids[0], context=context)
|
||||
|
||||
def validate_paypal_notification(self, cr, uid, url, context=None):
|
||||
parsed_url = urlparse.urlparse(url)
|
||||
query_parameters = parsed_url.query
|
||||
parameters = urlparse.parse_qs(query_parameters)
|
||||
return tx
|
||||
|
||||
def paypal_form_feedback(self, cr, uid, data, context=None):
|
||||
invalid_parameters = []
|
||||
|
||||
# check tx effectively exists
|
||||
txn_id = parameters.get('txn_id')[0]
|
||||
tx_ids = self.search(cr, uid, [('paypal_txn_id', '=', txn_id)], context=context)
|
||||
if not tx_ids:
|
||||
_logger.warning(
|
||||
'Received a notification from Paypal for a tx %s that does not exists in database.' %
|
||||
txn_id
|
||||
)
|
||||
return False
|
||||
elif len(tx_ids) > 1:
|
||||
_logger.warning(
|
||||
'Received a notification from Paypal for a tx %s that is duplicated in database.' %
|
||||
txn_id
|
||||
)
|
||||
# get tx
|
||||
tx = self._paypal_get_tx_from_data(cr, uid, data, context=context)
|
||||
|
||||
tx = self.browse(cr, uid, tx_ids[0], context=context)
|
||||
|
||||
if parameters.get('notify_version')[0] != '2.6':
|
||||
if data.get('notify_version')[0] != '2.6':
|
||||
_logger.warning(
|
||||
'Received a notification from Paypal with version %s instead of 2.6. This could lead to issues when managing it.' %
|
||||
parameters.get('notify_version')
|
||||
data.get('notify_version')
|
||||
)
|
||||
if parameters.get('test_ipn')[0]:
|
||||
if data.get('test_ipn'):
|
||||
_logger.warning(
|
||||
'Received a notification from Paypal using sandbox'
|
||||
),
|
||||
# check transaction
|
||||
if parameters.get('payment_status')[0] != 'Completed':
|
||||
invalid_parameters.append(('payment_status', 'Completed'))
|
||||
# check what is buyed
|
||||
if parameters.get('mc_gross')[0] != tx.amount:
|
||||
if float_compare(float(data.get('mc_gross', '0.0')), tx.amount, 2) != 0:
|
||||
invalid_parameters.append(('mc_gross', tx.amount))
|
||||
if parameters.get('mc_currency')[0] != tx.currency_id.name:
|
||||
if data.get('mc_currency') != tx.currency_id.name:
|
||||
invalid_parameters.append(('mc_currency', tx.currency_id.name))
|
||||
# if parameters.get('payment_fee') != tx.payment_fee:
|
||||
# invalid_parameters.append(('payment_fee', tx.payment_fee))
|
||||
|
@ -173,65 +175,33 @@ class TxPaypal(osv.Model):
|
|||
# if parameters.get('receiver_id') != tx.receiver_id:
|
||||
# invalid_parameters.append(('receiver_id', tx.receiver_id))
|
||||
|
||||
if not invalid_parameters:
|
||||
self.write(cr, uid, [tx.id], {
|
||||
'payment_type': parameters.get('payment_type')[0],
|
||||
'date_validate': parameters.get('payment_date', [fields.datetime.now()])[0],
|
||||
'txn_type': parameters.get('express_checkout')[0],
|
||||
}, context=context)
|
||||
return tx.id
|
||||
else:
|
||||
if invalid_parameters:
|
||||
_warn_message = 'The following transaction parameters are incorrect:\n'
|
||||
for item in invalid_parameters:
|
||||
_warn_message += '\t%s: received %s instead of %s\n' % (item[0], parameters.get(item[0])[0], item[1])
|
||||
_warn_message += '\t%s: received %s instead of %s\n' % (item, data.get(item[0]), item[1])
|
||||
_logger.warning(_warn_message)
|
||||
return False
|
||||
|
||||
return False
|
||||
|
||||
def create_paypal_command(self, cr, uid, cmd, parameters):
|
||||
parameters.update(cmd=cmd)
|
||||
return requests.post(self._paypal_url, data=parameters)
|
||||
|
||||
def _validate_paypal(self, cr, uid, ids, context=None):
|
||||
res = []
|
||||
for tx in self.browse(cr, uid, ids, context=context):
|
||||
parameters = {}
|
||||
parameters.update(
|
||||
cmd='_notify-validate',
|
||||
business='tdelavallee-facilitator@gmail.com',
|
||||
item_name="%s %s" % ('cacapoutch', tx.reference),
|
||||
item_number=tx.reference,
|
||||
amount=tx.amount,
|
||||
currency_code=tx.currency_id.name,
|
||||
)
|
||||
print '\t', parameters
|
||||
# paypal_url = "https://www.paypal.com/cgi-bin/webscr"
|
||||
paypal_url = "https://www.sandbox.paypal.com/cgi-bin/webscr"
|
||||
resp = requests.post(paypal_url, data=parameters)
|
||||
print resp
|
||||
print resp.url
|
||||
print resp.text
|
||||
response = urlparse.parse_qsl(resp)
|
||||
print response
|
||||
# transaction's unique id
|
||||
# response["txn_id"]
|
||||
|
||||
# "Failed", "Reversed", "Refunded", "Canceled_Reversal", "Denied"
|
||||
status = "refused"
|
||||
retry_time = False
|
||||
|
||||
if response["payment_status"] == "Voided":
|
||||
status = "refused"
|
||||
elif response["payment_status"] in ("Completed", "Processed") and response["item_number"] == tx.reference and response["mc_gross"] == tx.amount:
|
||||
status = "validated"
|
||||
elif response["payment_status"] in ("Expired", "Pending"):
|
||||
status = "pending"
|
||||
retry_time = 60
|
||||
|
||||
res.append(
|
||||
(status, retry_time, "payment_status=%s&pending_reason=%s&reason_code=%s" % (
|
||||
response["payment_status"],
|
||||
response.get("pending_reason"),
|
||||
response.get("reason_code")))
|
||||
)
|
||||
return response
|
||||
status = data.get('payment_status', 'Pending')
|
||||
if status in ['Completed', 'Processed']:
|
||||
tx.write({
|
||||
'state': 'done',
|
||||
'txn_id': data['txn_id'],
|
||||
'date_validate': data.get('payment_date', fields.datetime.now()),
|
||||
'paypal_txn_type': data.get('express_checkout')
|
||||
})
|
||||
return True
|
||||
elif status in ['Pending', 'Expired']:
|
||||
tx.write({
|
||||
'state': 'pending',
|
||||
'txn_id': data['txn_id'],
|
||||
})
|
||||
return True
|
||||
else:
|
||||
error = 'Paypal: feedback error'
|
||||
_logger.info(error)
|
||||
tx.write({
|
||||
'state': 'error',
|
||||
'state_message': error
|
||||
})
|
||||
return False
|
||||
|
|
|
@ -73,7 +73,7 @@ class BasicPayment(PaymentAcquirerCommon):
|
|||
partner_id=None,
|
||||
partner_values=self.buyer_values,
|
||||
context=context)
|
||||
print res
|
||||
# print res
|
||||
|
||||
# # check some basic paypal methods
|
||||
# res = self.payment_transaction.validate_paypal_notification(
|
||||
|
@ -110,3 +110,46 @@ class BasicPayment(PaymentAcquirerCommon):
|
|||
# print resp.text
|
||||
|
||||
# self.payment_transaction.validate(cr, uid, [tx_id], context=context)
|
||||
|
||||
# {
|
||||
# 'protection_eligibility': u'Ineligible',
|
||||
# 'last_name': u'Poilu',
|
||||
# 'txn_id': u'08D73520KX778924N',
|
||||
# 'receiver_email': u'tde+paypal-facilitator@openerp.com',
|
||||
# 'payment_status': u'Pending',
|
||||
# 'payment_gross': u'',
|
||||
# 'tax': u'0.00',
|
||||
# 'residence_country': u'FR',
|
||||
# 'address_state': u'Alsace',
|
||||
# 'payer_status': u'verified',
|
||||
# 'txn_type': u'web_accept',
|
||||
# 'address_street': u'Av. de la Pelouse, 87648672 Mayet',
|
||||
# 'handling_amount': u'0.00',
|
||||
# 'payment_date': u'03:21:19 Nov 18, 2013 PST',
|
||||
# 'first_name': u'Norbert',
|
||||
# 'item_name': u'test_ref_0',
|
||||
# 'address_country': u'France',
|
||||
# 'charset': u'windows-1252',
|
||||
# 'custom': u'',
|
||||
# 'notify_version': u'3.7',
|
||||
# 'address_name': u'Norbert Poilu',
|
||||
# 'pending_reason': u'multi_currency',
|
||||
# 'item_number': u'test_ref_0',
|
||||
# 'receiver_id': u'DEG7Z7MYGT6QA',
|
||||
# 'transaction_subject': u'',
|
||||
# 'business': u'tde+paypal-facilitator@openerp.com',
|
||||
# 'test_ipn': u'1',
|
||||
# 'payer_id': u'VTDKRZQSAHYPS',
|
||||
# 'verify_sign': u'An5ns1Kso7MWUdW4ErQKJJJ4qi4-AVoiUf-3478q3vrSmqh08IouiYpM',
|
||||
# 'address_zip': u'75002',
|
||||
# 'address_country_code': u'FR',
|
||||
# 'address_city': u'Paris',
|
||||
# 'address_status': u'unconfirmed',
|
||||
# 'mc_currency': u'EUR',
|
||||
# 'shipping': u'0.00',
|
||||
# 'payer_email': u'tde+buyer@openerp.com',
|
||||
# 'payment_type': u'instant',
|
||||
# 'mc_gross': u'1.95',
|
||||
# 'ipn_track_id': u'866df2ccd444b',
|
||||
# 'quantity': u'1'
|
||||
# }
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
<input type="hidden" name="first_name" t-att-value="tx_values['first_name']"/>
|
||||
<input type="hidden" name="last_name" t-att-value="tx_values['last_name']"/>
|
||||
<input type="hidden" name="zip" t-att-value="tx_values['zip']"/>
|
||||
<!-- after payment parameters -->
|
||||
<t t-if='tx_values.get("custom")'>
|
||||
<input type='hidden' name="custom" t-att-value='tx_values["custom"]'/>
|
||||
</t>
|
||||
<!-- URLs -->
|
||||
<input t-if="acquirer.paypal_use_dpn" type='hidden' name='return'
|
||||
t-att-value="tx_values['return']"/>
|
||||
|
|
|
@ -38,11 +38,20 @@ class WebsitePayment(http.Controller):
|
|||
currency_obj = request.registry['res.currency']
|
||||
|
||||
paypal_id = acquirer_obj.search(cr, uid, [('name', '=', 'paypal')], limit=1, context=context)[0]
|
||||
|
||||
currency_id = currency_obj.search(cr, uid, [('name', '=', 'EUR')], limit=1, context=context)[0]
|
||||
currency = currency_obj.browse(cr, uid, currency_id, context=context)
|
||||
|
||||
paypal_form = acquirer_obj.render(cr, uid, paypal_id, 'reference', 0.01, currency, context=context)
|
||||
nbr_tx = payment_obj.search(cr, uid, [], count=True, context=context)
|
||||
tx_id = payment_obj.create(cr, uid, {
|
||||
'reference': 'test_ref_%s' % (nbr_tx),
|
||||
'amount': 1.95,
|
||||
'currency_id': currency_id,
|
||||
'acquirer_id': paypal_id,
|
||||
'partner_name': 'Norbert Buyer',
|
||||
'partner_email': 'norbert.buyer@example.com',
|
||||
'partner_lang': 'fr_FR',
|
||||
}, context=context)
|
||||
|
||||
paypal_form = acquirer_obj.render(cr, uid, paypal_id, None, None, None, tx_id=tx_id, context=context)
|
||||
paypal = acquirer_obj.browse(cr, uid, paypal_id, context=context)
|
||||
|
||||
values = {
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
</t>
|
||||
<div id="wrap">
|
||||
<div class="container mt16 js_website_blog">
|
||||
<div class="row">
|
||||
<!-- <div class="row">
|
||||
<h3>Paypal payment: server 2 server</h3>
|
||||
<form class="form-horizontal col-sm-4 oe_cc" role="form">
|
||||
<div class="form-group col-sm-8">
|
||||
|
@ -60,7 +60,7 @@
|
|||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div> -->
|
||||
<div>
|
||||
<h3>Paypal payment: form based</h3>
|
||||
<t t-raw="acquirer_form"/>
|
||||
|
|
Loading…
Reference in New Issue