DoExpressCheckoutPayment

DoExpressCheckoutPayment

长话短说,我相信我已经正确实现了流程,但是在最终的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而忽略其余部分吗?

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

编辑:好的,我感到困惑。如果仅调用GetExpressCheckoutDetails,则响应为:

CHECKOUTSTATUS => PaymentActionNotInitiated

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

CHECKOUTSTATUS => PaymentActionCompleted(并且随后的DoExpressCheckoutPayment结果具有重复请求错误)

哪有道理?!原始的PHP是否刚刚变得异步?贝宝(PayPal)是否已分配足够的钱来购买计时机?我可能缺少一些非常基本的东西,但是我真的还没有看到它:\

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

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。您需要逐步检查代码,并确切地了解它是如何发生的。这可能是您正在使用的类中的东西。

关于这一点,您可能有兴趣改用look at my class。它使一切变得非常简单,因为它将全部转换为PHP数组并为您处理繁琐的工作。

但是,如果您不想从新的类开始,那么再次,您需要逐步检查代码中发生的情况以及类方法,以查看两次将其发布到何处。

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

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

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

10-10 19:17