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

相关推荐
bobz9656 分钟前
ovs patch port 对比 veth pair
后端
Asthenia041216 分钟前
Java受检异常与非受检异常分析
后端
uhakadotcom30 分钟前
快速开始使用 n8n
后端·面试·github
JavaGuide37 分钟前
公司来的新人用字符串存储日期,被组长怒怼了...
后端·mysql
bobz9651 小时前
qemu 网络使用基础
后端
Asthenia04121 小时前
面试攻略:如何应对 Spring 启动流程的层层追问
后端
Asthenia04121 小时前
Spring 启动流程:比喻表达
后端
Asthenia04122 小时前
Spring 启动流程分析-含时序图
后端
ONE_Gua2 小时前
chromium魔改——CDP(Chrome DevTools Protocol)检测01
前端·后端·爬虫
致心2 小时前
记一次debian安装mariadb(带有迁移数据)
后端