Payflow会在托管结帐页面上重复出现

时间:2015-10-13 08:12:31

标签: php paypal recurring-billing payflowpro

我想为我的客户整合经常性付费流程(在PayPal上托管页面)。但我没有在php中找到相同的教程或示例代码。

除此之外,我也无法获得以下查询的答案。

  • 在PayPal付款后,如果有成功,我将获得付款成功或失败的结果,并取消支付流中的网址和IPN。请建议。
  • 每次重复出现如何获得付款成功或失败的结果?

1 个答案:

答案 0 :(得分:0)

为避免重复测试,您可以使用价格进行测试,例如0,01。要创建定期付款,请使用以下HTML格式:

<form method="post" name="formName" id="submitThisForm" action="https://www.paypal.com/cgi-bin/webscr" >
<input type="hidden" name="cmd" value="_xclick-subscriptions">
<input type="hidden" name="business" value="your@papypamail.com" />
<input type="hidden" name="item_name" value="Your Membership" />
<input type="hidden" name="a3" value="0.01">
<input type="hidden" name="p3" value="1"> 
<input type="hidden" name="t3" value="M">
<input type="hidden" name="src" value="1">
<input type="hidden" name="sra" value="1">
<input type="hidden" name="item_number" value="2" />
<input type="hidden" name="custom" value="SECURITYCODE" />
<input type="hidden" name="currency_code" value="USD" />
<input type="hidden" name="quantity" value="1" />
<input type="hidden" name="no_shipping" value="1" />
<input type="hidden" name="return" value="page going after payment" />
<input type="hidden" name="cancel_return" value="" />
<input type="hidden" name="cbt" value="ITEM DESCRIPTION" />
<input type="hidden" name="rm" value="2" />
<input type="hidden" name="notify_url" value="your_listener_file.php" />

