[REF] payment: moved paypal and ogone stuff into their dedicated modules.
authorThibault Delavallée <tde@openerp.com>
Thu, 7 Nov 2013 18:04:44 +0000 (19:04 +0100)
committerThibault Delavallée <tde@openerp.com>
Thu, 7 Nov 2013 18:04:44 +0000 (19:04 +0100)
Added payment_acquirer_paypal and .._ogone modules. Those modules hold
the model / data / controllers related to the specific acquirer.

Also updated website_payment, to use website.menu instead of custom change
in header, as menus are now editable.

bzr revid: tde@openerp.com-20131107180444-bbzobquqq9o6pctv

38 files changed:
addons/payment_acquirer/__openerp__.py
addons/payment_acquirer/controllers/main.py
addons/payment_acquirer/data/__init__.py [deleted file]
addons/payment_acquirer/data/ogone.py [deleted file]
addons/payment_acquirer/data/ogone.xml [deleted file]
addons/payment_acquirer/data/paypal.xml [deleted file]
addons/payment_acquirer/models/__init__.py
addons/payment_acquirer/models/ogone.py [deleted file]
addons/payment_acquirer/models/paypal.py [deleted file]
addons/payment_acquirer/tests/__init__.py
addons/payment_acquirer/tests/common.py
addons/payment_acquirer/tests/test_payment_acquirer.py [deleted file]
addons/payment_acquirer/views/ogone.xml [deleted file]
addons/payment_acquirer/views/paypal.xml [deleted file]
addons/payment_acquirer_ogone/__init__.py [new file with mode: 0644]
addons/payment_acquirer_ogone/__openerp__.py [new file with mode: 0644]
addons/payment_acquirer_ogone/controllers/__init__.py [new file with mode: 0644]
addons/payment_acquirer_ogone/controllers/main.py [new file with mode: 0644]
addons/payment_acquirer_ogone/data/__init__.py [new file with mode: 0644]
addons/payment_acquirer_ogone/data/ogone.py [new file with mode: 0644]
addons/payment_acquirer_ogone/data/ogone.xml [new file with mode: 0644]
addons/payment_acquirer_ogone/models/__init__.py [new file with mode: 0644]
addons/payment_acquirer_ogone/models/ogone.py [new file with mode: 0644]
addons/payment_acquirer_ogone/tests/__init__.py [new file with mode: 0644]
addons/payment_acquirer_ogone/tests/test_ogone.py [new file with mode: 0644]
addons/payment_acquirer_ogone/views/ogone.xml [new file with mode: 0644]
addons/payment_acquirer_paypal/__init__.py [new file with mode: 0644]
addons/payment_acquirer_paypal/__openerp__.py [new file with mode: 0644]
addons/payment_acquirer_paypal/controllers/__init__.py [new file with mode: 0644]
addons/payment_acquirer_paypal/controllers/main.py [new file with mode: 0644]
addons/payment_acquirer_paypal/data/paypal.xml [new file with mode: 0644]
addons/payment_acquirer_paypal/models/__init__.py [new file with mode: 0644]
addons/payment_acquirer_paypal/models/paypal.py [new file with mode: 0644]
addons/payment_acquirer_paypal/tests/__init__.py [new file with mode: 0644]
addons/payment_acquirer_paypal/tests/test_paypal.py [new file with mode: 0644]
addons/payment_acquirer_paypal/views/paypal.xml [new file with mode: 0644]
addons/website_payment/__openerp__.py
addons/website_payment/views/website_payment_templates.xml

index 6fd1d82..164e1d7 100644 (file)
     'depends': ['decimal_precision', 'mail'],
     'data': [
         'views/payment_acquirer_views.xml',
-        'views/ogone.xml',
-        'views/paypal.xml',
         'data/payment_acquirer_data.xml',
-        'data/ogone.xml',
-        'data/paypal.xml',
         'security/ir.model.access.csv',
     ],
     'installable': True,
index 9f1dcdc..c0ef7f3 100644 (file)
 ##############################################################################
 
 from openerp.addons.web import http
-from openerp.addons.web.http import request
-# from openerp.addons.payment_acquirer.models.payment_acquirer import ValidationError
-from openerp.addons.website.models import website
 
 import logging
-import requests
-from urllib import urlencode
 
 _logger = logging.getLogger(__name__)
 
 
