使用托管结帐页面重复支付流

Posted

技术标签:

【中文标题】使用托管结帐页面重复支付流【英文标题】:Payflow recurring with hosted checkout pages 【发布时间】:2016-01-10 21:29:17 【问题描述】:

我想为我的客户将经常性与 payflow(与 paypal 上的托管页面)集成在一起。但是我没有在 php 中找到相同的教程或示例代码。

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

通过贝宝付款后,我将如何获得付款成功或失败的结果,因为有成功并取消支付流中的 url 和 IPN。请提出建议。 在每次循环中,我将如何获得付款成功或失败的结果?

【问题讨论】:

【参考方案1】:

为避免重复测试,您可以使用 price 进行测试,例如 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" />

当用户取消会员资格时,贝宝将通知“notify_url” - 在您的情况下,这将是文件 your_listener_file.php。在此文件中,您必须检查 paypal POST 变量 'txn_type' = 'subscr_cancel'。有几点很重要:

    您必须验证 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();
    
    

    其次 - 使用唯一键检查数据库中是否存在事务。您必须使用 Paypal POST 变量“自定义”。

    如果交易存在,做一些简单的检查:

    if( !empty($_POST['txn_type']) && $_POST['txn_type'] == 'subscr_cancel' )
        $paypalData['approved'] = 0;
    

其他方式是使用 paypal express checkout。我推荐了这种方法。这里有一个简单的 (PHP) 示例:

// SetExpressCheckout 的参数,将发送到 PayPal $pada['L_BILLINGAGREEMENTDESCRIPTION0'] = '产品描述'; $pada['L_BILLINGAGREEMENTDESCRIPTION0'] = $pada['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'; $pada['PAYMENTREQUEST_0_CURRENCYCODE'] = 'USD'; $pada['PAYMENTREQUEST_0_PAYMENTACTION'] = '销售'; $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'] = $产品->价格; $paypal_data = http_build_query($pada); $httpParsedResponseAr = $this->PPHttpPost('SetExpressCheckout', $paypal_data); //根据我们从 Paypal 收到的消息进行响应 if("SUCCESS" == strtoupper($httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($httpParsedResponseAr["ACK"])) //使用收到的令牌将用户重定向到 PayPal 商店。 $paypalurl ='https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token='.$httpParsedResponseAr["TOKEN"].''; header('位置:'.$paypalurl); 别的 echo '错误:'.urldecode($httpParsedResponseAr["L_LONGMESSAGE0"]).'';

页面返回网址:

$hosteddata['L_BILLINGAGREEMENTDESCRIPTION0'] = '重复描述';$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('Ym-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'] = '月';$hosteddata['BILLINGFREQUENCY'] = '1';$ hostsdata['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'] = '数字' ;$hosteddata['L_PAYMENTREQUEST_0_AMT0'] = $pr->price;$hosteddata['INITAMT'] = $pr->price;$hosteddata['L_PAYMENTREQUE ST_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);

我使用单独的方法将参数发布到贝宝

私有函数 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); 如果(!$http响应) exit("$methodName_ failed: ".curl_error($ch).'('.curl_errno($ch).')'); // 提取响应详细信息。 $httpResponseAr = explode("&", $httpResponse); $httpParsedResponseAr = 数组(); foreach ($httpResponseAr as $i => $value) $tmpAr = explode("=", $value); 如果(大小($tmpAr)> 1) $httpParsedResponseAr[$tmpAr[0]] = $tmpAr[1]; if((0 == sizeof($httpParsedResponseAr)) || !array_key_exists('ACK', $httpParsedResponseAr)) exit("对 $api_endpoint 的 POST 请求 ($nvpreq) 的 HTTP 响应无效。"); 返回 $httpParsedResponseAr;

【讨论】:

其他方式是使用paypal express checkout,我会添加express checkout的例子

以上是关于使用托管结帐页面重复支付流的主要内容,如果未能解决你的问题,请参考以下文章

Bluesnap 托管支付页面自定义元数据

贝宝支付流链接错误

Woocommerce:结帐页面后获取订单ID [重复]

信用卡交易是不是会因测试交易而被拒绝?

使用 Paypal Payflow Pro 进行快速结帐 - 托管页面

Magento 2在结帐页面phtml中发送到支付网关之前获取订单ID?