Quickbooks Webconnector Delays 10+ minutes before each import

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-11 18:00:06

问题


I have a portal that we use to import invoices, customers and vendors into Quickbooks using web connector. The import is successful, however, after we submit each new entry their is a 10+ minute delay from the time we submit to the time the entry is imported into Quickbooks.

Please find my QWC File Code, Que Table and Logs.

QWClog File

below is my controller i use to import data in quickbooks

class QuickBooks extends CI_Controller
{


  public function __construct()
    {
    parent::__construct();

    // QuickBooks config
    $this->load->config('quickbooks');

    // Load your other models here...
    //$this->load->model('yourmodel1');
    //$this->load->model('yourmodel2');
    //$this->load->model('yourmodel3');
}

/**
 * Generate and return a .QWC Web Connector configuration file
 */
public function config()
{
    $name = 'test_site Web Connect';            // A name for your server (make it whatever you want)
    $descrip = 'test_site Web Connect';     // A description of your server

    $appurl = 'https://' . $_SERVER['HTTP_HOST'] . dirname($_SERVER['REQUEST_URI']) . '/qbwc';      // This *must* be httpS:// (path to your QuickBooks SOAP server)
    $appsupport = $appurl;      // This *must* be httpS:// and the domain name must match the domain name above

    $username = $this->config->item('quickbooks_user');     // This is the username you stored in the 'quickbooks_user' table by using QuickBooks_Utilities::createUser()

    $fileid = QuickBooks_WebConnector_QWC::fileID();        // Just make this up, but make sure it keeps that format
    $ownerid = QuickBooks_WebConnector_QWC::ownerID();      // Just make this up, but make sure it keeps that format

    $qbtype = QUICKBOOKS_TYPE_QBFS; // You can leave this as-is unless you're using QuickBooks POS

    $readonly = false; // No, we want to write data to QuickBooks

    $run_every_n_seconds = 60; // Run every 60 seconds (1 minute)

    // Generate the XML file
    $QWC = new QuickBooks_WebConnector_QWC($name, $descrip, $appurl, $appsupport, $username, $fileid, $ownerid, $qbtype, $readonly, $run_every_n_seconds);
    $xml = $QWC->generate();

    // Send as a file download
    header('Content-type: text/xml');
    header('Content-Disposition: attachment; filename="my-quickbooks-wc-file.qwc"');
    print($xml);
    exit;

}

/**
 * SOAP endpoint for the Web Connector to connect to
 */
public function qbwc()
{
    $user = $this->config->item('quickbooks_user');
    $pass = $this->config->item('quickbooks_pass');

    // Memory limit
    ini_set('memory_limit', $this->config->item('quickbooks_memorylimit'));

    // We need to make sure the correct timezone is set, or some PHP installations will complain
    if (function_exists('date_default_timezone_set'))
    {
        // * MAKE SURE YOU SET THIS TO THE CORRECT TIMEZONE! *
        // List of valid timezones is here: http://us3.php.net/manual/en/timezones.php
        date_default_timezone_set($this->config->item('quickbooks_tz'));
    }


    // Build the database connection string
    //$dsn = 'mysqli://devstagetest_site_qbuser:6Y_9aI@PBSrF@50.62.57.212/devstagetest_site_qb_database'; // dev
    $dsn = 'mysqli://test_site_qbuser:r1R1aQ;gcE%;@50.62.57.212/test_site_qb_database'; // live


    // Map QuickBooks actions to handler functions
    $map = array(
        QUICKBOOKS_ADD_CUSTOMER => array( array( $this, '_addCustomerRequest' ), array( $this, '_addCustomerResponse' ) ),
        QUICKBOOKS_ADD_INVOICE => array( array( $this, '_invoice_add_request' ), array( $this, '_invoice_add_response' ) ),
        QUICKBOOKS_ADD_VENDOR => array( array( $this, '_vendor_add_request' ), array( $this, '_vendor_add_response' ) ),
    );

    // Catch all errors that QuickBooks throws with this function
    $errmap = array(
        3070 => array( $this,'_quickbooks_error_stringtoolong'),
        'InvoiceAdd' => array( $this,'_quickbooks_error_invoiceadd'),
        'CustomerAdd' => array( $this,'_quickbooks_error_customeradd'),
        'VendorAdd' => array( $this,'_quickbooks_error_vendoradd'),
        500 => array( $this,'cust_not_exist'),
        3100 => array( $this,'cust_already_exist'),
        '*' => array( $this, '_catchallErrors' ),
    );

    // Call this method whenever the Web Connector connects
    $hooks = array(
        //QuickBooks_WebConnector_Handlers::HOOK_LOGINSUCCESS => array( array( $this, '_loginSuccess' ) ),  // Run this function whenever a successful login occurs
    );
    // An array of callback options
    $callback_options = array();

    // Logging level
    $log_level = $this->config->item('quickbooks_loglevel');

    // What SOAP server you're using
    //$soapserver = QUICKBOOKS_SOAPSERVER_PHP;          // The PHP SOAP extension, see: www.php.net/soap
    $soapserver = QUICKBOOKS_SOAPSERVER_BUILTIN;        // A pure-PHP SOAP server (no PHP ext/soap extension required, also makes debugging easier)

    $soap_options = array(      // See http://www.php.net/soap
    );

    $handler_options = array(
        'deny_concurrent_logins' => false,
    );      // See the comments in the QuickBooks/Server/Handlers.php file

    $driver_options = array(        // See the comments in the QuickBooks/Driver/<YOUR DRIVER HERE>.php file ( i.e. 'Mysql.php', etc. )
        'max_log_history' => 32000, // Limit the number of quickbooks_log entries to 1024
        'max_queue_history' => 1024,    // Limit the number of *successfully processed* quickbooks_queue entries to 64
    );



    // Check to make sure our database is set up
    if (!QuickBooks_Utilities::initialized($dsn))
    {
        // Initialize creates the neccessary database schema for queueing up requests and logging
        QuickBooks_Utilities::initialize($dsn);

        // This creates a username and password which is used by the Web Connector to authenticate
        QuickBooks_Utilities::createUser($dsn, $user, $pass);
    }

    // Set up our queue singleton
    QuickBooks_WebConnector_Queue_Singleton::initialize($dsn);

    // Create a new server and tell it to handle the requests
    // __construct($dsn_or_conn, $map, $errmap = array(), $hooks = array(), $log_level = QUICKBOOKS_LOG_NORMAL, $soap = QUICKBOOKS_SOAPSERVER_PHP, $wsdl = QUICKBOOKS_WSDL, $soap_options = array(), $handler_options = array(), $driver_options = array(), $callback_options = array()
    $Server = new QuickBooks_WebConnector_Server($dsn, $map, $errmap, $hooks, $log_level, $soapserver, QUICKBOOKS_WSDL, $soap_options, $handler_options, $driver_options, $callback_options);
    $response = $Server->handle(true, true);
}

function _invoice_add_request($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $version, $locale) {

    $record = $this->db->query("SELECT * FROM qb_add_invoice WHERE id = '".$ID."'")->row();
    if(count($record)>0){
        $orderid = $record->orderID;
        $uordername = $record->uordername;
        $xplode_data = explode("_", $uordername);
        $sendfrom = $record->sendfrom;
        $notary_fee = $record->notary_fee;
        $test_site_fee = $record->test_site_fee;

        $orders_record = $this->db->query("SELECT * FROM orders WHERE orderID = '".$orderid."'")->row();
        $Addr1 ='';
        $Addr2 = '';

        if($sendfrom == 'Notary'){
            $notary_record = $this->db->query("SELECT * FROM notaryRegis WHERE notaryID = '".$orders_record->notaryID."'")->row();
            if($notary_record->state > 0){
                $stateRow = $this->db->query("select * from state where stateID = '".$notary_record->state."'")->row();
                $stateName= $stateRow->stateName;
            }
            else {
                $stateName= "";
            }

            $FullName = trim($notary_record->lastName).', '.trim($notary_record->firstName);

            $Addr1 =$FullName;
            $Addr2 = $notary_record->streetAddress;
            $City = $notary_record->city;
            $State = $stateName;
            $PostalCode = $notary_record->zip;
            $PONumber = $notary_record->lastName;
            $Rate = number_format((float)$notary_fee, 2, '.', '');;
        }
        else if($sendfrom == 'Client'){
            $client_record = $this->db->query("SELECT 
                                                        cr. *,
                                                        zf.fee AS client_test_site_fee 
                                                    FROM 
                                                        customer_table cr
                                                    LEFT JOIN test_site_fees zf
                                                        ON(cr.serviceType = zf.type)
                                                    WHERE 
                                                        cr.clientID = '".$orders_record->clientID."'")->row();



            $FullName = trim($client_record->company).'-'.trim($client_record->firstName).' '.trim($client_record->lastName);
            $Addr1 = substr($client_record->mailingAddress, 0, 39);
            $Addr2 = '';
            $City = $client_record->city;
            $State = $client_record->state;
            $PostalCode = $client_record->zip;
            $PONumber = $orders_record->customerLastName;
            $Rate = $notary_fee+$client_record->client_test_site_fee;
        }
        $TxnDate = explode(" ",$orders_record->RequestedAppointmentDate);
        $TxnDate = $TxnDate[0];

        if($TxnDate == '0000-00-00'){
            $TxnDate = date('Y-m-d');
        }else{
            $TxnDate = date('Y-m-d', strtotime($TxnDate));

        }

        $RefNumber = $orders_record->escrowNumber;
        $Bill = $orders_record->loanPackageType;

        if($sendfrom == 'Client'){
            /*  $xml = '<?xml version="1.0" encoding="utf-8"?>
                            <?qbxml version="13.0"?>
                            <QBXML>
                                <QBXMLMsgsRq onError="continueOnError">
                                    <InvoiceAddRq requestID="' . $requestID . '">
                                        <InvoiceAdd>
                                            <CustomerRef>
                                                <FullName>'.$FullName.'</FullName>
                                            </CustomerRef>
                                            <TxnDate>'.$TxnDate.'</TxnDate>
                                            <RefNumber>' . $RefNumber.'</RefNumber>
                                            <BillAddress>
                                                <Addr1>'.$FullName.'</Addr1>
                                                <Addr2>'.$Addr1.'</Addr2>
                                                <City>'.$City.'</City>
                                                <State>'.$State.'</State>
                                                <PostalCode>'.$PostalCode.'</PostalCode>
                                                <Country></Country>
                                            </BillAddress>
                                            <PONumber>'.$orders_record->customerLastName.'</PONumber>                               
                                            <TermsRef>
                                                <FullName>'.$FullName.'</FullName>
                                            </TermsRef>
                                            <DueDate>' . $TxnDate . '</DueDate>
                                            <InvoiceLineAdd>
                                                <ItemRef>
                                                    <FullName>Bill:test_site Fee</FullName>
                                                </ItemRef>
                                                <Rate>' . $Rate.'</Rate>
                                            </InvoiceLineAdd>
                                        </InvoiceAdd>
                                    </InvoiceAddRq>
                                </QBXMLMsgsRq>
                            </QBXML>';
                */

            $xml = '<?xml version="1.0" encoding="utf-8"?>
                            <?qbxml version="2.0"?>
                            <QBXML>
                                <QBXMLMsgsRq onError="stopOnError">
                                    <InvoiceAddRq requestID="' . $requestID . '">
                                        <InvoiceAdd>
                                            <CustomerRef>
                                                <FullName>'.$FullName.'</FullName>
                                            </CustomerRef>
                                            <TxnDate>' . $TxnDate . '</TxnDate>
                                            <RefNumber>' . $RefNumber.'</RefNumber>
                                            <ShipAddress>
                                                <Addr1>'.trim($orders_record->customerFirstName).' '.trim($orders_record->customerLastName).'</Addr1>
                                                <Addr2>'.$orders_record->signingAddress.'</Addr2>
                                                <City>'.$orders_record->city.'</City>
                                                <State>'.$this->db->get_where('state', "stateID = $orders_record->state", 1)->row()->stateName.'</State>
                                                <PostalCode>'.$orders_record->zip.'</PostalCode>
                                                <Country></Country>
                                            </ShipAddress>
                                            <PONumber>'.$orders_record->customerLastName.'</PONumber>
                                                <TermsRef>
                                                    <FullName>Net 30</FullName>
                                                </TermsRef>
                                            <DueDate>' . $TxnDate . '</DueDate>
                                            <InvoiceLineAdd>
                                                <ItemRef>
                                                    <FullName>test_site Fee</FullName>
                                                </ItemRef>
                                                <Rate>' . $Rate.'</Rate>
                                            </InvoiceLineAdd>
                                        </InvoiceAdd>
                                    </InvoiceAddRq>
                                </QBXMLMsgsRq>
                            </QBXML>';



        }
        else if($sendfrom == 'Notary'){
            $xml = '<?xml version="1.0" encoding="utf-8"?>
                        <?qbxml version="2.0"?>
                        <QBXML>
                            <QBXMLMsgsRq onError="continueOnError">
                                <BillAddRq requestID="' . $requestID . '">
                                    <BillAdd>
                                        <VendorRef>
                                            <FullName>' .$FullName.'</FullName>
                                        </VendorRef>
                                        <TxnDate>' . $TxnDate . '</TxnDate>
                                        <DueDate>' . $TxnDate . '</DueDate>
                                        <RefNumber>' . $RefNumber.'</RefNumber>
                                            <TermsRef>
                                                <FullName>Net 15</FullName>
                                            </TermsRef>
                                        <ExpenseLineAdd>
                                            <AccountRef>
                                            <FullName>Outside Services:Loan Signing Fee</FullName>
                                            </AccountRef>
                                            <Amount>' . $Rate.'</Amount>
                                        </ExpenseLineAdd>
                                    </BillAdd>
                                </BillAddRq>
                            </QBXMLMsgsRq>
                        </QBXML>';


        }


        /*$this->email->from('info@test_site.com');
       $this->email->to('jaihind530@gmail.com');
       $this->email->cc('shehrozasmat005@gmail.com');
       $this->email->subject("test_site : invoice XML");
       $this->email->message($xml);
       $this->email->send();*/

        // storing xml for the loging



        return $xml;

    }
    else {
        $this->db->query("DELETE from qb_add_invoice WHERE id = '".$ID."'");
        return true;
    }

}


public function _invoice_add_response($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents)
{
    $this->db->query("UPDATE qb_add_invoice SET status=1, updated_at = '".date("Y-m-d H:i:s")."' WHERE id = '".$ID."'");

    $record = $this->db->query("SELECT sendfrom,orderID FROM qb_add_invoice WHERE id = '".$ID."'")->row();
    $orecord = $this->db->query("SELECT clientID,notaryID FROM orders WHERE orderID = '".$record->orderID."'")->row();
    if($record->sendfrom == 'Notary'){
        $crecord = $this->db->query("SELECT firstName,lastName FROM notaryRegis WHERE notaryID = '".$orecord->notaryID."'")->row();
    }
    else {
        $crecord = $this->db->query("SELECT firstName,lastName FROM customer_table WHERE clientID = '".$orecord->clientID."'")->row();
    }

    return "";
}

function _quickbooks_error_invoiceadd($requestID, $user, $action, $ID, $extra, &$err, $xml, $errnum, $errmsg) {

    $this->db->query("DELETE from qb_add_invoice WHERE id = '".$ID."'");
    return false;
}

/**
 * Issue a request to QuickBooks to add a customer
 */
public function _addCustomerRequest($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $version, $locale)
{
    $qb_add_cust = $this->db->query("SELECT * FROM qb_add_cust WHERE id = '".$ID."'")->row();
    $record = $this->db->query("SELECT * FROM customer_table WHERE clientID = '".$qb_add_cust->clientID."'")->row();
    if(count($record)>0){
        // Build the qbXML request from $data
        $xml = '<?xml version="1.0" encoding="utf-8"?>
        <?qbxml version="2.0"?>
        <QBXML>
            <QBXMLMsgsRq onError="continueOnError">
                <CustomerAddRq requestID="' . $requestID . '">
                    <CustomerAdd>
                        <Name>'.trim($record->company).'-'.trim($record->firstName).' '.trim($record->lastName).'</Name>
                        <CompanyName>' . trim($record->company) . '</CompanyName>
                        <FirstName>'.trim($record->firstName).'</FirstName>
                        <LastName>'.trim($record->lastName).'</LastName>
                        <BillAddress>
                            <Addr1>'.trim(substr($record->mailingAddress,0,39)).'</Addr1>
                            <Addr2></Addr2>
                            <City>'.trim($record->city).'</City>
                            <State>'.trim($record->state).'</State>
                            <PostalCode>'.trim($record->zip).'</PostalCode>
                            <Country></Country>
                        </BillAddress>
                        <Phone>'.$record->businessPhone.'</Phone>
                        <AltPhone></AltPhone>
                        <Fax></Fax>
                        <Email>'.$record->email.'</Email>                       
                    </CustomerAdd>
                </CustomerAddRq>
            </QBXMLMsgsRq>
        </QBXML>';

        // storing xml for the loging


        return $xml;
    }
    else {

        //$this->db->query("DELETE from qb_add_cust WHERE id = '".$ID."'");
        return true;
    }
}

/**
 * Handle a response from QuickBooks indicating a new customer has been added
 */
public function _addCustomerResponse($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents)
{


    $this->db->query("UPDATE qb_add_cust SET ListID = '".$idents['ListID']."' , status=1, updated_at = '".date("Y-m-d H:i:s")."' WHERE id = '".$ID."'");

    $qb_add_cust = $this->db->query("SELECT * FROM qb_add_cust WHERE id = '".$ID."'")->row();

    $record = $this->db->query("SELECT * FROM customer_table WHERE clientID = '".$qb_add_cust->clientID."'")->row();

    return true;
}

function _quickbooks_error_customeradd($requestID, $user, $action, $ID, $extra, &$err, $xml, $errnum, $errmsg) {



    $this->db->query("DELETE from qb_add_cust WHERE id = '".$ID."'");

    return true;
}

function _vendor_add_request($requestID, $user, $action, $ID, $extra, & $err, $last_action_time, $last_actionident_time, $xml, $idents)
{
    $qb_add_vendor = $this->db->get_where("qb_add_vendor", "id = $ID")->row();

    /*$ins['request_id'] = $requestID;
    $ins['import'] = $ID;
    $ins['operation_xml'] = implode('==',$qb_add_vendor);
    $ins['operation_type'] = 'pre_add_vendor_failed';
    $this->db->insert('qb_operations_xml_response', $ins);*/

    $record = $this->db->query("SELECT * FROM notaryRegis WHERE notaryID = '".$qb_add_vendor->notaryID."'")->row();

    if(!empty($record)){
        $pay = "";
        $cell = $record->phone;

        if($record->state > 0){
            $stateRow = $this->db->query("select * from state where stateID = '".$record->state."'")->row();
            $stateName= $stateRow->stateName;
        }
        else {
            $stateName= "";
        }

        $address1 = str_replace('-', ' ',$record->streetAddress);
        $address2 = '';
        $city     = $record->city;

        $zip1     = $record->zip;

        // Create and return a qbXML request
        $xml = '<?xml version="1.0" encoding="utf-8"?>
                    <?qbxml version="13.0"?>
                    <QBXML>
                        <QBXMLMsgsRq onError="StopOnError">
                            <VendorAddRq requestID="' . $requestID . '">
                                <VendorAdd>
                                    <Name>' .trim($record->lastName).', '.trim($record->firstName).'</Name>
                                    <CompanyName></CompanyName>
                                    <FirstName>'.trim($record->firstName).'</FirstName>
                                    <LastName>'.trim($record->lastName).'</LastName>
                                    <VendorAddress>
                                        <Addr1>'.trim($record->firstName).' '.trim($record->lastName).'</Addr1>
                                        <Addr2>'.substr($address1,0, 35).'</Addr2>
                                        <Addr3></Addr3>
                                        <City>'.$city.'</City>
                                        <State>'.$stateName.'</State>
                                        <PostalCode>'.$zip1.'</PostalCode>
                                        <Country></Country>
                                    </VendorAddress>
                                    <Phone>'.$cell.'</Phone>
                                    <AltPhone></AltPhone>
                                    <Fax></Fax>
                                    <Email>'.$record->email.'</Email>
                                    <VendorTaxIdent></VendorTaxIdent>
                                    <IsVendorEligibleFor1099>true</IsVendorEligibleFor1099>
                                </VendorAdd>
                            </VendorAddRq>
                        </QBXMLMsgsRq>
                    </QBXML>';

        // storing xml for the loging



        return $xml;
    }
    else
    {

        $this->db->query("DELETE from qb_add_vendor WHERE id = '".$ID."'");
        return "";

    }




}

function _vendor_add_response($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents)
{


    $this->db->query("UPDATE qb_add_vendor SET ListID = '".$idents['ListID']."' , status=1, updated_at = '".date("Y-m-d H:i:s")."' WHERE id = '".$ID."'");
    $qb_add_vendor = $this->db->query("SELECT * FROM qb_add_vendor WHERE id = '".$ID."'")->row();

    $ins['request_id'] = $requestID;
    $ins['import'] = $ID;
    $ins['operation_xml'] = implode('==', $qb_add_vendor);
    $ins['operation_type'] = 'add_vendor_response';
    $this->db->insert('qb_operations_xml_response', $ins);

    $record = $this->db->query("SELECT * FROM notaryRegis WHERE notaryID = '".$qb_add_vendor->notaryID."'")->row();

    return "";
}

function _quickbooks_error_vendoradd($requestID, $user, $action, $ID, $extra, &$err, $xml, $errnum, $errmsg)
{

    $this->db->query("DELETE from qb_add_vendor WHERE id = '".$ID."'");
    return false;
}


function _quickbooks_error_stringtoolong($requestID, $user, $action, $ID, $extra, &$err, $xml, $errnum, $errmsg)
{
    if($action == "InvoiceAdd")
    {
        $sql1="DELETE from qb_add_invoice WHERE id = '".$ID."'";
    }
    if($action == "CustomerAdd")
    {
        $sql1="DELETE from  qb_add_cust WHERE id = '".$ID."'";

    }
    if($action == "VendorAdd")
    {
        $sql1="DELETE from  qb_add_vendor WHERE id = '".$ID."'";
    }

    return true;
}


/**
 * Catch and handle errors from QuickBooks
 */
public function _catchallErrors($requestID, $user, $action, $ID, $extra, &$err, $xml, $errnum, $errmsg)
{
    if($action == "InvoiceAdd")
    {
        $sql1="DELETE from qb_add_invoice WHERE id = '".$ID."'";
    }
    if($action == "CustomerAdd")
    {
        $sql1="DELETE from  qb_add_cust WHERE id = '".$ID."'";

    }
    if($action == "VendorAdd")
    {
        $sql1="DELETE from  qb_add_vendor WHERE id = '".$ID."'";
    }

    $this->db->query($sql1);

    $admin_template = '<p>'.$errmsg.'</p>';
    $this->email->from('info@test_site.com');
    $this->email->to('adam@test_site.com');
    $this->email->subject('test_site : Error to send in Quickbooks');
    $this->email->message($admin_template);
    $this->email->send();

    return true;
}

function cust_already_exist($requestID, $user, $action, $ID, $extra, &$err, $xml, $errnum, $errmsg)
{

    $qb_add_cust = $this->db->query("SELECT * FROM qb_add_cust WHERE id = '".$ID."'")->row();

    $customer_table = $this->db->query("SELECT * FROM customer_table WHERE clientID = '" .$qb_add_cust->clientID."'")->row();


    $this->db->query("UPDATE qb_add_cust SET status=1, updated_at = '".date("Y-m-d H:i:s")."' WHERE id = '".$ID."'");
    return true;
}

function cust_not_exist($requestID, $user, $action, $ID, $extra, &$err, $xml, $errnum, $errmsg)
{

    $this->db->query("DELETE from qb_add_invoice WHERE id = '".$ID."'");
    return true;
}

/**
 * Whenever the Web Connector connects, do something (e.g. queue some stuff up if you want to)
 */
public function _loginSuccess($requestID, $user, $hook, &$err, $hook_data, $callback_config)
{
    return true;
    }
}

来源:https://stackoverflow.com/questions/57998316/quickbooks-webconnector-delays-10-minutes-before-each-import

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!