<?php
/**
* Plugin Name: Shopify Checkout for WooCommerce
* Plugin URI: https://example.com/shopify-checkout-for-woo
* Description: Replaces the default WooCommerce checkout with a modern, Shopify-style single-page checkout experience.
* Version: 1.0.0
* Requires at least: 6.0
* Requires PHP: 7.4
* Author: Your Name
* Author URI: https://example.com
* License: GPL v2 or later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: shopify-checkout-woo
* Domain Path: /languages
* WC requires at least: 7.0
* WC tested up to: 9.0
*/
defined( 'ABSPATH' ) || exit;
// βββββββββββββββββββββββββββββββββββββββββββββ
// Constants
// βββββββββββββββββββββββββββββββββββββββββββββ
define( 'SCW_VERSION', '1.0.0' );
define( 'SCW_PLUGIN_FILE', __FILE__ );
define( 'SCW_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
define( 'SCW_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
// βββββββββββββββββββββββββββββββββββββββββββββ
// WooCommerce HPOS (High-Performance Order Storage) compatibility
// βββββββββββββββββββββββββββββββββββββββββββββ
add_action( 'before_woocommerce_init', function () {
if ( class_exists( \Automattic\WooCommerce\Utilities\FeaturesUtil::class ) ) {
\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility(
'custom_order_tables',
SCW_PLUGIN_FILE,
true
);
\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility(
'cart_checkout_blocks',
SCW_PLUGIN_FILE,
false // We override the classic checkout template; blocks not supported
);
}
} );
// βββββββββββββββββββββββββββββββββββββββββββββ
// Activation hook β verify WooCommerce is active
// βββββββββββββββββββββββββββββββββββββββββββββ
register_activation_hook( SCW_PLUGIN_FILE, 'scw_activate' );
function scw_activate() {
if ( ! class_exists( 'WooCommerce' ) ) {
deactivate_plugins( plugin_basename( SCW_PLUGIN_FILE ) );
wp_die(
esc_html__(
'Shopify Checkout for WooCommerce requires WooCommerce to be installed and active.',
'shopify-checkout-woo'
),
esc_html__( 'Plugin Activation Error', 'shopify-checkout-woo' ),
array( 'back_link' => true )
);
}
// Flush rewrite rules on activation
flush_rewrite_rules();
}
// βββββββββββββββββββββββββββββββββββββββββββββ
// Deactivation hook
// βββββββββββββββββββββββββββββββββββββββββββββ
register_deactivation_hook( SCW_PLUGIN_FILE, 'scw_deactivate' );
function scw_deactivate() {
flush_rewrite_rules();
}
// βββββββββββββββββββββββββββββββββββββββββββββ
// Guard: only run plugin logic if WooCommerce is active
// βββββββββββββββββββββββββββββββββββββββββββββ
add_action( 'plugins_loaded', 'scw_init', 20 );
function scw_init() {
if ( ! class_exists( 'WooCommerce' ) ) {
add_action( 'admin_notices', function () {
echo '<div class="notice notice-error"><p>'
. esc_html__(
'Shopify Checkout for WooCommerce requires WooCommerce. Please install and activate WooCommerce.',
'shopify-checkout-woo'
)
. '</p></div>';
} );
return;
}
// Load text domain
load_plugin_textdomain(
'shopify-checkout-woo',
false,
dirname( plugin_basename( SCW_PLUGIN_FILE ) ) . '/languages'
);
// Hook everything in
scw_register_hooks();
}
// βββββββββββββββββββββββββββββββββββββββββββββ
// Register all plugin hooks
// βββββββββββββββββββββββββββββββββββββββββββββ
function scw_register_hooks() {
// Template override
add_filter( 'woocommerce_locate_template', 'scw_override_checkout_template', 10, 3 );
// Scripts & styles
add_action( 'wp_enqueue_scripts', 'scw_enqueue_assets', 20 );
add_action( 'wp_enqueue_scripts', 'scw_dequeue_the7_styles', 100 );
// Body class
add_filter( 'body_class', 'scw_body_classes' );
// Checkout fields
add_filter( 'woocommerce_checkout_fields', 'scw_modify_checkout_fields' );
// AJAX β coupon (logged-in)
add_action( 'wp_ajax_scw_apply_coupon', 'scw_ajax_apply_coupon' );
add_action( 'wp_ajax_scw_remove_coupon', 'scw_ajax_remove_coupon' );
// AJAX β coupon (guest / not logged-in)
add_action( 'wp_ajax_nopriv_scw_apply_coupon', 'scw_ajax_apply_coupon' );
add_action( 'wp_ajax_nopriv_scw_remove_coupon', 'scw_ajax_remove_coupon' );
}
// βββββββββββββββββββββββββββββββββββββββββββββ
// 1. Template override: redirect checkout.php to plugin template
// βββββββββββββββββββββββββββββββββββββββββββββ
function scw_override_checkout_template( $template, $template_name, $template_path ) {
// Only override the checkout template (not order-received / thankyou)
if ( 'checkout/form-checkout.php' !== $template_name ) {
return $template;
}
$plugin_template = SCW_PLUGIN_DIR . 'templates/checkout.php';
if ( file_exists( $plugin_template ) ) {
return $plugin_template;
}
return $template;
}
// βββββββββββββββββββββββββββββββββββββββββββββ
// 2. Enqueue CSS & JS on checkout (not order-received)
// βββββββββββββββββββββββββββββββββββββββββββββ
function scw_enqueue_assets() {
if ( ! function_exists( 'is_checkout' ) || ! is_checkout() ) {
return;
}
// Do NOT enqueue on the order-received (thank-you) page
if ( is_wc_endpoint_url( 'order-received' ) ) {
return;
}
// ββ CSS ββββββββββββββββββββββββββββββββββ
wp_enqueue_style(
'scw-checkout',
SCW_PLUGIN_URL . 'assets/css/checkout.css',
array( 'woocommerce-layout', 'woocommerce-general' ),
SCW_VERSION
);
// ββ JS βββββββββββββββββββββββββββββββββββ
wp_enqueue_script(
'scw-checkout',
SCW_PLUGIN_URL . 'assets/js/checkout.js',
array( 'jquery', 'wc-checkout' ),
SCW_VERSION,
true // load in footer
);
// ββ Localize βββββββββββββββββββββββββββββ
wp_localize_script(
'scw-checkout',
'scwData',
array(
'ajaxUrl' => esc_url( admin_url( 'admin-ajax.php' ) ),
'nonce' => wp_create_nonce( 'scw_nonce' ),
'i18n' => array(
'applying' => esc_html__( 'Applyingβ¦', 'shopify-checkout-woo' ),
'removing' => esc_html__( 'Removingβ¦', 'shopify-checkout-woo' ),
'couponApplied' => esc_html__( 'Coupon applied!', 'shopify-checkout-woo' ),
'couponRemoved' => esc_html__( 'Coupon removed.', 'shopify-checkout-woo' ),
'errorGeneric' => esc_html__( 'Something went wrong. Please try again.', 'shopify-checkout-woo' ),
'enterCoupon' => esc_html__( 'Enter coupon code', 'shopify-checkout-woo' ),
'applyCoupon' => esc_html__( 'Apply', 'shopify-checkout-woo' ),
'removeCoupon' => esc_html__( 'Remove', 'shopify-checkout-woo' ),
'showOrderSummary' => esc_html__( 'Show order summary', 'shopify-checkout-woo' ),
'hideOrderSummary' => esc_html__( 'Hide order summary', 'shopify-checkout-woo' ),
),
)
);
}
// βββββββββββββββββββββββββββββββββββββββββββββ
// 3. Dequeue The7 theme conflicting styles (priority 100)
// βββββββββββββββββββββββββββββββββββββββββββββ
function scw_dequeue_the7_styles() {
if ( ! function_exists( 'is_checkout' ) || ! is_checkout() ) {
return;
}
if ( is_wc_endpoint_url( 'order-received' ) ) {
return;
}
$conflicting_handles = array(
'the7-woocommerce',
'the7-woocommerce-checkout',
'dt-woocommerce',
'presscore-woocommerce',
);
foreach ( $conflicting_handles as $handle ) {
wp_dequeue_style( $handle );
wp_deregister_style( $handle );
}
}
// βββββββββββββββββββββββββββββββββββββββββββββ
// 4. Body class filter
// βββββββββββββββββββββββββββββββββββββββββββββ
function scw_body_classes( $classes ) {
if ( function_exists( 'is_checkout' ) && is_checkout() && ! is_wc_endpoint_url( 'order-received' ) ) {
$classes[] = 'scw-checkout-page';
$classes[] = 'scw-no-sidebar';
}
return $classes;
}
// βββββββββββββββββββββββββββββββββββββββββββββ
// 5. Checkout fields: move email to priority 5, phone to 100
// βββββββββββββββββββββββββββββββββββββββββββββ
function scw_modify_checkout_fields( $fields ) {
// Move billing email to priority 5 (top of billing section)
if ( isset( $fields['billing']['billing_email'] ) ) {
$fields['billing']['billing_email']['priority'] = 5;
}
// Move billing phone to priority 100 (bottom of billing section)
if ( isset( $fields['billing']['billing_phone'] ) ) {
$fields['billing']['billing_phone']['priority'] = 100;
}
return $fields;
}
// βββββββββββββββββββββββββββββββββββββββββββββ
// 6. AJAX: Apply coupon
// βββββββββββββββββββββββββββββββββββββββββββββ
function scw_ajax_apply_coupon() {
// Verify nonce
if ( ! check_ajax_referer( 'scw_nonce', 'nonce', false ) ) {
wp_send_json_error(
array( 'message' => esc_html__( 'Security check failed.', 'shopify-checkout-woo' ) ),
403
);
}
$coupon_code = isset( $_POST['coupon_code'] ) ? sanitize_text_field( wp_unslash( $_POST['coupon_code'] ) ) : '';
if ( empty( $coupon_code ) ) {
wp_send_json_error(
array( 'message' => esc_html__( 'Please enter a coupon code.', 'shopify-checkout-woo' ) )
);
}
// WooCommerce cart apply coupon
if ( ! WC()->cart ) {
wp_send_json_error(
array( 'message' => esc_html__( 'Cart not available.', 'shopify-checkout-woo' ) )
);
}
// Check if coupon already applied
if ( WC()->cart->has_discount( $coupon_code ) ) {
wp_send_json_error(
array( 'message' => esc_html__( 'Coupon code already applied!', 'shopify-checkout-woo' ) )
);
}
$result = WC()->cart->apply_coupon( $coupon_code );
if ( $result ) {
// Recalculate totals
WC()->cart->calculate_totals();
ob_start();
scw_render_order_summary();
$order_summary_html = ob_get_clean();
wp_send_json_success(
array(
'message' => esc_html__( 'Coupon applied successfully!', 'shopify-checkout-woo' ),
'orderSummary' => $order_summary_html,
)
);
} else {
// WooCommerce adds notices; grab the last one
$notices = wc_get_notices( 'error' );
$message = ! empty( $notices )
? wp_strip_all_tags( $notices[0]['notice'] )
: esc_html__( 'Invalid coupon code.', 'shopify-checkout-woo' );
wc_clear_notices();
wp_send_json_error( array( 'message' => $message ) );
}
}
// βββββββββββββββββββββββββββββββββββββββββββββ
// 7. AJAX: Remove coupon
// βββββββββββββββββββββββββββββββββββββββββββββ
function scw_ajax_remove_coupon() {
// Verify nonce
if ( ! check_ajax_referer( 'scw_nonce', 'nonce', false ) ) {
wp_send_json_error(
array( 'message' => esc_html__( 'Security check failed.', 'shopify-checkout-woo' ) ),
403
);
}
$coupon_code = isset( $_POST['coupon_code'] ) ? sanitize_text_field( wp_unslash( $_POST['coupon_code'] ) ) : '';
if ( empty( $coupon_code ) ) {
wp_send_json_error(
array( 'message' => esc_html__( 'No coupon code provided.', 'shopify-checkout-woo' ) )
);
}
if ( ! WC()->cart ) {
wp_send_json_error(
array( 'message' => esc_html__( 'Cart not available.', 'shopify-checkout-woo' ) )
);
}
$result = WC()->cart->remove_coupon( $coupon_code );
if ( $result ) {
WC()->cart->calculate_totals();
ob_start();
scw_render_order_summary();
$order_summary_html = ob_get_clean();
wp_send_json_success(
array(
'message' => esc_html__( 'Coupon removed.', 'shopify-checkout-woo' ),
'orderSummary' => $order_summary_html,
)
);
} else {
wp_send_json_error(
array( 'message' => esc_html__( 'Could not remove coupon.', 'shopify-checkout-woo' ) )
);
}
}
// βββββββββββββββββββββββββββββββββββββββββββββ
// 8. Helper: Render order summary HTML
// Outputs: cart items (image, name, variant, qty, price),
// coupon rows with remove button,
// subtotal / tax / total rows.
// βββββββββββββββββββββββββββββββββββββββββββββ
function scw_render_order_summary() {
if ( ! WC()->cart ) {
return;
}
$cart = WC()->cart;
?>
<div class="scw-order-summary">
<!-- ββ Cart Items βββββββββββββββββββββββββββββββ -->
<ul class="scw-order-summary__items">
<?php foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) :
/** @var WC_Product $product */
$product = $cart_item['data'];
$quantity = (int) $cart_item['quantity'];
$item_name = $product->get_name();
$item_id = $product->get_id();
// Thumbnail
$thumbnail_id = $product->get_image_id();
$thumbnail_url = $thumbnail_id
? wp_get_attachment_image_url( $thumbnail_id, 'thumbnail' )
: wc_placeholder_img_src( 'thumbnail' );
// Line total
$line_total = wc_price( $cart_item['line_total'] + $cart_item['line_tax'] );
// Variation attributes
$variation_data = array();
if ( ! empty( $cart_item['variation'] ) ) {
foreach ( $cart_item['variation'] as $attr_key => $attr_value ) {
if ( '' === $attr_value ) {
continue;
}
$taxonomy = str_replace( 'attribute_', '', $attr_key );
$label = wc_attribute_label( $taxonomy );
$term = get_term_by( 'slug', $attr_value, $taxonomy );
$value = $term ? $term->name : $attr_value;
$variation_data[] = esc_html( $label ) . ': ' . esc_html( $value );
}
}
?>
<li class="scw-order-summary__item">
<div class="scw-item__image-wrap">
<img
src="<?php echo esc_url( $thumbnail_url ); ?>"
alt="<?php echo esc_attr( $item_name ); ?>"
class="scw-item__image"
width="64"
height="64"
loading="lazy"
/>
<span class="scw-item__qty-badge" aria-label="<?php echo esc_attr( sprintf(
/* translators: %d: item quantity */
__( 'Quantity: %d', 'shopify-checkout-woo' ),
$quantity
) ); ?>">
<?php echo esc_html( $quantity ); ?>
</span>
</div>
<div class="scw-item__details">
<span class="scw-item__name"><?php echo esc_html( $item_name ); ?></span>
<?php if ( ! empty( $variation_data ) ) : ?>
<span class="scw-item__variant">
<?php echo esc_html( implode( ' / ', $variation_data ) ); ?>
</span>
<?php endif; ?>
</div>
<div class="scw-item__price">
<?php echo wp_kses_post( $line_total ); ?>
</div>
</li>
<?php endforeach; ?>
</ul>
<!-- ββ Coupon Rows βββββββββββββββββββββββββββββββ -->
<?php $applied_coupons = $cart->get_applied_coupons(); ?>
<?php if ( ! empty( $applied_coupons ) ) : ?>
<ul class="scw-order-summary__coupons">
<?php foreach ( $applied_coupons as $coupon_code ) :
$coupon = new WC_Coupon( $coupon_code );
$discount_amt = wc_price( $cart->get_coupon_discount_amount( $coupon_code, $cart->display_cart_ex_tax ) );
?>
<li class="scw-order-summary__coupon-row">
<span class="scw-coupon__label">
<?php
echo esc_html__(
'Discount',
'shopify-checkout-woo'
);
echo ' (<code>' . esc_html( strtoupper( $coupon_code ) ) . '</code>)';
?>
</span>
<span class="scw-coupon__amount">
−<?php echo wp_kses_post( $discount_amt ); ?>
</span>
<button
type="button"
class="scw-coupon__remove"
data-coupon="<?php echo esc_attr( $coupon_code ); ?>"
aria-label="<?php echo esc_attr( sprintf(
/* translators: %s: coupon code */
__( 'Remove coupon %s', 'shopify-checkout-woo' ),
strtoupper( $coupon_code )
) ); ?>"
>
<?php esc_html_e( 'Remove', 'shopify-checkout-woo' ); ?>
</button>
</li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
<!-- ββ Totals βββββββββββββββββββββββββββββββββββ -->
<table class="scw-order-summary__totals" role="presentation">
<tbody>
<!-- Subtotal -->
<tr class="scw-totals__row scw-totals__subtotal">
<th scope="row"><?php esc_html_e( 'Subtotal', 'shopify-checkout-woo' ); ?></th>
<td><?php echo wp_kses_post( wc_price( $cart->get_subtotal() ) ); ?></td>
</tr>
<!-- Shipping (if applicable) -->
<?php if ( $cart->needs_shipping() && $cart->show_shipping() ) : ?>
<tr class="scw-totals__row scw-totals__shipping">
<th scope="row"><?php esc_html_e( 'Shipping', 'shopify-checkout-woo' ); ?></th>
<td>
<?php
$packages = WC()->shipping()->get_packages();
if ( ! empty( $packages ) ) {
foreach ( $packages as $package ) {
$chosen_method = isset( WC()->session )
? WC()->session->get( 'chosen_shipping_methods' )
: array();
if ( ! empty( $chosen_method[0] ) && isset( $package['rates'][ $chosen_method[0] ] ) ) {
$rate = $package['rates'][ $chosen_method[0] ];
echo wp_kses_post( wc_price( $rate->get_cost() ) );
} else {
esc_html_e( 'Calculated at next step', 'shopify-checkout-woo' );
}
}
} else {
esc_html_e( 'Free', 'shopify-checkout-woo' );
}
?>
</td>
</tr>
<?php endif; ?>
<!-- Tax -->
<?php if ( wc_tax_enabled() && ! $cart->display_prices_including_tax() ) : ?>
<tr class="scw-totals__row scw-totals__tax">
<th scope="row"><?php echo esc_html( WC()->countries->tax_or_vat() ); ?></th>
<td><?php echo wp_kses_post( wc_price( $cart->get_total_tax() ) ); ?></td>
</tr>
<?php endif; ?>
<!-- Total -->
<tr class="scw-totals__row scw-totals__total">
<th scope="row"><strong><?php esc_html_e( 'Total', 'shopify-checkout-woo' ); ?></strong></th>
<td><strong><?php echo wp_kses_post( $cart->get_total() ); ?></strong></td>
</tr>
</tbody>
</table>
</div><!-- .scw-order-summary -->
<?php
}