通过 REST API 同步 WooCommerce 网站时出现重复订单问题

问题描述 投票:0回答:1

我一直在努力解决通过 woocommerce 订单休息 API 端点在源站点和目标站点之间同步订单的重复问题:

/wp-json/wc/v3/orders

我提出了以下代码,它成功地从源检索订单数据并在目标上创建,但它反复从源获取相同的订单,并使用自动分配给它的新 ID 一次又一次地创建它。

因此,我希望订单仅同步一次,然后在源站点上的状态发生变化时进行更新



if (!empty($orders) && is_array($orders)) {
      
       foreach ($orders as $order) {
          
           if (isset($order['status']) && isset($order['customer_id'])) {
               
               $first_name = $order['billing']['first_name'];
               $last_name = $order['billing']['last_name'];
               $phone = $order['billing']['phone'];
               
              
   //line items             
if (isset($order['line_items']) && is_array($order['line_items'])) {
   
   foreach ($order['line_items'] as $item) {
       $line_item_data = array(
           
           'name' => $item['name'],
           'quantity' => $item['quantity'],
           'price' => $item['price'],
           'subtotal' => $item['subtotal'],
           'total' => $item['total'],
           'product_id' => $item['product_id'],
       );

      
       $line_items_data[] = $line_item_data;
   }
}


          
               $order_data = array(
                   'status' => $order['status'],
                   'customer_id' => $order['customer_id'],
                   'billing' => array(
                       'first_name' => $first_name,
                       'last_name' => $last_name,
                       'phone' => $phone,
                   ),
                   'line_items' => $line_items_data,
                   
               );


首先,我尝试匹配两个网站的订单 ID,这当然不是推荐做法,但值得一试,通过

$url .= '/' . $order_data['number'];

现在两个站点的订单都有相同的标识符,避免了重复订单,但却导致了

line_items
字段的积累(包括数量、价格等)

因此,在第二步中,我删除了上面的行,并尝试通过在

id
数组中包含
line_items
属性来区分订单:

  $line_item_data = array(
            'id' => $item['id'], //adding id object
            'name' => $item['name'],
            'quantity' => $item['quantity'],
            'price' => $item['price'],
            'subtotal' => $item['subtotal'],
            'total' => $item['total'],
            'product_id' => $item['product_id'],
        );

但是我最后发现这是不允许的,所以这个方法也无法解决问题。


{
   "code": "woocommerce_rest_invalid_item_id",
   "message": "Order item ID provided is not associated with order.",
   "data": {
       "status": 400
   }
}

问题似乎是由于缺乏映射机制、源 ID 及其对应的目标 ID 的跟踪而导致的,如果没有映射机制,源上的相同订单将被一遍又一遍地获取,而不是更新其状态。 我想知道是否还有其他方法可以解决这个令人沮丧的问题。 任何帮助将不胜感激。

完整代码:

// Cron Schedule to Run the Code
add_filter('cron_schedules', 'add_every_minute_interval');

function add_every_minute_interval($schedules) {
    $schedules['every_minute'] = array(
        'interval' => 60, 
        'display' => __('Every Minute')
    );
    return $schedules;
}


add_action('wp_loaded', 'schedule_order_sync');

function schedule_order_sync() {
    if (!wp_next_scheduled('sync_orders_event')) {
        wp_schedule_event(time(), 'every_minute', 'sync_orders_event');
    }
}


add_action('sync_orders_event', 'sync_orders_from_source_to_destination');

 

    // Function to create order on destination site
    function create_order_on_destination_site($order_data, $api_url, $consumer_key, $consumer_secret) {
        $url = $api_url . '/wp-json/wc/v3/orders';

        

        $response = wp_remote_post($url, array(
            'headers' => array(
                'Authorization' => 'Basic ' . base64_encode($consumer_key . ':' . $consumer_secret),
                'Content-Type' => 'application/json',
            ),
            'body' => json_encode($order_data),
        ));

        if (is_wp_error($response)) {
            return false;
        }

        $body = wp_remote_retrieve_body($response);
        $created_order = json_decode($body, true);

        return $created_order;
    }
    
    // Function to get orders from source site
    function get_orders_from_source_site($api_url, $consumer_key, $consumer_secret) {
        $url = $api_url . '/wp-json/wc/v3/orders';
        $response = wp_remote_get($url, array(
            'headers' => array(
                'Authorization' => 'Basic ' . base64_encode($consumer_key . ':' . $consumer_secret),
            ),
        ));

        if (is_wp_error($response)) {
            return array();
        }

        $body = wp_remote_retrieve_body($response);
        $orders = json_decode($body, true);

        return $orders;
    }

// Main function to sync orders from source to destination
function sync_orders_from_source_to_destination() {
    // Source site API credentials
    $sourceSiteApiUrl = 'https://source.com';
    $sourceConsumerKey = 'xxxxxxxxxxxxxxxxxxxx';
    $sourceConsumerSecret = 'xxxxxxxxxxxxxxxxxxxx';

    // Destination site API credentials
    $destinationSiteApiUrl = 'https://destination.com';
    $destinationConsumerKey = 'xxxxxxxxxxxxxxxxxxxx';
    $destinationConsumerSecret = 'xxxxxxxxxxxxxxxxxxxx';

   

    // Get orders from source site
    $orders = get_orders_from_source_site($sourceSiteApiUrl, $sourceConsumerKey, $sourceConsumerSecret);


    
    if (!empty($orders) && is_array($orders)) {
        
        foreach ($orders as $order) {
           
            if (isset($order['status']) && isset($order['customer_id'])) {
               
                $first_name = $order['billing']['first_name'];
                $last_name = $order['billing']['last_name'];
                $phone = $order['billing']['phone'];
                
               
                
if (isset($order['line_items']) && is_array($order['line_items'])) {
    
    foreach ($order['line_items'] as $item) {
        $line_item_data = array(
            
            'name' => $item['name'],
            'quantity' => $item['quantity'],
            'price' => $item['price'],
            'subtotal' => $item['subtotal'],
            'total' => $item['total'],
            'product_id' => $item['product_id'],
        );

       
        $line_items_data[] = $line_item_data;
    }
}





                // order data
                $order_data = array(
                    'status' => $order['status'],
                    'customer_id' => $order['customer_id'],
                    'billing' => array(
                        'first_name' => $first_name,
                        'last_name' => $last_name,
                        'phone' => $phone,
                    ),
                    'line_items' => $line_items_data,
                    //etc
                );


                // Create order on destination site
                $created_order = create_order_on_destination_site($order_data, $destinationSiteApiUrl, $destinationConsumerKey, $destinationConsumerSecret);

                if ($created_order) {
                    echo 'Order ' . $created_order['id'] . ' created on destination site';
                } else {
                    echo 'Failed to create order on destination site';
                }
            } else {
                echo 'Order data is missing required fields';
            }
        }
    } else {
        echo 'No orders fetched from the source site';
    }
}
 
php api synchronization woocommerce-rest-api
1个回答
0
投票

正确的做法是明确要插入的各个数据表之间的关系:哪个是主表,哪个是子表,是一对一还是一对多或多对许多。 要同步数据,您可以使用

redis
队列或
kafka
。 生成格式化数据并推送到队列,然后让消费者消费并与数据表同步。 例如,确保数据表具有订单号字段的唯一索引。 防止插入重复数据。 您可以维护一个
redis
集合来存储已消耗的订单。

© www.soinside.com 2019 - 2024. All rights reserved.