Plugin Directory

Changeset 3473803


Ignore:
Timestamp:
03/03/2026 03:30:51 PM (3 weeks ago)
Author:
stitchexpress
Message:

1.4.0

Location:
stitch-express
Files:
12 edited
1 copied

Legend:

Unmodified
Added
Removed
  • stitch-express/tags/1.4.0/build/index.asset.php

    r3442620 r3473803  
    1 <?php return array('dependencies' => array('react'), 'version' => 'b7bf90c4bf35b8115381');
     1<?php return array('dependencies' => array('react'), 'version' => '501bc5cb7bd21f909312');
  • stitch-express/tags/1.4.0/build/index.js

    r3442620 r3473803  
    1 (()=>{"use strict";const e=window.React;function t(t){return(0,e.createElement)("span",null,"Secure payments powered by Stitch Express")}const{registerPaymentMethod:a}=window.wc.wcBlocksRegistry;a({label:(0,e.createElement)((function(t){const a=window.wc.wcSettings.getSetting("stitch-express_data");return(0,e.createElement)("div",{className:"UxZcXi_y2qynokK0PSsy"},(0,e.createElement)("span",{className:"UmqPaUuJYLCVz6igFbTW"},"Pay with Apple | Google | Capitec | Card | BNPL"),(0,e.createElement)("div",{className:"IGKYqJZGeWmHgWNjllAN"},(0,e.createElement)("img",{src:a.icon_block_master_card,alt:"Master card logo"}),(0,e.createElement)("img",{src:a.icon_block_visa,alt:"visa logo"}),(0,e.createElement)("img",{src:a.icon_block_apple_pay,alt:"apple pay logo"}),(0,e.createElement)("img",{src:a.icon_block_google_pay,alt:"google pay logo"}),(0,e.createElement)("img",{src:a.icon_block_capitec_pay,alt:"capitec pay logo"}),(0,e.createElement)("img",{src:a.icon_block_bnpl,alt:"BNPL logo"})))}),null),ariaLabel:"Pay with Stitch Express",content:(0,e.createElement)(t,null),edit:(0,e.createElement)(t,null),name:"stitch-express",canMakePayment(e){const{currency_code:t,total_price:a}=e.cartTotals;return"ZAR"===t&&parseInt(a,10)>=500},supports:{features:["products","refunds"]},placeOrderButtonLabel:"Pay"})})();
     1(()=>{"use strict";const e=window.React;function t(t){return(0,e.createElement)("span",null,"Secure payments powered by Stitch Express")}const{registerPaymentMethod:a}=window.wc.wcBlocksRegistry;a({label:(0,e.createElement)((function(t){const a=window.wc.wcSettings.getSetting("stitch-express_data");return(0,e.createElement)("div",{className:"UxZcXi_y2qynokK0PSsy"},(0,e.createElement)("span",{className:"UmqPaUuJYLCVz6igFbTW"},"Pay with Apple | Google | Capitec | Card | BNPL"),(0,e.createElement)("div",{className:"IGKYqJZGeWmHgWNjllAN"},(0,e.createElement)("img",{src:a.icon_block_master_card,alt:"Master card logo"}),(0,e.createElement)("img",{src:a.icon_block_visa,alt:"visa logo"}),(0,e.createElement)("img",{src:a.icon_block_apple_pay,alt:"apple pay logo"}),(0,e.createElement)("img",{src:a.icon_block_google_pay,alt:"google pay logo"}),(0,e.createElement)("img",{src:a.icon_block_capitec_pay,alt:"capitec pay logo"}),(0,e.createElement)("img",{src:a.icon_block_bnpl,alt:"BNPL logo"})))}),null),ariaLabel:"Pay with Stitch Express",content:(0,e.createElement)(t,null),edit:(0,e.createElement)(t,null),name:"stitch-express",canMakePayment(e){const{currency_code:t,total_price:a}=e.cartTotals;return"ZAR"===t&&parseInt(a,10)>=100},supports:{features:["products","refunds"]},placeOrderButtonLabel:"Pay"})})();
  • stitch-express/tags/1.4.0/includes/stitch-express-client.php

    r3472754 r3473803  
    3838
    3939class Stitch_Express_Client {
    40     private const PLUGIN_VERSION = '1.3.9';
     40    private const PLUGIN_VERSION = '1.4.0';
    4141    private string $baseUrl = 'https://express.stitch.money';
    4242    private string $client_id;
     
    9595
    9696        return $response->data['data']['refund'];
     97    }
     98
     99    /**
     100     * @throws Stitch_Express_Failed_Request_Exception
     101     * @throws Stitch_Express_Failed_Authentication_Exception
     102     */
     103    public function confirm_delivery(string $payment_id, string $merchant_reference): void {
     104        $response = $this->make_request("/api/v1/payments/{$payment_id}/order-confirmed", 'POST', [
     105            'merchantReference' => $merchant_reference,
     106        ]);
     107
     108        if (!$response->data['success']) {
     109            throw new Stitch_Express_Failed_Request_Exception($response->status_code, $response->raw_body);
     110        }
    97111    }
    98112
  • stitch-express/tags/1.4.0/includes/stitch-express-gateway.php

    r3472754 r3473803  
    2727
    2828        add_action('woocommerce_update_options_payment_gateways_'.$this->id, [$this, 'process_admin_options']);
     29        add_action('wp_ajax_stitch_express_dismiss_webhook_notice', [$this, 'dismiss_webhook_notice']);
    2930    }
    3031
     
    3738    }
    3839
     40    public function dismiss_webhook_notice(): void {
     41        check_ajax_referer('stitch_express_dismiss_webhook_notice', 'nonce');
     42        update_user_meta(get_current_user_id(), '_stitch_express_webhook_notice_dismissed', '1');
     43        wp_send_json_success();
     44    }
     45
    3946    public function admin_options(): void {
     47        $webhook_url = rest_url('stitch-express/v1/webhook');
     48        $is_dismissed = get_user_meta(get_current_user_id(), '_stitch_express_webhook_notice_dismissed', true) === '1';
     49
     50        if (!$is_dismissed) {
     51            ?>
     52            <div id="stitch-express-webhook-notice" style="
     53                background: linear-gradient(135deg, #FFF7ED 0%, #FFFBF5 100%);
     54                border: 1px solid #F59E0B;
     55                border-left: 4px solid #F59E0B;
     56                border-radius: 6px;
     57                padding: 16px 20px;
     58                margin: 20px 0;
     59                display: flex;
     60                align-items: flex-start;
     61                gap: 14px;
     62                max-width: 800px;
     63                position: relative;
     64                transition: opacity 0.3s ease, max-height 0.3s ease;
     65                overflow: hidden;
     66            ">
     67                <span style="font-size: 22px; line-height: 1; flex-shrink: 0; margin-top: 1px;">&#9888;</span>
     68                <div style="flex: 1;">
     69                    <p style="margin: 0 0 6px; font-weight: 600; font-size: 14px; color: #92400E;">
     70                        Webhook Firewall Notice
     71                    </p>
     72                    <p style="margin: 0 0 10px; color: #78350F; font-size: 13px; line-height: 1.5;">
     73                        Stitch Express sends payment confirmations to your site via webhooks. If your hosting provider
     74                        or security plugin (e.g. Cloudflare, Sucuri, Wordfence) blocks incoming POST requests,
     75                        orders may not update automatically. Please ensure the following URL is allowlisted:
     76                    </p>
     77                    <code style="
     78                        display: inline-block;
     79                        background: #FFFFFF;
     80                        border: 1px solid #E5E7EB;
     81                        border-radius: 4px;
     82                        padding: 8px 12px;
     83                        font-size: 12.5px;
     84                        color: #1F2937;
     85                        word-break: break-all;
     86                        line-height: 1.4;
     87                    "><?php echo esc_html($webhook_url); ?></code>
     88                </div>
     89                <button
     90                    type="button"
     91                    id="stitch-express-dismiss-webhook-notice"
     92                    style="
     93                        background: none;
     94                        border: none;
     95                        cursor: pointer;
     96                        color: #92400E;
     97                        font-size: 20px;
     98                        line-height: 1;
     99                        padding: 0 2px;
     100                        flex-shrink: 0;
     101                        opacity: 0.6;
     102                        transition: opacity 0.15s ease;
     103                    "
     104                    onmouseover="this.style.opacity='1'"
     105                    onmouseout="this.style.opacity='0.6'"
     106                    title="Dismiss notice"
     107                >&times;</button>
     108            </div>
     109            <script>
     110                document.getElementById('stitch-express-dismiss-webhook-notice').addEventListener('click', function() {
     111                    var notice = document.getElementById('stitch-express-webhook-notice');
     112                    notice.style.opacity = '0';
     113                    notice.style.maxHeight = '0';
     114                    notice.style.padding = '0';
     115                    notice.style.margin = '0';
     116                    notice.style.border = 'none';
     117
     118                    var data = new FormData();
     119                    data.append('action', 'stitch_express_dismiss_webhook_notice');
     120                    data.append('nonce', '<?php echo esc_js(wp_create_nonce('stitch_express_dismiss_webhook_notice')); ?>');
     121                    fetch(ajaxurl, { method: 'POST', body: data });
     122                });
     123            </script>
     124        <?php
     125        }
     126
    40127        parent::admin_options();
    41128        ?>
  • stitch-express/tags/1.4.0/readme.txt

    r3472754 r3473803  
    33Tags: woocommerce, card, payments, south africa, apple pay, google pay, stitch, express, stitch express
    44Tested up to: 6.7
    5 Stable tag: 1.3.9
     5Stable tag: 1.4.0
    66License: GPLv3
    77License URI: https://www.gnu.org/licenses/gpl-3.0.html
     
    8383
    8484== Changelog ==
     85= 1.4.0 =
     86* Updates to plugin admin page
     87
    8588= 1.3.9 =
    8689* Stitch BNPL Widget fixes
     
    181184
    182185== Upgrade Notice ==
     186= 1.4.0 =
     187* Updates to plugin admin page
     188
    183189= 1.3.9 =
    184190* Stitch BNPL Widget fixes
  • stitch-express/tags/1.4.0/stitch-express.php

    r3472754 r3473803  
    99 * Description:          Use Stitch Express to easily and securely accept Card payment on your WooCommerce store.
    1010 * Plugin URI:           https://wordpress.org/plugins/stitchexpress/
    11  * Version:              1.3.9
     11 * Version:              1.4.0
    1212 * Requires at least:    6.5
    1313 * Requires PHP:         8.0
     
    106106}
    107107
     108function stitch_express_complete_order_payment(WC_Order $order, string $payment_id, string $reference, string $source, Stitch_Express_Client $client, bool $override = false): bool {
     109    $logger = wc_get_logger();
     110    $can_complete = in_array($order->get_status(), ['awaiting-payment', 'pending', 'cancelled', 'failed'], true);
     111
     112    if (!$can_complete && !$override) {
     113        $logger->info(
     114            "{$source}: Order {$order->get_id()} status is '{$order->get_status()}', skipping payment completion.",
     115            ['source' => 'stitch-express']
     116        );
     117
     118        return false;
     119    }
     120
     121    if (in_array($order->get_status(), ['cancelled', 'failed'], true)) {
     122        $order->add_order_note(
     123            sprintf(
     124                'Stitch Express: Payment confirmed (ID: %s) while order was "%s". Order status will be updated.',
     125                $payment_id,
     126                $order->get_status()
     127            )
     128        );
     129    }
     130
     131    $previous_status = $order->get_status();
     132
     133    $order->payment_complete($payment_id);
     134    $order->save();
     135
     136    $logger->info(
     137        "{$source}: Payment completed for order {$order->get_id()}. Order status updated from '{$previous_status}' to '{$order->get_status()}'. Stitch Payment ID: {$payment_id}",
     138        ['source' => 'stitch-express']
     139    );
     140
     141    try {
     142        $client->confirm_delivery($payment_id, $reference);
     143    } catch (Exception $e) {
     144        $logger->error(
     145            "{$source}: Failed to send delivery confirmation for payment {$payment_id}: {$e->getMessage()}",
     146            ['source' => 'stitch-express']
     147        );
     148    }
     149
     150    return true;
     151}
     152
    108153/**
    109154 * GET callback handler — used for user browser redirects.
     
    153198    }
    154199
    155     $can_complete_payment = in_array($order->get_status(), ['awaiting-payment', 'pending', 'cancelled', 'failed'], true);
    156 
    157     if ($can_complete_payment || $override) {
    158         if (in_array($order->get_status(), ['cancelled', 'failed'], true)) {
    159             $order->add_order_note(
    160                 sprintf(
    161                     'Stitch Express: Payment confirmed (ID: %s) while order was "%s". Overriding status and completing payment.',
    162                     $payment_id,
    163                     $order->get_status()
    164                 )
    165             );
    166         }
    167 
    168         $logger->info(
    169             "Marking order {$order_id} with status '{$order->get_status()}' as complete. Stitch Payment ID: {$payment_id}",
    170             ['source' => 'stitch-express']
    171         );
    172 
    173         $order->payment_complete($payment_id);
    174         $order->save();
    175 
    176         return stitch_express_generate_redirect_response($order->get_checkout_order_received_url());
    177     }
    178 
    179     $logger->info("Order {$order_id} status is '{$order->get_status()}', skipping payment completion", ['source' => 'stitch-express']);
     200    stitch_express_complete_order_payment($order, $payment_id, $reference, 'Callback', $stitch_express_client, $override);
    180201
    181202    return stitch_express_generate_redirect_response($order->get_checkout_order_received_url());
     
    274295    }
    275296
    276     $can_complete_payment = in_array($order->get_status(), ['awaiting-payment', 'pending', 'cancelled', 'failed'], true);
    277 
    278     if ($can_complete_payment) {
    279         if (in_array($order->get_status(), ['cancelled', 'failed'], true)) {
    280             $order->add_order_note(
    281                 sprintf(
    282                     'Stitch Express: Payment confirmed (ID: %s) while order was "%s". Overriding status and completing payment.',
    283                     $payment_id,
    284                     $order->get_status()
    285                 )
    286             );
    287         }
    288 
    289         $logger->info(
    290             "Webhook: Marking order {$order_id} with status '{$order->get_status()}' as complete. Stitch Payment ID: {$payment_id}",
    291             ['source' => 'stitch-express']
    292         );
    293 
    294         $order->payment_complete($payment_id);
    295         $order->save();
    296     } else {
    297         $logger->info("Webhook: Order {$order_id} status is '{$order->get_status()}', skipping payment completion", ['source' => 'stitch-express']);
    298     }
     297    stitch_express_complete_order_payment($order, $payment_id, $reference, 'Webhook', $stitch_express_client);
    299298
    300299    return new WP_REST_Response([
  • stitch-express/trunk/build/index.asset.php

    r3442620 r3473803  
    1 <?php return array('dependencies' => array('react'), 'version' => 'b7bf90c4bf35b8115381');
     1<?php return array('dependencies' => array('react'), 'version' => '501bc5cb7bd21f909312');
  • stitch-express/trunk/build/index.js

    r3442620 r3473803  
    1 (()=>{"use strict";const e=window.React;function t(t){return(0,e.createElement)("span",null,"Secure payments powered by Stitch Express")}const{registerPaymentMethod:a}=window.wc.wcBlocksRegistry;a({label:(0,e.createElement)((function(t){const a=window.wc.wcSettings.getSetting("stitch-express_data");return(0,e.createElement)("div",{className:"UxZcXi_y2qynokK0PSsy"},(0,e.createElement)("span",{className:"UmqPaUuJYLCVz6igFbTW"},"Pay with Apple | Google | Capitec | Card | BNPL"),(0,e.createElement)("div",{className:"IGKYqJZGeWmHgWNjllAN"},(0,e.createElement)("img",{src:a.icon_block_master_card,alt:"Master card logo"}),(0,e.createElement)("img",{src:a.icon_block_visa,alt:"visa logo"}),(0,e.createElement)("img",{src:a.icon_block_apple_pay,alt:"apple pay logo"}),(0,e.createElement)("img",{src:a.icon_block_google_pay,alt:"google pay logo"}),(0,e.createElement)("img",{src:a.icon_block_capitec_pay,alt:"capitec pay logo"}),(0,e.createElement)("img",{src:a.icon_block_bnpl,alt:"BNPL logo"})))}),null),ariaLabel:"Pay with Stitch Express",content:(0,e.createElement)(t,null),edit:(0,e.createElement)(t,null),name:"stitch-express",canMakePayment(e){const{currency_code:t,total_price:a}=e.cartTotals;return"ZAR"===t&&parseInt(a,10)>=500},supports:{features:["products","refunds"]},placeOrderButtonLabel:"Pay"})})();
     1(()=>{"use strict";const e=window.React;function t(t){return(0,e.createElement)("span",null,"Secure payments powered by Stitch Express")}const{registerPaymentMethod:a}=window.wc.wcBlocksRegistry;a({label:(0,e.createElement)((function(t){const a=window.wc.wcSettings.getSetting("stitch-express_data");return(0,e.createElement)("div",{className:"UxZcXi_y2qynokK0PSsy"},(0,e.createElement)("span",{className:"UmqPaUuJYLCVz6igFbTW"},"Pay with Apple | Google | Capitec | Card | BNPL"),(0,e.createElement)("div",{className:"IGKYqJZGeWmHgWNjllAN"},(0,e.createElement)("img",{src:a.icon_block_master_card,alt:"Master card logo"}),(0,e.createElement)("img",{src:a.icon_block_visa,alt:"visa logo"}),(0,e.createElement)("img",{src:a.icon_block_apple_pay,alt:"apple pay logo"}),(0,e.createElement)("img",{src:a.icon_block_google_pay,alt:"google pay logo"}),(0,e.createElement)("img",{src:a.icon_block_capitec_pay,alt:"capitec pay logo"}),(0,e.createElement)("img",{src:a.icon_block_bnpl,alt:"BNPL logo"})))}),null),ariaLabel:"Pay with Stitch Express",content:(0,e.createElement)(t,null),edit:(0,e.createElement)(t,null),name:"stitch-express",canMakePayment(e){const{currency_code:t,total_price:a}=e.cartTotals;return"ZAR"===t&&parseInt(a,10)>=100},supports:{features:["products","refunds"]},placeOrderButtonLabel:"Pay"})})();
  • stitch-express/trunk/includes/stitch-express-client.php

    r3472754 r3473803  
    3838
    3939class Stitch_Express_Client {
    40     private const PLUGIN_VERSION = '1.3.9';
     40    private const PLUGIN_VERSION = '1.4.0';
    4141    private string $baseUrl = 'https://express.stitch.money';
    4242    private string $client_id;
     
    9595
    9696        return $response->data['data']['refund'];
     97    }
     98
     99    /**
     100     * @throws Stitch_Express_Failed_Request_Exception
     101     * @throws Stitch_Express_Failed_Authentication_Exception
     102     */
     103    public function confirm_delivery(string $payment_id, string $merchant_reference): void {
     104        $response = $this->make_request("/api/v1/payments/{$payment_id}/order-confirmed", 'POST', [
     105            'merchantReference' => $merchant_reference,
     106        ]);
     107
     108        if (!$response->data['success']) {
     109            throw new Stitch_Express_Failed_Request_Exception($response->status_code, $response->raw_body);
     110        }
    97111    }
    98112
  • stitch-express/trunk/includes/stitch-express-gateway.php

    r3472754 r3473803  
    2727
    2828        add_action('woocommerce_update_options_payment_gateways_'.$this->id, [$this, 'process_admin_options']);
     29        add_action('wp_ajax_stitch_express_dismiss_webhook_notice', [$this, 'dismiss_webhook_notice']);
    2930    }
    3031
     
    3738    }
    3839
     40    public function dismiss_webhook_notice(): void {
     41        check_ajax_referer('stitch_express_dismiss_webhook_notice', 'nonce');
     42        update_user_meta(get_current_user_id(), '_stitch_express_webhook_notice_dismissed', '1');
     43        wp_send_json_success();
     44    }
     45
    3946    public function admin_options(): void {
     47        $webhook_url = rest_url('stitch-express/v1/webhook');
     48        $is_dismissed = get_user_meta(get_current_user_id(), '_stitch_express_webhook_notice_dismissed', true) === '1';
     49
     50        if (!$is_dismissed) {
     51            ?>
     52            <div id="stitch-express-webhook-notice" style="
     53                background: linear-gradient(135deg, #FFF7ED 0%, #FFFBF5 100%);
     54                border: 1px solid #F59E0B;
     55                border-left: 4px solid #F59E0B;
     56                border-radius: 6px;
     57                padding: 16px 20px;
     58                margin: 20px 0;
     59                display: flex;
     60                align-items: flex-start;
     61                gap: 14px;
     62                max-width: 800px;
     63                position: relative;
     64                transition: opacity 0.3s ease, max-height 0.3s ease;
     65                overflow: hidden;
     66            ">
     67                <span style="font-size: 22px; line-height: 1; flex-shrink: 0; margin-top: 1px;">&#9888;</span>
     68                <div style="flex: 1;">
     69                    <p style="margin: 0 0 6px; font-weight: 600; font-size: 14px; color: #92400E;">
     70                        Webhook Firewall Notice
     71                    </p>
     72                    <p style="margin: 0 0 10px; color: #78350F; font-size: 13px; line-height: 1.5;">
     73                        Stitch Express sends payment confirmations to your site via webhooks. If your hosting provider
     74                        or security plugin (e.g. Cloudflare, Sucuri, Wordfence) blocks incoming POST requests,
     75                        orders may not update automatically. Please ensure the following URL is allowlisted:
     76                    </p>
     77                    <code style="
     78                        display: inline-block;
     79                        background: #FFFFFF;
     80                        border: 1px solid #E5E7EB;
     81                        border-radius: 4px;
     82                        padding: 8px 12px;
     83                        font-size: 12.5px;
     84                        color: #1F2937;
     85                        word-break: break-all;
     86                        line-height: 1.4;
     87                    "><?php echo esc_html($webhook_url); ?></code>
     88                </div>
     89                <button
     90                    type="button"
     91                    id="stitch-express-dismiss-webhook-notice"
     92                    style="
     93                        background: none;
     94                        border: none;
     95                        cursor: pointer;
     96                        color: #92400E;
     97                        font-size: 20px;
     98                        line-height: 1;
     99                        padding: 0 2px;
     100                        flex-shrink: 0;
     101                        opacity: 0.6;
     102                        transition: opacity 0.15s ease;
     103                    "
     104                    onmouseover="this.style.opacity='1'"
     105                    onmouseout="this.style.opacity='0.6'"
     106                    title="Dismiss notice"
     107                >&times;</button>
     108            </div>
     109            <script>
     110                document.getElementById('stitch-express-dismiss-webhook-notice').addEventListener('click', function() {
     111                    var notice = document.getElementById('stitch-express-webhook-notice');
     112                    notice.style.opacity = '0';
     113                    notice.style.maxHeight = '0';
     114                    notice.style.padding = '0';
     115                    notice.style.margin = '0';
     116                    notice.style.border = 'none';
     117
     118                    var data = new FormData();
     119                    data.append('action', 'stitch_express_dismiss_webhook_notice');
     120                    data.append('nonce', '<?php echo esc_js(wp_create_nonce('stitch_express_dismiss_webhook_notice')); ?>');
     121                    fetch(ajaxurl, { method: 'POST', body: data });
     122                });
     123            </script>
     124        <?php
     125        }
     126
    40127        parent::admin_options();
    41128        ?>
  • stitch-express/trunk/readme.txt

    r3472754 r3473803  
    33Tags: woocommerce, card, payments, south africa, apple pay, google pay, stitch, express, stitch express
    44Tested up to: 6.7
    5 Stable tag: 1.3.9
     5Stable tag: 1.4.0
    66License: GPLv3
    77License URI: https://www.gnu.org/licenses/gpl-3.0.html
     
    8383
    8484== Changelog ==
     85= 1.4.0 =
     86* Updates to plugin admin page
     87
    8588= 1.3.9 =
    8689* Stitch BNPL Widget fixes
     
    181184
    182185== Upgrade Notice ==
     186= 1.4.0 =
     187* Updates to plugin admin page
     188
    183189= 1.3.9 =
    184190* Stitch BNPL Widget fixes
  • stitch-express/trunk/stitch-express.php

    r3472754 r3473803  
    99 * Description:          Use Stitch Express to easily and securely accept Card payment on your WooCommerce store.
    1010 * Plugin URI:           https://wordpress.org/plugins/stitchexpress/
    11  * Version:              1.3.9
     11 * Version:              1.4.0
    1212 * Requires at least:    6.5
    1313 * Requires PHP:         8.0
     
    106106}
    107107
     108function stitch_express_complete_order_payment(WC_Order $order, string $payment_id, string $reference, string $source, Stitch_Express_Client $client, bool $override = false): bool {
     109    $logger = wc_get_logger();
     110    $can_complete = in_array($order->get_status(), ['awaiting-payment', 'pending', 'cancelled', 'failed'], true);
     111
     112    if (!$can_complete && !$override) {
     113        $logger->info(
     114            "{$source}: Order {$order->get_id()} status is '{$order->get_status()}', skipping payment completion.",
     115            ['source' => 'stitch-express']
     116        );
     117
     118        return false;
     119    }
     120
     121    if (in_array($order->get_status(), ['cancelled', 'failed'], true)) {
     122        $order->add_order_note(
     123            sprintf(
     124                'Stitch Express: Payment confirmed (ID: %s) while order was "%s". Order status will be updated.',
     125                $payment_id,
     126                $order->get_status()
     127            )
     128        );
     129    }
     130
     131    $previous_status = $order->get_status();
     132
     133    $order->payment_complete($payment_id);
     134    $order->save();
     135
     136    $logger->info(
     137        "{$source}: Payment completed for order {$order->get_id()}. Order status updated from '{$previous_status}' to '{$order->get_status()}'. Stitch Payment ID: {$payment_id}",
     138        ['source' => 'stitch-express']
     139    );
     140
     141    try {
     142        $client->confirm_delivery($payment_id, $reference);
     143    } catch (Exception $e) {
     144        $logger->error(
     145            "{$source}: Failed to send delivery confirmation for payment {$payment_id}: {$e->getMessage()}",
     146            ['source' => 'stitch-express']
     147        );
     148    }
     149
     150    return true;
     151}
     152
    108153/**
    109154 * GET callback handler — used for user browser redirects.
     
    153198    }
    154199
    155     $can_complete_payment = in_array($order->get_status(), ['awaiting-payment', 'pending', 'cancelled', 'failed'], true);
    156 
    157     if ($can_complete_payment || $override) {
    158         if (in_array($order->get_status(), ['cancelled', 'failed'], true)) {
    159             $order->add_order_note(
    160                 sprintf(
    161                     'Stitch Express: Payment confirmed (ID: %s) while order was "%s". Overriding status and completing payment.',
    162                     $payment_id,
    163                     $order->get_status()
    164                 )
    165             );
    166         }
    167 
    168         $logger->info(
    169             "Marking order {$order_id} with status '{$order->get_status()}' as complete. Stitch Payment ID: {$payment_id}",
    170             ['source' => 'stitch-express']
    171         );
    172 
    173         $order->payment_complete($payment_id);
    174         $order->save();
    175 
    176         return stitch_express_generate_redirect_response($order->get_checkout_order_received_url());
    177     }
    178 
    179     $logger->info("Order {$order_id} status is '{$order->get_status()}', skipping payment completion", ['source' => 'stitch-express']);
     200    stitch_express_complete_order_payment($order, $payment_id, $reference, 'Callback', $stitch_express_client, $override);
    180201
    181202    return stitch_express_generate_redirect_response($order->get_checkout_order_received_url());
     
    274295    }
    275296
    276     $can_complete_payment = in_array($order->get_status(), ['awaiting-payment', 'pending', 'cancelled', 'failed'], true);
    277 
    278     if ($can_complete_payment) {
    279         if (in_array($order->get_status(), ['cancelled', 'failed'], true)) {
    280             $order->add_order_note(
    281                 sprintf(
    282                     'Stitch Express: Payment confirmed (ID: %s) while order was "%s". Overriding status and completing payment.',
    283                     $payment_id,
    284                     $order->get_status()
    285                 )
    286             );
    287         }
    288 
    289         $logger->info(
    290             "Webhook: Marking order {$order_id} with status '{$order->get_status()}' as complete. Stitch Payment ID: {$payment_id}",
    291             ['source' => 'stitch-express']
    292         );
    293 
    294         $order->payment_complete($payment_id);
    295         $order->save();
    296     } else {
    297         $logger->info("Webhook: Order {$order_id} status is '{$order->get_status()}', skipping payment completion", ['source' => 'stitch-express']);
    298     }
     297    stitch_express_complete_order_payment($order, $payment_id, $reference, 'Webhook', $stitch_express_client);
    299298
    300299    return new WP_REST_Response([
Note: See TracChangeset for help on using the changeset viewer.