source: main/waeup.ikoba/trunk/src/waeup/ikoba/payments/demo_provider.py @ 17664

Last change on this file since 17664 was 12767, checked in by Henrik Bettermann, 10 years ago

Rename templates folder.

  • Property svn:keywords set to Id
File size: 6.2 KB
Line 
1import datetime
2import grok
3import random
4import re
5from zope.event import notify
6from waeup.ikoba.interfaces import MessageFactory as _
7from waeup.ikoba.browser.layout import IkobaEditFormPage, action
8from waeup.ikoba.payments.interfaces import (
9    IPaymentGatewayService, IPayment, IPayable, IPayer, IPayee,
10    STATE_AWAITING_GATEWAY_CONFIRM, STATE_PAID)
11from waeup.ikoba.payments.payment import (
12    Payment, get_payment, find_payable_from_payable_id, format_amount,
13    find_payer_from_payer_id, PaymentProviderServiceBase,
14    PaymentWaitingForGatewayEvent, PaymentFinishedEvent)
15
16
17grok.templatedir('browser_templates')
18
19
20WARN_FINAL_SUBMIT = _(
21    'You can not edit your contract after final submission. '
22    'Do you really want to submit?'
23)
24
25
26RE_CC_NUMBER = re.compile('^[0-9]{9,25}$')
27RE_CSC = re.compile('^[0-9]{3,4}$')
28
29
30class DemoCreditcardPaymentService(PaymentProviderServiceBase):
31    """A demo payment gateway service.
32
33    This one supports credit card payments.
34    """
35    grok.implements(IPaymentGatewayService)
36    grok.name('demo_creditcard')
37
38    title = _(u'Credit Card (Demo Payments)')
39
40    def create_payment(self, payer, payable,  payee=None):
41        """Create a payment.
42        """
43        if not IPayer.providedBy(payer):
44            payer = IPayer(payer)
45        if not IPayable.providedBy(payable):
46            payable = IPayable(payable)
47        if (payee is not None) and (not IPayee.providedBy(payee)):
48            payee = IPayee(payee)
49        payment = Payment(payer, payable, payee)
50        payment.gateway_service = 'demo_creditcard'  # must be grok.name above
51        return payment
52
53    def next_step(self, payment_id):
54        """Tell where to go next.
55
56        Returns (context, view_name). Both may be none.
57        """
58        payment = get_payment(payment_id)
59        if payment is None:
60            return None, None
61        if payment.state == STATE_AWAITING_GATEWAY_CONFIRM:
62            return payment, 'demo_cc2'
63        return payment, 'demo_cc1'
64
65
66class CreditCardStep1(IkobaEditFormPage):
67    grok.context(IPayment)
68    grok.name('demo_cc1')
69    # XXX: Use own permissions for payments
70    grok.require('waeup.Authenticated')
71    label = "Enter Credit Card Details"
72    grok.template('demo_cc_step1')
73    pnav = 4
74
75    def validate_form(self):
76        fields = ['first_name', 'last_name', 'cc_number', 'csc', 'exp_date']
77        cls = 'form-group'
78        if len(self.request.form):
79            cls += ' has-success'
80        result = dict([(x, cls) for x in fields])
81        if not len(self.request.form):
82            return True, result
83        err = 'form-group has-error'
84        if not self.first_name:
85            result['first_name'] = err
86        if not self.last_name:
87            result['last_name'] = err
88        if not RE_CC_NUMBER.match(self.cc_number):
89            result['cc_number'] = err
90        if not RE_CSC.match(self.csc):
91            result['csc'] = err
92        if err in result.values():
93            return False, result
94        return True, result
95
96    def update(self, first_name=None, last_name=None, cc_number=None,
97               month=None, year=None):
98        self.payer = IPayer(find_payer_from_payer_id(self.context.payer_id))
99        self.payable = IPayable(find_payable_from_payable_id(
100            self.context.payable_id))
101        form = self.request.form
102        self.first_name = form.get('first_name', self.payer.first_name)
103        self.last_name = form.get('last_name', self.payer.last_name)
104        self.cc_number = form.get('cc_number', '')
105        self.month = int(form.get('exp_month', datetime.datetime.now().month))
106        self.year = int(form.get('exp_year', datetime.datetime.now().year))
107        self.csc = form.get('csc', '')
108        self.amount = format_amount(
109            self.context.amount, self.context.currency)
110        self.months = ''.join([
111            '<option%s>%s</option>' % (
112                (x == self.month) and ' selected="selected"' or '',
113                x) for x in range(1, 13)])
114        self.years = ''.join([
115            '<option%s>%s</option>' % (
116                (x == self.year + 1) and ' selected="selected"' or '',
117                x) for x in range(self.year - 1, self.year + 15)])
118        self.ok, self.validations = self.validate_form()
119
120    @action(_('Authorize Payment'), warning=WARN_FINAL_SUBMIT,
121            style="primary")
122    def authorize(self, **data):
123        if not self.ok:
124            self.flash(_("Please review (red) entries below!"),
125                       type='warning')
126            return
127        # XXX: payment really started, do lots of logging
128        self.context.state = STATE_AWAITING_GATEWAY_CONFIRM
129        notify(PaymentWaitingForGatewayEvent(self.context))
130        self.redirect(self.url(self.context, 'demo_cc2'))
131        return
132
133    @action(_('Cancel'))
134    def cancel(self, **data):
135        """Go back to the payable (if possible) or site home.
136        """
137        payable_id = getattr(self.context, 'payable_id', '')
138        payed_item = find_payable_from_payable_id(payable_id)
139        self.flash(_("Payment cancelled."))
140        if payed_item is not None:
141            # remove context/payment?
142            target = payed_item
143        else:
144            target = grok.getSite()
145        self.redirect(self.url(target))
146
147
148class CreditCardStep2(IkobaEditFormPage):
149    grok.context(IPayment)
150    grok.name('demo_cc2')
151    # XXX: Use own permissions for payments
152    grok.require('waeup.Authenticated')
153    label = "&nbsp;"
154    grok.template('demo_cc_step2')
155    pnav = 4
156
157    def update(self):
158        cnt = int(self.request.form.get('cnt', '0'))
159        self.cnt = cnt + 1
160        threshold = random.choice(range(10))
161        self.success = False
162        # HERE WOULD WE REALLY ASK FOR VERIFICATION
163        if threshold <= cnt:
164            self.success = True
165            self.flash(_("Your payment was finished successfully."))
166        if self.request.form.get('SUBMIT', None):
167            self.renew()
168
169    def renew(self):
170        if not self.success:
171            return
172        payable_id = getattr(self.context, 'payable_id', '')
173        payed_item = find_payable_from_payable_id(payable_id)
174        self.context.state = STATE_PAID
175        self.context.payment_date = datetime.datetime.utcnow()
176        notify(PaymentFinishedEvent(self.context))
177        self.redirect(self.url(payed_item))
Note: See TracBrowser for help on using the repository browser.