【问题标题】:Updating an old payment script for a vBulletin product更新 vBulletin 产品的旧付款脚本
【发布时间】:2021-02-08 01:20:42
【问题描述】:

我正在尝试从 vBulletin 产品更新旧的付款脚本。我已经设法让一切正常付款。我可以完成购买,但是当我点击"Return to merchant" PayPal 按钮时,它不会执行购买验证。购买确实存储在"ma_purchases" 表下的我的数据库中,但其他信息应在验证后插入其他表中并且它没有插入。然后(如果正确阅读此脚本)一旦购买经过验证返回,它应该切换用户的用户组并将购买详细信息插入其他地方。

    <?php
// ####################### SET PHP ENVIRONMENT ###########################
error_reporting(E_ALL & ~ E_NOTICE);

// #################### DEFINE IMPORTANT CONSTANTS #######################
define('THIS_SCRIPT', 'mem_payment');
define('CSRF_PROTECTION', false);
define('SKIP_SESSIONCREATE', 1);

// #################### PRE-CACHE TEMPLATES AND DATA ######################
// get special phrase groups
$phrasegroups = array('subscription');

// get special data templates from the datastore
$specialtemplates = array();

// pre-cache templates used by all actions
$globaltemplates = array();

// pre-cache templates used by specific actions
$actiontemplates = array();

// ######################### REQUIRE BACK-END ############################
define('VB_AREA', 'Subscriptions');
define('CWD', (($getcwd = getcwd()) ? $getcwd : '.'));
require_once (CWD . '/includes/init.php');
require_once (CWD . '/includes/class_vbma.php');
$vbma = new vbma($vbulletin, $vbphrase);
$vbulletin->input->clean_array_gpc('p', array(
    'item_number'    => TYPE_STR,
    'business'       => TYPE_STR,
    'receiver_email' => TYPE_STR,
    'tax'            => TYPE_STR,
    'txn_type'       => TYPE_STR,
    'payment_status' => TYPE_STR,
    'mc_currency'    => TYPE_STR,
    'mc_gross'       => TYPE_STR,
    'txn_id'         => TYPE_STR    
));
$transaction_id = $vbulletin->GPC['txn_id'];
$id = $vbulletin->GPC['item_number'];
$mc_gross = doubleval($vbulletin->GPC['mc_gross']);
$tax = doubleval($vbulletin->GPC['tax']);

$query = 'cmd=_notify-validate';
foreach ($_POST as $key => $value)
{
    $value = urlencode(stripslashes($value));
    $query .= "&$key=$value";
}

