Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrate Paypal Payment Gateway with Django [Not an issue] #12

Open
rahul37865 opened this issue Dec 2, 2024 · 2 comments
Open

Integrate Paypal Payment Gateway with Django [Not an issue] #12

rahul37865 opened this issue Dec 2, 2024 · 2 comments

Comments

@rahul37865
Copy link

rahul37865 commented Dec 2, 2024

First of I apology If you think this is irrelevant. I take full responsibility. Second I want to create a tutorial about this new sdk integrating payment gateway in Django apps. However the doc is still in beta so i couldn't make it but I hope with your help i will complete this tutorial which will help community.

Install Packages

pip install paypal-server-sdk==0.6.1
pip install python-decouple

Create .env

# Paypal Credentials
PAYPAL_API_BASE_URL = 'https://api-m.sandbox.paypal.com/'
PAYPAL_CLIENT_ID = '123456789'
PAYPAL_SECRET_KEY = '123XX43534'
# Payment Client URLs (Your own custom urls)
RETURN_URL = 'http://127.0.0.1:8000/orders/payment/success/'
CANCEL_URL = 'http://127.0.0.1:8000/'

Note:- You can get all above keys from Paypal Developer Account.

your_app/views.py

from decouple import config
from paypalserversdk.paypal_serversdk_client import PaypalServersdkClient, Environment
from paypalserversdk.http.auth.o_auth_2 import ClientCredentialsAuthCredentials
from paypalserversdk.models.order_request import OrderRequest, PurchaseUnitRequest
from paypalserversdk.models.checkout_payment_intent import CheckoutPaymentIntent
from paypalserversdk.models.amount_with_breakdown import AmountWithBreakdown
from paypalserversdk.models.payment_source import PaymentSource
from paypalserversdk.models.bancontact_payment_request import BancontactPaymentRequest
from paypalserversdk.models.experience_context import ExperienceContext
from paypalserversdk.models.payer import Payer
from paypalserversdk.models.name import Name

# Initialize PayPal SDK client
client = PaypalServersdkClient(
    client_credentials_auth_credentials=ClientCredentialsAuthCredentials(
        o_auth_client_id=config('PAYPAL_CLIENT_ID'),
        o_auth_client_secret=config('PAYPAL_SECRET_KEY')
    ),
    environment=Environment.SANDBOX  # For Testing Only You need to change it on Production
)
orders_controller = client.orders

# Creating Order or Payment
def handle_paypal(request, order):

    collect = {
        'body': OrderRequest(
            intent=CheckoutPaymentIntent.CAPTURE,
            payer=Payer(
                email_address="[email protected]",
                payer_id="cust2323",
                name=Name(
                    given_name="Payer Name"
                )
            ),
            purchase_units=[
                PurchaseUnitRequest(
                    amount=AmountWithBreakdown(
                        currency_code='USD',   # if you handle multi currency make it dynamic 
                        value='4'   # make this value dynamic your product cost
                    )
                )
            ],
            payment_source=PaymentSource(
                bancontact=BancontactPaymentRequest(
                    experience_context=ExperienceContext(
                        brand_name="Your Brand Name It will override your business name",
                        return_url=config('RETURN_URL'),
                        cancel_url=config('CANCEL_URL')
                    )
                )
            )

        ),
        'prefer': 'return=minimal'
    }

    # Create the PayPal order
    response = orders_controller.orders_create(collect)
    print(response)

    # Parse the JSON response
    try:
        response_data = json.loads(response.text)  # Parse the JSON text
    except json.JSONDecodeError as e:
        print("Error parsing JSON response:", e)
        return None

    # Ensure response_data is a dictionary
    if not isinstance(response_data, dict):
        print("Unexpected response format. Response:", response_data)
        return None

    # Extract the approval link
    links = response_data.get('links', [])
    if isinstance(links, list):  # Ensure links is a list
        for link in links:
            if link.get('rel') == 'approve':  # Use .get to avoid KeyError
                approve_link = link.get('href')
                print("Approval URL:", approve_link)
                return HttpResponseRedirect(approve_link)
    else:
        print("Unexpected links format. Links:", links)
        return None

    print("No approval link found.")
    return None

