Tag Archives: how to

How to make hello world program in wxPython

In this article we will look at creating a simple hello world program using wxPython. This program will create and display simple window with a big button on it. Up on clicking the button program will exit. Use the following code to create hello world program. You must already have wxPython library installed

Hello world program

import wx

class MainWindow(wx.Frame):
    def __init__(self,parent):
        wx.Frame.__init__(self,parent,title="Hello World")
        self.killButton = wx.Button(self,label="Kill Me")
        self.killButton.Bind(wx.EVT_BUTTON,self.kill)
        self.Show()

    def kill(self,event):
        self.Close()
        print("Bye Bye cruel world")
        
app = wx.App(False)
frame = MainWindow(None)
app.MainLoop()

Explanation

We will go line by line here and try to explain what’s going on in this program. Most of the lines of self explanatory. If you are just getting started in programming the following explanation will be helpful.

  1. Import wxpython library
  2. Inherit from wx.Frame class. This is useful style for most of the programs that you will build. You can create one base frame or window and put rest of GUI widgets on top of it like Text controls, buttons,images, tables etc.
  3. Instantiate the inherited frame the desired title. parent argument is usually None for main windows.
  4. Create a button with label “Kill Me”. The first argument is parent. In this case we use “self” which is the main window we have just created.
  5. Bind the button click event (EVT_BUTTON) of the killButton to kill method. Whenever, EVT_BUTTON event is fired aka the killButton is clicked, kill method will be called.
  6. This line will cause the window to get displayed on screen. It’s customary to call this method after being done with construction of GUI i.e. create main window, place widgets, bind event like we did here.
  7. Create wxPython application by call wx.App. Every wxPython program must have this application.
  8. Start the main loop. Which will hand over control to wxPython library. This post explains why main loop has to be called.

Output

This program will launch the following window. The button takes all the available space on the window since there are no other widgets. You need a few more lines of code to make the button look like what users are used to – small and horizontal. You can exit the program by clicking the button.

How to install wxpython

In this post we will go over the topic of easy way to install wxpython. The following command will install wxpython easily in python3.

pip install wxpython

Python 2

Older versions of wxpython can be installed by downloading binaries (for windows) from sourceforge . The binaries are available for both Windows and MacOS.

Linux

The pip install command should work on linux also. However, if you are stuck on old linux vesions. You can try installing wxpython using your distro’s package manager like apt-get or yum. You can search for exact version and package name available on your platform using the following commands for debian variants.

apt-cache search wxpython

┌──(kali㉿kali)-[~]
└─$ apt-cache search wxpython
gnumed-client - medical practice management - Client
psychopy - environment for creating psychology stimuli in Python
pyscanfcs - scientific tool for perpendicular line scanning FCS
python3-genx - differential evolution algorithm for fitting
python3-opengl - Python bindings to OpenGL (Python 3)
python3-pyface - traits-capable windowing framework
python3-squaremap - wxPython control to display hierarchic data as nested squares
python3-wxgtk-media4.0 - Python 3 interface to the wxWidgets Cross-platform C++ GUI toolkit (wx.media)
python3-wxgtk-webview4.0 - Python 3 interface to the wxWidgets Cross-platform C++ GUI toolkit (wx.html2)
python3-wxgtk4.0 - Python 3 interface to the wxWidgets Cross-platform C++ GUI toolkit
soundgrain - Graphical interface to control granular sound synthesis modules
wxglade - GUI designer written in Python with wxPython
wxpython-tools - Tools from the wxPython distribution

Successful installation

Use the following command to check if the installation is successful or not.

