WooCommerce Payments, Shipping and Tax — Complete Configuration Guide
In this tutorial, you'll learn to configure WooCommerce payments, shipping, and tax on WordPress — setting up PayPal, Stripe, and Square, creating shipping zones with methods and classes, configuring tax rates, and troubleshooting checkout issues that block sales.
What You'll Learn
- How payment gateways work in WooCommerce and how to enable them
- How to set up PayPal Standard with sandbox testing
- How to set up Stripe with API keys and webhook configuration
- How to set up Square for WooCommerce with API credentials
- How to configure bank transfer (BACS), cash on delivery (COD), and check payments
- How to create shipping zones with regions, methods, and priorities
- How to configure flat rate, free shipping, and local pickup methods
- How to use shipping classes for advanced rate calculations
- How shipping zone priority affects checkout
- How to enable and configure tax options
- How to set up standard, reduced, and zero-rate tax classes
- How to calculate taxes based on shipping or billing address
- How to troubleshoot common checkout issues (gateway logs, SSL, conflicts)
Why It Matters
Payments, shipping, and tax are the three pillars that convert a browsing customer into a paying one. If your payment gateway is misconfigured, customers get error messages and abandon their carts. If shipping costs are wrong, customers are surprised at checkout and leave. If taxes are incorrect, you either overpay or face legal issues. WooCommerce gives you the tools to configure all three correctly, but each has specific steps that must be followed precisely. A store with working checkout processes more orders, fewer support tickets, and happier customers.
Real-World Use
A home goods store ships across the United States and Canada. They need: PayPal and credit card payments, different shipping rates for small items (flat $5) and large items (calculated $15-25), free shipping for orders over $75, local pickup for nearby customers, and tax collection for states where they have nexus. With WooCommerce, they set up two shipping zones (US and Canada), assign shipping classes (Small, Large), configure PayPal and Stripe, and add tax rates for their nexus states. The checkout flow shows correct shipping and tax based on the customer's address, and payments process without errors.
Learning Path
flowchart LR
A[Products & Inventory] --> B[Payments, Shipping & Tax]
B --> C[Order Management]
B --> D[Payment Gateways]
B --> E[Shipping Zones]
B --> F[Tax Configuration]
B --> G[Checkout Optimization]
style B fill:#38bdf8,color:#0f172a,stroke-width:2px
Payment Gateways Overview
WooCommerce includes built-in payment gateways and supports many more via extensions. Configure them at WooCommerce > Settings > Payments.
Each gateway has:
- Enable / Disable toggle: Turn the gateway on or off
- Title: What customers see at checkout (e.g., "Credit Card (Stripe)")
- Description: Explanation shown below the payment method
- Gateway-specific settings: API keys, credentials, test mode
How Payment Gateways Work
Payment gateways follow this flow:
- Customer enters payment details on your checkout page.
- The gateway sends the data to its server (via API).
- The gateway processor charges the card or initiates the transfer.
- The gateway sends a response back to WooCommerce.
- WooCommerce updates the order status: Processing (success) or Failed.
flowchart TD
A[Customer enters payment] --> B[WooCommerce sends to gateway]
B --> C{Gateway processes payment}
C -->|Success| D[Order status: Processing]
C -->|Failure| E[Order status: Failed]
D --> F[Send confirmation email]
E --> G[Show error message]
D --> H[Payment settled in gateway dashboard]
PayPal Setup
PayPal Standard is built into WooCommerce core. It redirects customers to PayPal to complete payment.
Enabling PayPal
- Go to WooCommerce > Settings > Payments.
- Find PayPal and click Manage.
- Check Enable PayPal Standard.
- Enter your PayPal email address (the email associated with your PayPal business account).
PayPal Configuration Options
- Title: Default is "PayPal". Change to "PayPal or Credit Card" to indicate PayPal's guest checkout feature.
- Description: "Pay via PayPal; you can pay with your credit card if you don't have a PayPal account."
- IPN Email: PayPal Instant Payment Notification settings. This is how PayPal communicates payment status to WooCommerce.
- Sandbox mode: Enable to test transactions without real money.
- Debug log: Enable to capture errors for troubleshooting.
// Enable PayPal debug logging programmatically
add_filter('woocommerce_paypal_settings', function($settings) {
$settings['debug'] = 'yes';
return $settings;
});
// Customize PayPal description at checkout
add_filter('woocommerce_gateway_description', function($description, $gateway_id) {
if ($gateway_id === 'paypal') {
$description .= ' You can use a credit card without a PayPal account.';
}
return $description;
}, 10, 2);
PayPal Sandbox Testing
- Go to developer.paypal.com and log in with your PayPal account.
- Navigate to Dashboard > Sandbox > Accounts.
- Create a Business account (seller) and a Personal account (buyer).
- In WooCommerce PayPal settings, enable PayPal Sandbox and set the API credentials.
- Use the sandbox buyer account to place test orders and verify the flow.
PayPal IPN Setup
PayPal IPN (Instant Payment Notification) is the mechanism that tells WooCommerce when a payment is received. If IPN is not configured, orders show as "Pending payment" even after customers pay.
- In your PayPal account, go to Profile > Website payments > Instant payment notifications.
- Set the IPN URL to:
https://yourstore.com/?wc-api=WC_Gateway_Paypal - Ensure IPN messages are enabled.
// The PayPal IPN endpoint in WooCommerce is:
// https://yourstore.com/?wc-api=WC_Gateway_Paypal
// This receives POST data from PayPal about payment status changes.
Stripe Setup
Stripe processes credit card payments on your site without redirecting the customer. Customers enter card details on your checkout page.
Installing Stripe
- Install the WooCommerce Stripe Payment Gateway plugin from the WordPress Repository.
- Activate the plugin.
- Go to WooCommerce > Settings > Payments > Stripe.
Stripe API Keys
You need two keys from your Stripe dashboard:
- Log in to dashboard.stripe.com.
- Go to Developers > API keys.
- Copy the Publishable key (starts with
pk_live_orpk_test_). - Copy the Secret key (starts with
sk_live_orsk_test_). - Paste both into the WooCommerce Stripe settings.
// Stripe keys are stored in WordPress options
// Option name: woocommerce_stripe_settings
$stripe_settings = get_option('woocommerce_stripe_settings', array());
$publishable_key = $stripe_settings['publishable_key'] ?? '';
$secret_key = $stripe_settings['secret_key'] ?? '';
// Never expose the secret key in client-side code
// The publishable key is safe to use in JavaScript
Stripe Webhook Configuration
The webhook is how Stripe notifies WooCommerce about payment events.
- In your Stripe dashboard, go to Developers > Webhooks.
- Click Add endpoint.
- Set the endpoint URL to:
https://yourstore.com/?wc_stripe_webhook=1 - Select events to listen for:
checkout.session.completed,payment_intent.succeeded,payment_intent.payment_failed. - Copy the Webhook signing secret and paste it into WooCommerce Stripe settings.
// The webhook handler in WooCommerce Stripe
// File: woocommerce-gateway-stripe/includes/class-wc-gateway-stripe-webhook.php
// It receives Stripe events and updates order statuses accordingly
// Without the webhook, orders stay in "Pending payment" status
// even after Stripe confirms successful payment
add_action('woocommerce_api_wc_stripe_webhook', function() {
// Stripe sends a JSON payload with event data
$body = file_get_contents('php://input');
$event = json_decode($body);
// Process and update order status
});
Test Mode
Stripe provides test keys. Enable Test mode in the Stripe settings to try transactions with the test card number 4242 4242 4242 4242 (any future date, any CVC).
Square for WooCommerce
Square is an alternative to Stripe, popular for in-person payments and retail stores.
- Install Square for WooCommerce from the WordPress repository.
- Connect your Square account — authorize WooCommerce to access your Square data.
- Configure:
- Application ID: From your Square Developer Dashboard
- Access Token: Generated when you connect Square
- Location ID: Your physical store location in Square
- Sandbox mode: Enable for testing
Square processes payments on your checkout page without redirect. It also supports Square Terminal for in-person payments.
Bank Transfer (BACS)
Bank Transfer (also called BACS or Direct Bank Transfer) lets customers pay directly to your bank account.
Configuration
Go to WooCommerce > Settings > Payments > Bank Transfer (BACS).
Enable the gateway.
Enter your bank account details:
- Account name: Your business name
- Account number: Your bank account number
- Bank name: Name of your bank
- Sort code / Routing number: Bank identifier
- IBAN: International account number (if applicable)
- BIC / SWIFT: International bank identifier
// BACS account details stored in options
// Option name: woocommerce_bacs_settings
// Account details are in: woocommerce_bacs_accounts
$accounts = get_option('woocommerce_bacs_accounts', array());
foreach ($accounts as $account) {
echo $account['account_name'] . ': ' . $account['account_number'];
}
How BACS Works
- Customer selects "Bank Transfer" at checkout.
- WooCommerce shows the bank details on the order confirmation page and in the email.
- Customer transfers the money manually.
- Store admin checks the bank account and manually updates the order status from "On hold" to "Processing" or "Completed".
BACS requires manual work. Only offer it if customers specifically request it or for large B2B transactions.
Cash on Delivery (COD)
Cash on Delivery lets customers pay when the order arrives.
Configuration
- Enable Cash on Delivery at WooCommerce > Settings > Payments.
- Set an Additional charge (optional fee for using COD).
- Instructions: What the customer should prepare (exact change, etc.).
- Enable for shipping methods: Restrict COD to specific shipping methods (e.g., only local pickup).
// Add a COD fee programmatically
add_action('woocommerce_cart_calculate_fees', function() {
if (WC()->session->get('chosen_payment_method') === 'cod') {
WC()->cart->add_fee('COD Processing Fee', 2.99);
}
});
When to Use COD
COD builds trust with customers who don't use cards or PayPal. However, COD has risks: customers may refuse delivery, and you lose shipping costs. Use COD only for local deliveries or established customer relationships.
Check Payments
Check payments are the simplest gateway. Customers mail a check, and you process the order when it arrives.
Configuration
- Enable Check payments at WooCommerce > Settings > Payments.
- Enter Instructions: Where to mail the check, what to include (order number, etc.).
- Set the Check title and Description.
Check payments are rare for online stores. Use them only for B2B clients who require purchase order + check workflows.
Shipping Zones
Shipping zones define where you ship and how much it costs. Configure them at WooCommerce > Settings > Shipping > Shipping zones.
Creating a Zone
- Click Add shipping zone.
- Zone name: Make it descriptive — "United States", "Europe", "Local Pickup Only".
- Zone regions: Select the countries, states, or postcodes this zone covers.
- Add shipping method: Choose one or more methods for the zone.
// Create a shipping zone programmatically
function create_us_shipping_zone() {
$zone = new WC_Shipping_Zone();
$zone->set_zone_name('Continental US');
$zone->set_zone_locations(array(
array(
'code' => 'US',
'type' => 'country',
),
));
$zone->save();
// Add flat rate shipping method
$zone->add_shipping_method('flat_rate');
// Add free shipping method
$zone->add_shipping_method('free_shipping');
}
Shipping Methods
Flat Rate
A fixed cost per order. Useful for stores with consistent shipping costs.
- Cost: Fixed amount (e.g., $5.99).
- Handling fee: Additional charge (percentage or fixed).
- Shipping class costs: Different costs for different product groups.
// Configure flat rate with shipping classes
// In the flat rate settings, you can set costs per class:
// Item: Heavy = $15, Standard = $5, Small = $3
add_filter('woocommerce_flat_rate_shipping_cost', function($cost, $package) {
if ($package['contents_cost'] > 100) {
return $cost * 0.5; // 50% discount for high-value orders
}
return $cost;
}, 10, 2);
Free Shipping
No cost to the customer. You can set conditions:
- Minimum order amount: Free shipping for orders over a set value (e.g., $75).
- Valid coupon: Customer enters a coupon code to get free shipping.
- Minimum order amount OR coupon: Either condition triggers free shipping.
// Set free shipping minimum amount programmatically
add_filter('woocommerce_shipping_free_shipping_settings', function($settings) {
$settings['min_amount'] = 75;
return $settings;
});
// Add a note in the cart showing how much more for free shipping
add_action('woocommerce_before_cart', function() {
$minimum = 75;
$current = WC()->cart->get_subtotal();
if ($current < $minimum) {
$remaining = wc_price($minimum - $current);
echo '<p>Add ' . $remaining . ' more to get free shipping!</p>';
}
});
Local Pickup
Customer collects the order from your store. No shipping cost.
- Title: "Local Pickup" (or your store name).
- Cost: Usually $0.
- Taxable: Whether pickup is taxable (usually not).
Shipping Classes
Shipping classes group similar products for custom rates. They are optional but useful for stores with diverse product types.
Creating Shipping Classes
- Go to WooCommerce > Settings > Shipping > Shipping classes.
- Add classes: "Small Items", "Large Items", "Heavy Items", "Fragile Items".
- Assign a slug and description (optional).
Assigning Classes to Products
Each product has a Shipping class dropdown in the Shipping tab. Assign the appropriate class.
Configuring Class-Specific Rates
In each shipping zone's flat rate method, you can set different costs per class:
- Small Items: $3.99
- Large Items: $12.99
- Heavy Items: $24.99
- No class: $5.99
// Calculate shipping based on shipping class
add_filter('woocommerce_package_rates', function($rates, $package) {
$has_heavy = false;
foreach ($package['contents'] as $item) {
$product = $item['data'];
if ($product->get_shipping_class() === 'heavy-items') {
$has_heavy = true;
break;
}
}
if ($has_heavy) {
// Increase flat rate for heavy items
foreach ($rates as $rate) {
if ($rate->method_id === 'flat_rate') {
$rate->cost = max($rate->cost, 24.99);
}
}
}
return $rates;
}, 10, 2);
Shipping Zone Priority
When a customer checks out, WooCommerce checks shipping zones in priority order. The first zone matching the customer's address is used.
Priority Rules
- Priority 1: Checked first. Use for very specific zones (e.g., "California" with local pickup only).
- Priority 10: Checked next. Use for broader zones (e.g., "United States" with flat rate and free shipping).
- Priority 100: Checked last. Use for "Rest of the World" as a fallback.
Example Zone Setup
| Priority | Zone Name | Regions | Methods |
|---|---|---|---|
| 1 | Local Pickup | Specific city/zip | Local pickup |
| 10 | Domestic | US | Flat rate $5, Free over $75 |
| 20 | Canada | Canada | Flat rate $12 |
| 100 | International | All other countries | Flat rate $25 |
If a customer is in your local city, they see local pickup. If they're in the US but not local, they see domestic shipping. If they're in Canada, they see Canadian rates. Everyone else gets international rates.
Tax Options
Tax configuration in WooCommerce is flexible but requires understanding how your business handles taxes.
Enabling Tax
- Go to WooCommerce > Settings > General.
- Check Enable tax rates and calculations.
- Save changes — the Tax tab now appears in the Settings menu.
Tax Settings
Go to WooCommerce > Settings > Tax.
Prices entered with tax:
- Yes, I will enter prices inclusive of tax: Product prices include tax. The tax portion is calculated from the displayed price.
- No, I will enter prices exclusive of tax: Product prices exclude tax. Tax is added at checkout.
Which to choose? If you sell to consumers (B2C), prices usually include tax. If you sell to businesses (B2B), prices usually exclude tax and businesses claim the tax back.
Display prices in the shop:
- Including tax
- Excluding tax
Display prices during cart and checkout:
- Including tax
- Excluding tax
- Showing both
Shipping tax class:
- Same as products
- Standard rate
- Reduced rate
- Zero rate
// Set tax display options programmatically
update_option('woocommerce_prices_include_tax', 'yes');
update_option('woocommerce_tax_display_shop', 'incl');
update_option('woocommerce_tax_display_cart', 'incl');
Tax Rate Setup
Tax rates define how much tax to charge based on the customer's location.
Adding a Tax Rate
Go to WooCommerce > Settings > Tax > Standard rates.
Click Insert row.
Configure:
- Country: The country where this rate applies (e.g., US).
- State: The state (e.g., CA for California, * for all states).
- ZIP/Postcode: Specific postal codes (optional).
- City: Specific city (optional).
- Rate %: The tax percentage (e.g., 8.75).
- Tax name: What customers see (e.g., "CA Sales Tax").
- Priority: Higher priority rates are applied first. Use 1 for most rates.
- Compound: Whether this tax is compounded on top of other taxes.
- Shipping: Whether tax applies to shipping costs.
- Tax class: Standard, Reduced rate, or Zero rate.
Tax Classes
- Standard rate: The default tax rate for most products.
- Reduced rate: Lower tax rate for specific products (e.g., food items in some regions).
- Zero rate: No tax (e.g., books in many jurisdictions).
Assign tax classes to products in the General tab of the Product Data section.
Tax Calculation Methods
WooCommerce can calculate taxes based on:
- Store base address: Your business location — used when you can't determine the customer's location.
- Customer shipping address: Most common for physical products — tax based on where the product is delivered.
- Customer billing address: Used for digital products — tax based on the customer's registered address.
// Set tax calculation to use shipping address
add_filter('woocommerce_base_tax_address', function($address) {
// 'base' = store location
// 'shipping' = customer shipping address
// 'billing' = customer billing address
return 'shipping';
});
Troubleshooting Checkout Issues
Checkout issues directly cost you money. Here are the most common problems and solutions.
Payment Gateway Logs
All major gateways have debug logging. Enable it:
- Go to the gateway settings.
- Check Enable debug log.
- Check the log file at WooCommerce > Status > Logs.
// Write to WooCommerce debug log
function log_checkout_error($message) {
$logger = wc_get_logger();
$logger->error($message, array('source' => 'checkout'));
}
Logs show exactly what data was sent to the gateway, what response was received, and where the error occurred.
SSL Requirement
WooCommerce requires SSL (HTTPS) for checkout pages. Without SSL, payment gateways refuse to process transactions because card data must be encrypted in transit.
- Install an SSL certificate on your server (many hosts provide free SSL via Let's Encrypt).
- Go to WooCommerce > Settings > Advanced.
- Ensure Force secure checkout is enabled.
- Verify your site loads via
https://yourstore.com/.
Conflict Testing
Payment issues are often caused by plugin or theme conflicts.
- Switch to a default theme like Storefront or Twenty Twenty-Four.
- If the issue disappears, your theme is causing it. Contact the theme developer.
- Deactivate all plugins except WooCommerce and the payment gateway.
- reactivate plugins one by one until the issue returns.
- The last reactivated plugin is the conflict source.
Address Validation
Some payment gateways validate billing addresses against the cardholder's address on file. If the address doesn't match, the Transaction is declined.
- Enable address validation in Stripe settings.
- Add address fields to the checkout form if they're missing.
- Use a plugin like Address Validation for WooCommerce to provide suggestions.
Common Error Codes
| Error | Likely Cause | Solution |
|---|---|---|
| "This transaction cannot be processed" | Invalid API key | Check publishable/secret keys |
| "Currency not supported" | Unsupported currency | Change store currency or use a multi-currency plugin |
| "Webhook delivery failed" | Webhook URL not accessible | Ensure the site is accessible at the webhook URL |
| "No shipping methods available" | No matching shipping zone | Check shipping zone regions and priorities |
Common Mistakes
Not configuring the Stripe webhook. You enter Stripe API keys and everything looks fine. Customers pay successfully, but orders remain in "Pending payment" status forever. The webhook is missing. Stripe needs a webhook endpoint to tell WooCommerce "this payment succeeded." Without it, the loop never closes. Always configure the webhook in the Stripe dashboard with the correct endpoint URL.
Misunderstanding shipping zone priority. You create a zone for "California" with local pickup and a zone for "United States" with flat rate. California is priority 10 and United States is priority 1. A California customer checks out — they get flat rate, not local pickup. The zone with priority 1 (United States) matches first because it covers the entire US including California. Always put more specific zones at lower (higher priority) numbers.
Enabling too many payment gateways. A checkout page with 6 payment options overwhelms customers. They spend time deciding and often leave. Choose 2-3 gateways: one card gateway (Stripe or Square), one digital wallet (PayPal), and optionally a local option (bank transfer for B2B). Too many gateways also means more maintenance and more potential points of failure.
Setting up tax incorrectly for their business type. B2C stores should usually enter prices including tax. B2B stores should enter prices excluding tax. If you choose the wrong option, either customers see unexpected charges at checkout, or invoices show incorrect tax amounts. Research your jurisdiction's tax laws and choose the correct display settings before adding products.
Testing with live payment gateways instead of sandbox. You set up Stripe with live keys and place a test order. Real money is charged. You cannot refund without going through the payment processor's refund flow. Always use sandbox/test mode when developing and testing your store. Switch to live mode only when you're ready to launch.
Practice Questions
Why does Stripe need a webhook URL, and what happens if you skip this step? Answer: The webhook URL allows Stripe to send asynchronous payment status updates (success, failure, refund) to WooCommerce. Without it, orders stay in "Pending payment" status after successful payment because WooCommerce never receives confirmation from Stripe. The webhook must point to
https://yourstore.com/?wc_stripe_webhook=1.A customer in New York checks out and sees "No shipping methods available." What could be wrong with your shipping zone configuration? Answer: Either there is no shipping zone that includes New York, or the zone that includes New York has no shipping methods assigned. Check that a zone covering US (or specifically NY) exists and has at least one shipping method. Also check zone priority — a higher-priority zone might be matching first without applicable methods.
What is the difference between "prices including tax" and "prices excluding tax"? Which should a B2C store use? Answer: "Prices including tax" means the displayed price already contains the tax amount — common for consumer (B2C) stores where customers expect the shelf price to be the final price. "Prices excluding tax" means tax is added at checkout — common for B2B stores where businesses claim tax back. B2C stores should typically use "prices including tax" to avoid surprising customers.
Challenge: Set up a complete checkout flow for a multi-region store. Configure three shipping zones: "Local" (your city, local pickup only, priority 1), "Domestic" (your country, flat rate $4.99, free over $50, priority 10), "International" (rest of world, flat rate $19.99, priority 100). Set up PayPal sandbox and Stripe test mode. Create a customer account, add a product to the cart, and go through checkout with each shipping option. Test with a local address (should see only local pickup), a domestic address (should see flat rate and free shipping), and an international address (should see international flat rate). Debug and fix any issues you encounter. Write down what you learned about zone priority from the test.
FAQ
Mini Project
Configure a complete checkout system for a multi-region electronics store.
- Set up PayPal sandbox: create a sandbox business account and personal buyer account.
- Set up Stripe test mode: get the publishable and secret test keys from the Stripe dashboard.
- Configure the Stripe webhook using a tool like webhook.site or ngrok if testing locally.
- Create shipping zones:
- Local (priority 1): your city zip code, local pickup only
- Domestic (priority 10): your country, flat rate $5.99, free over $100
- Canada (priority 20): Canada, flat rate $14.99
- International (priority 100): rest of world, flat rate $29.99
- Create shipping classes: "Small Electronics" ($3.99), "Large Electronics" ($12.99), "Fragile Items" ($8.99). Assign classes to at least two products each.
- Configure tax: add a standard 7% tax rate for your state. Set prices to include tax for B2C display.
- Run a full test: add products to cart, go through checkout with each shipping zone, pay with Stripe test card 4242... and PayPal sandbox. Verify:
- Correct shipping method shows for each address
- Tax is calculated correctly
- Order status updates to "Processing" after payment
- Confirmation email is generated
- Enable debug logging for Stripe. Trigger a payment error intentionally (use a declined test card like 4000000000000002). Check the log file to see the error details.
What's Next
Now that payments, shipping, and tax are configured, learn how to manage orders, process refunds, and generate reports:
Continue to Lesson 48: Order Management — Manage orders, update statuses, process refunds, and generate sales reports.
Related lessons:
- Products and Inventory — Create products and manage stock for your store
- WooCommerce Setup — Back to the installation and initial configuration
- Essential Plugins — Recommended plugins for every WordPress site
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro