# Cart Integration

This document covers how the plugin bootstraps WooCommerce sessions for Global-e's inbound cart API calls and how it injects country and currency data derived from the Global-e cookie.

---

## Cookie contract

Global-e's JS sets a cookie (default name: `GlobalE_Data`, configurable via `COOKIE_NAME_GLOBALE_DATA_KEY`) on the shopper's browser. The plugin reads this cookie via `Helper\Cookie` to extract:

- **Country code** — ISO 3166-1 alpha-2 (e.g. `DE`).
- **Currency code** — ISO 4217 (e.g. `EUR`).

A second cookie, `GlobalE_Gem_Data` (`Config::COOKIE_NAME_GEM_DATA`), holds the store code used by the GEM checkout overlay.

The `GlobalE_Data` cookie name can be customised in the integration settings (`cookie_name_globale_data_key`). The plugin compares the configured name against the default; if they differ, it updates the browser cookie name at script load time via `updateCookies: true` in the JS config object.

---

## Session bootstrap for REST calls

When Global-e calls `/?wc-api=pro-cart-info?hash={cartId}`, WooCommerce's session is not automatically loaded (no cookie is sent by Global-e's server). The plugin bootstraps it explicitly:

1. `Helper\Session::injectCookieForRestCall()` — extracts the `hash` query parameter (which equals the shopper's `CartId` / WooCommerce session key) and synthesises the WooCommerce session cookie (`wp_woocommerce_session_{COOKIEHASH}`) before WooCommerce initialises its session handler.
2. WooCommerce loads the session associated with that key, restoring the shopper's cart.

For session-based calls (no `hash`, session cookie present), `Model\Cart::initSession()` calls `WC()->cart->get_cart()` directly.

---

## Country and currency injection

`Helper\Session::getCountryCookie()` and `Helper\Session::getCurrencyCookie()` return the country and currency extracted from the `GlobalE_Data` cookie.

These values are injected into WooCommerce via:

- **`GlobalePro::getCountry()`** — applied to `wc_aelia_pbc_customer_country` and `wc_aelia_cs_customer_country` filters (Aelia plugins).
- **`GlobalePro::getCurrency()`** — applied to `wc_aelia_cs_selected_currency` (Aelia Currency Switcher). The currency is only set if it is in Aelia's enabled currency list; otherwise the base currency is used.
- **`GlobalePro::preSetCustomerLocation()`** — applied on `wc_price_based_country_before_frontend_init` (WCPBC plugin); sets `WC_Customer` billing and shipping country before WCPBC reads the customer location.

---

## Cart model — `Model\Cart`

`Model\Cart` builds the cart payload sent to Global-e. Key methods:

### `buildCartProductsList()`

Iterates over `WC()->cart->get_cart()`. For each item:

1. Resolves the `\WC_Product` object.
2. Determines prices via the `CART_GET_PRODUCT_LIST_PRICE` and `CART_GET_PRODUCT_SALE_PRICE` filters (allowing overrides for custom pricing plugins).
3. Builds a `ProductEntity` with SKU, name, quantity, list price, sale price, VAT rate, images, attributes (standard + extra + meta data), brand, class code, country of origin, HS code, weight, and description.
4. Applies the `woocommerce_globale_pro_add_cart_product_meta_attributes` filter for custom meta attributes.
5. Applies the `woocommerce_globale_pro_transform_product_sku` filter to allow SKU transformation.
6. Fires `woocommerce_globale_pro_build_product_after` after the entity is built.
7. Appends extra virtual products via `woocommerce_globale_pro_add_extra_virtual_products`.

### `buildCartDiscounts()`

Iterates over applied coupons. Builds `DiscountEntity` objects with:

- Coupon code, discount type (`percent`, `percent_product`, `onetime_coupon`, or fixed), and amount.
- Minimum order amount and product SKU restrictions.

### `filterDiscounts($productsList, $discountsList)`

Applies `woocommerce_globale_pro_modify_discounts` to allow removal or modification of discount entries.

### `getFreeShipping()`

Returns `[bool $isFreeShipping, string|null $couponCode]`. Free shipping is active if any applied coupon grants free shipping; the coupon code is included for traceability.

### `generateMerchantCartHash()`

Generates a hash of the cart contents used to detect cart changes between the cart-info call and order creation. Validated during order creation unless `SKIP_CART_HASH_VALIDATION` is enabled.

---

## Cart cookie management

`Helper\Session::setCartCoookie()` is invoked from `GlobalePro::initAfterWc()` and `initAfterWcSetCookie()`. It writes the `GlobalE_Data` cookie (or a merge of it) so that the shopper's country/currency persists across page loads. Logic details:

- Skips admin, Global-e order API mode, and unsupported browse modes.
- Handles WooCommerce ≥ 10.0.0 separately, reading the session key from the `Set-Cookie` response headers when the cookie is not yet in `$_COOKIE`.

### `Session::clearCart()`

Clears the WooCommerce cart (and optionally customer data) when the shopper switches country. Fires the `woocommerce_globale_pro_action_clear_cart_after` action after clearing, allowing hooks to clean up additional state.

### `Session::logout()`

Hooked on `wp_logout`. Clears Global-e session data on logout.

---

## Country switch — coupon removal

`Front\Cart::handleSwitchedCountry()` is called from `initAfterWc()`. When a shopper switches from the domestic country to an international one:

- If `CHECKOUT_REMOVE_COUPONS_ON_SWITCH_COUNTRY` is enabled, all coupons are removed from the cart.
- The `handleAppliedCoupon` method (hooked on `woocommerce_applied_coupon`) re-validates coupons when one is applied after a country switch.

---

## Product identifier strategy

The cart payload uses either SKU or product ID to identify products, controlled by `PRODUCT_IDENTIFIER` config:

| Value | Field used |
|---|---|
| `sku` | `WC_Product::get_sku()` |
| `productId` | `WC_Product::get_id()` for simple products; variation ID for variable products |

This same setting applies in both cart (`Model\Cart`) and order (`Model\Order`) contexts to ensure consistent identification across the integration lifecycle.
