{"id":1399,"date":"2025-10-08T06:52:43","date_gmt":"2025-10-08T06:52:43","guid":{"rendered":"http:\/\/wwwdev.dugtour.com\/?page_id=1399"},"modified":"2025-10-08T06:52:43","modified_gmt":"2025-10-08T06:52:43","slug":"test","status":"publish","type":"page","link":"https:\/\/www.dugtour.com\/es\/test\/","title":{"rendered":"Test"},"content":{"rendered":"<pre class=\"wp-block-code\"><code>&lt;?php\n\/**\n * Test API for PagoMovil Bank List - FINAL FIXED VERSION\n * Fixed UTF-8 encoding issues and proper bank list display\n *\/\n\n\/\/ Enable error reporting for debugging\nerror_reporting(E_ALL);\nini_set('display_errors', 1);\n\nclass PagoMovilBankTest {\n    private $api_base_url = 'https:\/\/servicios.bncenlinea.com:16500';\n    private $client_guid = '8358c7d5-5a6c-4883-8526-05ec48ed0130';\n    private $master_key = '667ce71bfc380183546d0005140b58f3';\n    private $working_key = '';\n    \n    public function __construct() {\n        echo \"&lt;!DOCTYPE html>\n        &lt;html>\n        &lt;head>\n            &lt;title>PagoMovil Bank List Test - FIXED&lt;\/title>\n            &lt;style>\n                body { font-family: Arial, sans-serif; max-width: 1200px; margin: 0 auto; padding: 20px; }\n                .success { color: green; background: #f0fff0; padding: 10px; border-left: 4px solid green; }\n                .error { color: red; background: #fff0f0; padding: 10px; border-left: 4px solid red; }\n                .info { background: #f0f8ff; padding: 10px; border-left: 4px solid #0073aa; margin: 10px 0; }\n                table { width: 100%; border-collapse: collapse; margin: 20px 0; }\n                th, td { border: 1px solid #ddd; padding: 12px; text-align: left; }\n                th { background-color: #f2f2f2; }\n                .bank-dropdown { width: 100%; padding: 8px; margin: 10px 0; }\n            &lt;\/style>\n        &lt;\/head>\n        &lt;body>\";\n        \n        echo \"&lt;h1>PagoMovil Bank List API Test - FINAL FIXED VERSION&lt;\/h1>\\n\";\n        echo \"&lt;p>&lt;strong>Base URL:&lt;\/strong> \" . $this->api_base_url . \"&lt;\/p>\\n\";\n        echo \"&lt;p>&lt;strong>Client GUID:&lt;\/strong> \" . substr($this->client_guid, 0, 8) . \"...&lt;\/p>\\n\";\n    }\n    \n    public function runTests() {\n        echo \"&lt;h2>Step 1: Authentication&lt;\/h2>\\n\";\n        if (!$this->authenticate()) {\n            echo \"&lt;p class='error'>&lt;strong>Authentication FAILED&lt;\/strong>&lt;\/p>\\n\";\n            return false;\n        }\n        \n        echo \"&lt;h2>Step 2: Get Bank List&lt;\/h2>\\n\";\n        $banks = $this->getBankList();\n        \n        if ($banks &amp;&amp; is_array($banks)) {\n            echo \"&lt;p class='success'>&lt;strong>Bank list retrieved successfully!&lt;\/strong>&lt;\/p>\\n\";\n            $this->displayBanks($banks);\n            $this->displayBankDropdown($banks);\n            return true;\n        } else {\n            echo \"&lt;p class='error'>&lt;strong>Failed to get bank list&lt;\/strong>&lt;\/p>\\n\";\n            return false;\n        }\n    }\n    \n    private function authenticate() {\n        echo \"&lt;p>Authenticating with bank API...&lt;\/p>\\n\";\n        \n        $auth_data = array('ClientGUID' => $this->client_guid);\n        $encrypted_data = $this->encrypt_data($auth_data, $this->master_key);\n        \n        if (!$encrypted_data) {\n            echo \"&lt;p class='error'>Encryption failed&lt;\/p>\\n\";\n            return false;\n        }\n        \n        $response = $this->make_api_call('\/api\/Auth\/LogOn', $encrypted_data);\n        \n        if ($response &amp;&amp; isset($response&#91;'status']) &amp;&amp; $response&#91;'status'] === 'OK') {\n            $decrypted_response = $this->decrypt_data($response&#91;'value'], $this->master_key);\n            \n            if ($decrypted_response === false) {\n                echo \"&lt;p class='error'>Decryption failed&lt;\/p>\\n\";\n                return false;\n            }\n            \n            echo \"&lt;div class='info'>&lt;strong>Decrypted authentication response:&lt;\/strong> \" . htmlspecialchars($decrypted_response) . \"&lt;\/div>\\n\";\n            \n            $response_data = json_decode($decrypted_response, true);\n            \n            if (isset($response_data&#91;'WorkingKey'])) {\n                $this->working_key = $response_data&#91;'WorkingKey'];\n                echo \"&lt;p class='success'>&lt;strong>Authentication SUCCESSFUL&lt;\/strong>&lt;\/p>\\n\";\n                echo \"&lt;p>WorkingKey obtained: \" . substr($this->working_key, 0, 20) . \"...&lt;\/p>\\n\";\n                return true;\n            } else {\n                echo \"&lt;p class='error'>WorkingKey not found in response&lt;\/p>\\n\";\n                if (isset($response_data&#91;'Message'])) {\n                    echo \"&lt;p>API Message: \" . htmlspecialchars($response_data&#91;'Message']) . \"&lt;\/p>\\n\";\n                }\n            }\n        } else {\n            echo \"&lt;p class='error'>Authentication failed: API status not OK&lt;\/p>\\n\";\n            if (isset($response&#91;'message'])) {\n                echo \"&lt;p>Error message: \" . htmlspecialchars($response&#91;'message']) . \"&lt;\/p>\\n\";\n            }\n        }\n        \n        return false;\n    }\n    \n    private function getBankList() {\n        echo \"&lt;p>Requesting bank list from API...&lt;\/p>\\n\";\n        \n        if (empty($this->working_key)) {\n            echo \"&lt;p class='error'>No WorkingKey available. Please authenticate first.&lt;\/p>\\n\";\n            return false;\n        }\n        \n        \/\/ Use empty object format which worked in your test\n        $bank_data = new stdClass();\n        $encrypted_data = $this->encrypt_data($bank_data, $this->working_key);\n        \n        if (!$encrypted_data) {\n            echo \"&lt;p class='error'>Bank data encryption failed&lt;\/p>\\n\";\n            return false;\n        }\n        \n        $response = $this->make_api_call('\/api\/Services\/Banks', $encrypted_data);\n        \n        if ($response &amp;&amp; isset($response&#91;'status']) &amp;&amp; $response&#91;'status'] === 'OK') {\n            $decrypted_response = $this->decrypt_data($response&#91;'value'], $this->working_key);\n            \n            if ($decrypted_response === false) {\n                echo \"&lt;p class='error'>Bank list decryption failed&lt;\/p>\\n\";\n                return false;\n            }\n            \n            echo \"&lt;div class='info'>\";\n            echo \"&lt;p>&lt;strong>Decrypted bank list response length:&lt;\/strong> \" . strlen($decrypted_response) . \" characters&lt;\/p>\\n\";\n            \n            \/\/ FIX: Clean UTF-8 encoding before JSON decoding\n            $clean_response = $this->clean_utf8($decrypted_response);\n            \n            \/\/ Try to decode JSON with error handling\n            $banks = json_decode($clean_response, true);\n            \n            if (json_last_error() !== JSON_ERROR_NONE) {\n                echo \"&lt;p class='error'>JSON decode error: \" . json_last_error_msg() . \"&lt;\/p>\\n\";\n                \n                \/\/ Try to fix common JSON issues\n                $fixed_response = $this->fix_json($clean_response);\n                $banks = json_decode($fixed_response, true);\n                \n                if (json_last_error() !== JSON_ERROR_NONE) {\n                    echo \"&lt;p class='error'>Still cannot decode JSON after fixes. Showing raw data:&lt;\/p>\\n\";\n                    echo \"&lt;pre>\" . htmlspecialchars($clean_response) . \"&lt;\/pre>\\n\";\n                    return false;\n                }\n            }\n            \n            echo \"&lt;\/div>\";\n            return $banks;\n        } else {\n            echo \"&lt;p class='error'>Bank list API returned non-OK status&lt;\/p>\\n\";\n            if (isset($response&#91;'message'])) {\n                echo \"&lt;p>Error message: \" . htmlspecialchars($response&#91;'message']) . \"&lt;\/p>\\n\";\n            }\n        }\n        \n        return false;\n    }\n    \n    \/**\n     * Clean UTF-8 encoding issues\n     *\/\n    private function clean_utf8($string) {\n        \/\/ First, try to detect encoding and convert to UTF-8\n        $encoding = mb_detect_encoding($string, &#91;'UTF-8', 'ISO-8859-1', 'Windows-1252'], true);\n        \n        if ($encoding &amp;&amp; $encoding != 'UTF-8') {\n            $string = mb_convert_encoding($string, 'UTF-8', $encoding);\n        }\n        \n        \/\/ Remove any invalid UTF-8 characters\n        $string = mb_convert_encoding($string, 'UTF-8', 'UTF-8');\n        \n        \/\/ Replace common problematic characters\n        $string = str_replace(\n            &#91;'\u00c3\u00a1', '\u00c3\u00a9', '\u00c3\u00ad', '\u00c3\u00b3', '\u00c3\u00ba', '\u00c3\u00b1', '\u00c3\u0081', '\u00c3\u2030', '\u00c3\u008d', '\u00c3\u201c', '\u00c3\u0161', '\u00c3\u2018'],\n            &#91;'\u00e1', '\u00e9', '\u00ed', '\u00f3', '\u00fa', '\u00f1', '\u00c1', '\u00c9', '\u00cd', '\u00d3', '\u00da', '\u00d1'],\n            $string\n        );\n        \n        return $string;\n    }\n    \n    \/**\n     * Fix common JSON formatting issues\n     *\/\n    private function fix_json($json_string) {\n        \/\/ Remove BOM if present\n        $json_string = str_replace(\"\\xEF\\xBB\\xBF\", '', $json_string);\n        \n        \/\/ Trim whitespace\n        $json_string = trim($json_string);\n        \n        return $json_string;\n    }\n    \n    private function make_api_call($endpoint, $data) {\n        $url = $this->api_base_url . $endpoint;\n        \n        echo \"&lt;div class='info'>\\n\";\n        echo \"&lt;p>&lt;strong>API Request:&lt;\/strong>&lt;\/p>\\n\";\n        echo \"&lt;p>Endpoint: \" . htmlspecialchars($url) . \"&lt;\/p>\\n\";\n        \n        $ch = curl_init();\n        curl_setopt_array($ch, &#91;\n            CURLOPT_URL => $url,\n            CURLOPT_RETURNTRANSFER => true,\n            CURLOPT_POST => true,\n            CURLOPT_POSTFIELDS => json_encode($data),\n            CURLOPT_HTTPHEADER => &#91;\n                'Content-Type: application\/json',\n                'User-Agent: Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/91.0.4472.124 Safari\/537.36'\n            ],\n            CURLOPT_TIMEOUT => 30,\n            CURLOPT_SSL_VERIFYPEER => false,\n            CURLOPT_SSL_VERIFYHOST => false,\n            CURLOPT_FOLLOWLOCATION => true\n        ]);\n        \n        $response = curl_exec($ch);\n        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);\n        $curl_error = curl_error($ch);\n        curl_close($ch);\n        \n        echo \"&lt;p>&lt;strong>HTTP Response Code:&lt;\/strong> \" . $http_code . \"&lt;\/p>\\n\";\n        \n        \/\/ HTTP 202 Accepted is a SUCCESS status\n        $success_codes = &#91;200, 202];\n        \n        if ($curl_error) {\n            echo \"&lt;p class='error'>&lt;strong>cURL Error:&lt;\/strong> \" . htmlspecialchars($curl_error) . \"&lt;\/p>\\n\";\n            echo \"&lt;\/div>\\n\";\n            return false;\n        }\n        \n        if (!in_array($http_code, $success_codes)) {\n            echo \"&lt;p class='error'>&lt;strong>HTTP Error:&lt;\/strong> \" . $http_code . \"&lt;\/p>\\n\";\n            echo \"&lt;p>&lt;strong>Raw Response:&lt;\/strong> \" . htmlspecialchars($response) . \"&lt;\/p>\\n\";\n            echo \"&lt;\/div>\\n\";\n            return false;\n        }\n        \n        echo \"&lt;\/div>\\n\";\n        \n        $decoded_response = json_decode($response, true);\n        \n        if (json_last_error() !== JSON_ERROR_NONE) {\n            echo \"&lt;p class='error'>JSON decode error: \" . json_last_error_msg() . \"&lt;\/p>\\n\";\n            return false;\n        }\n        \n        return $decoded_response;\n    }\n    \n    private function encrypt_data($data, $key) {\n        $plain_text = json_encode($data);\n        $salt = hex2bin('4976616e204d65647665646576'); \/\/ \"Ivan Medvedev\"\n        \n        \/\/ Use PBKDF2 to derive key and IV (exactly like Postman)\n        $derived_key = hash_pbkdf2('sha1', $key, $salt, 1000, 48, true);\n        $aes_key = substr($derived_key, 0, 32);\n        $iv = substr($derived_key, 32, 16);\n\n        \/\/ Convert to UTF-16LE (little endian) and encrypt\n        $plain_text_utf16 = '';\n        for ($i = 0; $i &lt; strlen($plain_text); $i++) {\n            $plain_text_utf16 .= $plain_text&#91;$i] . \"\\x00\";\n        }\n\n        $cipher_text = openssl_encrypt(\n            $plain_text_utf16,\n            'AES-256-CBC',\n            $aes_key,\n            OPENSSL_RAW_DATA,\n            $iv\n        );\n\n        if ($cipher_text === false) {\n            echo \"&lt;p class='error'>Encryption failed: \" . openssl_error_string() . \"&lt;\/p>\\n\";\n            return false;\n        }\n\n        $validation = hash('sha256', $plain_text);\n\n        return array(\n            'ClientGUID' => $this->client_guid,\n            'Reference' => 'REF' . time(),\n            'Value' => base64_encode($cipher_text),\n            'Validation' => $validation,\n            'swTestOperation' => false\n        );\n    }\n    \n    private function decrypt_data($encrypted_data, $key) {\n        $salt = hex2bin('4976616e204d65647665646576');\n        $derived_key = hash_pbkdf2('sha1', $key, $salt, 1000, 48, true);\n        $aes_key = substr($derived_key, 0, 32);\n        $iv = substr($derived_key, 32, 16);\n\n        $decrypted = openssl_decrypt(\n            base64_decode($encrypted_data),\n            'AES-256-CBC',\n            $aes_key,\n            OPENSSL_RAW_DATA,\n            $iv\n        );\n\n        if ($decrypted === false) {\n            echo \"&lt;p class='error'>Decryption failed: \" . openssl_error_string() . \"&lt;\/p>\\n\";\n            return false;\n        }\n\n        \/\/ Convert from UTF-16LE to UTF-8\n        $result = '';\n        for ($i = 0; $i &lt; strlen($decrypted); $i += 2) {\n            if ($decrypted&#91;$i] != \"\\x00\") {\n                $result .= $decrypted&#91;$i];\n            }\n        }\n\n        return $result;\n    }\n    \n    private function displayBanks($banks) {\n        if (!is_array($banks) || empty($banks)) {\n            echo \"&lt;p>No banks found in response&lt;\/p>\\n\";\n            return;\n        }\n        \n        echo \"&lt;h3>Complete Bank List (\" . count($banks) . \" banks found)&lt;\/h3>\\n\";\n        echo \"&lt;table>\\n\";\n        echo \"&lt;tr>&lt;th>Code&lt;\/th>&lt;th>Bank Name&lt;\/th>&lt;th>Services&lt;\/th>&lt;\/tr>\\n\";\n        \n        foreach ($banks as $bank) {\n            $code = htmlspecialchars($bank&#91;'Code'] ?? 'N\/A');\n            $name = htmlspecialchars($bank&#91;'Name'] ?? 'N\/A');\n            $services = htmlspecialchars($bank&#91;'Services'] ?? 'N\/A');\n            \n            echo \"&lt;tr>\\n\";\n            echo \"&lt;td>&lt;strong>{$code}&lt;\/strong>&lt;\/td>\\n\";\n            echo \"&lt;td>{$name}&lt;\/td>\\n\";\n            echo \"&lt;td>{$services}&lt;\/td>\\n\";\n            echo \"&lt;\/tr>\\n\";\n        }\n        \n        echo \"&lt;\/table>\\n\";\n    }\n    \n    private function displayBankDropdown($banks) {\n        if (!is_array($banks) || empty($banks)) {\n            echo \"&lt;p>No banks available for dropdown&lt;\/p>\\n\";\n            return;\n        }\n        \n        echo \"&lt;h3>Bank Selection Dropdown&lt;\/h3>\\n\";\n        echo \"&lt;select class='bank-dropdown' onchange='showSelectedBank(this)'>\\n\";\n        echo \"&lt;option value=''>-- Select Your Bank --&lt;\/option>\\n\";\n        \n        foreach ($banks as $bank) {\n            $code = htmlspecialchars($bank&#91;'Code'] ?? '');\n            $name = htmlspecialchars($bank&#91;'Name'] ?? '');\n            $services = htmlspecialchars($bank&#91;'Services'] ?? '');\n            \n            $displayText = \"{$code}: {$name}\";\n            if (!empty($services)) {\n                $displayText .= \" ({$services})\";\n            }\n            \n            $value = \"{$code}|{$name}\";\n            \n            echo \"&lt;option value='{$value}'>{$displayText}&lt;\/option>\\n\";\n        }\n        \n        echo \"&lt;\/select>\\n\";\n        \n        echo \"\n        &lt;script>\n        function showSelectedBank(select) {\n            if(select.value) {\n                const &#91;code, name] = select.value.split('|');\n                alert('Selected Bank: ' + code + ' - ' + name);\n            }\n        }\n        &lt;\/script>\n        \";\n        \n        \/\/ Also show BNC bank specifically if found\n        $bnc_found = false;\n        foreach ($banks as $bank) {\n            if (($bank&#91;'Code'] ?? '') === '0191') {\n                $bnc_found = true;\n                echo \"&lt;div class='success'>\\n\";\n                echo \"&lt;h4>\u2713 BNC Bank Found and Available&lt;\/h4>\\n\";\n                echo \"&lt;p>&lt;strong>Code:&lt;\/strong> \" . htmlspecialchars($bank&#91;'Code'] ?? '') . \"&lt;\/p>\\n\";\n                echo \"&lt;p>&lt;strong>Name:&lt;\/strong> \" . htmlspecialchars($bank&#91;'Name'] ?? '') . \"&lt;\/p>\\n\";\n                echo \"&lt;p>&lt;strong>Services:&lt;\/strong> \" . htmlspecialchars($bank&#91;'Services'] ?? '') . \"&lt;\/p>\\n\";\n                echo \"&lt;\/div>\\n\";\n                break;\n            }\n        }\n    }\n    \n    public function __destruct() {\n        echo \"&lt;\/body>\\n&lt;\/html>\";\n    }\n}\n\n\/\/ Check if required extensions are available\nif (!extension_loaded('openssl')) {\n    die(\"&lt;p class='error'>&lt;strong>ERROR:&lt;\/strong> OpenSSL extension is required but not loaded.&lt;\/p>\\n\");\n}\n\nif (!extension_loaded('mbstring')) {\n    die(\"&lt;p class='error'>&lt;strong>ERROR:&lt;\/strong> MBString extension is required for UTF-8 handling but not loaded.&lt;\/p>\\n\");\n}\n\nif (!function_exists('hash_pbkdf2')) {\n    die(\"&lt;p class='error'>&lt;strong>ERROR:&lt;\/strong> hash_pbkdf2() function is required but not available. Please upgrade PHP.&lt;\/p>\\n\");\n}\n\n\/\/ Run the test\n$test = new PagoMovilBankTest();\n$success = $test->runTests();\n\necho \"&lt;hr>\\n\";\nif ($success) {\n    echo \"&lt;h2 class='success'>\u2713 TEST COMPLETED SUCCESSFULLY&lt;\/h2>\\n\";\n    echo \"&lt;p>The bank list has been successfully retrieved and displayed in both table and dropdown format.&lt;\/p>\\n\";\n} else {\n    echo \"&lt;h2 class='error'>\u2717 TEST FAILED&lt;\/h2>\\n\";\n    echo \"&lt;p>Check the error messages above for troubleshooting.&lt;\/p>\\n\";\n}\n\necho \"&lt;h3>Next Steps for Your WooCommerce Plugin:&lt;\/h3>\\n\";\necho \"&lt;ul>\\n\";\necho \"&lt;li>Use the 'empty_object' format ({}) for bank list requests&lt;\/li>\\n\";\necho \"&lt;li>Implement similar UTF-8 cleaning in your main plugin&lt;\/li>\\n\";\necho \"&lt;li>Use the dropdown format: 'Code: Bank Name (Services)'&lt;\/li>\\n\";\necho \"&lt;li>BNC bank code 0191 is confirmed available&lt;\/li>\\n\";\necho \"&lt;\/ul>\\n\";\n?><\/code><\/pre>","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-1399","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.dugtour.com\/es\/wp-json\/wp\/v2\/pages\/1399","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dugtour.com\/es\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.dugtour.com\/es\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.dugtour.com\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dugtour.com\/es\/wp-json\/wp\/v2\/comments?post=1399"}],"version-history":[{"count":1,"href":"https:\/\/www.dugtour.com\/es\/wp-json\/wp\/v2\/pages\/1399\/revisions"}],"predecessor-version":[{"id":1400,"href":"https:\/\/www.dugtour.com\/es\/wp-json\/wp\/v2\/pages\/1399\/revisions\/1400"}],"wp:attachment":[{"href":"https:\/\/www.dugtour.com\/es\/wp-json\/wp\/v2\/media?parent=1399"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}