php - 使用 omnipay paypal 处理 paypal redirect failuers

标签 php omnipay paypal

我已经在我的 Laravel 站点中实现了 Omnipay paypal。 首先,我对 paypal 进行授权调用,如下所示:

$invoice = $this->find($id);
$gateway = Omnipay::create('PayPal_Express');
$gateway->setUsername(config('payment.paypal_api_username'));
$gateway->setPassword(config('payment.paypal_api_password'));
$gateway->setSignature(config('payment.paypal_signature'));
$gateway->setTestMode(config('payment.paypal_testmode'));

$response = $gateway->purchase([
    'cancelUrl' => route('paypal.cancel'),
    'returnUrl' => route('paypal.return'),
    'amount' => $invoice->price.'.00',
    'currency' => $invoice->currency->abbr,
    'Description' => 'Sandbox test transaction'
])->send();

if($response->isRedirect()) {
    // Redirect user to paypal login page
    return $response->redirect();
} else {
    Flash::error('Unable to authenticate against PayPal');        
}

在此之后,用户将被重定向到 paypal 站点进行支付,如果成功,则将被重定向回 returnUrl。发生这种情况的地方:

$payment = Payment::where('paypal_token', '=', $token)->first();
$invoice = $payment->invoice;
$gateway = Omnipay::create('PayPal_Express');
$gateway->setUsername(config('payment.paypal_api_username'));
$gateway->setPassword(config('payment.paypal_api_password'));
$gateway->setSignature(config('payment.paypal_signature'));
$gateway->setTestMode(config('payment.paypal_testmode'));

$response = $gateway->completePurchase(array (
    'cancelUrl' => route('paypal.cancel'),
    'returnUrl' => route('paypal.success'),
    'amount' => $invoice->price.'.00',
    'currency' => $invoice->currency->abbr 
))->send();

if($response->isSuccessful()) {
    Event::fire(new MakePaymentEvent($invoice));
    Flash::message('Thank you for your payment!');
} else {
    Flash::error('Unable to complete transaction. Check your balance');
}

然而,从 paypal 重定向回来时偶尔会出现一些失败,可能是浏览器关闭或网络故障阻止用户重定向回我的 laravel 站点。

所以我尝试创建一个 cron 作业(laravel 中的调度程序),它每 5 分钟检查一次是否有未完成的付款,并尝试检查付款是否已成功转移,如果是,则将发票状态设置为已付款:

$gateway = Omnipay::create('PayPal_Rest');

$gateway->initialize(array (
    'clientId' => config('payment.paypal_client_id'),
    'secret'   => config('payment.paypal_secret_id'),
    'testMode' => config('payment.paypal_testmode'),
));

$transaction = $gateway->fetchPurchase();
$transaction->setTransactionReference($token);
$response = $transaction->send();
$data = $response->getData();
dd($data);

但我只从 paypal api 得到这个响应

array:4 [
  "name" => "INVALID_RESOURCE_ID"
  "message" => "The requested resource ID was not found"
  "information_link" => "https://developer.paypal.com/webapps/developer/docs/api/#INVALID_RESOURCE_ID"
  "debug_id" => "8240e7d79fa91"
]

那么我应该如何从用户重定向之前的授权请求中获取付款交易:

#data: array:6 [▼
    "TOKEN" => "EC-9XF92859YM415352K"
    "TIMESTAMP" => "2016-02-12T14:25:09Z"
    "CORRELATIONID" => "e6a70075ad9d5"
    "ACK" => "Success"
    "VERSION" => "119.0"
    "BUILD" => "18308778"
]

我已经尝试使用 token 和 correlationid 来获取交易,但是它们都不是有效的资源 id

最佳答案

  1. 我建议您从 PayPal Express API 切换到 Paypal 休息API。 REST API 更新、文档更好等 完成。
  2. 我建议您为每个人提供唯一的返回和取消 URL 交易。这样做的一个例子是在 omnipay-paypal REST API 的文档 block 。基本上你需要存储 调用 purchase() 之前的交易数据和交易 ID 以及 使用该 ID 作为 returnUrl 的一部分。然后returnUrl中的代码 将知道这是针对哪笔交易。
  3. 您在创建 cron 作业以搜索丢失的交易方面的方法是正确的(我自己就是这样做的,除了我每天只做一次),但是您需要搜索初始购买提供的交易引用() 调用,而不是在 returnUrl 中提供的调用。

因此,例如,查看您的初始代码,我添加了一些关于我将要进行的更改的评论:

    // OK I'm assuming that your $id is a transaction ID, so we will use that.
    $invoice = $this->find($id);

    // Make the purchase call
    $response = $gateway->purchase([
        // Add $id to these two URLs.
        'cancelUrl' => route('paypal.cancel') . '/' . $id,
        'returnUrl' => route('paypal.return') . '/' . $id,
        'amount' => $invoice->price.'.00',
        'currency' => $invoice->currency->abbr,
        'Description' => 'Sandbox test transaction'
    ])->send();

    if($response->isRedirect()) {
        // Get the transaction reference.
        $txnRef = $response->getTransactionReference();
        // Store the above $txnRef in the transaction somewhere.
        // This will be the transaction reference you need to search for.

        // Redirect user to paypal login page
        return $response->redirect();

注意:

  • $txnRef 是关键。
  • 有些交易您有 $txnRef 但在 PayPal 上找不到。看起来这些是已取消的交易,它们会在一段时间后超时。如果找不到,则假设它们被取消。
  • 在来自 PayPal fetchTransaction() 调用的响应数据中,将有一些交易返回不同的交易引用。这通常意味着交易已在 PayPal 端完成,您需要更新交易引用。

有关示例,请参阅 omnipay-paypal RestFetchTransactionRequest、RestFetchPurchaseRequest 和 RestListPurchaseRequest 类中的文档。

关于php - 使用 omnipay paypal 处理 paypal redirect failuers,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35365646/

相关文章:

php - 如何使用 gdb 在 php 脚本中设置断点

php - 禁用 Paypal Express 的沙盒模式

paypal - Omnipay - 如何将 'custom' 或 'invoice' 参数传递给 Paypal?

paypal - 用于检索交易详细信息的 PayPal PDT URL 是什么?

java - IPN 在 payflow pro 中可用吗?

php - 带有 COUNT、FROM、WHERE、GROUP BY 的 MYSQL SELECT 跳过返回的第一行

php - PHP OOP 方法链

php - 禁用提交按钮,直到 textarea ihas 超过 100 个字符

php - 使用 Omnipay 的 PayPal 快速结帐未在沙盒帐户中显示订单

paypal - 是否可以使用 PayPal API 向随机帐户汇款?