2012-10-03 127 views
0

我使用贝宝快速结账,这是继该流程: enter image description here如何保护敏感页面进行PayPal付款处理?

当他们提交的PayPal网站上它跟随在我的网站传回网址,显示的顺序审查,确认按钮,和两个GET变量从paypal传回:tokenpayerId。该令牌允许我请求送货信息&稍后完成付款。

第一个问题是我可以通过在地址栏中输入网址直接访问'使用PayPal结账'页面,它会将请求提交给贝宝,如果$_SESSION['Payment_Amount']变量没有设置它的处理与支付金额为0并引发错误。

SetExpressCheckout API调用失败。详细的错误消息:此事务无法处理。要收取的金额为零。

我知道我可以设置购物车页面上的其他会话变量,以确保他们首先参观了车,然后清除检查之后的变量,但另外一个问题仍然是,用户只需要登陆车页面一次,变量将被设置为允许他们访问向PayPal发送令牌请求的敏感页面。

接下来的问题是,经过所有的步骤和用户按下'确认订单'按钮后,请求被发送到贝宝处理该订单/金钱为该token。用户可以按页面上的'返回'按钮并再次查看订单审核,然后用户可以再次按确认订单,并且错误将显示已经为该标志处理了订单。

GetExpressCheckout详细API调用失败。详细的错误消息:此令牌的成功事务已经完成。

这显然是一件好事,但我应该实施哪些措施来防止用户访问敏感页面?我需要跟踪后端数据库中的某些密钥吗?

目前我正在使用paypal的沙箱localhost。

回答

1

您必须以某种方式创建一个流程,以确保用户按照正确的顺序遵循所需步骤,并防止他跳出此顺序。

跟踪用户会话中的步骤似乎是很自然的事情。如果会话不允许请求的步骤,请将其重定向到别处而不是询问贝宝。

豪华版本将为您实现状态机,以便日后更轻松地进行改进。状态机一开始就面临着巨大的开销,如果你最初采取了不同的方法,那么稍后实施起来会很麻烦。这就是为什么从一开始就考虑使用它的原因。

如果您希望稍后添加其他支付提供商,该怎么办?一台状态机可以很容易地扩展 - 其他任何东西都可能是一团糟。

编辑: 其实,paypal希望您在用户返回您的网站后发送给他们的唯一东西就是您要收取的金额。这些信息可以通过将其发送到您发送给PayPal的返回网址来传递。尝试在那里添加一些校验和以防止数据错误和容易篡改(如果数量不正确,Paypal可以让流程失败),并且基本完成。根本不需要任何会话。

Edit2:这里是我的代码片段,它定义了paypal第一步的nvp参数。你也需要必要的认证资料。

public function preparePayment(...) { 
     $nvp = array(

     'METHOD' => 'SetExpressCheckout', 
     'VERSION' => '52.0', 

     'RETURNURL'  => 'https://'.$request->server['HTTP_HOST'].'/'.$request->getLanguage().'/paypal/success/'.$this->hashAmount($amount), 
     'CANCELURL'  => 'https://'.$request->server['HTTP_HOST'].'/'.$request->getLanguage().'/paypal/cancel', 

      'CURRENCYCODE' => $amount->getCurrency(), 
      'AMT'   => number_format($amount->getAmount(), 2, '.', ''), 
      'ITEMAMT'  => number_format($amount->getNettoAmount(), 2, '.', ''), 
      'TAXAMT'  => number_format($amount->getVatAmount(), 2, '.', ''), 
      'PAYMENTACTION' => 'Sale', 
      'LOCALECODE' => strtoupper($request->getLanguage()) 
     ); 
} 
protected function hashAmount(Currency_Class $amount) { 
    return urlencode(
     sprintf(
      '%s-%s-%s-%u', 
      number_format($amount->getNettoAmount(), 2, '', ''), 
      number_format($amount->getVatAmount(), 2, '', ''), 
      strtoupper($amount->getCurrency()), 
      $this->makeChecksumString(number_format($amount->getNettoAmount(), 2, '', ''), strtoupper($amount->getCurrency())) 
     ) 
    ); 
} 

protected function makeChecksumString($amount, $currency) { 
    return crc32(sprintf('%sSaltValue%s', $amount, $currency)); 
} 

protected function dehashAmount($string) { 
    $parts = array(); 
    $found = preg_match('/^(\d+)\-(\d+)\-([A-Z]+)\-(\d+)$/', $string, $parts); 
    if ($found) { 
     $check = sprintf('%u', $this->makeChecksumString($parts[1], $parts[3])); 
     if ($check == $parts[4]) { 
      $netto = floatval(substr($parts[1], 0, -2) .'.'. substr($parts[1], -2)); 
      $vat = floatval(substr($parts[2], 0, -2) .'.'. substr($parts[2], -2)); 
     } 
    } 
    return ... 
} 
+0

我不明白什么是状态机;管理费用?不可能!并且由于快速结账流程(从购物车直接到贝宝)没有第一步;我的第一个问题是,发送购物车金额到PayPal的页面需要无法访问,除非按下购物车上的PayPal按钮。我怎样才能做到这一点? – Ozzy

+0

我们现在是否在您的第一页上留言 - 在图表中左下角标有“购物车”的那一页?如果不满足所有要求,则不会将请求发送到PayPal应该很容易。金额为零?没有贝宝。按钮没有按下?没有贝宝。任何其他错误?没有贝宝。 – Sven

+0

正如我在我的文章中所说'我知道我可以在购物车页面上设置另一个会话变量,以确保他们首先访问购物车,然后在检查后清除变量,但是另一个问题是用户只需要访问购物车页面一次,变量将被设置为允许他们访问发送令牌请求到paypal的敏感页面。“但是从不知道我想它不是一个大问题 – Ozzy