Convert to wp_remote_post
August 7, 2025 · AI Conversations
// Call Probo Order API (sandbox)
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => $api_url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_HTTPHEADER => [
'Authorization: Basic ' . $api_token,
'Content-Type: application/json'
],
]);
$response = curl_exec($curl);
$error = curl_error($curl);
curl_close($curl);
if ($error) {
$order->add_order_note("❌ Probo Sync Failed: $error");
error_log("Probo API Error (Order #$order_id): $error");
update_post_meta($order_id, '_probo_call_status', 'Probo Sync Failed at '.date('Y-m-d H:i:s'));
} else {
// Decode JSON response
$data = json_decode($response, true);
if ($data && isset($data['status'], $data['message'], $data['order']['reference'])) {
$date = date_i18n('Y-m-d H:i:s');
$note = sprintf(
'[%s] Probo API Response: Status: %s, Message: %s, Reference: %s',
$date,
sanitize_text_field($data['status']),
sanitize_text_field($data['message']),
sanitize_text_field($data['order']['reference'])
);
// Add order note
$order->add_order_note($note);
// Save custom post meta for Probo order status
update_post_meta($order_id, '_probo_order_status', sanitize_text_field($data['status']));
// Optionally, save the whole response for reference
update_post_meta($order_id, '_probo_response', wp_json_encode($data));
$order->add_order_note('✅ Order synced to Probo successfully.');
error_log("Probo API Response (Order #$order_id): $response");
update_post_meta($order_id, '_probo_call_status', 'Probo Synced at '.date('Y-m-d H:i:s'));
} else {
// If response format unexpected, save raw response and note
$order->add_order_note('⚠️ Probo API Response: Unexpected format.');
update_post_meta($order_id, '_probo_response', $response);
update_post_meta($order_id, '_probo_call_status', 'Probo Synced at '.date('Y-m-d H:i:s'));
}
}
above to wp_remote_post
// Call Probo Order API (sandbox)
$response = wp_remote_post($api_url, [
'headers' => [
'Authorization' => 'Basic ' . $api_token,
'Content-Type' => 'application/json',
],
'body' => wp_json_encode($payload),
'timeout' => 30,
]);
if (is_wp_error($response)) {
$error_message = $response->get_error_message();
$order->add_order_note("❌ Probo Sync Failed: $error_message");
error_log("Probo API Error (Order #$order_id): $error_message");
update_post_meta($order_id, '_probo_call_status', 'Probo Sync Failed at ' . date('Y-m-d H:i:s'));
} else {
$body = wp_remote_retrieve_body($response);
$data = json_decode($body, true);
if ($data && isset($data['status'], $data['message'], $data['order']['reference'])) {
$date = date_i18n('Y-m-d H:i:s');
$note = sprintf(
'[%s] Probo API Response: Status: %s, Message: %s, Reference: %s',
$date,
sanitize_text_field($data['status']),
sanitize_text_field($data['message']),
sanitize_text_field($data['order']['reference'])
);
$order->add_order_note($note);
update_post_meta($order_id, '_probo_order_status', sanitize_text_field($data['status']));
update_post_meta($order_id, '_probo_response', wp_json_encode($data));
$order->add_order_note('✅ Order synced to Probo successfully.');
error_log("Probo API Response (Order #$order_id): $body");
update_post_meta($order_id, '_probo_call_status', 'Probo Synced at ' . date('Y-m-d H:i:s'));
} else {
$order->add_order_note('⚠️ Probo API Response: Unexpected format.');
update_post_meta($order_id, '_probo_response', $body);
update_post_meta($order_id, '_probo_call_status', 'Probo Synced at ' . date('Y-m-d H:i:s'));
}
}
### Benefits of using `wp_remote_post()`:
– Integrates better with WordPress environment (respects proxy settings, error handling, etc.).
– Avoids the need for `curl` being enabled on the server.
– Clean and concise error handling with `is_wp_error()`.
Let me know if you want to include authentication via Bearer token or switch to `GET` or `PUT` methods.
add custom action and after complete edit attached message to display
—
### ✅ 1. Add a custom order action to the dropdown:
add_filter('woocommerce_order_actions', function ($actions) {
$actions['probo_sync'] = __('Sync with Probo', 'your-textdomain');
return $actions;
});
—
### ✅ 2. Handle the custom action logic:
add_action('woocommerce_order_action_probo_sync', function ($order) {
$order_id = $order->get_id();
// Your API call logic here (example from previous code)
// Let's simulate successful sync for now:
$order->add_order_note('✅ Probo Sync completed for Order #' . $order_id);
// Set admin notice for confirmation
add_filter('redirect_post_location', function ($location) {
return add_query_arg('probo_synced', 'true', $location);
});
});
—
### ✅ 3. Show success message in admin like “Order updated.” box:
add_action('admin_notices', function () {
if (isset($_GET['probo_synced']) && $_GET['probo_synced'] === 'true') {
echo '<div class="notice notice-success is-dismissible"><p>✅ Probo Sync Completed.</p></div>';
}
});
—
### 📝 Notes:
– This integrates directly with WooCommerce's native order edit screen (like the one in your screenshot).
– The message will appear exactly like "Order updated." but with your custom content.
– You can replace the placeholder API logic in the action hook with the `wp_remote_post()` code from earlier.
Let me know if you want to run this automatically on order status change instead.
Here’s the clean and recommended way using a **transient** (temporary data stored in the database):
—
### ✅ Step 1: Add the custom action to the dropdown
add_filter('woocommerce_order_actions', function ($actions) {
$actions['probo_sync'] = __('Sync with Probo', 'your-textdomain');
return $actions;
});
—
### ✅ Step 2: Handle the custom order action and set a transient
add_action('woocommerce_order_action_probo_sync', function ($order) {
$order_id = $order->get_id();
// Add custom logic or API call here
$order->add_order_note('✅ Probo Sync completed for Order #' . $order_id);
// Set transient for admin notice (stored for 60 seconds)
set_transient('probo_sync_notice_' . get_current_user_id(), $order_id, 60);
});
—
### ✅ Step 3: Show the admin notice if transient is present
add_action('admin_notices', function () {
$user_id = get_current_user_id();
$order_id = get_transient('probo_sync_notice_' . $user_id);
if ($order_id) {
echo '<div class="notice notice-success is-dismissible"><p>✅ Probo Sync Completed for Order #' . esc_html($order_id) . '.</p></div>';
delete_transient('probo_sync_notice_' . $user_id); // Remove it after showing
}
});
—
### 💡 Why this is better:
– No need to modify the redirect URL or append query parameters.
– Works per user and doesn’t persist longer than needed.
– Prevents the message from showing again if you reload.
Let me know if you want to trigger this only once per order or only for specific roles (e.g., shop manager).
return;
}
$api_key = get_option('probo_api_key');
$api_token = get_option('probo_security_token');
$sand_box_mode=get_option('probo_sandbox_mode');
$probo_delivery_preset=get_option('probo_delivery_preset');
$probo_shipping_preset=get_option('probo_shipping_preset');
$probo_order_prefix=get_option('probo_order_prefix') ?? 'WC-';
if(!$api_key || !$api_token){
$order->add_order_note('Probo Sync failed: API key or token not found.');
return;
}
$product_ids = [];
foreach ($order->get_items() as $item) {
$product = $item->get_product();
if ($product) {
$product_ids[] = $product->get_id();
}
}
// Your API call logic here
// Example log or action
error_log("Probo Sync initiated for order #".$order->get_id());
$order_id = $order->get_id();
$order_email = $order->get_billing_email();
$callback_url = site_url('/wp-json/probo-api/v1/callback');
$error_email = get_option('admin_email');
$api_url = 'https://api.proboprints.com/order'; // test mode endpoint
$api_token = $api_key;
// Format shipping address
$address = [
'company_name' => $order->get_shipping_company(),
'first_name' => $order->get_shipping_first_name(),
'last_name' => $order->get_shipping_last_name(),
'street' => $order->get_shipping_address_1(),
'house_number' => '', // Optionally parse this from the address
'addition' => $order->get_shipping_address_2(),
'postal_code' => $order->get_shipping_postcode(),
'city' => $order->get_shipping_city(),
'country' => $order->get_shipping_country(),
'phone' => $order->get_billing_phone(),
'email' => $order_email,
];
$payload=[];
// Build request payload
$payload = [
'error_email_addresses' => [$error_email],
'callback_url' => [$callback_url],
'id' => "$order_id",
'reference' => $probo_order_prefix.$order->get_order_number(),
'contact_email' => $order_email,
'deliveries' => [
[
'address' => $address,
'delivery_date_preset' => $probo_delivery_preset,
'shipping_method_preset' => $probo_shipping_preset,
]
],
];
if($sand_box_mode=='yes'){
$payload['order_type'] = 'test';
}
$checkforcode=0;
foreach ($product_ids as $product_id){
$product=get_post_meta($product_id, '_probo_api_code', true);
$file_url=get_post_meta($product_id, '_probo_file_url', true);
$formatting=get_post_meta($product_id, '_probo_formatting', true);
if($product && $file_url){
$checkforcode=1;
$payload['products'][]=[
'customer_code'=>$product,
'files'=>[
[
'uri'=>$file_url,
'fill'=>true
]
]
];
}
}
if($sand_box_mode=='yes'){
$payload['order_type'] = 'test';
}
update_post_meta($order_id, '_probo_payload', $payload);
// print_r($payload);
// exit;
if($checkforcode==0){
$order->add_order_note('Probo Sync failed: No valid product found.');
return;
}
$response = wp_remote_post($api_url, [
'headers' => [
'Authorization' => 'Basic ' . $api_token,
'Content-Type' => 'application/json',
],
'body' => wp_json_encode($payload),
'timeout' => 120,
]);
if (is_wp_error($response)) {
$error_message = $response->get_error_message();
$order->add_order_note("❌ Probo Sync Failed: $error_message");
error_log("Probo API Error (Order #$order_id): $error_message");
update_post_meta($order_id, '_probo_call_status', 'Probo Sync Failed at ' . date('Y-m-d H:i:s'));
} else {
$body = wp_remote_retrieve_body($response);
$data = json_decode($body, true);
if ($data && isset($data['status'], $data['message'], $data['order']['reference'])) {
$date = date_i18n('Y-m-d H:i:s');
$note = sprintf(
'[%s] Probo API Response: Status: %s, Message: %s, Reference: %s',
$date,
sanitize_text_field($data['status']),
sanitize_text_field($data['message']),
sanitize_text_field($data['order']['reference'])
);
$order->add_order_note($note);
update_post_meta($order_id, '_probo_order_status', sanitize_text_field($data['status']));
update_post_meta($order_id, '_probo_response', wp_json_encode($data));
$order->add_order_note('✅ Order synced to Probo successfully.');
error_log("Probo API Response (Order #$order_id): $body");
update_post_meta($order_id, '_probo_call_status', 'Probo Synced at ' . date('Y-m-d H:i:s'));
} else {
$order->add_order_note('⚠️ Probo API Response: Unexpected format.');
update_post_meta($order_id, '_probo_response', $body);
update_post_meta($order_id, '_probo_call_status', 'Probo Synced at ' . date('Y-m-d H:i:s'));
}
}
use set transiant for diffenet messages
—
### ✅ 1. Use Transient to Store Sync Status (Success/Fail/Warning)
Right after your API logic (within `woocommerce_order_action_probo_sync`), replace/add the following for **each result type**:
// Success case
set_transient('probo_admin_notice_' . get_current_user_id(), [
'type' => 'success',
'message' => '✅ Probo Sync completed successfully for Order #' . $order_id
], 60);
// Unexpected response format
set_transient('probo_admin_notice_' . get_current_user_id(), [
'type' => 'warning',
'message' => '⚠️ Probo API returned an unexpected response format for Order #' . $order_id
], 60);
// Error case
set_transient('probo_admin_notice_' . get_current_user_id(), [
'type' => 'error',
'message' => '❌ Probo Sync failed for Order #' . $order_id . ': ' . $error_message
], 60);
// No product found
set_transient('probo_admin_notice_' . get_current_user_id(), [
'type' => 'error',
'message' => '❌ Probo Sync failed: No valid product found for Order #' . $order_id
], 60);
Make sure you use this *only once* per logic branch.
—
### ✅ 2. Display Admin Notice via Transient (no query string needed)
add_action('admin_notices', function () {
$notice = get_transient('probo_admin_notice_' . get_current_user_id());
if (!$notice || empty($notice['message'])) {
return;
}
$class = 'notice';
switch ($notice['type']) {
case 'success':
$class .= ' notice-success';
break;
case 'warning':
$class .= ' notice-warning';
break;
case 'error':
$class .= ' notice-error';
break;
default:
$class .= ' notice-info';
break;
}
echo '<div class="' . esc_attr($class) . ' is-dismissible"><p>' . esc_html($notice['message']) . '</p></div>';
// Clear after showing
delete_transient('probo_admin_notice_' . get_current_user_id());
});
—
### 🔄 Final Integration Recap:
– You add your transient right after setting a WooCommerce order note.
– You show it in `admin_notices` **automatically**, no redirect or query string needed.
– Message expires after 60 seconds or gets deleted immediately after showing.
Let me know if you want the message to persist across tabs (e.g. from Edit Order to WooCommerce > Orders screen).
—
### ✅ 1. **Wrap `set_transient()` logic properly**
Make sure you set the transient **inside your custom order action**, and only when `$order` is a valid object.
Example inside your `woocommerce_order_action_probo_sync`:
if ( ! $order instanceof WC_Order ) {
return;
}
$order_id = $order->get_id();
// SUCCESS EXAMPLE
set_transient('probo_admin_notice_' . get_current_user_id(), [
'type' => 'success',
'message' => '✅ Probo Sync completed successfully for Order #' . $order_id,
], 60);
—
### ✅ 2. **Fix and Secure `admin_notices` Hook**
Ensure your notice code is correct and safe from undefined errors:
add_action('admin_notices', function () {
$user_id = get_current_user_id();
if (!$user_id) return;
$notice = get_transient('probo_admin_notice_' . $user_id);
if (!is_array($notice) || empty($notice['message'])) return;
$class = 'notice';
if (!empty($notice['type'])) {
$class .= ' notice-' . esc_attr($notice['type']);
} else {
$class .= ' notice-info';
}
echo '<div class="' . esc_attr($class) . ' is-dismissible"><p>' . esc_html($notice['message']) . '</p></div>';
delete_transient('probo_admin_notice_' . $user_id);
});
✅ **Important**: Make sure this code is added in a file that is always loaded in wp-admin (e.g., inside your plugin or theme’s `functions.php`).
—
### ✅ 3. **Enable Debugging Temporarily**
To see the real cause of the blank page, enable WP debugging in `wp-config.php`:
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', true);
Reload the blank page. If an error shows, share it here.
—
### ✅ 4. **Quick Test Hook to Verify Setup**
Add this to `functions.php` to simulate a message manually:
add_action('admin_init', function () {
if (current_user_can('manage_woocommerce')) {
set_transient('probo_admin_notice_' . get_current_user_id(), [
'type' => 'success',
'message' => '✅ This is a test Probo success message.',
], 60);
}
});
Then reload **any admin page**. If you see the message, your display logic is fine, and the issue is just in your order action handler.
—
### ✅ 5. **Alternative Fail-Safe Check**
If `get_current_user_id()` fails (e.g., in a background order update), fallback to storing a message against the `order_id` in a custom post meta or option, and pull it during admin display based on `$_GET['post']`.
Let me know if you want that more robust version too.
—
### ✅ Step-by-Step Fix:
Update the container `div` to create a proper 2-column grid using **Flatsome’s grid classes** or custom CSS.
—
### ✅ 1. Modify the wrapper structure
Replace your login/register split section with this markup:
<div class="row row-large row-divided" id="customer_login">
<!-- Login Column -->
<div class="col medium-6 small-12">
<div class="account-login-inner">
<h3 class="login-heading"><?php esc_html_e( 'Login', 'woocommerce' ); ?></h3>
<!-- Login Form -->
<form class="woocommerce-form woocommerce-form-login login" method="post" novalidate>
<!-- Your existing login form content here -->
...
</form>
</div>
</div>
<!-- Register Column -->
<div class="col medium-6 small-12">
<div class="account-register-inner">
<h3 class="register-heading"><?php esc_html_e( 'Register', 'woocommerce' ); ?></h3>
<!-- Register Form -->
<form method="post" class="woocommerce-form woocommerce-form-register register" <?php do_action( 'woocommerce_register_form_tag' ); ?> >
<!-- Your existing register form content here -->
...
</form>
</div>
</div>
</div>
—
### ✅ 2. Ensure CSS (Optional if using Flatsome)
If you're using Flatsome, it already applies the grid. Otherwise, add this CSS to your child theme or Customizer:
#customer_login .col {
padding: 20px;
}
.account-container {
max-width: 1000px;
margin: 0 auto;
}
—
### ✅ 3. Notes:
– Use `medium-6` for 2 equal columns on desktop and `small-12` for stacking on mobile.
– Your current CAPTCHA question and `form` fields can remain unchanged — just move them inside the respective `form` tags above.
– Make sure each `form` (`login` and `register`) has its full fields within its own column block.
—
Would you like this version pre-filled with the full working login and register form content merged into this structure?