01f40ddd0944b1ed47a5ab6f8e525dd03c6ac4dc
[odoo/odoo.git] / addons / payment_paypal / tests / test_paypal.py
1 # -*- coding: utf-8 -*-
2
3 from openerp.addons.payment.models.payment_acquirer import ValidationError
4 from openerp.addons.payment.tests.common import PaymentAcquirerCommon
5 from openerp.addons.payment_paypal.controllers.main import PaypalController
6 from openerp.tools import mute_logger
7
8 from lxml import objectify
9 import urlparse
10
11
12 class PaypalCommon(PaymentAcquirerCommon):
13
14     def setUp(self):
15         super(PaypalCommon, self).setUp()
16         cr, uid = self.cr, self.uid
17         self.base_url = self.registry('ir.config_parameter').get_param(cr, uid, 'web.base.url')
18
19         # get the paypal account
20         model, self.paypal_id = self.registry('ir.model.data').get_object_reference(cr, uid, 'payment_paypal', 'payment_acquirer_paypal')
21         # tde+seller@openerp.com - tde+buyer@openerp.com - tde+buyer-it@openerp.com
22
23         # some CC
24         self.amex = (('378282246310005', '123'), ('371449635398431', '123'))
25         self.amex_corporate = (('378734493671000', '123'))
26         self.autralian_bankcard = (('5610591081018250', '123'))
27         self.dinersclub = (('30569309025904', '123'), ('38520000023237', '123'))
28         self.discover = (('6011111111111117', '123'), ('6011000990139424', '123'))
29         self.jcb = (('3530111333300000', '123'), ('3566002020360505', '123'))
30         self.mastercard = (('5555555555554444', '123'), ('5105105105105100', '123'))
31         self.visa = (('4111111111111111', '123'), ('4012888888881881', '123'), ('4222222222222', '123'))
32         self.dankord_pbs = (('76009244561', '123'), ('5019717010103742', '123'))
33         self.switch_polo = (('6331101999990016', '123'))
34
35
36 class PaypalServer2Server(PaypalCommon):
37
38     def test_00_tx_management(self):
39         cr, uid, context = self.cr, self.uid, {}
40         # be sure not to do stupid things
41         paypal = self.payment_acquirer.browse(self.cr, self.uid, self.paypal_id, None)
42         self.assertEqual(paypal.env, 'test', 'test without test env')
43
44         res = self.payment_acquirer._paypal_s2s_get_access_token(cr, uid, [self.paypal_id], context=context)
45         self.assertTrue(res[self.paypal_id] is not False, 'paypal: did not generate access token')
46
47         tx_id = self.payment_transaction.s2s_create(
48             cr, uid, {
49                 'amount': 0.01,
50                 'acquirer_id': self.paypal_id,
51                 'currency_id': self.currency_euro_id,
52                 'reference': 'test_reference',
53                 'partner_id': self.buyer_id,
54             }, {
55                 'number': self.visa[0][0],
56                 'cvc': self.visa[0][1],
57                 'brand': 'visa',
58                 'expiry_mm': 9,
59                 'expiry_yy': 2015,
60             }, context=context
61         )
62
63         tx = self.payment_transaction.browse(cr, uid, tx_id, context=context)
64         self.assertTrue(tx.paypal_txn_id is not False, 'paypal: txn_id should have been set after s2s request')
65
66         self.payment_transaction.write(cr, uid, tx_id, {'paypal_txn_id': False}, context=context)
67
68
69 class PaypalForm(PaypalCommon):
70
71     def test_10_paypal_form_render(self):
72         cr, uid, context = self.cr, self.uid, {}
73         # be sure not to do stupid things
74         self.payment_acquirer.write(cr, uid, self.paypal_id, {'fees_active': False}, context)
75         paypal = self.payment_acquirer.browse(cr, uid, self.paypal_id, context)
76         self.assertEqual(paypal.env, 'test', 'test without test env')
77
78         # ----------------------------------------
79         # Test: button direct rendering
80         # ----------------------------------------
81
82         # render the button
83         res = self.payment_acquirer.render(
84             cr, uid, self.paypal_id,
85             'test_ref0', 0.01, self.currency_euro_id,
86             partner_id=None,
87             partner_values=self.buyer_values,
88             context=context)
89
90         form_values = {
91             'cmd': '_xclick',
92             'business': 'tde+paypal-facilitator@openerp.com',
93             'item_name': 'test_ref0',
94             'item_number': 'test_ref0',
95             'first_name': 'Buyer',
96             'last_name': 'Norbert',
97             'amount': '0.01',
98             'currency_code': 'EUR',
99             'address1': 'Huge Street 2/543',
100             'city': 'Sin City',
101             'zip': '1000',
102             'country': 'Belgium',
103             'email': 'norbert.buyer@example.com',
104             'return': '%s' % urlparse.urljoin(self.base_url, PaypalController._return_url),
105             'notify_url': '%s' % urlparse.urljoin(self.base_url, PaypalController._notify_url),
106             'cancel_return': '%s' % urlparse.urljoin(self.base_url, PaypalController._cancel_url),
107         }
108
109         # check form result
110         tree = objectify.fromstring(res)
111         self.assertEqual(tree.get('action'), 'https://www.sandbox.paypal.com/cgi-bin/webscr', 'paypal: wrong form POST url')
112         for form_input in tree.input:
113             if form_input.get('name') in ['submit']:
114                 continue
115             self.assertEqual(
116                 form_input.get('value'),
117                 form_values[form_input.get('name')],
118                 'paypal: wrong value for input %s: received %s instead of %s' % (form_input.get('name'), form_input.get('value'), form_values[form_input.get('name')])
119             )
120
121     def test_11_paypal_form_with_fees(self):
122         cr, uid, context = self.cr, self.uid, {}
123         # be sure not to do stupid things
124         paypal = self.payment_acquirer.browse(self.cr, self.uid, self.paypal_id, None)
125         self.assertEqual(paypal.env, 'test', 'test without test env')
126
127         # update acquirer: compute fees
128         self.payment_acquirer.write(cr, uid, self.paypal_id, {
129             'fees_active': True,
130             'fees_dom_fixed': 1.0,
131             'fees_dom_var': 0.35,
132             'fees_int_fixed': 1.5,
133             'fees_int_var': 0.50,
134         }, context)
135
136         # render the button
137         res = self.payment_acquirer.render(
138             cr, uid, self.paypal_id,
139             'test_ref0', 12.50, self.currency_euro,
140             partner_id=None,
141             partner_values=self.buyer_values,
142             context=context)
143
144         # check form result
145         handling_found = False
146         tree = objectify.fromstring(res)
147         self.assertEqual(tree.get('action'), 'https://www.sandbox.paypal.com/cgi-bin/webscr', 'paypal: wrong form POST url')
148         for form_input in tree.input:
149             if form_input.get('name') in ['handling']:
150                 handling_found = True
151                 self.assertEqual(form_input.get('value'), '1.56', 'paypal: wrong computed fees')
152         self.assertTrue(handling_found, 'paypal: fees_active did not add handling input in rendered form')
153
154     @mute_logger('openerp.addons.payment_paypal.models.paypal', 'ValidationError')
155     def test_20_paypal_form_management(self):
156         cr, uid, context = self.cr, self.uid, {}
157         # be sure not to do stupid things
158         paypal = self.payment_acquirer.browse(cr, uid, self.paypal_id, context)
159         self.assertEqual(paypal.env, 'test', 'test without test env')
160
161         # typical data posted by paypal after client has successfully paid
162         paypal_post_data = {
163             'protection_eligibility': u'Ineligible',
164             'last_name': u'Poilu',
165             'txn_id': u'08D73520KX778924N',
166             'receiver_email': u'tde+paypal-facilitator@openerp.com',
167             'payment_status': u'Pending',
168             'payment_gross': u'',
169             'tax': u'0.00',
170             'residence_country': u'FR',
171             'address_state': u'Alsace',
172             'payer_status': u'verified',
173             'txn_type': u'web_accept',
174             'address_street': u'Av. de la Pelouse, 87648672 Mayet',
175             'handling_amount': u'0.00',
176             'payment_date': u'03:21:19 Nov 18, 2013 PST',
177             'first_name': u'Norbert',
178             'item_name': u'test_ref_2',
179             'address_country': u'France',
180             'charset': u'windows-1252',
181             'custom': u'',
182             'notify_version': u'3.7',
183             'address_name': u'Norbert Poilu',
184             'pending_reason': u'multi_currency',
185             'item_number': u'test_ref_2',
186             'receiver_id': u'DEG7Z7MYGT6QA',
187             'transaction_subject': u'',
188             'business': u'tde+paypal-facilitator@openerp.com',
189             'test_ipn': u'1',
190             'payer_id': u'VTDKRZQSAHYPS',
191             'verify_sign': u'An5ns1Kso7MWUdW4ErQKJJJ4qi4-AVoiUf-3478q3vrSmqh08IouiYpM',
192             'address_zip': u'75002',
193             'address_country_code': u'FR',
194             'address_city': u'Paris',
195             'address_status': u'unconfirmed',
196             'mc_currency': u'EUR',
197             'shipping': u'0.00',
198             'payer_email': u'tde+buyer@openerp.com',
199             'payment_type': u'instant',
200             'mc_gross': u'1.95',
201             'ipn_track_id': u'866df2ccd444b',
202             'quantity': u'1'
203         }
204
205         # should raise error about unknown tx
206         with self.assertRaises(ValidationError):
207             self.payment_transaction.form_feedback(cr, uid, paypal_post_data, 'paypal', context=context)
208
209         # create tx
210         tx_id = self.payment_transaction.create(
211             cr, uid, {
212                 'amount': 1.95,
213                 'acquirer_id': self.paypal_id,
214                 'currency_id': self.currency_euro_id,
215                 'reference': 'test_ref_2',
216                 'partner_name': 'Norbert Buyer',
217                 'partner_country_id': self.country_france_id,
218             }, context=context
219         )
220         # validate it
221         self.payment_transaction.form_feedback(cr, uid, paypal_post_data, 'paypal', context=context)
222         # check
223         tx = self.payment_transaction.browse(cr, uid, tx_id, context=context)
224         self.assertEqual(tx.state, 'pending', 'paypal: wrong state after receiving a valid pending notification')
225         self.assertEqual(tx.state_message, 'multi_currency', 'paypal: wrong state message after receiving a valid pending notification')
226         self.assertEqual(tx.paypal_txn_id, '08D73520KX778924N', 'paypal: wrong txn_id after receiving a valid pending notification')
227         self.assertFalse(tx.date_validate, 'paypal: validation date should not be updated whenr receiving pending notification')
228
229         # update tx
230         self.payment_transaction.write(cr, uid, [tx_id], {
231             'state': 'draft',
232             'paypal_txn_id': False,
233         }, context=context)
234         # update notification from paypal
235         paypal_post_data['payment_status'] = 'Completed'
236         # validate it
237         self.payment_transaction.form_feedback(cr, uid, paypal_post_data, 'paypal', context=context)
238         # check
239         tx = self.payment_transaction.browse(cr, uid, tx_id, context=context)
240         self.assertEqual(tx.state, 'done', 'paypal: wrong state after receiving a valid pending notification')
241         self.assertEqual(tx.paypal_txn_id, '08D73520KX778924N', 'paypal: wrong txn_id after receiving a valid pending notification')
242         self.assertEqual(tx.date_validate, '2013-11-18 03:21:19', 'paypal: wrong validation date')