[ADD] payment_acquirer: first implementation of paypal and ogone acquirers.
paypal: only form is currently implemented. Method name and call order will change. However the basic mechanism is impelmented. IPN is implemented (paypal contact us back after the transaction with transaction details). ogone: form and server2server are implemented. Method names and call order will change. Based on chs / dle / ... implementation for ogone server2server. basic addition of tests, still wip. This commit is not a clean commit but a WIP commit. Please excuse me but it's time to commit. bzr revid: tde@openerp.com-20131107172236-chmg198305crgrud
This commit is contained in:
parent
3d0ac6643e
commit
7fe8885216
|
@ -0,0 +1,22 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2013-Today OpenERP SA (<http://www.openerp.com>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import ogone
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="0">
|
||||
|
||||
<record id="payment_acquirer_ogone" model="payment.acquirer">
|
||||
<field name="name">ogone</field>
|
||||
<field name="view_template_id" ref="ogone_acquirer_button"/>
|
||||
<field name="env">test</field>
|
||||
<field name='ogone_pspid'>pinky</field>
|
||||
<field name='ogone_userid'>OOAPI</field>
|
||||
<field name='ogone_password'>R!ci/6Nu8a</field>
|
||||
<field name="ogone_shakey_in">tINY4Yv14789gUix1130</field>
|
||||
<field name="ogone_shakey_out">tINYj885Tfvd4P471464</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="0">
|
||||
|
||||
<record id="payment_acquirer_paypal" model="payment.acquirer">
|
||||
<field name="name">paypal</field>
|
||||
<field name="view_template_id" ref="paypal_acquirer_button"/>
|
||||
<field name="env">test</field>
|
||||
<field name="paypal_tx_url">https://www.sandbox.paypal.com/cgi-bin/webscr</field>
|
||||
<field name="paypal_email_id">tde+paypal-facilitator@openerp.com</field>
|
||||
<field name="paypal_username">'tde+paypal-facilitator_api1.openerp.com</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -0,0 +1,397 @@
|
|||
# -*- coding: utf-'8' "-*-"
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2013-Today OpenERP SA (<http://www.openerp.com>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from hashlib import sha1
|
||||
import logging
|
||||
from lxml import etree, objectify
|
||||
from pprint import pformat
|
||||
# import requests
|
||||
import time
|
||||
from urllib import urlencode
|
||||
import urllib2
|
||||
# import urlparse
|
||||
|
||||
from openerp.addons.payment_acquirer.data import ogone
|
||||
from openerp.addons.payment_acquirer.controllers.main import OgoneController
|
||||
from openerp.addons.payment_acquirer.models.payment_acquirer import ValidationError
|
||||
from openerp.osv import osv, fields
|
||||
from openerp.tools import float_round
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class PaymentAcquirerOgone(osv.Model):
|
||||
_inherit = 'payment.acquirer'
|
||||
|
||||
def _get_ogone_urls(self, cr, uid, ids, name, args, context=None):
|
||||
""" Ogone URLS:
|
||||
|
||||
- standard order: POST address for form-based
|
||||
|
||||
@TDETODO: complete me
|
||||
"""
|
||||
res = {}
|
||||
for acquirer in self.browse(cr, uid, ids, context=context):
|
||||
qualif = acquirer.env
|
||||
res[acquirer.id] = {
|
||||
'ogone_standard_order_url': 'https://secure.ogone.com/ncol/%s/orderstandard.asp' % qualif,
|
||||
'ogone_direct_order_url': 'https://secure.ogone.com/ncol/%s/orderdirect.asp' % qualif,
|
||||
'ogone_direct_query_url': 'https://secure.ogone.com/ncol/%s/querydirect.asp' % qualif,
|
||||
'ogone_afu_agree_url': 'https://secure.ogone.com/ncol/%s/AFU_agree.asp' % qualif,
|
||||
}
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
'ogone_pspid': fields.char(
|
||||
'PSPID', required_if_provider='ogone'),
|
||||
'ogone_userid': fields.char(
|
||||
'API User id', required_if_provider='ogone'),
|
||||
'ogone_password': fields.char(
|
||||
'Password', required_if_provider='ogone'),
|
||||
'ogone_shakey_in': fields.char(
|
||||
'SHA Key IN', size=32, required_if_provider='ogone'),
|
||||
'ogone_shakey_out': fields.char(
|
||||
'SHA Key OUT', size=32, required_if_provider='ogone'),
|
||||
# store ogone contact URLs -> not necessary IMHO
|
||||
'ogone_standard_order_url': fields.function(
|
||||
_get_ogone_urls, type='char', multi='_get_ogone_urls',
|
||||
string='Stanrd Order URL (form)'),
|
||||
'ogone_direct_order_url': fields.function(
|
||||
_get_ogone_urls, type='char', multi='_get_ogone_urls',
|
||||
string='Direct Order URL (2)'),
|
||||
'ogone_direct_query_url': fields.function(
|
||||
_get_ogone_urls, type='char', multi='_get_ogone_urls',
|
||||
string='Direct Query URL'),
|
||||
'ogone_afu_agree_url': fields.function(
|
||||
_get_ogone_urls, type='char', multi='_get_ogone_urls',
|
||||
string='AFU Agree URL'),
|
||||
}
|
||||
|
||||
def _ogone_generate_shasign(self, acquirer, inout, values):
|
||||
""" Generate the shasign for incoming or outgoing communications.
|
||||
|
||||
:param browse acquirer: the payment.acquirer browse record. It should
|
||||
have a shakey in shaky out
|
||||
:param string inout: 'in' (openerp contacting ogone) or 'out' (ogone
|
||||
contacting openerp). In this last case only some
|
||||
fields should be contained (see e-Commerce basic)
|
||||
:param dict values: transaction values
|
||||
|
||||
:return string: shasign
|
||||
"""
|
||||
assert inout in ('in', 'out')
|
||||
assert acquirer.name == 'ogone'
|
||||
key = getattr(acquirer, 'ogone_shakey_' + inout)
|
||||
|
||||
def filter_key(key):
|
||||
if inout == 'in':
|
||||
return True
|
||||
else:
|
||||
keys = "ORDERID CURRENCY AMOUNT PM ACCEPTANCE STATUS CARDNO ALIAS ED CN TRXDATE PAYID NCERROR BRAND ECI IP COMPLUS".split()
|
||||
return key.upper() in keys
|
||||
|
||||
items = sorted((k.upper(), v) for k, v in values.items())
|
||||
sign = ''.join('%s=%s%s' % (k, v, key) for k, v in items if v and filter_key(k))
|
||||
shasign = sha1(sign).hexdigest()
|
||||
return shasign
|
||||
|
||||
def ogone_form_generate_values(self, cr, uid, id, reference, amount, currency, partner_id=False, partner_values=None, tx_custom_values=None, context=None):
|
||||
if partner_values is None:
|
||||
partner_values = {}
|
||||
base_url = self.pool['ir.config_parameter'].get_param(cr, uid, 'web.base.url')
|
||||
acquirer = self.browse(cr, uid, id, context=context)
|
||||
partner = None
|
||||
if partner_id:
|
||||
partner = self.pool['res.partner'].browse(cr, uid, partner_id, context=context)
|
||||
tx_values = {
|
||||
'PSPID': acquirer.ogone_pspid,
|
||||
'ORDERID': reference,
|
||||
'AMOUNT': '%d' % int(float_round(amount, 2) * 100),
|
||||
'CURRENCY': currency and currency.name or 'EUR',
|
||||
'LANGUAGE': partner and partner.lang or partner_values.get('lang', ''),
|
||||
'CN': partner and partner.name or partner_values.get('name', ''),
|
||||
'EMAIL': partner and partner.email or partner_values.get('email', ''),
|
||||
'OWNERZIP': partner and partner.zip or partner_values.get('zip', ''),
|
||||
'OWNERADDRESS': partner and ' '.join((partner.street, partner.street2)).strip() or ' '.join((partner_values.get('street', ''), partner_values.get('street2', ''))).strip(),
|
||||
'OWNERTOWN': partner and partner.city or partner_values.get('city', ''),
|
||||
'OWNERCTY': partner and partner.country_id and partner.country_id.name or partner_values.get('country_name', ''),
|
||||
'OWNERTELNO': partner and partner.phone or partner_values.get('phone', ''),
|
||||
'ACCEPTURL': '%s/%s' % (base_url, OgoneController._accept_url),
|
||||
'DECLINEURL': '%s/%s' % (base_url, OgoneController._decline_url),
|
||||
'EXCEPTIONURL': '%s/%s' % (base_url, OgoneController._exception_url),
|
||||
'CANCELURL': '%s/%s' % (base_url, OgoneController._cancel_url),
|
||||
}
|
||||
if tx_custom_values:
|
||||
tx_values.update(tx_custom_values)
|
||||
shasign = self._ogone_generate_shasign(acquirer, 'in', tx_values)
|
||||
tx_values['SHASIGN'] = shasign
|
||||
return tx_values
|
||||
|
||||
|
||||
class PaymentTxOgone(osv.Model):
|
||||
_inherit = 'payment.transaction'
|
||||
|
||||
_columns = {
|
||||
'ogone_3ds': fields.dummy('3ds Activated'),
|
||||
'ogone_3ds_html': fields.html('3DS HTML'),
|
||||
'ogone_feedback_model': fields.char(),
|
||||
'ogone_feedback_eval': fields.char(),
|
||||
'ogone_complus': fields.char('Complus'),
|
||||
}
|
||||
|
||||
# --------------------------------------------------
|
||||
# FORM RELATED METHODS
|
||||
# --------------------------------------------------
|
||||
|
||||
def _ogone_form_get_tx_from_shasign_out(self, cr, uid, data, context=None):
|
||||
reference, pay_id, shasign = data.get('orderID'), data.get('PAYID'), data.get('SHASIGN')
|
||||
if not reference or not pay_id or not shasign:
|
||||
error_msg = 'Ogone: received data with missing reference (%s) or pay_id (%s) or shashign (%s)' % (reference, pay_id, shasign)
|
||||
_logger.error(error_msg)
|
||||
raise ValidationError(error_msg)
|
||||
|
||||
# find tx -> @TDENOTE use paytid ?
|
||||
tx_ids = self.pool['payment.transaction'].search(cr, uid, [('reference', '=', reference)], context=context)
|
||||
if not tx_ids or len(tx_ids) > 1:
|
||||
error_msg = 'Ogone: received data for reference' % (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)
|
||||
|
||||
# verify shasign
|
||||
shasign_check = self.pool['payment.acquirer']._generate_ogone_shasign(tx.acquirer_id, 'out', data)
|
||||
if shasign_check.upper() != shasign.upper():
|
||||
error_msg = 'Ogone: invalid shasign, received %s, computed %s, for data %s' % (shasign, shasign_check, data)
|
||||
_logger.error(error_msg)
|
||||
raise ValidationError(error_msg)
|
||||
|
||||
return tx
|
||||
|
||||
def ogone_form_generate_values(self, cr, uid, id, tx_custom_values=None, context=None):
|
||||
tx = self.browse(cr, uid, id, context=context)
|
||||
|
||||
tx_data = {
|
||||
'LANGUAGE': tx.partner_lang,
|
||||
'CN': tx.partner_name,
|
||||
'EMAIL': tx.partner_email,
|
||||
'OWNERZIP': tx.partner_zip,
|
||||
'OWNERADDRESS': tx.partner_address,
|
||||
'OWNERTOWN': tx.partner_city,
|
||||
'OWNERCTY': tx.partner_country_id and tx.partner_country_id.name or '',
|
||||
'OWNERTELNO': tx.partner_phone,
|
||||
}
|
||||
if tx_custom_values:
|
||||
tx_data.update(tx_custom_values)
|
||||
return self.pool['payment.acquirer'].ogone_form_generate_values(
|
||||
cr, uid, tx.acquirer_id.id,
|
||||
tx.reference, tx.amount, tx.currency_id,
|
||||
tx_custom_values=tx_data,
|
||||
context=context
|
||||
)
|
||||
|
||||
def ogone_form_feedback(self, cr, uid, data, context=None):
|
||||
print '-- ogone: ogone_form_feedback'
|
||||
tx = self._ogone_get_tx_from_shasign_out(cr, uid, data, context)
|
||||
if not tx:
|
||||
raise ValidationError('Ogone: feedback: tx not found')
|
||||
|
||||
status = int(data.get('STATUS', '0'))
|
||||
print '\togone: statuts %s' % status
|
||||
if status in [5, 9]:
|
||||
tx.write({'state': 'done'})
|
||||
return True
|
||||
else:
|
||||
error = 'Ogone: feedback error: %(error_str)s\n\n%(error_code)s: %(error_msg)s' % {
|
||||
'error_str': data.get('NCERROR'),
|
||||
'error_code': data.get('NCERRORPLUS'),
|
||||
'error_msg': ogone.OGONE_ERROR_MAP.get(data.get('NCERRORPLUS')),
|
||||
}
|
||||
_logger.info(error)
|
||||
tx.write({'state': 'error', 'state_message': error})
|
||||
return False
|
||||
|
||||
# --------------------------------------------------
|
||||
# S2S RELATED METHODS
|
||||
# --------------------------------------------------
|
||||
|
||||
def ogone_s2s_create_alias(self, cr, uid, id, values, context=None):
|
||||
""" Purpose: create an alias via batch """
|
||||
tx = self.browse(cr, uid, id, context=context)
|
||||
assert tx.type == 'server2server', 'Calling s2s dedicated method for a %s acquirer' % tx.type
|
||||
alias = 'OPENERP-%d-%d' % (tx.partner_id.id, tx.id)
|
||||
|
||||
expiry_date = '%s%s' % (values['expiry_date_mm'], values['expiry_date_yy'][2:])
|
||||
line = 'ADDALIAS;%(alias)s;%(holder_name)s;%(number)s;%(expiry_date)s;%(brand)s;%(pspid)s'
|
||||
line = line % dict(values, alias=alias, expiry_date=expiry_date, pspid=tx.acquirer_id.ogone_pspid)
|
||||
|
||||
tx_data = {
|
||||
'FILE_REFERENCE': 'OPENERP-NEW-ALIAS-%s' % time.time(), # something unique,
|
||||
'TRANSACTION_CODE': 'ATR',
|
||||
'OPERATION': 'SAL',
|
||||
'NB_PAYMENTS': 1, # even if we do not actually have any payment, ogone want it to not be 0
|
||||
'FILE': line,
|
||||
'REPLY_TYPE': 'XML',
|
||||
'PSPID': tx.acquirer_id.ogone_pspid,
|
||||
'USERID': tx.acquirer_id.ogone_userid,
|
||||
'PSWD': tx.acquirer_id.ogone_password,
|
||||
'PROCESS_MODE': 'CHECKANDPROCESS',
|
||||
}
|
||||
|
||||
request = urllib2.Request(tx.acquirer_id.ogone_afu_agree_url, urlencode(tx_data))
|
||||
result = urllib2.urlopen(request).read()
|
||||
|
||||
try:
|
||||
tree = objectify.fromstring(result)
|
||||
except etree.XMLSyntaxError:
|
||||
_logger.exception('Invalid xml response from ogone')
|
||||
return None
|
||||
|
||||
error_code = error_str = None
|
||||
if hasattr(tree, 'PARAMS_ERROR'):
|
||||
error_code = tree.NCERROR.text
|
||||
error_str = 'PARAMS ERROR: %s' % (tree.PARAMS_ERROR.text or '',)
|
||||
else:
|
||||
node = tree.FORMAT_CHECK
|
||||
error_node = getattr(node, 'FORMAT_CHECK_ERROR', None)
|
||||
if error_node is not None:
|
||||
error_code = error_node.NCERROR.text
|
||||
error_str = 'CHECK ERROR: %s' % (error_node.ERROR.text or '',)
|
||||
|
||||
if error_code:
|
||||
error_msg = ogone.OGONE_ERROR_MAP.get(error_code)
|
||||
error = '%s\n\n%s: %s' % (error_str, error_code, error_msg)
|
||||
_logger.error(error)
|
||||
raise Exception(error) # TODO specific exception
|
||||
|
||||
tx.write({'partner_reference': alias})
|
||||
return True
|
||||
|
||||
def ogone_s2s_generate_values(self, cr, uid, id, custom_values, context=None):
|
||||
tx = self.browse(cr, uid, id, context=context)
|
||||
tx_data = {
|
||||
'PSPID': tx.acquirer_id.ogone_pspid,
|
||||
'USERID': tx.acquirer_id.ogone_userid,
|
||||
'PSWD': tx.acquirer_id.ogone_password,
|
||||
'OrderID': tx.reference,
|
||||
'amount': '%d' % int(float_round(tx.amount, 2) * 100), # tde check amount or str * 100 ?
|
||||
'CURRENCY': tx.currency_id.name,
|
||||
'LANGUAGE': tx.partner_lang,
|
||||
'OPERATION': 'SAL',
|
||||
'ECI': 2, # Recurring (from MOTO)
|
||||
'ALIAS': tx.partner_reference,
|
||||
'RTIMEOUT': 30,
|
||||
}
|
||||
if custom_values.get('ogone_cvc'):
|
||||
tx_data['CVC'] = custom_values.get('ogone_cvc')
|
||||
if custom_values.pop('ogone_3ds', None):
|
||||
tx_data.update({
|
||||
'FLAG3D': 'Y', # YEAH!!
|
||||
})
|
||||
if custom_values.get('ogone_complus'):
|
||||
tx_data['COMPLUS'] = custom_values.get('ogone_complus')
|
||||
if custom_values.get('ogone_accept_url'):
|
||||
pass
|
||||
|
||||
shasign = self.pool['payment.acquirer']._ogone_generate_shasign(tx.acquirer_id, 'in', tx_data)
|
||||
tx_data['SHASIGN'] = shasign
|
||||
return tx_data
|
||||
|
||||
def ogone_s2s_execute(self, cr, uid, id, values, context=None):
|
||||
tx = self.browse(cr, uid, id, context=context)
|
||||
|
||||
tx_data = self.ogone_s2s_generate_values(cr, uid, id, values, context=context)
|
||||
_logger.info('Generated Ogone s2s data %s', pformat(tx_data)) # debug
|
||||
|
||||
request = urllib2.Request(tx.acquirer_id.ogone_direct_order_url, urlencode(tx_data))
|
||||
result = urllib2.urlopen(request).read()
|
||||
_logger.info('Contacted Ogone direct order; result %s', result) # debug
|
||||
|
||||
tree = objectify.fromstring(result)
|
||||
payid = tree.get('PAYID')
|
||||
print 'payid', payid
|
||||
|
||||
query_direct_data = dict(
|
||||
PSPID=tx.acquirer_id.ogone_pspid,
|
||||
USERID=tx.acquirer_id.ogone_userid,
|
||||
PSWD=tx.acquirer_id.ogone_password,
|
||||
ID=payid,
|
||||
)
|
||||
query_direct_url = 'https://secure.ogone.com/ncol/%s/querydirect.asp' % (tx.acquirer_id.env,)
|
||||
|
||||
tries = 2
|
||||
tx_done = False
|
||||
tx_status = False
|
||||
while not tx_done or tries > 0:
|
||||
try:
|
||||
tree = objectify.fromstring(result)
|
||||
except etree.XMLSyntaxError:
|
||||
# invalid response from ogone
|
||||
_logger.exception('Invalid xml response from ogone')
|
||||
raise
|
||||
|
||||
# see https://secure.ogone.com/ncol/paymentinfos1.asp
|
||||
VALID_TX = [5, 9]
|
||||
WAIT_TX = [41, 50, 51, 52, 55, 56, 91, 92, 99]
|
||||
PENDING_TX = [46] # 3DS HTML response
|
||||
# other status are errors...
|
||||
|
||||
status = tree.get('STATUS')
|
||||
if status == '':
|
||||
status = None
|
||||
else:
|
||||
status = int(status)
|
||||
|
||||
if status in VALID_TX:
|
||||
tx_status = True
|
||||
tx_done = True
|
||||
|
||||
elif status in PENDING_TX:
|
||||
html = str(tree.HTML_ANSWER)
|
||||
tx_data.update(ogone_3ds_html=html.decode('base64'))
|
||||
tx_status = False
|
||||
tx_done = True
|
||||
|
||||
elif status in WAIT_TX:
|
||||
time.sleep(1500)
|
||||
|
||||
request = urllib2.Request(query_direct_url, urlencode(query_direct_data))
|
||||
result = urllib2.urlopen(request).read()
|
||||
_logger.debug('Contacted Ogone query direct; result %s', result)
|
||||
|
||||
else:
|
||||
error_code = tree.get('NCERROR')
|
||||
if not ogone.retryable(error_code):
|
||||
error_str = tree.get('NCERRORPLUS')
|
||||
error_msg = ogone.OGONE_ERROR_MAP.get(error_code)
|
||||
error = 'ERROR: %s\n\n%s: %s' % (error_str, error_code, error_msg)
|
||||
_logger.info(error)
|
||||
raise Exception(error)
|
||||
|
||||
tries = tries - 1
|
||||
|
||||
if not tx_done and tries == 0:
|
||||
raise Exception('Cannot get transaction status...')
|
||||
|
||||
return (tx_status, orderid, payid)
|
|
@ -0,0 +1,241 @@
|
|||
# -*- coding: utf-'8' "-*-"
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2013-Today OpenERP SA (<http://www.openerp.com>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.addons.payment_acquirer.controllers.main import PaypalController
|
||||
from openerp.addons.payment_acquirer.models.payment_acquirer import ValidationError
|
||||
from openerp.osv import osv, fields
|
||||
|
||||
import logging
|
||||
import requests
|
||||
import urlparse
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AcquirerPaypal(osv.Model):
|
||||
_inherit = 'payment.acquirer'
|
||||
|
||||
_columns = {
|
||||
'paypal_email_id': fields.char('Email ID', required_if_provider='paypal'),
|
||||
'paypal_username': fields.char('Username', required_if_provider='paypal'),
|
||||
'paypal_password': fields.char('Password'),
|
||||
'paypal_signature': fields.char('Signature'),
|
||||
'paypal_tx_url': fields.char('Transaction URL', required_if_provider='paypal'),
|
||||
'paypal_use_dpn': fields.boolean('Use DPN'),
|
||||
'paypal_use_ipn': fields.boolean('Use IPN'),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'paypal_use_dpn': True,
|
||||
'paypal_use_ipn': True,
|
||||
'paypal_tx_url': 'https://www.sandbox.paypal.com/cgi-bin/webscr',
|
||||
}
|
||||
|
||||
def paypal_form_generate_values(self, cr, uid, id, reference, amount, currency, partner_id=False, partner_values=None, tx_custom_values=None, context=None):
|
||||
if partner_values is None:
|
||||
partner_values = {}
|
||||
base_url = self.pool['ir.config_parameter'].get_param(cr, uid, 'web.base.url')
|
||||
acquirer = self.browse(cr, uid, id, context=context)
|
||||
partner = None
|
||||
if partner_id:
|
||||
partner = self.pool['res.partner'].browse(cr, uid, partner_id, context=context)
|
||||
tx_values = {
|
||||
'cmd': '_xclick',
|
||||
'business': acquirer.paypal_email_id,
|
||||
'item_name': reference,
|
||||
'item_number': reference,
|
||||
'amount': amount,
|
||||
'currency_code': currency and currency.name or 'EUR',
|
||||
'address1': partner and ' '.join((partner.street, partner.street2)).strip() or ' '.join((partner_values.get('street', ''), partner_values.get('street2', ''))).strip(),
|
||||
'city': partner and partner.city or partner_values.get('city', ''),
|
||||
'country': partner and partner.country_id and partner.country_id.name or partner_values.get('country_name', ''),
|
||||
'email': partner and partner.email or partner_values.get('email', ''),
|
||||
'zip': partner and partner.zip or partner_values.get('zip', ''),
|
||||
'first_name': partner and partner.name or partner_values.get('name', '').split()[-1:],
|
||||
'last_name': partner and partner.name or partner_values.get('name', '').split()[:-1],
|
||||
'return': '%s/%s' % (base_url, PaypalController._return_url),
|
||||
'notify_url': '%s/%s' % (base_url, PaypalController._notify_url),
|
||||
'cancel_return': '%s/%s' % (base_url, PaypalController._cancel_url),
|
||||
}
|
||||
if tx_custom_values:
|
||||
tx_values.update(tx_custom_values)
|
||||
return tx_values
|
||||
|
||||
|
||||
class TxPaypal(osv.Model):
|
||||
_inherit = 'payment.transaction'
|
||||
|
||||
_columns = {
|
||||
'paypal_txn_id': fields.char('Transaction ID'),
|
||||
}
|
||||
|
||||
# --------------------------------------------------
|
||||
# FORM RELATED METHODS
|
||||
# --------------------------------------------------
|
||||
|
||||
def paypal_form_generate_values(self, cr, uid, id, tx_custom_values=None, context=None):
|
||||
tx = self.browse(cr, uid, id, context=context)
|
||||
|
||||
tx_data = {
|
||||
'item_name': tx.name,
|
||||
'first_name': tx.partner_name and tx.partner_name.split()[-1:],
|
||||
'last_name': tx.partner_name and tx.partner_name.split()[:-1],
|
||||
'email': tx.partner_email,
|
||||
'zip': tx.partner_zip,
|
||||
'address1': tx.partner_address,
|
||||
'city': tx.partner_city,
|
||||
'country': tx.partner_country_id and tx.partner_country_id.name or '',
|
||||
}
|
||||
if tx_custom_values:
|
||||
tx_data.update(tx_custom_values)
|
||||
return self.pool['payment.acquirer'].paypal_form_generate_values(
|
||||
cr, uid, tx.acquirer_id.id,
|
||||
tx.reference, tx.amount, tx.currency_id,
|
||||
tx_custom_values=tx_data,
|
||||
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)
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
tx = self.browse(cr, uid, tx_ids[0], context=context)
|
||||
|
||||
if parameters.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')
|
||||
)
|
||||
if parameters.get('test_ipn')[0]:
|
||||
_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:
|
||||
invalid_parameters.append(('mc_gross', tx.amount))
|
||||
if parameters.get('mc_currency')[0] != 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))
|
||||
# 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))
|
||||
# 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))
|
||||
# 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 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:
|
||||
_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])
|
||||
_logger.warning(_warn_message)
|
||||
|
||||
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
|
||||
|
||||
def _transaction_feedback_paypal(self, **values):
|
||||
print values
|
||||
return True
|
Binary file not shown.
After Width: | Height: | Size: 973 B |
Binary file not shown.
After Width: | Height: | Size: 3.3 KiB |
Binary file not shown.
After Width: | Height: | Size: 8.3 KiB |
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
|
@ -0,0 +1,28 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Business Applications
|
||||
# Copyright (c) 2012-TODAY OpenERP S.A. <http://openerp.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from . import test_payment_acquirer
|
||||
|
||||
checks = [
|
||||
test_payment_acquirer,
|
||||
]
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -0,0 +1,66 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Business Applications
|
||||
# Copyright (c) 20123TODAY OpenERP S.A. <http://www.openerp.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.tests import common
|
||||
|
||||
|
||||
class TestPaymentAcquirer(common.TransactionCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestPaymentAcquirer, self).setUp()
|
||||
self.payment_acquirer = self.registry('payment.acquirer')
|
||||
self.payment_transaction = self.registry('payment.transaction')
|
||||
|
||||
self.currency_euro_id = self.registry('res.currency').search(
|
||||
self.cr, self.uid, [('name', '=', 'EUR')], limit=1)[0]
|
||||
self.currency_euro = self.registry('res.currency').browse(
|
||||
self.cr, self.uid, self.currency_euro_id)
|
||||
country_belgium_id = self.registry('res.country').search(
|
||||
self.cr, self.uid, [('code', 'like', 'BE')], limit=1)[0]
|
||||
|
||||
# dict partner values
|
||||
self.buyer_values = {
|
||||
'name': 'Norbert Buyer',
|
||||
'lang': 'en_US',
|
||||
'email': 'norbert.buyer@example.com',
|
||||
'street': 'Huge Street',
|
||||
'street2': '2/543',
|
||||
'phone': '0032 12 34 56 78',
|
||||
'city': 'Sin City',
|
||||
'zip': '1000',
|
||||
'country_id': country_belgium_id,
|
||||
'country_name': 'Belgium',
|
||||
}
|
||||
|
||||
# test partner
|
||||
self.buyer_id = self.registry('res.partner').create(
|
||||
self.cr, self.uid, {
|
||||
'name': 'Norbert Buyer',
|
||||
'lang': 'en_US',
|
||||
'email': 'norbert.buyer@example.com',
|
||||
'street': 'Huge Street',
|
||||
'street2': '2/543',
|
||||
'phone': '0032 12 34 56 78',
|
||||
'city': 'Sin City',
|
||||
'zip': '1000',
|
||||
'country_id': country_belgium_id,
|
||||
}
|
||||
)
|
|
@ -0,0 +1,272 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Business Applications
|
||||
# Copyright (c) 2012-TODAY OpenERP S.A. <http://openerp.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.addons.payment_acquirer.controllers.main import OgoneController
|
||||
from openerp.addons.payment_acquirer.tests.common import TestPaymentAcquirer
|
||||
from openerp.osv.orm import except_orm
|
||||
|
||||
from lxml import objectify
|
||||
# import requests
|
||||
# import urlparse
|
||||
|
||||
|
||||
class BasicPayment(TestPaymentAcquirer):
|
||||
|
||||
def test_10_paypal_basic(self):
|
||||
pass
|
||||
|
||||
def test_11_paypal_form(self):
|
||||
cr, uid = self.cr, self.uid
|
||||
context = {}
|
||||
base_url = self.registry('ir.config_parameter').get_param(cr, uid, 'web.base.url')
|
||||
# ogone_url = self.payment_acquirer._get_ogone_urls(cr, uid, [ogone_id], None, None)[ogone_id]['ogone_standard_order_url']
|
||||
|
||||
model, paypal_view_id = self.registry('ir.model.data').get_object_reference(cr, uid, 'payment_acquirer', 'paypal_acquirer_button')
|
||||
|
||||
# forgot some mandatory fields: should crash
|
||||
with self.assertRaises(except_orm):
|
||||
paypal_id = self.payment_acquirer.create(
|
||||
cr, uid, {
|
||||
'name': 'paypal',
|
||||
'env': 'test',
|
||||
'view_template_id': paypal_view_id,
|
||||
'paypal_email_id': 'tde+paypal-facilitator@openerp.com',
|
||||
}, context=context
|
||||
)
|
||||
# tde+buyer@openerp.com
|
||||
|
||||
# create a new paypal account
|
||||
paypal_id = self.payment_acquirer.create(
|
||||
cr, uid, {
|
||||
'name': 'paypal',
|
||||
'env': 'test',
|
||||
'view_template_id': paypal_view_id,
|
||||
'paypal_email_id': 'tde+paypal-facilitator@openerp.com',
|
||||
'paypal_username': 'tde+paypal-facilitator_api1.openerp.com',
|
||||
}, context=context
|
||||
)
|
||||
# verify acquirer data
|
||||
paypal = self.payment_acquirer.browse(cr, uid, paypal_id, context)
|
||||
self.assertEqual(paypal.env, 'test', 'test without test env')
|
||||
|
||||
# render the button
|
||||
res = self.payment_acquirer.render(
|
||||
cr, uid, paypal_id,
|
||||
'test_ref0', 0.01, self.currency_euro,
|
||||
partner_id=None,
|
||||
partner_values=self.buyer_values,
|
||||
context=context)
|
||||
print res
|
||||
|
||||
# # check some basic paypal methods
|
||||
# res = self.payment_transaction.validate_paypal_notification(
|
||||
# cr, uid,
|
||||
# 'http://localhost/payment?mc_gross=19.95&protection_eligibility=Eligible&address_status=confirmed&payer_id=LPLWNMTBWMFAY&tax=0.00&address_street=1+Main+St&payment_date=20%3A12%3A59+Jan+13%2C+2009+PST&payment_status=Completed&charset=windows-1252&address_zip=95131&first_name=Test&mc_fee=0.88&address_country_code=US&address_name=Test+User¬ify_version=2.6&custom=&payer_status=verified&address_country=United+States&address_city=San+Jose&quantity=1&verify_sign=AtkOfCXbDm2hu0ZELryHFjY-Vb7PAUvS6nMXgysbElEn9v-1XcmSoGtf&payer_email=gpmac_1231902590_per%40paypal.com&txn_id=61E67681CH3238416&payment_type=instant&last_name=User&address_state=CA&receiver_email=gpmac_1231902686_biz%40paypal.com&payment_fee=0.88&receiver_id=S8XGHLYDW9T3S&txn_type=express_checkout&item_name=&mc_currency=USD&item_number=&residence_country=US&test_ipn=1&handling_amount=0.00&transaction_subject=&payment_gross=19.95&shipping=0.00')
|
||||
# self.assertEqual(res, False, 'payment: paypal validation on a txn_id that does not exists should return False')
|
||||
|
||||
# txn_id = self.payment_transaction.create(
|
||||
# cr, uid, {
|
||||
# 'amount': 0.01,
|
||||
# 'acquirer_id': paypal_id,
|
||||
# 'currency_id': currency_id,
|
||||
# 'reference': 'test_reference',
|
||||
# 'paypal_txn_id': '61E67681CH3238416',
|
||||
# }, context=context
|
||||
# )
|
||||
# res = self.payment_transaction.validate_paypal_notification(
|
||||
# cr, uid,
|
||||
# 'http://localhost/payment?mc_gross=19.95&protection_eligibility=Eligible&address_status=confirmed&payer_id=LPLWNMTBWMFAY&tax=0.00&address_street=1+Main+St&payment_date=20%3A12%3A59+Jan+13%2C+2009+PST&payment_status=Completed&charset=windows-1252&address_zip=95131&first_name=Test&mc_fee=0.88&address_country_code=US&address_name=Test+User¬ify_version=2.6&custom=&payer_status=verified&address_country=United+States&address_city=San+Jose&quantity=1&verify_sign=AtkOfCXbDm2hu0ZELryHFjY-Vb7PAUvS6nMXgysbElEn9v-1XcmSoGtf&payer_email=gpmac_1231902590_per%40paypal.com&txn_id=61E67681CH3238416&payment_type=instant&last_name=User&address_state=CA&receiver_email=gpmac_1231902686_biz%40paypal.com&payment_fee=0.88&receiver_id=S8XGHLYDW9T3S&txn_type=express_checkout&item_name=&mc_currency=USD&item_number=&residence_country=US&test_ipn=1&handling_amount=0.00&transaction_subject=&payment_gross=19.95&shipping=0.00')
|
||||
# print res
|
||||
|
||||
# # user pays using Paypal
|
||||
# resp = self.payment_transaction.create_paypal_command(
|
||||
# cr, uid, cmd='_xclick', parameters={
|
||||
# 'business': 'tdelavallee-facilitator@gmail.com',
|
||||
# 'amount': 50,
|
||||
# 'item_name': 'test_item',
|
||||
# 'quantity': 1,
|
||||
# 'currency_code': 'USD',
|
||||
# 'return': 'http://www.example.com',
|
||||
# })
|
||||
# print resp
|
||||
# print resp.url
|
||||
# print resp.text
|
||||
|
||||
# self.payment_transaction.validate(cr, uid, [tx_id], context=context)
|
||||
|
||||
def test_20_ogone_form(self):
|
||||
cr, uid = self.cr, self.uid
|
||||
context = {}
|
||||
base_url = self.registry('ir.config_parameter').get_param(cr, uid, 'web.base.url')
|
||||
# ogone_url = self.payment_acquirer._get_ogone_urls(cr, uid, [ogone_id], None, None)[ogone_id]['ogone_standard_order_url']
|
||||
|
||||
model, ogone_view_id = self.registry('ir.model.data').get_object_reference(cr, uid, 'payment_acquirer', 'ogone_acquirer_button')
|
||||
|
||||
# create a new ogone account
|
||||
ogone_id = self.payment_acquirer.create(
|
||||
cr, uid, {
|
||||
'name': 'ogone',
|
||||
'env': 'test',
|
||||
'view_template_id': ogone_view_id,
|
||||
'ogone_pspid': 'pinky',
|
||||
'ogone_userid': 'OOAPI',
|
||||
'ogone_password': 'R!ci/6Nu8a',
|
||||
'ogone_shakey_in': 'tINY4Yv14789gUix1130',
|
||||
'ogone_shakey_out': 'tINYj885Tfvd4P471464',
|
||||
}, context=context
|
||||
)
|
||||
# verify acquirer data
|
||||
ogone = self.payment_acquirer.browse(cr, uid, ogone_id, context)
|
||||
self.assertEqual(ogone.env, 'test', 'test without test env')
|
||||
|
||||
form_values = {
|
||||
'PSPID': 'pinky',
|
||||
'ORDERID': 'test_ref0',
|
||||
'AMOUNT': '1',
|
||||
'CURRENCY': 'EUR',
|
||||
'LANGUAGE': 'en_US',
|
||||
'CN': 'Norbert Buyer',
|
||||
'EMAIL': 'norbert.buyer@example.com',
|
||||
'OWNERZIP': '1000',
|
||||
'OWNERADDRESS': 'Huge Street 2/543',
|
||||
'OWNERCTY': 'Belgium',
|
||||
'OWNERTOWN': 'Sin City',
|
||||
'OWNERTELNO': '0032 12 34 56 78',
|
||||
'SHASIGN': 'ea74bb42d4f25746279cdd44a737aaddc71e7f9f',
|
||||
'ACCEPTURL': '%s/%s' % (base_url, OgoneController._accept_url),
|
||||
'DECLINEURL': '%s/%s' % (base_url, OgoneController._decline_url),
|
||||
'EXCEPTIONURL': '%s/%s' % (base_url, OgoneController._exception_url),
|
||||
'CANCELURL': '%s/%s' % (base_url, OgoneController._cancel_url),
|
||||
}
|
||||
|
||||
# render the button
|
||||
res = self.payment_acquirer.render(
|
||||
cr, uid, ogone_id,
|
||||
'test_ref0', 0.01, self.currency_euro,
|
||||
partner_id=None,
|
||||
partner_values=self.buyer_values,
|
||||
context=context)
|
||||
# check form result
|
||||
tree = objectify.fromstring(res)
|
||||
self.assertEqual(tree.get('action'), 'https://secure.ogone.com/ncol/test/orderstandard.asp', 'ogone: wrong form POST url')
|
||||
for form_input in tree.input:
|
||||
if form_input.get('name') in ['submit']:
|
||||
continue
|
||||
self.assertEqual(
|
||||
form_input.get('value'),
|
||||
form_values[form_input.get('name')],
|
||||
'ogone: wrong value for form: received %s instead of %s' % (form_input.get('value'), form_values[form_input.get('name')])
|
||||
)
|
||||
# resp = requests.post(tree.get('action'), data=form_values)
|
||||
|
||||
# create a new draft tx
|
||||
tx_id = self.payment_transaction.create(
|
||||
cr, uid, {
|
||||
'amount': 0.01,
|
||||
'acquirer_id': ogone_id,
|
||||
'currency_id': self.currency_euro_id,
|
||||
'reference': 'test_ref0',
|
||||
'partner_id': self.buyer_id,
|
||||
}, context=context
|
||||
)
|
||||
# render the button
|
||||
res = self.payment_acquirer.render(
|
||||
cr, uid, ogone_id,
|
||||
'test_ref0', 0.01, self.currency_euro,
|
||||
tx_id=tx_id,
|
||||
partner_id=None,
|
||||
partner_values=self.buyer_values,
|
||||
context=context)
|
||||
# check form result
|
||||
tree = objectify.fromstring(res)
|
||||
self.assertEqual(tree.get('action'), 'https://secure.ogone.com/ncol/test/orderstandard.asp', 'ogone: wrong form POST url')
|
||||
for form_input in tree.input:
|
||||
if form_input.get('name') in ['submit']:
|
||||
continue
|
||||
self.assertEqual(
|
||||
form_input.get('value'),
|
||||
form_values[form_input.get('name')],
|
||||
'ogone: wrong value for form input %s: received %s instead of %s' % (form_input.get('name'), form_input.get('value'), form_values[form_input.get('name')])
|
||||
)
|
||||
|
||||
def test_21_ogone_s2s(self):
|
||||
cr, uid = self.cr, self.uid
|
||||
context = {}
|
||||
|
||||
model, ogone_view_id = self.registry('ir.model.data').get_object_reference(cr, uid, 'payment_acquirer', 'ogone_acquirer_button')
|
||||
|
||||
# create a new ogone account
|
||||
ogone_id = self.payment_acquirer.create(
|
||||
cr, uid, {
|
||||
'name': 'ogone',
|
||||
'env': 'test',
|
||||
'view_template_id': ogone_view_id,
|
||||
'ogone_pspid': 'pinky',
|
||||
'ogone_userid': 'OOAPI',
|
||||
'ogone_password': 'R!ci/6Nu8a',
|
||||
'ogone_shakey_in': 'tINY4Yv14789gUix1130',
|
||||
'ogone_shakey_out': 'tINYj885Tfvd4P471464',
|
||||
}, context=context
|
||||
)
|
||||
|
||||
# create a new draft tx
|
||||
tx_id = self.payment_transaction.create(
|
||||
cr, uid, {
|
||||
'amount': 0.01,
|
||||
'acquirer_id': ogone_id,
|
||||
'currency_id': self.currency_euro_id,
|
||||
'reference': 'test_ogone_0',
|
||||
'partner_id': self.buyer_id,
|
||||
'type': 'server2server',
|
||||
}, context=context
|
||||
)
|
||||
|
||||
res = self.payment_transaction.ogone_s2s_create_alias(
|
||||
cr, uid, tx_id, {
|
||||
'expiry_date_mm': '01',
|
||||
'expiry_date_yy': '2015',
|
||||
'holder_name': 'Norbert Poilu',
|
||||
'number': '4000000000000002',
|
||||
'brand': 'VISA',
|
||||
}, context=context)
|
||||
print res
|
||||
|
||||
res = self.payment_transaction.ogone_s2s_execute(cr, uid, tx_id, {}, context=context)
|
||||
print res
|
||||
|
||||
|
||||
# {
|
||||
# 'orderID': u'reference',
|
||||
# 'STATUS': u'9',
|
||||
# 'CARDNO': u'XXXXXXXXXXXX0002',
|
||||
# 'PAYID': u'24998692',
|
||||
# 'CN': u'Norbert Poilu',
|
||||
# 'NCERROR': u'0',
|
||||
# 'TRXDATE': u'11/05/13',
|
||||
# 'IP': u'85.201.233.72',
|
||||
# 'BRAND': u'VISA',
|
||||
# 'ACCEPTANCE': u'test123',
|
||||
# 'currency': u'EUR',
|
||||
# 'amount': u'1.95',
|
||||
# 'SHASIGN': u'EFDC56879EF7DE72CCF4B397076B5C9A844CB0FA',
|
||||
# 'ED': u'0314',
|
||||
# 'PM': u'CreditCard'
|
||||
# }
|
|
@ -0,0 +1,44 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="0">
|
||||
|
||||
<template id="ogone_acquirer_button">
|
||||
<form t-if="acquirer" t-att-action="acquirer.ogone_standard_order_url" method="post" target="_self">
|
||||
<!-- seller -->
|
||||
<input type='hidden' name='PSPID' t-att-value='tx_values["PSPID"]'/>
|
||||
<input type='hidden' name='ORDERID' t-att-value='tx_values["ORDERID"]'/>
|
||||
<!-- cart -->
|
||||
<input type='hidden' name='AMOUNT' t-att-value='tx_values["AMOUNT"]'/>
|
||||
<input type='hidden' name='CURRENCY' t-att-value='tx_values["CURRENCY"]'/>
|
||||
<!-- buyer -->
|
||||
<input type='hidden' name='LANGUAGE' t-att-value='tx_values["LANGUAGE"]'/>
|
||||
<input type='hidden' name='CN' t-att-value='tx_values["CN"]'/>
|
||||
<input type='hidden' name='EMAIL' t-att-value='tx_values["EMAIL"]'/>
|
||||
<input type='hidden' name='OWNERZIP' t-att-value='tx_values["OWNERZIP"]'/>
|
||||
<input type='hidden' name='OWNERADDRESS' t-att-value='tx_values["OWNERADDRESS"]'/>
|
||||
<input type='hidden' name='OWNERCTY' t-att-value='tx_values["OWNERCTY"]'/>
|
||||
<input type='hidden' name='OWNERTOWN' t-att-value='tx_values["OWNERTOWN"]'/>
|
||||
<input type='hidden' name='OWNERTELNO' t-att-value='tx_values["OWNERTELNO"]'/>
|
||||
<!-- before payment verification -->
|
||||
<input type='hidden' name='SHASIGN' t-att-value='tx_values["SHASIGN"]'/>
|
||||
<!-- look and print -->
|
||||
<!-- <input type='hidden' name='TITLE' t-att-value='tx_dict["currency_name"]'/>
|
||||
<input type='hidden' name='BGCOLOR' t-att-value='tx_dict["currency_name"]'/>
|
||||
<input type='hidden' name='TXTCOLOR' t-att-value='tx_dict["currency_name"]'/>
|
||||
<input type='hidden' name='TBLBGCOLOR' t-att-value='tx_dict["currency_name"]'/>
|
||||
<input type='hidden' name='TBLTXTCOLOR' t-att-value='tx_dict["currency_name"]'/>
|
||||
<input type='hidden' name='BUTTONBGCOLOR' t-att-value='tx_dict["currency_name"]'/>
|
||||
<input type='hidden' name='BUTTONTXTCOLOR' t-att-value='tx_dict["currency_name"]'/>
|
||||
<input type='hidden' name='LOGO' t-att-value='tx_dict["currency_name"]'/>
|
||||
<input type='hidden' name='FONTTYPE' t-att-value='tx_dict["currency_name"]'/> -->
|
||||
<!-- redirection -->
|
||||
<input type='hidden' name='ACCEPTURL' t-att-value='tx_values["ACCEPTURL"]'/>
|
||||
<input type='hidden' name='DECLINEURL' t-att-value='tx_values["DECLINEURL"]'/>
|
||||
<input type='hidden' name='EXCEPTIONURL' t-att-value='tx_values["EXCEPTIONURL"]'/>
|
||||
<input type='hidden' name='CANCELURL' t-att-value='tx_values["CANCELURL"]'/>
|
||||
<input type="image" name="submit" src="https://www.paypal.com/en_US/i/btn/btn_paynowCC_LG.gif"/>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="0">
|
||||
|
||||
<template id="paypal_acquirer_button">
|
||||
<form t-if="acquirer.paypal_email_id" t-att-action="acquirer.paypal_tx_url" method="post" target="_self">
|
||||
<input type="hidden" name="cmd" value="tx_values['cmd']"/>
|
||||
<input type="hidden" name="business" t-att-value="tx_values['business']"/>
|
||||
<input type="hidden" name="item_name" t-attf-value="tx_values['item_name']"/>
|
||||
<input type="hidden" name="item_number" t-att-value="tx_values['item_number']"/>
|
||||
<input type="hidden" name="amount" t-att-value="tx_values['amount']"/>
|
||||
<input type="hidden" name="currency_code" t-att-value="tx_values['currency_code']"/>
|
||||
<!-- partner / address data -->
|
||||
<input type="hidden" name="address1" t-att-value="tx_values['address1']"/>
|
||||
<input type="hidden" name="city" t-att-value="tx_values['city']"/>
|
||||
<input type="hidden" name="country" t-att-value="tx_values['country']"/>
|
||||
<input type="hidden" name="email" t-att-value="tx_values['email']"/>
|
||||
<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']"/>
|
||||
<!-- URLs -->
|
||||
<input t-if="acquirer.paypal_use_dpn" type='hidden' name='return'
|
||||
t-att-value="tx_values['return']"/>
|
||||
<input t-if="acquirer.paypal_use_ipn" type='hidden' name='notify_url'
|
||||
t-att-value="tx_values['notify_url']"/>
|
||||
<input t-if="tx_values['cancel_return']" type="hidden" name="cancel_return"
|
||||
t-att-value="tx_values['cancel_return']"/>
|
||||
<!-- button -->
|
||||
<input type="image" name="submit" src="https://www.paypal.com/en_US/i/btn/btn_paynowCC_LG.gif"/>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
</data>
|
||||
</openerp>
|
Loading…
Reference in New Issue