$used_curl = false;
//If you are ever messing around with Paypal it's a good idea to use the sandbox.
$usesandbox = false;
if ($usesandbox)
{
    $script = 'www.sandbox.paypal.com';
}
else
{
    $script = 'www.paypal.com';
}
if (function_exists('curl_init') and $ch = curl_init())
{
    curl_setopt($ch, CURLOPT_URL, 'https://' . $script . '/cgi-bin/webscr');
    curl_setopt($ch, CURLOPT_TIMEOUT, 15);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDSIZE, 0);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $query);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_USERAGENT, 'vBulletin via cURL/PHP');
    $result = curl_exec($ch);
    curl_close($ch);
    if ($result !== false)
    {
        $used_curl = true;
    }
}
if (!$used_curl)
{
    $header = "POST /cgi-bin/webscr HTTP/1.0\r\n";
    $header .= "Host: " . $script . "\r\n";
    $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
    $header .= "Content-Length: " . strlen($query) . "\r\n\r\n";
    if ($fp = fsockopen($script, 80, $errno, $errstr, 15))
    {
        socket_set_timeout($fp, 15);
        fwrite($fp, $header . $query);
        while (!feof($fp))
        {
            $result = fgets($fp, 1024);
            if (strcmp($result, 'VERIFIED') == 0)
            {
                break;
            }
        }
        fclose($fp);
    }
}
if ($result == 'VERIFIED')
{
    $purchase = $vbulletin->db->query_first("SELECT * FROM " . TABLE_PREFIX .
        "ma_purchases WHERE id = '" . $id . "'");
    $order = unserialize($purchase['order']);
    if ($order[0] !== $vbulletin->GPC['business'])
    {
        $status_code = '503 Service Unavailable';
        // Paypal likes to get told its message has been received
        if (SAPI_NAME == 'cgi' or SAPI_NAME == 'cgi-fcgi')
        {
            header('Status: ' . $status_code);
        }
        else
        {
            header('HTTP/1.1 ' . $status_code);
        }
    }
    unset($order[0]);
    if ($purchase and !in_array($order[1], array('renew', 'upgrade')))
    {
        $product = $vbulletin->db->query_read("SELECT pur_group FROM " . TABLE_PREFIX .
            "ma_products WHERE id = '" . $order[1] . "'");
        $userinfo = fetch_userinfo($purchase['userid']);
        $vbma->setCustomerNumber(unserialize($purchase['info']), $product['pur_group'], false,
            $userinfo);
        $rand = rand($vbulletin->options['memarea_numstart'], $vbulletin->options['memarea_numend']);
        $licnum = substr(md5($prodid . rand(0, 20000) . $rand . $rand), 0, rand(10, $vbulletin->
            options['memarea_custnumleng']));
        $licensedm = datamanager_init('License', $vbulletin, ERRTYPE_ARRAY);
        $licensedm->setr('userid', $userinfo['userid']);
        $licensedm->setr('productid', $order[1]);
        $licensedm->setr('licensenum', $licnum);
        $licensedm->set('dateline', TIMENOW);
        $licensedm->set('status', 2);
        $licensedm->pre_save();
        if (!empty($licensedm->errors))
        {
            var_dump($licensedm->errors);
        }
        else
        {
            $licensedm->save();
        }
    } elseif ($purchase and $order[1] == 'renew')
    {
        $licenseinfo = $vbma->getLicense($order[2], false, false, '', false, false);
        $licensedm = datamanager_init('License', $vbulletin, ERRTYPE_ARRAY);
        $licensedm->set_existing($licenseinfo);
        $licensedm->set('dateline', TIMENOW);
        $licensedm->set('status', 2);
        $licensedm->pre_save();
        if (!empty($licensedm->errors))
        {
            var_dump($licensedm->errors);
        }
        else
        {
            $licensedm->save();
        }
    } elseif ($purchase and $order[1] == 'upgrade')
    {
        $licenseinfo = $vbma->getLicense($order[2], false, false, '', false, false);
        $licensedm = datamanager_init('License', $vbulletin, ERRTYPE_ARRAY);
        $licensedm->set_existing($licenseinfo);
        $licensedm->set('upgrades', serialize($order[3]));
        $licensedm->pre_save();
        if (!empty($licensedm->errors))
        {
            var_dump($licensedm->errors);
        }
        else
        {
            $licensedm->save();
        }
    }
    $vbma->sendOutNewSaleEmail();
    $vbulletin->db->query_write("DELETE FROM " . TABLE_PREFIX .
        "ma_purchases WHERE id = '" . $id . "'");
    $status_code = '200 OK';
    // Paypal likes to get told its message has been received
    if (SAPI_NAME == 'cgi' or SAPI_NAME == 'cgi-fcgi')
    {
        header('Status: ' . $status_code);
    }
    else
    {
        header('HTTP/1.1 ' . $status_code);
    }
    exit;
}
$status_code = '503 Service Unavailable';
// Paypal likes to get told its message has been received
if (SAPI_NAME == 'cgi' or SAPI_NAME == 'cgi-fcgi')
{
    header('Status: ' . $status_code);
}
else
{
    header('HTTP/1.1 ' . $status_code);
}
?>

可能需要更多的东西来帮助我解决这个问题,但我只是想问一下,自 2008 年编写以来,是否有人发现与此付款脚本有任何冲突。

【问题讨论】:

    标签: php paypal payment verification vbulletin


    【解决方案1】:
    • 您需要使用 HTTP/1.1
    • URL to post back to 现在是 https://ipnpb.paypal.com/cgi-bin/webscr,基本上是 ipnpb 代替 www
    • 您的服务器/环境可能没有最新的根证书,无法验证 paypal.com 的主机并为回发形成安全的 HTTPS SSL 连接,因此无法启动连接并接收“已验证”回应
    • 您的服务器/环境还需要支持 TLS 1.2

    一有机会就停止使用 IPN,并升级到基于 v2/orders/checkout APIs(设置/捕获事务)和 server approval flow 的东西,因为理智。

    【讨论】:

    • 我尝试替换 www。使用 ipnpb(在 localhost 上)到并且仍然得到相同的结果,但是我的域上有一个证书,所以我将在我的实时站点上尝试,看看这是否有效。
    • 然而我发现如果一个产品免费,它确实完成了所有需要的数据库条目(尽管这是通过另一个文件执行的)
    • 刚刚在我的 HTTPS 服务器上尝试过,付款再次通过,但数据库中没有发布任何其他内容。我更深入地查看了代码,我发现如果产品是免费的,它会处理许可证信息,否则它会处理贝宝的东西,第 164 行是它开始的地方。 pastebin.com/0Y9k9y6c我需要深入挖掘这些文件。
    猜你喜欢
    • 1970-01-01
    • 2016-06-11
    • 2012-12-10
    • 2015-07-01
    • 2013-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-22
    相关资源
    最近更新 更多