django实现paypal订阅记录

开发者链接 登录开发者

沙箱账号链接 沙箱账号链接


  1. 创建沙箱应用
  1. 记录 Client ID和 Secret 后面有用 然后点击进去创建回调url和回调事件,可以全选事件也可以选择你需要的

3.拿沙箱账号信息去登录

4.登录后创建订阅产品内容。记住产品id

5.配置django后端信息和创建订阅链接进行支付

python 复制代码
import requests
from datetime import datetime

# 配置 PayPal 凭据和环境
PAYPAL_CLIENT_ID_SANDBOX = '沙箱SANDBOX'
PAYPAL_SECRET_KEY_SANDBOX = '沙箱密钥'
PAYPAL_CLIENT_ID_PRODUCTION = ''  # 替换为实际生产环境的客户端 ID
PAYPAL_SECRET_KEY_PRODUCTION = ''  # 替换为实际生产环境的密钥
PAYPAL_MODE = 'sandbox'  # 'sandbox' 或 'live'
PAYPAL_BASE_URL = "https://api.sandbox.paypal.com" if PAYPAL_MODE == "sandbox" else "https://api.paypal.com"

# 工具函数:生成自定义订单号
def generate_order_id():
    """
    根据当前时间生成唯一订单号
    格式:P-YYYYMMDD-HHMMSS
    """
    current_time = datetime.now().strftime("%Y%m%d-%H%M%S")
    return f"P-{current_time}"

# 工具函数:获取 PayPal 访问令牌
def get_paypal_access_token():
    """
    获取 PayPal API 访问令牌
    """
    url = f"{PAYPAL_BASE_URL}/v1/oauth2/token"
    auth = (PAYPAL_CLIENT_ID_SANDBOX, PAYPAL_SECRET_KEY_SANDBOX)
    headers = {"Accept": "application/json", "Accept-Language": "en_US"}
    data = {"grant_type": "client_credentials"}

    response = requests.post(url, headers=headers, data=data, auth=auth)
    if response.status_code == 200:
        return response.json().get("access_token")
    else:
        raise Exception(f"获取访问令牌失败: {response.text}")

# 创建 PayPal 订阅链接
def create_paypal_subscription_link(plan_id):
    """
    使用 PayPal API 创建订阅链接
    :param plan_id: 示例计划 ID (如: P-4KL07437GC7241026M5AW2JY)
    :return: 订阅链接 URL
    """
    try:
        # 获取访问令牌
        access_token = get_paypal_access_token()

        # PayPal 订阅 API URL
        subscription_url = f"{PAYPAL_BASE_URL}/v1/billing/subscriptions"

        # 自定义订单号
        custom_order_id = generate_order_id()

        # 构建订阅请求的 payload
        payload = {
            "plan_id": plan_id,
            "custom_id": custom_order_id,
            "application_context": {
                "brand_name": "Your Brand Name",
                "user_action": "SUBSCRIBE_NOW",
                "landing_page": "BILLING",
                "return_url": f"支付成功跳转的url",
                "cancel_url": f"取消支付跳转的url",
            }
        }

        headers = {
            "Authorization": f"Bearer {access_token}",
            "Content-Type": "application/json"
        }

        # 发送请求以创建订阅
        response = requests.post(subscription_url, json=payload, headers=headers)

        if response.status_code in [200, 201]:
            # 提取审批链接
            subscription_data = response.json()
            approval_url = next(link["href"] for link in subscription_data["links"] if link["rel"] == "approve")
            print(f"订阅链接生成成功: {approval_url}")
            return approval_url
        else:
            print(f"创建订阅链接失败: {response.text}")
            return None
    except Exception as e:
        print(f"创建订阅链接时发生错误: {e}")
        return None