-class PaypalController(http.Controller):
-    _notify_url = '/payment/paypal/ipn/'
-    _return_url = '/payment/paypal/dpn/'
-    _cancel_url = '/payment/paypal/cancel/'
-    # _ipn_url2 = '/payment/paypal/<int:acquirer_id>/ipn/'
-
-    @website.route('/payment/paypal/<int:acquirer_id>/ipn/', type='http', auth='admin')
-    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 ''
-
-        # step 2: POST the complete, unaltered message back to Paypal (preceded by cmd=_notify-validate), with same encoding
-        paypal_url = "https://www.sandbox.paypal.com/cgi-bin/webscr"
-        post_url = '%s?cmd=_notify-validate&%s' % (paypal_url, urlencode(post))
-        resp = requests.post(post_url)
-        print '\tReceived response', resp, resp.text
-
-        # step 3: paypal send either VERIFIED or INVALID (single word)
-        if resp.text == 'VERIFIED':
-            # _logger.warning('')
-            cr, uid, context = request.cr, request.uid, request.context
-            # payment_transaction = request.registry['payment.transaction']
-            # payment_transaction.validate()
-        elif resp.text == 'INVALID':
-            # _logger.warning('')
-            pass
-        else:
-            # _logger.warning('') -> something went wrong
-            pass
-
-        return ''
-
-    @website.route([
-        '/payment/paypal/test/dpn',
-    ], type='http', auth="public")
-    def paypal_test_success(self, **post):
-        """ TODO
-        """
-        cr, uid, context = request.cr, request.uid, request.context
-        print post
-        return ''
-
-
-class OgoneController(http.Controller):
-    _accept_url = '/payment/ogone/test/accept'
-    _decline_url = '/payment/ogone/test/decline'
-    _exception_url = '/payment/ogone/test/exception'
-    _cancel_url = '/payment/ogone/test/cancel'
-
-    @website.route([
-        '/payment/ogone/feedback', '/payment/ogone/test/accept',
-        '/payment/ogone/decline', '/payment/ogone/test/decline',
-        '/payment/ogone/exception', '/payment/ogone/test/exception',
-        '/payment/ogone/cancel', '/payment/ogone/test/cancel',
-    ], type='http', auth='admin')
-    def feedback(self, **post):
-        cr, uid, context = request.cr, request.uid, request.context
-        Payment = request.registry['payment.transaction']
-        print 'Entering ogone feedback with', post
-
-        res = Payment.tx_ogone_feedback(cr, uid, post, context)
-        print res
-        return ''
+class PaymentController(http.Controller):
+    pass
diff --git a/addons/payment_acquirer/data/__init__.py b/addons/payment_acquirer/data/__init__.py
deleted file mode 100644 (file)
index 61f4cbe..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-# -*- 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
diff --git a/addons/payment_acquirer/data/ogone.py b/addons/payment_acquirer/data/ogone.py
deleted file mode 100644 (file)
index 3a2500e..0000000
+++ /dev/null
@@ -1,497 +0,0 @@
-# -*- coding: utf-8 -*-
-
-OGONE_ERROR_MAP = {
-    '0020001001': "Authorization failed, please retry",
-    '0020001002': "Authorization failed, please retry",
-    '0020001003': "Authorization failed, please retry",
-    '0020001004': "Authorization failed, please retry",
-    '0020001005': "Authorization failed, please retry",
-    '0020001006': "Authorization failed, please retry",
-    '0020001007': "Authorization failed, please retry",
-    '0020001008': "Authorization failed, please retry",
-    '0020001009': "Authorization failed, please retry",
-    '0020001010': "Authorization failed, please retry",
-    '0030001999': "Our payment system is currently under maintenance, please try later",
-    '0050001005': "Expiry date error",
-    '0050001007': "Requested Operation code not allowed",
-    '0050001008': "Invalid delay value",
-    '0050001010': "Input date in invalid format",
-    '0050001013': "Unable to parse socket input stream",
-    '0050001014': "Error in parsing stream content",
-    '0050001015': "Currency error",
-    '0050001016': "Transaction still posted at end of wait",
-    '0050001017': "Sync value not compatible with delay value",
-    '0050001019': "Transaction duplicate of a pre-existing transaction",
-    '0050001020': "Acceptation code empty while required for the transaction",
-    '0050001024': "Maintenance acquirer differs from original transaction acquirer",
-    '0050001025': "Maintenance merchant differs from original transaction merchant",
-    '0050001028': "Maintenance operation not accurate for the original transaction",
-    '0050001031': "Host application unknown for the transaction",
-    '0050001032': "Unable to perform requested operation with requested currency",
-    '0050001033': "Maintenance card number differs from original transaction card number",
-    '0050001034': "Operation code not allowed",
-    '0050001035': "Exception occurred in socket input stream treatment",
-    '0050001036': "Card length does not correspond to an acceptable value for the brand",
-    '0050001036': "Card length does not correspond to an acceptable value for the brand",
-    '0050001068': "A technical problem occurred, please contact helpdesk",
-    '0050001069': "Invalid check for CardID and Brand",
-    '0050001070': "A technical problem occurred, please contact helpdesk",
-    '0050001116': "Unknown origin IP",
-    '0050001117': "No origin IP detected",
-    '0050001118': "Merchant configuration problem, please contact support",
-    '10001001': "Communication failure",
-    '10001002': "Communication failure",
-    '10001003': "Communication failure",
-    '10001004': "Communication failure",
-    '10001005': "Communication failure",
-    '20001001': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.",
-    '20001002': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.",
-    '20001003': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.",
-    '20001004': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.",
-    '20001005': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.",
-    '20001006': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.",
-    '20001007': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.",
-    '20001008': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.",
-    '20001009': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.",
-    '20001010': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.",
-    '20001101': "A technical problem occurred, please contact helpdesk",
-    '20001105': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.",
-    '20001111': "A technical problem occurred, please contact helpdesk",
-    '20002001': "Origin for the response of the bank can not be checked",
-    '20002002': "Beneficiary account number has been modified during processing",
-    '20002003': "Amount has been modified during processing",
-    '20002004': "Currency has been modified during processing",
-    '20002005': "No feedback from the bank server has been detected",
-    '30001001': "Payment refused by the acquirer",
-    '30001002': "Duplicate request",
-    '30001010': "A technical problem occurred, please contact helpdesk",
-    '30001011': "A technical problem occurred, please contact helpdesk",
-    '30001012': "Card black listed - Contact acquirer",
-    '30001015': "Your merchant's acquirer is temporarily unavailable, please try later or choose another payment method.",
-    '30001051': "A technical problem occurred, please contact helpdesk",
-    '30001054': "A technical problem occurred, please contact helpdesk",
-    '30001057': "Your merchant's acquirer is temporarily unavailable, please try later or choose another payment method.",
-    '30001058': "Your merchant's acquirer is temporarily unavailable, please try later or choose another payment method.",
-    '30001060': "Aquirer indicates that a failure occured during payment processing",
-    '30001070': "RATEPAY Invalid Response Type (Failure)",
-    '30001071': "RATEPAY Missing Mandatory status code field (failure)",
-    '30001072': "RATEPAY Missing Mandatory Result code field (failure)",
-    '30001073': "RATEPAY Response parsing Failed",
-    '30001090': "CVC check required by front end and returned invalid by acquirer",
-    '30001091': "ZIP check required by front end and returned invalid by acquirer",
-    '30001092': "Address check required by front end and returned as invalid by acquirer.",
-    '30001100': "Unauthorized buyer's country",
-    '30001101': "IP country <> card country",
-    '30001102': "Number of different countries too high",
-    '30001103': "unauthorized card country",
-    '30001104': "unauthorized ip address country",
-    '30001105': "Anonymous proxy",
-    '30001110': "If the problem persists, please contact Support, or go to paysafecard's card balance page (https://customer.cc.at.paysafecard.com/psccustomer/GetWelcomePanelServlet?language=en) to see when the amount reserved on your card will be available again.",
-    '30001120': "IP address in merchant's black list",
-    '30001130': "BIN in merchant's black list",
-    '30001131': "Wrong BIN for 3xCB",
-    '30001140': "Card in merchant's card blacklist",
-    '30001141': "Email in blacklist",
-    '30001142': "Passenger name in blacklist",
-    '30001143': "Card holder name in blacklist",
-    '30001144': "Passenger name different from owner name",
-    '30001145': "Time to departure too short",
-    '30001149': "Card Configured in Card Supplier Limit for another relation (CSL)",
-    '30001150': "Card not configured in the system for this customer (CSL)",
-    '30001151': "REF1 not allowed for this relationship (Contract number",
-    '30001152': "Card/Supplier Amount limit reached (CSL)",
-    '30001153': "Card not allowed for this supplier (Date out of contract bounds)",
-    '30001154': "You have reached the usage limit allowed",
-    '30001155': "You have reached the usage limit allowed",
-    '30001156': "You have reached the usage limit allowed",
-    '30001157': "Unauthorized IP country for itinerary",
-    '30001158': "email usage limit reached",
-    '30001159': "Unauthorized card country/IP country combination",
-    '30001160': "Postcode in highrisk group",
-    '30001161': "generic blacklist match",
-    '30001162': "Billing Address is a PO Box",
-    '30001180': "maximum scoring reached",
-    '30001997': "Authorization canceled by simulation",
-    '30001998': "A technical problem occurred, please try again.",
-    '30001999': "Your merchant's acquirer is temporarily unavailable, please try later or choose another payment method.",
-    '30002001': "Payment refused by the financial institution",
-    '30002001': "Payment refused by the financial institution",
-    '30021001': "Call acquirer support call number.",
-    '30022001': "Payment must be approved by the acquirer before execution.",
-    '30031001': "Invalid merchant number.",
-    '30041001': "Retain card.",
-    '30051001': "Authorization declined",
-    '30071001': "Retain card - special conditions.",
-    '30121001': "Invalid transaction",
-    '30131001': "Invalid amount",
-    '30131002': "You have reached the total amount allowed",
-    '30141001': "Invalid card number",
-    '30151001': "Unknown acquiring institution.",
-    '30171001': "Payment method cancelled by the buyer",
-    '30171002': "The maximum time allowed is elapsed.",
-    '30191001': "Try again later.",
-    '30201001': "A technical problem occurred, please contact helpdesk",
-    '30301001': "Invalid format",
-    '30311001': "Unknown acquirer ID.",
-    '30331001': "Card expired.",
-    '30341001': "Suspicion of fraud.",
-    '30341002': "Suspicion of fraud (3rdMan)",
-    '30341003': "Suspicion of fraud (Perseuss)",
-    '30341004': "Suspicion of fraud (ETHOCA)",
-    '30381001': "A technical problem occurred, please contact helpdesk",
-    '30401001': "Invalid function.",
-    '30411001': "Lost card.",
-    '30431001': "Stolen card, pick up",
-    '30511001': "Insufficient funds.",
-    '30521001': "No Authorization. Contact the issuer of your card.",
-    '30541001': "Card expired.",
-    '30551001': "Invalid PIN.",
-    '30561001': "Card not in authorizer's database.",
-    '30571001': "Transaction not permitted on card.",
-    '30581001': "Transaction not allowed on this terminal",
-    '30591001': "Suspicion of fraud.",
-    '30601001': "The merchant must contact the acquirer.",
-    '30611001': "Amount exceeds card ceiling.",
-    '30621001': "Restricted card.",
-    '30631001': "Security policy not respected.",
-    '30641001': "Amount changed from ref. trn.",
-    '30681001': "Tardy response.",
-    '30751001': "PIN entered incorrectly too often",
-    '30761001': "Card holder already contesting.",
-    '30771001': "PIN entry required.",
-    '30811001': "Message flow error.",
-    '30821001': "Authorization center unavailable",
-    '30831001': "Authorization center unavailable",
-    '30901001': "Temporary system shutdown.",
-    '30911001': "Acquirer unavailable.",
-    '30921001': "Invalid card type for acquirer.",
-    '30941001': "Duplicate transaction",
-    '30961001': "Processing temporarily not possible",
-    '30971001': "A technical problem occurred, please contact helpdesk",
-    '30981001': "A technical problem occurred, please contact helpdesk",
-    '31011001': "Unknown acceptance code",
-    '31021001': "Invalid currency",
-    '31031001': "Acceptance code missing",
-    '31041001': "Inactive card",
-    '31051001': "Merchant not active",
-    '31061001': "Invalid expiration date",
-    '31071001': "Interrupted host communication",
-    '31081001': "Card refused",
-    '31091001': "Invalid password",
-    '31101001': "Plafond transaction (majoré du bonus) dépassé",
-    '31111001': "Plafond mensuel (majoré du bonus) dépassé",
-    '31121001': "Plafond centre de facturation dépassé",
-    '31131001': "Plafond entreprise dépassé",
-    '31141001': "Code MCC du fournisseur non autorisé pour la carte",
-    '31151001': "Numéro SIRET du fournisseur non autorisé pour la carte",
-    '31161001': "This is not a valid online banking account",
-    '32001004': "A technical problem occurred, please try again.",
-    '34011001': "Bezahlung mit RatePAY nicht möglich.",
-    '39991001': "A technical problem occurred, please contact the helpdesk of your acquirer",
-    '40001001': "A technical problem occurred, please try again.",
-    '40001002': "A technical problem occurred, please try again.",
-    '40001003': "A technical problem occurred, please try again.",
-    '40001004': "A technical problem occurred, please try again.",
-    '40001005': "A technical problem occurred, please try again.",
-    '40001006': "A technical problem occurred, please try again.",
-    '40001007': "A technical problem occurred, please try again.",
-    '40001008': "A technical problem occurred, please try again.",
-    '40001009': "A technical problem occurred, please try again.",
-    '40001010': "A technical problem occurred, please try again.",
-    '40001011': "A technical problem occurred, please contact helpdesk",
-    '40001012': "Your merchant's acquirer is temporarily unavailable, please try later or choose another payment method.",
-    '40001013': "A technical problem occurred, please contact helpdesk",
-    '40001016': "A technical problem occurred, please contact helpdesk",
-    '40001018': "A technical problem occurred, please try again.",
-    '40001019': "Sorry, an error occurred during processing. Please retry the operation (use back button of the browser). If problem persists, contact your merchant's helpdesk.",
-    '40001020': "Sorry, an error occurred during processing. Please retry the operation (use back button of the browser). If problem persists, contact your merchant's helpdesk.",
-    '40001050': "A technical problem occurred, please contact helpdesk",
-    '40001133': "Authentication failed, the signature of your bank access control server is incorrect",
-    '40001134': "Authentication failed, please retry or cancel.",
-    '40001135': "Authentication temporary unavailable, please retry or cancel.",
-    '40001136': "Technical problem with your browser, please retry or cancel",
-    '40001137': "Your bank access control server is temporary unavailable, please retry or cancel",
-    '40001998': "Temporary technical problem. Please retry a little bit later.",
-    '50001001': "Unknown card type",
-    '50001002': "Card number format check failed for given card number.",
-    '50001003': "Merchant data error",
-    '50001004': "Merchant identification missing",
-    '50001005': "Expiry date error",
-    '50001006': "Amount is not a number",
-    '50001007': "A technical problem occurred, please contact helpdesk",
-    '50001008': "A technical problem occurred, please contact helpdesk",
-    '50001009': "A technical problem occurred, please contact helpdesk",
-    '50001010': "A technical problem occurred, please contact helpdesk",
-    '50001011': "Brand not supported for that merchant",
-    '50001012': "A technical problem occurred, please contact helpdesk",
-    '50001013': "A technical problem occurred, please contact helpdesk",
-    '50001014': "A technical problem occurred, please contact helpdesk",
-    '50001015': "Invalid currency code",
-    '50001016': "A technical problem occurred, please contact helpdesk",
-    '50001017': "A technical problem occurred, please contact helpdesk",
-    '50001018': "A technical problem occurred, please contact helpdesk",
-    '50001019': "A technical problem occurred, please contact helpdesk",
-    '50001020': "A technical problem occurred, please contact helpdesk",
-    '50001021': "A technical problem occurred, please contact helpdesk",
-    '50001022': "A technical problem occurred, please contact helpdesk",
-    '50001023': "A technical problem occurred, please contact helpdesk",
-    '50001024': "A technical problem occurred, please contact helpdesk",
-    '50001025': "A technical problem occurred, please contact helpdesk",
-    '50001026': "A technical problem occurred, please contact helpdesk",
-    '50001027': "A technical problem occurred, please contact helpdesk",
-    '50001028': "A technical problem occurred, please contact helpdesk",
-    '50001029': "A technical problem occurred, please contact helpdesk",
-    '50001030': "A technical problem occurred, please contact helpdesk",
-    '50001031': "A technical problem occurred, please contact helpdesk",
-    '50001032': "A technical problem occurred, please contact helpdesk",
-    '50001033': "A technical problem occurred, please contact helpdesk",
-    '50001034': "A technical problem occurred, please contact helpdesk",
-    '50001035': "A technical problem occurred, please contact helpdesk",
-    '50001036': "Card length does not correspond to an acceptable value for the brand",
-    '50001037': "Purchasing card number for a regular merchant",
-    '50001038': "Non Purchasing card for a Purchasing card merchant",
-    '50001039': "Details sent for a non-Purchasing card merchant, please contact helpdesk",
-    '50001040': "Details not sent for a Purchasing card transaction, please contact helpdesk",
-    '50001041': "Payment detail validation failed",
-    '50001042': "Given transactions amounts (tax,discount,shipping,net,etc…) do not compute correctly together",
-    '50001043': "A technical problem occurred, please contact helpdesk",
-    '50001044': "No acquirer configured for this operation",
-    '50001045': "No UID configured for this operation",
-    '50001046': "Operation not allowed for the merchant",
-    '50001047': "A technical problem occurred, please contact helpdesk",
-    '50001048': "A technical problem occurred, please contact helpdesk",
-    '50001049': "A technical problem occurred, please contact helpdesk",
-    '50001050': "A technical problem occurred, please contact helpdesk",
-    '50001051': "A technical problem occurred, please contact helpdesk",
-    '50001052': "A technical problem occurred, please contact helpdesk",
-    '50001053': "A technical problem occurred, please contact helpdesk",
-    '50001054': "Card number incorrect or incompatible",
-    '50001055': "A technical problem occurred, please contact helpdesk",
-    '50001056': "A technical problem occurred, please contact helpdesk",
-    '50001057': "A technical problem occurred, please contact helpdesk",
-    '50001058': "A technical problem occurred, please contact helpdesk",
-    '50001059': "A technical problem occurred, please contact helpdesk",
-    '50001060': "A technical problem occurred, please contact helpdesk",
-    '50001061': "A technical problem occurred, please contact helpdesk",
-    '50001062': "A technical problem occurred, please contact helpdesk",
-    '50001063': "Card Issue Number does not correspond to range or not present",
-    '50001064': "Start Date not valid or not present",
-    '50001066': "Format of CVC code invalid",
-    '50001067': "The merchant is not enrolled for 3D-Secure",
-    '50001068': "The card number or account number (PAN) is invalid",
-    '50001069': "Invalid check for CardID and Brand",
-    '50001070': "The ECI value given is either not supported, or in conflict with other data in the transaction",
-    '50001071': "Incomplete TRN demat",
-    '50001072': "Incomplete PAY demat",
-    '50001073': "No demat APP",
-    '50001074': "Authorisation too old",
-    '50001075': "VERRes was an error message",
-    '50001076': "DCP amount greater than authorisation amount",
-    '50001077': "Details negative amount",
-    '50001078': "Details negative quantity",
-    '50001079': "Could not decode/decompress received PARes (3D-Secure)",
-    '50001080': "Received PARes was an erereor message from ACS (3D-Secure)",
-    '50001081': "Received PARes format was invalid according to the 3DS specifications (3D-Secure)",
-    '50001082': "PAReq/PARes reconciliation failure (3D-Secure)",
-    '50001084': "Maximum amount reached",
-    '50001087': "The transaction type requires authentication, please check with your bank.",
-    '50001090': "CVC missing at input, but CVC check asked",
-    '50001091': "ZIP missing at input, but ZIP check asked",
-    '50001092': "Address missing at input, but Address check asked",
-    '50001095': "Invalid date of birth",
-    '50001096': "Invalid commodity code",
-    '50001097': "The requested currency and brand are incompatible.",
-    '50001111': "Data validation error",
-    '50001113': "This order has already been processed",
-    '50001114': "Error pre-payment check page access",
-    '50001115': "Request not received in secure mode",
-    '50001116': "Unknown IP address origin",
-    '50001117': "NO IP address origin",
-    '50001118': "Pspid not found or not correct",
-    '50001119': "Password incorrect or disabled due to numbers of errors",
-    '50001120': "Invalid currency",
-    '50001121': "Invalid number of decimals for the currency",
-    '50001122': "Currency not accepted by the merchant",
-    '50001123': "Card type not active",
-    '50001124': "Number of lines don't match with number of payments",
-    '50001125': "Format validation error",
-    '50001126': "Overflow in data capture requests for the original order",
-    '50001127': "The original order is not in a correct status",
-    '50001128': "missing authorization code for unauthorized order",
-    '50001129': "Overflow in refunds requests",
-    '50001130': "Error access to original order",
-    '50001131': "Error access to original history item",
-    '50001132': "The Selected Catalog is empty",
-    '50001133': "Duplicate request",
-    '50001134': "Authentication failed, please retry or cancel.",
-    '50001135': "Authentication temporary unavailable, please retry or cancel.",
-    '50001136': "Technical problem with your browser, please retry or cancel",
-    '50001137': "Your bank access control server is temporary unavailable, please retry or cancel",
-    '50001150': "Fraud Detection, Technical error (IP not valid)",
-    '50001151': "Fraud detection : technical error (IPCTY unknown or error)",
-    '50001152': "Fraud detection : technical error (CCCTY unknown or error)",
-    '50001153': "Overflow in redo-authorisation requests",
-    '50001170': "Dynamic BIN check failed",
-    '50001171': "Dynamic country check failed",
-    '50001172': "Error in Amadeus signature",
-    '50001174': "Card Holder Name is too long",
-    '50001175': "Name contains invalid characters",
-    '50001176': "Card number is too long",
-    '50001177': "Card number contains non-numeric info",
-    '50001178': "Card Number Empty",
-    '50001179': "CVC too long",
-    '50001180': "CVC contains non-numeric info",
-    '50001181': "Expiration date contains non-numeric info",
-    '50001182': "Invalid expiration month",
-    '50001183': "Expiration date must be in the future",
-    '50001184': "SHA Mismatch",
-    '50001205': "Missing mandatory fields for billing address.",
-    '50001206': "Missing mandatory field date of birth.",
-    '50001207': "Missing required shopping basket details.",
-    '50001208': "Missing social security number",
-    '50001209': "Invalid country code",
-    '50001210': "Missing yearly salary",
-    '50001211': "Missing gender",
-    '50001212': "Missing email",
-    '50001213': "Missing IP address",
-    '50001214': "Missing part payment campaign ID",
-    '50001215': "Missing invoice number",
-    '50001216': "The alias must be different than the card number",
-    '60000001': "account number unknown",
-    '60000003': "not credited dd-mm-yy",
-    '60000005': "name/number do not correspond",
-    '60000007': "account number blocked",
-    '60000008': "specific direct debit block",
-    '60000009': "account number WKA",
-    '60000010': "administrative reason",
-    '60000011': "account number expired",
-    '60000012': "no direct debit authorisation given",
-    '60000013': "debit not approved",
-    '60000014': "double payment",
-    '60000018': "name/address/city not entered",
-    '60001001': "no original direct debit for revocation",
-    '60001002': "payer’s account number format error",
-    '60001004': "payer’s account at different bank",
-    '60001005': "payee’s account at different bank",
-    '60001006': "payee’s account number format error",
-    '60001007': "payer’s account number blocked",
-    '60001008': "payer’s account number expired",
-    '60001009': "payee’s account number expired",
-    '60001010': "direct debit not possible",
-    '60001011': "creditor payment not possible",
-    '60001012': "payer’s account number unknown WKA-number",
-    '60001013': "payee’s account number unknown WKA-number",
-    '60001014': "impermissible WKA transaction",
-    '60001015': "period for revocation expired",
-    '60001017': "reason for revocation not correct",
-    '60001018': "original run number not numeric",
-    '60001019': "payment ID incorrect",
-    '60001020': "amount not numeric",
-    '60001021': "amount zero not permitted",
-    '60001022': "negative amount not permitted",
-    '60001023': "payer and payee giro account number",
-    '60001025': "processing code (verwerkingscode) incorrect",
-    '60001028': "revocation not permitted",
-    '60001029': "guaranteed direct debit on giro account number",
-    '60001030': "NBC transaction type incorrect",
-    '60001031': "description too large",
-    '60001032': "book account number not issued",
-    '60001034': "book account number incorrect",
-    '60001035': "payer’s account number not numeric",
-    '60001036': "payer’s account number not eleven-proof",
-    '60001037': "payer’s account number not issued",
-    '60001039': "payer’s account number of DNB/BGC/BLA",
-    '60001040': "payee’s account number not numeric",
-    '60001041': "payee’s account number not eleven-proof",
-    '60001042': "payee’s account number not issued",
-    '60001044': "payee’s account number unknown",
-    '60001050': "payee’s name missing",
-    '60001051': "indicate payee’s bank account number instead of 3102",
-    '60001052': "no direct debit contract",
-    '60001053': "amount beyond bounds",
-    '60001054': "selective direct debit block",
-    '60001055': "original run number unknown",
-    '60001057': "payer’s name missing",
-    '60001058': "payee’s account number missing",
-    '60001059': "restore not permitted",
-    '60001060': "bank’s reference (navraaggegeven) missing",
-    '60001061': "BEC/GBK number incorrect",
-    '60001062': "BEC/GBK code incorrect",
-    '60001087': "book account number not numeric",
-    '60001090': "cancelled on request",
-    '60001091': "cancellation order executed",
-    '60001092': "cancelled instead of bended",
-    '60001093': "book account number is a shortened account number",
-    '60001094': "instructing party account number not identical with payer",
-    '60001095': "payee unknown GBK acceptor",
-    '60001097': "instructing party account number not identical with payee",
-    '60001099': "clearing not permitted",
-    '60001101': "payer’s account number not spaces",
-    '60001102': "PAN length not numeric",
-    '60001103': "PAN length outside limits",
-    '60001104': "track number not numeric",
-    '60001105': "track number not valid",
-    '60001106': "PAN sequence number not numeric",
-    '60001107': "domestic PAN not numeric",
-    '60001108': "domestic PAN not eleven-proof",
-    '60001109': "domestic PAN not issued",
-    '60001110': "foreign PAN not numeric",
-    '60001111': "card valid date not numeric",
-    '60001112': "book period number (boekperiodenr) not numeric",
-    '60001113': "transaction number not numeric",
-    '60001114': "transaction time not numeric",
-    '60001115': "transaction no valid time",
-    '60001116': "transaction date not numeric",
-    '60001117': "transaction no valid date",
-    '60001118': "STAN not numeric",
-    '60001119': "instructing party’s name missing",
-    '60001120': "foreign amount (bedrag-vv) not numeric",
-    '60001122': "rate (verrekenkoers) not numeric",
-    '60001125': "number of decimals (aantaldecimalen) incorrect",
-    '60001126': "tariff (tarifering) not B/O/S",
-    '60001127': "domestic costs (kostenbinnenland) not numeric",
-    '60001128': "domestic costs (kostenbinnenland) not higher than zero",
-    '60001129': "foreign costs (kostenbuitenland) not numeric",
-    '60001130': "foreign costs (kostenbuitenland) not higher than zero",
-    '60001131': "domestic costs (kostenbinnenland) not zero",
-    '60001132': "foreign costs (kostenbuitenland) not zero",
-    '60001134': "Euro record not fully filled in",
-    '60001135': "Client currency incorrect",
-    '60001136': "Amount NLG not numeric",
-    '60001137': "Amount NLG not higher than zero",
-    '60001138': "Amount NLG not equal to Amount",
-    '60001139': "Amount NLG incorrectly converted",
-    '60001140': "Amount EUR not numeric",
-    '60001141': "Amount EUR not greater than zero",
-    '60001142': "Amount EUR not equal to Amount",
-    '60001143': "Amount EUR incorrectly converted",
-    '60001144': "Client currency not NLG",
-    '60001145': "rate euro-vv (Koerseuro-vv) not numeric",
-    '60001146': "comma rate euro-vv (Kommakoerseuro-vv) incorrect",
-    '60001147': "acceptgiro distributor not valid",
-    '60001148': "Original run number and/or BRN are missing",
-    '60001149': "Amount/Account number/ BRN different",
-    '60001150': "Direct debit already revoked/restored",
-    '60001151': "Direct debit already reversed/revoked/restored",
-    '60001153': "Payer’s account number not known",
-}
-
-DATA_VALIDATION_ERROR = '50001111'
-
-
-def retryable(error):
-    return error in [
-        '0020001001', '0020001002', '0020001003', '0020001004', '0020001005',
-        '0020001006', '0020001007', '0020001008', '0020001009', '0020001010',
-        '30001010', '30001011', '30001015',
-        '30001057', '30001058',
-        '30001998', '30001999',
-        #'30611001',     # amount exceeds card limit
-        '30961001',
-        '40001001', '40001002', '40001003', '40001004', '40001005',
-        '40001006', '40001007', '40001008', '40001009', '40001010',
-        '40001012',
-        '40001018', '40001019', '40001020',
-        '40001134', '40001135', '40001136', '40001137',
-        #'50001174',      # cardholder name too long
-    ]
diff --git a/addons/payment_acquirer/data/ogone.xml b/addons/payment_acquirer/data/ogone.xml
deleted file mode 100644 (file)
index 2288ccc..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-<?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>
diff --git a/addons/payment_acquirer/data/paypal.xml b/addons/payment_acquirer/data/paypal.xml
deleted file mode 100644 (file)
index eab754a..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-<?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>
index fdedec5..0ce2de5 100644 (file)
@@ -20,5 +20,3 @@
 ##############################################################################
 
 import payment_acquirer
