Want to create a plugin to extend WooCommerce? WooCommerce plugins are the same as regular WordPress plugins. For more information, visit Writing a plugin.

Your WooCommerce extension should:

  • Adhere to all WordPress plugin coding standards, as well as best practice guidelines for harmonious existence within WordPress and alongside other WordPress plugins.
  • Have a single core purpose and use WooCommerce features as much as possible.
  • Not do anything malicious or underhanded — for example, inserting spam links or up selling services outside of the WooCommerce.com ecosystem.
  • Not subvert or override Marketplace connections in core — for example, extensions cannot create branded top level menu items or introduce their own telemetry.

Merchants make use of WooCommerce extensions daily, and should have an unified and pleasant experience while doing so without advertising invading their WP Admin or store.

Note: We provide this page as a best practice for developers.


Note: We are unable to provide support for custom code under our Support Policy. If you are unfamiliar with code and resolving potential conflicts, select a WooExpert or Developer  for assistance.

Check if WooCommerce is active

Most WooCommerce plugins do not need to run unless WooCommerce is already active. You can wrap your plugin in a check to see if WooCommerce is installed:

/** * Check if WooCommerce is active **/ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) { // Put your plugin code here }

Note that this check will fail if the WC plugin folder is named anything other than woocommerce.

Main file naming

The main plugin file should adopt the name of the plugin, e.g., A plugin with the directory name plugin-name would have its main file named plugin-name.php.

Text domains

Follow guidelines for Internationalization for WordPress Developers, the text domain should match your plugin directory name, e.g., A plugin with a directory name of plugin-name would have the text domain plugin-name. Do not use underscores.


All text strings within the plugin code should be in English. This is the WordPress default locale, and English should always be the first language. If your plugin is intended for a specific market (e.g., Spain or Italy), include appropriate translation files for those languages within your plugin package. Learn more at Using Makepot to translate your plugin.

Follow WordPress PHP Guidelines

WordPress has a set of guidelines to keep all WordPress code consistent and easy to read. This includes quotes, indentation, brace style, shorthand php tags, yoda conditions, naming conventions, and more. Please review the guidelines.

Code conventions also prevent basic mistakes, as Apple made with iOS 7.0.6.

Custom Database Tables & Data Storage

Avoid creating custom database tables. Whenever possible, use WordPress post types, taxonomies, and options.

Consider the permanence of your data. Here’s a quick primer:

  • If the data may not always be present (i.e., it expires), use a transient.
  • If the data is persistent but not always present, consider using the WP Cache.
  • If the data is persistent and always present, consider the wp_options table.
  • If the data type is an entity with n units, consider a post type.
  • If the data is a means or sorting/categorizing an entity, consider a taxonomy.

Logs should be written to a file using the WC_Logger class.

Prevent Data Leaks

Try to prevent direct access data leaks. Add this line of code after the opening PHP tag in each PHP file:

if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly }


All plugins need a standard WordPress readme.

Your readme might look something like this:

