php - DoExpressCheckoutPayment(数字商品结账 express )中的重复请求

标签 php paypal

长话短说,我相信我已经正确地实现了流程,但在最终的 DoExpressCheckoutPayment 上我得到:

ACK => SuccessWithWarning  
L_ERRORCODE0 => 11607
L_SHORTMESSAGE0 => Duplicate Request
L_LONGMESSAGE0 => A successful transaction has already been completed for this token

这仅仅是因为我在此之前正在执行 GetExpressCheckoutDetails 请求吗? (GetExpressCheckoutDetails ACK 是“成功”)

请注意,从 DoExpressCheckoutPayment 返回的其他数据看起来不错:

PAYMENTINFO_0_PAYMENTSTATUS => Completed
PAYMENTINFO_0_ACK => Success

我是否应该只查找 PAYMENTINFO_0_ACK 而忽略其余部分?

旁注 - 如果有兴趣,我正在使用 PHP 库 https://github.com/thenbrent/paypal-digital-goods尽管我将示例 return.php 中的内容更改为新类上的 GetExpressCheckoutDetails,因为当然,每次都使用相同的购买数据是没有意义的,而且它必须是动态的

编辑: 好吧,我很困惑。如果我调用 GetExpressCheckoutDetails,则响应为:

CHECKOUTSTATUS => PaymentActionNotInitiated

但是,如果我调用 GetExpressCheckoutDetails,然后调用 DoExpressCheckoutPayment,前面的 GetExpressCheckoutDetails 的响应将变为:

CHECKOUTSTATUS => PaymentActionCompleted(由此可见后续DoExpressCheckoutPayment的结果出现Duplicate Request的错误)

这有什么意义?! Vanilla PHP 刚刚变得异步了吗? paypal拨够钱买时光机了吗?我可能遗漏了一些非常基本的东西,但我真的还没有看到它:\

编辑 2 一些示例代码(没有将其剥离以使其成为 100% Vanilla ,但应该非常简单):

public static function completePaypalPurchase() {
    self::configurePaypal(''); // Not relevent, just some setting of API keys and stuff
    $paypalAPI = new PayPal_Purchase(); // Just to get purchase info so we can form the real purchase request
    $response = $paypalAPI->get_checkout_details(); // Uses token from GET automatically

    echo("RESPONSE FROM GET CHECKOUT");
    print_r($response);

    $ack = strtoupper($response['ACK']);
    $userID = (int)$response['CUSTOM']; // This was passed earlier and is retrieved correctly
    $numCredits = (int)$response['L_QTY0'];

    //NOTE: If I comment out the below, then the $response above has CHECKOUTSTATUS => PaymentActionNotInitiated
    //      BUT If I do not comment it out, leaving it as-is then the $response above has CHECKOUTSTATUS => PaymentActionCompleted
    //      That's the core of the problem and where I'm stuck

    if($ack == "SUCCESS" && $numCredits && $userID && $userID == $loggedInUserID) {
        $paypalAPI = self::getPaypalPurchaseCredits($userID, $numCredits); // This creates a new PayPal_Purchase() with this info. In fact, it's the same method and therefore should return the same sort of object as the one used at the beginning of the flow
        $response = $paypalAPI->process_payment();
        $ack = strtoupper($response['ACK']);

        echo("RESPONSE FROM DO PAYMENT");
        print_r($response);
        if(isset($response['PAYMENTINFO_0_TRANSACTIONID']) && $ack == "SUCCESS") {
            $transactionID = $response['PAYMENTINFO_0_TRANSACTIONID'];
            return(new APIReturn(true, array('ack'=>$ack, 'userid'=>$userID, 'numcredits'=>$numCredits, 'transactionid'=>$transactionID)));
        }
    }
    return(new APIReturn(false, self::ERROR_NORESULT));
}

最佳答案

调用的正确顺序是 SetExpressCheckout、GetExpressCheckoutDetails,然后是 DoExpressCheckoutPayment。如果您收到重复订单错误,那么您必须以某种方式两次调用 DECP。您需要单步执行您的代码并确切地了解它是如何发生的。它可能是您正在使用的类(class)中的东西。

关于这一点,您可能有兴趣参加 look at my class反而。它使一切变得非常简单,因为它将所有内容都转换为 PHP 数组并为您处理繁重的工作。

但是,如果您不想使用新类重新开始,那么您需要逐步检查代码中发生的情况,并通过类方法查看它在哪里被发布了两次。

我注意到的另一件事是您只检查 ACK = Success。这意味着当 ACK = SuccessWithWarning 时,它将被视为失败。您需要同时处理 Success 和 SuccessWithWarning(一个体面的类库会为您处理。)

抱歉,我没有更明确的答案,但同样,在您的代码或库中的某处,它必须被发布两次。您是否在记录原始 API 请求和响应?如果是这样,您将能够确认它被击中了两次,因为您记录了 2 组 DECP 请求和响应。

关于php - DoExpressCheckoutPayment(数字商品结账 express )中的重复请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20528689/

相关文章:

php - 存储过程不返回带有 PDO 语句的记录

php - file_get_contents() 返回 "failed to open stream: File name too long",但 url 从浏览器中打开正常

php - PayPal IPN 处理器不再插入数据库

paypal - 付款后修改 PayPal Express Checkout 自定义参数

php - 单击按钮后将数据库的值更改为当前日期和时间

php - 无法修复 PDO 建立动态 sql 时参数编号无效

php - 如何将值传递给 Laravel 中的密码字段

android - 从 EditText 获取值时出错?

使用 Payflow Pro 退还费用的 PHP 代码

paypal - 在我的 wordpress 站点中将 paypal 与 PAID MEMBERSHIP PRO 集成时,帐户受到限制