首页 > 解决方案 > 无法提交贝宝和验证按钮

问题描述

我在使用 paypal 按钮时遇到了一些问题。

这是我用于创建、参数化和加密按钮的 php 类:

<?php
    
    class paypal {
    
        public $config;
        public $payPalCertID = "myCertID";
        public $myPrivateKeyFile;
        public $myPublicCertFile;
        public $paypalCertFile;
        public $caCertFile;
        public $openSSL;
        
        /**
         * @var bool $use_sandbox     Indicates if the sandbox endpoint is used.
         */
        private $use_sandbox = false;
        /**
         * @var bool $use_local_certs Indicates if the local certificates are used.
         */
        private $use_local_certs = true;
        
        /** Production Postback URL */
        const VERIFY_URI = 'https://ipnpb.paypal.com/cgi-bin/webscr';
        /** Sandbox Postback URL */
        const SANDBOX_VERIFY_URI = 'https://ipnpb.sandbox.paypal.com/cgi-bin/webscr';
        
        
        /** Response from PayPal indicating validation was successful */
        const VALID = 'VERIFIED';
        /** Response from PayPal indicating validation failed */
        const INVALID = 'INVALID';
        
        public function __construct($conf) {
            $this->config=$conf;
            $this->myPrivateKeyFile = "../my-prvkey.pem";
            $this->myPublicCertFile= "../my-pubcert.pem";
            $this->paypalCertFile = "../paypal_cert.pem";
            $this->caCertFile = "../cacert.pem";
            $this->openSSL = "/usr/bin/openssl";
        }
        
        function getEncryptedForm($title, $id_item, $price, $promoCodeValidity) {
            $form = array("cmd" => "_xclick",
                    "business" => $this->config->payPalMail,
                    "cert_id" => $this->payPalCertID,
                    "lc" => "IT",
                    "item_name" => $title,
                    "item_number" => $id_item,
                    "amount" => $price,
                    "currency_code" => "EUR",
                    "no_note" => "1",
                    "shipping" => "0",
                    "address_override" => "0",
                    "return" => "myreturnurl.php"
            );
            $encryptedData = $this->paypal_encrypt($form);
            if ($encryptedData != null) {
                return '<form class="center" action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank">
                    <input type="hidden" name="cmd" value="_s-xclick">
                    <input type="hidden" name="encrypted" value="'.$encryptedData.'">
                    <input type="image" src="../paypalPayNow.png" 
                        border="0" name="submit"
                        style="width: 174px;height: 47px;"/>
                </form>';   
            }
        }
        
        private function paypal_encrypt($hash) {
            if (!file_exists($this->myPrivateKeyFile)) {
                echo "ERROR: MY_KEY_FILE $this->myPrivateKeyFile not found\n";
                return null;
            }
            if (!file_exists($this->myPublicCertFile)) {
                echo "ERROR: MY_CERT_FILE $this->myPublicCertFile not found\n";
                return null;
            }
            if (!file_exists($this->paypalCertFile)) {
                echo "ERROR: PAYPAL_CERT_FILE $this->paypalCertFile not found\n";
                return null;
            }
            if (!file_exists($this->openSSL)) {
                echo "ERROR: OPENSSL $this->openSSL not found\n";
                return null;
            }
            //Assign Build Notation for PayPal Support
            $hash['bn']= $config->secret_world;
            $data = "";
            foreach ($hash as $key => $value) {
                if ($value != "") {
                    //echo "Adding to blob: $key=$value\n";
                    $data .= "$key=$value\n";
                }
            }
            $openssl_cmd = "($this->openSSL smime -sign -signer $this->myPublicCertFile -inkey $this->myPrivateKeyFile " .
            "-outform der -nodetach -binary <<_EOF_\n$data\n_EOF_\n) | " .
            "$this->openSSL smime -encrypt -des3 -binary -outform pem $this->paypalCertFile";
            exec($openssl_cmd, $output, $error);
            if (!$error) {
                return implode("\n",$output);
            } else {
                return null;
            }
        }
        
        /**
         * Sets the IPN verification to sandbox mode (for use when testing,
         * should not be enabled in production).
         * @return void
         */
        public function useSandbox()
        {
            $this->use_sandbox = true;
        }
        
        /**
         * Sets curl to use php curl's built in certs (may be required in some
         * environments).
         * @return void
         */
        public function usePHPCerts()
        {
            $this->use_local_certs = false;
        }
        
        
        /**
         * Determine endpoint to post the verification data to.
         * @return string
         */
        public function getPaypalUri()
        {
            if ($this->use_sandbox) {
                return self::SANDBOX_VERIFY_URI;
            } else {
                return self::VERIFY_URI;
            }
        }
        
        
        /**
         * Verification Function
         * Sends the incoming post data back to PayPal using the cURL library.
         *
         * @return bool
         * @throws Exception
         */
        public function verifyIPN()
        {
            if ( ! count($_POST)) {
                throw new Exception("Missing POST Data");
            }
            
            $raw_post_data = file_get_contents('php://input');
            $raw_post_array = explode('&', $raw_post_data);
            $myPost = array();
            foreach ($raw_post_array as $keyval) {
                $keyval = explode('=', $keyval);
                if (count($keyval) == 2) {
                    // Since we do not want the plus in the datetime string to be encoded to a space, we manually encode it.
                    if ($keyval[0] === 'payment_date') {
                        if (substr_count($keyval[1], '+') === 1) {
                            $keyval[1] = str_replace('+', '%2B', $keyval[1]);
                        }
                    }
                    $myPost[$keyval[0]] = urldecode($keyval[1]);
                }
            }
            
            // Build the body of the verification post request, adding the _notify-validate command.
            $req = 'cmd=_notify-validate';
            $get_magic_quotes_exists = false;
            if (function_exists('get_magic_quotes_gpc')) {
                $get_magic_quotes_exists = true;
            }
            foreach ($myPost as $key => $value) {
                if ($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) {
                    $value = urlencode(stripslashes($value));
                } else {
                    $value = urlencode($value);
                }
                $req .= "&$key=$value";
            }
            
            // Post the data back to PayPal, using curl. Throw exceptions if errors occur.
            $ch = curl_init($this->getPaypalUri());
            curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
            curl_setopt($ch, CURLOPT_SSLVERSION, 6);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
            
            
            // This is often required if the server is missing a global cert bundle, or is using an outdated one.
            if ($this->use_local_certs) {
                curl_setopt($ch, CURLOPT_CAINFO, __DIR__ . $this->caCertFile);
            }
            curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
            curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));
            $res = curl_exec($ch);
            if ( ! ($res)) {
                $errno = curl_errno($ch);
                $errstr = curl_error($ch);
                curl_close($ch);
                throw new Exception("cURL error: [$errno] $errstr");
            }
            
            $info = curl_getinfo($ch);
            $http_code = $info['http_code'];
            if ($http_code != 200) {
                throw new Exception("PayPal responded with http code $http_code");
            }
            
            curl_close($ch);
            
            // Check if PayPal verifies the IPN data, and if so, return true.
            if ($res == self::VALID) {
                return true;
            } else {
                return false;
            }
        }
    
    }
     
?>

我不知道 PayPal 方面是否有任何更改,但现在使用上面的代码,在提交表单后,我在 PayPal 页面上收到以下错误:

X-PP-Simple-Handler: ?cmd=_dispatch-failed 状态: 200 内容长度: 382 internal_cmd=_dispatch-simple-handler&simple_handler_cmd=_dispatch-failed&reason=ERROR%20--%20exception%20during%20dispatch.THashException%3a% 20operator%5b%5d%20illegal%20on%20duplicate-okay%20hashtable%20Backtrace%3a%201935125b%201933c13f%2018a0cd5c%2018a05399%20100001af%20d70d033%20d7b01b0%2018a47a27%2018a28429%2018a2a53e%20807d42b%20f6b59647%20d7094e9&failed_application=webscr

谁能给我一些反馈或提示?

谢谢

标签: phpbuttonencryptionpaypal

解决方案


推荐阅读