Plugin Directory

Changeset 3462156


Ignore:
Timestamp:
02/16/2026 02:33:16 AM (6 weeks ago)
Author:
tripleatechnology
Message:

testing v2.0.27

Location:
triplea-cryptocurrency-payment-gateway-for-woocommerce/trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • triplea-cryptocurrency-payment-gateway-for-woocommerce/trunk/includes/WooCommerce/TripleA_Payment_Gateway.php

    r3446959 r3462156  
    6363        $this->clientID         = $this->get_option('client_id');
    6464        $this->clientSecret     = $this->decrypt_credential($this->get_option('client_secret'));
    65         $this->oauthToken       = $this->get_option('oauth_token');
     65        $this->oauthToken       = $this->decrypt_credential($this->get_option('oauth_token'));
    6666        $this->oauthTokenExpiry = $this->get_option('oauth_token_expiry');
    6767
    6868        $this->logger           = Logger::get_instance();
     69
     70        // Migrate plaintext OAuth token to encrypted storage (one-time migration for existing installations)
     71        if (!empty($this->oauthToken) && strpos($this->get_option('oauth_token'), 'ENC:') !== 0) {
     72            // Token exists in plaintext (not encrypted) - migrate it
     73            $encrypted_token = $this->encrypt_credential($this->oauthToken);
     74            if ($encrypted_token !== false) {
     75                $this->update_option('oauth_token', $encrypted_token);
     76                $this->logger->write_log('OAuth token successfully migrated to encrypted storage', true);
     77            } else {
     78                $this->logger->write_log('MIGRATION ERROR: Failed to encrypt existing OAuth token. Check TRIPLEA_ENCRYPTION_KEY in wp-config.php', true);
     79            }
     80        }
    6981
    7082        $this->triplea_set_api_endpoint_token();
     
    158170        // Nonce is verified by WooCommerce settings save process
    159171        $client_secret_raw = null;
    160         $client_secret_posted = !empty($_POST['woocommerce_triplea_payment_gateway_client_secret']) ? sanitize_text_field(wp_unslash($_POST['woocommerce_triplea_payment_gateway_client_secret'])) : '';
     172        $client_secret_posted = '';
     173
     174        if (!empty($_POST['woocommerce_triplea_payment_gateway_client_secret'])) {
     175            $client_secret_posted = wp_unslash($_POST['woocommerce_triplea_payment_gateway_client_secret']);
     176
     177            // Validate format: alphanumeric + common special chars, 16-256 chars
     178            if (!preg_match('/^[a-zA-Z0-9\-_+=\/]{16,256}$/', $client_secret_posted)) {
     179                add_settings_error(
     180                    'triplea_payment_gateway',
     181                    'invalid_client_secret',
     182                    __('Invalid client secret format. Must be 16-256 characters (alphanumeric and -_+=/)', 'triplea-cryptocurrency-payment-gateway-for-woocommerce'),
     183                    'error'
     184                );
     185                return; // Stop processing
     186            }
     187        }
    161188
    162189        // Check if encryption key is defined
     
    200227            }
    201228
    202             $response = wp_remote_post('https://api.triple-a.io/api/v2/oauth/token', array(
    203                 'headers' => array(
    204                     'Content-Type' => 'application/x-www-form-urlencoded',
    205                 ),
    206                 'body' => array(
    207                     'client_id' => isset($_POST['woocommerce_triplea_payment_gateway_client_id']) ? sanitize_text_field(wp_unslash($_POST['woocommerce_triplea_payment_gateway_client_id'])) : '',
     229            $client_id_posted = '';
     230            if (!empty($_POST['woocommerce_triplea_payment_gateway_client_id'])) {
     231                $client_id_posted = wp_unslash($_POST['woocommerce_triplea_payment_gateway_client_id']);
     232
     233                // Validate format: alphanumeric + common special chars
     234                if (!preg_match('/^[a-zA-Z0-9\-_]{8,128}$/', $client_id_posted)) {
     235                    add_settings_error(
     236                        'triplea_payment_gateway',
     237                        'invalid_client_id',
     238                        __('Invalid client ID format. Must be 8-128 characters (alphanumeric and -_)', 'triplea-cryptocurrency-payment-gateway-for-woocommerce'),
     239                        'error'
     240                    );
     241                    return;
     242                }
     243            }
     244
     245            $response = $this->secure_post(
     246                'https://api.triple-a.io/api/v2/oauth/token',
     247                [
     248                    'client_id'     => $client_id_posted,
    208249                    'client_secret' => $client_secret_raw,
    209                     'grant_type' => 'client_credentials',
    210                 ),
    211             ));
    212 
    213             if (!is_wp_error($response)) {
    214                 // The request went through successfully, check the response code against
    215                 // what we're expecting
    216                 if (200 == wp_remote_retrieve_response_code($response)) {
    217                     // Do something with the response
    218                     $body = json_decode(wp_remote_retrieve_body($response));
    219                 } else {
    220                     // The response code was not what we were expecting, record the message
    221                     $error_message = wp_remote_retrieve_response_message($response);
    222                 }
     250                    'grant_type'    => 'client_credentials',
     251                ]
     252            );
     253
     254            if (!$response['error'] && $response['code'] === 200) {
     255                $body = json_decode($response['body']);
    223256            } else {
    224257                // There was an error making the request
    225                 $error_message = $response->get_error_message();
     258                $error_message = $response['error'] ?: 'HTTP ' . $response['code'];
    226259            }
    227260            //exit;
    228261
    229             $this->settings['oauth_token'] = $body->access_token;
    230             $this->settings['oauth_token_expiry'] = $body->expires_in;
     262            if (isset($body->access_token)) {
     263                $this->settings['oauth_token'] = $this->encrypt_credential($body->access_token);
     264                $this->settings['oauth_token_expiry'] = time() + $body->expires_in;
     265            }
    231266        }
    232267
     
    747782                $this->oauthToken       = $new_token_data->access_token;
    748783                $this->oauthTokenExpiry = $date_now + $new_token_data->expires_in;
    749                 $this->update_option('oauth_token', $this->oauthToken);
     784                $this->update_option('oauth_token', $this->encrypt_credential($this->oauthToken));
    750785                $this->update_option('oauth_token_expiry', $this->oauthTokenExpiry);
    751786                $this->logger->write_log('refreshOauthToken() Obtained and saved a new oauth token.', $this->debugLog);
     
    779814        $buffer_time     = 600; // 10 min buffer time, so new token will generated after 50 min
    780815        $current_token_expiry   = intval($this->get_option('oauth_token_expiry'));
    781         $current_token   = $this->get_option('oauth_token');
     816        $current_token_encrypted   = $this->get_option('oauth_token');
     817        $current_token   = $this->decrypt_credential($current_token_encrypted);
    782818
    783819        if ($this->isOauthTokenInvalid()) {
     
    800836                $this->oauthToken       = $new_token_data->access_token;
    801837                $this->oauthTokenExpiry = $date_now + $new_token_data->expires_in;
    802                 $this->update_option('oauth_token', $this->oauthToken);
     838                $this->update_option('oauth_token', $this->encrypt_credential($this->oauthToken));
    803839                $this->update_option('oauth_token_expiry', $this->oauthTokenExpiry);
    804840
     
    831867    {
    832868
    833         $post_url = 'https://api.triple-a.io/api/v2/oauth/token';
    834         $body     = [
    835             'client_id'     => $client_id,
    836             'client_secret' => $client_secret,
    837             'grant_type'    => 'client_credentials',
    838         ];
    839 
    840         // $this->logger->write_log( 'Making an oauth token request with body: \n' . wc_print_r($body, TRUE), $this->debugLog );
    841         $this->logger->write_log('Making an oauth token request with clinet id: \n' . wc_print_r($client_id, true), $this->debugLog);
    842 
    843         $result = wp_remote_post($post_url, [
    844             'method'      => 'POST',
    845             'headers'     => [
    846                 'content-type' => 'application/x-www-form-urlencoded; charset=utf-8',
    847             ],
    848             //'sslverify' => false,
    849             'body'        => $body,
    850             'data_format' => 'body',
    851         ]);
    852 
    853         if (is_wp_error($result)) {
     869        $this->logger->write_log('Making an oauth token request with client id: \n' . wc_print_r($client_id, true), $this->debugLog);
     870
     871        $response = $this->secure_post(
     872            'https://api.triple-a.io/api/v2/oauth/token',
     873            [
     874                'client_id'     => $client_id,
     875                'client_secret' => $client_secret,
     876                'grant_type'    => 'client_credentials',
     877            ]
     878        );
     879
     880        if ($response['error'] || $response['code'] !== 200) {
     881            $this->logger->write_log('OAuth token request failed with code: ' . $response['code'], $this->debugLog);
    854882            return ['error' => 'Error happened, could not complete the oauth token request.'];
    855883        }
    856884
    857         $this->logger->write_log("Oauth token request object: \n" . wc_print_r($result['body'], true), $this->debugLog);
    858 
    859         return json_decode($result['body']);
     885        $this->logger->write_log('OAuth token request completed successfully', $this->debugLog);
     886
     887        return json_decode($response['body']);
    860888    }
    861889    public static function custom_user_agent($user_agent, $url)
     
    912940        $self->logger->write_log('Making a payment form API request with body: ' . wc_print_r($body, true), $self->debugLog);
    913941
    914         $result = wp_remote_post($post_url, [
    915             'method'      => 'POST',
    916             'headers'     => [
     942        $response = $self->secure_post(
     943            'https://api.triple-a.io/api/v2/payment',
     944            json_encode($body),
     945            [
    917946                'Authorization' => 'Bearer ' . $oauth_token,
    918947                'Content-Type'  => 'application/json; charset=utf-8',
    919             ],
    920             //'sslverify' => false,
    921             'body'        => json_encode($body),
    922             'data_format' => 'body',
    923         ]);
    924 
    925         if (is_wp_error($result)) {
     948            ]
     949        );
     950
     951        if ($response['error']) {
    926952            return ['error' => 'Error happened, could not complete the payment form request.'];
    927953        }
    928         $self->logger->write_log('Payment form request response: \n' . wc_print_r($result['body'], true), $self->debugLog);
    929 
    930         if ($result['response']['code'] > 299) {
     954
     955        $self->logger->write_log('Payment form request completed with code: ' . $response['code'], $self->debugLog);
     956
     957        if ($response['code'] > 299) {
    931958            return json_encode([
    932959                'error'   => 'Error happened, could not complete the payment form request.',
    933                 'code'    => $result['response']['code'],
    934                 'message' => $result['response']['message'],
     960                'code'    => $response['code'],
     961                'message' => 'HTTP Error',
    935962            ]);
    936963        }
    937964
    938         $json_result = json_decode($result['body']);
     965        $json_result = json_decode($response['body']);
    939966        if (!isset($json_result->payment_reference)) {
    940967            return json_encode([
     
    16431670    {
    16441671
    1645         $oauth_token = $this->get_option('oauth_token');
     1672        $oauth_token = $this->decrypt_credential($this->get_option('oauth_token'));
    16461673        if (empty($oauth_token)) {
    16471674            wp_die('Missing oauth token for bitcoin payments with local currency settlement.');
    16481675        }
    16491676
    1650         $post_url = "https://api.triple-a.io/api/v2/payment/$payment_reference";
    1651 
    1652         $result = wp_remote_get($post_url, [
    1653             'headers'     => [
    1654                 'Authorization' => 'Bearer ' . $oauth_token,
    1655             ],
    1656             //'sslverify' => false,
    1657             //'body'        => json_encode($body),
    1658             'data_format' => 'body',
     1677        $url = 'https://api.triple-a.io/api/v2/payment/' . urlencode($payment_reference);
     1678
     1679        $response = $this->secure_get($url, [
     1680            'Authorization' => 'Bearer ' . $oauth_token,
    16591681        ]);
    16601682
    1661         if (is_wp_error($result)) {
    1662             wp_die('Could not complete the payment status API request.');
    1663         }
    1664 
    1665         if ($result['response']['code'] > 299) {
     1683        if ($response['error']) {
     1684            return (object) [
     1685                'error'   => 'Could not complete the payment status API request.',
     1686                'code'    => 0,
     1687                'message' => $response['error'],
     1688            ];
     1689        }
     1690
     1691        if ($response['code'] > 299) {
    16661692            return (object) [
    16671693                'error'   => 'Error happened, could not complete the payment form request.',
    1668                 'code'    => $result['response']['code'],
    1669                 'message' => $result['response']['message'],
     1694                'code'    => $response['code'],
     1695                'message' => 'HTTP Error',
    16701696            ];
    16711697        }
    16721698
    1673         $json_result = json_decode($result['body']);
     1699        $json_result = json_decode($response['body']);
    16741700        if (!isset($json_result->payment_reference)) {
    16751701            return [
     
    25732599        return true;
    25742600    }
     2601
     2602    /**
     2603     * Secure POST request bypassing WordPress HTTP filters
     2604     * Prevents credential interception by third-party plugins
     2605     *
     2606     * @param string $url
     2607     * @param array|string $body
     2608     * @param array $headers
     2609     * @return array
     2610     */
     2611    private function secure_post($url, $body, $headers = [])
     2612    {
     2613        // Validate API endpoint - only allow TripleA API calls
     2614        if (strpos($url, 'https://api.triple-a.io/') !== 0) {
     2615            if (isset($this->logger)) {
     2616                $this->logger->write_log('secure_post(): Blocked invalid API endpoint: ' . $url, true);
     2617            }
     2618            return [
     2619                'body'  => '',
     2620                'code'  => 0,
     2621                'error' => 'Invalid API endpoint',
     2622            ];
     2623        }
     2624
     2625        $ch = curl_init($url);
     2626
     2627        $header_array = [];
     2628        $has_content_type = false;
     2629
     2630        // Add User-Agent header matching existing custom_user_agent() format
     2631        $version = get_option('wc_triplea_crypto_payment_version');
     2632        $default_user_agent = 'WordPress/' . get_bloginfo('version') . '; ' . get_bloginfo('url');
     2633        $header_array[] = 'User-Agent: ' . $default_user_agent . '; wc_triplea_crypto_payment:' . $version;
     2634
     2635        foreach ($headers as $key => $value) {
     2636            $header_array[] = "$key: $value";
     2637            if (strtolower($key) === 'content-type') {
     2638                $has_content_type = true;
     2639            }
     2640        }
     2641
     2642        if (is_array($body)) {
     2643            $body = http_build_query($body);
     2644            if (!$has_content_type) {
     2645                $header_array[] = 'Content-Type: application/x-www-form-urlencoded';
     2646            }
     2647        }
     2648
     2649        curl_setopt_array($ch, [
     2650            CURLOPT_POST           => true,
     2651            CURLOPT_POSTFIELDS     => $body,
     2652            CURLOPT_HTTPHEADER     => $header_array,
     2653            CURLOPT_RETURNTRANSFER => true,
     2654            CURLOPT_TIMEOUT        => 30,
     2655            CURLOPT_SSL_VERIFYPEER => true,
     2656            CURLOPT_SSL_VERIFYHOST => 2,
     2657        ]);
     2658
     2659        $result = curl_exec($ch);
     2660        $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
     2661        $error = curl_error($ch);
     2662        curl_close($ch);
     2663
     2664        return [
     2665            'body'  => $result,
     2666            'code'  => $code,
     2667            'error' => $error ?: null,
     2668        ];
     2669    }
     2670
     2671    /**
     2672     * Secure GET request bypassing WordPress HTTP filters
     2673     *
     2674     * @param string $url
     2675     * @param array $headers
     2676     * @return array
     2677     */
     2678    private function secure_get($url, $headers = [])
     2679    {
     2680        // Validate API endpoint - only allow TripleA API calls
     2681        if (strpos($url, 'https://api.triple-a.io/') !== 0) {
     2682            if (isset($this->logger)) {
     2683                $this->logger->write_log('secure_get(): Blocked invalid API endpoint: ' . $url, true);
     2684            }
     2685            return [
     2686                'body'  => '',
     2687                'code'  => 0,
     2688                'error' => 'Invalid API endpoint',
     2689            ];
     2690        }
     2691
     2692        $ch = curl_init($url);
     2693
     2694        $header_array = [];
     2695        // Add User-Agent header matching existing custom_user_agent() format
     2696        $version = get_option('wc_triplea_crypto_payment_version');
     2697        $default_user_agent = 'WordPress/' . get_bloginfo('version') . '; ' . get_bloginfo('url');
     2698        $header_array[] = 'User-Agent: ' . $default_user_agent . '; wc_triplea_crypto_payment:' . $version;
     2699
     2700        foreach ($headers as $key => $value) {
     2701            $header_array[] = "$key: $value";
     2702        }
     2703
     2704        curl_setopt_array($ch, [
     2705            CURLOPT_HTTPGET        => true,
     2706            CURLOPT_HTTPHEADER     => $header_array,
     2707            CURLOPT_RETURNTRANSFER => true,
     2708            CURLOPT_TIMEOUT        => 30,
     2709            CURLOPT_SSL_VERIFYPEER => true,
     2710            CURLOPT_SSL_VERIFYHOST => 2,
     2711        ]);
     2712
     2713        $result = curl_exec($ch);
     2714        $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
     2715        $error = curl_error($ch);
     2716        curl_close($ch);
     2717
     2718        return [
     2719            'body'  => $result,
     2720            'code'  => $code,
     2721            'error' => $error ?: null,
     2722        ];
     2723    }
     2724
    25752725}
  • triplea-cryptocurrency-payment-gateway-for-woocommerce/trunk/readme.txt

    r3449218 r3462156  
    77Requires at least: 5.5
    88Tested up to: 6.9
    9 Stable tag: 2.0.26
     9Stable tag: 2.0.27
    1010Requires PHP: 7.0
    1111License: GPLv2 or later
     
    104104== Changelog ==
    105105
    106 = 2.0.26 - 2026-01-26 =
     106= 2.0.27 =
     107
     108* Improved error handling for API request failures
     109* Added URL allowlist validation for API endpoints
     110* User-Agent header added to all API requests
     111* Requires TRIPLEA_ENCRYPTION_KEY in wp-config.php (see installation instructions)
     112
     113= 2.0.26 =
    107114* Improved: Code quality and performance enhancements
    108115* Fix: WordPress 6.9 compatibility
     
    331338== Upgrade Notice ==
    332339
     340= 2.0.27 =
     341CRITICAL SECURITY UPDATE - Immediate update recommended. Before updating, add TRIPLEA_ENCRYPTION_KEY to wp-config.php. Generate key with: openssl rand -base64 32. Then add: define('TRIPLEA_ENCRYPTION_KEY', 'your-generated-key'); Existing credentials will be automatically migrated to encrypted storage. See installation instructions for full details.
     342
    333343= 2.0.22 =
    334344Simply install the update. No further action is needed.
  • triplea-cryptocurrency-payment-gateway-for-woocommerce/trunk/triplea-cryptocurrency-payment-gateway-for-woocommerce.php

    r3449218 r3462156  
    1717 * Plugin URI:        https://wordpress.org/plugins/triplea-cryptocurrency-payment-gateway-for-woocommerce/
    1818 * Description:       Offer cryptocurrency as a payment option on your website and get access to even more clients. Receive payments in cryptocurrency or in your local currency, directly in your bank account. Enjoy an easy setup, no cryptocurrency expertise required. Powered by Triple-A.
    19  * Version:           2.0.26
     19 * Version:           2.0.27
    2020 * Author:            Triple-A Team
    2121 * Author URI:        https://triple-a.io
     
    4949     * $var string
    5050     */
    51     public const version = '2.0.26';
     51    public const version = '2.0.27';
    5252
    5353    /*
Note: See TracChangeset for help on using the changeset viewer.