Integrating PayMongo to your Django Application - carloramferrer/Django-AWS GitHub Wiki

Add a PayMongo Credit Card Payment Gateway

To integrate a PayMongo payment form, you need to setup an account first and take note of your public and private keys. You will need this for simple authentication when making your API calls.

Django Methods

Initialize your public and private keys in your environment settings:

public_key = "---"
private_key = "---"

Create your Payment Intent

You should create your payment intent from your back end using your secret API key then send the client_key of the response to the client-side. This client_key will be used to attach a payment method to the payment intent. In this step, the payment intent's status is awaiting_payment_method.

def PaymentIntent(amount):

    url = "https://api.paymongo.com/v1/payment_intents"
    payload = "{\"data\":{\"attributes\":{\"payment_method_allowed\":[\"card\"],\"amount\":" + str(amount) + ",\"currency\":\"PHP\"}}}"
    headers = {
        'accept': "application/json",
        'content-type': "application/json",
        'authorization': "Basic ____"
        }

    response = requests.request("POST", url, data=payload, headers=headers)
    data = response.json()
    print(data)
    return data

Setup and Attach your Payment Method

From the client-side, the collected credit card information must be sent to PayMongo by creating a PaymentMethod. Attach it to the Payment Intent using the client_key as the Payment Intent identifier and your public API key for authentication. For better user experience, an asynchronous call is highly recommended to lessen page redirection.

def PaymentMethod(cardnum, exp_month, exp_year, cvc):
    
    url = "https://api.paymongo.com/v1/payment_methods"
    payload = "{\"data\":{\"attributes\":{\"details\":{\"card_number\":\""+ str(cardnum) + "\",\"exp_month\":" + str(exp_month) + ",\"exp_year\":" + str(exp_year) + ",\"cvc\":\"" + str(cvc) + "\"},\"type\":\"card\"}}}"
    headers = {
        'accept': "application/json",
        'content-type': "application/json",
        'authorization': "Basic ___"
        }

    response = requests.request("POST", url, data=payload, headers=headers)
    data = response.json()
    print(data)
    return data

def AttachPaymentMethod(pi, pm):

    url = "https://api.paymongo.com/v1/payment_intents/" + str(pi) + "/attach"

    payload = "{\"data\":{\"attributes\":{\"payment_method\":\"" + str(pm) + "\"}}}"
    headers = {
        'accept': "application/json",
        'content-type': "application/json",
        'authorization': "Basic ___"
        }

    response = requests.request("POST", url, data=payload, headers=headers)
    data = response.json()
    print(data)
    return data

Paymongo Payment Page Sample

Create a checkout page that accepts payments and updates your booking details. After a POST method is called, you shall call your methods to generate a payment method and attach this to the intent to fulfill the payment. Make sure to note all errors and issues during payment processing.

def PayTransaction(request,id):
    status = "Pending"
    try:
        booking = Booking.objects.get(id = id)
        if booking.status == "Successful":
            status = "Successful"
    except(TypeError, ValueError, OverflowError, Booking.DoesNotExist):
        booking = None

    if request.method == "POST":
        name = request.POST.get('name','')
        cardnum = int(request.POST.get('cardnum',''))
        month = int(request.POST.get('month',''))
        year = int(request.POST.get('year',''))
        cvv = int(request.POST.get('cvv',''))

        # Create payment intent
        intent = PaymentIntent(int(booking.price*100))
        pi = intent['data']['id']
        try:
            intent_errors = intent['errors'][0]['detail']
            booking.notes = booking.notes + " \n Error: " + str(intent_errors)
            return redirect('landing',int(booking.id), 'Unsuccessful')
        except:
            # Create payment method
            method = PaymentMethod(cardnum, month, year, cvv)
            try :
                method_errors = method['errors'][0]['detail']
                booking.notes = booking.notes + " \n Error: " + str(method_errors)
                return redirect('landing',int(booking.id), 'Unsuccessful')
            except:
                pm = method['data']['id']

        attach = AttachPaymentMethod(pi,pm)
        
        try:
            errors = attach['errors'][0]['detail']
            booking.notes = booking.notes + " \n Error: " + str(errors)
            booking.save()
            return redirect('landing',int(booking.id), 'Unsuccessful')
        except:
            status = attach['data']['attributes']['status']
            payment_status = attach['data']['attributes']['payments'][0]['attributes']['status']
            if status == "succeeded" and payment_status == 'paid':
                return redirect('landing', int(booking.id), 'Success')
            else:
                return redirect('pay',(int(booking.id)))

    context = {
        'status':status,
        'booking':booking,
    }
    return render(request, 'checkout.html', context)