Ai_Admin/WebAdmin/paypal_payment.py
2024-09-20 04:29:09 +00:00

200 lines
8.4 KiB
Python
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import requests
from django.conf import settings
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from datetime import datetime
from .models import Order, Plan, User
import json
import logging
logger = logging.getLogger(__name__)
def get_paypal_access_token():
"""获取 PayPal 访问令牌"""
print("正在获取 PayPal 访问令牌...")
url = f"https://api.{settings.PAYPAL_MODE}.paypal.com/v1/oauth2/token"
auth = (
settings.PAYPAL_CLIENT_ID_SANDBOX if settings.PAYPAL_MODE == 'sandbox' else settings.PAYPAL_CLIENT_ID_PRODUCTION,
settings.PAYPAL_SECRET_KEY_SANDBOX if settings.PAYPAL_MODE == 'sandbox' else settings.PAYPAL_SECRET_KEY_PRODUCTION
)
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:
access_token = response.json().get('access_token')
print(f"获取的访问令牌: {access_token}")
return access_token
else:
print(f"获取 PayPal 访问令牌失败: {response.text}")
return None
@csrf_exempt
def create_paypal_payment(request):
"""创建 PayPal 支付"""
if request.method == 'POST':
try:
print("创建 PayPal 支付开始...")
data = json.loads(request.body)
plan_id = data.get('plan_id')
payment_method = data.get('payment_method', 'paypal')
# 获取当前用户信息
user = request.user
# 验证用户和计划是否存在
if not user.is_authenticated:
print("用户未认证")
return JsonResponse({"code": 401, "message": "用户未认证", "data": {}})
try:
plan = Plan.objects.get(id=plan_id)
print(f"找到的套餐: {plan.title}")
except Plan.DoesNotExist:
print("套餐不存在")
return JsonResponse({"code": 400, "message": "套餐不存在", "data": {}})
access_token = get_paypal_access_token()
if not access_token:
return JsonResponse({"code": 500, "message": "无法获取支付访问令牌", "data": {}})
# 配置支付请求
url = f"https://api.{settings.PAYPAL_MODE}.paypal.com/v1/payments/payment"
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {access_token}"
}
payload = {
"intent": "sale",
"payer": {"payment_method": "paypal"},
"redirect_urls": {
"return_url": f"{settings.PAYPAL_RETURN_URL}",
"cancel_url": f"{settings.PAYPAL_CANCEL_URL}"
},
"transactions": [{
"item_list": {
"items": [{
"name": plan.title,
"sku": str(plan.id),
"price": str(plan.price),
"currency": "USD",
"quantity": 1
}]
},
"amount": {
"total": str(plan.price),
"currency": "USD"
},
"description": f"购买 {plan.title} 计划"
}]
}
print(f"支付请求Payload: {json.dumps(payload, indent=2)}")
response = requests.post(url, headers=headers, json=payload)
if response.status_code == 201:
payment_id = response.json().get('id')
approval_url = None
for link in response.json().get('links', []):
if link.get('rel') == "approval_url":
approval_url = link.get('href')
break
# 检查订单是否已经存在,防止重复创建订单
if Order.objects.filter(order_id=payment_id).exists():
return JsonResponse({"code": 400, "message": "订单已存在", "data": {}})
# 创建订单并使用PayPal返回的paymentId作为order_id
order = Order.objects.create(
order_id=payment_id, # 使用PayPal的支付ID作为订单ID
user=user,
username=user.username,
plan=plan,
amount=plan.price,
payment_method=payment_method,
status='pending'
)
print(f"订单创建成功订单ID: {order.order_id}")
if approval_url:
print(f"支付批准URL: {approval_url}")
return JsonResponse({"code": 200, "message": "支付创建成功", "data": {"approval_url": approval_url}})
else:
print("未找到支付批准URL")
return JsonResponse({"code": 400, "message": "未找到支付批准URL", "data": {}})
else:
print(f"支付创建失败: {response.status_code}, {response.json()}")
return JsonResponse({"code": 400, "message": "支付创建失败", "data": response.json()})
except json.JSONDecodeError:
print("请求体不是有效的JSON")
return JsonResponse({"code": 400, "message": "请求体不是有效的JSON", "data": {}})
except Exception as e:
print(f"支付创建过程中发生异常: {str(e)}")
return JsonResponse({"code": 500, "message": f"支付创建过程中发生异常: {str(e)}", "data": {}})
else:
return JsonResponse({"code": 405, "message": "方法不允许", "data": {}})
@csrf_exempt
def execute_paypal_payment(request):
"""执行 PayPal 支付"""
if request.method == 'POST':
try:
data = json.loads(request.body)
payment_id = data.get('paymentId')
payer_id = data.get('PayerID')
if not payment_id or not payer_id:
return JsonResponse({"code": 400, "message": "缺少支付ID或付款人ID", "data": {}})
order = Order.objects.get(order_id=payment_id)
if order.status == 'completed':
return JsonResponse({"code": 400, "message": "订单已支付", "data": {}})
# 获取PayPal访问令牌
access_token = get_paypal_access_token()
if not access_token:
return JsonResponse({"code": 500, "message": "无法获取支付访问令牌", "data": {}})
# 执行支付确认请求
url = f"https://api.{settings.PAYPAL_MODE}.paypal.com/v1/payments/payment/{payment_id}/execute"
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {access_token}"
}
payload = {
"payer_id": payer_id
}
response = requests.post(url, headers=headers, json=payload)
if response.status_code == 200:
try:
order.status = 'completed'
order.updated_at = datetime.now()
order.save()
# 更新用户积分
user = order.user
user.points += order.plan.credits_per_month
user.save()
return JsonResponse({"code": 200, "message": "支付成功", "data": {}})
except Order.DoesNotExist:
return JsonResponse({"code": 400, "message": "订单不存在", "data": {}})
else:
return JsonResponse({"code": 400, "message": "支付执行失败", "data": response.json()})
except json.JSONDecodeError:
return JsonResponse({"code": 400, "message": "请求体不是有效的JSON", "data": {}})
except Exception as e:
return JsonResponse({"code": 500, "message": f"支付执行过程中发生异常: {str(e)}", "data": {}})
else:
return JsonResponse({"code": 405, "message": "方法不允许", "data": {}})