本文旨在解决API回调URL页面Session ID不一致导致数据无法关联的常见问题。我们将深入探讨问题根源,并提供一套基于唯一事务标识符的解决方案,通过在用户会话中存储该标识符并将其作为URL参数传递给回调函数,最终实现客户端与服务器端数据流的无缝对接,确保支付状态等关键信息能够准确回传并被原始请求用户获取。
理解回调URL中Session ID不一致的根源
在web应用开发中,尤其是在集成第三方api(如支付网关)时,我们经常会遇到回调(callback)机制。当用户在浏览器中发起一个请求,并通过服务器端代码调用外部api时,外部api通常会在处理完成后向我们预设的callbackurl发送一个响应。问题在于,这个由外部api服务器发起的请求,是一个全新的、独立的http请求。
php的session_start()函数依赖于客户端(通常是浏览器)发送的Session ID Cookie来识别用户会话。当外部API服务器调用CallBackURL时,它并不会携带用户浏览器的Session ID Cookie。因此,CallBackURL页面上的session_start()会创建一个全新的会话,并生成一个与用户浏览器会话完全不同的Session ID。这就是为什么在response.php页面记录的Session ID与用户在processor.php或fromdb.php页面上的Session ID不一致的根本原因。
由于Session ID不一致,当response.php将API响应数据和其自身的Session ID存入数据库后,用户浏览器通过fromdb.php尝试使用其自身的Session ID去查询数据库时,自然无法找到匹配的数据,导致无法获取支付状态等关键信息。
解决方案:使用唯一事务标识符进行数据关联
为了解决这个问题,我们需要引入一个独立于PHP会话机制的唯一标识符来关联用户请求和API回调响应。这个标识符应该在用户发起请求时生成,并贯穿整个交易流程:从用户浏览器会话到API回调,再到数据库存储,最终回到用户浏览器。
核心思路如下:
- 生成唯一标识符: 在用户发起API请求(例如支付请求)时,生成一个全局唯一的事务标识符(Transaction Reference ID)。
- 用户会话中存储: 将这个唯一标识符存储在用户的PHP会话($_SESSION)中,以便用户浏览器后续查询时使用。
- 传递给回调URL: 将这个唯一标识符作为参数附加到CallBackURL上,这样当外部api调用回调URL时,它会一并传递这个标识符。
- 回调处理: 在CallBackURL页面,从URL参数中获取这个唯一标识符,并将其与API响应数据一同存入数据库。
- 客户端查询: 当用户浏览器发起查询请求时,从其自身的PHP会话中获取之前存储的唯一标识符,并使用它来查询数据库中对应的API响应数据。
逐步实现
接下来,我们将修改现有代码,以实现上述解决方案。
1. processor.php:生成并传递唯一标识符
在processor.php中,我们需要在发起API请求之前生成一个唯一的事务标识符,将其存储在用户会话中,并将其作为查询参数添加到CallBackURL。
<?php session_start(); // 确保用户会话已启动 // 生成一个唯一的事务引用ID // 使用uniqid()或更健壮的UUID生成方式 $transaction_ref_id = uniqid('txn_', true); $_SESSION['current_transaction_id'] = $transaction_ref_id; // 存储在用户会话中 include_once "db.te.php"; date_default_timezone_set('Africa/Nairobi'); $Passkey = 'bfb279f9aa9bdbcf158e97dd71a467cd2e0c893059b10f78e6b72ada1ed2c919'; $Amount= $_POST['amount']; $BusinessShortCode = '174379'; $PartyA =$_POST['phone']; $AccountReference =$_POST['name']; $TransactionDesc = 'test'; $Timestamp =date('YmdHis'); $Password = base64_encode($BusinessShortCode.$Passkey.$Timestamp); $headers=['Content-Type:application/json; charset=utf8']; $initiate_url='https://sandbox.safaricom.co.ke/mpesa/stkpush/v1/processrequest'; // 将transaction_ref_id作为查询参数添加到CallBackURL $callBackURL ='https://c28d-197-231-178-65.ngrok.io/textEditor/response.php?transaction_id=' . $transaction_ref_id; function newaccessToken() { // ... (保持不变) ... $ConsumerKey = 'uhsjjsjbVGatHuJKK'; $ConsumerSecret = 'Yh29KHAY17LKjahh'; $credentials = base64_encode($ConsumerKey.":".$ConsumerSecret); $url = "https://sandbox.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials"; $curl = curl_init();
评论(已关闭)
评论已关闭