Just call handle_paypal on a Button Click and it will create an order then redirect to a approve link where user can make payment. On success payment it will redirect to return_url

Unfortunately this doesn't work and I believe the code which i wrote is really poor. I need your help to complete this tutorial. I read the doc but doc is not comprehensive. The very basic requirement of creating an order is to define purchase_unit detail, payer name, payer email, return_url and cancel_url. I understood how to define purchase_unit detail only as its described in doc. I also think these many imports might be not necessary.

@rahul37865
Copy link
Author

ok after digging into sdk i realize i made few mistakes which i am correcting below and it will create the checkout page for specific order.

from paypalserversdk.models.paypal_wallet_experience_context import PaypalWalletExperienceContext
from paypalserversdk.models.paypal_wallet import PaypalWallet
from django.shortcuts import redirect
from paypalserversdk.paypal_serversdk_client import PaypalServersdkClient, Environment
from paypalserversdk.http.auth.o_auth_2 import ClientCredentialsAuthCredentials
from paypalserversdk.models.order_request import OrderRequest, PurchaseUnitRequest
from paypalserversdk.models.checkout_payment_intent import CheckoutPaymentIntent
from paypalserversdk.models.amount_with_breakdown import AmountWithBreakdown
from paypalserversdk.models.payment_source import PaymentSource
from paypalserversdk.models.payer import Payer
from paypalserversdk.models.name import Name
from decouple import config
# Initialize PayPal SDK client
client = PaypalServersdkClient(
    client_credentials_auth_credentials=ClientCredentialsAuthCredentials(
        o_auth_client_id=config('PAYPAL_CLIENT_ID'),
        o_auth_client_secret=config('PAYPAL_SECRET_KEY')
    ),
    environment=Environment.SANDBOX  # Use Environment.LIVE for production
)
orders_controller = client.orders

# Creating Order or Payment


def handle_paypal(request, order):
    print("Handle Paypal", order)
    collect = {
        'body': OrderRequest(
            intent=CheckoutPaymentIntent.CAPTURE,
            payer=Payer(
                email_address="[email protected]",
                name=Name(
                    given_name="Sonam",
                    surname="Kumari"
                )
            ),
            purchase_units=[
                PurchaseUnitRequest(
                    amount=AmountWithBreakdown(
                        currency_code='USD',
                        value='6'
                    )
                )
            ],
            payment_source=PaymentSource(
                paypal=PaypalWallet(
                    experience_context=PaypalWalletExperienceContext(
                        brand_name="CAP",
                        return_url='http://127.0.0.1:8000/orders/payment/success/',
                        cancel_url='http://127.0.0.1:8000/'
                    )
                )
            )
        ),
        'prefer': 'return=minimal'
    }

    # Create the PayPal order
    try:
        response = orders_controller.orders_create(collect)

        # Extract the payer action link from the response
        payer_action_url = None
        for link in response.body.links:
            if link.rel == 'payer-action':  
                payer_action_url = link.href  
                break

        if payer_action_url:
            # Redirect the user to the PayPal payment page
            return redirect(payer_action_url)
        else:
            print("No payer action URL found.")
            # Handle the error if the payer action URL is missing
    except Exception as e:
        print("Error:", e.__class__.__name__)
        print("Message:", str(e))
        if hasattr(e, 'response') and e.response is not None:
            print("Response Status Code:", e.response.status_code)
            print("Response Body:", e.response.text)
            print("Response Headers:", e.response.headers)

I will keep update if i implement something new in this code. I am still looking way to confirm the payment so we could start the product shipping and update the same on DB. BTW those many print statements are for you guys who wants to experiment with various other OrderRequest attributes and debug. It will give you comprehensive detail.

@rahul37865
Copy link
Author

rahul37865 commented Dec 9, 2024

Just wanted to inform I have successfully integrated Paypal with Django. I will update this thread soon...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant