Version Description
- Fix known issue
Download this release
Release Info
Developer | aftership |
Plugin | AfterShip – WooCommerce Tracking |
Version | 1.9.20 |
Comparing to | |
See all releases |
Code changes from version 1.9.19 to 1.9.20
- .gitignore +26 -0
- aftership.php +1 -1
- api/class-aftership-api-v2-json-handler.php +129 -0
- api/class-aftership-api-v2-orders.php +424 -0
- readme.txt +11 -40
.gitignore
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# =============== RubyMine.gitignore
|
2 |
+
# =============== PhPStorm.gitignore
|
3 |
+
.idea
|
4 |
+
dump.rdb
|
5 |
+
|
6 |
+
|
7 |
+
# =============== OSX.gitignore
|
8 |
+
.DS_Store
|
9 |
+
.AppleDouble
|
10 |
+
.LSOverride
|
11 |
+
|
12 |
+
# Thumbnails
|
13 |
+
._*
|
14 |
+
|
15 |
+
# =============== # Windows image file caches
|
16 |
+
Thumbs.db
|
17 |
+
ehthumbs.db
|
18 |
+
|
19 |
+
# Folder config file
|
20 |
+
Desktop.ini
|
21 |
+
|
22 |
+
# Recycle Bin used on file shares
|
23 |
+
$RECYCLE.BIN/
|
24 |
+
|
25 |
+
# Except the .htpassed
|
26 |
+
!.htpasswd
|
aftership.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
Plugin Name: AfterShip - WooCommerce Tracking
|
4 |
Plugin URI: http://aftership.com/
|
5 |
Description: Add tracking number and carrier name to WooCommerce, display tracking info at order history page, auto import tracking numbers to AfterShip.
|
6 |
-
Version: 1.9.
|
7 |
Author: AfterShip
|
8 |
Author URI: http://aftership.com
|
9 |
|
3 |
Plugin Name: AfterShip - WooCommerce Tracking
|
4 |
Plugin URI: http://aftership.com/
|
5 |
Description: Add tracking number and carrier name to WooCommerce, display tracking info at order history page, auto import tracking numbers to AfterShip.
|
6 |
+
Version: 1.9.20
|
7 |
Author: AfterShip
|
8 |
Author URI: http://aftership.com
|
9 |
|
api/class-aftership-api-v2-json-handler.php
ADDED
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* AfterShip API
|
4 |
+
*
|
5 |
+
* Handles parsing JSON request bodies and generating JSON responses
|
6 |
+
*
|
7 |
+
* @author AfterShip
|
8 |
+
* @category API
|
9 |
+
* @package AfterShip/API
|
10 |
+
* @since 1.0
|
11 |
+
*/
|
12 |
+
|
13 |
+
if (!defined('ABSPATH')) {
|
14 |
+
exit;
|
15 |
+
} // Exit if accessed directly
|
16 |
+
|
17 |
+
class AfterShip_API_V2_JSON_Handler implements AfterShip_API_Handler
|
18 |
+
{
|
19 |
+
/**
|
20 |
+
* Get the content type for the response
|
21 |
+
*
|
22 |
+
* @return string
|
23 |
+
* @since 2.1
|
24 |
+
*/
|
25 |
+
public function get_content_type()
|
26 |
+
{
|
27 |
+
return 'application/json; charset=' . get_option('blog_charset');
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Parse the raw request body entity
|
32 |
+
*
|
33 |
+
* @param string $body the raw request body
|
34 |
+
*
|
35 |
+
* @return array|mixed
|
36 |
+
* @since 2.1
|
37 |
+
*
|
38 |
+
*/
|
39 |
+
public function parse_body($body)
|
40 |
+
{
|
41 |
+
return json_decode($body, true);
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Generate a JSON response given an array of data
|
46 |
+
*
|
47 |
+
* @param array $data the response data
|
48 |
+
*
|
49 |
+
* @return string
|
50 |
+
* @since 2.1
|
51 |
+
*
|
52 |
+
*/
|
53 |
+
public function generate_response($data)
|
54 |
+
{
|
55 |
+
if (isset($_GET['_jsonp'])) {
|
56 |
+
// JSONP enabled by default
|
57 |
+
if (!apply_filters('aftership_api_jsonp_enabled', true)) {
|
58 |
+
|
59 |
+
WC()->api->server->send_status(400);
|
60 |
+
|
61 |
+
$data = [
|
62 |
+
[
|
63 |
+
'code' => 'aftership_api_jsonp_disabled',
|
64 |
+
'message' => __('JSONP support is disabled on this site', 'aftership')
|
65 |
+
]
|
66 |
+
];
|
67 |
+
}
|
68 |
+
|
69 |
+
// Check for invalid characters (only alphanumeric allowed)
|
70 |
+
if (preg_match('/\W/', $_GET['_jsonp'])) {
|
71 |
+
|
72 |
+
WC()->api->server->send_status(400);
|
73 |
+
|
74 |
+
$data = [
|
75 |
+
[
|
76 |
+
'code' => 'aftership_api_jsonp_callback_invalid',
|
77 |
+
__('The JSONP callback function is invalid', 'aftership')
|
78 |
+
]
|
79 |
+
];
|
80 |
+
}
|
81 |
+
|
82 |
+
return $_GET['_jsonp'] . '(' . json_encode($data) . ')';
|
83 |
+
}
|
84 |
+
|
85 |
+
$ok = [
|
86 |
+
'meta' => [
|
87 |
+
'code' => 20000,
|
88 |
+
'type' => 'OK',
|
89 |
+
'message' => 'Everything worked as expected'
|
90 |
+
],
|
91 |
+
'data' => $data
|
92 |
+
];
|
93 |
+
|
94 |
+
if (isset($data['errors'])) {
|
95 |
+
$error = [
|
96 |
+
'meta' => [
|
97 |
+
'code' => $this->map_error_code($data['errors'][0]['code']),
|
98 |
+
'type' => $data['errors'][0]['code'],
|
99 |
+
'message' => $data['errors'][0]['message'],
|
100 |
+
|
101 |
+
],
|
102 |
+
'data' => '{}'
|
103 |
+
];
|
104 |
+
return json_encode($error);
|
105 |
+
}
|
106 |
+
|
107 |
+
|
108 |
+
return json_encode($ok);
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* get error code by error message
|
113 |
+
* @param $code_text
|
114 |
+
* @return int
|
115 |
+
*/
|
116 |
+
private function map_error_code($code_text)
|
117 |
+
{
|
118 |
+
$code = 40010;
|
119 |
+
switch ($code_text) {
|
120 |
+
case 'aftership_api_disabled':
|
121 |
+
$code = 400011;
|
122 |
+
break;
|
123 |
+
default:
|
124 |
+
break;
|
125 |
+
}
|
126 |
+
|
127 |
+
return $code;
|
128 |
+
}
|
129 |
+
}
|
api/class-aftership-api-v2-orders.php
ADDED
@@ -0,0 +1,424 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* AfterShip API Orders Class
|
4 |
+
*
|
5 |
+
* Handles requests to the /orders endpoint
|
6 |
+
*
|
7 |
+
* @author AfterShip
|
8 |
+
* @category API
|
9 |
+
* @package AfterShip/API
|
10 |
+
* @since 1.0
|
11 |
+
*/
|
12 |
+
|
13 |
+
if (!defined('ABSPATH')) {
|
14 |
+
exit;
|
15 |
+
} // Exit if accessed directly
|
16 |
+
|
17 |
+
class AfterShip_API_V2_Orders extends AfterShip_API_Resource
|
18 |
+
{
|
19 |
+
|
20 |
+
/** @var string $base the route base */
|
21 |
+
protected $base = '/v2/orders';
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Register the routes for this class
|
25 |
+
*
|
26 |
+
* GET /orders
|
27 |
+
*
|
28 |
+
* @param array $routes
|
29 |
+
*
|
30 |
+
* @return array
|
31 |
+
* @since 2.1
|
32 |
+
*
|
33 |
+
*/
|
34 |
+
public function register_routes($routes)
|
35 |
+
{
|
36 |
+
# GET /orders/ping
|
37 |
+
$routes[$this->base . '/ping'] = [
|
38 |
+
[[$this, 'ping'], AfterShip_API_Server::READABLE],
|
39 |
+
];
|
40 |
+
|
41 |
+
# GET /orders
|
42 |
+
$routes[$this->base] = [
|
43 |
+
[[$this, 'get_orders'], AfterShip_API_Server::READABLE]
|
44 |
+
];
|
45 |
+
|
46 |
+
# GET /orders/:id
|
47 |
+
$routes[$this->base . '/(?P<id>[\d]+)'] = [
|
48 |
+
[[$this, 'get_order'], AfterShip_API_Server::READABLE],
|
49 |
+
];
|
50 |
+
|
51 |
+
return $routes;
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* heath checkendpoint for wordpress url validation
|
56 |
+
*
|
57 |
+
* @return string
|
58 |
+
* @since 2.1
|
59 |
+
*/
|
60 |
+
public function ping()
|
61 |
+
{
|
62 |
+
return 'pong';
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Get orders
|
67 |
+
*
|
68 |
+
* @param string $updated_at_min
|
69 |
+
* @param string $updated_at_max
|
70 |
+
* @param string $max_results_number
|
71 |
+
*
|
72 |
+
* @return array
|
73 |
+
* @throws Exception
|
74 |
+
* @since 2.1
|
75 |
+
*
|
76 |
+
*/
|
77 |
+
public function get_orders($updated_at_min = null, $updated_at_max = null, $max_results_number = null)
|
78 |
+
{
|
79 |
+
$args = [
|
80 |
+
'updated_at_min' => $updated_at_min,
|
81 |
+
'updated_at_max' => $updated_at_max,
|
82 |
+
'orderby' => 'modified',
|
83 |
+
'order' => 'ASC',
|
84 |
+
'limit' => $max_results_number,
|
85 |
+
'page' => !empty($_GET['page']) && intval($_GET['page']) > 1 ? absint($_GET['page']) : 1
|
86 |
+
];
|
87 |
+
|
88 |
+
$query = $this->query_orders($args);
|
89 |
+
|
90 |
+
//define pagination
|
91 |
+
$pagination = [
|
92 |
+
'page' => $query->query['paged'],
|
93 |
+
'limit' => intval($query->query['posts_per_page']),
|
94 |
+
'total' => intval($query->found_posts)
|
95 |
+
];
|
96 |
+
|
97 |
+
$orders = [];
|
98 |
+
foreach ($query->posts as $order_id) {
|
99 |
+
if (!$this->is_readable($order_id)) {
|
100 |
+
continue;
|
101 |
+
}
|
102 |
+
$orders[] = $this->get_order($order_id);
|
103 |
+
}
|
104 |
+
|
105 |
+
return ['orders' => $orders, 'pagination' => $pagination];
|
106 |
+
}
|
107 |
+
|
108 |
+
/**
|
109 |
+
* get single order by id
|
110 |
+
* @param $id
|
111 |
+
* @return array|int|WP_Error
|
112 |
+
* @throws Exception
|
113 |
+
*/
|
114 |
+
public function get_order($id)
|
115 |
+
{
|
116 |
+
$weight_unit = get_option('woocommerce_weight_unit');
|
117 |
+
// ensure order ID is valid & user has permission to read
|
118 |
+
$id = $this->validate_request($id, 'shop_order', 'read');
|
119 |
+
if (is_wp_error($id)) {
|
120 |
+
return $id;
|
121 |
+
}
|
122 |
+
$order = new WC_Order($id);
|
123 |
+
$customer = new WC_Customer($order->get_customer_id());
|
124 |
+
$current_shipping_method = current($order->get_shipping_methods());
|
125 |
+
$shipping_method = null;
|
126 |
+
if($current_shipping_method['method_id'] && $current_shipping_method['name']) {
|
127 |
+
$shipping_method = [
|
128 |
+
'code' => $current_shipping_method['method_id'],
|
129 |
+
'name' => $current_shipping_method['name'],
|
130 |
+
];
|
131 |
+
}
|
132 |
+
$order_data = [
|
133 |
+
'id' => (string)$order->get_id(),
|
134 |
+
'order_number' => $order->get_order_number(),
|
135 |
+
'order_name' => $order->get_order_number(),
|
136 |
+
'taxes_included' => ($order->get_total_tax() > 0),
|
137 |
+
'shipping_method' => $shipping_method,
|
138 |
+
'order_total' => [
|
139 |
+
'currency' => $order->get_currency(),
|
140 |
+
'amount' => (float)wc_format_decimal($order->get_total(), 2),
|
141 |
+
],
|
142 |
+
'note' => $order->get_customer_note(),
|
143 |
+
'locale' => get_locale(),
|
144 |
+
'metrics' => [
|
145 |
+
'placed_at' => $this->server->format_datetime($order->get_date_created()),
|
146 |
+
'updated_at' => $this->server->format_datetime($order->get_date_modified()),
|
147 |
+
'fully_shipped_at' => null,
|
148 |
+
'expected_earliest_delivery_at' => null,
|
149 |
+
'expected_last_delivery_at' => null,
|
150 |
+
],
|
151 |
+
'customer' => [
|
152 |
+
'id' => (string)$order->get_customer_id(),
|
153 |
+
'first_name' => $customer->get_first_name(),
|
154 |
+
'last_name' => $customer->get_last_name(),
|
155 |
+
'emails' => ($customer->get_email()) ? [$customer->get_email()] : [],
|
156 |
+
'phones' => ($customer->get_billing_phone()) ? [[
|
157 |
+
'country_code' => null,
|
158 |
+
'number' => $customer->get_billing_phone()
|
159 |
+
]] : [],
|
160 |
+
],
|
161 |
+
'shipping_address' => [
|
162 |
+
'first_name' => $order->get_shipping_first_name(),
|
163 |
+
'last_name' => $order->get_shipping_last_name(),
|
164 |
+
'company' => $order->get_shipping_company(),
|
165 |
+
'address_line_1' => $order->get_shipping_address_1(),
|
166 |
+
'address_line_2' => $order->get_shipping_address_2(),
|
167 |
+
'city' => $order->get_shipping_city(),
|
168 |
+
'state' => $order->get_shipping_state(),
|
169 |
+
'country' => $this->server->convert_country_code($order->get_shipping_country()),
|
170 |
+
'postal_code' => $order->get_shipping_postcode(),
|
171 |
+
'email' => $order->get_billing_email(),
|
172 |
+
'phone' => [
|
173 |
+
'country_code' => null,
|
174 |
+
'number' => $order->get_billing_phone()
|
175 |
+
],
|
176 |
+
'address_type' => null,
|
177 |
+
'tax_number' => null,
|
178 |
+
],
|
179 |
+
'billing_address' => array(
|
180 |
+
'first_name' => $order->get_billing_first_name(),
|
181 |
+
'last_name' => $order->get_billing_last_name(),
|
182 |
+
'company' => $order->get_billing_company(),
|
183 |
+
'address_line_1' => $order->get_billing_address_1(),
|
184 |
+
'address_line_2' => $order->get_billing_address_2(),
|
185 |
+
'city' => $order->get_billing_city(),
|
186 |
+
'state' => $order->get_billing_state(),
|
187 |
+
'postal_code' => $order->get_billing_postcode(),
|
188 |
+
'country' => $this->server->convert_country_code($order->get_billing_country()),
|
189 |
+
'email' => $order->get_billing_email(),
|
190 |
+
'phone' => [
|
191 |
+
'country_code' => null,
|
192 |
+
'number' => $order->get_billing_phone()
|
193 |
+
],
|
194 |
+
'address_type' => null,
|
195 |
+
'tax_number' => null,
|
196 |
+
),
|
197 |
+
'status' => $order->get_status(),
|
198 |
+
'items' => [],
|
199 |
+
'trackings' => []
|
200 |
+
];
|
201 |
+
|
202 |
+
|
203 |
+
// add line items
|
204 |
+
foreach ($order->get_items() as $item_id => $item) {
|
205 |
+
if (is_callable($item, 'get_product')) {
|
206 |
+
$product = $item->get_product();
|
207 |
+
} else {
|
208 |
+
$product = $order->get_product_from_item($item);
|
209 |
+
}
|
210 |
+
if (empty($product)) continue;
|
211 |
+
$weight = $product->get_weight();
|
212 |
+
$product_id = (isset($product->variation_id)) ? $product->variation_id : $product->get_id();
|
213 |
+
// set the response object
|
214 |
+
$terms_tags = get_the_terms($product_id, 'product_tag');
|
215 |
+
$product_tags = [];
|
216 |
+
foreach ($terms_tags as $termsKey => $termsVal) {
|
217 |
+
$product_tags[] = $termsVal->name;
|
218 |
+
}
|
219 |
+
$product_categories = [];
|
220 |
+
|
221 |
+
$categories = get_the_terms($product_id, 'product_cat');
|
222 |
+
foreach ($categories as $categoriesKey => $categoriesVal) {
|
223 |
+
$product_categories[] = $categoriesVal->name;
|
224 |
+
}
|
225 |
+
$order_data['items'][] = [
|
226 |
+
'id' => (string)$item_id,
|
227 |
+
'product_id' => (string)$product_id,
|
228 |
+
'sku' => is_object($product) ? $product->get_sku() : null,
|
229 |
+
'title' => $item['name'],
|
230 |
+
'quantity' => (int)$item['qty'],
|
231 |
+
'returnable_quantity' => (int)($item['qty'] - $order->get_qty_refunded_for_item($item_id)),
|
232 |
+
|
233 |
+
'unit_weight' => [
|
234 |
+
'unit' => $weight_unit,
|
235 |
+
'value' => (float)$weight,
|
236 |
+
],
|
237 |
+
'unit_price' => [
|
238 |
+
'currency' => $order->get_currency(),
|
239 |
+
'amount' => (float)wc_format_decimal($order->get_item_total($item), 2),
|
240 |
+
],
|
241 |
+
'discount' => null,
|
242 |
+
'image_urls' => wp_get_attachment_url($product->image_id) ? [wp_get_attachment_url($product->image_id)] : [],
|
243 |
+
'tags' => $product_tags,
|
244 |
+
'categories' => $product_categories,
|
245 |
+
];
|
246 |
+
}
|
247 |
+
|
248 |
+
// tracking field will be
|
249 |
+
/*
|
250 |
+
{
|
251 |
+
tracking_number: fulfillment.tracking_number,
|
252 |
+
slug: mapped_slug,
|
253 |
+
additional_fields: {
|
254 |
+
account_number: null,
|
255 |
+
key: null,
|
256 |
+
postal_code: (data.shipping_address && data.shipping_address.zip) ? data.shipping_address.zip : null,
|
257 |
+
ship_date: moment(fulfillment.updated_at).utcOffset('+0000').format('YYYYMMDD'),
|
258 |
+
state: null,
|
259 |
+
origin_country: null,
|
260 |
+
destination_country: (data.shipping_address && data.shipping_address.country_code) ? beautifyAddress({country: data.shipping_address.country_code}).country_iso3 : null,
|
261 |
+
},
|
262 |
+
}
|
263 |
+
*/
|
264 |
+
|
265 |
+
$trackings = [];
|
266 |
+
//The function definition will be available after installing the aftership plugin.
|
267 |
+
if(function_exists('order_post_meta_getter')) {
|
268 |
+
$aftership_tracking_number = order_post_meta_getter($order, 'aftership_tracking_number');
|
269 |
+
if (!empty($aftership_tracking_number)) {
|
270 |
+
$trackings[] = [
|
271 |
+
'slug' => order_post_meta_getter($order, 'aftership_tracking_provider'),
|
272 |
+
'tracking_number' => $aftership_tracking_number,
|
273 |
+
'additional_fields' => [
|
274 |
+
'postal_code' => order_post_meta_getter($order, 'aftership_tracking_postal'),
|
275 |
+
],
|
276 |
+
];
|
277 |
+
}
|
278 |
+
|
279 |
+
// 兼容 woocommerce 官方的 tracking 插件
|
280 |
+
$woocommerce_tracking_arr = order_post_meta_getter($order, 'wc_shipment_tracking_items');
|
281 |
+
if (empty($aftership_tracking_number) && !empty($woocommerce_tracking_arr)) {
|
282 |
+
foreach ($woocommerce_tracking_arr as $trackingKey => $trackingVal) {
|
283 |
+
$trackingArr = $this->getTrackingInfoByShipmentTracking($trackingVal);
|
284 |
+
if (!empty($trackingArr)) {
|
285 |
+
$trackings[] = [
|
286 |
+
'slug' => $trackingArr['tracking_provider'],
|
287 |
+
'tracking_number' => $trackingVal["tracking_number"],
|
288 |
+
'additional_fields' => [
|
289 |
+
'postal_code' => $trackingArr['tracking_postal_code'],
|
290 |
+
],
|
291 |
+
];
|
292 |
+
} else {
|
293 |
+
$trackings[] = [
|
294 |
+
'slug' => $trackingVal["tracking_provider"],
|
295 |
+
'tracking_number' =>$trackingVal["tracking_number"],
|
296 |
+
'additional_fields'=> [
|
297 |
+
'postal_code' => null,
|
298 |
+
]
|
299 |
+
];
|
300 |
+
}
|
301 |
+
}
|
302 |
+
}
|
303 |
+
$order_data['trackings'] = $trackings;
|
304 |
+
}
|
305 |
+
|
306 |
+
return $order_data;
|
307 |
+
}
|
308 |
+
|
309 |
+
/**
|
310 |
+
* 从wc ShipmentTracking 插件获取 Postalcode - postnl
|
311 |
+
* @param $tracking_items
|
312 |
+
* @return array
|
313 |
+
*/
|
314 |
+
private function getTrackingInfoByShipmentTracking($tracking_items)
|
315 |
+
{
|
316 |
+
if (!isset($tracking_items['custom_tracking_link'])) {
|
317 |
+
return array();
|
318 |
+
}
|
319 |
+
|
320 |
+
// 获取 postnl Postalcode
|
321 |
+
$urlArr = parse_url(stripslashes($tracking_items['custom_tracking_link']));
|
322 |
+
|
323 |
+
if ($urlArr === false) {
|
324 |
+
return array();
|
325 |
+
}
|
326 |
+
|
327 |
+
if (!isset($urlArr['host'])) {
|
328 |
+
return array();
|
329 |
+
}
|
330 |
+
|
331 |
+
$hostArr = explode(".", $urlArr['host']);
|
332 |
+
$hostArrIndex = count($hostArr) - 2;
|
333 |
+
if (empty($hostArr) || !isset($hostArr[$hostArrIndex])) {
|
334 |
+
return array();
|
335 |
+
}
|
336 |
+
|
337 |
+
if ($hostArr[$hostArrIndex] == 'postnl') {
|
338 |
+
parse_str($urlArr['query'], $queryArr);
|
339 |
+
if (!isset($queryArr['Postalcode'])) {
|
340 |
+
return array();
|
341 |
+
}
|
342 |
+
|
343 |
+
return array(
|
344 |
+
'tracking_provider' => 'postnl',
|
345 |
+
'tracking_postal_code' => str_replace(" ", "", $queryArr['Postalcode']),
|
346 |
+
);
|
347 |
+
}
|
348 |
+
return array();
|
349 |
+
}
|
350 |
+
|
351 |
+
|
352 |
+
/**
|
353 |
+
* Helper method to get order post objects
|
354 |
+
*
|
355 |
+
* @param array $args request arguments for filtering query
|
356 |
+
*
|
357 |
+
* @return WP_Query
|
358 |
+
* @since 2.1
|
359 |
+
*
|
360 |
+
*/
|
361 |
+
private function query_orders($args)
|
362 |
+
{
|
363 |
+
|
364 |
+
function aftership_wpbo_get_woo_version_number()
|
365 |
+
{
|
366 |
+
// If get_plugins() isn't available, require it
|
367 |
+
if (!function_exists('get_plugins'))
|
368 |
+
require_once(ABSPATH . 'wp-admin/includes/plugin.php');
|
369 |
+
|
370 |
+
// Create the plugins folder and file variables
|
371 |
+
$plugin_folder = get_plugins('/' . 'woocommerce');
|
372 |
+
$plugin_file = 'woocommerce.php';
|
373 |
+
|
374 |
+
// If the plugin version number is set, return it
|
375 |
+
if (isset($plugin_folder[$plugin_file]['Version'])) {
|
376 |
+
return $plugin_folder[$plugin_file]['Version'];
|
377 |
+
|
378 |
+
} else {
|
379 |
+
// Otherwise return null
|
380 |
+
return NULL;
|
381 |
+
}
|
382 |
+
}
|
383 |
+
|
384 |
+
$woo_version = aftership_wpbo_get_woo_version_number();
|
385 |
+
|
386 |
+
if ($woo_version >= 2.2) {
|
387 |
+
// set base query arguments
|
388 |
+
$query_args = array(
|
389 |
+
'fields' => 'ids',
|
390 |
+
'post_type' => 'shop_order',
|
391 |
+
// 'post_status' => 'publish',
|
392 |
+
'post_status' => array_keys(wc_get_order_statuses())
|
393 |
+
);
|
394 |
+
} else {
|
395 |
+
// set base query arguments
|
396 |
+
$query_args = array(
|
397 |
+
'fields' => 'ids',
|
398 |
+
'post_type' => 'shop_order',
|
399 |
+
'post_status' => 'publish',
|
400 |
+
);
|
401 |
+
}
|
402 |
+
|
403 |
+
// add status argument
|
404 |
+
if (!empty($args['status'])) {
|
405 |
+
|
406 |
+
$statuses = explode(',', $args['status']);
|
407 |
+
|
408 |
+
$query_args['tax_query'] = array(
|
409 |
+
array(
|
410 |
+
'taxonomy' => 'shop_order_status',
|
411 |
+
'field' => 'slug',
|
412 |
+
'terms' => $statuses,
|
413 |
+
),
|
414 |
+
);
|
415 |
+
|
416 |
+
unset($args['status']);
|
417 |
+
}
|
418 |
+
|
419 |
+
$query_args = $this->merge_query_args($query_args, $args);
|
420 |
+
|
421 |
+
return new WP_Query($query_args);
|
422 |
+
}
|
423 |
+
|
424 |
+
}
|
readme.txt
CHANGED
@@ -1,70 +1,41 @@
|
|
1 |
=== Plugin Name ===
|
2 |
Contributors: aftership
|
3 |
Donate link: https://www.aftership.com/
|
4 |
-
Tags: shipping, tracking, ups, usps, fedex, dhl, tnt, dpd, post, shipment
|
5 |
Requires at least: 2.9
|
6 |
Tested up to: 5.2.1
|
7 |
-
Stable tag: 1.9.
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
11 |
-
Auto import all your
|
|
|
12 |
|
13 |
== Description ==
|
14 |
|
15 |
###Top Shipment Tracking Plugin (Free)
|
16 |
-
|
17 |
-
By installing AfterShip - Shipment tracking plugin for WordPress, you can automatically add Tracking Number and Courier fields to your admin panel. After you fulfill an order, simply enter the order tracking number and select a courier at WooCommerce, the same info will be displayed at customer’s order history page. AfterShip supports over 657+ carriers worldwide, you can select couriers by [signing up a free AfterShip account](https://secure.aftership.com/signup).
|
18 |
-
|
19 |
|
20 |
###Display tracking info at order history page (Free)
|
|
|
21 |
|
22 |
-
|
23 |
-
|
24 |
-
###Support 668+ International Courier (Free)
|
25 |
-
|
26 |
-
AfterShip supports UPS tracking, FedEx tracking, USPS tracking, DHL tracking and shipment tracking of over 668+ carriers worldwide. Please scroll down to see the full list of our supported carriers.
|
27 |
|
28 |
|
29 |
###Track all shipments in one place (Free)
|
30 |
By setting up an auto import of tracking numbers to AfterShip, you can get the latest tracking info of all your shipments in one place. Each free account comes with a Dashboard to monitor current statuses of all shipments. You can also filter your shipments by dates, statuses, couriers and destination. Find out if all your shipments are delivered on time and discover any exceptions. Support [WooCommerce Shipment Tracking Plugin](http://www.woothemes.com/products/shipment-tracking/) as well.
|
31 |
|
32 |
-
|
33 |
###Branded Tracking Page (Free)
|
34 |
|
35 |
AfterShip automatically generates a tracking page for each shipment. Customize tracking page by adding your brand logo, store URL and Instagram pictures to improve SEO and generate more sales. You can also embed the [AfterShip Track Button](http://support.aftership.com/article/111-how-can-i-add-track-button-to-wordpress-or-woocommerce) to allow tracking at your store. Improve your customer experience on tracking.
|
36 |
|
37 |
-
|
38 |
###Notify customers of delivery updates (Premium)
|
39 |
-
|
40 |
Upgrade to [Premium](https://www.aftership.com/pricing) to automatically send out delivery notifications to customers or yourself. Your choice of notification triggers - In transit, Out for delivery, Delivered, Failed delivery attempt or Exceptions. Use your own email to send out notifications, and customize messages to add store logo, URL, a tracking link to get more returned customers after shipping!
|
41 |
|
42 |
-
|
43 |
-
###BRANDED RETURNS PAGE (FREE)
|
44 |
-
|
45 |
-
Get the top-rated returns management solution for WordPress. Customize your branded returns center with your logo, custom URL and return policy. Offer a customer-friendly returns experience. Improve your brand image, customer satisfaction and loyalty.
|
46 |
-
|
47 |
-
|
48 |
-
###MANAGE ALL RETURNS REQUESTS (FREE)
|
49 |
-
|
50 |
-
Track and manage all returns requests in one place to save processing time. Automatically generate an RMA# once a return request is submitted.
|
51 |
-
product returns management
|
52 |
-
|
53 |
-
|
54 |
-
###PREPAID SHIPPING LABELS
|
55 |
-
|
56 |
-
Automatically generate or manually upload prepaid labels to provide a seamless returns experience. Customers will receive an email with shipping instructions, simply print the label out and tap them to the box.
|
57 |
-
|
58 |
-
|
59 |
-
###CUT RETURNS COSTS WITH ADVANCED AUTOMATION RULES (FREE)
|
60 |
-
|
61 |
-
Set up eligibility rules to prevent customers from returning an old order or product in certain categories. Automatically select a returns method and set shipping rates based on the region and reason of returns (e.g. damaged, defective, or wrong item).
|
62 |
-
|
63 |
-
|
64 |
[youtube http://www.youtube.com/watch?v=1zCCx8Ap9ms]
|
65 |
|
66 |
-
|
67 |
-
###Partial list of supported carriers (668+):
|
68 |
**①. US, Canada & Global Tracking (35)**
|
69 |
ABF Freight • APC Postal Logistics • Aramex • Asendia USA • Canada Post • Canpar Courier • Con-way Freight • DACHSER • DHL Express • DHL eCommerce • DHL Express (Piece ID) • DPD • DSV • Echo • Ensenda • Estes • FedEx • FedEx Freight • Globegistics Inc. • Greyhound • i-parcel • LaserShip • Newgistics • Old Dominion Freight Line • OnTrac • Purolator • RL Carriers • RR Donnelley • TNT • TNT Reference • UPS • UPS Freight • UPS Mail Innovations • USPS • YRC
|
70 |
|
@@ -126,8 +97,8 @@ You'll find the FAQ on [AfterShip.com](https://aftership.uservoice.com/knowledge
|
|
126 |
|
127 |
== Changelog ==
|
128 |
|
129 |
-
= 1.9.
|
130 |
-
*
|
131 |
|
132 |
= 1.9.18 =
|
133 |
* Add new couriers (borderexpress)
|
1 |
=== Plugin Name ===
|
2 |
Contributors: aftership
|
3 |
Donate link: https://www.aftership.com/
|
4 |
+
Tags: shipping, tracking, ups, usps, fedex, dhl, tnt, dpd, post, shipment, woocommerce, tracking number, aftership, package tracking, fulfilment, tracking link, carrier, courier, woo commerce, woocommerce shipment tracking, shipping details plugin, widget, shipstation, track, package
|
5 |
Requires at least: 2.9
|
6 |
Tested up to: 5.2.1
|
7 |
+
Stable tag: 1.9.18
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
11 |
+
Auto import tracking of all your shipments in one place to WooCommerce (Free), branded tracking page to view order status in one click and ensure great post-purchase experience for your customers, send email / SMS delivery notifications to engage your customers after sales (Premium).
|
12 |
+
AfterShip is free for 100 first shipments, then try Premium.
|
13 |
|
14 |
== Description ==
|
15 |
|
16 |
###Top Shipment Tracking Plugin (Free)
|
17 |
+
By installing AfterShip plugin, you can automatically add Tracking Number and Courier fields to your admin panel. After you fulfill an order, simply enter the tracking number and select a courier at WooCommerce, the same info will be displayed at customer's order history page. AfterShip supports over 550+ carriers worldwide, you can select couriers by [signing up a free AfterShip account](https://secure.aftership.com/signup).
|
|
|
|
|
18 |
|
19 |
###Display tracking info at order history page (Free)
|
20 |
+
The plugin allows you to insert the AfterShip Track Button to order history page, so that your customers can track the latest order status in one click.
|
21 |
|
22 |
+
###Support 550+ International Courier (Free)
|
23 |
+
AfterShip supports UPS tracking, FedEx tracking, USPS tracking, DHL tracking and shipment tracking of over 550+ carriers worldwide. Please scroll down to see the full list of our supported carriers.
|
|
|
|
|
|
|
24 |
|
25 |
|
26 |
###Track all shipments in one place (Free)
|
27 |
By setting up an auto import of tracking numbers to AfterShip, you can get the latest tracking info of all your shipments in one place. Each free account comes with a Dashboard to monitor current statuses of all shipments. You can also filter your shipments by dates, statuses, couriers and destination. Find out if all your shipments are delivered on time and discover any exceptions. Support [WooCommerce Shipment Tracking Plugin](http://www.woothemes.com/products/shipment-tracking/) as well.
|
28 |
|
|
|
29 |
###Branded Tracking Page (Free)
|
30 |
|
31 |
AfterShip automatically generates a tracking page for each shipment. Customize tracking page by adding your brand logo, store URL and Instagram pictures to improve SEO and generate more sales. You can also embed the [AfterShip Track Button](http://support.aftership.com/article/111-how-can-i-add-track-button-to-wordpress-or-woocommerce) to allow tracking at your store. Improve your customer experience on tracking.
|
32 |
|
|
|
33 |
###Notify customers of delivery updates (Premium)
|
|
|
34 |
Upgrade to [Premium](https://www.aftership.com/pricing) to automatically send out delivery notifications to customers or yourself. Your choice of notification triggers - In transit, Out for delivery, Delivered, Failed delivery attempt or Exceptions. Use your own email to send out notifications, and customize messages to add store logo, URL, a tracking link to get more returned customers after shipping!
|
35 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
[youtube http://www.youtube.com/watch?v=1zCCx8Ap9ms]
|
37 |
|
38 |
+
###Partial list of supported carriers (550+):
|
|
|
39 |
**①. US, Canada & Global Tracking (35)**
|
40 |
ABF Freight • APC Postal Logistics • Aramex • Asendia USA • Canada Post • Canpar Courier • Con-way Freight • DACHSER • DHL Express • DHL eCommerce • DHL Express (Piece ID) • DPD • DSV • Echo • Ensenda • Estes • FedEx • FedEx Freight • Globegistics Inc. • Greyhound • i-parcel • LaserShip • Newgistics • Old Dominion Freight Line • OnTrac • Purolator • RL Carriers • RR Donnelley • TNT • TNT Reference • UPS • UPS Freight • UPS Mail Innovations • USPS • YRC
|
41 |
|
97 |
|
98 |
== Changelog ==
|
99 |
|
100 |
+
= 1.9.20 =
|
101 |
+
* Fix known issue
|
102 |
|
103 |
= 1.9.18 =
|
104 |
* Add new couriers (borderexpress)
|