当用户取消会员资格时,paypal将通知&#34; notify_url&#34; - 在你的情况下,这将是文件your_listener_file.php。在这个文件里面你必须检查paypal POST变量&#39; txn_type&#39; =&#39; subscr_cancel&#39;。有几个要点:

  1. 您必须验证ipn事务:

        $post           = array( 'cmd' => '_notify-validate' );
    foreach($_POST as $key=>$value){
            $post[$key] = $value;
    }
    $c  = curl_init();
    curl_setopt_array($c, array(
        CURLOPT_FOLLOWLOCATION  => TRUE,
        CURLOPT_RETURNTRANSFER  => TRUE,
        CURLOPT_CONNECTTIMEOUT  => 15,
        CURLOPT_MAXREDIRS       => 15,
        CURLOPT_TIMEOUT         => 15,
        CURLOPT_URL             => 'https://www.paypal.com/cgi-bin/webscr',
        CURLOPT_POST            => TRUE,
        CURLOPT_POSTFIELDS      => $post,
    ));
    $res = curl_exec($c);
    curl_close($c);
    $res    = trim($res);
    
    if( $res != 'VERIFIED' ) {
        exit();
    }
    
  2. 第二 - 检查是使用唯一键在数据库中存在的事务。您必须使用Paypal POST变量&#39; custom&#39;。

  3. 如果交易存在,只需进行一些简单的检查:

    if( !empty($_POST['txn_type']) && $_POST['txn_type'] == 'subscr_cancel' )
        $paypalData['approved'] = 0;
    
  4. 其他方式是使用paypal快速结账。我推荐这种方法。这是一个简单的(PHP)示例:

    // Parameters for SetExpressCheckout, which will be sent to PayPal
    $padata['L_BILLINGAGREEMENTDESCRIPTION0'] = 'Product description'; $padata['L_BILLINGAGREEMENTDESCRIPTION0'] = $padata['L_BILLINGAGREEMENTDESCRIPTION0'] . ' $'.$product->price.'/month'; $padata['L_PAYMENTREQUEST_0_DESC0'] = $padata['L_BILLINGAGREEMENTDESCRIPTION0'] . ' $'.$product->price.'/month';
    $padata['PAYMENTREQUEST_0_NOTIFYURL'] = 'http://site_url/paypal/ipn'; $padata['PAYMENTREQUEST_0_DESC'] = $product->name; $padata['RETURNURL'] = 'http://site_url/paypal/returnurl'; $padata['CANCELURL'] = 'http://site_url/paypal/cancelurl';
    $padata['PAYMENTREQUEST_0_CURRENCYCODE'] = 'USD'; $padata['PAYMENTREQUEST_0_PAYMENTACTION'] = 'SALE'; $padata['PAYMENTREQUEST_0_ITEMAMT'] = $product->price;
    $padata['PAYMENTREQUEST_0_AMT'] = $product->price;
    $padata['L_BILLINGTYPE0'] = 'RecurringPayments';
    $padata['L_PAYMENTREQUEST_0_NAME0'] = $product->name;
    $padata['L_PAYMENTREQUEST_0_NUMBER0']= '322';
    $padata['L_PAYMENTREQUEST_0_QTY0'] = '1';
    $padata['L_PAYMENTREQUEST_0_AMT0'] = $product->price;
    $paypal_data = http_build_query($padata); $httpParsedResponseAr = $this->PPHttpPost('SetExpressCheckout', $paypal_data); //Respond according to message we receive from Paypal if("SUCCESS" == strtoupper($httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($httpParsedResponseAr["ACK"])){ //Redirect user to PayPal store with Token received. $paypalurl ='https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token='.$httpParsedResponseAr["TOKEN"].''; header('Location: '.$paypalurl); }else{ echo 'Error : '.urldecode($httpParsedResponseAr["L_LONGMESSAGE0"]).'';
    }

    Page returnurl:

    $hosteddata['L_BILLINGAGREEMENTDESCRIPTION0']   = 'Recurring Description';
    $hosteddata['L_BILLINGAGREEMENTDESCRIPTION0'] = $hosteddata['L_BILLINGAGREEMENTDESCRIPTION0'] . ' $'.$pr->price.'/month';
    $hosteddata['L_PAYMENTREQUEST_0_NAME0'] = $pr->name;
    $hosteddata['PROFILEREFERENCE'] = $GetExpressCheckoutDetails['L_PAYMENTREQUEST_0_NUMBER0'];
    $hosteddata['PROFILESTARTDATE'] = date('Y-m-d') . 'T' . date('H:i:s').'Z';
    $hosteddata['SUBSCRIBERNAME'] = $GetExpressCheckoutDetails['FIRSTNAME'] . ' ' . $GetExpressCheckoutDetails['LASTNAME'];
    $hosteddata['TOKEN'] = urlencode($_POST['token']);
    $hosteddata['DESC'] = $hosteddata['L_BILLINGAGREEMENTDESCRIPTION0'];
    $hosteddata['AMT'] = $pr->price;
    $hosteddata['BILLINGPERIOD'] = 'Month';
    $hosteddata['BILLINGFREQUENCY'] = '1';
    $hosteddata['TOTALBILLINGCYCLES'] = '12';
    $hosteddata['REGULARTOTALBILLINGCYCLES'] = '1';
    $hosteddata['VERSION'] = '74.0';
    $hosteddata['MAXFAILEDPAYMENTS'] = '1';
    $hosteddata['L_PAYMENTREQUEST_0_QTY0'] = '1';
    $hosteddata['L_BILLINGTYPE0'] = 'RecurringPayments';
    $hosteddata['L_PAYMENTREQUEST_0_ITEMCATEGORY0'] = 'Digital';
    $hosteddata['L_PAYMENTREQUEST_0_AMT0'] = $pr->price;
    $hosteddata['INITAMT'] = $pr->price;
    $hosteddata['L_PAYMENTREQUEST_0_NUMBER0'] = $pr->id;
    $hosteddata['PAYMENTREQUEST_0_NOTIFYURL'] = 'http://site_url/paypal/ipn';
    $paypal_data = http_build_query($hosteddata); $hosted_saas_response = $this->PPHttpPost('CreateRecurringPaymentsProfile', $paypal_data);

    我使用了一个单独的方法将参数发布到paypal

    private function PPHttpPost( $methodName_, $nvpStr_ ) {
    $api_username = 'yourpaypal@email.com'; $api_password = 'QWEQWEWQEQWEQEQWE';
    $api_signature = 'WQEQWEQWEQWEWQEQWEQWEQWEQWEQWE.cT';
    $api_endpoint = "https://api-3t.paypal.com/nvp";
    $version = '124.0'; $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $api_endpoint);
    curl_setopt($ch, CURLOPT_VERBOSE, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_POST, 1);
    $nvpreq = "METHOD=$methodName_&VERSION=$version&PWD=$api_password&USER=$api_username&SIGNATURE=$api_signature&$nvpStr_";
    curl_setopt($ch, CURLOPT_POSTFIELDS, $nvpreq);
    $httpResponse = curl_exec($ch); if(!$httpResponse) { exit("$methodName_ failed: ".curl_error($ch).'('.curl_errno($ch).')');
    } // Extract the response details. $httpResponseAr = explode("&", $httpResponse);
    $httpParsedResponseAr = array(); foreach ($httpResponseAr as $i => $value) { $tmpAr = explode("=", $value); if(sizeof($tmpAr) > 1) { $httpParsedResponseAr[$tmpAr[0]] = $tmpAr[1]; } } if((0 == sizeof($httpParsedResponseAr)) || !array_key_exists('ACK', $httpParsedResponseAr)) {
    exit("Invalid HTTP Response for POST request($nvpreq) to $api_endpoint.");
    } return $httpParsedResponseAr;
    }