This Python library allows you to interact with the PayPal REST API to manage subscriptions with variable pricing. It includes functionality for creating, updating, suspend and verifying subscriptions, as well as managing products and plans.
Project description
PayPal Subscription (Python) Library
This Python library allows you to interact with the PayPal REST API to manage subscriptions with variable pricing. It includes functionality for creating, updating, suspend and verifying subscriptions, as well as managing products and plans.
Note: When the subscription is approved the user receive an email from Paypal to inform that a new automatic payment is approved, and of course one about the payment itself.
Addendum
To simplify and avoid to use also the PayPal SDK this library implements methods like create_order and verify_payment so can be used also for single payments.
Usage Example
This example demonstrates how to create a CLI app that creates or updates a PayPal subscription and a FastAPI server with a webhook to save the PayPal identifier in an SQLite database. This setup allows you to check if a plan exists and in case update it automatically.
Dependencies
Install the required dependencies:
pip install fastapi uvicorn requests
Environment
Set up your environment variables in a .env file:
PAYPAL_CLIENT_ID=your_client_id
PAYPAL_CLIENT_SECRET=your_client_secret
PAYPAL_SANDBOX=True # Set to False for production
Payment script
The payment script creates or updates a subscription and sends an email with a PayPal approval link to the user.
This script can be extended to use other library methods, such as suspend_subscription, to manage subscriptions further.
payment_request.py
#!/usr/bin/env python
import sqlite3
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from paypal_subscription import PayPalAPI
paypal_api = PayPalAPI()
# Define subscription details
identifier = ""
name = "Subscription Name"
description = "Subscription Description"
price = "10.00"
currency = "EUR"
subscriber_email = "user@example.com"
return_url = "http://localhost:8000/return_url/"
cancel_url = "http://localhost:8000/cancel_url/"
# Connect to SQLite database
conn = sqlite3.connect('subscriptions.db')
cursor = conn.cursor()
# Retrieve identifier from the database (assuming it's stored there)
cursor.execute("SELECT id FROM subscriptions WHERE email = ?", (subscriber_email,))
result = cursor.fetchone()
if result:
identifier = result[0]
else:
raise ValueError("Subscription identifier not found in the database.")
# Create or update the subscription
subscription = paypal_api.create_or_update_subscription(
identifier=identifier,
name=name,
description=description,
price=price,
currency=currency,
subscriber_email=subscriber_email,
return_url=return_url,
cancel_url=cancel_url
)
# Get the approval link
approval_link = subscription['links'][0]['href']
# Send email with the approval link
def send_email(to_address, subject, body):
from_address = "your_email@example.com"
password = "your_email_password"
msg = MIMEMultipart()
msg['From'] = from_address
msg['To'] = to_address
msg['Subject'] = subject
msg.attach(MIMEText(body, 'plain'))
server = smtplib.SMTP('smtp.example.com', 587)
server.starttls()
server.login(from_address, password)
text = msg.as_string()
server.sendmail(from_address, to_address, text)
server.quit()
# Email details
subject = "Approve Your Subscription"
body = f"Please click the following link to approve your subscription: {approval_link}"
# Send the email
send_email(subscriber_email, subject, body)
print("Subscription approval link sent to the subscriber's email.")
FastAPI server
The FastAPI server handles the return URL webhook to save the subscription identifier in the SQLite database.
This server can be extended to save additional payment details.
from fastapi import FastAPI, Request
from paypal_subscription import PayPalAPI
import sqlite3
app = FastAPI()
paypal_api = PayPalAPI()
# Set up SQLite database
conn = sqlite3.connect('subscriptions.db')
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS subscriptions (
id TEXT PRIMARY KEY,
name TEXT,
description TEXT,
price TEXT,
email TEXT,
status TEXT
)
''')
conn.commit()
def save_subscription_to_db(subscription_id: str, name: str, description: str, price: str, email: str, status: str):
conn = sqlite3.connect('subscriptions.db')
cursor = conn.cursor()
cursor.execute('''
INSERT INTO subscriptions (id, name, description, price, email, status)
VALUES (?, ?, ?, ?, ?, ?)
''', (subscription_id, name, description, price, email, status))
conn.commit()
@app.post("/return_url/")
async def return_url(request: Request):
data = await request.json()
subscription_id = data.get("subscription_id")
subscription_details = paypal_api.verify_subscription(subscription_id=subscription_id, payer_id="email")
if subscription_details["status"] == "success":
save_subscription_to_db(
subscription_id=subscription_id,
name=subscription_details["name"],
description=subscription_details["description"],
price=subscription_details["price"],
email=subscription_details["payer_email"],
status=subscription_details["subscription_status"]
)
return {"message": "Subscription saved successfully"}
else:
return {"message": "Subscription verification failed"}
Run
Execute the payment request:
payment_request.py
Run the web server:
uvicorn main\:app --reload
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file paypal_subscription-0.1.2.tar.gz.
File metadata
- Download URL: paypal_subscription-0.1.2.tar.gz
- Upload date:
- Size: 18.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aff0802b7dd4c6c2fa44bd8bce9333a3f1cb33230c0f419652cc05ba1e80dfbb
|
|
| MD5 |
41e45c3586fa850554fe466831f7a02b
|
|
| BLAKE2b-256 |
c6ee306012f896e73dd8976f0e17634818851a17897c9287c991df40d7f70ec3
|
Provenance
The following attestation bundles were made for paypal_subscription-0.1.2.tar.gz:
Publisher:
pypi.yml on CodeAtCode/paypal-subscription-lib
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
paypal_subscription-0.1.2.tar.gz -
Subject digest:
aff0802b7dd4c6c2fa44bd8bce9333a3f1cb33230c0f419652cc05ba1e80dfbb - Sigstore transparency entry: 197380054
- Sigstore integration time:
-
Permalink:
CodeAtCode/paypal-subscription-lib@1ed9063d6f2ceefd1c3d79c761d0881a0b654e58 -
Branch / Tag:
refs/tags/0.1.2 - Owner: https://github.com/CodeAtCode
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yml@1ed9063d6f2ceefd1c3d79c761d0881a0b654e58 -
Trigger Event:
push
-
Statement type:
File details
Details for the file paypal_subscription-0.1.2-py3-none-any.whl.
File metadata
- Download URL: paypal_subscription-0.1.2-py3-none-any.whl
- Upload date:
- Size: 19.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2e43966dc27f52c45ab0050c878cc4cbdc6ff951c682b3617847f72f56adc5ee
|
|
| MD5 |
b20644eb9fd6207e9548aba0c1e08ac9
|
|
| BLAKE2b-256 |
b2efb3c8202112472c0071bf524bd34b90cbc0c7e58c5d1af53dd4eaa7e332ae
|
Provenance
The following attestation bundles were made for paypal_subscription-0.1.2-py3-none-any.whl:
Publisher:
pypi.yml on CodeAtCode/paypal-subscription-lib
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
paypal_subscription-0.1.2-py3-none-any.whl -
Subject digest:
2e43966dc27f52c45ab0050c878cc4cbdc6ff951c682b3617847f72f56adc5ee - Sigstore transparency entry: 197380056
- Sigstore integration time:
-
Permalink:
CodeAtCode/paypal-subscription-lib@1ed9063d6f2ceefd1c3d79c761d0881a0b654e58 -
Branch / Tag:
refs/tags/0.1.2 - Owner: https://github.com/CodeAtCode
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yml@1ed9063d6f2ceefd1c3d79c761d0881a0b654e58 -
Trigger Event:
push
-
Statement type: