Django调用API遇InvalidSchema错误,请求协助处理订单状态更新
解决Django Intasend Webhook的InvalidSchema错误
问题背景
接触Django开发已有一年,对API了解不多。编写了一个Intasend支付Webhook视图,希望在支付事件返回“COMPLETED”状态时将订单状态改为“Paid”,返回“FAILED”时改为“Unpaid”,原代码如下:
@csrf_exempt def intasend_webhook_view(request): if request.method == "POST": payload = request.body response = requests.get(payload) intasend_body = json.loads(response) api_ref = intasend_body.get("api_ref") state = intasend_body.get("state") order = Order.objects.get(pk=api_ref) if state == "FAILED": order.payment_status == "Unpaid" order.save() elif state == "COMPLETED": order.payment_status == "Paid" order.save() return JsonResponse('success', safe=False)
错误信息
测试交易时,Shell中出现如下错误:
raise InvalidSchema(f"No connection adapters were found for {url!r}") requests.exceptions.InvalidSchema: No connection adapters were found for '{"invoice_id": "VYBP5OQ", "state": "FAILED", "provider": "CARD-PAYMENT", "charges": "0.00", "net_amount": "84.00", "currency": "USD", "value": "84.00", "account": "email@outlook.com", "api_ref": "2", "mpesa_reference": null, "host": "http://127.0.0.1:8000", "failed_reason": null, "failed_code": null, "failed_code_link": "https://intasend.com/troubleshooting", "created_at": "2022-10-28T11:55:40.755353+03:00", "updated_at": "2022-10-28T11:55:54.504547+03:00", "challenge": "123"}' [28/Oct/2022 11:55:54] "POST /webhooks/intasend/ HTTP/1.1" 500 97938
解决步骤
修复核心错误:错误使用
requests.get
Webhook的本质是Intasend直接把支付数据POST到你的视图,request.body已经包含了完整的支付事件JSON数据,不需要再用requests.get去请求这个字符串(这会被当成URL,导致InvalidSchema错误)。直接解析request.body即可。修正赋值语法错误
原代码中order.payment_status == "Unpaid"是比较运算符,应该改为赋值运算符=,否则无法更新订单状态。添加异常处理(可选但推荐)
直接用Order.objects.get(pk=api_ref)如果找不到对应订单会抛出DoesNotExist异常,导致500错误,建议捕获该异常并处理。
修正后的代码
import json from django.http import JsonResponse from django.views.decorators.csrf import csrf_exempt from .models import Order # 确保导入你的Order模型 @csrf_exempt def intasend_webhook_view(request): if request.method == "POST": # 解析请求体的JSON数据 try: intasend_body = json.loads(request.body.decode('utf-8')) except json.JSONDecodeError: return JsonResponse({'status': 'error', 'message': 'Invalid JSON'}, status=400) api_ref = intasend_body.get("api_ref") state = intasend_body.get("state") # 处理订单状态更新 try: order = Order.objects.get(pk=api_ref) if state == "FAILED": order.payment_status = "Unpaid" order.save() elif state == "COMPLETED": order.payment_status = "Paid" order.save() except Order.DoesNotExist: return JsonResponse({'status': 'error', 'message': 'Order not found'}, status=404) return JsonResponse({'status': 'success'}, safe=False)
额外建议
- 生产环境中不要依赖
@csrf_exempt,请按照Intasend文档验证Webhook的签名,确保请求来自合法的Intasend服务器。 - 可以添加日志记录,方便后续排查支付事件的处理情况。
内容的提问来源于stack exchange,提问作者Caleb Peter
相关产品推荐
相关产品推荐

