You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Flask中如何立即返回200 Ok响应以解决Payfast ITN的307临时重定向问题

Flask中如何立即返回200 Ok响应以解决Payfast ITN的307临时重定向问题

我之前集成Payfast的时候也碰到过一模一样的问题——用户支付成功了,但ITN回调总是返回307,试了好几种返回200的写法都没用,折腾了好一阵才找到根源。结合你的情况,我给你梳理几个排查方向和解决方案:

先确认核心前提:你的路由真的接收到请求了吗?

你在代码里加了日志,先去看日志里有没有Request received:的记录。如果完全没看到,说明请求根本没走到这个路由,大概率是下面两个问题:

  • Payfast配置的回调URL和你的路由不匹配(比如多了/少了斜杠,或者域名不对)
  • 你的服务器(Nginx/Apache)配置了自动重定向规则,比如把无斜杠的URL重定向到带斜杠的版本,哪怕你加了strict_slashes=False也可能被服务器层面的规则覆盖

如果日志有记录,那问题出在响应返回的环节,往下看:

解决方案1:先返回200响应,再异步处理ITN逻辑

Payfast的ITN机制要求你立即返回200 OK,不能因为处理验证逻辑而阻塞响应。PHP示例里的flush()就是为了确保响应立刻发送,放到Flask里,你需要先返回响应,再把ITN的验证/处理逻辑放到后台线程里:

from flask import Response, request
import threading

@orders.route('/status/notify', methods=['POST'], strict_slashes=False)
def notify():
    # 先构造并返回200响应,设置Connection: close确保连接立刻断开
    response = Response('OK', status=200, mimetype='text/plain')
    response.headers['Connection'] = 'close'

    # 把ITN处理逻辑放到后台线程,避免阻塞响应返回
    def process_itn():
        pf_data = request.form.to_dict()
        # 这里写你的Payfast签名验证、订单状态更新等逻辑
        current_app.logger.debug(f"Received ITN data: {pf_data}")
    
    threading.Thread(target=process_itn, daemon=True).start()

    return response

注意:ITN一般都是POST请求,不需要开GET方法,反而可能增加安全风险,所以路由里只保留methods=['POST']就好。

解决方案2:排查全局钩子/中间件的干扰

如果你的Flask应用有全局的before_request或者after_request钩子(比如登录验证、权限检查),这些钩子可能会对这个路由做重定向处理。你需要把这个路由排除在外:

@app.before_request
def before_request():
    # 跳过ITN回调路由的全局钩子处理
    if request.path == '/status/notify':
        return None
    # 其他全局逻辑,比如登录验证...

解决方案3:检查服务器反向代理配置

如果你用Nginx或Apache做反向代理,一定要确保配置里没有自动添加斜杠或重定向的规则。比如Nginx的try_files指令如果配置不当,会把无斜杠的URL重定向到带斜杠的版本,哪怕Flask设置了strict_slashes=False也没用。举个Nginx的正确配置示例:

location /status/notify {
    proxy_pass http://your-flask-app:5000/status/notify;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
}

不要用location /这种泛匹配的规则来处理这个路由,单独配置更稳妥。

最后用curl测试路由

你可以自己用curl模拟Payfast的请求,看看本地返回的状态码是不是200:

curl -X POST http://your-domain.com/status/notify -d "test=123" -v

如果curl返回的是200,但Payfast那边还是307,那可能是Payfast侧的问题,比如他们的请求链路里有代理导致重定向,这时候可以联系Payfast的技术支持确认。

备注:内容来源于stack exchange,提问作者JBstrap

火山引擎 最新活动