=== Plugin Name === Contributors: (this should be a list of wordpress.org userid's) Tags: comments, spam Requires at least: 4.0.1 Tested up to: 4.3 Requires PHP: 5.6 Stable tag: 4.3 License: GPLv3 or later License URI: http://www.gnu.org/licenses/gpl-3.0.html

Plugin Author Name

Consistency is important to us and our customers. Products offered through WooCommerce.com should provide a consistent experience for all aspects of the product, including finding information on who to contact with queries.

Customers should be able to easily to differentiate a product purchased at WooCommerce.com from a product purchased elsewhere, just by looking through their plugin list in WordPress.

Thus, the following plugin headers should be in place:

  • The Plugin Author isYourName/YourCompany
  • The Developer header is YourName/YourCompany, with the Developer URI field listed as http://yourdomain.com/

For example:

/** * Plugin Name: WooCommerce Extension * Plugin URI: http://woocommerce.com/products/woocommerce-extension/ * Description: Your extension's description text. * Version: 1.0.0 * Author: Your Name * Author URI: http://yourdomain.com/ * Developer: Your Name * Developer URI: http://yourdomain.com/ * Text Domain: woocommerce-extension * Domain Path: /languages * * Woo: 12345:342928dfsfhsf8429842374wdf4234sfd * WC requires at least: 2.2 * WC tested up to: 2.3 * * License: GNU General Public License v3.0 * License URI: http://www.gnu.org/licenses/gpl-3.0.html */

Declaring required and supported WooCommerce version

Use the follow headers to declare “required” and “tested up to” versions:

  • WC requires at least
  • WC tested up to

Plugin URI

Ensure that the Plugin URI line of the above plugin header is provided. This line should contain the URL of the plugin’s product/sale page on WooCommerce.com (if sold by WooCommerce) or to a dedicated page for the plugin on your website.

Woo Plugin Header For Updates

WooCommerce core looks for a Woo line in the plugin header comment, to ensure it can check for updates to your plugin, on WooCommerce.com. This line looks like this:

Woo: 12345:342928dfsfhsf8429842374wdf4234sfd

This is only required for products sold on WooCommerce.com.  Using this line for products listed on WordPress.org or elsewhere is not required or necessary.

For products sold on WooCommerce.com, Vendors can find this snippet by logging in to their logging in to the Vendors Dashboard and going to Extensions > All Extensions. Then, select the product and click Edit product page. This snippet will be in the upper-right-hand corner of the screen.

See the plugin header comment example above for how the Woo header looks in context.

Make it Extensible

Developers should use WordPress actions and filters to allow for modification/customization without requiring users to touch the plugin’s core code base.

If your plugin creates a front-end output, we recommend to having a templating engine in place so users can create custom template files in their theme’s WooCommerce folder to overwrite the plugin’s template files.

For more information, check out Pippin’s post on Writing Extensible Plugins with Actions and Filters.

Remove Unused Code

With version control, there’s no reason to leave commented-out code; it’s annoying to scroll through and read. Remove it and add it back later if needed.


If you have a function, what does the function do? There should be comments for most if not all functions in your code. Someone/You may want to modify the plugin, and comments are helpful for that. We recommend using PHP Doc Blocks  similar to WooCommerce.

Avoid God Objects

God Objects are objects that know or do too much. The point of object-oriented programming is to take a large problem and break it into smaller parts. When functions do too much, it’s hard to follow their logic, making bugs harder to fix. Instead of having massive functions, break them down into smaller pieces.

Test Your Code with WP_DEBUG

Always develop with WP_DEBUG mode on, so you can see all PHP warnings sent to the screen. This will flag things like making sure a variable is set before checking the value.

Separate Business Logic & Presentation Logic

It’s a good practice to separate business logic (i.e., how the plugin works) from presentation logic (i.e., how it looks). Two separate pieces of logic are more easily maintained and swapped if necessary. An example is to have two different classes — one for displaying the end results, and one for the admin settings page.

Use Transients to Store Offsite Information

If you provide a service via an API, it’s best to store that information so future queries can be done faster and the load on your service is lessened. WordPress transients can be used to store data for a certain amount of time.

Logging Data

You may want to log data that can be useful for debugging purposes. This is great with two conditions:

  • Allow any logging as an ‘opt in’.
  • Use the WC_Logger class. A user can then view logs on their system status page.

If adding logging to your extension, here’s a snippet for presenting a link to the logs, in a way the extension user can easily make use of.

  $label = __( 'Enable Logging', 'your-textdomain-here' );
  $description = __( 'Enable the logging of errors.', 'your-textdomain-here' );
  if ( defined( 'WC_LOG_DIR' ) ) {
  $log_url = add_query_arg( 'tab', 'logs', add_query_arg( 'page', 'wc-status', admin_url( 'admin.php' ) ) );
  $log_key = 'your-plugin-slug-here-' . sanitize_file_name( wp_hash( 'your-plugin-slug-here' ) ) . '-log';
  $log_url = add_query_arg( 'log_file', $log_key, $log_url );
  $label .= ' | ' . sprintf( __( '%1$sView Log%2$s', 'your-textdomain-here' ), '<a href="' . esc_url( $log_url ) . '">', '</a>' );
  $form_fields['wc_yourpluginslug_debug'] = array(
  'title' => __( 'Debug Log', 'your-textdomain-here' ),
  'label' => $label,
  'description' => $description,
  'type' => 'checkbox',
  'default' => 'no'

view raw
hosted with 

 by GitHub

Error codes

This information is intended for the third-party developers so products they write can better handle errors. Error codes are produced by the Product Build Server when uploading a new submission or updating an existing product on the Marketplace.


The operation has completed successfully.


Internal error with the Product Build Server – cannot initialize the Apache daemon.


Internal error with the Product Build Server – cannot initialize the MySQL daemon.


Internal error with the Product Build Server – cannot initialize WordPress.


Internal error with the Product Build Server – cannot initialize WooCommerce.


Internal error with the Product Build Server – cannot configure dependencies.


Malware scanning error. This can happen if your product contains malware in the code.

Here’s an example output:

ObfuscatedPhp /tmp/product_clone/woocommerce-example/includes/views/html-settings-page.php 0x406:$ini_set: ini_set( 0x506:$ini_set: ini_set( ObfuscatedPhp /tmp/product_clone/woocommerce-example/includes/views/html-extras-page.php 0x406:$eval: exec(

This means that the character at the absolute position 0x406 (1030) and 0x506 (1286) in the file html-settings-page.php doesn’t pass the $ini_set rule, because it is using call_user_func in that file. Also, the other file html-extras-page.php doesn’t pass the rule $register_function which is using exec call.


Cannot extract the product. Most common issue is the top directory of the zip does not match its slug.


phpcs checks failed. The check uses the WooCommerce-Core sniffs with following phpcs.xml:

  <?xml version="1.0"?>
  <ruleset name="WordPress Coding Standards">
  <description>WooCommerce extension PHP_CodeSniffer ruleset.</description>
  <!– Exclude paths –>
  <!– Configs –>
  <config name="minimum_supported_wp_version" value="4.7" />
  <config name="testVersion" value="5.6-" />
  <!– Rules –>
  <rule ref="WordPress-Extra">
  <exclude name="Generic.Commenting.DocComment.SpacingAfter" />
  <exclude name="Generic.Files.LineEndings.InvalidEOLChar" />
  <exclude name="Generic.Functions.FunctionCallArgumentSpacing.SpaceBeforeComma" />
  <exclude name="PEAR.Functions.FunctionCallSignature" />
  <exclude name="Squiz.Commenting" />
  <exclude name="Squiz.PHP.DisallowSizeFunctionsInLoops.Found" />
  <exclude name="Squiz.WhiteSpace" />
  <exclude name="WordPress.Arrays" />
  <exclude name="WordPress.Files.FileName" />
  <exclude name="WordPress.NamingConventions" />
  <exclude name="WordPress.Security.ValidatedSanitizedInput.MissingUnslash" />
  <exclude name="WordPress.WP.I18n.NonSingularStringLiteralText" />
  <exclude name="WordPress.WhiteSpace" />
  <rule ref="WooCommerce-Core">
  <exclude name="Core.Commenting.CommentTags.AuthorTag" />
  <exclude name="WordPress.PHP.DontExtract" />
  <exclude name="Generic.Arrays.DisallowShortArraySyntax" />
  <exclude name="Generic.WhiteSpace.ScopeIndent.Incorrect" />
  <rule ref="PHPCompatibility">

view raw
hosted with 

 by GitHub

To install locally:

  1. Go to your product directory.
  2. Install WooCommerce sniffs with composer require woocommerce/woocommerce-sniffs.
  3. Put phpcs.xml above in the product directory.
  4. Run ./vendor/bin/phpcs --warning-severity=0 -s --ignore-annotations --extensions=php,html . .


Cannot install the product. Most common issue is the top directory of the zip does not match its slug.


Cannot activate the product. Refer to the build output for more details.


Cannot deactivate the product. Refer to the build output for more details.


This error means that your product is incompatible with other products in the host plan. Refer to the build output for more details.


This error means that your product is incompatible with other products in the host plan. Refer to the build output for more details.


This error means that your product is incompatible with other products in the host plan. Refer to the build output for more details.


Your theme is missing the theme info file theme_info.txt under the root directory.


Your theme info file theme_info.txt contains malformed data structure. It should contain the product ID, hash and main file, all separated by new lines. For example:

887931 2429c1dde521031cd053886b15844bbf storechild/style.css


Your theme main file contains malformed data structure. Provide Theme Name, Version, and the Woo headers in your main file.


Your plugin main file contains malformed data structure. Provide Plugin Name, Version, and the Woo headers in your main file.


Your product main file contains an invalid Woo header structure. Use the format ID:HASH. For example:

* Woo: 390890:911c438934af094c2b38d5560b9f50f3


Your product main file contains an invalid product ID in the Woo header.


Your product main file contains an invalid hash in the Woo header.


Your product is missing the main file.


Your product is missing the changelog.txt file.


The version in your product’s main file does not match with the provided version in changelog.txt.


Your product contains malformed changelog.txt structure. Refer to changelog.txt as an example.





블로그 이미지



댓글을 달아 주세요




Orders are created when a customer completes the checkout process, and they are visible to users with Admin and Shop Manager roles only. Each order is given a unique Order ID.

Order IDs are non-sequential as they use the default WordPress ID approach. For sequential order numbers, you can use Sequential Order Numbers Pro.

Order Statuses

An order also has a Status. Order statuses let you know how far along the order is, starting with “Pending payment” and ending with “Completed.” The following order statuses are used:

  • Pending payment — Order received, no payment initiated. Awaiting payment (unpaid).
  • Failed — Payment failed or was declined (unpaid) or requires authentication (SCA). Note that this status may not show immediately and instead show as Pending until verified (e.g., PayPal).
  • Processing — Payment received (paid) and stock has been reduced; order is awaiting fulfillment. All product orders require processing, except those that only contain products which are both Virtual and Downloadable.
  • Completed — Order fulfilled and complete – requires no further action.
  • On hold — Awaiting payment – stock is reduced, but you need to confirm payment.
  • Canceled — Canceled by an admin or the customer – stock is increased, no further action required.
  • Refunded — Refunded by an admin – no further action required.
  • Authentication required — Awaiting action by the customer to authenticate the transaction and/or complete SCA requirements.

Visual Diagram to Illustrate Order Statuses

This visual representation follows an order through its statuses from “Pending payment” to “Completed”, “Canceled” or “Refunded.”

Order Statuses and Payment Gateways

More about how order statuses relate to payment gateways in the Troubleshooting section.

Order Statuses and Emails

More about the different emails that are automatically sent at Email Settings.

If you are using PayPal and orders are staying in Pending, you may have an IPN issue. See the troubleshooting section at Debugging IPN Issues

Viewing and Managing Multiple Orders

Orders Overview

When a shop starts taking orders, the Orders management page begins to fill up. Go to: WooCommerce > Orders.

Each row displays several details. Some are there by default, others can be added. These are the available options:

  • Order number and customer name,
  • Date of purchase,
  • Order status,
  • Billing address,
  • Shipping address,
  • Purchase total, and
  • Actions.

To change these columns:

  • Go to: WooCommerce > Orders.
  • Select Screen Options in the top right corner.
  • Select which Columns to show.
  • Select how many Items you want to be displayed on each page.
  • Then Apply.

Filter and Arrange Orders

Filter orders by Date (month/year) or by registered customer.

  • Select the month, or search for a customer.
  • Select Filter.

Arrange orders in ascending or descending order by Order number, Date or Total by select the heading.

Note that the “Total” column does not take the refunded amount into consideration.

Click the order number and customer name to see the Single Order page, where you can also Edit order details, Update Status, and Add Notes. More details on that in Viewing and Editing Single Orders.

Searching and Finding Orders

Orders can be found using the search box at the top right of the order list. Enter an order number, customer name, or other information shown in the order list such as address. Click Search orders or tap return on your keyboard and search results will show a list of matching orders.

Previewing Orders

Order rows have a Preview “eye.”

Clicking Preview opens a Modal, containing the order number, order status, billing details, payment method, shipping details, shipping method, items ordered, and the option to change the order status.

Order Statuses in the Overview

Order Statuses are color-coded and descriptive.

  • Canceled – Grey
  • Completed – Blue
  • Failed – Red
  • On Hold – Orange
  • Pending Payment – Grey
  • Processing – Green
  • Refunded – Grey

Order Actions

Hovering over an order Status displays Notes made on the order.

At the end of a row are shortcut buttons to quickly mark orders as Processing or Complete.

Viewing and Editing a Single Order

From the Single Order page not only can you view all order data, but also edit and update.

  • Change the order status.
  • Edit order items – modify the product, prices, and taxes.
  • Stock – Reduce and restore stock for an order
  • Order Actions – Email order details to customer (handy if manually creating an order for your customers) or Regenerate download permissions
  • Modify product Meta to edit product variations by removing and adding meta
  • Apply coupons. You will need to know the coupon code to apply to the order. Coupon usage counts are tracked, and coupons can also be removed from orders. Note: the order must be unpaid for coupons to have an affect
  • Add fee. You can enter an amount or percentage to add a fee to an order. Negative fees will apportion taxes between all other items, and will not make the cart total go below zero

Order Details

Viewing Order Details

The Order Details panel you can view:

  • Order number
  • Payment details
  • Order date and time
  • Order status
  • Customer details:
    • Username and email, together with a link to view their profile and other purchases the customer may have had in the past
    • Billing details
    • Shipping details

Editing Order Details

Most of the details in this section can be updated and/or changes.

  • To change the date and time, use the dropdown date selector and the quantity selectors for the time.
  • To change the status, choose the right status in the dropdown.
  • To change the customer, select the current customer and search for the new customer.

Under “Billing” and “Shipping”, several other details can be changed. In order to do so, select the pencil icon next to each of them.

  • Under “Billing”, the following things can be changed:
    • Billing address — this can also be loaded from the customer’s profile by selecting “Load billing address”
    • Email
    • Phone number
    • Payment method and details
  • Under “Shipping”, the following things can be changed:
    • Shipping address — this can also be loaded from the customer’s profile or copied from the billing address
    • Customer provided note

Once you’ve made the necessary changes, select Update to update the order.

Order Items and Totals

Viewing Order Items

The next panel on the order page is the Order Items panel. This contains the product items, the shipping details, and the order summary.

  • Each product item row lists:
    • Product image
    • Product name
    • Single product Cost
    • Quantity
    • Total (Cost x Quantity, with discounts taken into consideration)
    • Taxes
  • Below that, the shipping details are displayed. This will include:
    • Shipping method
    • Boxed items
    • Total cost
    • Taxes
  • The last section contains an overview of the order costs. This section will change if an order is refunded. By default, it will include:
    • Items subtotal — cost excluding tax
    • Coupon(s) — amount deducted based on the use of coupons; the coupons used are displayed left in this section
    • Shipping — the shipping cost for the order
    • Taxes — the amount of taxes for the whole order; this will be replaced by the tax code applied to the order
    • Order total — the total of the above costs
    • Finally, below the line, an overview of what is paid and the fees taken by payment gateways

Editing or Adding Order Items

Apart from refunding, order items can not be edited, unless the order status is “Pending payment”, or “On hold.”

Product items. Select the pencil icon next to a product line to edit.

The following product items can be edited:

  • Add Meta — Add and remove meta to change product variable options.
  • Quantity — Number of items the customer is purchasing.
  • Total — Line price and line tax before pre-tax discounts.
  • Tax — Tax cost. For example, if a customer is tax-exempt you may want to remove the taxes.

Other actions. Next, you can do four actions at the bottom of this window:

  • Add item(s) — this will show you six new options:
    • Add product(s) — Add additional products to the order.
    • Add fee — Add an additional fee, such as gift wrapping.
    • Add shipping — Add a shipping cost. When you’ve done this, select the pencil icon to update the name, the method, the cost, and the tax.
    • Add tax — Add an additional tax code to every section in the order.
    • Cancel — Cancel if you do not want to make any changes.
    • Save — Save once the changes are made.
  • Once you’ve done this, you can select Recalculate if you want to automatically perform new calculations based on store settings. This can be handy if you are adding or removing products, coupons, shipping methods, etc. Note that any tax changes that you’ve manually included will be removed as the tax settings in your store will apply based on the customer address.

  • Apply coupon — If your customer forgot to add the coupon could or you want to reward the customer before they pay, selecting this option will show a modal that allows you to apply a coupon code.
  • Refund — to refund the customer. For more information about Manual and Automatic Refunds, see WooCommerce Refunds.

Custom Fields

To add custom meta fields, use the Custom Fields metabox:

Order Notes

The Order Notes panel displays notes attached to the order and can be used for storing event details, such as payment results or reducing stock levels, or adding notes to the order for customers to view. Some payment gateways also add notes for debugging.

The following note types are possible:

  • Purple: System status notices, such as payment gateway details.
  • Grey: General status updates, such as status changes or private notes. Customers do not see these notes but may receive notification of them, e.g., when the status changes from processing to completed, an email may be sent (depending on your settings).
  • Blue: Notes to the customer. Customers receive notes via email but can view them by viewing an order in their My account section.

Notes can be a powerful tool for communicating with customers or other store managers. Need to add a tracking number for shipping? Is stock delayed? Add a customer note, and they are automatically notified.

To add a note,

  • Use the textarea to add the content of the note.
  • Select Private note or Note to customer in the dropdown.
  • Select Add.

Manually Adding an Order

To add an order:

  1. Go to: WooCommerce > Orders.
  2. Use Add New at the top of the page. The Single Order page appears.
  3. Input customer details, add line items, apply coupons, apply fees and calculate totals. These are the same as the Editing or Adding Order Items.
  4. Set a status for the new order, e.g., If it needs to be paid, use “Pending payment.”
  5. Save.

Use the Order Actions dropdown to Email order details to the customer with payment instructions.

Paying for an Order

Orders that are “Pending payment” can be paid for through the payment link.

As the shop manager, you can find this link on the order overview:

  • If the customer is a Guest, anyone with the right link will be able to view the payment page and pay for the order.
  • If the customer is registered on your site,
    • Only this customer will be able to see the payment link once they are logged in.
    • The customer can also find the order in: My Account > Orders.

If the customer is assigned to the order, they will be asked to log in before paying:

  • If you are the store owner and wish to pay on behalf of the customer, consider using User Switching (not endorsed by WooCommerce.com) to log in to the customer’s account and complete the payment as them.

Removing Personal Data

Starting with WooCommerce 3.4+, it is possible to remove customer data.

  • Go to: WooCommerce > Settings > Accounts & Privacy.
  • Enable Allow personal data to be removed in bulk from orders.
  • Save changes.

This option is now available for orders:

  • Go to: WooCommerce > Orders.
  • Select the orders that need personal data removed.
  • Select Bulk Actions > Remove personal data.
  • Select Apply.

Please note, that once you press Apply this will remove personal data with no further warning. Orders will appear on the Orders screen like this:

On an individual order, data is updated like this:

  • Failedpending, and canceled orders which get cleaned up will be moved to the trash.
  • Completed orders which get cleaned up will be anonymized so sales stats are unaffected (as above).
  • Inactive accounts will be deleted. An inactive account is one which has not been logged in to, or which has not placed orders, for the specified time.

Personal data removal can be automatically associated with account erasure requests. WordPress allows deleting user details upon request via Tools > Erase Personal Data. This removal can now also be associated with the orders of this user.

  • Go to: WooCommerce > Settings > Accounts & Privacy.
  • Under Account erasure requests:
    • Enable Remove personal data from orders on request, if you also want to remove order data when this is done
    • Enable Remove access to downloads on request, if the customer should no longer access the download links once their personal details have been removed.

Personal data retention can also be automated.

  • Go to: WooCommerce > Settings > Accounts & Privacy
  • Under Personal data retention, set thresholds for inactive accounts and for orders with different statuses.
  • Save changes.

If enabled, this cleanup will run via a daily cron job. Inactive accounts are tracked using metadata, and only subscribers/customer accounts are removed.

Multi-Site Orders

Starting with WooCommerce 3.4+ there is now a widget that appears under Dashboard that shows order information from across all sites. You can click on an order to be taken to the details of the order on that site.


Understanding Order Statuses in Relation to Payment Gateways


Awaiting payment – stock is reduced, but you need to confirm payment Usually seen with payment methods when you need to manually confirm, such as BACS (bank transfer) or cheque.

You’ll also see this when the gateway is set to authorize instead of capture a charge: the shop owner will need to manually switch the status to processing.
Order received (unpaid). Most gateways will report back and set the order status to Processing (payment successful) or Failed (payment unsuccessful).  If the shop never receives either signal, it keeps the status on Pending.

This tends to be a misconfiguration of payment notification URLs or a plugin conflict.
Payment received and stock has been reduced- the order is awaiting fulfillment. All product orders require processing, except those with only products that are both digital and downloadable. If the payment has been successful and the order does not contain Digital or Downloadable products, the order will be set to Processing.

This is the shop owner or warehouse’s cue to ship the order and manually mark it as completed.
Order fulfilled and complete – requires no further action These generally aren’t interesting because everything has gone correctly.
Payment failed or was declined (unpaid). The order can be manually canceled, but this status can come up if the payment window has expired. It can happen for a few reasons:
  • order was abandoned  before payment was completeThe hold stock window expired without a response
  • Same reasons as Pending
Customer must complete requirements for SCA. It can occur when:
  • a new customer makes a purchase
  • an existing subscription renews


Do you still have questions and need assistance? 

  • Get in touch with a Happiness Engineer via our Help Desk. We provide expert priority support for WooCommerce.com and Jetpack customers but not other third-party plugins.
  • If you are not a customer at WooCommerce.com, we recommend finding help on the WooCommerce Support Forum or hiring a recommended expert on our customizations page.
블로그 이미지



댓글을 달아 주세요

Payment Gateway API

Payment gateways in WooCommerce are class based and can be added through traditional plugins. This guide provides an intro to gateway development.

Note: This is a Developer level doc provided as guidance. We are unable to dispense advice or review code under our Support Policy.

Types of payment gateway

Payment gateways come in several varieties:

  1. Form based – This is where the user must click a button on a form that then redirects them to the payment processor on the gateway’s own website. Example: PayPal standard, Authorize.net DPM
  2. iFrame based – This is when the gateway payment system is loaded inside an iframe on your store. Example: SagePay Form, PayPal Advanced
  3. Direct – This is when the payment fields are shown directly on the checkout page and the payment is made when ‘place order’ is pressed. Example: PayPal Pro, Authorize.net AIM
  4. Offline – No online payment is made. Example: Cheque, Bank Transfer

Form and iFrame based gateways post data offsite, meaning there are less security issues for you to think about. Direct gateways, however, require server security to be implemented (SSL certificates, etc.) and may also require a level of PCI compliance.

Creating a basic payment gateway

Note: We are unable to provide support for customizations under our Support Policy. If you are unfamiliar with code/templates and resolving potential conflicts, select a WooExpert or Developer  for assistance.

Payment gateways should be created as additional plugins that hook into WooCommerce. Inside the plugin, you need to create a class after plugins are loaded. Example:

add_action( 'plugins_loaded', 'init_your_gateway_class' );

It is also important that your gateway class extends the WooCommerce base gateway class, so you have access to important methods and the settings API:

function init_your_gateway_class() { class WC_Gateway_Your_Gateway extends WC_Payment_Gateway {} }

You can view the WC_Payment_Gateway class in the API Docs.

As well as defining your class, you need to also tell WooCommerce (WC) that it exists. Do this by filtering woocommerce_payment_gateways:

function add_your_gateway_class( $methods ) { $methods[] = 'WC_Gateway_Your_Gateway'; return $methods; } add_filter( 'woocommerce_payment_gateways', 'add_your_gateway_class' );

Required Methods

Most methods are inherited from the WC_Payment_Gateway class, but some are required in your custom gateway.

Within your constructor, you should define the following variables:

  • $this->id – Unique ID for your gateway, e.g., ‘your_gateway’
  • $this->icon – If you want to show an image next to the gateway’s name on the frontend, enter a URL to an image.
  • $this->has_fields – Bool. Can be set to true if you want payment fields to show on the checkout (if doing a direct integration).
  • $this->method_title – Title of the payment method shown on the admin page.
  • $this->method_description – Description for the payment method shown on the admin page.

Your constructor should also define and load settings fields:

$this->init_form_fields(); $this->init_settings();

We’ll cover init_form_fields() later, but this basically defines your settings that are then loaded with init_settings().

After init_settings() is called, you can get the settings and load them into variables, meaning:

$this->title = $this->get_option( 'title' );

Finally, you need to add a save hook for your settings:

add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );

Use this method to set $this->form_fields – these are options you’ll show in admin on your gateway settings page and make use of the WC Settings API.

A basic set of settings for your gateway would consist of enabled, title and description:

$this->form_fields = array( 'enabled' => array( 'title' => __( 'Enable/Disable', 'woocommerce' ), 'type' => 'checkbox', 'label' => __( 'Enable Cheque Payment', 'woocommerce' ), 'default' => 'yes' ), 'title' => array( 'title' => __( 'Title', 'woocommerce' ), 'type' => 'text', 'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ), 'default' => __( 'Cheque Payment', 'woocommerce' ), 'desc_tip' => true, ), 'description' => array( 'title' => __( 'Customer Message', 'woocommerce' ), 'type' => 'textarea', 'default' => '' ) );

process_payment( $order_id )
Now for the most important part of the gateway — handling payment and processing the order. Process_payment also tells WC where to redirect the user, and this is done with a returned array.

Here is an example of a process_payment function from the Cheque gateway:

function process_payment( $order_id ) { global $woocommerce; $order = new WC_Order( $order_id ); // Mark as on-hold (we're awaiting the cheque) $order->update_status('on-hold', __( 'Awaiting cheque payment', 'woocommerce' )); // Remove cart $woocommerce->cart->empty_cart(); // Return thankyou redirect return array( 'result' => 'success', 'redirect' => $this->get_return_url( $order ) ); }

As you can see, its job is to:

  • Get and update the order being processed
  • Return success and redirect URL (in this case the thanks page)

Cheque gives the order On-Hold status since the payment cannot be verified automatically. If, however, you are building a direct gateway, then you can complete the order here instead. Rather than using update_status when an order is paid, you should use payment_complete:


This ensures stock reductions are made, and the status is changed to the correct value.

If payment fails, you should throw an error and return null:

wc_add_notice( __('Payment error:', 'woothemes') . $error_message, 'error' ); return;

WooCommerce will catch this error and show it on the checkout page.

Stock levels are updated via actions (woocommerce_payment_complete and in transitions between order statuses), so it’s no longer needed to manually call the methods reducing stock levels while processing the payment.

Updating Order Status and Adding Notes

Updating the order status can be done using functions in the order class. You should only do this if the order status is not processing (in which case you should use payment_complete()). An example of updating to a custom status would be:

$order = new WC_Order( $order_id ); $order->update_status('on-hold', __('Awaiting cheque payment', 'woothemes'));

The above example updates the status to On-Hold and adds a note informing the owner that it is awaiting a Cheque. You can add notes without updating the order status; this is used for adding a debug message:

$order->add_order_note( __('IPN payment completed', 'woothemes') );

Order Status Best Practice

  • If the order has completed but the admin needs to manually verify payment, use On-Hold
  • If the order fails and has already been created, set to Failed
  • If payment is complete, let WooCommerce handle the status and use $order->payment_complete(). WooCommerce will use either Completed or Processing status and handle stock.

Notes on Direct Gateways

If you are creating an advanced, direct gateway (i.e., one that takes payment on the actual checkout page), there are additional steps involved. First, you need to set has_fields to true in the gateway constructor:

$this->has_fields = true;

This tells the checkout to output a ‘payment_box’ containing your direct payment form that you define next.

Create a method called payment_fields() – this contains your form, most likely to have credit card details.

The next but optional method to add is validate_fields(). Return true if the form passes validation or false if it fails. You can use the wc_add_notice() function if you want to add an error and display it to the user.

Finally, you need to add payment code inside your process_payment( $order_id ) method. This takes the posted form data and attempts payment directly via the payment provider.

If payment fails, you should output an error and return nothing:

wc_add_notice( __('Payment error:', 'woothemes') . $error_message, 'error' ); return;

If payment is successful, you should set the order as paid and return the success array:

// Payment complete $order->payment_complete();// Return thank you page redirect return array( 'result' => 'success', 'redirect' => $this->get_return_url( $order ) );

Working with Payment Gateway Callbacks (such as PayPal IPN)

If you are building a gateway that makes a callback to your store to tell you about the status of an order, you need to add code to handle this inside your gateway.

The best way to add a callback and callback handler is to use WC-API hooks. An example would be as PayPal Standard does. It sets the callback/IPN URL as:

str_replace( 'https:', 'http:', add_query_arg( 'wc-api', 'WC_Gateway_Paypal', home_url( '/' ) ) );

Then hooks in its handler to the hook:

add_action( 'woocommerce_api_wc_gateway_paypal', array( $this, 'check_ipn_response' ) );

WooCommerce will call your gateway and run the action when the URL is called.

For more information, see WC_API — The WooCommerce API Callback.

Hooks in Gateways

It’s important to note that adding hooks inside gateway classes may not trigger. Gateways are only loaded when needed, such as during checkout and on the settings page in admin.

You should keep hooks outside of the class or use WC-API if you need to hook into WordPress events from your class.

More Examples

For more examples of payment gateways, go to WooCommerce core gateways or WooCommerce premium gateways.






블로그 이미지



댓글을 달아 주세요


A plugin is a piece of software containing a group of functions that can be added to a WordPress website.


Steps for creating a plugin for WooCommerce :

One of the easiest ways to create a settings page is by taking advantage of the WC_Integration class. Using the Integration class will automatically create a new settings page under WooCommerce > Settings > Integration and it will automatically save and sanitize your data for you.

1) Download and activate the latest version of WooCommerce from here: https://wordpress.org/plugins/woocommerce/


2) create new folder for our new plugin in wp-content/plugin/ directory.

e.g, wp-content/plugin/my-custom-plugin


3) WC_Integration class file. e.g, class-wc-integration-demo-integration.php.

 * Integration Demo.
 * @package   Woocommerce My plugin Integration
 * @category Integration
 * @author   Addweb Solution Pvt. Ltd.
if ( ! class_exists( 'WC_My_plugin_Integration' ) ) :
class WC_My_plugin_Integration extends WC_Integration {
   * Init and hook in the integration.
  public function __construct() {
    global $woocommerce;
    $this->id                 = 'my-plugin-integration';
    $this->method_title       = __( 'My Plugin Integration');
    $this->method_description = __( 'My Plugin Integration to show you how easy it is to extend WooCommerce.');
    // Load the settings.
    // Define user set variables.
    $this->custom_name          = $this->get_option( 'custom_name' );
    // Actions.
    add_action( 'woocommerce_update_options_integration_' .  $this->id, array( $this, 'process_admin_options' ) );
   * Initialize integration settings form fields.
  public function init_form_fields() {
    $this->form_fields = array(
      'custom_name' => array(
        'title'             => __( 'Custom Name'),
        'type'              => 'text',
        'description'       => __( 'Enter Custom Name'),
        'desc_tip'          => true,
        'default'           => '',
        'css'      => 'width:170px;',


4) plugin file. e.g, woocommerce-my-custom-plugin.php

 * Plugin Name: My custom plugin
 * Plugin URI: http://www.addwebsolution.com
 * Description: A plugin demonstrating how to add a new WooCommerce integration.
 * Author:  Addweb Solution Pvt. Ltd.
 * Author URI: http://www.addwebsolution.com
 * Version: 1.0
if ( ! class_exists( 'WC_my_custom_plugin' ) ) :
class WC_my_custom_plugin {
  * Construct the plugin.
  public function __construct() {
    add_action( 'plugins_loaded', array( $this, 'init' ) );
  * Initialize the plugin.
  public function init() {
    // Checks if WooCommerce is installed.
    if ( class_exists( 'WC_Integration' ) ) {
      // Include our integration class.
      include_once 'class-wc-integration-demo-integration.php';
      // Register the integration.
      add_filter( 'woocommerce_integrations', array( $this, 'add_integration' ) );
   * Add a new integration to WooCommerce.
  public function add_integration( $integrations ) {
    $integrations[] = 'WC_My_plugin_Integration';
    return $integrations;
$WC_my_custom_plugin = new WC_my_custom_plugin( __FILE__ );


Now, you can see the My custom plugin in the list of all plugins.

5) create settings link for the plugin. Add this in init() method of your plugin.

// Set the plugin slug
 define( 'MY_PLUGIN_SLUG', 'wc-settings' );

// Setting action for plugin
add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), 'WC_my_custom_plugin_action_links' );


Now add the function after object creation in the plugin file.

function WC_my_custom_plugin_action_links( $links ) {

    $links[] = '<a href="'. menu_page_url( MY_PLUGIN_SLUG, false ) .'&tab=integration">Settings</a>';
    return $links;


Now you are able to see the settings link for the plugin. It is dependent on the WooCommerce plugin activation and deactivation.

6) Click on the settings link. You are now able to save data also.

Hope this blog helps you out. Feel free to share any questions, we are ready to help always :) If you need more assistance regarding WordPress Development Service then get in touch.





블로그 이미지



댓글을 달아 주세요


다음 우편번호 API가 보안상 강화이유로 패치되었다.

완전한 패치날짜는 2021년 03월 31일 분기경이다. 


따라서 뒤에오는 인자에 대해서 일반적으로 잘 허용하지 않는다.



1. Cosmosfarm Customizing quotation

//wp_register_script('daum-postcode', '//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js', array('jquery'), NULL, true);
wp_enqueue_script('daum-postcode', '//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js', array('jquery'), NULL, true);


해당 부분에서 뒤의 인자값에 대해서 NULL 값으로 등록되는 부분으로 패치한 것을 볼 수 있다.

뒤에 인자를 추가적으로 받지 않는다. 

(예전처럼 플러그인을 만들었다거나, 추가 커스터마이징을 해서 기록을 남겨두는 의미로 뒤의 의미없는 인자를 생략하겟다는 이야기)


Wooshiping 에서는 WSP_VERSION 관련된 인자가 쭉 이어져서, 추적하다보면 

"class-wsp-assets.php" 에서 Version Control 을 하는 것을 볼 수 있다.



[해당 부분에서 보고 패치]



Daum 우편번호 서비스

우편번호 검색과 도로명 주소 입력 기능을 너무 간단하게 적용할 수 있는 방법. Daum 우편번호 서비스를 이용해보세요. 어느 사이트에서나 무료로 제약없이 사용 가능하답니다.



블로그 이미지



댓글을 달아 주세요

WordPress로 운영되는 사이트나 블로그가 있는 경우 WordPress용 인스턴트 아티클 플러그인을 사용하여 쉽게 인스턴트 아티클을 만들 수 있습니다. 이 방법이 인스턴트 아티클을 만드는 가장 쉬운 방법이며 HTML 관련 경험이 필요하지 않습니다.

필수 요건


빠른 시작

1. 다운로드

WP용 인스턴트 아티클 플러그인을 다운로드하고 설치합니다.

2. Facebook 페이지 ID 삽입

플러그인을 설치한 다음 인스턴트 아티클 메뉴 옵션을 클릭하고 인스턴트 아티클 가입에 사용한 Facebook 페이지의 ID를 입력하세요.

인스턴트 아티클 구성 화면의 "사이트 연결" 섹션에서 페이지 ID를 가져올 수 있습니다.

3. 공유 시작

인스턴트 아티클 피드가 승인되면 게시할 수 있습니다.

다른 링크를 공유하는 것처럼 인스턴트 아티클을 배포하세요. 아티클을 포함하여 새 게시물을 구성하고 공유하면 됩니다! 인스턴트 아티클은 페이지에 자동으로 게시되지 않습니다.


In testing, This stage might need to push. If not, In final stage was not submited.

다음 단계

  1. 인스턴트 아티클 스타일 맞춤 설정.
  2. Facebook 블로그 팔로우. 인스턴트 아티클 뉴스 및 업데이트에 대해 알아보려면 알림에 가입하세요.
  3. 인스턴트 아티클 수익화. 자신의 직접 판매 광고 또는 Audience Network (또는 둘 다)를 사용하세요.
  4. 인터랙티브 디자인 기능 추가. 인스턴트 아티클의 고유 기능을 사용하여 독자에게 즐거움을 제공하세요.
  5. 인사이트 아티클의 분석 기능 사용. 자신 또는 타사의 트래커를 포함하는 방법을 알아보세요.
  6. 문제 해결.
블로그 이미지



댓글을 달아 주세요

Are you encountering RSS feed errors on your WordPress site? RSS feeds help users subscribe to your blog using news reader apps like Feedly.

Since RSS feeds are published in the XML markup language, a tiny mistake in the feed can make it unreadable, and users will not be able to see new content in their news feeds.

Other apps also rely on getting content updates from your WordPress RSS feed. For example, if you use IFTTT to automate social sharing of your new posts, then that would stop working as well.

In this article, we will show you how to easily fix RSS feed errors in WordPress. We will also talk about what causes those errors and how to avoid them in the future.

Most Common WordPress RSS Feed Errors

Most common WordPress RSS feed errors are caused by poor formatting.

WordPress outputs RSS feeds in XML which is a strict markup language. A missing line break or an extra tab can break your RSS feed.

The RSS error message will look something like this:

XML Parsing Error: XML or text declaration not at start of entity
Location: http://example.com/feed
Line Number 2, Column 1:

Depending on what browser you are using, your RSS feed error message may vary.

You can also see this error message when visiting your feed in a browser.

Warning: Cannot modify header information – headers already sent by (output started at /home/username/example.com/wp-content/themes/twentysixteen/functions.php:433) in /home/username/example.com/wp-includes/pluggable.php on line 1228

If you are using FeedBurner, then your errors may look different.

Having said that, let’s take a look at what causes these RSS feed errors and how to fix them.

Manually Fixing RSS Feed Errors in WordPress

The most likely reason for your RSS feeds to show error is poor formatting. This poor formatting can be caused by a blank space after closing PHP tag in a plugin or in your theme’s functions.php file.

If you recently added a code snippet to your theme or child theme‘s functions.php file. Then you need to edit your functions file.

If there is a closing PHP tag at the end of your functions file, then you need to make sure that there is no extra space or line breaks after it.

Ideally, the closing PHP tag is not required at the end of the file. This is why it would be best if you remove the closing php tag altogether.

This should fix the problem in most cases. However, if it does not fix your RSS feed error, then continue reading.

Disable RSS Feed Related Plugins

If you are using a WordPress plugin that modifies your website’s RSS feed or creates a new one, then you need to disable that plugin.

If you are unsure, then you can temporarily disable all WordPress plugins.

Next, check your RSS feed for the error. If the error disappears, then this means one of the plugins installed on your website was the culprit.

You can now reactivate your installed plugins one by one and check your RSS feed after activating each plugin. This way you will be able to find out exactly which plugin is causing the issue.

Once you have located the plugin, you can contact the plugin’s support for an update or find an alternative plugin that does the same thing.

Temporarily Switch to a Default Theme

Occasionally, a poorly coded WordPress theme function can also affect your WordPress RSS feed. To see if the problem is caused by your WordPress theme, you need to temporarily switch to a default WordPress theme.

Simply go to Appearance » Themes page and if you already have a default theme installed then activate it.

Default themes include Twenty Nineteen, Twenty Seventeen, Twenty Sixteen, and so on. If you don’t have one installed on your website, then you can click on the Add New button to install and activate it. See our guide on how to install a WordPress theme for step by step instructions.

After switching to the default theme, check your WordPress feed for error. You can visit your feed in a browser window or test it with a feed validator tool.

If the error disappears, then this means your WordPress theme was causing the issue. You can contact the theme author for support or find a suitable new theme for your website.

We hope this article helped you fix WordPress RSS feed errors on your site. You may also want to take a look at our guide on how to increase your website traffic and why you need to build an email list right away.

If you liked this article, then please subscribe to our YouTube Channel for WordPress video tutorials. You can also find us on Twitter and Facebook.




블로그 이미지



댓글을 달아 주세요




  • Steven Stern (sterndata) 


    Forum Moderator & Support Team Volunteer

    1 year, 7 months ago

    What’s your .htaccess file for this site?

    Thread Starter



    1 year, 7 months ago

    Hi Steve,
    Thanks for responding!

    Hmm, I’m on a Windows server. Sorry I should have mentioned that. There is no .htaccess file for IIS as far as I’m aware. Or?

    I’ve checked the default document list and it’s the same as for the working site.


    Steven Stern (sterndata) 


    Forum Moderator & Support Team Volunteer

    1 year, 7 months ago

    When I hit any 404 on your site, it goes to a hosting-supplied 404 page and not the one that should be part of your site, so it’s something related to what would be handled by htaccess. I don’t use Windows so I’m not sure if I can help.

    Thread Starter



    1 year, 7 months ago

    Ok, you might have pointed me in the right direction here. On the site that works, a random 404 shows me the WordPress “page not found” page, not the hosting company 404 page.

    I don’t suppose you’d be able to provide the part of .htaccess that would usually handle the /feed/ redirect? Then I might be able to figure it out.


    Steven Stern (sterndata) 


    Forum Moderator & Support Team Volunteer

    1 year, 7 months ago


    Thread Starter



    1 year, 7 months ago

    I took a copy of the web.config file from the working site, changed the reference to the domain in one of the RULE tags so that it referred to the correct domain, and uploaded it to the broken site.
    The 404 handling immediately started being done by WordPress. It took a little while for the RSS feed to sort itself out, but that’s working too now – checked via Google Chrome Feeder extension.

    I haven’t copied the contents of the config file here because I’m not sure which parts, if any, might be sensitive info that could make my site vulnerable if publicly known. Although if the same file works for 2 of my sites, I guess there’s probably nothing sensitive in it…

    Thanks @sterndata for your tips!

Viewing 6 replies - 1 through 6 (of 6 total)





블로그 이미지



댓글을 달아 주세요