All*_*ney 7 cookies wordpress express reactjs axios
我挑战的背景
我正在建立一个无头的WordPress/WooCommerce商店.
如果您不熟悉无头CMS的概念,我会通过WordPress/WooCommerce REST API提取商店的内容(产品及其图像,文本).通过这种方式,我可以为我的客户提供CMS仪表板,同时我可以使用现代语言/库进行开发 - 就我而言 - React!
如果可能的话,我想在WordPress/WooCommerce/PHP中保存结账.根据项目,我应用此代码/样板文件,我怀疑我必须切断和更改支付网关,并且在PHP/WordPress中使这种安全和PCI兼容性要容易得多 - 这里有很多插件.
这意味着整个商店/前端将存在于React中,但购物车除外,当用户希望完成订单时,用户将被重定向到CMS前端(WordPress,PHP).
挑战
这使得管理会话的cookie变得非常不直观和非正统.当用户从商店(React站点)重定向到结帐(WooCommerce/PHP站点)时,购物车会话必须在两个站点之间保持不变.
此外,对WooCommerce的请求通过我的React客户端所在的Node/Express服务器进行路由.我这样做是因为我想让WordPress地址变得模糊,所以我可以应用GraphQL来清理我的请求和响应.这个问题是在这个过程中,cookie丢失了,因为我的客户端和我的CMS正在通过中间人(我的节点服务器)进行通信 - 我需要额外的逻辑来手动管理我的cookie.
代码
当我尝试从一个动作创建者(我使用Redux进行状态管理)向购物车添加内容时,我点击了我的Node/Express服务器上的api对应端点:
export const addToCart = (productId, quantity) => async (dispatch) => {
dispatch({type: ADD_TO_CART});
try {
// Manually append cookies somewhere here
const payload = await axios.get(`${ROOT_API}/addtocart?productId=${productId}&quantity=${quantity}`, {
withCredentials: true
});
dispatch(addToSuccess(payload));
} catch (error) {
dispatch(addToCartFailure(error));
}
};
Run Code Online (Sandbox Code Playgroud)
然后在Node/Express服务器上,我向WooCommerce发出请求:
app.get('/api/addtocart', async (req, res) => {
try {
// Manually retrieve & append cookies somewhere here
const productId = parseInt(req.query.productId);
const quantity = parseInt(req.query.quantity);
const response = await axios.post(`${WP_API}/wc/v2/cart/add`, {
product_id: productId,
quantity
});
return res.json(response.data);
} catch (error) {
// Handle error
return res.json(error);
}
});
Run Code Online (Sandbox Code Playgroud)
根据@TarunLalwani(感谢一百万!)在他的评论中给出的线索,我已经设法制定了一个解决方案。
Cookie 域设置
由于我正在使用两个不同的站点,为了使其工作,我必须确保它们都在同一个域中,并且该域已在所有 cookie 中设置。这确保了 cookie 包含在我在 Node/Express 服务器(坐在例如somedomain.com)和 WooCommerce CMS(坐在例如wp.somedomain.com)之间的请求中,而不是wp.somedomain子域独有。这是通过define( 'COOKIE_DOMAIN', 'somedomain.com' );在我wp-config.php的 CMS 上设置来实现的。
手动获取和设置 Cookie
我的代码需要重要的额外逻辑,以便在请求通过我的 Node / Express 服务器通过客户端路由时包含 cookie。
在 React 中,我必须检查 cookie 是否存在,如果存在,我必须在我的 GET 请求的标头中将其发送到 Node/Express 服务器。
import Cookies from 'js-cookie';
export const getSessionData = () => {
// WooCommerce session cookies are appended with a random hash.
// Here I am tracking down the key of the session cookie.
const cookies = Cookies.get();
if (cookies) {
const cookieKeys = Object.keys(cookies);
for (const key of cookieKeys) {
if (key.includes('wp_woocommerce_session_')) {
return `${key}=${Cookies.get(key)};`;
}
}
}
return false;
};
export const addToCart = (productId, quantity) => async (dispatch) => {
dispatch({type: ADD_TO_CART});
const sessionData = getSessionData();
const config = {};
if (sessionData) config['session-data'] = sessionData;
console.log('config', config);
try {
const payload = await axios.get(`${ROOT_API}/addtocart?productId=${productId}&quantity=${quantity}`, {
withCredentials: true,
headers: config
});
dispatch(addToSuccess(payload));
} catch (error) {
dispatch(addToCartFailure(error));
}
};
Run Code Online (Sandbox Code Playgroud)
在 Node / Express 服务器上,我必须检查是否包含来自客户端的 cookie(req.headers与密钥一起保存session-data-Cookie在此处用作密钥是非法的),如果我这样做了,请将其附加到我的请求的标题中去我的 CMS。
如果我没有找到附加的 cookie,这意味着这是会话中的第一个请求,所以我必须从我从 CMS 返回的响应中手动获取 cookie 并将其保存到客户端 ( setCookieFunc)。
app.get('/api/addtocart', async (req, res) => {
try {
const productId = parseInt(req.query.productId);
const quantity = parseInt(req.query.quantity);
const sessionData = req.headers['session-data'];
const headers = {};
if (sessionData) headers.Cookie = sessionData;
const response = await axios.post(`${WP_API}/wc/v2/cart/add`, {
product_id: productId,
quantity
}, { headers });
if (!sessionData) {
const cookies = response.headers['set-cookie'];
const setCookieFunc = (cookie) => {
const [cookieKeyValue, ...cookieOptionsArr] = cookie.split('; ');
const cookieKey = cookieKeyValue.split('=')[0];
const cookieValue = decodeURIComponent(cookieKeyValue.split('=')[1]);
const cookieOptions = { };
cookieOptionsArr.forEach(option => (cookieOptions[option.split('=')[0]] = option.split('=')[1]));
if (cookieOptions.expires) {
const expires = new Date(cookieOptions.expires);
cookieOptions.expires = expires;
}
res.cookie(cookieKey, cookieValue, cookieOptions);
};
cookies.map(cookie => setCookieFunc(cookie));
}
return res.json(response.data);
} catch (error) {
// Handle error
return res.json(error);
}
});
Run Code Online (Sandbox Code Playgroud)
我不确定这是否是该问题最优雅的解决方案,但它对我有用。
笔记
我使用js-cookie库与我的 React 客户端上的 cookie进行交互。
陷阱
如果您试图在您的开发环境(使用 localhost)中进行这项工作,则需要完成一些额外的工作。使用显式域查看本地主机上的 Cookie
| 归档时间: |
|
| 查看次数: |
362 次 |
| 最近记录: |