source: main/waeup.ikoba/branches/uli-payments/src/waeup/ikoba/payments/interfaces.py @ 12727

Last change on this file since 12727 was 12726, checked in by uli, 10 years ago

Extend IPayable.

  • Property svn:keywords set to Id
File size: 10.0 KB
Line 
1## $Id: interfaces.py 12726 2015-03-11 09:17:36Z uli $
2##
3## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18import decimal
19from zc.sourcefactory.basic import BasicSourceFactory
20from zope import schema
21from zope.component import getUtilitiesFor
22from zope.container.interfaces import IContainer
23from zope.container.constraints import contains
24from zope.interface import Interface, Attribute
25from waeup.ikoba.interfaces import (
26    IIkobaObject, SimpleIkobaVocabulary, ContextualDictSourceFactoryBase)
27from waeup.ikoba.interfaces import MessageFactory as _
28from waeup.ikoba.payments.currencies import ISO_4217_CURRENCIES_VOCAB
29
30#: Possible states of payments
31STATE_UNPAID = 1
32STATE_PAID = 2
33STATE_FAILED = 4
34
35payment_states = SimpleIkobaVocabulary(
36    (_('Not yet paid'), STATE_UNPAID),
37    (_('Paid'), STATE_PAID),
38    (_('Failed'), STATE_FAILED),
39    )
40
41
42class PaymentGatewayServicesSource(BasicSourceFactory):
43    """A source that lists available payment services.
44
45    Suitable for forms etc. Token and value correspond to the name the
46    respective IPaymentGatewayService utility is registered with.
47    """
48
49    _services = None
50
51    @classmethod
52    def services(cls):
53        """Cache the services registered on startup.
54
55        We assume that services do not change after startup.
56        """
57        if cls._services is None:
58            cls._services = dict(getUtilitiesFor(IPaymentGatewayService))
59        return cls._services
60
61    def getValues(self):
62        """Get payment gateway registration names.
63        """
64        return sorted(PaymentGatewayServicesSource.services().keys())
65
66    def getTitle(self, value):
67        """Get title of the respective service, if it exists.
68        """
69        service = PaymentGatewayServicesSource.services().get(value, None)
70        if service is not None:
71            return service.title
72
73
74class IPaymentGatewayService(Interface):
75    """A financial gateway service.
76
77    Any gateway provider might provide several services. For instance
78    payments by credit card, scratch card, bank transfer, etc. An
79    `IPaymentGatewayService` represents one of those services.
80
81    Payment services are normally registered as a named global
82    utility.
83    """
84    title = schema.TextLine(
85        title=u'Title',
86        description=u'Human readable name of gateway service.',
87        required=True,
88        )
89
90    def create_payment(payer, payment_item_list, payee):
91        """Create a payment.
92
93        For all parameters we expect an object, that implements
94        `IPayer`, `IPaymentItem`, or `IPayee` respectively. If not,
95        then the given objects must be at least adaptable to the
96        respective interface.
97
98        Therfore you can pass in some `Customer` as long as there is
99        some `IPayer` adapter for `Customer` objects defined.
100
101        Returns an `IPayment` object.
102        """
103
104    def next_step(payment_id):
105        """Returns a payment (as context) and a view name.
106
107        May result in (None, None).
108        """
109
110
111class IPaymentGatewayServicesLister(Interface):
112    """A utility that lists all valid payment gateways.
113
114    This is a subset of the available payment methods, as some might
115    be disabled in some site.
116
117    Register your own lister in customized sites!
118    """
119
120
121class PaymentCategorySource(ContextualDictSourceFactoryBase):
122    """A payment category source delivers all categories of payments.
123
124    """
125    #: name of dict to deliver from ikoba utils.
126    DICT_NAME = 'PAYMENT_CATEGORIES'
127
128
129class IPaymentsContainer(IIkobaObject):
130    """A container for all kind of payment objects.
131
132    """
133
134
135class ICreditCard(Interface):
136    """A credit card.
137
138    A credit card is connected to a Payer.
139    """
140    credit_card_id = schema.TextLine(
141        title=u'Internal Credit Card ID',
142        required=True,
143        )
144
145
146class IPayableFinder(Interface):
147    """Finds payables.
148
149    For each type of content you want to make payable, you should
150    define an IPayableFinder that can lookup payables in the
151    site.
152
153    This enables access from payments (which store payable ids only)
154    to arbitrary content objects (for which a payable finder is
155    registered under some name).
156
157    The other way round (getting an id and other relevant data from
158    any content object) is ensured by IPayable adapters.
159    """
160    def get_payable_by_id(item_id):
161        """Get an item by its Id, or none.
162        """
163
164
165class IPaymentItem(Interface):
166    """Something to sell.
167    """
168    item_id = schema.TextLine(
169        title=u'Payment Item ID',
170        required=True,
171        )
172
173    title = schema.TextLine(
174        title=u'Title',
175        description=u'A short title of the good sold.',
176        required=True,
177        default=u'Unnamed'
178        )
179
180    amount = schema.Decimal(
181        title=u'Amount',
182        description=u'Total amount, includung any taxes, fees, etc.',
183        required=True,
184        default=decimal.Decimal('0.00'),
185        )
186
187
188class IPayable(Interface):
189    """Something that can be payed.
190
191    Designed to serve as adapter. IPayables turn arbitrary content
192    objects into something with a standarized interfaces for use with
193    payments.
194
195    While currency is important to tell about the amount currency, the
196    total amount is computed on-demand from payment items.
197    """
198    payable_id = schema.TextLine(
199        title=u'ID of a payable',
200        description=(u'It should be possible to lookup the payable id '
201                     u'by some registered IPayableFinder later on'),
202        required=True,
203        readonly=True,
204        )
205
206    title = schema.TextLine(
207        title=u'Title',
208        description=u'A short description of the payed item.',
209        required=True,
210        default=u'',
211        readonly=True,
212        )
213
214    currency = schema.Choice(
215        title=u'Currency',
216        source=ISO_4217_CURRENCIES_VOCAB,
217        required=True,
218        default='USD',
219        readonly=True,
220        )
221
222    payment_items = schema.Tuple(
223        title=u'Tuple of IPaymentItems.',
224        value_type=schema.Object(
225            title=u'Payment Item',
226            schema=IPaymentItem,
227            ),
228        required=False,
229        default=(),
230        readonly=True,
231        )
232
233
234class IPayment(IContainer, IIkobaObject):
235    """A base representation of payments.
236
237    In a payment, a payer payes someone (the payee) for something, the
238    item to pay.
239
240    We currently support only the case where one payer pays one payee
241    for one item. The item might include taxes, handling,
242    shipping, etc.
243
244    As in RL any payment is actually performed by some financial
245    service provider (like paypal, interswitch, etc.), each of which
246    might provide several types of payments (credit card, scratch
247    card, you name it).
248
249    In Ikoba we call financial service providers 'gateway' and their
250    types of services are handled as gateway types. Therefore PayPal
251    handling a credit card payment is different from PayPal handling a
252    regular PayPal account transaction.
253
254    A payment can be approve()d, which means the act of paying was
255    really performed. It can also fail for any reason, in which case
256    we mark the payment 'failed'.
257    """
258    contains(IPaymentItem)
259
260    payment_id = schema.TextLine(
261        title=u'Payment Identifier',
262        default=None,
263        required=True,
264        )
265
266    payer_id = schema.TextLine(
267        title=u'Payer',
268        default=None,
269        required=True,
270        )
271
272    payee_id = schema.TextLine(
273        title=u'Payee',
274        default=None,
275        required=False,
276        )
277
278    payable_id = schema.TextLine(
279        title=u'ID of item/good being paid',
280        default=None,
281        required=False,
282        )
283
284    gateway_service = schema.Choice(
285        title=u'Payment Gateway',
286        description=u'Payment gateway that handles this transaction.',
287        source=PaymentGatewayServicesSource(),
288        default=None,
289        required=True,
290        )
291
292    state = schema.Choice(
293        title=_(u'Payment State'),
294        default=STATE_UNPAID,
295        vocabulary=payment_states,
296        required=True,
297        )
298
299    creation_date = schema.Datetime(
300        title=_(u'Creation Datetime'),
301        readonly=False,
302        required=False,
303        )
304
305    payment_date = schema.Datetime(
306        title=_(u'Payment Datetime'),
307        required=False,
308        readonly=False,
309        )
310
311    currency = schema.Choice(
312        title=u'Currency',
313        source=ISO_4217_CURRENCIES_VOCAB,
314        required=True,
315        default='USD',
316        )
317
318    amount = Attribute("Sum of amounts of items contained")
319
320    def approve():
321        """Approve a payment.
322
323        The payment was approved and can now be considered payed. This
324        kind of approvement means the final one (in case there are
325        several instances to ask).
326        """
327
328    def mark_failed(reason=None):
329        """Mark the payment as failed.
330
331        A failed payment was canceled due to technical problems,
332        insufficient funds, etc.
333        """
334
335    def add_payment_item(item):
336        """Payments contain payment items.
337
338        Add one
339        """
340
341
342class IPayer(Interface):
343    """A payer.
344    """
345    payer_id = schema.TextLine(
346        title=u'Payer ID',
347        required=True,
348        )
349
350    first_name = schema.TextLine(
351        title=u'First Name',
352        required=True,
353        )
354
355    last_name = schema.TextLine(
356        title=u'Last Name',
357        required=True,
358        )
359
360
361class IPayee(Interface):
362    """A person or institution being paid.
363    """
364    payee_id = schema.TextLine(
365        title=u'Payee ID',
366        required=True
367        )
Note: See TracBrowser for help on using the repository browser.