卸载
是否保留数据
1
2
|
//告诉WCC,删除插件的时候,是否保留数据
define('WC_REMOVE_ALL_DATA', true);
|
角色
安装woocommerce之后会自动创建两个角色
1、店铺管理员(Shop manager)
2、顾客(Customer)
固定链接
后台->设置->固定链接
产品固定链接
1
|
http://wordpress.localhost/product/sample-product/
|
1
|
http://wordpress.localhost/shop/sample-product/
|
1
|
http://wordpress.localhost/shop/product-category/sample-product/
|
1
2
3
|
//输入个自定义base,它必须被设置,否则 WordPress 会使用默认值替代.
/product/
|
产品常规设置
评论设置
库存设置
- 保留库存(保留库存(为未支付订单)x 分钟。当达到限制时间时,待付款的订单将会被取消。留空则一直保留,不会自动取消订单。)
- 库存不足的最低值(当库存数量达到这个数量时,会发送通知)
- 售罄的最低值(当库存达到这里数量时,库存状态将会改编为”售罄“,并发送通知)
可下载设置
- 文件下载方法
- 强制下载
- X-Accel-Redirect/X-Sendfile(需要服务器配置)
- 仅重定向(在发布产品时,可以设置对应文件的url)
- 访问限制
- 下载必须登录
- 支付后授权访问可下载产品(启用此选项时当下载订单状态为“正在处理”,而非“已完成”,授权访问下载资源。否则,订单状态为”已完成“才能下载)
配送设置
配送方式
免费配送
- N/A (无限制)
- 免费送货需要免费送货券
- 最小订单金额
- 最小订单金额或优惠券
- 最小订单金额和优惠券
标准运费(统一费率)
-
税状态
-
成本
1
2
3
4
5
6
7
8
9
10
|
//[qty]表示商品数量
//[cost]表示商品总额
//[fee percent="10" min_fee="20" max_fee=""]
//运费每件商品10元
10*[qty]
//运费为商品总额的10%
[cost]*0.1
[fee percent="10"]
//运费为商品总额的10%,最低收5元,最高30元
[fee percent="10" min_fee="5" max_fee="30"]
|
本地自提
通过代码设置
1
2
3
4
5
6
7
8
9
10
11
|
//如果配送符合免费,则仅仅展示免费
add_filter('woocommerce_package_rates', function($rates) {
$free = [];
foreach($rates as $rate_id => $rate) {
if ('free_shipping' === $rate->method_id) {
$free[$rate_id] = $rate;
break;
}
}
return !empty($free) ? $free : $rates;
}, 100);
|
配送类型
”配送类型“针对单个产品设置的,可以看作是”配送方式->统一费率(标准运费)“中更细粒度的设置
结算设置
优惠券使用
是否启用优惠券功能
当应用多个优惠券,应用第一个优惠券的全价和第二优待券的折扣价格等。
即:按顺序,先根据前面的优惠券计算出应付价格,再结合后面的优惠券计算折扣。
API设置
Rest API
查看所有的路由:http://wordpress.localhost/wp-json/wc/v2
- 生成Api Key
- OAuth 1.0 (http)
- Basic Auth (https)
Webhook
特定的时候要求wcc向指定的页面发送post请求。webbook是一种通知机制。
优惠券
常规
-
折扣类型
优惠券的金额就是比例,如:10 标识 10%的优惠
整个购物车固定金额的优惠。如果购物车中的商品总金额小于优惠券金额,则优惠总额为商品总金额
按产品数据计算优惠。如产品数量为2,优惠券金额为8,则优惠金额为2*8=16
-
优惠券金额
-
允许免运费
要配合配送方式中的免费配送的设置使用。其中免费送货需要免费送货券、最小订单金额或优惠券、最小订单金额和优惠券这三个设置都可以
精确到天,过期时间为设置日期的00:00:00
使用限制
如果优惠券不能与其他优惠券一起使用请勾选此框
如果优惠券不适用用于促销产品,请选中该复选框。基于物品的优惠券仅在该物品非促销时可用。基于购物车的优惠券仅在购物车内无促销产品时可用
折扣类型是固定的购物车优惠时候,如果购物车中包含了排除的产品,整个购物车都无法使用该优惠券
使用次数
- 每个优惠券的使用次数限制
- 限制x个物品使用 (只用于折扣类型:百分比优惠、固定的产品优惠)
如果购物车中有多个商品,优先级为 数量 > 金额
订单
状态 (7种)
- 待付款 (Pending payment)
- 正在处理(Processing)
- 保留(On hold)
- 已完成(Completed)
- 已取消(Cancelled)
- 已退款(Refunded)
- 失败订单(Failed)
动作
- 发给客户的邮件收据/订单详情
- 重新发送新订单通知 (发送给管理员)
- 重新生成下载权限 (下载剩余次数会被重置)
产品
发布
发布时间
可用于实现定时发布的功能,仅当当前时间大于发布时间,产品才显示
目录可见
产品数据
产品类型
- 单个产品
- 成组产品 (包含多个产品,类似套餐)
- 外接/关联产品
- 可变产品 (产品的多个属性可选,可以选择不同组合。如:产品尺寸,产品颜色,不同颜色和不同尺寸组成不同的组合。)
- 属性 (可以勾上是否用于变量)
- 变量
- 自动生成 (自动根据勾选用于变量的属性,通过组合方式生成不同的变量,即:可能产品)
- 手动添加
库存
SKU,即库存单位,是一种可以帮助零售商识别最小库存持有量的代码。每个 SKU 都是独一无二的,代表了一个特定的商品,包括它的型号、尺寸、颜色等属性。
- 允许缺货超售?
- 不允许
- 允许
- 允许,但通知客户 (客户购买后,会在邮件通知中显示”延迟交货“)
全局变量$product
1
2
3
4
5
6
7
8
9
|
<?php if(have_posts()): ?>
<?php while(have_post()):the_post(); ?>
<?php global $product; ?>
<pre>
<!-- simple:单个产品 external:外接/关联产品 grouped:成组产品 variable:可变产品 -->
<?php echo $product->get_type(); ?>
</pre>
<?php endwhile; ?>
<?php endif; ?>
|
产品相关数据查询
产品ID
1
2
3
4
5
6
7
8
9
10
|
<?php if(have_posts()): ?>
<?php while(have_post()):the_post(); ?>
<?php global $product, $post; ?>
<h2>产品ID</h2>
<?php echo $product->get_id(); ?>
<?php echo get_the_ID(); ?>
<?php echo $post->ID; ?>
<?php echo get_queried_object_id(); ?>
<?php endwhile; ?>
<?php endif; ?>
|
产品图片查询
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
<!-- 新版woocommerce没有产品图片设置页面,可以通过代码自定图片尺寸 -->
<?php
add_image_size('shop_catalog', 300, 300, true);
add_image_size('shop_single', 600, 600, true);
add_image_size('shop_thumbnail', 180, 180, true);
//新版提供了新的方法
//single、gallery_thumbnail、thumbnail
wc_get_image_size('single');
?>
<?php if(have_posts()): ?>
<?php while(have_post()):the_post(); ?>
<?php global $product; ?>
<h2>产品图片</h2>
<?php the_post_thumbnail('shop_catalog');//目录图片 ?>
<?php the_post_thumbnail('shop_single');//产品详情页的产品图片 ?>
<?php the_post_thumbnail('shop_thumbnail');//产品缩略图 ?>
<?php endwhile; ?>
<?php endif; ?>
|
产品相册
1
2
3
4
5
6
7
8
|
<?php if(have_posts()): ?>
<?php while(have_post()):the_post(); ?>
<?php global $product; ?>
<h2>产品相册</h2>
<?php foreach($product->get_gallery_image_ids() as $aid): ?>
<?php echo wp_get_attachment_image($aid, 'shop_thumbnail'); ?>
<?php endwhile; ?>
<?php endif; ?>
|
产品其他信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
<?php if(have_posts()): ?>
<?php while(have_post()):the_post(); ?>
<?php global $product; ?>
<div>
<h2>产品标题</h2>
<?php echo $post->post_title; ?>
<?php echo $product->get_name(); ?>
</div>
<div>
<h2>产品价格</h2>
<?php echo $post->get_price_html(); ?>
</div>
<div>
<h2>产品简介</h2>
<?php the_excerpt(); ?>
<?php echo $product->get_short_description(); ?>
</div>
<div>
<h2>产品货号</h2>
<?php echo $product->get_sku(); ?>
</div>
<div>
<h2>产品正文</h2>
<?php echo $product->get_description(); ?>
<?php the_content(); ?>
</div>
<div>
<h2>产品属性</h2>
<?php echo wc_display_product_attributes($product); ?>
</div>
<div>
<h2>产品所属分类</h2>
<?php echo wc_get_product_category_list($product->get_id(), '-'); ?>
</div>
<div>
<h2>产品所属标签</h2>
<?php echo wc_get_product_tag_list($product->get_id(), '-'); ?>
</div>
<div>
<h2>加入购物车</h2>
<?php woocommerce_template_single_add_to_cat(); ?>
</div>
<div>
<h2>增销产品</h2>
<?php
//$limit 显示数量 -1显示全部
//$columns 每行显示几个
//woocommerce_upsell_display($limit, $columns, $orderby, $order);
?>
<?php woocommerce_upsell_display(); ?>
</div>
<div>
<h2>相关产品</h2>
<?php
// orderby: rand,title,ID,date,modified,menu_order,price
$defauls = [
'posts_per_page' => 1,
'columns' => 2,
'orderby' => 'rand',
'order' => 'desc'
];
woocommerce_related_products($defauls);
?>
</div>
<?php endwhile; ?>
<?php endif; ?>
|
产品自定义查询示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
/**
* 获取所有有货、店铺页可见 (NOT IN (outofstock, exclude-from-catalog))
* 并且
* 在别名为phone的产品分类中或者在别名为hot的产品标签中的
* 所有产品
*/
$query = new WP_Query([
'post_type' => 'product',
'posts_per_page' => -1,
'tax_query' => [
'relation' => 'AND',
[
'taxonomy' => 'product_visibility',
'field' => 'slug',
'terms' => [
'exclude-from-catalog',
'outofstock'
],
'operator' => 'NOT IN',
],
[
'relation' => 'OR',
[
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => 'phone',
],
[
'taxonomy' => 'product_tag',
'field' => 'slug',
'terms' => 'hot',
]
]
],
]);
if ($query->have_post()) while($query->have_post()) {
$query->the_post();
$global $product;
$product->get_id();
the_ID();
}
wp_reset_postdata();
|
产品可见性(product_visibility)
所有在搜索结果中排除的产品,都在此分类项目中
所有从店铺页或分类归档页中排除的产品,都在此分类项目中
所有推荐的产品,都在此分类项目中
所有没有库存的产品,都在此分类项目中
1星评价
2星评价
3星评价
4星评价
5星评价
产品可见性页面设置中对应的值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
// 1.商店页和搜索结果页
"product_visibility NOT IN ('exclude-from-catalog', 'exclude-from-search')"
// 2.仅商店页
"product_visibility IN ('exclude-from-search')"
// 3.仅搜索结果页
"product_visibility IN ('exclude-from-catalog')"
// 4.隐藏
"product_visibility IN ('exclude-from-catalog', 'exclude-from-search')"
// 5.推荐产品
"product_visibility IN ('featured')"
|
产品可见性查询示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
/**
* 获取所有有货、店铺页可见 (NOT IN (outofstock, exclude-from-catalog))
* 并且
* 在别名为other的产品分类中的
* 所有产品
*/
$query = new WP_Query([
'post_type' => 'product',
'posts_per_page' => -1,
'tax_query' => [
'relation' => 'AND',
[
'taxonomy' => 'product_visibility',
'field' => 'slug',
'terms' => [
'exclude-from-catalog',
'outofstock'
],
'operator' => 'NOT IN',
],
[
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => 'other',
]
],
]);
|
模板层级
开启主题对woocommerce支持
1
2
3
4
|
add_action('after_setup_theme', function () {
// 开启woocommerce支持,后面的模板层级才生效
add_theme_support('woocommerce');
});
|
产品详情页模板层级
1
2
3
4
5
|
woocommerce.php
$custom.php //自定义模板文件
single-product.php
woocommerce/single-product.php
plugins/woocommerce/templates/single-product.php //wcc插件中的模板文件
|
产品分类归档页模板层级
1
2
3
4
5
6
|
woocommerce.php
taxonomy-product_cat-$slug.php
woocomerce/taxonomy-product_cat-$slug.php
taxonomy-product_cat.php
woocommerce/taxonomu-product_cat.php
plugins/woocomerce/templates/taxonomy-product_cat.php
|
产品标签归档页模板层级
1
2
3
4
5
6
|
woocommerce.php
taxonomy-product_tag-$slug.php
woocommerce/taxonomy-proudct_tag-$slug.php
taxonomy-product_tag.php
woocommerce/taxonomy-product_tag.php
plugins/woocommerce/templates/taxonomy-product_tag.php
|
全局属性归档页模板层级
1
2
3
4
5
6
7
8
|
woocommerce.php
taxonomy-pa_$attr_slug-$term_slug.php
woocomerce/taxonomy-pa_$attr_slug-$term_slug.php
taxonomy-pa_$attr_slug.php
woocomerce/taxonomy-pa_$attr_slug.php
archive-product.php
woocommerce/archive-product.php
plugins/woocommerce/templates/archive-product.php
|
WCC创建的页面模板层级
店铺页面
1
2
3
4
|
woocomerce.php
archive-product.php
woocommerce/archive-product.php
plugins/woocomerce/templates/archive-product.php
|
我的账户页
普通页面,按照wordpress默认的模板层级规则来
结算页
普通页面,按照wordpress默认的模板层级规则来
购物车页
普通页面,按照wordpress默认的模板层级规则来
用户协议页
普通页面,按照wordpress默认的模板层级规则来
WCC条件标签
是否woocommerce页面
1
2
3
4
5
6
7
8
|
/**
* Is_woocommerce - Returns true if on a page which uses WooCommerce templates (cart and checkout are standard pages with shortcodes and thus are not included).
*
* @return bool
*/
function is_woocommerce() {
return apply_filters( 'is_woocommerce', is_shop() || is_product_taxonomy() || is_product() );
}
|
是否店铺页
1
2
3
4
5
6
7
8
|
/**
* Is_shop - Returns true when viewing the product type archive (shop).
*
* @return bool
*/
function is_shop() {
return ( is_post_type_archive( 'product' ) || is_page( wc_get_page_id( 'shop' ) ) );
}
|
是否产品分类页
1
2
3
4
5
6
7
8
9
|
/**
* Is_product_category - Returns true when viewing a product category.
*
* @param string $term (default: '') The term slug your checking for. Leave blank to return true on any.
* @return bool
*/
function is_product_category( $term = '' ) {
return is_tax( 'product_cat', $term );
}
|
是否产品标签页
1
2
3
4
5
6
7
8
9
|
/**
* Is_product_tag - Returns true when viewing a product tag.
*
* @param string $term (default: '') The term slug your checking for. Leave blank to return true on any.
* @return bool
*/
function is_product_tag( $term = '' ) {
return is_tax( 'product_tag', $term );
}
|
是否产品详情页
1
2
3
4
5
6
7
8
|
/**
* Is_product - Returns true when viewing a single product.
*
* @return bool
*/
function is_product() {
return is_singular( array( 'product' ) );
}
|
是否购物车页
1
2
3
4
5
6
7
8
9
10
|
/**
* Is_cart - Returns true when viewing the cart page.
*
* @return bool
*/
function is_cart() {
$page_id = wc_get_page_id( 'cart' );
return ( $page_id && is_page( $page_id ) ) || Constants::is_defined( 'WOOCOMMERCE_CART' ) || wc_post_content_has_shortcode( 'woocommerce_cart' );
}
|
是否是结算页
1
2
3
4
5
6
7
8
9
10
|
/**
* Is_checkout - Returns true when viewing the checkout page, or when processing AJAX requests for updating or processing the checkout.
*
* @return bool
*/
function is_checkout() {
$page_id = wc_get_page_id( 'checkout' );
return ( $page_id && is_page( $page_id ) ) || wc_post_content_has_shortcode( 'woocommerce_checkout' ) || apply_filters( 'woocommerce_is_checkout', false ) || Constants::is_defined( 'WOOCOMMERCE_CHECKOUT' );
}
|
是否是账户页
1
2
3
4
5
6
7
8
9
10
|
/**
* Is_account_page - Returns true when viewing an account page.
*
* @return bool
*/
function is_account_page() {
$page_id = wc_get_page_id( 'myaccount' );
return ( $page_id && is_page( $page_id ) ) || wc_post_content_has_shortcode( 'woocommerce_my_account' ) || apply_filters( 'woocommerce_is_account_page', false );
}
|
是否产品相关的分类方式归档页
包括产品分类、产品标签、产品属性等
1
2
3
4
5
6
7
8
|
/**
* Is_product_taxonomy - Returns true when viewing a product taxonomy archive.
*
* @return bool
*/
function is_product_taxonomy() {
return is_tax( get_object_taxonomies( 'product' ) );
}
|
更多条件标签
所有条件标签查看:plugins/woocommerce/includes/wc-conditional-functions.php
WCC短代码
短代码的执行
1
2
3
4
5
6
7
|
<?php if(have_posts()): ?>
<?php while(have_post()):the_post(); ?>
<?php global $post; ?>
<?php echo do_shortcode($post->content); ?>
<?php echo the_content();//the_content()里面自动解析了短代码 ?>
<?php endwhile; ?>
<?php endif; ?>
|
购物车页面短代码
[woocommerce_cart]
plugins/woocommerce/includes/class-wc-shortcodes.php
1
2
3
4
5
6
7
8
9
10
11
12
|
class WC_Shortcodes {
/**
* Cart page shortcode.
*
* @return string
*/
public static function cart() {
return is_null( WC()->cart ) ? '' : self::shortcode_wrapper( array( 'WC_Shortcode_Cart', 'output' ) );
}
}
|
结算页面短代码
[woocommerce_checkout]
plugins/woocommerce/includes/class-wc-shortcodes.php
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class WC_Shortcodes {
/**
* Checkout page shortcode.
*
* @param array $atts Attributes.
* @return string
*/
public static function checkout( $atts ) {
return self::shortcode_wrapper( array( 'WC_Shortcode_Checkout', 'output' ), $atts );
}
}
|
账户页面短代码
[woocommerce_my_account]
plugins/woocommerce/includes/class-wc-shortcodes.php
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class WC_Shortcodes {
/**
* My account page shortcode.
*
* @param array $atts Attributes.
* @return string
*/
public static function my_account( $atts ) {
return self::shortcode_wrapper( array( 'WC_Shortcode_My_Account', 'output' ), $atts );
}
}
|
输出notices
1
2
3
4
|
//打印所有notices
wc_print_notices();
//添加notice
wc_add_notice('hello world');
|
WCC主题开发
样式和脚本
1
2
3
4
5
6
|
// 1. 通过wp_register_script()和wp_register_style(),先注册脚本和样式
wp_register_script( $handle, $path, $deps, $version, $in_footer );
wp_register_style( $handle, $path, $deps, $version, $media );
// 2. 通过wp_enqueue_script($handle)和wp_enqueue_style($handle),调用已经注册好的脚本和样式
wp_enqueue_script( 'wc-add-to-cart-variation' );
|
移除WCC自带的样式和脚本
1
2
3
4
5
|
// 去除wcc自带的样式,__return_empty_array是wp自带的函数,返回空数组
add_filter('woocommerce_enqueue_styles', '__return_empty_array');
// 去除wcc自带的样式和脚本,load_scripts 里面执行了woocommerce_enqueue_styles过滤器钩子
remove_action( 'wp_enqueue_scripts', [ WC_Frontend_Scripts::class, 'load_scripts' ] );
|
声明支持WCC
1
2
3
4
|
add_action('after_setup_theme', function () {
//声明支持woocommerce
add_theme_support('woocommerce');
});
|
自主式主题开发
自己根据WCC的模板层级,通过自定义的查询和自定义CSS、js的方式实现自己的主题
覆盖式主题开发
在开发兼容WCC的主题时,首先考虑的不是要自己去写所有的模板,而是在WCC模板的基础上去修改。比如,去修改数据的输出结构等。把plugins/woocommerce/templates的指定的模板文件复制到当前主题/woocommerce目录下
重要函数
1
2
3
4
5
6
7
8
9
|
/**
* Get other templates (e.g. product attributes) passing attributes and including the file.
*
* @param string $template_name Template name.
* @param array $args Arguments. (default: array).
* @param string $template_path Template path. (default: '').
* @param string $default_path Default path. (default: '').
*/
function wc_get_template( $template_name, $args = array(), $template_path = '', $default_path = '' )
|
1
2
3
4
5
6
|
wc_get_template('cart/cart-item-data.php', [
'item_data' => $item_data
]);
//1. 先在当前主题的woocommerce目录中查找
//2. 然后再到plugins/woocommerce/templates目录中查找
|
1
2
3
4
5
6
7
8
9
|
/**
* Get template part (for templates like the shop-loop).
*
* WC_TEMPLATE_DEBUG_MODE will prevent overrides in themes from taking priority.
*
* @param mixed $slug Template slug.
* @param string $name Template name (default: '').
*/
function wc_get_template_part( $slug, $name = '' )
|
1
2
3
4
5
6
7
8
|
// 查找shop-product.php文件
wc_get_template_part('shop', 'product');
//1. 在当前主题目录中查找$slug-$name.php文件
//2. 在当前主题的woocommerce目录查找$slug-$name.php文件
//3. 在plugins/woocommerce/templates目录中查找$slug-$name.php
//4. 在当前主题的woocommerce目录查找$slug.php
//5. 在plugins/woocommerce/templates目录中查找$slug.php
|
主题开发要点串联
制作详情页顶部导航
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
/**
* 获取当前访问页面的url的方法
* 在主题的function.php定义,在模板文件中使用
*/
function get_curr_url() {
global $wp;
return get_home_url(null, $wp->request);
}
// 前台使用
$curr_url = get_curr_url();
$login_url = wp_login_url($curr_url);
<a href="<?php echo $login_url; ?>">登录</a>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
/**
* $pagename可选的值,如下:
* myaccount 我的账户页面
* shop 店铺
* cart 购物车
* checkout 结算
* terms 条款
*/
wc_get_page_permalink($pagename);
//我的账户页面
wc_get_page_permalink('myacount');
//购物车页面
wc_get_page_permalink('cart');
//我的账户页面的端点
//订单 orders
//查看订单 view-order
//下载 downloads
//编辑账户 edit-address
//地址 edit-address
|
商品搜索框
1
2
3
4
|
get_product_search_form($echo = true);
//复制woocommerce/templates/product-searchform.php到当前主题的woocommerce目录下
//修改product-searchform.php内容完成定制
|
面包屑导航
1
2
3
4
5
6
7
8
9
|
$args = [
'delimiter' => ' / ',
'wrap_before' => '<nav class="woocommerce-breadcrumb" aria-label="Breadcrumb">',
'wrap_after' => '</nav>',
'before' => '',
'after' => '',
'home' => '站点首页',
];
woocommerce_breadcrumb($args);
|
获取产品信息
1
|
the_post_thumbnail_url('shop_single');
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
//格式化价格 $16.90
wc_price($price);
//获取产品价格,可以设定数量和自定义价格
//$args可选参数,如不传递则返回一件产品的实际价格。如传递格式为['price' => 123, 'qty' => 2],意思是:获取2件产品的价格,每件为123元。
wc_get_price_to_display($product, $args = []);
//产品原价
$product->get_regular_price();
//产品促销价格
$product->get_sale_price();
//产品实际价格,如果有设置促销价格就显示促销价格,否则显示产原价
$product->get_price();
//综合应用
wc_price(wc_get_price_to_display($product));
|
1
2
3
4
5
6
7
8
9
|
/**
* @param $weigth 重量的数值
* @param $to_unit 转为什么单位 可取的值为 'g','kg','lbs','oz'
* @param $from_unit 转换前的单位,可选参数。不传递会自动获取WCC设置的默认重量单位
*/
wc_get_weight($weight, $to_unit, $from_unit = '');
//应用举例
wc_get_weight($product->get_weight(), 'g');
|
1
2
3
|
// 该方法调用的是woocommerce/templates/single-product-reviews.php
// 可以把single-product-reviews.php复制到当前主题woocommerce目录下
comments_template();
|
加入购物车
wcc默认方式
1
2
3
4
|
// 表单方式
woocommerce_template_single_add_to_cart();
// ajax方式
woocommerce_template_loop_add_to_cart();
|
自定义ajax方式
关键文件plugins/woocommerce/includes/class-wc-ajax.php
do_action( 'wc_ajax_' . $action )
根据$action参数动态触发钩子,可以用于自定义?wc-ajax=自定义动作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
/**
* Check for WC Ajax request and fire action.
*/
public static function do_wc_ajax() {
global $wp_query;
// phpcs:disable WordPress.Security.NonceVerification.Recommended
if ( ! empty( $_GET['wc-ajax'] ) ) {
$wp_query->set( 'wc-ajax', sanitize_text_field( wp_unslash( $_GET['wc-ajax'] ) ) );
}
$action = $wp_query->get( 'wc-ajax' );
if ( $action ) {
self::wc_ajax_headers();
$action = sanitize_text_field( $action );
do_action( 'wc_ajax_' . $action );
wp_die();
}
// phpcs:enable
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
<!-- WCC默认会向商品页面中增加JS脚本,这些脚本给我们提供了一些重要的数据。-->
<script>
console.log(wc_add_to_cart_params)
// 获取加入购物车的url
var ajax_url = wc_add_to_cart_params.wc_ajax_url.toString().replace('%%endpoint%%', 'add_to_cart');
// 通过ajax把数据提交到ajax_url
var params = {'product_id': 100, 'quantity': 2};
// $.post()发起请求
// 获取response数据
if (!response) {
return ;
}
//返回的数据中标明有错误时
if (response.error && response.product_url) {
window.location = response.product_url;
return ;
}
//如果后台设置了加入购物车后就跳转到购物车页面时
if (wc_add_to_cart_params.cart_redirect_after_add == 'yes') {
window.location = wc_add_to_cart_params.cart_url;
return ;
}
</script>
|
- 通过钩子
woocommerce_add_to_cart_fragments
扩展购物车产品数量字段
1
2
3
4
|
add_filter('woocommerce_add_to_cart_fragments', function ($return) {
$return['qty'] = WC()->cart->get_cart_contents_count();
return $return;
});
|
获取购物车中的产品数量
1
|
WC()->cart->get_cart_contents_count();
|
计算商品总价格
通过class-wc-ajax.php中do_action( 'wc_ajax_' . $action )
自定义一个action,如?wc-ajax=get_product_total_price
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
//在functions.php文件中添加以下方法
add_action('wc_ajax_get_product_total_price', function () {
$product_id = $_POST['product_id'];
$count = $_POST['count'];
$product = wc_get_product($product_id);
$total = wc_get_price_to_display($product, [
'qty' => $count
]);
$total = wc_price($total);
wp_send_json([
'total' => $total
]);
})
|
列表分页
1
|
woocommerce_pagination();
|
产品排序
1
|
woocommerce_catalog_ordering();
|
获取指定产品分类数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
$term_id = 19;
/* @var $term WP_Term */
$term = get_term($term_id, 'product_cat');
$term->name;
$term->slug;
$term->description;
$term_url = get_term_link($term);
//获取<img></img>格式的数据
woocommerce_subcategory_thumbnail($term);
//获取图片url
$term_thumbnail_id = get_term_meta($term_id, 'thumbnail_id', true);
$term_thumbnail_url = wp_get_attachment_image_url($term_thumbnail_id, 'thumbnail');
//通过自定义查询获取分类下的产品
$query = new WP_Query([
'post_type' => 'product',
'posts_per_page' => 4,
'tax_query' => [
'ralation' => 'AND',
[
'taxonomy' => 'product_visibility',
'field' => 'slug',
'terms' => ['exculde-from-catalog', 'outofstock'],
'operator' => 'NOT IN'
],
[
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => ['shuiguo']
]
]
]);
while ($query->have_posts()) {
$query->the_post();
//获取产品具体信息
}
|
WCC支付网关
woocommerce下单流程关键代码
1
2
3
4
5
6
7
8
9
10
|
woocommerce/includes/class-wc-ajax.php
do_wc_ajax() ===> do_action( 'wc_ajax_' . $action )
// 结算
checkout() ===> WC()->checkout()->process_checkout()
woocommerce/includes/class-wc-checkout.php
// 下单
process_checkout() ===> $this->process_order_payment( $order_id, $posted_data['payment_method'] )
// 获取支付网关中指定的支付方式,执行该支付方式的process_payment()方法
process_order_payment() ===> $available_gateways[ $payment_method ]->process_payment( $order_id )
|
woocommerce/includes/class-wc-ajax.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
/**
* Check for WC Ajax request and fire action.
*/
public static function do_wc_ajax() {
global $wp_query;
// phpcs:disable WordPress.Security.NonceVerification.Recommended
if ( ! empty( $_GET['wc-ajax'] ) ) {
$wp_query->set( 'wc-ajax', sanitize_text_field( wp_unslash( $_GET['wc-ajax'] ) ) );
}
$action = $wp_query->get( 'wc-ajax' );
if ( $action ) {
self::wc_ajax_headers();
$action = sanitize_text_field( $action );
do_action( 'wc_ajax_' . $action );//关键代码
wp_die();
}
// phpcs:enable
}
/**
* Process ajax checkout form.
*/
public static function checkout() {
wc_maybe_define_constant( 'WOOCOMMERCE_CHECKOUT', true );
WC()->checkout()->process_checkout();//关键代码
wp_die( 0 );
}
|
woocommerce/includes/class-wc-checkout.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
/**
* Process the checkout after the confirm order button is pressed.
*
* @throws Exception When validation fails.
*/
public function process_checkout() {
try {
$nonce_value = wc_get_var( $_REQUEST['woocommerce-process-checkout-nonce'], wc_get_var( $_REQUEST['_wpnonce'], '' ) ); // phpcs:ignore
$expiry_message = sprintf(
/* translators: %s: shop cart url */
__( 'Sorry, your session has expired. <a href="%s" class="wc-backward">Return to shop</a>', 'woocommerce' ),
esc_url( wc_get_page_permalink( 'shop' ) )
);
if ( empty( $nonce_value ) || ! wp_verify_nonce( $nonce_value, 'woocommerce-process_checkout' ) ) {
// If the cart is empty, the nonce check failed because of session expiry.
if ( WC()->cart->is_empty() ) {
throw new Exception( $expiry_message );
}
WC()->session->set( 'refresh_totals', true );
throw new Exception( __( 'We were unable to process your order, please try again.', 'woocommerce' ) );
}
wc_maybe_define_constant( 'WOOCOMMERCE_CHECKOUT', true );
wc_set_time_limit( 0 );
do_action( 'woocommerce_before_checkout_process' );
if ( WC()->cart->is_empty() ) {
throw new Exception( $expiry_message );
}
do_action( 'woocommerce_checkout_process' );
$errors = new WP_Error();
$posted_data = $this->get_posted_data();
// Update session for customer and totals.
$this->update_session( $posted_data );
// Validate posted data and cart items before proceeding.
$this->validate_checkout( $posted_data, $errors );
foreach ( $errors->errors as $code => $messages ) {
$data = $errors->get_error_data( $code );
foreach ( $messages as $message ) {
wc_add_notice( $message, 'error', $data );
}
}
if ( empty( $posted_data['woocommerce_checkout_update_totals'] ) && 0 === wc_notice_count( 'error' ) ) {
$this->process_customer( $posted_data );
$order_id = $this->create_order( $posted_data );
$order = wc_get_order( $order_id );
if ( is_wp_error( $order_id ) ) {
throw new Exception( $order_id->get_error_message() );
}
if ( ! $order ) {
throw new Exception( __( 'Unable to create order.', 'woocommerce' ) );
}
do_action( 'woocommerce_checkout_order_processed', $order_id, $posted_data, $order );
/**
* Note that woocommerce_cart_needs_payment is only used in
* WC_Checkout::process_checkout() to keep backwards compatibility.
* Use woocommerce_order_needs_payment instead.
*
* Note that at this point you can't rely on the Cart Object anymore,
* since it could be empty see:
* https://github.com/woocommerce/woocommerce/issues/24631
*/
if ( apply_filters( 'woocommerce_cart_needs_payment', $order->needs_payment(), WC()->cart ) ) {
$this->process_order_payment( $order_id, $posted_data['payment_method'] );//关键代码
} else {
$this->process_order_without_payment( $order_id );
}
}
} catch ( Exception $e ) {
wc_add_notice( $e->getMessage(), 'error' );
}
$this->send_ajax_failure_response();
}
/**
* Process an order that does require payment.
*
* @since 3.0.0
* @param int $order_id Order ID.
* @param string $payment_method Payment method.
*/
protected function process_order_payment( $order_id, $payment_method ) {
$available_gateways = WC()->payment_gateways->get_available_payment_gateways();
if ( ! isset( $available_gateways[ $payment_method ] ) ) {
return;
}
// Store Order ID in session so it can be re-used after payment failure.
WC()->session->set( 'order_awaiting_payment', $order_id );
// We save the session early because if the payment gateway hangs
// the request will never finish, thus the session data will neved be saved,
// and this can lead to duplicate orders if the user submits the order again.
WC()->session->save_data();
// Process Payment.
$result = $available_gateways[ $payment_method ]->process_payment( $order_id );//关键代码
// Redirect to success/confirmation/payment page.
if ( isset( $result['result'] ) && 'success' === $result['result'] ) {
$result['order_id'] = $order_id;
$result = apply_filters( 'woocommerce_payment_successful_result', $result, $order_id );
if ( ! wp_doing_ajax() ) {
// phpcs:ignore WordPress.Security.SafeRedirect.wp_redirect_wp_redirect
wp_redirect( $result['redirect'] );
exit;
}
wp_send_json( $result );
}
}
|
判断woocommerce是否启用
1
2
3
|
if (!in_array('woocommerce/woocommerce.php', get_option('active_plugins'))) {
return ;
}
|
告诉woocommerce新增的网关
1
2
3
4
|
add_filter('woocommerce_payment_gateways', function ($methods) {
$methods[] = 'WC_Gateway_Alipay';
return $methods;
});
|
必须调用的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
//在新增的网关类中调用$this->init_form_fields()、$this->init_settings()
// 实现init_form_fields方法
// 可以参考woocommerce/includes/gateways/paypal/settings-paypal.php
function init_form_fields() {
$this->form_fields = [
//是否启用当前的支付网关
'enabled' => [
'title' => '启用/禁用',
'type' => 'checkbox',
'label' => '是否启用支付宝网关,勾选为启用',
'default' => 'yes',
],
//当前支付网关的名称
'title' => [
'title' => '标题',
'type' => 'text',
'description' => '在结算时看到的当前支付网关的名称',
'default' => '支付宝',
'desc_tip' => true,
],
//当前支付网关的描述
'description' => [
'titile' => '描述',
'type' => 'text',
'desc_tip' => true,
'description' => '在结算时看到的当前支付网关的描述',
'default' => '将使用支付宝付款',
],
//以上三个字段是必须定义的
//下面可以定义一些当前支付网关的字段,如:app_id, mch_id
'app_id' => [
'titile' => 'app_id',
'type' => 'text',
'desc_tip' => true,
'description' => '支付宝APP ID',
'default' => '',
],
'mch_id' => [
'titile' => 'mch_id',
'type' => 'text',
'desc_tip' => true,
'description' => '支付宝商户ID',
'default' => '',
],
];
}
|
保存后台设置的数据
1
2
|
//在新增的网关类中挂载以下钩子
add_action('woocommerce_update_options_payment_gateways_' . $this->id, [$this, 'process_admin_options']);
|
异步回调
1
2
3
4
5
|
//异步通知地址。生成一个URL:域名/wc-api/WC_Gateway_Awxpay
$this->notify_url = WC()->api_request_url('WC_Gateway_Awxpay');
//异步退款通知地址。生成一个URL:域名/wc-api/WC_Gateway_Awxpay_Refund
$this->refund_notify_url = WC()->api_request_url('WC_Gateway_Awxpay_Refund');
|
1
2
3
4
5
6
7
8
9
10
|
//支付异步回调通知
//在plugins/woocommerce/includes/class-wc-api.php中的handle_api_requests()方法,处理了异步回调的请求,并且触发了对应的钩子。do_action( 'woocommerce_api_request', $api_request )和do_action( 'woocommerce_api_' . $api_request );;
add_action('woocommerce_api_wc_gateway_awxpay',array($this,'check_response'));
//退款异步回调通知
add_action('woocommerce_api_wc_gateway_awxpay_refund', array($this, 'refund_response'));
//订单完成时触发
add_action("woocommerce_order_status_completed",array($this, 'refund_order_trial_product'));
|