[IMP] [WIP] payment_acquirer_paypal: improved server2server communication + tests. Commit WIP for backup.
bzr revid: tde@openerp.com-20131122163256-f4l8b2kcrtzus56s
This commit is contained in:
@@ -295,6 +295,67 @@ class PaymentTransaction(osv.Model):
|
||||
# SERVER2SERVER RELATED METHODS
|
||||
# --------------------------------------------------
|
||||
|
||||
def create_s2s(self, cr, uid, tx_values, cc_values, context=None):
|
||||
tx_id = self.create(cr, uid, tx_values, context=context)
|
||||
def s2s_create(self, cr, uid, values, cc_values, context=None):
|
||||
tx_id, tx_result = self.s2s_send(cr, uid, values, cc_values, context=context)
|
||||
self.s2s_feedback(cr, uid, tx_id, tx_result, context=context)
|
||||
return tx_id
|
||||
|
||||
def s2s_send(self, cr, uid, values, cc_values, context=None):
|
||||
""" Create and send server-to-server transaction.
|
||||
|
||||
:param dict values: transaction values
|
||||
:param dict cc_values: credit card values that are not stored into the
|
||||
payment.transaction object. Acquirers should
|
||||
handle receiving void or incorrect cc values.
|
||||
Should contain :
|
||||
|
||||
- holder_name
|
||||
- number
|
||||
- cvc
|
||||
- expiry_date
|
||||
- brand
|
||||
- expiry_date_yy
|
||||
- expiry_date_mm
|
||||
"""
|
||||
tx_id, result = None, None
|
||||
|
||||
if values.get('acquirer_id'):
|
||||
acquirer = self.pool['payment.acquirer'].browse(cr, uid, values.get('acquirer_id'), context=context)
|
||||
custom_method_name = '_%s_s2s_send' % acquirer.name
|
||||
if hasattr(self, custom_method_name):
|
||||
tx_id, result = getattr(self, custom_method_name)(cr, uid, values, cc_values, context=context)
|
||||
|
||||
if tx_id is None and result is None:
|
||||
tx_id = super(PaymentTransaction, self).create(cr, uid, values, context=context)
|
||||
return (tx_id, result)
|
||||
|
||||
def s2s_feedback(self, cr, uid, tx_id, data, context=None):
|
||||
""" Handle the feedback of a server-to-server transaction. """
|
||||
tx = self.browse(cr, uid, tx_id, context=context)
|
||||
invalid_parameters = None
|
||||
|
||||
invalid_param_method_name = '_%s_s2s_get_invalid_parameters' % tx.acquirer_id.name
|
||||
if hasattr(self, invalid_param_method_name):
|
||||
invalid_parameters = getattr(self, invalid_param_method_name)(cr, uid, tx, data, context=context)
|
||||
|
||||
if invalid_parameters:
|
||||
_error_message = '%s: incorrect tx data:\n' % (tx.acquirer_id.name)
|
||||
for item in invalid_parameters:
|
||||
_error_message += '\t%s: received %s instead of %s\n' % (item[0], item[1], item[2])
|
||||
_logger.error(_error_message)
|
||||
return False
|
||||
|
||||
feedback_method_name = '_%s_s2s_validate' % tx.acquirer_id.name
|
||||
if hasattr(self, feedback_method_name):
|
||||
return getattr(self, feedback_method_name)(cr, uid, tx, data, context=context)
|
||||
|
||||
return True
|
||||
|
||||
def s2s_get_tx_status(self, cr, uid, tx_id, context=None):
|
||||
tx = self.browse(cr, uid, tx_id, context=context)
|
||||
|
||||
invalid_param_method_name = '_%s_s2s_get_tx_status' % tx.acquirer_id.name
|
||||
if hasattr(self, invalid_param_method_name):
|
||||
return getattr(self, invalid_param_method_name)(cr, uid, tx, context=context)
|
||||
|
||||
return True
|
||||
|
||||
@@ -82,7 +82,7 @@ class AcquirerPaypal(osv.Model):
|
||||
for explanation why we use Authorization header instead of urllib2
|
||||
password manager
|
||||
"""
|
||||
res = dict()
|
||||
res = dict.fromkeys(ids, False)
|
||||
parameters = urllib.urlencode({'grant_type': 'client_credentials'})
|
||||
request = urllib2.Request('https://api.sandbox.paypal.com/v1/oauth2/token', parameters)
|
||||
# add other headers (https://developer.paypal.com/webapps/developer/docs/integration/direct/make-your-first-call/)
|
||||
@@ -226,7 +226,7 @@ class TxPaypal(osv.Model):
|
||||
# SERVER2SERVER RELATED METHODS
|
||||
# --------------------------------------------------
|
||||
|
||||
def paypal_s2s_create(self, cr, uid, values, context=None):
|
||||
def _paypal_s2s_send(self, cr, uid, values, cc_values, context=None):
|
||||
tx_id = self.create(cr, uid, values, context=context)
|
||||
tx = self.browse(cr, uid, tx_id, context=context)
|
||||
|
||||
@@ -236,25 +236,96 @@ class TxPaypal(osv.Model):
|
||||
}
|
||||
data = {
|
||||
'intent': 'sale',
|
||||
'redirect_urls': {
|
||||
'transactions': [{
|
||||
'amount': {
|
||||
'total': '%.2f' % tx.amount,
|
||||
'currency': tx.currency_id.name,
|
||||
},
|
||||
'description': tx.reference,
|
||||
}]
|
||||
}
|
||||
if cc_values:
|
||||
data['payer'] = {
|
||||
'payment_method': 'credit_card',
|
||||
'funding_instruments': [{
|
||||
'credit_card': {
|
||||
'number': cc_values['number'],
|
||||
'type': cc_values['brand'],
|
||||
'expire_month': cc_values['expiry_mm'],
|
||||
'expire_year': cc_values['expiry_yy'],
|
||||
'cvv2': cc_values['cvc'],
|
||||
'first_name': tx.partner_name,
|
||||
'last_name': tx.partner_name,
|
||||
'billing_address': {
|
||||
'line1': tx.partner_address,
|
||||
'city': tx.partner_city,
|
||||
'country_code': tx.partner_country_id.code,
|
||||
'postal_code': tx.partner_zip,
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
else:
|
||||
data['redirect_urls'] = {
|
||||
'return_url': 'http://example.com/your_redirect_url/',
|
||||
'cancel_url': 'http://example.com/your_cancel_url/',
|
||||
},
|
||||
'payer': {
|
||||
data['payer'] = {
|
||||
'payment_method': 'paypal',
|
||||
},
|
||||
'transactions': [
|
||||
{
|
||||
'amount': {
|
||||
'total': '7.47',
|
||||
'currency': 'USD',
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
data = json.dumps(data)
|
||||
|
||||
request = urllib2.Request('https://api.sandbox.paypal.com/v1/payments/payment', data, headers)
|
||||
|
||||
result = urllib2.urlopen(request).read()
|
||||
return result
|
||||
result = urllib2.urlopen(request)
|
||||
print 'result', result
|
||||
|
||||
res2 = result.read()
|
||||
print res2
|
||||
return (tx_id, res2)
|
||||
|
||||
def _paypal_s2s_get_invalid_parameters(self, cr, uid, tx, data, context=None):
|
||||
invalid_parameters = []
|
||||
return invalid_parameters
|
||||
|
||||
def _paypal_s2s_validate(self, cr, uid, tx, data, context=None):
|
||||
values = json.loads(data)
|
||||
status = values.get('state')
|
||||
if status in ['approved']:
|
||||
_logger.info('Validated Paypal s2s payment for tx %s: set as done' % (tx.reference))
|
||||
tx.write({
|
||||
'state': 'done',
|
||||
'date_validate': values.get('udpate_time', fields.datetime.now()),
|
||||
'paypal_txn_id': values['id'],
|
||||
})
|
||||
return True
|
||||
elif status in ['pending', 'expired']:
|
||||
_logger.info('Received notification for Paypal s2s payment %s: set as pending' % (tx.reference))
|
||||
tx.write({
|
||||
'state': 'pending',
|
||||
# 'state_message': data.get('pending_reason', ''),
|
||||
'paypal_txn_id': values['id'],
|
||||
})
|
||||
return True
|
||||
else:
|
||||
error = 'Received unrecognized status for Paypal s2s payment %s: %s, set as error' % (tx.reference, status)
|
||||
_logger.info(error)
|
||||
tx.write({
|
||||
'state': 'error',
|
||||
# 'state_message': error,
|
||||
'paypal_txn_id': values['id'],
|
||||
})
|
||||
return False
|
||||
|
||||
def _paypal_s2s_get_tx_status(self, cr, uid, tx, context=None):
|
||||
headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer %s' % tx.acquirer_id._paypal_s2s_get_access_token()[tx.acquirer_id.id],
|
||||
}
|
||||
data = json.dumps({})
|
||||
url = 'https://api.sandbox.paypal.com/v1/payments/payment/%s' % (tx.paypal_txn_id)
|
||||
print url
|
||||
request = urllib2.Request(url, data, headers)
|
||||
result = urllib2.urlopen(request)
|
||||
print result
|
||||
return True
|
||||
|
||||
@@ -7,10 +7,6 @@ from openerp.osv.orm import except_orm
|
||||
from openerp.tools import mute_logger
|
||||
|
||||
from lxml import objectify
|
||||
# import requests
|
||||
# import urlparse
|
||||
import urllib
|
||||
import urllib2
|
||||
import urlparse
|
||||
|
||||
|
||||
@@ -37,6 +33,18 @@ class PaypalCommon(PaymentAcquirerCommon):
|
||||
})
|
||||
# tde+seller@openerp.com - tde+buyer@openerp.com - tde+buyer-it@openerp.com
|
||||
|
||||
# some CC
|
||||
self.amex = (('378282246310005', '123'), ('371449635398431', '123'))
|
||||
self.amex_corporate = (('378734493671000', '123'))
|
||||
self.autralian_bankcard = (('5610591081018250', '123'))
|
||||
self.dinersclub = (('30569309025904', '123'), ('38520000023237', '123'))
|
||||
self.discover = (('6011111111111117', '123'), ('6011000990139424', '123'))
|
||||
self.jcb = (('3530111333300000', '123'), ('3566002020360505', '123'))
|
||||
self.mastercard = (('5555555555554444', '123'), ('5105105105105100', '123'))
|
||||
self.visa = (('4111111111111111', '123'), ('4012888888881881', '123'), ('4222222222222', '123'))
|
||||
self.dankord_pbs = (('76009244561', '123'), ('5019717010103742', '123'))
|
||||
self.switch_polo = (('6331101999990016', '123'))
|
||||
|
||||
|
||||
class PaypalServer2Server(PaypalCommon):
|
||||
|
||||
@@ -44,18 +52,94 @@ class PaypalServer2Server(PaypalCommon):
|
||||
cr, uid, context = self.cr, self.uid, {}
|
||||
|
||||
res = self.payment_acquirer._paypal_s2s_get_access_token(cr, uid, [self.paypal_id], context=context)
|
||||
print res, res.get('access_token')
|
||||
self.assertTrue(res[self.paypal_id] is not False, 'paypal: did not generate access token')
|
||||
|
||||
res = self.payment_transaction.paypal_s2s_create(
|
||||
tx_id = self.payment_transaction.s2s_create(
|
||||
cr, uid, {
|
||||
'amount': 0.01,
|
||||
'acquirer_id': self.paypal_id,
|
||||
'currency_id': self.currency_euro_id,
|
||||
'reference': 'test_reference',
|
||||
'paypal_txn_id': '61E67681CH3238416',
|
||||
'partner_id': self.buyer_id,
|
||||
}, {
|
||||
'number': self.visa[0][0],
|
||||
'cvc': self.visa[0][1],
|
||||
'brand': 'visa',
|
||||
'expiry_mm': 9,
|
||||
'expiry_yy': 2015,
|
||||
}, context=context
|
||||
)
|
||||
print res
|
||||
|
||||
tx = self.payment_transaction.browse(cr, uid, tx_id, context=context)
|
||||
print tx.paypal_txn_id
|
||||
self.payment_transaction.s2s_get_tx_status(cr, uid, tx_id, context=context)
|
||||
# {
|
||||
# "id":"PAY-2LL14628DB722091TKKHXZHQ",
|
||||
# "create_time":"2013-11-22T15:47:42Z",
|
||||
# "update_time":"2013-11-22T15:48:05Z",
|
||||
# "state":"pending",
|
||||
# "intent":"sale",
|
||||
# "payer": {
|
||||
# "payment_method":"credit_card",
|
||||
# "funding_instruments": [{
|
||||
# "credit_card": {
|
||||
# "type":"visa",
|
||||
# "number":"xxxxxxxxxxxx1111",
|
||||
# "expire_month":"9",
|
||||
# "expire_year":"2015",
|
||||
# "first_name":"Norbert Buyer",
|
||||
# "last_name":"Norbert Buyer",
|
||||
# "billing_address": {
|
||||
# "line1":"Huge Street 2/543",
|
||||
# "city":"Sin City",
|
||||
# "postal_code":"1000",
|
||||
# "country_code":"BE"
|
||||
# }
|
||||
# }
|
||||
# }]
|
||||
# },
|
||||
# "transactions": [{
|
||||
# "amount": {
|
||||
# "total":"0.01",
|
||||
# "currency":"EUR",
|
||||
# "details": {
|
||||
# "subtotal":"0.01"
|
||||
# }
|
||||
# },
|
||||
# "related_resources": [{
|
||||
# "sale": {
|
||||
# "id":"4KU52719R3958614J",
|
||||
# "create_time":"2013-11-22T15:47:42Z",
|
||||
# "update_time":"2013-11-22T15:48:05Z",
|
||||
# "state":"pending",
|
||||
# "amount": {
|
||||
# "total":"0.01",
|
||||
# "currency":"EUR"
|
||||
# },
|
||||
# "pending_reason":"multicurrency",
|
||||
# "parent_payment":"PAY-2LL14628DB722091TKKHXZHQ",
|
||||
# "links": [{
|
||||
# "href":"https://api.sandbox.paypal.com/v1/payments/sale/4KU52719R3958614J",
|
||||
# "rel":"self",
|
||||
# "method":"GET"
|
||||
# },{
|
||||
# "href":"https://api.sandbox.paypal.com/v1/payments/sale/4KU52719R3958614J/refund",
|
||||
# "rel":"refund",
|
||||
# "method":"POST"
|
||||
# },{
|
||||
# "href":"https://api.sandbox.paypal.com/v1/payments/payment/PAY-2LL14628DB722091TKKHXZHQ",
|
||||
# "rel":"parent_payment",
|
||||
# "method":"GET"
|
||||
# }]
|
||||
# }
|
||||
# }]
|
||||
# }],
|
||||
# "links": [{
|
||||
# "href":"https://api.sandbox.paypal.com/v1/payments/payment/PAY-2LL14628DB722091TKKHXZHQ",
|
||||
# "rel":"self",
|
||||
# "method":"GET"
|
||||
# }]
|
||||
# }
|
||||
|
||||
|
||||
class PaypalForm(PaypalCommon):
|
||||
|
||||
Reference in New Issue
Block a user