| 
 | 1 | +---  | 
 | 2 | +title: Guide to integrate mobile money payments for a Python web app with Notchpay in Cameroon  | 
 | 3 | +date: '2024-09-07'  | 
 | 4 | +tags: ['Payment API', 'Mobile Money', 'Python']  | 
 | 5 | +draft: false  | 
 | 6 | +summary: 3 simple steps to integrate mobile money payment into your Python web application  | 
 | 7 | +images: []  | 
 | 8 | +layout: PostLayout  | 
 | 9 | +canonicalUrl: mobile-money-integration-python-cameroon-2024  | 
 | 10 | +authors: ['nab']  | 
 | 11 | +---  | 
 | 12 | + | 
 | 13 | +This is a translation of an article I wrote in January 2024. In that article, i'm explaining [how to integrate Orange Money or MTN Momo in a python web application](https://peef.dev/post/nasser/comment-integrer-les-paiements-orange-money-ou-mtn-momo-au-cameroun-dans-son-application-avec-python-286).  | 
 | 14 | + | 
 | 15 | +Just for you to know, i wrote that article because i wanted to share with every developer in Cameroon, the steps i did follow to integrate a mobile money payment provider to my [marketplace](https://peef.dev). I found that platform really simple, so, let's get started.  | 
 | 16 | + | 
 | 17 | +[Notchpay](https://notchpay.co/) offers you a way to integrate payment methods into your application and supports card and mobile money payments.  | 
 | 18 | + | 
 | 19 | +The integration is simple:  | 
 | 20 | + | 
 | 21 | +First, create an account on [Notchpay](https://business.notchpay.co/). Your account gives you access to a sandbox that allows you to test the API. In the **settings** (Settings > Developer), you'll find your **API key** (PUBLIC_KEY) that you'll use for authentication in your application.  | 
 | 22 | + | 
 | 23 | +## Initiating payment  | 
 | 24 | + | 
 | 25 | +The [documentation](https://developer.notchpay.co/) already describe all the endpoints you can use, particularly in the [API reference](https://developer.notchpay.co/api/tag/payment) section.  | 
 | 26 | + | 
 | 27 | +In our case, we will use [Flask](https://pypi.org/project/Flask/) to build the controllers and the [Requests](https://pypi.org/project/requests/) library to make requests to Notchpay.  | 
 | 28 | + | 
 | 29 | +Let's first initialize the payment:  | 
 | 30 | + | 
 | 31 | +```python  | 
 | 32 | +def initialize_payment(  | 
 | 33 | +    email, currency, amount, phone, reference, description, callback  | 
 | 34 | +):  | 
 | 35 | +    headers = {"Authorization": PUBLIC_KEY, "Accept": "application/json"}  | 
 | 36 | +    url = "https://api.notchpay.co/payments/initialize"  | 
 | 37 | +    data = {  | 
 | 38 | +        "email": email,  | 
 | 39 | +        "currency": currency,  | 
 | 40 | +        "amount": amount,  | 
 | 41 | +        "phone": phone,  | 
 | 42 | +        "reference": reference,  | 
 | 43 | +        "description": description,  | 
 | 44 | +        "callback": callback,  | 
 | 45 | +    }  | 
 | 46 | + | 
 | 47 | +    response = requests.post(url, headers=headers, data=data)  | 
 | 48 | + | 
 | 49 | +    if response.ok:  | 
 | 50 | +        json_response = response.json()  | 
 | 51 | +        return json_response  | 
 | 52 | +    else:  | 
 | 53 | +        return {"status_code": response.status_code, "msg": response.text}  | 
 | 54 | +```  | 
 | 55 | + | 
 | 56 | +In that function:  | 
 | 57 | + | 
 | 58 | +1. We define the necessary data for the payment as arguments, in the **data** variable,  | 
 | 59 | +2. Then the **header** through which we execute our request. This header contains the API Key  | 
 | 60 | +3. And we return a JSON response.  | 
 | 61 | + | 
 | 62 | +For more information on this payment initiation endpoint and the JSON response, just go to the documentation of that endpoint [/payments/initialize](https://developer.notchpay.co/api/tag/payment/post/payments)  | 
 | 63 | + | 
 | 64 | +Additionally, note that the callback will be a controller on your site that will be called after the payment. You can use it to implement payment verification.  | 
 | 65 | + | 
 | 66 | +- From there, we'll create our controllers: first a simple web page that displays a "Pay Now" link.  | 
 | 67 | +- When this link is clicked, the **pay()** controller is called and will initiate the payment then will do a redirection to the Notchpay payment page:  | 
 | 68 | + | 
 | 69 | +```python  | 
 | 70 | +return redirect(init_payment.get("authorization_url"))  | 
 | 71 | +```  | 
 | 72 | + | 
 | 73 | +- At this point, the Notchpay page dedicated for the payment will be displayed  | 
 | 74 | +- The user can then make his payment via credit card or mobile money phone number  | 
 | 75 | + | 
 | 76 | +```python  | 
 | 77 | +HTML_PAGE = """  | 
 | 78 | +<h1>Process payment</h1>  | 
 | 79 | +<a href="/pay">Pay Now</a>  | 
 | 80 | +"""  | 
 | 81 | + | 
 | 82 | +@app.route("/")  | 
 | 83 | +def home():  | 
 | 84 | +    return HTML_PAGE  | 
 | 85 | + | 
 | 86 | +@app.route("/pay")  | 
 | 87 | +def pay():  | 
 | 88 | +    payment_reference = uuid.uuid1()  | 
 | 89 | +    init_payment = initialize_payment(  | 
 | 90 | + | 
 | 91 | +        currency="XAF",  | 
 | 92 | +        amount="1500",  | 
 | 93 | +        phone=None,  | 
 | 94 | +        reference=payment_reference,  | 
 | 95 | +        description=f"Payment description {payment_reference}",  | 
 | 96 | +        callback=f"http://localhost:5000/verify", # make sure to have the right host  | 
 | 97 | +    )  | 
 | 98 | +    return redirect(init_payment.get("authorization_url"))  | 
 | 99 | +```  | 
 | 100 | + | 
 | 101 | +When the payment is made by the user, it must then be verified through the callback that was passed to the **initialize_payment()** function.  | 
 | 102 | + | 
 | 103 | +## Payment verification  | 
 | 104 | + | 
 | 105 | +Here is the verification function :  | 
 | 106 | + | 
 | 107 | +```python  | 
 | 108 | +def verify_payment(reference):  | 
 | 109 | +    url = f"https://api.notchpay.co/payments/{reference}"  | 
 | 110 | +    headers = {"Authorization": PUBLIC_KEY}  | 
 | 111 | + | 
 | 112 | +    response = requests.get(url, headers=headers)  | 
 | 113 | + | 
 | 114 | +    if response.ok:  | 
 | 115 | +        json_response = response.json()  | 
 | 116 | +        logger.debug(json_response)  | 
 | 117 | +        return json_response  | 
 | 118 | +    else:  | 
 | 119 | +        return {"status_code": response.status_code, "msg": response.text}  | 
 | 120 | +```  | 
 | 121 | + | 
 | 122 | +1. This function takes as parameter the payment reference which is passed in the callback via a **GET** method from Notchpay.  | 
 | 123 | +2. We then construct the header through the URL [/payments/{reference}](https://developer.notchpay.co/reference/payments#verify-and-fetch-payment) for payment verification  | 
 | 124 | +3. and return a JSON response  | 
 | 125 | + | 
 | 126 | +The callback will be the **verify()** controller which will extract the reference and pass this payment reference to the **verify_payment()** function  | 
 | 127 | + | 
 | 128 | +```python  | 
 | 129 | +@app.route("/verify")  | 
 | 130 | +def verify():  | 
 | 131 | +    reference = request.args.get("reference")  | 
 | 132 | +    return verify_payment(reference)  | 
 | 133 | +```  | 
 | 134 | + | 
 | 135 | +From there, you can just retrieve the JSON response to continue your process based on the response (payment failure or success)  | 
 | 136 | + | 
 | 137 | +## Payment verification through a Webhook  | 
 | 138 | + | 
 | 139 | +If you want to verify payments in the background, you can set up a webhook in your backend like this:  | 
 | 140 | + | 
 | 141 | +```python  | 
 | 142 | +@app.route("/webhook", methods=["POST"])  | 
 | 143 | +def webhook():  | 
 | 144 | +    signature = request.headers.get("x-notch-signature")  | 
 | 145 | +    hash_value = hashlib.sha256(HASH_KEY).hexdigest()  | 
 | 146 | +    if hash_value == signature:  | 
 | 147 | +        try:  | 
 | 148 | +            json_data = request.get_json()  | 
 | 149 | +            logger.info("Webhook data:", json_data)  | 
 | 150 | +            return "", 200  # OK  | 
 | 151 | +        except Exception as e:  | 
 | 152 | +            logger.info("Error parsing JSON:", e)  | 
 | 153 | +            abort(400)  # Bad request  | 
 | 154 | +    else:  | 
 | 155 | +        logger.info("Webhook request could not be verified.")  | 
 | 156 | +        abort(403)  # Forbidden  | 
 | 157 | +```  | 
 | 158 | + | 
 | 159 | +Notchpay will then send the response of each payment to your webhook and depending on the result, you can continue your process, such as validating an order for example.  | 
 | 160 | + | 
 | 161 | +If you're on localhost, you'll need to install [Ngrok](https://ngrok.com/) to make your URL public and go to the Notchpay administration interface to define your webhook with a key and your URL.  | 
 | 162 | + | 
 | 163 | +The key will be the one you will use as **HASH_KEY** to authenticate your server so that Notchpay recognizes your signature.  | 
 | 164 | + | 
 | 165 | +That's all for now.  | 
 | 166 | + | 
 | 167 | +You can find the complete code [here on GitHub](https://github.com/abdounasser202/just-for-fun/tree/main/notchpay)  | 
 | 168 | + | 
 | 169 | +If you have any questions, don't hesitate to ask in the OSS Telegram Channel.  | 
 | 170 | + | 
 | 171 | +Ciao !  | 
0 commit comments