gae-pesapal

Pesapal NDB Model


License
MIT
Install
pip install gae-pesapal==0.0.2

Documentation

GAE Pesapal

This library is meant to automatically kick-off payment status checks once a payment is made.

Install

$ pip install gae-pesapal

Use

import os
from datetime import datetime, date, tzinfo, timedelta

from google.appengine.dist import use_library
use_library('django', '1.2')
os.environ['DJANGO_SETTINGS_MODULE'] = '__init__'

import webapp2 as webapp
from webapp2_extras import sessions
from google.appengine.ext import ndb
from google.appengine.ext import deferred
from google.appengine.ext.webapp import template

from gae_pesapal import pesapal
from gae_pesapal.models import BasePesapalPayment

sessions.default_config['secret_key'] = '-- secret key --'
pesapal.consumer_key = '-- --'
pesapal.consumer_secret = '-- --'
pesapal.testing = False


class Payment(BasePesapalPayment):

    MAX_STATUS_CHECKS = 5 # fails payment after 5 retries

    DEFER_STATUS_CHECK_BY_MINUTES = 30 # checks payment status every half hour

    def check_status(self):

        super(Payment, self).check_status()

        status = self.get_status_string()

        if status == 'pending':
            pass
        elif status == 'completed':
            pass
        elif status == 'failed':
            pass
        elif status == 'invalid':
            pass
        elif status == 'refunded':
            pass
        elif status == 'overdue':
            pass
        else:
            raise


class PayView(webapp.RequestHandler):

    """ View that allows users to pay via pesapal. """

    def dispatch(self):

        self.session_store = sessions.get_store(
            request=self.request
        )

        try:
            webapp.RequestHandler.dispatch(self)
        finally:
            self.session_store.save_sessions(self.response)

    @webapp.cached_property
    def session(self):
        return self.session_store.get_session()

    def get(self):

        transaction_tracking_id = self.request.get(
            'pesapal_transaction_tracking_id'
        )
        merchant_reference = self.request.get(
            'pesapal_merchant_reference'
        )

        # if the request contains the details above, we store the payment in a model otherwise,
        # we display the payment form in an iframe

        if transaction_tracking_id and merchant_reference:

            # store payment details in a model

            ref = self.session.get('pesapal_ref')
            amount = int(self.session.get('pesapal_amount'))

            payment = Payment(
                ref=ref,
                amount=amount,
                transaction_tracking_id=transaction_tracking_id,
                merchant_reference=merchant_reference
            )
            payment.put()

            # start payment status check
            # defer the check if still pending

            payment.check_status()

            del self.session['pesapal_ref']
            del self.session['pesapal_amount']
            
            template_values = {
            }

        else:

            # build payment url and render it to user in an iframe

            amount = '200000'
            desc = 'Xbox purchase'
            ref = Payment.get_ref()
            email = 'me@example.com'

            self.session['pesapal_ref'] = ref
            self.session['pesapal_amount'] = amount

            request_data = {
              'Amount': amount,
              'Description': desc,
              'Reference': ref,
              'Email': email
            }

            oauth_callback = 'http://%s/' % (
                self.request.headers['host'],
            )

            post_params = {
              'oauth_callback': oauth_callback
            }

            src = pesapal.postDirectOrder(
                post_params,
                request_data
            )

            template_values = {
                'src': src,
            }

        path = os.path.join(
                os.path.dirname(__file__), 'template.html'
            )
        self.response.out.write(template.render(path, template_values))


urls = [
    ('/', PayView),
]

app = webapp.WSGIApplication(urls, debug=True)

Example

cp test/conf.sample.yml test/conf.yml # and polutate conf.yml
$ make deps example

Test

$ make deps test