PS C:\Users\godson> python
Python 3.8.6 (tags/v3.8.6:db45529, Sep 23 2020, 15:52:53) [MSC v.1927 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import wx
>>> wx.version()
'4.1.1 msw (phoenix) wxWidgets 3.1.5'
>>>

As shown above it should print current version of wxpython installed if the installation is successful.

A more extensive tutorial is available here

How to find out CPU make and model in Linux

Use the following simple command to find out make and model of CPU/Processor – cat /proc/cpuinfo

┌──(kali㉿kali)-[~]
└─$ cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 94
model name : Intel(R) Core(TM) i7-6700HQ CPU @ 2.60GHz
stepping : 3
cpu MHz : 2591.996
cache size : 6144 KB
physical id : 0
siblings : 1
core id : 0
cpu cores : 1
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level : 22
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid tsc_known_freq pni pclmulqdq monitor ssse3 cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti fsgsbase avx2 invpcid rdseed clflushopt md_clear flush_l1d
bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit srbds
bogomips : 5183.99
clflush size : 64
cache_alignment : 64
address sizes : 39 bits physical, 48 bits virtual
power management:

There are other commands like

lscpu

dmidecode

But, cat /proc/cpuinfo works reliably on all machines.

importContactss

Fetch Contacts From Native Phonebook

Import Contacts In iOS

Contacts are We are going to use built in Contacts.framework to import all contacts in our app. To display a list of contacts, you must have access to the user’s address book. Apple does a great job of protecting the user’s privacy, so you can’t read any of their contacts’ data without asking the user for permission. Similar restrictions apply to access the user’s camera, location, photos, and more.

Whenever we need access to privacy-sensitive information, you are required to specify this in your app’s Info.plist file. This file keeps track of many of your app’s properties, such as its display name, supported interface orientations, and, in the case of accessing a user’s contacts, Info.plist also contains information about why you need access to the user’s contacts.

Let’s go step by step:-

  • Add usage description in Info.plist file for contacts.

Open Plist file and click on plus button to add new row for contact usage description.

Add Privacy – Contacts Usage Description in key

Select Type as String

Write the usage purpose of contacts in your app.

  • Import Contacts Framework in your class.

import Contacts

 

  •  Request for Contact permission

func getAuthStatus() -> CNAuthorizationStatus{

        

        return CNContactStore.authorizationStatus(for: .contacts)

    }

    

    func requestForAccess(_ completionHandler: @escaping (_ accessGrandted: Bool, _ authStatus: CNAuthorizationStatus) -> Void)  {

        

        let authorizationStatus = getAuthStatus()

        

        switch authorizationStatus {

        case .authorized:

            

            completionHandler(true, CNAuthorizationStatus.authorized)

            break

            

        case .notDetermined:

            let store = CNContactStore()

            store.requestAccess(for: .contacts, completionHandler: { (authorized: Bool, error: Error?) in

                

                if authorized {

                    completionHandler(true, CNAuthorizationStatus.authorized)

                }

                else {

                    

                    if self.getAuthStatus() == CNAuthorizationStatus.denied {

                        completionHandler(false, CNAuthorizationStatus.denied)

                    }

                }

            } )

            

            break

            

        case .denied :

            

            completionHandler(false, CNAuthorizationStatus.denied)

            

            break

            

        default:

            completionHandler(false, CNAuthorizationStatus.notDetermined)

            break

        }

    }

 

Above two function will check Contact authorisation status. If not determined it will show alert for contact permission. Keep in mind you can ask Contact permission only once. Once user denied you can just open Setting screen for enable Contact permission.

  • Fetch Contact Using CNContactStore:-

do {

            let store = CNContactStore()

            var results = [CNContact]()

            let containers = try store.containers(matching: nil)

            for container in containers {

                let predicate = CNContact.predicateForContactsInContainer(withIdentifier: container.identifier)

      

                

                let keyToFetch = [CNContactIdentifierKey,

                                  CNContactFormatter.descriptorForRequiredKeys(for: .fullName),

                                  CNContactEmailAddressesKey,

                                  CNContactPhoneNumbersKey,

                                  

                                  CNContactPostalAddressesKey,

                                  CNContactNoteKey,

                                  CNContactOrganizationNameKey] as [Any]

                let contacts = try store.unifiedContacts(matching: predicate, keysToFetch: keyToFetch as! [CNKeyDescriptor])

                results.append(contentsOf: contacts)

            }

return results

            

        }

        catch

        {

            // print("Error1 is \(error)")

            

        }

 

We create a CNContactStore instance and this object is used to communicate directly with the Contacts system on iOS. In this method, we wrap our code in a do-catch statement because two of the methods we use are throwing methods.We can retrieve different values using different Keys like first name, last name, contact image, mobile number, address, emails etc. We then create an array that contains a number of constant keys. These keys directly relate to the information your app has access too.

There is different container Group in Native phonebook. We can retrieve Contacts from different Container according our need. Here we are retrieving contacts of all Groups using store.containers(matching: nil) and iterate it one by one to fetch contacts.

store.unifiedContacts will return array of CNContact which you can store in Your app data or in your app’s database and display contacts In your own tableview Format.

Important:-

In iOS 13, apple have added a new entitlement that is needed if you wish to access the notes for contacts. The entitlement is com.apple.developer.contacts.notes. You can request permission to use this entitlement for an app being put in the App Store.

The reason it was added is primarily for privacy reasons — the notes field can contain any information you might have on the contact; and a lot of times this information is significantly more sensitive than just the contact information.

 

Happy Coding.

Ajax Transparent Redirect

Fusebill AJAX Transparent Redirect

To facilitate PCI compliant credit card collections Fusebill provides a AJAX Transparent Redirect endpoint which you can use to securely capture customer’s credit cards. If you are adding the first payment method on a customer, it will be set to the default payment method automatically.

This API action is authenticated with a separate Public API Key. If you do not have that key, please contact Fusebill Support. The Public Key can only be used to authenticate the Transparent Redirect action.

Ajax Transparent Redirect

Google reCAPTCHA required.

Fusebill leverages reCAPTCHA technology to ensure payment method data captured is provided by a human and to protect against bots and scripting.

We use Google reCAPTCHA V2 in order to accomplish this.
https://developers.google.com/recaptcha/intro
The basic workflow for how this is accomplished is as follows:

  • Using Fusebill’s public site key, the client is presented with a captcha widget.
  • The user then verifies that they are human, starting with a check box. The user may be presented with additional verification steps such as an image recognition task.
  • The captcha widget then verifies with Google that the user is human, and returns a response token.
  • That response token is then sent to Fusebill with the payment method data for our system to validate and verify.
Fusebill Environment
reCAPTCHA Public Site Key

Staging (stg-payments.subscriptionplatform.com)

6LcI_GwUAAAAAJZu0VvB68DdxNxb5ZcBIwAX7RVj

Sandbox and Production (payments.subscriptionplatform.com)

6LfVtGwUAAAAALHn9Ycaig9801f6lrPmouzuKF11

Create Credit Card Payment Method

Field Name
Details
Required
Type

CustomerID

This is the Fusebill customer ID of the customer you wish to add the card to

Yes

Number

PublicAPIKey

This is your public API key.
This is found in fusebill account under Settings > Integrations > Transparent Redirect.

Yes

String

CardNumber

This is the credit card number.

Yes

Number

FirstName

 

The first name of the cardholder.

Yes

String

LastName

The last name of the card holder.

Yes

String

ExpirationMonth

Expiration month on the credit card.

Yes

Number

ExpirationYear

Expiration on the credit card.

Yes

Number

CVV

The credit card verification number.

Yes

Number

recaptcha

Recaptcha token response.

Yes

String

riskToken

WePay Risk token

No+

String

clientIp

Client/Customer IP address

No+

String

email

Customer Email address

No+

String

address1

First line of payment method address.

No*

String

address2

Second line of payment method address.

No*

String

city

City of the payment method

No*

String

stateId

State ID of the Payment method.
These can be found by performing a GET to v1/countries

No*

Number

countryId

Country ID of the payment method.
These can be found by performing a GET to v1/countries

No*

Number

postalZip

PostalZip of the payment method

No*

String

paymentCollectOptions

Object that allows specifying an amount to collect when creating the card.

Only works through Json
{
"collectionAmount": 1.0
}

No

Object

+ Denotes a field required for Fusebill Payments API Risk Fields
* Denotes fields required for AVS and may be required by your account’s Gateway. These fields are also required if using Fusebill Payments accounts as AVS is mandatory.

Notes:- Address information can optionally be captured as well.

Sample Code

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
	<head>
		<title>AJAX Transparent Redirect</title>
		http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js
		
		
		
		
      var verifyCallback = function(response) {
        document.getElementById("mySubmit").disabled = false;
        $('input#recaptcha_token').val(response);
      };
      var expCallback = function () {
        document.getElementById("mySubmit").disabled = true;
        grecaptcha.reset();
      };
      var onloadCallback = function() {
        grecaptcha.render('exampleWithCallback', {
          'sitekey': '',
          'callback': verifyCallback,
          'expired-callback': expCallback
        });
      };
      
			function AJAXTransparentRedirect() {                                 
				var dataString = 'CustomerId='+ $('input#CustomerId').val() + 
						'&PublicApiKey=' + $('input#PublicApiKey').val() + 
						'&SuccessUri='+$('input#SuccessUri').val() +
						'&FailUri='+$('input#FailUri').val() + 
						'&CardNumber='+$('input#CardNumber').val() + 
						'&FirstName='+$('input#FirstName').val() + 
						'&LastName='+$('input#LastName').val() + 
						'&ExpirationMonth='+$('input#ExpirationMonth').val() + 
						'&ExpirationYear='+$('input#ExpirationYear').val() + 
						'&makeDefault='+$('input#MakeDefault').val() + 
						'&Cvv='+$('input#Cvv').val() +
						'&recaptcha=' + $('input#recaptcha_token').val();
				alert(dataString);

				//Set up the request
				var request = $.ajax({
					type: "POST",
					url: "https://stg-payments.subscriptionplatform.com/api/paymentsv2/",                   
					data: dataString 
				});

				//Set up the callback functions
				request.done(function (msg) {
					//$('#response').append("

success

"); alert("success"); //document.location.replace = ''; }); request.fail(function (jqXHR) { // $('#response').append("

failure

"); alert(parseAndBuildErrorMessage(jqXHR)); //document.location.replace = ''; expCallback(); }); } function htmlEscape(msg) { return document.createElement('span') .appendChild(document.createTextNode(msg)) .parentNode .innerHTML; } function buildErrorMessage (errors) { if (errors.length == 0) { return ""; } var message; if (errors.length > 1) { message = "
    "; for (var i = 0; i " + htmlEscape(errors[i].Value) + ""; } } message += "
"; } else { var internalErrors = errors[0].Value; internalErrors = internalErrors.split("\r\n"); if (internalErrors.length > 1) { message = "
    "; for (var i = 0; i " + htmlEscape(internalErrors[i]) + ""; } message += "
"; } } else { message = htmlEscape(errors[0].Value); } } return message; } function parseAndBuildErrorMessage (xhr) { if (xhr.status >= 500) return "An error occurred, please try again"; else return buildErrorMessage(xhr.responseJSON.Errors); } </head> <body> <form id="allfields"> <fieldset> <div> <label for="CustomerId">Customer Id</label> <input autofocus="autofocus" id="CustomerId" name="CustomerId" type="text" value="your customer id here" /> </div> <div> <label for="PublicApiKey">Public Api Key</label> <input id="PublicApiKey" name="PublicApiKey" type="text" value="your key here" /> </div> <div> <label for="CardNumber">Card number</label> <input id="CardNumber" name="CardNumber" type="text" value="4111111111111111" /> </div> <div> <label for="FirstName">First name</label> <input id="FirstName" name="FirstName" type="text" value="John" /> </div> <div> <label for="LastName">Last name</label> <input id="LastName" name="LastName" type="text" value="Doe" /> </div> <div> <label for="ExpirationMonth">Expiry month</label> <input id="ExpirationMonth" name="ExpirationMonth" type="text" value="12" /> </div> <div> <label for="ExpirationYear">Expiry year</label> <input id="ExpirationYear" name="ExpirationYear" type="text" value="20" /> </div> <div> <label for="Cvv">CVV</label> <input id="Cvv" name="Cvv" type="text" value="123" /> </div> <input id="MakeDefault" name="MakeDefault" type="hidden" value="true" /> <div class="g-recaptcha" id="exampleWithCallback"></div> <input id="recaptcha_token" name="recaptcha_token" type="hidden" /> <fieldset> </form> <input type="button" onCLick="AJAXTransparentRedirect();" value="Submit Card" id="mySubmit" disabled /> <div id="response"/> </body> </html> https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit

Sample Response

{
    "maskedCardNumber" : "************1111",
    "cardType" : "Visa",
    "expirationMonth" : 10,
    "expirationYear" : 23,
    "customerId" : 50975,
    "firstName" : "a",
    "lastName" : "a",
    "address1" : null,
    "address2" : null,
    "countryId" : null,
    "country" : "",
    "stateId" : null,
    "state" : "",
    "city" : null,
    "postalZip" : null,
    "makeDefault" : true,
    "id" : 5933,
    "uri" : null
}

Fusebill Payments

When using Fusebill Payments as your gateway processing account, some additional processing and data is required.

These are the ClientIP and a Risk token.

Additional information is available here.

Fusebill Test Gateways

Available here.

How to upload a file in Zoho using python?

UploadFile API Method of Zoho CRM

Table of Contents

  • Purpose
  • Request URL
  • Request Parameters
  • Python Code to Upload a file to a record
  • Sample Response

Purpose

You can use this method to attach files to records.

Request URL

XML Format:
https://crm.zoho.com/crm/private/xml/Leads/uploadFile?authtoken=Auth Token&scope=crmapi&id=Record Id&content=File Input Stream

JSON Format:
https://crm.zoho.com/crm/private/json/Leads/uploadFile?authtoken=Auth Token&scope=crmapi&id=Record Id&content=File Input Stream

Request Parameters

Parameter Data Type Description
authtoken* String Encrypted alphanumeric string to authenticate your Zoho credentials.
scope* String Specify the value as crmapi
id* String Specify unique ID of the “record” or “note” to which the file has to be attached.
content FileInputStream Pass the File Input Stream of the file
attachmentUrl String Attach a URL to a record.

* – Mandatory parameter

Important Note:

  • The total file size should not exceed 20 MB.
  • Your program can request only up to 60 uploadFile calls per min. If API User requests more than 60 calls, system will block the API access for 5 min.
  • If the size exceeds 20 MB, you will receive the following error message: “File size should not exceed 20 MB“. This limit does not apply to URLs attached via attachmentUrl.
  • The attached file will be available under the Attachments section in the Record Details Page.
  • Files can be attached to records in all modules except Reports, Dashboards and Forecasts.
  • In the case of the parameter attachmentUrl, content is not required as the attachment is from a URL.
    Example for attachmentUrl: crm/private/xml/Leads/uploadFile?authtoken=*****&scope=crmapi&id=<entity_id>&attachmentUrl=<insert_ URL>

Python Code to Upload a file to a record

Here’s a simple script that you can use to upload a file in zoho using python.

Go to https://pypi.python.org/pypi/MultipartPostHandler2/0.1.5 and get the egg file and install it.

In the program, you need to specify values for the following:
  • Your Auth Token
  • The ID of the Record
  • The uploadFile Request URL in the format mentioned above
  • The File Path i.e the location of the File
import MultipartPostHandler, urllib2

ID ='put the accounts zoho id here '
authtoken = 'your zoho authtoken here'
fileName = "your file name here - i use the full path and filename"

opener = urllib2.build_opener(MultipartPostHandler.MultipartPostHandler)

params = {'authtoken':authtoken,'scope':'crmapi','newFormat':'1','id':ID, 'content':open(fileName,"rb")}

final_URL = "https://crm.zoho.com/crm/private/json/Accounts/uploadFile"

rslts = opener.open(final_URL, params)

print rslts.read()

Sample Response

{
   "response":{
      "result":{
         "recorddetail":{
            "FL":[
               {
                  "val":"Id",
                  "content":"2211247000000120001"
               },
               {
                  "val":"Created Time",
                  "content":"2016-11-19 14:54:07"
               },
               {
                  "val":"Modified Time",
                  "content":"2016-11-19 14:54:07"
               },
               {
                  "val":"Created By",
                  "content":"mayur"
               },
               {
                  "val":"Modified By",
                  "content":"mayur"
               }
            ]
         },
         "message":"File has been attached successfully"
      },
      "uri":"/crm/private/json/Accounts/uploadFile"
   }
}

 

Twisted Matrix

How to write port-forwarding program using Twisted

Recently I was faced with an issue where a long running process is listening on loop back IP (127.0.0.1) on port 8080 on one of our servers and client programs on other machines are trying to access it on server’s local IP 10.91.20.66.  We ended up at this situation when we have updated server configuration and restarted the server program and forgot to change IP binding info in config file from loop back to local IP. Server got busy with it’s work, with lots of customer’s connections already, by the time we have discovered that some services of  server are not accessible to client programs on other machines. So, the dummy’s guide to fixing it by changing config and restarting the server program is not an option as we can’t risk to disconnect existing customers. So, hot patching is the only option until we can restart the program at next scheduled down time.

I could have fixed this in couple of ways either by adding few lines to iptables configuration or by writing simple socket program in python. The task is to forward data coming in on local IP port 8080 to loop back IP (127.0.0.1) port 8080 and send replies back to source address. Forwarding one socket data to other socket is pretty trivial using Python’s socket library and Twisted made it even more trivial, so I went with the following solution using Twisted.

__author__ = 'godson'

from twisted.protocols.portforward import ProxyFactory
from twisted.application import internet,service

src_ip = "10.91.20.66"
src_port = 8080
dst_ip = "127.0.0.1"
dst_port = 8080

application = service.Application("Proxy")
server = ProxyFactory(dst_ip, dst_port)
ps = internet.TCPServer(src_port,server,50,src_ip)

ps.setServiceParent(application)

That’s it. Now, all I needed to do is to run this program by the following command

twistd -y portforwarder.py

This simple program is made possible by the heavy lifting done by twisted library. Interested folks can look under hood at twisted’s portforward.py module.

How to integrate Celery into Django project

What is Celery?

Celery is a distributed task queue that allows us to execute jobs in background. This article explains how to set up Celery with Django to perform a background task.

Advantages:

  • Large or small, Celery makes scheduling such periodic tasks easy.
  • You never want end users to have to wait unnecessarily for pages to load or actions to complete. If a long process is part of your application’s workflow, you can use Celery to execute that process in the background, as resources become available, so that your application can continue to respond to client requests.

Celery uses brokers to pass messages between a Django Project and the Celery workers. We will use Redis as the message broker.

Installation

Before diving into Celery, follow the below setup points

Create a new virtualenv ‘venv’ using following command:

$ virtualenv venv

To activate the environment use command:

$ source ./venv/bin/activate

Install django and create a django project ‘myproject’. Make sure to activate a virtualenv, create a requirements.txt file and run the migrations. Then fire up the server and navigate to http://localhost:8000/ in your browser. You should see the familiar “Congratulations on your first Django-powered page” text. When done, kill the sever.

Let’s install Celery:

$ pip install celery

$ pip freeze > requirements.txt

Now we will integrate Celery into our Django project with the following steps:

Step 1:

Inside the myproject directory i.e beside your settings.py create a new file called celery.py and add the following code in that:

from __future__ import absolute_import
import os
from celery import Celery
from django.conf import settings

# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
app = Celery('myproject')

# Using a string here means the worker will not have to
# pickle the object when using Windows.
app.config_from_object('django.conf:settings')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)

