동일한 도메인 사이트 간 쿠키 공유 - 헤드리스/디커플링된 CMS
나의 도전의 배경은
헤드리스 WordPress / WooCommerce Store를 만들고 있습니다.
헤드리스 CMS의 개념이 익숙하지 않은 경우 WordPress/WooCommerce REST API에서 스토어의 콘텐츠(제품 및 그 이미지, 텍스트)를 가져옵니다.이렇게 하면 클라이언트용 CMS 대시보드의 이점을 얻을 수 있습니다.또한 최신 언어/라이브러리에서 개발할 수 있습니다.리액션!
가능하다면 WordPress/WooCommerce/PHP에서 체크아웃을 유지하고 싶습니다.이 코드/보일러플레이트를 프로젝트에 따라서는 지불 게이트웨이를 잘라내고 변경해야 할 것 같습니다.또, PHP/WordPress에서는, 이 시큐어한 PCI 준거성을 실현하는 것이 훨씬 쉬워집니다.플러그인은 매우 많습니다.
이는 사용자가 주문을 완료하고 싶을 때 CMS 프론트엔드(WordPress, PHP)로 리디렉션되는 카트를 제외하고 전체 스토어/프런트엔드가 React에 상주함을 의미합니다.
과제
이로 인해 세션용 쿠키 관리는 다소 비타협적이고 비정통적입니다.사용자가 스토어(React 사이트)에서 체크아웃(WooCommerce/PHP 사이트)으로 리디렉션되면 두 사이트 간에 카트 세션을 유지해야 합니다.
또한 WooCommerce에 대한 요청은 내 React 클라이언트가 있는 노드/Express 서버를 통해 라우팅됩니다.WordPress 주소를 가리고 싶기 때문에, GraphQL을 적용하여 요청과 응답을 정리할 수 있습니다.이 문제는 클라이언트와 CMS가 중간자(노드 서버)를 통해 통신하기 때문에 쿠키가 손실된다는 것입니다.쿠키를 수동으로 관리하려면 추가 논리가 필요합니다.
코드
카트에 무언가를 추가하려고 할 때 작업 작성자(상태 관리에 Redx를 사용 중)에서 노드/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));
}
};
그런 다음 노드/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);
}
});
@TarunLalwani(고맙습니다!)가 코멘트에서 준 힌트로, 해결책을 생각해 냈습니다.
쿠키 도메인 설정
2개의 다른 사이트를 사용하고 있었기 때문에, 이 작업을 실시하기 위해서는, 양쪽이 같은 도메인에 있는 것과 모든 cookie에 도메인이 설정되어 있는 것을 확인할 필요가 있었습니다.이것에 의해, 노드/익스프레스 서버간의 요구에 쿠키가 포함되어 있는 것을 확인할 수 있었습니다(예: 설치 장소). somedomain.com
CMS( WooCommerce CMS(WooCommerce CMS)에). wp.somedomain.com
「」, 「」의,wp.somedomain
서브도메인이것은, 다음의 설정에 의해서 실현되었습니다.define( 'COOKIE_DOMAIN', 'somedomain.com' );
집에서는wp-config.php
CMS cms cms ★
쿠키 수동 가져오기 및 설정
요구가 클라이언트를 통해 노드/익스프레스 서버를 통해 라우팅되는 동안 쿠키를 포함하기 위해 코드에는 상당한 추가 논리가 필요했습니다.
리액트에서는 쿠키가 존재하는지 확인하고 존재하는지 여부를 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));
}
};
되어 있는지 에 되어 있습니다).req.headers
를 session-data
Cookie
CMS로 .
쿠키를 수 없는 에서 첫 으로 가져와 (CMS).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);
}
});
이것이 그 문제에 대한 가장 우아한 해결책인지는 모르겠지만, 나에게는 효과가 있었다.
메모들
리액트 클라이언트의 쿠키와 상호 작용하기 위해 js-cookie 라이브러리를 사용했습니다.
고차스
개발 환경(localhost 사용)에서 이 작업을 수행하려는 경우 몇 가지 추가 작업을 수행해야 합니다.명시적 도메인이 있는 로컬 호스트의 쿠키를 참조하십시오.
언급URL : https://stackoverflow.com/questions/51307403/sharing-cookies-between-sites-on-the-same-domain-headless-decoupled-cms
'programing' 카테고리의 다른 글
mongo 콘솔에서 오브젝트 ID를 사용하여 오브젝트를 검색하려면 어떻게 해야 합니까? (0) | 2023.03.07 |
---|---|
WordPress - PHP 경고 스트림을 열지 못했습니다.해당 파일 또는 디렉토리(advanced-cache.php)가 없습니다. (0) | 2023.03.07 |
useEffect에서 종속 어레이를 제공하지 않는 것과 빈 어레이의 차이점은 무엇입니까? (0) | 2023.03.07 |
AngularJS: 송신과 서버 응답 사이의 모든 폼 제어 비활성화 (0) | 2023.03.07 |
Angular UI 라우터가 비동기/대기 기능을 사용할 때 해결 기능을 처리하지 않습니까? (0) | 2023.03.02 |