Kristopher Allbright
Kristopher Allbright

Reputation: 21

Updating django database with paypal transaction details

I have a django project that takes payments and I need to update my database with a new owed balance of 0 after the paypal transaction is complete. I'm a newbie to javascript and the paypal docs aren't being helpful. here's my code:

I need to create a new payment from this and update the invoice with the correct amount owed.

This is the payment page where the payment happens, make_payment.html. Payments go through successfully.

{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block content %}


    <div class="card card-primary">
        <div class="card-header">
            <h2>Make a Payment</h2>
        </div>
        <div class="float-right list-group-item">
            <p class="font-weight-bold float-left p-0 m-0">Invoice Number</p>
            <p class="font-weight-bold float-right p-0 m-0">{{ object.pk }}</p>
        </div>

        <div class="float-right list-group-item">
            <p class="font-weight-bold float-left p-0 m-0">Amount Billed</p>
            <p class="font-weight-bold float-right p-0 m-0">${{ object.amount_billed }}</p>
        </div>

        <div class="float-right list-group-item">
            <p class="font-weight-bold float-left p-0 m-0">Amount Owed</p>
            <p class="font-weight-bold float-right p-0 m-0">${{ object.amount_owed }}</p>
        </div>



        <div class="float-right list-group-item">
            <!-- Set up a container element for the button -->
            <div id="paypal-button-container"></div>
        </div>

        <div class="float-right list-group-item">
            <a href="{% url 'invoice-list'%}"><button type="button" class="btn btn-primary float-right">Go back</button></a>
        </div>

    </div>
    <!-- Include the PayPal JavaScript SDK -->
    <script src="https://www.paypal.com/sdk/js?client-id=AeFSJDq8sonOdMT62SM-B040Eo4YWi6IS6xsPqDe-eamtEbGs9Jtbf5AbtwjnPC45LjFPOCa4sNoHEIt&currency=USD&disable-funding=credit&commit=false"></script>

    <script>
        // Render the PayPal button into #paypal-button-container

        paypal.Buttons({

            // Set up the transaction
            createOrder: function (data, actions) {
                return actions.order.create({
                    purchase_units: [{
                        amount: {
                            value: {{ object.amount_owed_as_string }}
                        }
                    }]
                });
            },

            // Finalize the transaction
            onApprove: function (data, actions) {
                return actions.order.capture().then(function (details) {
                    // Show a success message to the buyer

                    alert('Transaction completed by ' + details.payer.name.given_name + '!');

                });

            }


        }).render('#paypal-button-container');
    </script>


{% endblock content %}

This is the invoice screen where I'll need the updated amount owed after a payment, this is invoice_list.html

    {% extends "base.html" %}

{% block content %}



    <div class="card p-4 float">
        <div class="card-header mb-3"><h3>Invoices - {{ user.get_full_name }}</h3></div>



                <div class="card">


                    <div class="list-group">
                        <div  class="list-group-item list-group-item-action active disabled">
                            <p class="float-left">Invoice Number</p>
                            <p class="float-right">Amount Owed</p>

                        </div>
                    {% for invoice in user.invoice_set.all %}
                        <a href="{% url 'make-payment' pk=invoice.pk %}" class="list-group-item list-group-item-action
                                    {% if invoice.amount_owed <= 0 %} disabled {% endif %}">
                        <p class="float-left">{{ invoice.pk}}</p>
                        <p class="float-right">${{ invoice.amount_owed }}</p>
                        </a>
                    {% endfor %}

                    </div>


                </div>



    </div>

{% endblock content %}

This is models.py for the payments application

from django.db import models
from django.contrib.auth.models import User
from django.contrib.admin.utils import timezone





class Invoice(models.Model):
    # invoice number is it's primary key
    patient = models.ForeignKey(User, on_delete=models.CASCADE)
    amount_owed = models.DecimalField(decimal_places=2, max_digits=8)
    amount_billed = models.DecimalField(decimal_places=2, max_digits=8)
    date_billed = models.DateField(default=timezone.now)


    def amount_owed_as_string(self):
        return str(self.amount_owed)

    def __str__(self):
        return str(self.pk) + " - " + str(self.amount_billed)


class Payment(models.Model):
    payment_method = models.CharField(max_length=15)
    invoice = models.ForeignKey(Invoice, on_delete=models.CASCADE)
    payment_amount = models.DecimalField(decimal_places=2, max_digits=8)

    def __str__(self):
        return str(self.invoice.pk) + " - " + str(self.payment_amount)

views.py

from django.views.generic import ListView, DetailView

from .models import Payment, Invoice


class PaymentList(ListView):
    model = Payment
    paginate_by = 15
    ordering = ['payment_amount']
    template_name = 'payment_list.html'



class MakePayment(DetailView):
    model = Invoice
    template_name = 'make_payment.html'



class InvoiceList(ListView):
    model = Invoice
    paginate_by = 15
    ordering = ['date_billed']
    template_name = 'invoice_list.html'

Upvotes: 2

Views: 528

Answers (1)

Preston PHX
Preston PHX

Reputation: 30379

        onApprove: function (data, actions) {
            return actions.order.capture().then(function (details) {
                // Show a success message to the buyer

                alert('Transaction completed by ' + details.payer.name.given_name + '!');

            });

        }

This is where you need to add your own JS code that

  1. Displays a message to your buyer (using document.getElementbyId or similar) to update them on the status of what they just did.
  2. Communicates with your backend (using a fetch() or similar and records the new transaction, to "updates any amount owed" or whatever

Note that this is an insecure, client-side-only design of payment creation and capture.

For a secure solution, you need to call the v2/orders API from your server. Here is a front-end that uses that pattern, communicating via fetch() with routes on your server (which you need to implement, which would then call the PayPal v2/orders API) https://developer.paypal.com/demo/checkout/#/pattern/server

Upvotes: 1

Related Questions