-import paypal
-import ogone
diff --git a/addons/payment_acquirer/models/ogone.py b/addons/payment_acquirer/models/ogone.py
deleted file mode 100644 (file)
index 1c7296e..0000000
+++ /dev/null
@@ -1,397 +0,0 @@
-# -*- 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)
diff --git a/addons/payment_acquirer/models/paypal.py b/addons/payment_acquirer/models/paypal.py
deleted file mode 100644 (file)
index 7fbc063..0000000
+++ /dev/null
@@ -1,241 +0,0 @@
-# -*- 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
index ffdb032..8d0bb01 100644 (file)
 #
 ##############################################################################
 
-from . import test_payment_acquirer
-
-checks = [
-    test_payment_acquirer,
-]
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+import common
index a99a5d1..df368f5 100644 (file)
 from openerp.tests import common
 
 
-class TestPaymentAcquirer(common.TransactionCase):
+class PaymentAcquirerCommon(common.TransactionCase):
 
     def setUp(self):
-        super(TestPaymentAcquirer, self).setUp()
+        super(PaymentAcquirerCommon, self).setUp()
         self.payment_acquirer = self.registry('payment.acquirer')
         self.payment_transaction = self.registry('payment.transaction')
 
diff --git a/addons/payment_acquirer/tests/test_payment_acquirer.py b/addons/payment_acquirer/tests/test_payment_acquirer.py
deleted file mode 100644 (file)
index 0de5813..0000000
+++ /dev/null
@@ -1,272 +0,0 @@
-# -*- 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&notify_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&notify_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'
-# }
diff --git a/addons/payment_acquirer/views/ogone.xml b/addons/payment_acquirer/views/ogone.xml
deleted file mode 100644 (file)
index 0945ebf..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-<?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>
diff --git a/addons/payment_acquirer/views/paypal.xml b/addons/payment_acquirer/views/paypal.xml
deleted file mode 100644 (file)
index 105a859..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-<?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>
diff --git a/addons/payment_acquirer_ogone/__init__.py b/addons/payment_acquirer_ogone/__init__.py
new file mode 100644 (file)
index 0000000..dde6f25
--- /dev/null
@@ -0,0 +1,23 @@
+# -*- 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 models
+import controllers
diff --git a/addons/payment_acquirer_ogone/__openerp__.py b/addons/payment_acquirer_ogone/__openerp__.py
new file mode 100644 (file)
index 0000000..9583319
--- /dev/null
@@ -0,0 +1,35 @@
+# -*- 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/>.
+#
+##############################################################################
+
+{
+    'name': 'Ogone Payment Acquirer',
+    'category': 'Hidden',
+    'summary': 'Payment acquirer: Ogone',
+    'version': '0.1',
+    'description': """Ogone Payment Acquirer""",
+    'author': 'OpenERP SA',
+    'depends': ['payment_acquirer'],
+    'data': [
+        'views/ogone.xml',
+        'data/ogone.xml',
+    ],
+    'installable': True,
+}
diff --git a/addons/payment_acquirer_ogone/controllers/__init__.py b/addons/payment_acquirer_ogone/controllers/__init__.py
new file mode 100644 (file)
index 0000000..039d971
--- /dev/null
@@ -0,0 +1 @@
+import main
\ No newline at end of file
diff --git a/addons/payment_acquirer_ogone/controllers/main.py b/addons/payment_acquirer_ogone/controllers/main.py
new file mode 100644 (file)
index 0000000..8633ba3
--- /dev/null
@@ -0,0 +1,53 @@
+# -*- 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.web import http
+from openerp.addons.web.http import request
+# from openerp.addons.payment_acquirer.models.payment_acquirer import ValidationError
+from openerp.addons.website.models import website
+
+import logging
+import requests
+from urllib import urlencode
+
+_logger = logging.getLogger(__name__)
+
+
+class OgoneController(http.Controller):
+    _accept_url = '/payment/ogone/test/accept'
+    _decline_url = '/payment/ogone/test/decline'
+    _exception_url = '/payment/ogone/test/exception'
+    _cancel_url = '/payment/ogone/test/cancel'
+
+    @website.route([
+        '/payment/ogone/feedback', '/payment/ogone/test/accept',
+        '/payment/ogone/decline', '/payment/ogone/test/decline',
+        '/payment/ogone/exception', '/payment/ogone/test/exception',
+        '/payment/ogone/cancel', '/payment/ogone/test/cancel',
+    ], type='http', auth='admin')
+    def feedback(self, **post):
+        cr, uid, context = request.cr, request.uid, request.context
+        Payment = request.registry['payment.transaction']
+        print 'Entering ogone feedback with', post
+
+        res = Payment.tx_ogone_feedback(cr, uid, post, context)
+        print res
+        return ''
diff --git a/addons/payment_acquirer_ogone/data/__init__.py b/addons/payment_acquirer_ogone/data/__init__.py
new file mode 100644 (file)
index 0000000..61f4cbe
--- /dev/null
@@ -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
diff --git a/addons/payment_acquirer_ogone/data/ogone.py b/addons/payment_acquirer_ogone/data/ogone.py
new file mode 100644 (file)
index 0000000..3a2500e
--- /dev/null
@@ -0,0 +1,497 @@
+# -*- coding: utf-8 -*-
+
+OGONE_ERROR_MAP = {
+    '0020001001': "Authorization failed, please retry",
+    '0020001002': "Authorization failed, please retry",
+    '0020001003': "Authorization failed, please retry",
+    '0020001004': "Authorization failed, please retry",
+    '0020001005': "Authorization failed, please retry",
+    '0020001006': "Authorization failed, please retry",
+    '0020001007': "Authorization failed, please retry",
+    '0020001008': "Authorization failed, please retry",
+    '0020001009': "Authorization failed, please retry",
+    '0020001010': "Authorization failed, please retry",
+    '0030001999': "Our payment system is currently under maintenance, please try later",
+    '0050001005': "Expiry date error",
+    '0050001007': "Requested Operation code not allowed",
+    '0050001008': "Invalid delay value",
+    '0050001010': "Input date in invalid format",
+    '0050001013': "Unable to parse socket input stream",
+    '0050001014': "Error in parsing stream content",
+    '0050001015': "Currency error",
+    '0050001016': "Transaction still posted at end of wait",
+    '0050001017': "Sync value not compatible with delay value",
+    '0050001019': "Transaction duplicate of a pre-existing transaction",
+    '0050001020': "Acceptation code empty while required for the transaction",
+    '0050001024': "Maintenance acquirer differs from original transaction acquirer",
+    '0050001025': "Maintenance merchant differs from original transaction merchant",
+    '0050001028': "Maintenance operation not accurate for the original transaction",
+    '0050001031': "Host application unknown for the transaction",
+    '0050001032': "Unable to perform requested operation with requested currency",
+    '0050001033': "Maintenance card number differs from original transaction card number",
+    '0050001034': "Operation code not allowed",
+    '0050001035': "Exception occurred in socket input stream treatment",
+    '0050001036': "Card length does not correspond to an acceptable value for the brand",
+    '0050001036': "Card length does not correspond to an acceptable value for the brand",
+    '0050001068': "A technical problem occurred, please contact helpdesk",
+    '0050001069': "Invalid check for CardID and Brand",
+    '0050001070': "A technical problem occurred, please contact helpdesk",
+    '0050001116': "Unknown origin IP",
+    '0050001117': "No origin IP detected",
+    '0050001118': "Merchant configuration problem, please contact support",
+    '10001001': "Communication failure",
+    '10001002': "Communication failure",
+    '10001003': "Communication failure",
+    '10001004': "Communication failure",
+    '10001005': "Communication failure",
+    '20001001': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.",
+    '20001002': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.",
+    '20001003': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.",
+    '20001004': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.",
+    '20001005': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.",
+    '20001006': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.",
+    '20001007': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.",
+    '20001008': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.",
+    '20001009': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.",
+    '20001010': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.",
+    '20001101': "A technical problem occurred, please contact helpdesk",
+    '20001105': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.",
+    '20001111': "A technical problem occurred, please contact helpdesk",
+    '20002001': "Origin for the response of the bank can not be checked",
+    '20002002': "Beneficiary account number has been modified during processing",
+    '20002003': "Amount has been modified during processing",
+    '20002004': "Currency has been modified during processing",
+    '20002005': "No feedback from the bank server has been detected",
+    '30001001': "Payment refused by the acquirer",
+    '30001002': "Duplicate request",
+    '30001010': "A technical problem occurred, please contact helpdesk",
+    '30001011': "A technical problem occurred, please contact helpdesk",
+    '30001012': "Card black listed - Contact acquirer",
+    '30001015': "Your merchant's acquirer is temporarily unavailable, please try later or choose another payment method.",
+    '30001051': "A technical problem occurred, please contact helpdesk",
+    '30001054': "A technical problem occurred, please contact helpdesk",
+    '30001057': "Your merchant's acquirer is temporarily unavailable, please try later or choose another payment method.",
+    '30001058': "Your merchant's acquirer is temporarily unavailable, please try later or choose another payment method.",
+    '30001060': "Aquirer indicates that a failure occured during payment processing",
+    '30001070': "RATEPAY Invalid Response Type (Failure)",
+    '30001071': "RATEPAY Missing Mandatory status code field (failure)",
+    '30001072': "RATEPAY Missing Mandatory Result code field (failure)",
+    '30001073': "RATEPAY Response parsing Failed",
+    '30001090': "CVC check required by front end and returned invalid by acquirer",
+    '30001091': "ZIP check required by front end and returned invalid by acquirer",
+    '30001092': "Address check required by front end and returned as invalid by acquirer.",
+    '30001100': "Unauthorized buyer's country",
+    '30001101': "IP country <> card country",
+    '30001102': "Number of different countries too high",
+    '30001103': "unauthorized card country",
+    '30001104': "unauthorized ip address country",
+    '30001105': "Anonymous proxy",
+    '30001110': "If the problem persists, please contact Support, or go to paysafecard's card balance page (https://customer.cc.at.paysafecard.com/psccustomer/GetWelcomePanelServlet?language=en) to see when the amount reserved on your card will be available again.",
+    '30001120': "IP address in merchant's black list",
+    '30001130': "BIN in merchant's black list",
+    '30001131': "Wrong BIN for 3xCB",
+    '30001140': "Card in merchant's card blacklist",
+    '30001141': "Email in blacklist",
+    '30001142': "Passenger name in blacklist",
+    '30001143': "Card holder name in blacklist",
+    '30001144': "Passenger name different from owner name",
+    '30001145': "Time to departure too short",
+    '30001149': "Card Configured in Card Supplier Limit for another relation (CSL)",
+    '30001150': "Card not configured in the system for this customer (CSL)",
+    '30001151': "REF1 not allowed for this relationship (Contract number",
+    '30001152': "Card/Supplier Amount limit reached (CSL)",
+    '30001153': "Card not allowed for this supplier (Date out of contract bounds)",
+    '30001154': "You have reached the usage limit allowed",
+    '30001155': "You have reached the usage limit allowed",
+    '30001156': "You have reached the usage limit allowed",
+    '30001157': "Unauthorized IP country for itinerary",
+    '30001158': "email usage limit reached",
+    '30001159': "Unauthorized card country/IP country combination",
+    '30001160': "Postcode in highrisk group",
+    '30001161': "generic blacklist match",
+    '30001162': "Billing Address is a PO Box",
+    '30001180': "maximum scoring reached",
+    '30001997': "Authorization canceled by simulation",
+    '30001998': "A technical problem occurred, please try again.",
+    '30001999': "Your merchant's acquirer is temporarily unavailable, please try later or choose another payment method.",
+    '30002001': "Payment refused by the financial institution",
+    '30002001': "Payment refused by the financial institution",
+    '30021001': "Call acquirer support call number.",
+    '30022001': "Payment must be approved by the acquirer before execution.",
+    '30031001': "Invalid merchant number.",
+    '30041001': "Retain card.",
+    '30051001': "Authorization declined",
+    '30071001': "Retain card - special conditions.",
+    '30121001': "Invalid transaction",
+    '30131001': "Invalid amount",
+    '30131002': "You have reached the total amount allowed",
+    '30141001': "Invalid card number",
+    '30151001': "Unknown acquiring institution.",
+    '30171001': "Payment method cancelled by the buyer",
+    '30171002': "The maximum time allowed is elapsed.",
+    '30191001': "Try again later.",
+    '30201001': "A technical problem occurred, please contact helpdesk",
+    '30301001': "Invalid format",
+    '30311001': "Unknown acquirer ID.",
+    '30331001': "Card expired.",
+    '30341001': "Suspicion of fraud.",
+    '30341002': "Suspicion of fraud (3rdMan)",
+    '30341003': "Suspicion of fraud (Perseuss)",
+    '30341004': "Suspicion of fraud (ETHOCA)",
+    '30381001': "A technical problem occurred, please contact helpdesk",
+    '30401001': "Invalid function.",
+    '30411001': "Lost card.",
+    '30431001': "Stolen card, pick up",
+    '30511001': "Insufficient funds.",
+    '30521001': "No Authorization. Contact the issuer of your card.",
+    '30541001': "Card expired.",
+    '30551001': "Invalid PIN.",
+    '30561001': "Card not in authorizer's database.",
+    '30571001': "Transaction not permitted on card.",
+    '30581001': "Transaction not allowed on this terminal",
+    '30591001': "Suspicion of fraud.",
+    '30601001': "The merchant must contact the acquirer.",
+    '30611001': "Amount exceeds card ceiling.",
+    '30621001': "Restricted card.",
+    '30631001': "Security policy not respected.",
+    '30641001': "Amount changed from ref. trn.",
+    '30681001': "Tardy response.",
+    '30751001': "PIN entered incorrectly too often",
+    '30761001': "Card holder already contesting.",
+    '30771001': "PIN entry required.",
+    '30811001': "Message flow error.",
+    '30821001': "Authorization center unavailable",
+    '30831001': "Authorization center unavailable",
+    '30901001': "Temporary system shutdown.",
+    '30911001': "Acquirer unavailable.",
+    '30921001': "Invalid card type for acquirer.",
+    '30941001': "Duplicate transaction",
+    '30961001': "Processing temporarily not possible",
+    '30971001': "A technical problem occurred, please contact helpdesk",
+    '30981001': "A technical problem occurred, please contact helpdesk",
+    '31011001': "Unknown acceptance code",
+    '31021001': "Invalid currency",
+    '31031001': "Acceptance code missing",
+    '31041001': "Inactive card",
+    '31051001': "Merchant not active",
+    '31061001': "Invalid expiration date",
+    '31071001': "Interrupted host communication",
+    '31081001': "Card refused",
+    '31091001': "Invalid password",
+    '31101001': "Plafond transaction (majoré du bonus) dépassé",
+    '31111001': "Plafond mensuel (majoré du bonus) dépassé",
+    '31121001': "Plafond centre de facturation dépassé",
+    '31131001': "Plafond entreprise dépassé",
+    '31141001': "Code MCC du fournisseur non autorisé pour la carte",
+    '31151001': "Numéro SIRET du fournisseur non autorisé pour la carte",
+    '31161001': "This is not a valid online banking account",
+    '32001004': "A technical problem occurred, please try again.",
+    '34011001': "Bezahlung mit RatePAY nicht möglich.",
+    '39991001': "A technical problem occurred, please contact the helpdesk of your acquirer",
+    '40001001': "A technical problem occurred, please try again.",
+    '40001002': "A technical problem occurred, please try again.",
+    '40001003': "A technical problem occurred, please try again.",
+    '40001004': "A technical problem occurred, please try again.",
+    '40001005': "A technical problem occurred, please try again.",
+    '40001006': "A technical problem occurred, please try again.",
+    '40001007': "A technical problem occurred, please try again.",
+    '40001008': "A technical problem occurred, please try again.",
+    '40001009': "A technical problem occurred, please try again.",
+    '40001010': "A technical problem occurred, please try again.",
+    '40001011': "A technical problem occurred, please contact helpdesk",
+    '40001012': "Your merchant's acquirer is temporarily unavailable, please try later or choose another payment method.",
+    '40001013': "A technical problem occurred, please contact helpdesk",
+    '40001016': "A technical problem occurred, please contact helpdesk",
+    '40001018': "A technical problem occurred, please try again.",
+    '40001019': "Sorry, an error occurred during processing. Please retry the operation (use back button of the browser). If problem persists, contact your merchant's helpdesk.",
+    '40001020': "Sorry, an error occurred during processing. Please retry the operation (use back button of the browser). If problem persists, contact your merchant's helpdesk.",
+    '40001050': "A technical problem occurred, please contact helpdesk",
+    '40001133': "Authentication failed, the signature of your bank access control server is incorrect",
+    '40001134': "Authentication failed, please retry or cancel.",
+    '40001135': "Authentication temporary unavailable, please retry or cancel.",
+    '40001136': "Technical problem with your browser, please retry or cancel",
+    '40001137': "Your bank access control server is temporary unavailable, please retry or cancel",
+    '40001998': "Temporary technical problem. Please retry a little bit later.",
+    '50001001': "Unknown card type",
+    '50001002': "Card number format check failed for given card number.",
+    '50001003': "Merchant data error",
+    '50001004': "Merchant identification missing",
+    '50001005': "Expiry date error",
+    '50001006': "Amount is not a number",
+    '50001007': "A technical problem occurred, please contact helpdesk",
+    '50001008': "A technical problem occurred, please contact helpdesk",
+    '50001009': "A technical problem occurred, please contact helpdesk",
+    '50001010': "A technical problem occurred, please contact helpdesk",
+    '50001011': "Brand not supported for that merchant",
+    '50001012': "A technical problem occurred, please contact helpdesk",
+    '50001013': "A technical problem occurred, please contact helpdesk",
+    '50001014': "A technical problem occurred, please contact helpdesk",
+    '50001015': "Invalid currency code",
+    '50001016': "A technical problem occurred, please contact helpdesk",
+    '50001017': "A technical problem occurred, please contact helpdesk",
+    '50001018': "A technical problem occurred, please contact helpdesk",
+    '50001019': "A technical problem occurred, please contact helpdesk",
+    '50001020': "A technical problem occurred, please contact helpdesk",
+    '50001021': "A technical problem occurred, please contact helpdesk",
+    '50001022': "A technical problem occurred, please contact helpdesk",
+    '50001023': "A technical problem occurred, please contact helpdesk",
+    '50001024': "A technical problem occurred, please contact helpdesk",
+    '50001025': "A technical problem occurred, please contact helpdesk",
+    '50001026': "A technical problem occurred, please contact helpdesk",
+    '50001027': "A technical problem occurred, please contact helpdesk",
+    '50001028': "A technical problem occurred, please contact helpdesk",
+    '50001029': "A technical problem occurred, please contact helpdesk",
+    '50001030': "A technical problem occurred, please contact helpdesk",
+    '50001031': "A technical problem occurred, please contact helpdesk",
+    '50001032': "A technical problem occurred, please contact helpdesk",
+    '50001033': "A technical problem occurred, please contact helpdesk",
+    '50001034': "A technical problem occurred, please contact helpdesk",
+    '50001035': "A technical problem occurred, please contact helpdesk",
+    '50001036': "Card length does not correspond to an acceptable value for the brand",
+    '50001037': "Purchasing card number for a regular merchant",
+    '50001038': "Non Purchasing card for a Purchasing card merchant",
+    '50001039': "Details sent for a non-Purchasing card merchant, please contact helpdesk",
+    '50001040': "Details not sent for a Purchasing card transaction, please contact helpdesk",
+    '50001041': "Payment detail validation failed",
+    '50001042': "Given transactions amounts (tax,discount,shipping,net,etc…) do not compute correctly together",
+    '50001043': "A technical problem occurred, please contact helpdesk",
+    '50001044': "No acquirer configured for this operation",
+    '50001045': "No UID configured for this operation",
+    '50001046': "Operation not allowed for the merchant",
+    '50001047': "A technical problem occurred, please contact helpdesk",
+    '50001048': "A technical problem occurred, please contact helpdesk",
+    '50001049': "A technical problem occurred, please contact helpdesk",
+    '50001050': "A technical problem occurred, please contact helpdesk",
+    '50001051': "A technical problem occurred, please contact helpdesk",
+    '50001052': "A technical problem occurred, please contact helpdesk",
+    '50001053': "A technical problem occurred, please contact helpdesk",
+    '50001054': "Card number incorrect or incompatible",
+    '50001055': "A technical problem occurred, please contact helpdesk",
+    '50001056': "A technical problem occurred, please contact helpdesk",
+    '50001057': "A technical problem occurred, please contact helpdesk",
+    '50001058': "A technical problem occurred, please contact helpdesk",
+    '50001059': "A technical problem occurred, please contact helpdesk",
+    '50001060': "A technical problem occurred, please contact helpdesk",
+    '50001061': "A technical problem occurred, please contact helpdesk",
+    '50001062': "A technical problem occurred, please contact helpdesk",
+    '50001063': "Card Issue Number does not correspond to range or not present",
+    '50001064': "Start Date not valid or not present",
+    '50001066': "Format of CVC code invalid",
+    '50001067': "The merchant is not enrolled for 3D-Secure",
+    '50001068': "The card number or account number (PAN) is invalid",
+    '50001069': "Invalid check for CardID and Brand",
+    '50001070': "The ECI value given is either not supported, or in conflict with other data in the transaction",
+    '50001071': "Incomplete TRN demat",
+    '50001072': "Incomplete PAY demat",
+    '50001073': "No demat APP",
+    '50001074': "Authorisation too old",
+    '50001075': "VERRes was an error message",
+    '50001076': "DCP amount greater than authorisation amount",
+    '50001077': "Details negative amount",
+    '50001078': "Details negative quantity",
+    '50001079': "Could not decode/decompress received PARes (3D-Secure)",
+    '50001080': "Received PARes was an erereor message from ACS (3D-Secure)",
+    '50001081': "Received PARes format was invalid according to the 3DS specifications (3D-Secure)",
+    '50001082': "PAReq/PARes reconciliation failure (3D-Secure)",
+    '50001084': "Maximum amount reached",
+    '50001087': "The transaction type requires authentication, please check with your bank.",
+    '50001090': "CVC missing at input, but CVC check asked",
+    '50001091': "ZIP missing at input, but ZIP check asked",
+    '50001092': "Address missing at input, but Address check asked",
+    '50001095': "Invalid date of birth",
+    '50001096': "Invalid commodity code",
+    '50001097': "The requested currency and brand are incompatible.",
+    '50001111': "Data validation error",
+    '50001113': "This order has already been processed",
+    '50001114': "Error pre-payment check page access",
+    '50001115': "Request not received in secure mode",
+    '50001116': "Unknown IP address origin",
+    '50001117': "NO IP address origin",
+    '50001118': "Pspid not found or not correct",
+    '50001119': "Password incorrect or disabled due to numbers of errors",
+    '50001120': "Invalid currency",
+    '50001121': "Invalid number of decimals for the currency",
+    '50001122': "Currency not accepted by the merchant",
+    '50001123': "Card type not active",
+    '50001124': "Number of lines don't match with number of payments",
+    '50001125': "Format validation error",
+    '50001126': "Overflow in data capture requests for the original order",
+    '50001127': "The original order is not in a correct status",
+    '50001128': "missing authorization code for unauthorized order",
+    '50001129': "Overflow in refunds requests",
+    '50001130': "Error access to original order",
+    '50001131': "Error access to original history item",
+    '50001132': "The Selected Catalog is empty",
+    '50001133': "Duplicate request",
+    '50001134': "Authentication failed, please retry or cancel.",
+    '50001135': "Authentication temporary unavailable, please retry or cancel.",
+    '50001136': "Technical problem with your browser, please retry or cancel",
+    '50001137': "Your bank access control server is temporary unavailable, please retry or cancel",
+    '50001150': "Fraud Detection, Technical error (IP not valid)",
+    '50001151': "Fraud detection : technical error (IPCTY unknown or error)",
+    '50001152': "Fraud detection : technical error (CCCTY unknown or error)",
+    '50001153': "Overflow in redo-authorisation requests",
+    '50001170': "Dynamic BIN check failed",
+    '50001171': "Dynamic country check failed",
+    '50001172': "Error in Amadeus signature",
+    '50001174': "Card Holder Name is too long",
+    '50001175': "Name contains invalid characters",
+    '50001176': "Card number is too long",
+    '50001177': "Card number contains non-numeric info",
+    '50001178': "Card Number Empty",
+    '50001179': "CVC too long",
+    '50001180': "CVC contains non-numeric info",
+    '50001181': "Expiration date contains non-numeric info",
+    '50001182': "Invalid expiration month",
+    '50001183': "Expiration date must be in the future",
+    '50001184': "SHA Mismatch",
+    '50001205': "Missing mandatory fields for billing address.",
+    '50001206': "Missing mandatory field date of birth.",
+    '50001207': "Missing required shopping basket details.",
+    '50001208': "Missing social security number",
+    '50001209': "Invalid country code",
+    '50001210': "Missing yearly salary",
+    '50001211': "Missing gender",
+    '50001212': "Missing email",
+    '50001213': "Missing IP address",
+    '50001214': "Missing part payment campaign ID",
+    '50001215': "Missing invoice number",
+    '50001216': "The alias must be different than the card number",
+    '60000001': "account number unknown",
+    '60000003': "not credited dd-mm-yy",
+    '60000005': "name/number do not correspond",
+    '60000007': "account number blocked",
+    '60000008': "specific direct debit block",
+    '60000009': "account number WKA",
+    '60000010': "administrative reason",
+    '60000011': "account number expired",
+    '60000012': "no direct debit authorisation given",
+    '60000013': "debit not approved",
+    '60000014': "double payment",
+    '60000018': "name/address/city not entered",
+    '60001001': "no original direct debit for revocation",
+    '60001002': "payer’s account number format error",
+    '60001004': "payer’s account at different bank",
+    '60001005': "payee’s account at different bank",
+    '60001006': "payee’s account number format error",
+    '60001007': "payer’s account number blocked",
+    '60001008': "payer’s account number expired",
+    '60001009': "payee’s account number expired",
+    '60001010': "direct debit not possible",
+    '60001011': "creditor payment not possible",
+    '60001012': "payer’s account number unknown WKA-number",
+    '60001013': "payee’s account number unknown WKA-number",
+    '60001014': "impermissible WKA transaction",
+    '60001015': "period for revocation expired",
+    '60001017': "reason for revocation not correct",
+    '60001018': "original run number not numeric",
+    '60001019': "payment ID incorrect",
+    '60001020': "amount not numeric",
+    '60001021': "amount zero not permitted",
+    '60001022': "negative amount not permitted",
+    '60001023': "payer and payee giro account number",
+    '60001025': "processing code (verwerkingscode) incorrect",
+    '60001028': "revocation not permitted",
+    '60001029': "guaranteed direct debit on giro account number",
+    '60001030': "NBC transaction type incorrect",
+    '60001031': "description too large",
+    '60001032': "book account number not issued",
+    '60001034': "book account number incorrect",
+    '60001035': "payer’s account number not numeric",
+    '60001036': "payer’s account number not eleven-proof",
+    '60001037': "payer’s account number not issued",
+    '60001039': "payer’s account number of DNB/BGC/BLA",
+    '60001040': "payee’s account number not numeric",
+    '60001041': "payee’s account number not eleven-proof",
+    '60001042': "payee’s account number not issued",
+    '60001044': "payee’s account number unknown",
+    '60001050': "payee’s name missing",
+    '60001051': "indicate payee’s bank account number instead of 3102",
+    '60001052': "no direct debit contract",
+    '60001053': "amount beyond bounds",
+    '60001054': "selective direct debit block",
+    '60001055': "original run number unknown",
+    '60001057': "payer’s name missing",
+    '60001058': "payee’s account number missing",
+    '60001059': "restore not permitted",
+    '60001060': "bank’s reference (navraaggegeven) missing",
+    '60001061': "BEC/GBK number incorrect",
+    '60001062': "BEC/GBK code incorrect",
+    '60001087': "book account number not numeric",
+    '60001090': "cancelled on request",
+    '60001091': "cancellation order executed",
+    '60001092': "cancelled instead of bended",
+    '60001093': "book account number is a shortened account number",
+    '60001094': "instructing party account number not identical with payer",
+    '60001095': "payee unknown GBK acceptor",
+    '60001097': "instructing party account number not identical with payee",
+    '60001099': "clearing not permitted",
+    '60001101': "payer’s account number not spaces",
+    '60001102': "PAN length not numeric",
+    '60001103': "PAN length outside limits",
+    '60001104': "track number not numeric",
+    '60001105': "track number not valid",
+    '60001106': "PAN sequence number not numeric",
+    '60001107': "domestic PAN not numeric",
+    '60001108': "domestic PAN not eleven-proof",
+    '60001109': "domestic PAN not issued",
+    '60001110': "foreign PAN not numeric",
+    '60001111': "card valid date not numeric",
+    '60001112': "book period number (boekperiodenr) not numeric",
+    '60001113': "transaction number not numeric",
+    '60001114': "transaction time not numeric",
+    '60001115': "transaction no valid time",
+    '60001116': "transaction date not numeric",
+    '60001117': "transaction no valid date",
+    '60001118': "STAN not numeric",
+    '60001119': "instructing party’s name missing",
+    '60001120': "foreign amount (bedrag-vv) not numeric",
+    '60001122': "rate (verrekenkoers) not numeric",
+    '60001125': "number of decimals (aantaldecimalen) incorrect",
+    '60001126': "tariff (tarifering) not B/O/S",
+    '60001127': "domestic costs (kostenbinnenland) not numeric",
+    '60001128': "domestic costs (kostenbinnenland) not higher than zero",
+    '60001129': "foreign costs (kostenbuitenland) not numeric",
+    '60001130': "foreign costs (kostenbuitenland) not higher than zero",
+    '60001131': "domestic costs (kostenbinnenland) not zero",
+    '60001132': "foreign costs (kostenbuitenland) not zero",
+    '60001134': "Euro record not fully filled in",
+    '60001135': "Client currency incorrect",
+    '60001136': "Amount NLG not numeric",
+    '60001137': "Amount NLG not higher than zero",
+    '60001138': "Amount NLG not equal to Amount",
+    '60001139': "Amount NLG incorrectly converted",
+    '60001140': "Amount EUR not numeric",
+    '60001141': "Amount EUR not greater than zero",
+    '60001142': "Amount EUR not equal to Amount",
+    '60001143': "Amount EUR incorrectly converted",
+    '60001144': "Client currency not NLG",
+    '60001145': "rate euro-vv (Koerseuro-vv) not numeric",
+    '60001146': "comma rate euro-vv (Kommakoerseuro-vv) incorrect",
+    '60001147': "acceptgiro distributor not valid",
+    '60001148': "Original run number and/or BRN are missing",
+    '60001149': "Amount/Account number/ BRN different",
+    '60001150': "Direct debit already revoked/restored",
+    '60001151': "Direct debit already reversed/revoked/restored",
+    '60001153': "Payer’s account number not known",
+}
+
+DATA_VALIDATION_ERROR = '50001111'
+
+
+def retryable(error):
+    return error in [
+        '0020001001', '0020001002', '0020001003', '0020001004', '0020001005',
+        '0020001006', '0020001007', '0020001008', '0020001009', '0020001010',
+        '30001010', '30001011', '30001015',
+        '30001057', '30001058',
+        '30001998', '30001999',
+        #'30611001',     # amount exceeds card limit
+        '30961001',
+        '40001001', '40001002', '40001003', '40001004', '40001005',
+        '40001006', '40001007', '40001008', '40001009', '40001010',
+        '40001012',
+        '40001018', '40001019', '40001020',
+        '40001134', '40001135', '40001136', '40001137',
+        #'50001174',      # cardholder name too long
+    ]
diff --git a/addons/payment_acquirer_ogone/data/ogone.xml b/addons/payment_acquirer_ogone/data/ogone.xml
new file mode 100644 (file)
index 0000000..2288ccc
--- /dev/null
@@ -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>
diff --git a/addons/payment_acquirer_ogone/models/__init__.py b/addons/payment_acquirer_ogone/models/__init__.py
new file mode 100644 (file)
index 0000000..61f4cbe
--- /dev/null
@@ -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
diff --git a/addons/payment_acquirer_ogone/models/ogone.py b/addons/payment_acquirer_ogone/models/ogone.py
new file mode 100644 (file)
index 0000000..af7535a
--- /dev/null
@@ -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.models.payment_acquirer import ValidationError
+from openerp.addons.payment_acquirer_ogone.controllers.main import OgoneController
+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)
diff --git a/addons/payment_acquirer_ogone/tests/__init__.py b/addons/payment_acquirer_ogone/tests/__init__.py
new file mode 100644 (file)
index 0000000..2381425
--- /dev/null
@@ -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_ogone
+
+checks = [
+    test_ogone,
+]
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/payment_acquirer_ogone/tests/test_ogone.py b/addons/payment_acquirer_ogone/tests/test_ogone.py
new file mode 100644 (file)
index 0000000..cb34ed1
--- /dev/null
@@ -0,0 +1,190 @@
+# -*- 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.tests.common import PaymentAcquirerCommon
+from openerp.addons.payment_acquirer_ogone.controllers.main import OgoneController
+# from openerp.osv.orm import except_orm
+
+from lxml import objectify
+# import requests
+# import urlparse
+
+
+class BasicPayment(PaymentAcquirerCommon):
+
+    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', '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', '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'
+# }
diff --git a/addons/payment_acquirer_ogone/views/ogone.xml b/addons/payment_acquirer_ogone/views/ogone.xml
new file mode 100644 (file)
index 0000000..0945ebf
--- /dev/null
@@ -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>
diff --git a/addons/payment_acquirer_paypal/__init__.py b/addons/payment_acquirer_paypal/__init__.py
new file mode 100644 (file)
index 0000000..dde6f25
--- /dev/null
@@ -0,0 +1,23 @@
+# -*- 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 models
+import controllers
diff --git a/addons/payment_acquirer_paypal/__openerp__.py b/addons/payment_acquirer_paypal/__openerp__.py
new file mode 100644 (file)
index 0000000..d9ceb1e
--- /dev/null
@@ -0,0 +1,35 @@
+# -*- 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/>.
+#
+##############################################################################
+
+{
+    'name': 'Paypal Payment Acquirer',
+    'category': 'Hidden',
+    'summary': 'Paypal Payment Acquirer',
+    'version': '0.1',
+    'description': """Paypal Payment Acquirer""",
+    'author': 'OpenERP SA',
+    'depends': ['payment_acquirer'],
+    'data': [
+        'views/paypal.xml',
+        'data/paypal.xml',
+    ],
+    'installable': True,
+}
diff --git a/addons/payment_acquirer_paypal/controllers/__init__.py b/addons/payment_acquirer_paypal/controllers/__init__.py
new file mode 100644 (file)
index 0000000..039d971
--- /dev/null
@@ -0,0 +1 @@
+import main
\ No newline at end of file
diff --git a/addons/payment_acquirer_paypal/controllers/main.py b/addons/payment_acquirer_paypal/controllers/main.py
new file mode 100644 (file)
index 0000000..7b9d654
--- /dev/null
@@ -0,0 +1,74 @@
+# -*- 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.web import http
+from openerp.addons.web.http import request
+# from openerp.addons.payment_acquirer.models.payment_acquirer import ValidationError
+from openerp.addons.website.models import website
+
+import logging
+import requests
+from urllib import urlencode
+
+_logger = logging.getLogger(__name__)
+
+
+class PaypalController(http.Controller):
+    _notify_url = '/payment/paypal/ipn/'
+    _return_url = '/payment/paypal/dpn/'
+    _cancel_url = '/payment/paypal/cancel/'
+    # _ipn_url2 = '/payment/paypal/<int:acquirer_id>/ipn/'
+
+    @website.route('/payment/paypal/<int:acquirer_id>/ipn/', type='http', auth='admin')
+    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 ''
+
+        # step 2: POST the complete, unaltered message back to Paypal (preceded by cmd=_notify-validate), with same encoding
+        paypal_url = "https://www.sandbox.paypal.com/cgi-bin/webscr"
+        post_url = '%s?cmd=_notify-validate&%s' % (paypal_url, urlencode(post))
+        resp = requests.post(post_url)
+        print '\tReceived response', resp, resp.text
+
+        # step 3: paypal send either VERIFIED or INVALID (single word)
+        if resp.text == 'VERIFIED':
+            # _logger.warning('')
+            cr, uid, context = request.cr, request.uid, request.context
+            # payment_transaction = request.registry['payment.transaction']
+            # payment_transaction.validate()
+        elif resp.text == 'INVALID':
+            # _logger.warning('')
+            pass
+        else:
+            # _logger.warning('') -> something went wrong
+            pass
+
+        return ''
+
+    @website.route([
+        '/payment/paypal/test/dpn',
+    ], type='http', auth="public")
+    def paypal_test_success(self, **post):
+        """ TODO
+        """
+        cr, uid, context = request.cr, request.uid, request.context
+        print post
+        return ''
diff --git a/addons/payment_acquirer_paypal/data/paypal.xml b/addons/payment_acquirer_paypal/data/paypal.xml
new file mode 100644 (file)
index 0000000..eab754a
--- /dev/null
@@ -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>
diff --git a/addons/payment_acquirer_paypal/models/__init__.py b/addons/payment_acquirer_paypal/models/__init__.py
new file mode 100644 (file)
index 0000000..d89c4a0
--- /dev/null
@@ -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 paypal
diff --git a/addons/payment_acquirer_paypal/models/paypal.py b/addons/payment_acquirer_paypal/models/paypal.py
new file mode 100644 (file)
index 0000000..4211399
--- /dev/null
@@ -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.models.payment_acquirer import ValidationError
+from openerp.addons.payment_acquirer_paypal.controllers.main import PaypalController
+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
diff --git a/addons/payment_acquirer_paypal/tests/__init__.py b/addons/payment_acquirer_paypal/tests/__init__.py
new file mode 100644 (file)
index 0000000..2868b32
--- /dev/null
@@ -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_paypal
+
+checks = [
+    test_paypal,
+]
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/payment_acquirer_paypal/tests/test_paypal.py b/addons/payment_acquirer_paypal/tests/test_paypal.py
new file mode 100644 (file)
index 0000000..bd61749
--- /dev/null
@@ -0,0 +1,112 @@
+# -*- 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.tests.common import PaymentAcquirerCommon
+from openerp.osv.orm import except_orm
+
+from lxml import objectify
+# import requests
+# import urlparse
+
+
+class BasicPayment(PaymentAcquirerCommon):
+
+    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', '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&notify_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&notify_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)
diff --git a/addons/payment_acquirer_paypal/views/paypal.xml b/addons/payment_acquirer_paypal/views/paypal.xml
new file mode 100644 (file)
index 0000000..105a859
--- /dev/null
@@ -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>
index 4368363..05fe44a 100644 (file)
@@ -27,7 +27,7 @@
     'description': """
         """,
     'author': 'OpenERP SA',
