背景:使用Wordpress 做跨境电商,想要接入国内的物流公司API。实现实时计算物流价格。
如下图:
注意 get_shipping_rate_from_api 方法中的
// $this->save_local_post_json($response); //保存返回数据 我隐藏了,我调用的是锦联物流,这里只是举例,根据自己业务来更改。
其中 cost 就是物流的价格,通过物流api计算后的价格替换 cost 参数。
return array(
'id' => 'custom_shipping_rate',
'label' => 'Custom Shipping Rate',
'cost' => 50.00, // 示例费用
);
其中 save_local_post_json 方法用于查看联调数据,文件保存同目录下的post.json文件
把代码放入function.php 文件中
话不多说直接上代码都写备注了:
这家对接的物流公司只支持单个商品运费试算,多个的话我的计算方式是: 单个产品运费 * 产品数量
/**
* 自定义物流方式
* 首先在类的构造函数里定义运费的名称、描述、唯一ID等基本属性。
* 在init()函数里定义运费的选项,这些选项的值会被保存到wp_options表里,再获取用户填写的值。
* 在calculate_shipping()函数里实现运费计算的逻辑。
* sanitize_cost()是价格字段的过滤函数,可有可无。
*/
add_action('woocommerce_shipping_init', 'define_your_shipping_method');
add_filter('woocommerce_shipping_methods', 'add_your_shipping_method');
function define_your_shipping_method()
{
//定义运费名称、费用、计算运费方法等等的代码
class Your_Shipping_Method extends WC_Shipping_Method
{
/**
* Constructor.
*
* @param int $instance_id Shipping method instance.
*/
public function __construct($instance_id = 0)
{
$this->id = 'your_shipping_method';
$this->instance_id = absint($instance_id);
$this->method_title = 'Jinlian Logistics';
$this->method_description = '锦联物流描述信息,前台不可见';
// 让运费支持shipping zones,而不是单独显示出来
$this->supports = array(
'shipping-zones',
'instance-settings',
'instance-settings-modal',
);
$this->init();
add_action('woocommerce_update_options_shipping_' . $this->id, array($this, 'process_admin_options'));
}
/**
* Init user set variables.
*/
public function init()
{
// 定义选项字段
$this->instance_form_fields = array(
'title' => array(
'title' => __('Title', 'woocommerce'),
'type' => 'text',
'description' => __('This controls the title which the user sees during checkout.', 'woocommerce'),
'default' => $this->method_title,
'desc_tip' => true,
),
'cost' => array(
'title' => __('Cost', 'woocommerce'),
'type' => 'text',
'description' => '请输入价格',
'default' => '0',
'desc_tip' => true,
'sanitize_callback' => array($this, 'sanitize_cost'),
),
);
// 获取用户的选择
$this->title = $this->get_option('title');
$this->cost = $this->get_option('cost');
}
/**
* Calculate the shipping costs.
*
* @param array $package Package of items from cart.
*/
//运费计算逻辑
public function calculate_shipping($package = array())
{
// 调用第三方物流API接口,获取运输费用信息
$api_rate = $this->get_shipping_rate_from_api($package);
if ($api_rate !== false && isset($api_rate['cost']) && $api_rate['cost'] > 0) {
$rate = array(
'id' => $this->get_rate_id(),
'label' => $this->get_option('title'),
'cost' => $api_rate['cost'],
'package' => $package,
);
$this->add_rate($rate);
}
// $rate = array(
// 'id' => $this->get_rate_id(),
// 'label' => $this->get_option('title'), //标签
// 'cost' => $this->get_option('cost'), //成本
// 'package' => $package, //包裹信息
// );
// if ($rate['cost'] > 0) {
// $this->add_rate($rate);
// }
do_action('woocommerce_' . $this->id . '_shipping_add_rate', $this, $rate);
}
//调用三方物流接口
public function get_shipping_rate_from_api($package) {
// 使用第三方物流API发送请求并获取运输费用信息
// 这里是示例代码,您需要替换成实际的API请求代码
// 返回的数组应该包含'id'、'label'和'cost'等字段,与原始代码中的$rate数组格式相同
// 如果无法成功获取运输费用信息,返回false或空数组
// 设置请求参数
$product = null; //产品
$product_num = 1; //产品数量
$length = $width = $height = $weight = '';
if(isset($package['contents']) && $package['contents']){
$keys = array_keys($package['contents']);
$key = $keys[0];
$product_id = $package['contents'][$key]['product_id'];
$product = wc_get_product($product_id);
$product_num = $package['contents'][$key]['quantity'];
}
//计算产品的长宽高和重量
if($product){
$length = $product->get_length();
$width = $product->get_width();
$height = $product->get_height();
$weight = $product->get_weight();
}
$params = array(
'appToken' => '写你自己的',
'appKey' => '写你自己的',
'serviceMethod' => 'feetrail',
'paramsJson' => json_encode(array(
'country_code' => $package['destination']['country'],
'post_code'=>$package['destination']['postcode'],
'length'=> $length ? round($length/10,2) : '',
'width' => $width ? round($width/10,2) : '',
'height'=> $height ? round($height/10,2) : '',
'weight' => $weight,
))
);
// 第三方接口的URL
$url = 'http://ywjl.rtb56.com/webservice/PublicService.asmx/ServiceInterfaceUTF8'; // 第三方接口URL
// 发送请求并获取响应
$response = $this->send_post_request_to_third_party($url, $params);
if($response['code'] ==200){
//处理数据: 优先可跟踪物流,其次价格最低
$body_data = json_decode($response['body'],true);
if(isset($body_data['success']) && $body_data['success'] == 1){
$data_traceability = $body_data['data'];
if($data_traceability){
$traceability = []; //获取Traceability==Y的 支持物流跟踪
foreach ($data_traceability as $key => $value) {
if($value['Traceability'] == 'Y'){
$traceability[] = $value;
}
}
//如果都不支持物流跟踪处理,直接选择价格最低的。
if(!$traceability){
$final_data = $this->totalfee_orderby($data_traceability);
}else{
$final_data = $this->totalfee_orderby($traceability);
}
}
}
}
//汇率价格美元 7.24
$price = $final_data ? $final_data['TotalFee'] : 0;
if($price >0){
$price = round($price/7.24,2);
}
return array(
// 'id' => 'custom_shipping_rate',
'cost' => $price*$product_num, // 示例费用
);
}
/**
* Sanitize the cost field.
*
*/
public function sanitize_cost($value)
{
$value = is_null($value) ? '' : $value;
$value = wp_kses_post(trim(wp_unslash($value)));
$value = str_replace(array(get_woocommerce_currency_symbol(), html_entity_decode(get_woocommerce_currency_symbol())), '', $value);
return $value;
}
/**
* 发送POST请求到第三方接口
*
* @param string $url 接口URL
* @param array $params 请求参数
* @return array|WP_Error 接口返回的数据或错误对象
*/
public function send_post_request_to_third_party($url, $params) {
$response = wp_remote_post($url, array(
'method' => 'POST',
'timeout' => 45, // 设置超时时间
'redirection' => 5, // 设置重定向次数
'httpversion' => '1.1',
'blocking' => true,
'headers' => array(
'Content-Type' => 'application/x-www-form-urlencoded; charset=' . get_option('blog_charset'),
),
'body' => http_build_query($params), // 使用http_build_query将参数数组转换为查询字符串
'cookies' => array()
));
// 检查请求是否成功
if (is_wp_error($response)) {
// 请求失败,处理错误
$error_message = $response->get_error_message();
// 可以在这里记录错误日志或者进行其他错误处理
$this->save_local_post_json($error_message); //记录错误日志
// return $response; // 返回错误对象
return array(
'code' => 500,
'body' => $response,
);
} else {
// 请求成功,返回响应数据
$response_code = wp_remote_retrieve_response_code($response);
$response_body = wp_remote_retrieve_body($response);
// 可以在这里进一步处理响应数据,比如解析JSON等
return array(
'code' => $response_code,
'body' => $response_body,
);
}
}
/**
* 保存到本地数据
*/
public function save_local_post_json($data){
// 指定文件路径
$file_path = __DIR__ . '/post.json';
// 初始化一个数组来存储要保存的数据
$saved_data = [];
// 将当前时间戳添加到数据中
// $data['saved_at'] = date('Y-m-d H:i:s');
// 将新数据添加到数组中
$saved_data[] = $data;
// 将数据编码为 JSON 字符串
$json_data = json_encode($saved_data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
// 读取原文件内容
$file_content = '';
if (file_exists($file_path)) {
$file_content = file_get_contents($file_path);
$file_content = rtrim($file_content, ",\n"); // 去除末尾可能存在的逗号和换行符
$file_content .= ",\n"; // 添加新的记录前的逗号和换行符
}
// 写入文件
$json_data .= date('Y-m-d H:i:s').",\n";
$json_data .= $file_content;
$success = file_put_contents($file_path, $json_data);
if ($success) {
// 数据已成功保存
return true;
} else {
// 保存 post.json 文件时出错
// return false;
}
}
/**
* 筛选出价格最低的物流
*/
public function totalfee_orderby($arrays = []){
// 初始化最低值和对应数组
$minValue = PHP_INT_MAX;
$minArray = null;
// 遍历二维数组
foreach ($arrays as $array) {
// 检查当前数组中的 'value' 是否比已知的最低值还低
if ($array['TotalFee'] < $minValue) {
// 更新最低值和对应数组
$minValue = $array['TotalFee'];
$minArray = $array;
}
}
return $minArray;
}
}
}
function add_your_shipping_method($methods)
{
$methods['your_shipping_method'] = 'Your_Shipping_Method';
return $methods;
}
/**
* 自定义物流方式 end
*/
参考文章:WooCommerce创建Shipping方法详解(2022) - sola博客 (solagirl.net)