Plugin Directory

Changeset 3424485


Ignore:
Timestamp:
12/21/2025 07:05:08 AM (3 months ago)
Author:
aushamim
Message:

Update to version 1.8.12 from GitHub

Location:
subscription
Files:
30 edited
1 copied

Legend:

Unmodified
Added
Removed
  • subscription/tags/1.8.12/changelog.txt

    r3419216 r3424485  
    11*** WPSubscription Changelog ***
     2
     32025-12-21 - version 1.8.12
     4* fix: Subscription details default endpoint.
     5* fix: Proper subscription timings.
     6* fix: WordPress test up to version.
     7* fix: Other minor bugs.
    28
    392025-12-14 - version 1.8.11
  • subscription/tags/1.8.12/includes/Admin/Subscriptions.php

    r3392314 r3424485  
    137137            if ( 'subscrpt_start_date' === $column ) {
    138138                $start_date = get_post_meta( $post_id, '_subscrpt_start_date', true );
    139                 echo ! empty( $start_date ) ? esc_html( gmdate( 'F d, Y', $start_date ) ) : '-';
     139                echo ! empty( $start_date ) ? esc_html( wp_date( 'F d, Y', $start_date ) ) : '-';
    140140            } elseif ( 'subscrpt_customer' === $column ) {
    141141                ?>
     
    151151            } elseif ( 'subscrpt_next_date' === $column ) {
    152152                $next_date = get_post_meta( $post_id, '_subscrpt_next_date', true );
    153                 echo ! empty( $next_date ) ? esc_html( gmdate( 'F d, Y', $next_date ) ) : '-';
     153                echo ! empty( $next_date ) ? esc_html( wp_date( 'F d, Y', $next_date ) ) : '-';
    154154            } elseif ( 'subscrpt_status' === $column ) {
    155155                $status_obj = get_post_status_object( get_post_status( $post_id ) );
     
    377377            'start_date'       => array(
    378378                'label' => __( 'Started date', 'wp_subscription' ),
    379                 'value' => ! empty( $start_date ) ? gmdate( 'F d, Y', $trial && $trial_start_date ? $trial_start_date : $start_date ) : '-',
     379                'value' => ! empty( $start_date ) ? wp_date( 'F d, Y', $trial && $trial_start_date ? $trial_start_date : $start_date ) : '-',
    380380            ),
    381381            'next_date'        => array(
    382382                'label' => __( 'Payment due date', 'wp_subscription' ),
    383                 'value' => ! empty( $next_date ) ? gmdate( 'F d, Y', $trial && $trial_end_date && 'on' === $trial_mode ? $trial_end_date : ( $next_date ?? '-' ) ) : '-',
     383                'value' => ! empty( $next_date ) ? wp_date( 'F d, Y', $trial && $trial_end_date && 'on' === $trial_mode ? $trial_end_date : ( $next_date ?? '-' ) ) : '-',
    384384            ),
    385385            'status'           => array(
     
    408408                'trial_period' => array(
    409409                    'label' => __( 'Trial Period', 'wp_subscription' ),
    410                     'value' => ( $trial_start_date && $trial_end_date ? ' [ ' . gmdate( 'F d, Y', $trial_start_date ) . ' - ' . gmdate( 'F d, Y', $trial_end_date ) . ' ] ' : __( 'Trial isn\'t activated yet! ', 'wp_subscription' ) ),
     410                    'value' => ( $trial_start_date && $trial_end_date ? ' [ ' . wp_date( 'F d, Y', $trial_start_date ) . ' - ' . wp_date( 'F d, Y', $trial_end_date ) . ' ] ' : __( 'Trial isn\'t activated yet! ', 'wp_subscription' ) ),
    411411                ),
    412412            ) + array_slice( $rows, 3, count( $rows ) - 1, true );
     
    488488
    489489        $started_date = $subscription_data['start_date'] ?? '';
    490         $started_date = ! empty( $started_date ) ? gmdate( 'F j, Y - g:i A', strtotime( $started_date ) ) : '-';
     490        $started_date = ! empty( $started_date ) ? wp_date( 'F j, Y - g:i A', strtotime( $started_date ) ) : '-';
    491491
    492492        $next_payment_date = $subscription_data['next_date'] ?? '';
    493         $next_payment_date = ! empty( $next_payment_date ) ? gmdate( 'F j, Y - g:i A', strtotime( $next_payment_date ) ) : '-';
     493        $next_payment_date = ! empty( $next_payment_date ) ? wp_date( 'F j, Y - g:i A', strtotime( $next_payment_date ) ) : '-';
    494494
    495495        $is_grace_period = isset( $subscription_data['grace_period'] );
    496496        $grace_remaining = $subscription_data['grace_period']['remaining_days'] ?? 0;
    497497        $grace_end_date  = $subscription_data['grace_period']['end_date'] ?? '';
    498         $grace_end_date  = ! empty( $grace_end_date ) ? gmdate( 'F j, Y - g:i A', strtotime( $grace_end_date ) ) : '';
     498        $grace_end_date  = ! empty( $grace_end_date ) ? wp_date( 'F j, Y - g:i A', strtotime( $grace_end_date ) ) : '';
    499499
    500500        ?>
  • subscription/tags/1.8.12/includes/Admin/views/related-subscriptions.php

    r3381229 r3424485  
    4141
    4242            $start_date = $subscription_data['start_date'] ?? '';
    43             $start_date = ! empty( $start_date ) ? gmdate( 'F j, Y - g:i A', strtotime( $start_date ) ) : '-';
     43            $start_date = ! empty( $start_date ) ? wp_date( 'F j, Y - g:i A', strtotime( $start_date ) ) : '-';
    4444
    4545            $next_date = $subscription_data['next_date'] ?? '';
    46             $next_date = ! empty( $next_date ) ? gmdate( 'F j, Y - g:i A', strtotime( $next_date ) ) : '-';
     46            $next_date = ! empty( $next_date ) ? wp_date( 'F j, Y - g:i A', strtotime( $next_date ) ) : '-';
    4747
    4848            $price          = $subscription_data['price'] ?? 0;
  • subscription/tags/1.8.12/includes/Admin/views/subscription-info.php

    r3413403 r3424485  
    220220                    <tr>
    221221                        <th style="padding:8px 10px;">Started date</th>
    222                         <td style="padding:8px 10px;"><?php echo $start_date ? esc_html( gmdate( 'F d, Y', $start_date ) ) : '-'; ?></td>
     222                        <td style="padding:8px 10px;"><?php echo $start_date ? esc_html( wp_date( 'F d, Y', $start_date ) ) : '-'; ?></td>
    223223                    </tr>
    224224                    <tr>
    225225                        <th style="padding:8px 10px;">Payment due date</th>
    226                         <td style="padding:8px 10px;"><?php echo $renewal_date ? esc_html( gmdate( 'F d, Y', $renewal_date ) ) : '-'; ?></td>
     226                        <td style="padding:8px 10px;"><?php echo $renewal_date ? esc_html( wp_date( 'F d, Y', $renewal_date ) ) : '-'; ?></td>
    227227                    </tr>
    228228                    <tr>
  • subscription/tags/1.8.12/includes/Admin/views/subscription-list.php

    r3381229 r3424485  
    150150                        <?php endif; ?>
    151151                    </td>
    152                     <td><?php echo $start_date ? esc_html( gmdate( 'F d, Y', $start_date ) ) : '-'; ?></td>
    153                     <td><?php echo $renewal_date ? esc_html( gmdate( 'F d, Y', $renewal_date ) ) : '-'; ?></td>
     152                    <td><?php echo $start_date ? esc_html( wp_date( 'F d, Y', $start_date ) ) : '-'; ?></td>
     153                    <td><?php echo $renewal_date ? esc_html( wp_date( 'F d, Y', $renewal_date ) ) : '-'; ?></td>
    154154                    <td>
    155155                        <?php if ( $is_grace_period && $grace_remaining > 0 ) : ?>
  • subscription/tags/1.8.12/includes/Frontend/MyAccount.php

    r3419216 r3424485  
    100100
    101101        $start_date = $subscription_data['start_date'] ?? '';
    102         $start_date = ! empty( $start_date ) ? gmdate( 'F j, Y', strtotime( $start_date ) ) : '-';
     102        $start_date = ! empty( $start_date ) ? wp_date( 'F j, Y', strtotime( $start_date ) ) : '-';
    103103
    104104        $next_date = $subscription_data['next_date'] ?? '';
    105         $next_date = ! empty( $next_date ) ? gmdate( 'F j, Y', strtotime( $next_date ) ) : '-';
     105        $next_date = ! empty( $next_date ) ? wp_date( 'F j, Y', strtotime( $next_date ) ) : '-';
    106106
    107107        $trial      = get_post_meta( $id, '_subscrpt_trial', true );
     
    122122        $grace_remaining = $subscription_data['grace_period']['remaining_days'] ?? 0;
    123123        $grace_end_date  = $subscription_data['grace_period']['end_date'] ?? '';
    124         $grace_end_date  = ! empty( $grace_end_date ) ? gmdate( 'F j, Y', strtotime( $grace_end_date ) ) : '';
     124        $grace_end_date  = ! empty( $grace_end_date ) ? wp_date( 'F j, Y', strtotime( $grace_end_date ) ) : '';
    125125
    126126        $subscrpt_nonce = wp_create_nonce( 'subscrpt_nonce' );
  • subscription/tags/1.8.12/includes/Frontend/Order.php

    r3406135 r3424485  
    4747
    4848            $start_date_string = $subscription_data['start_date'] ?? '';
    49             $start_date        = ! empty( $start_date_string ) ? gmdate( 'F d, Y', strtotime( $start_date_string ) ) : '-';
     49            $start_date        = ! empty( $start_date_string ) ? wp_date( 'F d, Y', strtotime( $start_date_string ) ) : '-';
    5050
    5151            $next_date_string = $subscription_data['next_date'] ?? '';
    52             $next_date        = ! empty( $next_date_string ) ? gmdate( 'F d, Y', strtotime( $next_date_string ) ) : '-';
     52            $next_date        = ! empty( $next_date_string ) ? wp_date( 'F d, Y', strtotime( $next_date_string ) ) : '-';
    5353
    5454            $cost           = $subscription_data['price'] ?? '0.00';
  • subscription/tags/1.8.12/includes/Illuminate/Gateways/Paypal/Paypal.php

    r3349190 r3424485  
    416416     */
    417417    public function process_webhook() {
    418         if ( ! isset( $_GET['wc-api'] ) || $this->id !== $_GET['wc-api'] ) {
    419             wp_subscrpt_write_log( 'PayPal webhook called without valid API endpoint.' );
    420             return;
    421         }
    422 
    423         // Get Webhook Data.
    424         $webhook_data = stripslashes_deep( $_POST ); // phpcs:ignore WordPress.Security.NonceVerification
    425         $headers      = getallheaders();
    426 
    427         if ( empty( $webhook_data ) || ! count( $webhook_data ) ) {
    428             $post_data = file_get_contents( 'php://input' );
    429             // Sanitize the raw input before decoding.
    430             $post_data    = sanitize_text_field( $post_data );
    431             $webhook_data = json_decode( $post_data, true );
    432 
    433             if ( ! $webhook_data ) {
    434                 wp_subscrpt_write_log( 'Webhook data is empty.' );
    435                 wp_subscrpt_write_debug_log( "process_webhook EMPTY \n" . file_get_contents( 'php://input' ) );
    436                 exit( 'Webhook data is empty.' );
    437             }
     418        // Get raw webhook data.
     419        $raw_body = file_get_contents( 'php://input' );
     420        $headers  = function_exists( 'getallheaders' ) ? getallheaders() : [];
     421
     422        if ( empty( $raw_body ) ) {
     423            wp_subscrpt_write_log( 'PayPal webhook data is empty.' );
     424            wp_subscrpt_write_debug_log( "PayPal - process_webhook EMPTY \n" . $raw_body );
     425            wp_die( 'PayPal webhook data is empty.', '400 Bad Request', [ 'response' => 400 ] );
    438426        }
    439427
    440428        // Verify webhook.
    441         $this->verify_webhook( $headers, $webhook_data );
     429        $this->verify_webhook( $headers, $raw_body );
     430
     431        // Decode webhook data.
     432        $webhook_data = json_decode( $raw_body, true );
    442433
    443434        // Get event type from webhook data.
     
    526517     * Verify webhook data from PayPal.
    527518     *
    528      * @param array $headers       Headers from the request.
    529      * @param array $webhook_data Webhook data from PayPal.
    530      */
    531     public function verify_webhook( array $headers, array $webhook_data ) {
     519     * @param array  $headers       Headers from the request.
     520     * @param string $raw_body Webhook raw body from PayPal.
     521     */
     522    public function verify_webhook( array $headers, string $raw_body ) {
    532523        // Get PayPal Access Token.
    533524        $access_token = $this->get_paypal_access_token();
     
    537528        }
    538529
    539         // Prepare the request to verify the webhook.
     530        // Prepare the request data to verify the webhook.
    540531        $payload = [
    541             'auth_algo'         => $headers['Paypal-Auth-Algo'] ?? '',
    542             'cert_url'          => $headers['Paypal-Cert-Url'] ?? '',
    543             'transmission_id'   => $headers['Paypal-Transmission-Id'] ?? '',
    544             'transmission_sig'  => $headers['Paypal-Transmission-Sig'] ?? '',
    545             'transmission_time' => $headers['Paypal-Transmission-Time'] ?? '',
     532            'auth_algo'         => $headers['PAYPAL-AUTH-ALGO'] ?? $headers['Paypal-Auth-Algo'] ?? '',
     533            'cert_url'          => $headers['PAYPAL-CERT-URL'] ?? $headers['Paypal-Cert-Url'] ?? '',
     534            'transmission_id'   => $headers['PAYPAL-TRANSMISSION-ID'] ?? $headers['Paypal-Transmission-Id'] ?? '',
     535            'transmission_sig'  => $headers['PAYPAL-TRANSMISSION-SIG'] ?? $headers['Paypal-Transmission-Sig'] ?? '',
     536            'transmission_time' => $headers['PAYPAL-TRANSMISSION-TIME'] ?? $headers['Paypal-Transmission-Time'] ?? '',
    546537            'webhook_id'        => $this->webhook_id ?? '',
    547             'webhook_event'     => $webhook_data,
     538            'webhook_event'     => $raw_body,
    548539        ];
    549540
    550         $verified = $this->verify_paypal_webhook( $payload, $access_token );
     541        // Verify webhook via REST API.
     542        $verified = $this->verify_paypal_webhook_rest_api( $payload, $raw_body, $access_token );
     543
     544        if ( ! $verified ) {
     545            // Fallback to manual method if REST API verification fails.
     546            wp_subscrpt_write_log( 'PayPal webhook REST API verification failed. Retrying with manual verification.' );
     547
     548            $verified = $this->verify_paypal_webhook_manual( $payload, $raw_body );
     549        }
    551550
    552551        if ( ! $verified ) {
    553552            wp_subscrpt_write_log( 'PayPal webhook verification failed.' );
    554             wp_subscrpt_write_debug_log( 'Webhook verification failed for data: ' . wp_json_encode( $webhook_data ) );
     553            wp_subscrpt_write_debug_log( 'Webhook verification failed for data: ' . $raw_body );
    555554            wp_die( 'Error: PayPal webhook verification failed.', '403 Forbidden', array( 'response' => 403 ) );
    556555        }
     556    }
     557
     558    /**
     559     * Verify PayPal webhook with REST API.
     560     *
     561     * @param array  $payload       Payload data for verification.
     562     * @param string $raw_body Webhook raw body from PayPal.
     563     * @param string $access_token  PayPal Access Token.
     564     */
     565    protected function verify_paypal_webhook_rest_api( array $payload, string $raw_body, string $access_token ): bool {
     566        // Fix the webhook_event to be an array.
     567        $payload['webhook_event'] = json_decode( $raw_body, true );
     568
     569        // Verify webhook signature via PayPal REST API.
     570        try {
     571            $url  = $this->api_endpoint . '/v1/notifications/verify-webhook-signature';
     572            $args = [
     573                'method'  => 'POST',
     574                'headers' => [
     575                    'Authorization' => 'Bearer ' . $access_token,
     576                    'Content-Type'  => 'application/json',
     577                ],
     578                'body'    => wp_json_encode( $payload ),
     579            ];
     580
     581            $response            = wp_remote_post( $url, $args );
     582            $response_data       = json_decode( wp_remote_retrieve_body( $response ), true );
     583            $verification_status = $response_data['verification_status'] ?? null;
     584
     585            if ( empty( $verification_status ) || 'success' !== strtolower( $verification_status ) ) {
     586                wp_subscrpt_write_debug_log( 'PayPal Webhook Verification: ' . wp_json_encode( $response_data ) );
     587                return false;
     588            }
     589
     590            return ( 'success' === strtolower( $verification_status ) ) ? true : false;
     591
     592        } catch ( Exception $e ) {
     593            $log_message = 'PayPal Webhook Verification Failed: ' . $e->getMessage();
     594            wp_subscrpt_write_log( $log_message );
     595            wp_subscrpt_write_debug_log( $log_message );
     596            return false;
     597        }
     598    }
     599
     600    /**
     601     * Verify PayPal webhook manually (self verification).
     602     *
     603     * @param array  $payload       Payload data for verification.
     604     * @param string $raw_body Webhook raw body from PayPal.
     605     */
     606    protected function verify_paypal_webhook_manual( array $payload, string $raw_body ): bool {
     607        // Enforce CRC32 for 32-bit systems (edge case)
     608        $crc = sprintf( '%u', crc32( $raw_body ) );
     609
     610        // Build Message
     611        $message = implode(
     612            '|',
     613            [
     614                $payload['transmission_id'],
     615                $payload['transmission_time'],
     616                $payload['webhook_id'],
     617                $crc,
     618            ]
     619        );
     620
     621        // Fetch & cache cert
     622        $cert_url  = esc_url_raw( $payload['cert_url'] );
     623        $cache_key = 'paypal_cert_' . md5( $cert_url );
     624
     625        $cert_pem = get_transient( $cache_key );
     626
     627        if ( ! $cert_pem ) {
     628            $response = wp_remote_get( $cert_url, [ 'timeout' => 20 ] );
     629            if ( is_wp_error( $response ) ) {
     630                return false;
     631            }
     632
     633            $cert_pem = wp_remote_retrieve_body( $response );
     634            set_transient( $cache_key, $cert_pem, DAY_IN_SECONDS );
     635        }
     636
     637        if ( empty( $cert_pem ) ) {
     638            return false;
     639        }
     640
     641        // Signature
     642        $signature = base64_decode( $payload['transmission_sig'], true );
     643
     644        if ( false === $signature ) {
     645            return false;
     646        }
     647
     648        // Final verification
     649        $verified = openssl_verify(
     650            $message,
     651            $signature,
     652            $cert_pem,
     653            OPENSSL_ALGO_SHA256
     654        );
     655
     656        return ( 1 === $verified );
    557657    }
    558658
     
    14541554
    14551555    /**
    1456      * Verify PayPal webhook.
    1457      *
    1458      * @param array  $verification_data Verification data to verify.
    1459      * @param string $access_token      PayPal Access Token.
    1460      */
    1461     public function verify_paypal_webhook( array $verification_data, string $access_token ): bool {
    1462         try {
    1463             $url  = $this->api_endpoint . '/v1/notifications/verify-webhook-signature';
    1464             $args = [
    1465                 'method'  => 'POST',
    1466                 'headers' => [
    1467                     'Authorization' => 'Bearer ' . $access_token,
    1468                     'Content-Type'  => 'application/json',
    1469                 ],
    1470                 'body'    => wp_json_encode( $verification_data ),
    1471             ];
    1472 
    1473             $response      = wp_remote_post( $url, $args );
    1474             $response_data = json_decode( wp_remote_retrieve_body( $response ) );
    1475 
    1476             if ( empty( $response_data->verification_status ?? null ) || 'SUCCESS' !== $response_data->verification_status ) {
    1477                 wp_subscrpt_write_debug_log( 'PayPal Webhook Verification: ' . wp_json_encode( $response_data ) );
    1478                 return false;
    1479             }
    1480 
    1481             if ( 'SUCCESS' === $response_data->verification_status ) {
    1482                 return true;
    1483             } else {
    1484                 return false;
    1485             }
    1486         } catch ( Exception $e ) {
    1487             $log_message = 'PayPal Webhook Verification Failed: ' . $e->getMessage();
    1488             wp_subscrpt_write_log( $log_message );
    1489             wp_subscrpt_write_debug_log( $log_message );
    1490             return false;
    1491         }
    1492     }
    1493 
    1494     /**
    14951556     * Get PayPal order details.
    14961557     *
  • subscription/tags/1.8.12/includes/Illuminate/Helper.php

    r3415062 r3424485  
    2525     */
    2626    public static function get_typos( $number, $typo, $translate = false ) {
    27         if ( 1 === (int) $number && 'days' === $typo ) {
    28             return $translate ? __( 'day', 'wp_subscription' ) : 'day';
    29         } elseif ( 1 === (int) $number && 'weeks' === $typo ) {
    30             return $translate ? __( 'week', 'wp_subscription' ) : 'week';
    31         } elseif ( 1 === (int) $number && 'months' === $typo ) {
    32             return $translate ? __( 'month', 'wp_subscription' ) : 'month';
    33         } elseif ( 1 === (int) $number && 'years' === $typo ) {
    34             return $translate ? __( 'year', 'wp_subscription' ) : 'year';
    35         } else {
    36             return $typo;
     27        switch ( strtolower( $typo ) ) {
     28            case 'day':
     29            case 'days':
     30                return $translate
     31                    ? _n( 'day', 'days', $number, 'wp_subscription' )
     32                    : ( (int) $number === 1 ? 'day' : 'days' );
     33
     34            case 'week':
     35            case 'weeks':
     36                return $translate
     37                    ? _n( 'week', 'weeks', $number, 'wp_subscription' )
     38                    : ( (int) $number === 1 ? 'week' : 'weeks' );
     39
     40            case 'month':
     41            case 'months':
     42                return $translate
     43                    ? _n( 'month', 'months', $number, 'wp_subscription' )
     44                    : ( (int) $number === 1 ? 'month' : 'months' );
     45
     46            case 'year':
     47            case 'years':
     48                return $translate
     49                    ? _n( 'year', 'years', $number, 'wp_subscription' )
     50                    : ( (int) $number === 1 ? 'year' : 'years' );
     51
     52            default:
     53                return $typo;
    3754        }
    3855    }
     
    290307
    291308        $time = 1 === (int) $item_meta['time'] ? null : $item_meta['time'] . '-';
    292         $type = self::get_typos( $item_meta['time'], $item_meta['type'] );
     309        $type = self::get_typos( $item_meta['time'], $item_meta['type'], true );
    293310
    294311        $formatted_price = wc_price(
     
    297314                'currency' => $order->get_currency(),
    298315            )
    299         ) . ' / ' . $time . $type;
     316        ) . ' / ' . $time . ucfirst( $type );
    300317
    301318        if ( $display_trial ) {
    302             $trial     = $item_meta['trial'];
    303319            $has_trial = isset( $item_meta['trial'] ) && strlen( $item_meta['trial'] ) > 2;
     320            $trial     = $item_meta['trial'] ?? '';
    304321
    305322            if ( $has_trial ) {
    306                 $trial_html       = '<br/><small> + Got ' . $trial . ' free trial!</small>';
     323                // translators: %s: trial period.
     324                $trial_html       = '<br/><small> ' . sprintf( __( '+ %s free trial!', 'wp_subscription' ), $trial ) . '</small>';
    307325                $formatted_price .= $trial_html;
    308326            }
  • subscription/tags/1.8.12/includes/Illuminate/Subscription/Subscription.php

    r3419216 r3424485  
    3333        switch ( strtolower( $view ) ) {
    3434            case 'view_subs':
    35                 $default_endpoint = 'view-subscription';
     35                $default_endpoint = 'subscription';
    3636                $endpoint         = $is_pro ? get_option( 'wpsubs_custom_view_subscription_endpoint', $default_endpoint ) : $default_endpoint;
    3737                break;
  • subscription/tags/1.8.12/includes/Illuminate/views/subscription-table.php

    r3320126 r3424485  
    7171                </th>
    7272                <td class="td"
    73                     style="color: #636363; border: 1px solid #e5e5e5; vertical-align: middle; padding: 12px; text-align: left;"><?php echo ! empty( $next_date ) ? esc_html( gmdate( 'F d, Y', $next_date ) ) : '-'; ?></td>
     73                    style="color: #636363; border: 1px solid #e5e5e5; vertical-align: middle; padding: 12px; text-align: left;"><?php echo ! empty( $next_date ) ? esc_html( wp_date( 'F d, Y', $next_date ) ) : '-'; ?></td>
    7474            </tr>
    7575        <?php } else { ?>
     
    8888                </th>
    8989                <td class="td"
    90                     style="color: #636363; border: 1px solid #e5e5e5; vertical-align: middle; padding: 12px; text-align: left;"><?php echo ! empty( $start_date ) ? esc_html( gmdate( 'F d, Y', $start_date ) ) : '-'; ?></td>
     90                    style="color: #636363; border: 1px solid #e5e5e5; vertical-align: middle; padding: 12px; text-align: left;"><?php echo ! empty( $start_date ) ? esc_html( wp_date( 'F d, Y', $start_date ) ) : '-'; ?></td>
    9191            </tr>
    9292        <?php } ?>
  • subscription/tags/1.8.12/languages/wp_subscription.pot

    r3419216 r3424485  
    1010"Content-Type: text/plain; charset=UTF-8\n"
    1111"Content-Transfer-Encoding: 8bit\n"
    12 "POT-Creation-Date: 2025-12-14T05:43:22+00:00\n"
     12"POT-Creation-Date: 2025-12-21T06:59:21+00:00\n"
    1313"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
    1414"X-Generator: WP-CLI 2.12.0\n"
     
    562562#: includes/Admin/views/integrations.php:46
    563563#: includes/Admin/views/subscription-list.php:25
    564 #: includes/Illuminate/Helper.php:48
     564#: includes/Illuminate/Helper.php:65
    565565msgid "Active"
    566566msgstr ""
     
    835835
    836836#: includes/Admin/views/subscription-list.php:26
    837 #: includes/Illuminate/Helper.php:47
     837#: includes/Illuminate/Helper.php:64
    838838msgid "Pending"
    839839msgstr ""
    840840
    841841#: includes/Admin/views/subscription-list.php:27
    842 #: includes/Illuminate/Helper.php:52
     842#: includes/Illuminate/Helper.php:69
    843843msgid "Cancelled"
    844844msgstr ""
    845845
    846846#: includes/Admin/views/subscription-list.php:28
    847 #: includes/Illuminate/Helper.php:50
     847#: includes/Illuminate/Helper.php:67
    848848msgid "Expired"
    849849msgstr ""
    850850
    851851#: includes/Admin/views/subscription-list.php:29
    852 #: includes/Illuminate/Helper.php:53
     852#: includes/Illuminate/Helper.php:70
    853853msgid "Draft"
    854854msgstr ""
    855855
    856856#: includes/Admin/views/subscription-list.php:30
    857 #: includes/Illuminate/Helper.php:54
     857#: includes/Illuminate/Helper.php:71
    858858msgid "Trash"
    859859msgstr ""
     
    10851085
    10861086#: includes/functions.php:46
    1087 #: includes/Illuminate/Helper.php:28
     1087#: includes/Illuminate/Helper.php:31
    10881088msgid "day"
    1089 msgstr ""
     1089msgid_plural "days"
     1090msgstr[0] ""
     1091msgstr[1] ""
    10901092
    10911093#: includes/functions.php:48
    1092 #: includes/Illuminate/Helper.php:30
     1094#: includes/Illuminate/Helper.php:37
    10931095msgid "week"
    1094 msgstr ""
     1096msgid_plural "weeks"
     1097msgstr[0] ""
     1098msgstr[1] ""
    10951099
    10961100#: includes/functions.php:50
    1097 #: includes/Illuminate/Helper.php:32
     1101#: includes/Illuminate/Helper.php:43
    10981102msgid "month"
    1099 msgstr ""
     1103msgid_plural "months"
     1104msgstr[0] ""
     1105msgstr[1] ""
    11001106
    11011107#: includes/functions.php:52
    1102 #: includes/Illuminate/Helper.php:34
     1108#: includes/Illuminate/Helper.php:49
    11031109msgid "year"
    1104 msgstr ""
     1110msgid_plural "years"
     1111msgstr[0] ""
     1112msgstr[1] ""
    11051113
    11061114#: includes/functions.php:414
     
    11091117
    11101118#: includes/functions.php:415
    1111 #: includes/Illuminate/Helper.php:376
     1119#: includes/Illuminate/Helper.php:394
    11121120msgid "Renewal Order"
    11131121msgstr ""
     
    13241332
    13251333#. translators: %1$s: alert name; %2$s: order id.
    1326 #: includes/Illuminate/Gateways/Paypal/Paypal.php:500
     1334#: includes/Illuminate/Gateways/Paypal/Paypal.php:491
    13271335#, php-format
    13281336msgid "PayPal webhook received [%s]. Order not found."
     
    13301338
    13311339#. translators: %1$s: alert name; %2$s: order id.
    1332 #: includes/Illuminate/Gateways/Paypal/Paypal.php:516
     1340#: includes/Illuminate/Gateways/Paypal/Paypal.php:507
    13331341#, php-format
    13341342msgid "PayPal webhook received [%s]. No actions taken."
     
    13361344
    13371345#. translators: %1$s: alert name; %2$s: subscription id.
    1338 #: includes/Illuminate/Gateways/Paypal/Paypal.php:807
     1346#: includes/Illuminate/Gateways/Paypal/Paypal.php:907
    13391347#, php-format
    13401348msgid "Transaction webhook received [%1$s]. No order found for subscription ID [%2$s]."
    13411349msgstr ""
    13421350
    1343 #: includes/Illuminate/Gateways/Paypal/Paypal.php:820
     1351#: includes/Illuminate/Gateways/Paypal/Paypal.php:920
    13441352msgid "Payment completed by paypal webhook."
    13451353msgstr ""
    13461354
    1347 #: includes/Illuminate/Gateways/Paypal/Paypal.php:825
     1355#: includes/Illuminate/Gateways/Paypal/Paypal.php:925
    13481356msgid "Failed to complete payment. Requested by paypal webhook."
    13491357msgstr ""
    13501358
    1351 #: includes/Illuminate/Gateways/Paypal/Paypal.php:834
     1359#: includes/Illuminate/Gateways/Paypal/Paypal.php:934
    13521360msgid "Payment refunded by paypal webhook."
    13531361msgstr ""
    13541362
    1355 #: includes/Illuminate/Gateways/Paypal/Paypal.php:839
     1363#: includes/Illuminate/Gateways/Paypal/Paypal.php:939
    13561364msgid "Failed to refund payment. Requested by paypal webhook."
    13571365msgstr ""
    13581366
    13591367#. translators: %s: alert name.
    1360 #: includes/Illuminate/Gateways/Paypal/Paypal.php:849
     1368#: includes/Illuminate/Gateways/Paypal/Paypal.php:949
    13611369#, php-format
    13621370msgid "Transaction webhook received [%s]. No actions taken."
    13631371msgstr ""
    13641372
    1365 #: includes/Illuminate/Gateways/Paypal/Paypal.php:875
     1373#: includes/Illuminate/Gateways/Paypal/Paypal.php:975
    13661374msgid "Subscription not found. Attempting to get from order item."
    13671375msgstr ""
    13681376
    13691377#. translators: %s: alert name.
    1370 #: includes/Illuminate/Gateways/Paypal/Paypal.php:894
     1378#: includes/Illuminate/Gateways/Paypal/Paypal.php:994
    13711379#, php-format
    13721380msgid "Subscription webhook received [%s]. Subscription not found."
    13731381msgstr ""
    13741382
    1375 #: includes/Illuminate/Gateways/Paypal/Paypal.php:907
     1383#: includes/Illuminate/Gateways/Paypal/Paypal.php:1007
    13761384msgid "Subscription activated by PayPal webhook."
    13771385msgstr ""
    13781386
    1379 #: includes/Illuminate/Gateways/Paypal/Paypal.php:913
    1380 #: includes/Illuminate/Gateways/Paypal/Paypal.php:926
    1381 #: includes/Illuminate/Gateways/Paypal/Paypal.php:939
     1387#: includes/Illuminate/Gateways/Paypal/Paypal.php:1013
     1388#: includes/Illuminate/Gateways/Paypal/Paypal.php:1026
     1389#: includes/Illuminate/Gateways/Paypal/Paypal.php:1039
    13821390msgid "Subscription webhook received. No actions taken."
    13831391msgstr ""
    13841392
    1385 #: includes/Illuminate/Gateways/Paypal/Paypal.php:920
     1393#: includes/Illuminate/Gateways/Paypal/Paypal.php:1020
    13861394msgid "Subscription expired by PayPal webhook."
    13871395msgstr ""
    13881396
    1389 #: includes/Illuminate/Gateways/Paypal/Paypal.php:933
     1397#: includes/Illuminate/Gateways/Paypal/Paypal.php:1033
    13901398msgid "Subscription cancelled by PayPal webhook."
    13911399msgstr ""
    13921400
    13931401#. translators: %s: alert name.
    1394 #: includes/Illuminate/Gateways/Paypal/Paypal.php:945
     1402#: includes/Illuminate/Gateways/Paypal/Paypal.php:1045
    13951403#, php-format
    13961404msgid "Subscription webhook received [%s]. No actions taken."
    13971405msgstr ""
    13981406
    1399 #: includes/Illuminate/Gateways/Paypal/Paypal.php:1257
     1407#: includes/Illuminate/Gateways/Paypal/Paypal.php:1357
    14001408msgid "PayPal Product Creation Error: Product data is incomplete. Name and type are required."
    14011409msgstr ""
     
    14431451msgstr ""
    14441452
    1445 #: includes/Illuminate/Helper.php:49
     1453#: includes/Illuminate/Helper.php:66
    14461454msgid "On Hold"
    14471455msgstr ""
    14481456
    1449 #: includes/Illuminate/Helper.php:51
     1457#: includes/Illuminate/Helper.php:68
    14501458msgid "Pending Cancellation"
    14511459msgstr ""
    14521460
     1461#. translators: %s: trial period.
     1462#: includes/Illuminate/Helper.php:324
     1463#, php-format
     1464msgid "+ %s free trial!"
     1465msgstr ""
     1466
    14531467#. translators: %1$s: order id, %2$d: payment number, %3$d: total payments
    1454 #: includes/Illuminate/Helper.php:364
     1468#: includes/Illuminate/Helper.php:382
    14551469#, php-format
    14561470msgid "Split payment installment %2$d of %3$d. Order %1$s created for subscription."
    14571471msgstr ""
    14581472
    1459 #: includes/Illuminate/Helper.php:369
     1473#: includes/Illuminate/Helper.php:387
    14601474msgid "Split Payment - Renewal"
    14611475msgstr ""
    14621476
    14631477#. translators: order id.
    1464 #: includes/Illuminate/Helper.php:373
     1478#: includes/Illuminate/Helper.php:391
    14651479#, php-format
    14661480msgid "The order %s has been created for the subscription"
     
    14681482
    14691483#. translators: %1$s: order id, %2$d: max payments
    1470 #: includes/Illuminate/Helper.php:454
     1484#: includes/Illuminate/Helper.php:472
    14711485#, php-format
    14721486msgid "Split payment subscription created successfully. Order: %1$s. Total installments: %2$d."
    14731487msgstr ""
    14741488
    1475 #: includes/Illuminate/Helper.php:458
     1489#: includes/Illuminate/Helper.php:476
    14761490msgid "Split Payment - New Subscription"
    14771491msgstr ""
    14781492
    14791493#. translators: Order Id.
    1480 #: includes/Illuminate/Helper.php:462
     1494#: includes/Illuminate/Helper.php:480
    14811495#, php-format
    14821496msgid "Subscription successfully created. Order is %s"
    14831497msgstr ""
    14841498
    1485 #: includes/Illuminate/Helper.php:465
     1499#: includes/Illuminate/Helper.php:483
    14861500#: includes/Illuminate/Post.php:67
    14871501msgid "New Subscription"
    14881502msgstr ""
    14891503
    1490 #: includes/Illuminate/Helper.php:1096
     1504#: includes/Illuminate/Helper.php:1114
    14911505msgid "Subscription renewal isn't possible due to previous order not completed or deletion."
    14921506msgstr ""
  • subscription/tags/1.8.12/subscription.php

    r3419216 r3424485  
    77 * Description: WPSubscription allow WooCommerce to enables recurring payments, subscriptions, and auto-renewals for digital and physical products. Supports Stripe, PayPal, Paddle, and more.
    88 *
    9  * Version: 1.8.11
     9 * Version: 1.8.12
    1010 *
    1111 * Author: ConversWP
     
    1818 *
    1919 * Requires at least: 6.0
    20  * Tested up to: 6.8
     20 * Tested up to: 6.9
    2121 *
    2222 * WC requires at least: 6.0
     
    5151     * @var string
    5252     */
    53     const version = '1.8.11';
     53    const version = '1.8.12';
    5454
    5555    /**
  • subscription/tags/1.8.12/templates/myaccount/subscriptions.php

    r3419216 r3424485  
    5050
    5151                $start_date = $subscription_data['start_date'] ?? '';
    52                 $start_date = ! empty( $start_date ) ? gmdate( 'F j, Y', strtotime( $start_date ) ) : '-';
     52                $start_date = ! empty( $start_date ) ? wp_date( 'F j, Y', strtotime( $start_date ) ) : '-';
    5353
    5454                $next_date = $subscription_data['next_date'] ?? '';
    55                 $next_date = ! empty( $next_date ) ? gmdate( 'F j, Y', strtotime( $next_date ) ) : '-';
     55                $next_date = ! empty( $next_date ) ? wp_date( 'F j, Y', strtotime( $next_date ) ) : '-';
    5656
    5757                $trial      = get_post_meta( get_the_ID(), '_subscrpt_trial', true );
  • subscription/tags/1.8.12/vendor/composer/installed.php

    r3419216 r3424485  
    22    'root' => array(
    33        'name' => 'converswp/subscription',
    4         'pretty_version' => '1.8.11',
    5         'version' => '1.8.11.0',
    6         'reference' => 'cdc6fcf8aa53e23284845046caf19ef6649b6df0',
     4        'pretty_version' => '1.8.12',
     5        'version' => '1.8.12.0',
     6        'reference' => 'a9d0d2372826303a8c2a6a7ed051f99168ccbcdb',
    77        'type' => 'wordpress-plugin',
    88        'install_path' => __DIR__ . '/../../',
     
    1212    'versions' => array(
    1313        'converswp/subscription' => array(
    14             'pretty_version' => '1.8.11',
    15             'version' => '1.8.11.0',
    16             'reference' => 'cdc6fcf8aa53e23284845046caf19ef6649b6df0',
     14            'pretty_version' => '1.8.12',
     15            'version' => '1.8.12.0',
     16            'reference' => 'a9d0d2372826303a8c2a6a7ed051f99168ccbcdb',
    1717            'type' => 'wordpress-plugin',
    1818            'install_path' => __DIR__ . '/../../',
  • subscription/trunk/changelog.txt

    r3419216 r3424485  
    11*** WPSubscription Changelog ***
     2
     32025-12-21 - version 1.8.12
     4* fix: Subscription details default endpoint.
     5* fix: Proper subscription timings.
     6* fix: WordPress test up to version.
     7* fix: Other minor bugs.
    28
    392025-12-14 - version 1.8.11
  • subscription/trunk/includes/Admin/Subscriptions.php

    r3392314 r3424485  
    137137            if ( 'subscrpt_start_date' === $column ) {
    138138                $start_date = get_post_meta( $post_id, '_subscrpt_start_date', true );
    139                 echo ! empty( $start_date ) ? esc_html( gmdate( 'F d, Y', $start_date ) ) : '-';
     139                echo ! empty( $start_date ) ? esc_html( wp_date( 'F d, Y', $start_date ) ) : '-';
    140140            } elseif ( 'subscrpt_customer' === $column ) {
    141141                ?>
     
    151151            } elseif ( 'subscrpt_next_date' === $column ) {
    152152                $next_date = get_post_meta( $post_id, '_subscrpt_next_date', true );
    153                 echo ! empty( $next_date ) ? esc_html( gmdate( 'F d, Y', $next_date ) ) : '-';
     153                echo ! empty( $next_date ) ? esc_html( wp_date( 'F d, Y', $next_date ) ) : '-';
    154154            } elseif ( 'subscrpt_status' === $column ) {
    155155                $status_obj = get_post_status_object( get_post_status( $post_id ) );
     
    377377            'start_date'       => array(
    378378                'label' => __( 'Started date', 'wp_subscription' ),
    379                 'value' => ! empty( $start_date ) ? gmdate( 'F d, Y', $trial && $trial_start_date ? $trial_start_date : $start_date ) : '-',
     379                'value' => ! empty( $start_date ) ? wp_date( 'F d, Y', $trial && $trial_start_date ? $trial_start_date : $start_date ) : '-',
    380380            ),
    381381            'next_date'        => array(
    382382                'label' => __( 'Payment due date', 'wp_subscription' ),
    383                 'value' => ! empty( $next_date ) ? gmdate( 'F d, Y', $trial && $trial_end_date && 'on' === $trial_mode ? $trial_end_date : ( $next_date ?? '-' ) ) : '-',
     383                'value' => ! empty( $next_date ) ? wp_date( 'F d, Y', $trial && $trial_end_date && 'on' === $trial_mode ? $trial_end_date : ( $next_date ?? '-' ) ) : '-',
    384384            ),
    385385            'status'           => array(
     
    408408                'trial_period' => array(
    409409                    'label' => __( 'Trial Period', 'wp_subscription' ),
    410                     'value' => ( $trial_start_date && $trial_end_date ? ' [ ' . gmdate( 'F d, Y', $trial_start_date ) . ' - ' . gmdate( 'F d, Y', $trial_end_date ) . ' ] ' : __( 'Trial isn\'t activated yet! ', 'wp_subscription' ) ),
     410                    'value' => ( $trial_start_date && $trial_end_date ? ' [ ' . wp_date( 'F d, Y', $trial_start_date ) . ' - ' . wp_date( 'F d, Y', $trial_end_date ) . ' ] ' : __( 'Trial isn\'t activated yet! ', 'wp_subscription' ) ),
    411411                ),
    412412            ) + array_slice( $rows, 3, count( $rows ) - 1, true );
     
    488488
    489489        $started_date = $subscription_data['start_date'] ?? '';
    490         $started_date = ! empty( $started_date ) ? gmdate( 'F j, Y - g:i A', strtotime( $started_date ) ) : '-';
     490        $started_date = ! empty( $started_date ) ? wp_date( 'F j, Y - g:i A', strtotime( $started_date ) ) : '-';
    491491
    492492        $next_payment_date = $subscription_data['next_date'] ?? '';
    493         $next_payment_date = ! empty( $next_payment_date ) ? gmdate( 'F j, Y - g:i A', strtotime( $next_payment_date ) ) : '-';
     493        $next_payment_date = ! empty( $next_payment_date ) ? wp_date( 'F j, Y - g:i A', strtotime( $next_payment_date ) ) : '-';
    494494
    495495        $is_grace_period = isset( $subscription_data['grace_period'] );
    496496        $grace_remaining = $subscription_data['grace_period']['remaining_days'] ?? 0;
    497497        $grace_end_date  = $subscription_data['grace_period']['end_date'] ?? '';
    498         $grace_end_date  = ! empty( $grace_end_date ) ? gmdate( 'F j, Y - g:i A', strtotime( $grace_end_date ) ) : '';
     498        $grace_end_date  = ! empty( $grace_end_date ) ? wp_date( 'F j, Y - g:i A', strtotime( $grace_end_date ) ) : '';
    499499
    500500        ?>
  • subscription/trunk/includes/Admin/views/related-subscriptions.php

    r3381229 r3424485  
    4141
    4242            $start_date = $subscription_data['start_date'] ?? '';
    43             $start_date = ! empty( $start_date ) ? gmdate( 'F j, Y - g:i A', strtotime( $start_date ) ) : '-';
     43            $start_date = ! empty( $start_date ) ? wp_date( 'F j, Y - g:i A', strtotime( $start_date ) ) : '-';
    4444
    4545            $next_date = $subscription_data['next_date'] ?? '';
    46             $next_date = ! empty( $next_date ) ? gmdate( 'F j, Y - g:i A', strtotime( $next_date ) ) : '-';
     46            $next_date = ! empty( $next_date ) ? wp_date( 'F j, Y - g:i A', strtotime( $next_date ) ) : '-';
    4747
    4848            $price          = $subscription_data['price'] ?? 0;
  • subscription/trunk/includes/Admin/views/subscription-info.php

    r3413403 r3424485  
    220220                    <tr>
    221221                        <th style="padding:8px 10px;">Started date</th>
    222                         <td style="padding:8px 10px;"><?php echo $start_date ? esc_html( gmdate( 'F d, Y', $start_date ) ) : '-'; ?></td>
     222                        <td style="padding:8px 10px;"><?php echo $start_date ? esc_html( wp_date( 'F d, Y', $start_date ) ) : '-'; ?></td>
    223223                    </tr>
    224224                    <tr>
    225225                        <th style="padding:8px 10px;">Payment due date</th>
    226                         <td style="padding:8px 10px;"><?php echo $renewal_date ? esc_html( gmdate( 'F d, Y', $renewal_date ) ) : '-'; ?></td>
     226                        <td style="padding:8px 10px;"><?php echo $renewal_date ? esc_html( wp_date( 'F d, Y', $renewal_date ) ) : '-'; ?></td>
    227227                    </tr>
    228228                    <tr>
  • subscription/trunk/includes/Admin/views/subscription-list.php

    r3381229 r3424485  
    150150                        <?php endif; ?>
    151151                    </td>
    152                     <td><?php echo $start_date ? esc_html( gmdate( 'F d, Y', $start_date ) ) : '-'; ?></td>
    153                     <td><?php echo $renewal_date ? esc_html( gmdate( 'F d, Y', $renewal_date ) ) : '-'; ?></td>
     152                    <td><?php echo $start_date ? esc_html( wp_date( 'F d, Y', $start_date ) ) : '-'; ?></td>
     153                    <td><?php echo $renewal_date ? esc_html( wp_date( 'F d, Y', $renewal_date ) ) : '-'; ?></td>
    154154                    <td>
    155155                        <?php if ( $is_grace_period && $grace_remaining > 0 ) : ?>
  • subscription/trunk/includes/Frontend/MyAccount.php

    r3419216 r3424485  
    100100
    101101        $start_date = $subscription_data['start_date'] ?? '';
    102         $start_date = ! empty( $start_date ) ? gmdate( 'F j, Y', strtotime( $start_date ) ) : '-';
     102        $start_date = ! empty( $start_date ) ? wp_date( 'F j, Y', strtotime( $start_date ) ) : '-';
    103103
    104104        $next_date = $subscription_data['next_date'] ?? '';
    105         $next_date = ! empty( $next_date ) ? gmdate( 'F j, Y', strtotime( $next_date ) ) : '-';
     105        $next_date = ! empty( $next_date ) ? wp_date( 'F j, Y', strtotime( $next_date ) ) : '-';
    106106
    107107        $trial      = get_post_meta( $id, '_subscrpt_trial', true );
     
    122122        $grace_remaining = $subscription_data['grace_period']['remaining_days'] ?? 0;
    123123        $grace_end_date  = $subscription_data['grace_period']['end_date'] ?? '';
    124         $grace_end_date  = ! empty( $grace_end_date ) ? gmdate( 'F j, Y', strtotime( $grace_end_date ) ) : '';
     124        $grace_end_date  = ! empty( $grace_end_date ) ? wp_date( 'F j, Y', strtotime( $grace_end_date ) ) : '';
    125125
    126126        $subscrpt_nonce = wp_create_nonce( 'subscrpt_nonce' );
  • subscription/trunk/includes/Frontend/Order.php

    r3406135 r3424485  
    4747
    4848            $start_date_string = $subscription_data['start_date'] ?? '';
    49             $start_date        = ! empty( $start_date_string ) ? gmdate( 'F d, Y', strtotime( $start_date_string ) ) : '-';
     49            $start_date        = ! empty( $start_date_string ) ? wp_date( 'F d, Y', strtotime( $start_date_string ) ) : '-';
    5050
    5151            $next_date_string = $subscription_data['next_date'] ?? '';
    52             $next_date        = ! empty( $next_date_string ) ? gmdate( 'F d, Y', strtotime( $next_date_string ) ) : '-';
     52            $next_date        = ! empty( $next_date_string ) ? wp_date( 'F d, Y', strtotime( $next_date_string ) ) : '-';
    5353
    5454            $cost           = $subscription_data['price'] ?? '0.00';
  • subscription/trunk/includes/Illuminate/Gateways/Paypal/Paypal.php

    r3349190 r3424485  
    416416     */
    417417    public function process_webhook() {
    418         if ( ! isset( $_GET['wc-api'] ) || $this->id !== $_GET['wc-api'] ) {
    419             wp_subscrpt_write_log( 'PayPal webhook called without valid API endpoint.' );
    420             return;
    421         }
    422 
    423         // Get Webhook Data.
    424         $webhook_data = stripslashes_deep( $_POST ); // phpcs:ignore WordPress.Security.NonceVerification
    425         $headers      = getallheaders();
    426 
    427         if ( empty( $webhook_data ) || ! count( $webhook_data ) ) {
    428             $post_data = file_get_contents( 'php://input' );
    429             // Sanitize the raw input before decoding.
    430             $post_data    = sanitize_text_field( $post_data );
    431             $webhook_data = json_decode( $post_data, true );
    432 
    433             if ( ! $webhook_data ) {
    434                 wp_subscrpt_write_log( 'Webhook data is empty.' );
    435                 wp_subscrpt_write_debug_log( "process_webhook EMPTY \n" . file_get_contents( 'php://input' ) );
    436                 exit( 'Webhook data is empty.' );
    437             }
     418        // Get raw webhook data.
     419        $raw_body = file_get_contents( 'php://input' );
     420        $headers  = function_exists( 'getallheaders' ) ? getallheaders() : [];
     421
     422        if ( empty( $raw_body ) ) {
     423            wp_subscrpt_write_log( 'PayPal webhook data is empty.' );
     424            wp_subscrpt_write_debug_log( "PayPal - process_webhook EMPTY \n" . $raw_body );
     425            wp_die( 'PayPal webhook data is empty.', '400 Bad Request', [ 'response' => 400 ] );
    438426        }
    439427
    440428        // Verify webhook.
    441         $this->verify_webhook( $headers, $webhook_data );
     429        $this->verify_webhook( $headers, $raw_body );
     430
     431        // Decode webhook data.
     432        $webhook_data = json_decode( $raw_body, true );
    442433
    443434        // Get event type from webhook data.
     
    526517     * Verify webhook data from PayPal.
    527518     *
    528      * @param array $headers       Headers from the request.
    529      * @param array $webhook_data Webhook data from PayPal.
    530      */
    531     public function verify_webhook( array $headers, array $webhook_data ) {
     519     * @param array  $headers       Headers from the request.
     520     * @param string $raw_body Webhook raw body from PayPal.
     521     */
     522    public function verify_webhook( array $headers, string $raw_body ) {
    532523        // Get PayPal Access Token.
    533524        $access_token = $this->get_paypal_access_token();
     
    537528        }
    538529
    539         // Prepare the request to verify the webhook.
     530        // Prepare the request data to verify the webhook.
    540531        $payload = [
    541             'auth_algo'         => $headers['Paypal-Auth-Algo'] ?? '',
    542             'cert_url'          => $headers['Paypal-Cert-Url'] ?? '',
    543             'transmission_id'   => $headers['Paypal-Transmission-Id'] ?? '',
    544             'transmission_sig'  => $headers['Paypal-Transmission-Sig'] ?? '',
    545             'transmission_time' => $headers['Paypal-Transmission-Time'] ?? '',
     532            'auth_algo'         => $headers['PAYPAL-AUTH-ALGO'] ?? $headers['Paypal-Auth-Algo'] ?? '',
     533            'cert_url'          => $headers['PAYPAL-CERT-URL'] ?? $headers['Paypal-Cert-Url'] ?? '',
     534            'transmission_id'   => $headers['PAYPAL-TRANSMISSION-ID'] ?? $headers['Paypal-Transmission-Id'] ?? '',
     535            'transmission_sig'  => $headers['PAYPAL-TRANSMISSION-SIG'] ?? $headers['Paypal-Transmission-Sig'] ?? '',
     536            'transmission_time' => $headers['PAYPAL-TRANSMISSION-TIME'] ?? $headers['Paypal-Transmission-Time'] ?? '',
    546537            'webhook_id'        => $this->webhook_id ?? '',
    547             'webhook_event'     => $webhook_data,
     538            'webhook_event'     => $raw_body,
    548539        ];
    549540
    550         $verified = $this->verify_paypal_webhook( $payload, $access_token );
     541        // Verify webhook via REST API.
     542        $verified = $this->verify_paypal_webhook_rest_api( $payload, $raw_body, $access_token );
     543
     544        if ( ! $verified ) {
     545            // Fallback to manual method if REST API verification fails.
     546            wp_subscrpt_write_log( 'PayPal webhook REST API verification failed. Retrying with manual verification.' );
     547
     548            $verified = $this->verify_paypal_webhook_manual( $payload, $raw_body );
     549        }
    551550
    552551        if ( ! $verified ) {
    553552            wp_subscrpt_write_log( 'PayPal webhook verification failed.' );
    554             wp_subscrpt_write_debug_log( 'Webhook verification failed for data: ' . wp_json_encode( $webhook_data ) );
     553            wp_subscrpt_write_debug_log( 'Webhook verification failed for data: ' . $raw_body );
    555554            wp_die( 'Error: PayPal webhook verification failed.', '403 Forbidden', array( 'response' => 403 ) );
    556555        }
     556    }
     557
     558    /**
     559     * Verify PayPal webhook with REST API.
     560     *
     561     * @param array  $payload       Payload data for verification.
     562     * @param string $raw_body Webhook raw body from PayPal.
     563     * @param string $access_token  PayPal Access Token.
     564     */
     565    protected function verify_paypal_webhook_rest_api( array $payload, string $raw_body, string $access_token ): bool {
     566        // Fix the webhook_event to be an array.
     567        $payload['webhook_event'] = json_decode( $raw_body, true );
     568
     569        // Verify webhook signature via PayPal REST API.
     570        try {
     571            $url  = $this->api_endpoint . '/v1/notifications/verify-webhook-signature';
     572            $args = [
     573                'method'  => 'POST',
     574                'headers' => [
     575                    'Authorization' => 'Bearer ' . $access_token,
     576                    'Content-Type'  => 'application/json',
     577                ],
     578                'body'    => wp_json_encode( $payload ),
     579            ];
     580
     581            $response            = wp_remote_post( $url, $args );
     582            $response_data       = json_decode( wp_remote_retrieve_body( $response ), true );
     583            $verification_status = $response_data['verification_status'] ?? null;
     584
     585            if ( empty( $verification_status ) || 'success' !== strtolower( $verification_status ) ) {
     586                wp_subscrpt_write_debug_log( 'PayPal Webhook Verification: ' . wp_json_encode( $response_data ) );
     587                return false;
     588            }
     589
     590            return ( 'success' === strtolower( $verification_status ) ) ? true : false;
     591
     592        } catch ( Exception $e ) {
     593            $log_message = 'PayPal Webhook Verification Failed: ' . $e->getMessage();
     594            wp_subscrpt_write_log( $log_message );
     595            wp_subscrpt_write_debug_log( $log_message );
     596            return false;
     597        }
     598    }
     599
     600    /**
     601     * Verify PayPal webhook manually (self verification).
     602     *
     603     * @param array  $payload       Payload data for verification.
     604     * @param string $raw_body Webhook raw body from PayPal.
     605     */
     606    protected function verify_paypal_webhook_manual( array $payload, string $raw_body ): bool {
     607        // Enforce CRC32 for 32-bit systems (edge case)
     608        $crc = sprintf( '%u', crc32( $raw_body ) );
     609
     610        // Build Message
     611        $message = implode(
     612            '|',
     613            [
     614                $payload['transmission_id'],
     615                $payload['transmission_time'],
     616                $payload['webhook_id'],
     617                $crc,
     618            ]
     619        );
     620
     621        // Fetch & cache cert
     622        $cert_url  = esc_url_raw( $payload['cert_url'] );
     623        $cache_key = 'paypal_cert_' . md5( $cert_url );
     624
     625        $cert_pem = get_transient( $cache_key );
     626
     627        if ( ! $cert_pem ) {
     628            $response = wp_remote_get( $cert_url, [ 'timeout' => 20 ] );
     629            if ( is_wp_error( $response ) ) {
     630                return false;
     631            }
     632
     633            $cert_pem = wp_remote_retrieve_body( $response );
     634            set_transient( $cache_key, $cert_pem, DAY_IN_SECONDS );
     635        }
     636
     637        if ( empty( $cert_pem ) ) {
     638            return false;
     639        }
     640
     641        // Signature
     642        $signature = base64_decode( $payload['transmission_sig'], true );
     643
     644        if ( false === $signature ) {
     645            return false;
     646        }
     647
     648        // Final verification
     649        $verified = openssl_verify(
     650            $message,
     651            $signature,
     652            $cert_pem,
     653            OPENSSL_ALGO_SHA256
     654        );
     655
     656        return ( 1 === $verified );
    557657    }
    558658
     
    14541554
    14551555    /**
    1456      * Verify PayPal webhook.
    1457      *
    1458      * @param array  $verification_data Verification data to verify.
    1459      * @param string $access_token      PayPal Access Token.
    1460      */
    1461     public function verify_paypal_webhook( array $verification_data, string $access_token ): bool {
    1462         try {
    1463             $url  = $this->api_endpoint . '/v1/notifications/verify-webhook-signature';
    1464             $args = [
    1465                 'method'  => 'POST',
    1466                 'headers' => [
    1467                     'Authorization' => 'Bearer ' . $access_token,
    1468                     'Content-Type'  => 'application/json',
    1469                 ],
    1470                 'body'    => wp_json_encode( $verification_data ),
    1471             ];
    1472 
    1473             $response      = wp_remote_post( $url, $args );
    1474             $response_data = json_decode( wp_remote_retrieve_body( $response ) );
    1475 
    1476             if ( empty( $response_data->verification_status ?? null ) || 'SUCCESS' !== $response_data->verification_status ) {
    1477                 wp_subscrpt_write_debug_log( 'PayPal Webhook Verification: ' . wp_json_encode( $response_data ) );
    1478                 return false;
    1479             }
    1480 
    1481             if ( 'SUCCESS' === $response_data->verification_status ) {
    1482                 return true;
    1483             } else {
    1484                 return false;
    1485             }
    1486         } catch ( Exception $e ) {
    1487             $log_message = 'PayPal Webhook Verification Failed: ' . $e->getMessage();
    1488             wp_subscrpt_write_log( $log_message );
    1489             wp_subscrpt_write_debug_log( $log_message );
    1490             return false;
    1491         }
    1492     }
    1493 
    1494     /**
    14951556     * Get PayPal order details.
    14961557     *
  • subscription/trunk/includes/Illuminate/Helper.php

    r3415062 r3424485  
    2525     */
    2626    public static function get_typos( $number, $typo, $translate = false ) {
    27         if ( 1 === (int) $number && 'days' === $typo ) {
    28             return $translate ? __( 'day', 'wp_subscription' ) : 'day';
    29         } elseif ( 1 === (int) $number && 'weeks' === $typo ) {
    30             return $translate ? __( 'week', 'wp_subscription' ) : 'week';
    31         } elseif ( 1 === (int) $number && 'months' === $typo ) {
    32             return $translate ? __( 'month', 'wp_subscription' ) : 'month';
    33         } elseif ( 1 === (int) $number && 'years' === $typo ) {
    34             return $translate ? __( 'year', 'wp_subscription' ) : 'year';
    35         } else {
    36             return $typo;
     27        switch ( strtolower( $typo ) ) {
     28            case 'day':
     29            case 'days':
     30                return $translate
     31                    ? _n( 'day', 'days', $number, 'wp_subscription' )
     32                    : ( (int) $number === 1 ? 'day' : 'days' );
     33
     34            case 'week':
     35            case 'weeks':
     36                return $translate
     37                    ? _n( 'week', 'weeks', $number, 'wp_subscription' )
     38                    : ( (int) $number === 1 ? 'week' : 'weeks' );
     39
     40            case 'month':
     41            case 'months':
     42                return $translate
     43                    ? _n( 'month', 'months', $number, 'wp_subscription' )
     44                    : ( (int) $number === 1 ? 'month' : 'months' );
     45
     46            case 'year':
     47            case 'years':
     48                return $translate
     49                    ? _n( 'year', 'years', $number, 'wp_subscription' )
     50                    : ( (int) $number === 1 ? 'year' : 'years' );
     51
     52            default:
     53                return $typo;
    3754        }
    3855    }
     
    290307
    291308        $time = 1 === (int) $item_meta['time'] ? null : $item_meta['time'] . '-';
    292         $type = self::get_typos( $item_meta['time'], $item_meta['type'] );
     309        $type = self::get_typos( $item_meta['time'], $item_meta['type'], true );
    293310
    294311        $formatted_price = wc_price(
     
    297314                'currency' => $order->get_currency(),
    298315            )
    299         ) . ' / ' . $time . $type;
     316        ) . ' / ' . $time . ucfirst( $type );
    300317
    301318        if ( $display_trial ) {
    302             $trial     = $item_meta['trial'];
    303319            $has_trial = isset( $item_meta['trial'] ) && strlen( $item_meta['trial'] ) > 2;
     320            $trial     = $item_meta['trial'] ?? '';
    304321
    305322            if ( $has_trial ) {
    306                 $trial_html       = '<br/><small> + Got ' . $trial . ' free trial!</small>';
     323                // translators: %s: trial period.
     324                $trial_html       = '<br/><small> ' . sprintf( __( '+ %s free trial!', 'wp_subscription' ), $trial ) . '</small>';
    307325                $formatted_price .= $trial_html;
    308326            }
  • subscription/trunk/includes/Illuminate/Subscription/Subscription.php

    r3419216 r3424485  
    3333        switch ( strtolower( $view ) ) {
    3434            case 'view_subs':
    35                 $default_endpoint = 'view-subscription';
     35                $default_endpoint = 'subscription';
    3636                $endpoint         = $is_pro ? get_option( 'wpsubs_custom_view_subscription_endpoint', $default_endpoint ) : $default_endpoint;
    3737                break;
  • subscription/trunk/includes/Illuminate/views/subscription-table.php

    r3320126 r3424485  
    7171                </th>
    7272                <td class="td"
    73                     style="color: #636363; border: 1px solid #e5e5e5; vertical-align: middle; padding: 12px; text-align: left;"><?php echo ! empty( $next_date ) ? esc_html( gmdate( 'F d, Y', $next_date ) ) : '-'; ?></td>
     73                    style="color: #636363; border: 1px solid #e5e5e5; vertical-align: middle; padding: 12px; text-align: left;"><?php echo ! empty( $next_date ) ? esc_html( wp_date( 'F d, Y', $next_date ) ) : '-'; ?></td>
    7474            </tr>
    7575        <?php } else { ?>
     
    8888                </th>
    8989                <td class="td"
    90                     style="color: #636363; border: 1px solid #e5e5e5; vertical-align: middle; padding: 12px; text-align: left;"><?php echo ! empty( $start_date ) ? esc_html( gmdate( 'F d, Y', $start_date ) ) : '-'; ?></td>
     90                    style="color: #636363; border: 1px solid #e5e5e5; vertical-align: middle; padding: 12px; text-align: left;"><?php echo ! empty( $start_date ) ? esc_html( wp_date( 'F d, Y', $start_date ) ) : '-'; ?></td>
    9191            </tr>
    9292        <?php } ?>
  • subscription/trunk/languages/wp_subscription.pot

    r3419216 r3424485  
    1010"Content-Type: text/plain; charset=UTF-8\n"
    1111"Content-Transfer-Encoding: 8bit\n"
    12 "POT-Creation-Date: 2025-12-14T05:43:22+00:00\n"
     12"POT-Creation-Date: 2025-12-21T06:59:21+00:00\n"
    1313"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
    1414"X-Generator: WP-CLI 2.12.0\n"
     
    562562#: includes/Admin/views/integrations.php:46
    563563#: includes/Admin/views/subscription-list.php:25
    564 #: includes/Illuminate/Helper.php:48
     564#: includes/Illuminate/Helper.php:65
    565565msgid "Active"
    566566msgstr ""
     
    835835
    836836#: includes/Admin/views/subscription-list.php:26
    837 #: includes/Illuminate/Helper.php:47
     837#: includes/Illuminate/Helper.php:64
    838838msgid "Pending"
    839839msgstr ""
    840840
    841841#: includes/Admin/views/subscription-list.php:27
    842 #: includes/Illuminate/Helper.php:52
     842#: includes/Illuminate/Helper.php:69
    843843msgid "Cancelled"
    844844msgstr ""
    845845
    846846#: includes/Admin/views/subscription-list.php:28
    847 #: includes/Illuminate/Helper.php:50
     847#: includes/Illuminate/Helper.php:67
    848848msgid "Expired"
    849849msgstr ""
    850850
    851851#: includes/Admin/views/subscription-list.php:29
    852 #: includes/Illuminate/Helper.php:53
     852#: includes/Illuminate/Helper.php:70
    853853msgid "Draft"
    854854msgstr ""
    855855
    856856#: includes/Admin/views/subscription-list.php:30
    857 #: includes/Illuminate/Helper.php:54
     857#: includes/Illuminate/Helper.php:71
    858858msgid "Trash"
    859859msgstr ""
     
    10851085
    10861086#: includes/functions.php:46
    1087 #: includes/Illuminate/Helper.php:28
     1087#: includes/Illuminate/Helper.php:31
    10881088msgid "day"
    1089 msgstr ""
     1089msgid_plural "days"
     1090msgstr[0] ""
     1091msgstr[1] ""
    10901092
    10911093#: includes/functions.php:48
    1092 #: includes/Illuminate/Helper.php:30
     1094#: includes/Illuminate/Helper.php:37
    10931095msgid "week"
    1094 msgstr ""
     1096msgid_plural "weeks"
     1097msgstr[0] ""
     1098msgstr[1] ""
    10951099
    10961100#: includes/functions.php:50
    1097 #: includes/Illuminate/Helper.php:32
     1101#: includes/Illuminate/Helper.php:43
    10981102msgid "month"
    1099 msgstr ""
     1103msgid_plural "months"
     1104msgstr[0] ""
     1105msgstr[1] ""
    11001106
    11011107#: includes/functions.php:52
    1102 #: includes/Illuminate/Helper.php:34
     1108#: includes/Illuminate/Helper.php:49
    11031109msgid "year"
    1104 msgstr ""
     1110msgid_plural "years"
     1111msgstr[0] ""
     1112msgstr[1] ""
    11051113
    11061114#: includes/functions.php:414
     
    11091117
    11101118#: includes/functions.php:415
    1111 #: includes/Illuminate/Helper.php:376
     1119#: includes/Illuminate/Helper.php:394
    11121120msgid "Renewal Order"
    11131121msgstr ""
     
    13241332
    13251333#. translators: %1$s: alert name; %2$s: order id.
    1326 #: includes/Illuminate/Gateways/Paypal/Paypal.php:500
     1334#: includes/Illuminate/Gateways/Paypal/Paypal.php:491
    13271335#, php-format
    13281336msgid "PayPal webhook received [%s]. Order not found."
     
    13301338
    13311339#. translators: %1$s: alert name; %2$s: order id.
    1332 #: includes/Illuminate/Gateways/Paypal/Paypal.php:516
     1340#: includes/Illuminate/Gateways/Paypal/Paypal.php:507
    13331341#, php-format
    13341342msgid "PayPal webhook received [%s]. No actions taken."
     
    13361344
    13371345#. translators: %1$s: alert name; %2$s: subscription id.
    1338 #: includes/Illuminate/Gateways/Paypal/Paypal.php:807
     1346#: includes/Illuminate/Gateways/Paypal/Paypal.php:907
    13391347#, php-format
    13401348msgid "Transaction webhook received [%1$s]. No order found for subscription ID [%2$s]."
    13411349msgstr ""
    13421350
    1343 #: includes/Illuminate/Gateways/Paypal/Paypal.php:820
     1351#: includes/Illuminate/Gateways/Paypal/Paypal.php:920
    13441352msgid "Payment completed by paypal webhook."
    13451353msgstr ""
    13461354
    1347 #: includes/Illuminate/Gateways/Paypal/Paypal.php:825
     1355#: includes/Illuminate/Gateways/Paypal/Paypal.php:925
    13481356msgid "Failed to complete payment. Requested by paypal webhook."
    13491357msgstr ""
    13501358
    1351 #: includes/Illuminate/Gateways/Paypal/Paypal.php:834
     1359#: includes/Illuminate/Gateways/Paypal/Paypal.php:934
    13521360msgid "Payment refunded by paypal webhook."
    13531361msgstr ""
    13541362
    1355 #: includes/Illuminate/Gateways/Paypal/Paypal.php:839
     1363#: includes/Illuminate/Gateways/Paypal/Paypal.php:939
    13561364msgid "Failed to refund payment. Requested by paypal webhook."
    13571365msgstr ""
    13581366
    13591367#. translators: %s: alert name.
    1360 #: includes/Illuminate/Gateways/Paypal/Paypal.php:849
     1368#: includes/Illuminate/Gateways/Paypal/Paypal.php:949
    13611369#, php-format
    13621370msgid "Transaction webhook received [%s]. No actions taken."
    13631371msgstr ""
    13641372
    1365 #: includes/Illuminate/Gateways/Paypal/Paypal.php:875
     1373#: includes/Illuminate/Gateways/Paypal/Paypal.php:975
    13661374msgid "Subscription not found. Attempting to get from order item."
    13671375msgstr ""
    13681376
    13691377#. translators: %s: alert name.
    1370 #: includes/Illuminate/Gateways/Paypal/Paypal.php:894
     1378#: includes/Illuminate/Gateways/Paypal/Paypal.php:994
    13711379#, php-format
    13721380msgid "Subscription webhook received [%s]. Subscription not found."
    13731381msgstr ""
    13741382
    1375 #: includes/Illuminate/Gateways/Paypal/Paypal.php:907
     1383#: includes/Illuminate/Gateways/Paypal/Paypal.php:1007
    13761384msgid "Subscription activated by PayPal webhook."
    13771385msgstr ""
    13781386
    1379 #: includes/Illuminate/Gateways/Paypal/Paypal.php:913
    1380 #: includes/Illuminate/Gateways/Paypal/Paypal.php:926
    1381 #: includes/Illuminate/Gateways/Paypal/Paypal.php:939
     1387#: includes/Illuminate/Gateways/Paypal/Paypal.php:1013
     1388#: includes/Illuminate/Gateways/Paypal/Paypal.php:1026
     1389#: includes/Illuminate/Gateways/Paypal/Paypal.php:1039
    13821390msgid "Subscription webhook received. No actions taken."
    13831391msgstr ""
    13841392
    1385 #: includes/Illuminate/Gateways/Paypal/Paypal.php:920
     1393#: includes/Illuminate/Gateways/Paypal/Paypal.php:1020
    13861394msgid "Subscription expired by PayPal webhook."
    13871395msgstr ""
    13881396
    1389 #: includes/Illuminate/Gateways/Paypal/Paypal.php:933
     1397#: includes/Illuminate/Gateways/Paypal/Paypal.php:1033
    13901398msgid "Subscription cancelled by PayPal webhook."
    13911399msgstr ""
    13921400
    13931401#. translators: %s: alert name.
    1394 #: includes/Illuminate/Gateways/Paypal/Paypal.php:945
     1402#: includes/Illuminate/Gateways/Paypal/Paypal.php:1045
    13951403#, php-format
    13961404msgid "Subscription webhook received [%s]. No actions taken."
    13971405msgstr ""
    13981406
    1399 #: includes/Illuminate/Gateways/Paypal/Paypal.php:1257
     1407#: includes/Illuminate/Gateways/Paypal/Paypal.php:1357
    14001408msgid "PayPal Product Creation Error: Product data is incomplete. Name and type are required."
    14011409msgstr ""
     
    14431451msgstr ""
    14441452
    1445 #: includes/Illuminate/Helper.php:49
     1453#: includes/Illuminate/Helper.php:66
    14461454msgid "On Hold"
    14471455msgstr ""
    14481456
    1449 #: includes/Illuminate/Helper.php:51
     1457#: includes/Illuminate/Helper.php:68
    14501458msgid "Pending Cancellation"
    14511459msgstr ""
    14521460
     1461#. translators: %s: trial period.
     1462#: includes/Illuminate/Helper.php:324
     1463#, php-format
     1464msgid "+ %s free trial!"
     1465msgstr ""
     1466
    14531467#. translators: %1$s: order id, %2$d: payment number, %3$d: total payments
    1454 #: includes/Illuminate/Helper.php:364
     1468#: includes/Illuminate/Helper.php:382
    14551469#, php-format
    14561470msgid "Split payment installment %2$d of %3$d. Order %1$s created for subscription."
    14571471msgstr ""
    14581472
    1459 #: includes/Illuminate/Helper.php:369
     1473#: includes/Illuminate/Helper.php:387
    14601474msgid "Split Payment - Renewal"
    14611475msgstr ""
    14621476
    14631477#. translators: order id.
    1464 #: includes/Illuminate/Helper.php:373
     1478#: includes/Illuminate/Helper.php:391
    14651479#, php-format
    14661480msgid "The order %s has been created for the subscription"
     
    14681482
    14691483#. translators: %1$s: order id, %2$d: max payments
    1470 #: includes/Illuminate/Helper.php:454
     1484#: includes/Illuminate/Helper.php:472
    14711485#, php-format
    14721486msgid "Split payment subscription created successfully. Order: %1$s. Total installments: %2$d."
    14731487msgstr ""
    14741488
    1475 #: includes/Illuminate/Helper.php:458
     1489#: includes/Illuminate/Helper.php:476
    14761490msgid "Split Payment - New Subscription"
    14771491msgstr ""
    14781492
    14791493#. translators: Order Id.
    1480 #: includes/Illuminate/Helper.php:462
     1494#: includes/Illuminate/Helper.php:480
    14811495#, php-format
    14821496msgid "Subscription successfully created. Order is %s"
    14831497msgstr ""
    14841498
    1485 #: includes/Illuminate/Helper.php:465
     1499#: includes/Illuminate/Helper.php:483
    14861500#: includes/Illuminate/Post.php:67
    14871501msgid "New Subscription"
    14881502msgstr ""
    14891503
    1490 #: includes/Illuminate/Helper.php:1096
     1504#: includes/Illuminate/Helper.php:1114
    14911505msgid "Subscription renewal isn't possible due to previous order not completed or deletion."
    14921506msgstr ""
  • subscription/trunk/subscription.php

    r3419216 r3424485  
    77 * Description: WPSubscription allow WooCommerce to enables recurring payments, subscriptions, and auto-renewals for digital and physical products. Supports Stripe, PayPal, Paddle, and more.
    88 *
    9  * Version: 1.8.11
     9 * Version: 1.8.12
    1010 *
    1111 * Author: ConversWP
     
    1818 *
    1919 * Requires at least: 6.0
    20  * Tested up to: 6.8
     20 * Tested up to: 6.9
    2121 *
    2222 * WC requires at least: 6.0
     
    5151     * @var string
    5252     */
    53     const version = '1.8.11';
     53    const version = '1.8.12';
    5454
    5555    /**
  • subscription/trunk/templates/myaccount/subscriptions.php

    r3419216 r3424485  
    5050
    5151                $start_date = $subscription_data['start_date'] ?? '';
    52                 $start_date = ! empty( $start_date ) ? gmdate( 'F j, Y', strtotime( $start_date ) ) : '-';
     52                $start_date = ! empty( $start_date ) ? wp_date( 'F j, Y', strtotime( $start_date ) ) : '-';
    5353
    5454                $next_date = $subscription_data['next_date'] ?? '';
    55                 $next_date = ! empty( $next_date ) ? gmdate( 'F j, Y', strtotime( $next_date ) ) : '-';
     55                $next_date = ! empty( $next_date ) ? wp_date( 'F j, Y', strtotime( $next_date ) ) : '-';
    5656
    5757                $trial      = get_post_meta( get_the_ID(), '_subscrpt_trial', true );
  • subscription/trunk/vendor/composer/installed.php

    r3419216 r3424485  
    22    'root' => array(
    33        'name' => 'converswp/subscription',
    4         'pretty_version' => '1.8.11',
    5         'version' => '1.8.11.0',
    6         'reference' => 'cdc6fcf8aa53e23284845046caf19ef6649b6df0',
     4        'pretty_version' => '1.8.12',
     5        'version' => '1.8.12.0',
     6        'reference' => 'a9d0d2372826303a8c2a6a7ed051f99168ccbcdb',
    77        'type' => 'wordpress-plugin',
    88        'install_path' => __DIR__ . '/../../',
     
    1212    'versions' => array(
    1313        'converswp/subscription' => array(
    14             'pretty_version' => '1.8.11',
    15             'version' => '1.8.11.0',
    16             'reference' => 'cdc6fcf8aa53e23284845046caf19ef6649b6df0',
     14            'pretty_version' => '1.8.12',
     15            'version' => '1.8.12.0',
     16            'reference' => 'a9d0d2372826303a8c2a6a7ed051f99168ccbcdb',
    1717            'type' => 'wordpress-plugin',
    1818            'install_path' => __DIR__ . '/../../',
Note: See TracChangeset for help on using the changeset viewer.