使用omnipay paypal处理paypal重定向故障

时间:2016-02-12 14:56:56

标签: 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"
]

我尝试使用令牌和correlationid获取事务,但它们都不是有效的资源ID

1 个答案:

答案 0 :(得分:2)

  1. 我建议您从PayPal Express API切换到Paypal REST API。 REST API更新,更好地记录,等等 完整。
  2. 我建议您为每个提供唯一的退货和取消网址 交易。这样做的一个例子是omnipay-paypal REST API的docblocks。基本上你需要存储 在您调用purchase()和之前的交易数据和交易ID 将该ID用作returnUrl的一部分。然后是returnUrl中的代码 将知道这是为了什么交易。
  3. 您在创建cron作业以搜索缺失的交易方面的方法是正确的(我自己做的确切,但我每天只做一次),但是您需要搜索初始购买提供的交易参考()调用,而不是returnUrl中提供的那些。
  4. 因此,例如,查看您的初始代码,我已经添加了一些关于我将做出的更改的评论:

        // 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类中的文档。