Ai_Admin/WebAdmin/paypal_payment.py

200 lines
8.4 KiB
Python
Raw Normal View History

2024-09-20 12:29:09 +08:00
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": {}})