@app.task(bind=True)
def debug_task(self):
    print('Request: {0!r}'.format(self.request))

Let’s break down what happens in the first module, first we import absolute imports from the future, so that our celery.py module will not clash with the library:

from __future__ import absolute_import

Then we set the default DJANGO_SETTINGS_MODULE for the celery command-line program:

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')

Specifying the settings here means the celery command line program will know where your Django project is. This statement must always appear before the app instance is created, which is what we do next:

app = Celery('myproject')

This is your instance of the library, you can have many instances but there’s probably no reason for that when using Django.

We also add the Django settings module as a configuration source for Celery. This means that you don’t have to use multiple configuration files, and instead configure Celery directly from the Django settings.

You can pass the object directly here, but using a string is better since then the worker doesn’t have to serialize the object when using Windows or execv:

app.config_from_object('django.conf:settings')

Next, a common practice for reusable apps is to define all tasks in a separate tasks.py module, and Celery does have a way to autodiscover these modules:

app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)

Step 2:

To ensure that the Celery app is loaded when Django starts, add the following code into the __init__.py file that sits next to your settings.py file:

from __future__ import absolute_import
# This will make sure the app is always imported when
# Django starts so that shared_task will use this app.

from .celery import app as celery_app

Project layout should look like:

├── manage.py
├── myproject
│   ├── __init__.py
│   ├── celery.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── requirements.txt