-    'depends': ['website', 'payment_acquirer'],
+    'depends': ['website', 'payment_acquirer', 'payment_acquirer_ogone', 'payment_acquirer_paypal'],
     'data': [
         'views/website_payment_templates.xml',
     ],
index 03b045b..924be2e 100644 (file)
@@ -1,42 +1,51 @@
 <?xml version="1.0" encoding="utf-8"?>
 <openerp>
-<data>
+
     <!-- Layout add nav and footer -->
-    <template id="header_footer_custom" inherit_id="website.layout">
-        <xpath expr="//header//ul[@id='top_menu']/li[@name='contactus']" position="before">
-            <li><a t-attf-href="/payment/paypal/test">Test (Paypal)</a></li>
-        </xpath>
-        <xpath expr="//header//ul[@id='top_menu']/li[@name='contactus']" position="before">
-            <li><a t-attf-href="/payment/ogone/test">Test (Ogone)</a></li>
-        </xpath>
-    </template>
+    <data noupdate="0">
+        <record id="menu_paypal_test" model="website.menu">
+            <field name="name">Paypal (Test)</field>
+            <field name="url">/payment/paypal/test</field>
+            <field name="parent_id" ref="website.main_menu"/>
+            <field name="sequence" type="int">50</field>
+        </record>
+    </data>
+    <data noupdate="0">
+        <record id="menu_paypal_ogone" model="website.menu">
+            <field name="name">Ogone (Test)</field>
+            <field name="url">/payment/ogone/test</field>
+            <field name="parent_id" ref="website.main_menu"/>
+            <field name="sequence" type="int">50</field>
+        </record>
+    </data>
 
     <!-- Page --> 
