summaryrefslogtreecommitdiffstats
path: root/eopayment/dummy.py
blob: 816d9413d10cfe303329ec26deb06559ac01d592 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
import urllib
import string
import logging
import warnings

def N_(message): return message

try:
    from cgi import parse_qs
except ImportError:
    from urlparse import parse_qs

from common import PaymentCommon, URL, PaymentResponse, PAID, ERROR, ResponseError

__all__ = [ 'Payment' ]

SERVICE_URL = 'http://dummy-payment.demo.entrouvert.com/'
ALPHANUM = string.letters + string.digits
LOGGER = logging.getLogger(__name__)

class Payment(PaymentCommon):
    '''
       Dummy implementation of the payment interface.

       It is used with a dummy implementation of a bank payment service that
       you can find on:

           http://dummy-payment.demo.entrouvert.com/

       You must pass the following keys inside the options dictionnary:
        - dummy_service_url, the URL of the dummy payment service, it defaults
          to the one operated by Entr'ouvert.
        - automatic_return_url: where to POST to notify the service of a
          payment
        - origin: a human string to display to the user about the origin of
          the request.
        - siret: an identifier for the eCommerce site, fake.
        - normal_return_url: the return URL for the user (can be overriden on a
          per request basis).
    '''
    description = {
            'caption': 'Dummy payment backend',
            'parameters': [
                {
                    'name': 'normal_return_url',
                    'caption': N_('Normal return URL'),
                    'default': '',
                    'required': True,
                },
                {
                    'name': 'automatic_return_url',
                    'caption': N_('Automatic return URL'),
                    'required': False,
                },
                {   'name': 'dummy_service_url',
                    'caption': 'URL of the dummy payment service',
                    'default': SERVICE_URL,
                    'type': str,
                },
                {   'name': 'origin',
                    'caption': 'name of the requesting service, '
                               'to present in the user interface',
                    'type': str,

                },
                {   'name': 'siret',
                    'caption': 'dummy siret parameter',
                    'type': str,
                },
                {   'name': 'consider_all_response_signed',
                    'caption': 'All response will be considered as signed '
                         '(to test payment locally for example, as you '
                         'cannot received the signed callback)',
                    'type': bool,
                    'default': False,
                },
                {   'name': 'direct_notification_url',
                    'caption': 'direct notification url (replaced by automatic_return_url)',
                    'type': str,
                    'deprecated': True,
                },
                {   'name': 'next_url (replaced by normal_return_url)',
                    'caption': 'Return URL for the user',
                    'type': str,
                    'deprecated': True,
                },
            ],
    }

    def request(self, amount, name=None, address=None, email=None, phone=None,
            orderid=None, info1=None, info2=None, info3=None, next_url=None, **kwargs):
        self.logger.debug('%s amount %s name %s address %s email %s phone %s'
                ' next_url %s info1 %s info2 %s info3 %s kwargs: %s',
                __name__, amount, name, address, email, phone, info1, info2, info3, next_url, kwargs)
        transaction_id = self.transaction_id(30, ALPHANUM, 'dummy', self.siret)
        normal_return_url = self.normal_return_url
        if next_url and not normal_return_url:
            warnings.warn("passing next_url to request() is deprecated, "
                          "set normal_return_url in options", DeprecationWarning)
            normal_return_url = next_url
        automatic_return_url = self.automatic_return_url
        if self.direct_notification_url and not automatic_return_url:
            warnings.warn("direct_notification_url option is deprecated, "
                          "use automatic_return_url", DeprecationWarning)
            automatic_return_url = self.direct_notification_url
        query = {
                'transaction_id': transaction_id,
                'siret': self.siret,
                'amount': amount,
                'email': email,
                'return_url': normal_return_url or '',
                'direct_notification_url': automatic_return_url or '',
                'origin': self.origin
        }
        query.update(dict(name=name, address=address, email=email, phone=phone,
            orderid=orderid, info1=info1, info2=info2, info3=info3))
        for key in query.keys():
            if query[key] is None:
                del query[key]
        url = '%s?%s' % (SERVICE_URL, urllib.urlencode(query))
        return transaction_id, URL, url

    def response(self, query_string, logger=LOGGER, **kwargs):
        form = parse_qs(query_string)
        if not 'transaction_id' in form:
            raise ResponseError()
        transaction_id = form.get('transaction_id',[''])[0]
        form[self.BANK_ID] = transaction_id

        signed = 'signed' in form
        if signed:
            content = 'signature ok'
        else:
            content = None
        signed = signed or self.consider_all_response_signed
        result = PAID if 'ok' in form else ERROR

        response = PaymentResponse(result=result,
                signed=signed,
                bank_data=form,
                return_content=content,
                order_id=transaction_id,
                transaction_id=transaction_id,
                bank_status=form.get('reason'),
                test=True)
        return response

    def validate(self, amount, bank_data, **kwargs):
        return {}

    def cancel(self, amount, bank_data, **kwargs):
        return {}

if __name__ == '__main__':
    options = {
            'direct_notification_url': 'http://example.com/direct_notification_url',
            'siret': '1234',
            'origin': 'Mairie de Perpette-les-oies'
    }
    p = Payment(options)
    retour = 'http://example.com/retour?amount=10.0&direct_notification_url=http%3A%2F%2Fexample.com%2Fdirect_notification_url&email=toto%40example.com&transaction_id=6Tfw2e1bPyYnz7CedZqvdHt7T9XX6T&return_url=http%3A%2F%2Fexample.com%2Fretour&nok=1'
    r = p.response(retour.split('?',1)[1])
    assert not r[0]
    assert r[1] == '6Tfw2e1bPyYnz7CedZqvdHt7T9XX6T'
    assert r[3] is None
    retour = 'http://example.com/retour?amount=10.0&direct_notification_url=http%3A%2F%2Fexample.com%2Fdirect_notification_url&email=toto%40example.com&transaction_id=6Tfw2e1bPyYnz7CedZqvdHt7T9XX6T&return_url=http%3A%2F%2Fexample.com%2Fretour&ok=1&signed=1'
    r = p.response(retour.split('?',1)[1])
    assert r[0]
    assert r[1] == '6Tfw2e1bPyYnz7CedZqvdHt7T9XX6T'
    assert r[3] == 'signature ok'