Common Phases: Discovery & Valuation
These phases are required for all integrations, regardless of which payment path you choose.
Understanding Sessions
Before implementing, understand how session management works between your system and Ealyx.
Session Flow Diagram
Terminology
| Term | What it is | Who generates it |
|---|---|---|
Your session_id | Your internal session identifier (PHP session, JWT, cookie, etc.) | Your backend |
salt | A secret key for HMAC generation (store securely, never expose) | Your backend |
session_hash / session_hash_token | HMAC-SHA256 hash of your session_id using salt as key | Your backend |
Ealyx session_id | Ealyx's internal identifier for the valuation session | Ealyx API |
Note:
session_hashandsession_hash_tokenrefer to the same value. The_tokensuffix is used in the shopper_data response to emphasize it's a secure token.
Why HMAC-SHA256?
The session hash serves two security purposes:
- Privacy: Your real session_id is never exposed to Ealyx or the browser
- Integrity: HMAC (vs simple hash) provides timing-attack resistance
❌ WRONG: SHA256(session_id + salt) → vulnerable to length extension attacks
✅ RIGHT: HMAC-SHA256(session_id, salt) → cryptographically secure
Session Redirect
When you call GET /core/sessions/{session_hash}, Ealyx may return a session_id different from your hash. This happens when:
- The session was updated server-side (e.g., customer linked accounts)
- Multiple valuations were consolidated
How to handle it:
1. Call GET /core/sessions/{your_session_hash}
2. If response.session_id ≠ your_session_hash:
→ Retry: GET /core/sessions/{response.session_id}
(Use the returned session_id directly - no re-hashing needed)
3. Use the tradein_item from the final response
Note: The
session_idreturned by Ealyx is their internal identifier. When doing a redirect, use it directly as the path parameter without applying HMAC.
Phase 1: Discovery - Display Teasers
Flow Diagram:
Implementation:
Add teaser placeholders across your site:
<!-- Homepage banner -->
<div class="ealyx-teaser" data-type="banner"></div>
<!-- Product detail page -->
<div class="ealyx-teaser" data-type="product-widget"></div>
<!-- Cart page (both types) -->
<div class="ealyx-teaser" data-type="product-widget"></div>
<div class="ealyx-teaser" data-type="cart-summary"></div>
<!-- Checkout page -->
<div class="ealyx-teaser" data-type="cart-summary"></div>
<!-- Thank you page -->
<div class="ealyx-teaser" data-type="thank-you"></div>
Note: For advanced teaser placement strategies, see Advanced Features
Phase 2: Valuation & Identification
Flow Diagram:
When customers click "Calculate Discount", the valuation wizard opens in a modal window (iframe). If the shopper accepts the offer, the selected product and discount details are automatically reflected in the corresponding widget(s).
In case the shopper leaves the site without completing a purchase, the valuation can be used to try to reactivate the shopper. To enable this, the Ealyx frontend script will request shopper data from your backend system.
Implement Shopper Data Endpoint
Create a GET endpoint at $MERCHANT_CALLBACKS_BASE/shopper_data on your backend. This endpoint returns customer session information and a session hash token.
Who calls this endpoint: The Ealyx frontend SDK (running in the customer's browser in same domain of web) calls this endpoint via JavaScript AJAX when the valuation modal needs customer data.
Endpoint Specification:
GET $MERCHANT_CALLBACKS_BASE/shopper_data
Response Format:
Your endpoint must return JSON with this structure:
{
"customer": {
"id": "customer_123",
"email": "john@example.com",
"given_name": "John",
"family_name": "Doe"
},
"session_hash_token": "sha256_hash_of_session_with_salt"
}
Note: The
customerobject includes only:id,given_name,family_name. These fields are required when the customer is logged in. For guest checkout, setcustomerandsession_hash_tokentonull.
Session Hash Token Generation:
The session hash is a secure token derived from your session ID using HMAC-SHA256. It should:
- Never expose your real session ID
- Use a random salt as the HMAC key for security
- Be deterministic (same input = same output)
- Use HMAC-SHA256 (timing-attack resistant)
Example implementation:
# Generate session hash using HMAC-SHA256
session_id="abc123def456"
salt="your_random_salt_16plus_bytes"
# Using openssl (recommended)
session_hash=$(echo -n "$session_id" | openssl dgst -sha256 -hmac "$salt" | cut -d' ' -f2)
# Result: "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
# Alternative using printf (if openssl dgst doesn't support -hmac on your system)
# session_hash=$(printf '%s' "$session_id" | openssl dgst -sha256 -hmac "$salt" -hex | cut -d' ' -f2)
⚠️ IMPORTANT: Use HMAC-SHA256 as shown above, NOT simple SHA256 hash. The salt must be treated as the HMAC secret key, not concatenated with the session_id. This provides timing-attack resistance.
Example Implementation (Pseudocode):
Create an endpoint that retrieves customer data from your session, and returns it in JSON format:
# Pseudocode - adapt to your language/framework
# Get session ID from your session management system
session_id = get_session_id()
# Get customer data from your database (if logged in)
customer_data = None
session_hash = None
if session_id and is_logged_in():
customer = get_customer_from_database()
customer_data = {
'id': customer.id,
'email': customer.email,
'given_name': customer.first_name,
'family_name': customer.last_name
# Note: phone field is NOT part of customer object, only id/email/given_name/family_name
}
# Generate session hash using HMAC-SHA256
salt = 'your_session_salt_key' # Store this in your session/database
session_hash = HMAC_SHA256(session_id, salt)
else:
# For guest checkout, return null
customer_data = None
# Return JSON response
return {
'customer': customer_data,
'session_hash_token': session_hash
}
⚠️ Note on Guest Checkout: If
customerisnull, Ealyx will display trade-in options linked to a temporary session. Once the customer logs in, the trade-in data is migrated to their merchant session. This behavior is intentional — customers must be identified to complete a trade-in and apply the discount.
Testing with curl:
curl -X GET '$MERCHANT_CALLBACKS_BASE/shopper_data' \
-H 'Content-Type: application/json' \
-b 'Cookie-Session: $SESSION'
# Response:
# {
# "customer": {
# "id": "customer_123",
# "email": "john@example.com",
# "given_name": "John",
# "family_name": "Doe"
# },
# "session_hash_token": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
# }
What to Store:
For each session, persist these fields:
session_id- Your internal session identifier (for regeneration with hash and salt)customer_id(optional) - Link to customer record
Key Principles:
- Persistence required: You must store the hash to verify it later
- Deterministic verification: Always regenerate from stored values
- Auto-expiration: Automatically cleanup old sessions (24 hours is safe)
- Timing-attack safe: Use constant-time string comparison when verifying
Test your endpoint:
curl -X GET "$MERCHANT_CALLBACKS_BASE/shopper_data" \
-H 'Content-Type: application/json' \
-b 'session=YOUR_SESSION_COOKIE'
| Check | Expected | If it fails |
|---|---|---|
| HTTP status | 200 OK | Check endpoint URL and method (must be GET) |
customer object | {id, email, given_name, family_name} | Ensure user is logged in |
session_hash_token | Non-null string | Check HMAC-SHA256 implementation |
| Guest checkout | {"customer": null, "session_hash_token": null} | This is correct for guests |