PHP(CodeIgniter)集成PayPal IPN时无法向IPN文件传递当前用户会话
PayPal IPN无法获取用户会话的根因
这不是CodeIgniter框架会话配置的问题,是PayPal IPN的请求逻辑决定的:IPN回调是PayPal的服务器从公网主动向你的notify.php地址发起的服务端POST请求,不是付款用户的浏览器发起的请求,请求头里不会携带你站点存在用户浏览器里的Session Cookie,自然读不到当前登录用户的会话数据,哪怕你站点其他所有页面会话共享都正常,也不可能在IPN里拿到会话。
标准解决方法
不要尝试通过修改会话配置、手动加载session类库的方式解决,这类方案完全走不通,按照PayPal官方的设计用参数透传+本地订单关联即可:
- 优先用预生成订单+invoice字段关联(最稳妥)
用户点击支付按钮、跳转到PayPal之前,先在本地数据库插入一条状态为「待支付」的订单记录,提前存好当前登录用户ID、订单应付金额、订单生成时间、唯一订单号,把你生成的唯一订单号传入PayPal支付接口的invoice参数。这个字段是PayPal官方预留的商户订单号字段,会在IPN回调中原样返回,同时PayPal会自动帮你校验该字段的唯一性,避免重复回调。
你在notify.php里拿到回调POST过来的invoice参数,直接查询本地对应的待支付订单,就能拿到关联的用户ID,完全不需要依赖会话。 - 轻量场景用custom字段透传用户标识
如果是不需要复杂订单逻辑的简单支付场景,可以在发起支付时,把当前用户ID等需要关联的非敏感参数,传入PayPal接口的custom字段,这个字段支持最长256字节的自定义内容,IPN回调时会原样返回。
CodeIgniter中调用PayPal接口传参示例:
回调处理时直接从POST数据里解析// 发起支付的控制器方法里,当前可以正常拿到会话 $customData = [ 'user_id' => $this->session->userdata('user_id'), 'biz_scene' => 'vip_recharge' ]; $paypalRequest->addField('custom', json_encode($customData));custom字段即可拿到用户ID。
处理IPN的注意事项
- IPN回调必须严格按照PayPal官方规则做签名校验,不要直接信任回调携带的所有参数
- 回调拿到的支付金额、交易状态,必须和你本地存储的订单数据做比对,校验通过后再更新订单状态、给用户加权益,避免恶意伪造回调
- IPN请求和用户端的支付成功跳转是完全独立的两个链路,不要依赖用户跳转回站点的动作触发业务逻辑,所有支付成功后的处理逻辑都要放到IPN里做
内容的提问来源于stack exchange,提问作者Haitham Nakib
相关产品推荐
相关产品推荐

