长话短说,我相信我已经正确实施了流量,但是在最后的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并忽略其余的吗?
Sidenote-如果感兴趣,我在https://github.com/thenbrent/paypal-digital-goods使用PHP库虽然我将示例中的return.php中的内容更改为新类的GetExpressCheckoutDetails,当然,这没有任何意义每次使用相同的购买数据,它必须是动态的
编辑:好吧,我很困惑。如果我仅调用GetExpressCheckoutDetails,则响应为:
CHECKOUTSTATUS => PaymentActionNotInitiated
但是,如果我调用GetExpressCheckoutDetails然后调用DoExpressCheckoutPayment,则之前的GetExpressCheckoutDetails 的响应变为:
CHECKOUTSTATUS => PaymentActionCompleted
(以下是后续DoExpressCheckoutPayment的结果有重复请求的错误)
这怎么有意义?! vanilla 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));
}
答案 0 :(得分:0)
调用的正确顺序是SetExpressCheckout,GetExpressCheckoutDetails,然后是DoExpressCheckoutPayment。如果您发现重复的订单错误,那么您必须以某种方式调用DECP两次。您需要逐步完成代码并确切了解这是如何发生的。这可能是你正在使用的课堂上的东西。
在这方面,您可能有兴趣转而使用look at my class。它使一切变得非常简单,因为它将所有内容都转换为PHP数组并为您处理繁琐的工作。
如果您不想重新开始使用新课程,那么您需要逐步完成代码和类方法的操作,以了解它的发布位置。
我注意到的另一件事是你只检查ACK =成功。这意味着当ACK = SuccessWithWarning时,它将被视为失败。您需要同时处理Success和SuccessWithWarning(一个体面的类库将为您处理。)
抱歉,我没有更明确的答案,但是,无论是在您的代码还是在库中的某个地方,它都必须被发布两次。您是否正在记录原始API请求和响应?如果是这样你就能确认它被击中两次,因为你有2套DECP请求并且记录了响应。