## $Id: browser.py 14759 2017-08-03 09:09:54Z henrik $ ## ## Copyright (C) 2017 Uli Fouquet & Henrik Bettermann ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 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 General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## import grok import hashlib from datetime import datetime, timedelta from zope.component import getUtility, queryUtility from zope.security import checkPermission from waeup.kofa.interfaces import IKofaUtils from waeup.kofa.utils.helpers import to_timezone from waeup.kofa.browser.layout import UtilityView, KofaPage from waeup.kofa.browser.viewlets import ManageActionButton from waeup.kofa.applicants.browser import OnlinePaymentDisplayFormPage as OPDPApplicant #from kofacustom.nigeria.remita.helpers import ( # get_JSON_POST_response, query_remita, write_payments_log) from kofacustom.nigeria.payments.interfaces import INigeriaOnlinePayment from kofacustom.nigeria.applicants.interfaces import INigeriaApplicantOnlinePayment from kofacustom.nigeria.interfaces import MessageFactory as _ from kofacustom.nigeria.paypal import module_activated, Amount, PurchaseUnit from kofacustom.nigeria.paypal.interfaces import IPaypalConfig from kofacustom.nigeria.paypal.rest import create_order, capture_order # grok.templatedir('browser_templates') # Buttons class PaypalActionButtonApplicant(ManageActionButton): grok.order(1) grok.context(INigeriaOnlinePayment) grok.view(OPDPApplicant) grok.require('waeup.payApplicant') icon = 'actionicon_paypal.png' text = _('Pay via Paypal') target = 'goto_paypal' @property def target_url(self): # import pdb; pdb.set_trace() if not module_activated( self.context.__parent__.__parent__.year, self.context): return '' if self.context.p_state != 'unpaid': return '' return self.view.url(self.view.context, self.target) class PaypalRequestPaymentStatusActionButtonApplicant(ManageActionButton): grok.order(2) grok.context(INigeriaOnlinePayment) grok.view(OPDPApplicant) grok.require('waeup.payApplicant') icon = 'actionicon_call.png' text = _('Requery Paypal Payment Status') target = 'capture_paypal_payment' @property def target_url(self): if not module_activated( self.context.__parent__.__parent__.year, self.context): return '' if self.context.p_state in ('paid', 'waived', 'scholarship'): return '' return self.view.url(self.view.context, self.target) class PaypalVerifyPaymentStatusActionButtonApplicant(ManageActionButton): grok.order(3) grok.context(INigeriaOnlinePayment) grok.view(OPDPApplicant) grok.require('waeup.manageApplication') icon = 'actionicon_call.png' text = _('Verify Paypal Payment Status') target = 'verify_payment_status' @property def target_url(self): if not module_activated( self.context.__parent__.__parent__.year, self.context): return '' if self.context.p_state != 'paid' \ or self.context.r_company != u'paypal': return '' return self.view.url(self.view.context, self.target) # Webservice request views class PaypalRequestPaymentStatusPageApplicant(UtilityView, grok.View): """ Capture order created before """ grok.context(INigeriaApplicantOnlinePayment) grok.name('capture_paypal_payment') grok.require('waeup.payApplicant') def update(self): if not module_activated( self.context.__parent__.__parent__.year, self.context): self.flash(_('Forbidden'), type='danger') self.redirect(self.url(self.context, '@@index')) return if self.context.p_state in ('paid', 'waived', 'scholarship'): self.flash(_('This ticket has already been paid.'), type='danger') return response = capture_order(self.context.r_pay_reference) if response.get("status", None) == "COMPLETED": self.context.p_state = u'paid' if self.context.payment_date is None: self.context.payment_date = datetime.utcnow() if not response: self.flash(_('Paypal Order ID not found.'), type='danger') return def render(self): self.redirect(self.url(self.context, '@@index')) return # Forwarding pages class PaypalPageApplicant(KofaPage): """ Create Paypal Order (and send user to paypal) """ grok.context(INigeriaApplicantOnlinePayment) grok.name('goto_paypal') grok.require('waeup.payApplicant') label = _('Pay via Paypal') submit_button = _('Pay now') # Nigerian Naira would be "NGN" but is not supported with # most paypal accounts currency_code = 'USD' @property def action(self): return self.context.r_payment_link def create_paypal_order(self, currency_code): if self.context.r_pay_reference or self.context.p_state == 'paid': return _("Payment ticket can't be re-sent to Paypal.") if self.context.r_company and self.context.r_company != 'paypal': return _("Payment ticket has been used for another payment gateway.") now = datetime.utcnow() if self.context.creation_date.tzinfo is not None: # That's bad. Please store timezone-naive datetimes only! now = self.context.creation_date.tzinfo.localize(now) time_delta = now - self.context.creation_date if time_delta.days > 7: return _("This payment ticket is too old. Please create a new ticket.") # The success url... self.responseurl = self.url(self.context, 'capture_paypal_payment') amount = Amount(value=self.context.amount_auth, currency_code=self.currency_code) purchase_units = [ PurchaseUnit(description=self.context.p_id, amount=amount) ] order_id, payment_link, request_id, data = create_order( purchase_units, self.responseurl, # success/authorized url self.url(self.context), # cancel/failed url notify_url="https://h9.waeup.org/ipn" ) if not order_id: # an error happened... err_msg = " ".join([x["description"] for x in data["details"]]) return _("Paypal order failed: %s") % err_msg self.context.r_payment_link = payment_link self.context.r_pay_reference = order_id self.context.r_company = u'paypal' self.customer = self.context.__parent__ self.customer.writeLogMessage(self, "Paypal Order Created: %s" % ( order_id)) return def update(self): if not module_activated( self.context.__parent__.__parent__.year, self.context): self.flash(_('Forbidden'), type='danger') self.redirect(self.url(self.context, '@@index')) return self.paypal_error = u'' if not self.context.r_payment_link: self.paypal_error = self.create_paypal_order(self.currency_code) if self.paypal_error: self.flash(error, type='danger') self.redirect(self.url(self.context, '@@index')) return # Payment created - it must now be # - authorized (by user) # - captured (by us, afterwards) if not self.context.r_company: self.context.r_company = u'paypal' return def render(self): if self.context.r_payment_link and self.context.p_state != 'paid': self.redirect(self.context.r_payment_link, trusted=True) return self.redirect(self.url(self.context, '@@index'))