Step 3:

Celery uses “brokers” to pass messages between a Django Project and the Celery workers. In this article, we will use Redis as the message broker.

First, install Redis from the official download page and then turn to your terminal, in a new terminal window, fire up the server:

$ redis-server

You can test that Redis is working properly by typing this into your terminal:

$ redis-cli ping

Redis should reply with PONG – try it!

Once Redis is up, add the following code to your settings.py file:

# CELERY STUFF
BROKER_URL = 'redis://localhost:6379'
CELERY_RESULT_BACKEND = 'redis://localhost:6379'
CELERY_ACCEPT_CONTENT = ['application/json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TIMEZONE = 'Africa/Nairobi'

You also need to add Redis as a dependency in the Django Project:

$ pip install redis==2.10.3
$ pip freeze > requirements.txt

Test that the Celery worker is ready to receive tasks:

$ celery -A myproject worker -l info

Kill the process with CTRL-C. Now, test that the Celery task scheduler is ready for action:

$ celery -A myproject beat -l info

That’s it! You can now use Celery with Django. For more information on setting up Celery with Django, please check out the official Celery documentation.

How to implement PayPal payment gateway

The PayPal REST APIs are supported in two environments. Use the Sandbox environment for testing purposes, then move to the live environment for production processing.

The following endpoints address are two environments:

Sandbox (for testing) : https://api.sandbox.paypal.com 
Live (production) : https://api.paypal.com

A complete REST operation is formed by combining an HTTP method with the full URI to the resource you’re addressing. For example, here is the operation to create a new payment:

POST https://api.paypal.com/v1/payments/payment

The PayPal REST sdk can be obtained through pip

pip install paypalrestsdk

OAuth Request / Response

import paypalrestsdk
api = paypalrestsdk.set_config(
       mode="sandbox", # sandbox or live
       client_id="CLIENT_ID",
       client_secret="CLIENT_SECRET")
api.get_access_token()

Client Id and Secret Id can be obtained from the application created in the paypal account.

For the following each API call, you’ll need to set request headers, including the access token.

Creating a WebProfile:

web_profile = WebProfile({
        "name": Web_Profile_Name,
        "presentation": {
            "brand_name": "BusinessName",
            "logo_image": URL to logo image,
            "locale_code": "US"
            },
        "input_fields": {
            "allow_note": 1,
            "no_shipping": 1,
            "address_override": 1
            },
        "flow_config": {
            "landing_page_type": "Login"
            }
    })
web_profile.create(): # Will return True or False
name:

The name of the web experience profile which should be unique among the profiles for a given merchant.

presentation:

It contains the parameters for style and presentation.

input_fields:

Parameters for input fields customization:

  1. allow_note : It enables the buyer to enter a note to the merchant on the paypal page during checkout.

  2. no_shipping : Determines whether or not PayPal displays shipping address fields on the experience pages.

    • 0 – PayPal displays the shipping address on the PayPal pages.
    • 1 – PayPal does not display shipping address fields whatsoever.
    • 2 – If you do not pass the shipping address, PayPal obtains it from the buyer’s account profile.
  3. address_override : Determines if the PayPal pages should display the shipping address supplied in this call, rather than the shipping address on file with PayPal for this buyer.

    • 0 – PayPal pages should display the address on file
    • 1 – PayPal pages should display the addresses supplied in this call instead of the address from the buyer’s PayPal account.
flow_config:

Parameters for flow configuration

  1. landing_page_type : Type of PayPal page to be displayed when a user lands on the PayPal site for checkout.

    • Billing – The Non-PayPal account landing page is used
    • Login – The paypal account login page is used.

Creating a Payment:

payment = Payment({
    "intent": "sale",
    "experience_profile_id": web_profile.id,
    "payer": {
        "payment_method": "paypal",
        "status": "VERIFIED" },
    "redirect_urls": {
        "return_url": RETURN_URL,
        "cancel_url": CANCEL_URL },
    "transactions": [ {
    "amount": {
        "total": amount,
        "currency": "USD" },
        "description": 'description' } ] } )
payment.create(): # Returns True or False

 

intent:

Payment intent. Allowed values are:

  • “sale” – For immediate payment
  • “authorize” – To authorize a payment for capture later
  • “order” – To create an order
experience_profile_id:

Id that will be obtained from the response of web profile request

payer:

Source of the funds for this payment represented by a PayPal account or a credit card.

  • payment_method : Payment method used. Must be either credit_card or paypal.
  • funding_instruments : A list of funding instruments for the current payment
  • payer_info : Information related to the payer
  • status : Status of the payer’s PayPal account. VERIFIED or UNVERIFIED
transactions:

Transactional details including the amount and item details.

redirect_urls:

Set of redirect URLs you provide only for PayPal-based payments.

  • return_url : The payer is redirected to this URL after approving the payment.
  • cancel_url : The payer is redirected to this URL after canceling the payment.

Execute an approved PayPal payment:

Use this call to complete a PayPal payment that has been approved by the payer.

payment = Payment.find("PAY-23456676765ASCASFE45")
payment.execute({ "payer_id": "7D4FDSFWEF5" })

The payment_id and payer_id are passed in the return_url. Once the payment is executed,it returns an array of payment object.

In the response state of the payment is obtained as : created approved failed, canceled, expired or pending.

The transaction details in the response contains state of the sale which is obtained as: pending, completed, refunded or partially_refunded

If the payment state is approved and the sale state is completed, the payment is successfully executed.

How to blink browser tab

Have you ever wished to blink browser tab on certain activity to get user’s attention?

Here is a scenario: Suppose there is a chat application installed on your website. Now what if the user of your website has multiple tabs opened in his browser and there is an incoming message in your website? How will you make your user realize that there is an unread message? Of course you can play some music, but it has some limitations. For instance, user may be listening to some songs or speakers could be muted. If none of them is applicable then also he has to go through each and every single tab in his browser and find out the one which is playing that music.

Visual blinking is the best way to get user’s attention and the easiest way to achieve that is to keep blinking the title of your website until user returns.

Here’s a JavaScript function to do so:

var blinkTab = function(message) {
  var oldTitle = document.title,                                                           /* save original title */
      timeoutId,
      blink = function() { document.title = document.title == message ? ' ' : message; },  /* function to BLINK browser tab */
      clear = function() {                                                                 /* function to set title back to original */
        clearInterval(timeoutId);
        document.title = oldTitle;
        window.onmousemove = null;
        timeoutId = null;
      };

  if (!timeoutId) {
    timeoutId = setInterval(blink, 1000);
    window.onmousemove = clear;                                                            /* stop changing title on moving the mouse */
  }
};

Just execute the function like below and browser tab will start blinking:

blinkTab("your message");