# 示例调用
if __name__ == "__main__":
    PLAN_ID = "P-4KL07437GC7241026M5AW2JY"  # 示例计划 ID
    approval_url = create_paypal_subscription_link(PLAN_ID)
    if approval_url:
        print(f"请访问以下链接以完成订阅: {approval_url}")
    else:
        print("无法生成订阅链接,请检查配置或 API 调用。")

6.订阅成功后回调

当用户进入approval_url 付款成功后会回调到给个前面创建的回调链接。测试付款的账号也在开发者后台生成自行付款测试。最后后端再根据不同的回调类型操作数据库即可

python 复制代码
def paypal_webhook(request):
    """
    PayPal Webhook 回调入口
    """
    try:
        # 解析请求体
        webhook_data = json.loads(request.body.decode("utf-8"))
        print("[Webhook] 收到数据:", json.dumps(webhook_data, indent=4))

        event_type = webhook_data.get("event_type")
        resource = webhook_data.get("resource")
        webhook_id = webhook_data.get("id")

        print(f"[Webhook] 事件类型: {event_type}, Webhook ID: {webhook_id}")

        handle_webhook_event(event_type, resource, webhook_id)

    except Exception as e:
        print(f"[Webhook] 错误: {str(e)}")
        return JsonResponse({"code": 500, "message": f"服务器错误: {str(e)}"})

def handle_webhook_event(event_type, resource, webhook_id):
    """
    处理 PayPal Webhook 回调事件
    :param event_type: 回调事件类型(如 BILLLING.SUBSCRIPTION.ACTIVATED)
    :param resource: 事件的资源数据(JSON 格式)
    :param webhook_id: PayPal Webhook ID,用于验证请求合法性
    """
    print(f"[Webhook 回调] 收到事件: {event_type}, Webhook ID: {webhook_id}")

    if event_type == "BILLING.SUBSCRIPTION.ACTIVATED":
        # 处理订阅激活事件
        print("[Webhook 回调] 事件类型: 订阅已激活")
        print(f"[Webhook 回调] 资源数据: {resource}")
        handle_subscription_activated(resource, webhook_id)

    elif event_type == "BILLING.SUBSCRIPTION.UPDATED":
        # 处理订阅更新事件
        print("[Webhook 回调] 事件类型: 订阅已更新")
        print(f"[Webhook 回调] 资源数据: {resource}")
        handle_subscription_updated(resource, webhook_id)

    elif event_type == "BILLING.SUBSCRIPTION.CANCELLED":
        # 处理订阅取消事件
        print("[Webhook 回调] 事件类型: 订阅已取消")
        print(f"[Webhook 回调] 资源数据: {resource}")
        handle_subscription_cancelled(resource, webhook_id)

    elif event_type == "PAYMENT.SALE.COMPLETED":
        # 处理付款完成事件
        print("[Webhook 回调] 事件类型: 付款已完成")
        print(f"[Webhook 回调] 资源数据: {resource}")
        handle_payment_completed(resource, webhook_id)

    else:
        # 未知的事件类型
        print(f"[Webhook 回调] 未知事件类型: {event_type}")
        print(f"[Webhook 回调] 资源数据: {resource}")

7.最后为了安全性建议在生产环境对回调进行验签再操作。有其它疑问可以互相交流

相关推荐
子兮曰3 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰3 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
默_笙3 天前
🍙 给每个请求过安检:FastAPI 是怎么把校验写进类型注解的
python
爱勇宝3 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
qq_426003963 天前
启动playwright录制codegen生成自动化测试脚本
python·自动化
虎头金猫3 天前
4K 视频总卡在公网带宽?用 N1 + OpenList 把网盘播放链路重新理顺
运维·服务器·网络·python·容器·beautifulsoup·pandas
胡写代码3 天前
别再前后端各写一套表单校验了
java·后端
长沙三为智能科技3 天前
家政小程序开发从0到上线:五阶段交付流程与验收清单
python
伞伞悦读3 天前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python
大勇前进3 天前
原生 PHP 还是 Laravel?小项目到底要不要上框架
后端