-    <template id="index_paypal" name="Paypal (Test)" page="True">
-        <t t-call="website.layout">
-            <div id="wrap">
-                <div class="container mt16 js_website_blog">
-                    <div class="row">
-                        Paypal payment
-                        <t t-raw="acquirer_form"/>
+    <data>
+        <template id="index_paypal" name="Paypal (Test)" page="True">
+            <t t-call="website.layout">
+                <div id="wrap">
+                    <div class="container mt16 js_website_blog">
+                        <div class="row">
+                            Paypal payment
+                            <t t-raw="acquirer_form"/>
+                        </div>
                     </div>
                 </div>
-            </div>
-        </t>
-    </template>
+            </t>
+        </template>
 
-    <template id="index_ogone" name="Ogone (Test)" page="True">
-        <t t-call="website.layout">
-            <div id="wrap">
-                <div class="container mt16 js_website_blog">
-                    <div class="row">
-                        Ogone payment
-                        <t t-raw="acquirer_form"/>
+        <template id="index_ogone" name="Ogone (Test)" page="True">
+            <t t-call="website.layout">
+                <div id="wrap">
+                    <div class="container mt16 js_website_blog">
+                        <div class="row">
+                            Ogone payment
+                            <t t-raw="acquirer_form"/>
+                        </div>
                     </div>
                 </div>
-            </div>
-        </t>
-    </template>
+            </t>
+        </template>
+    </data>
 
-</data>
 </openerp>