Reputation: 2937
we are using wordpress JSON API to signon a user and to add / update / remove cart-items. We are doing this with the register_rest_route
function.
We use this code to remove a cart item:
function remove_from_cart(WP_REST_Request $req)
{
$resp = null;
$cart_item = $req['cart_item'];
try {
WC()->cart->remove_cart_item($cart_item);
} catch (Exception $e) {
$resp = $e;
}
return rest_ensure_response(new CartResponse());
}
This is working perfectly fine for guests. but as soon as a logged in user tries it, the cart is back to its normal state after a page reload. The response created by new CartResponse()
is correctly showing the cart without the removed item. however, after a page reload the item is still there.
As this only happens for logged in users and not for guests I think it is a session issue.
Also, updating the cart with the following method works for logged in users:
function update_cart_item(WP_REST_Request $req)
{
$resp = null;
$cart_item = $req['cart_item'];
try {
if ($cart_item && $cart_item['quantity']) {
WC()->cart->set_quantity($cart_item['key'], $cart_item['quantity']);
}
} catch (Exception $e) {
$resp = $e;
}
return rest_ensure_response(new CartResponse());
}
Unfortunately, setting the quantity to 0
is also not working.
This is how we signon users:
function login_customer(WP_REST_Request $req)
{
$body = $req->get_body();
$input = json_decode($body, TRUE);
$credentials = ['user_login' => $input['email'], 'user_password' => $input['password']];
$user = wp_signon($credentials, false);
if (is_a($user, 'WP_Error') || !$user) {
// if an error occurs, return null
return rest_ensure_response(null);
}
$resp = new CustomerResponse($user->ID);
return rest_ensure_response($resp);
}
And we are not using any caching plugins. What is wrong here?
Here is a list of all session cookies:
EDIT:
I just inspected the cookies while beeing logged in and removing a cart item.
So it seems like the cart hash is stored somewhere and restored on a reload, but not correctly updated on deleting a cart item
Upvotes: 1
Views: 1278
Reputation: 2937
It seems like you need nonces to authenticate DELETE requests.
Now I am adding nonces to each response in a header:
function add_cors_http_header(){
header("X-WP-Nonce: ".wp_create_nonce('wp_rest'));
}
add_action('init','add_cors_http_header');
And in the frontend I set it:
let nonce: string = null;
export const fetchNoAuth = (endpoint: string, method: string = 'GET', data: any = null): Promise<any> => {
let headers: any = {'Content-Type': 'application/json'};
if (nonce) {
headers['X-WP-Nonce'] = nonce;
}
return fetch('http://' + apiUrl + apiPath + endpoint + '?' + debugQuery, {
method,
credentials: 'include',
headers,
body: data ? JSON.stringify(data) : null
})
.then((data) => {
const nonceFromResponse = data.headers.get('X-WP-Nonce');
if (nonceFromResponse) {
nonce = nonceFromResponse;
} else {
nonce = null;
}
return data;
})
};
Make sure that the header in the request is named X-WP-Nonce
Upvotes: 1