âš ī¸ "Message from unexpected origin: https://js.stripe.com"

Why this happens: Stripe Elements uses postMessage internally for communication between its payment form components. These messages are not meant for your application.

✅ Solution

This is completely normal and expected. Filter out Stripe messages in your event listener:

JavaScript
window.addEventListener('message', (event) => {
  // Ignore Stripe's internal messages
  if (event.origin === 'https://js.stripe.com') {
    return;
  }
  
  // Process your modal messages
  if (event.data?.type === 'payment-success') {
    // Handle success
  }
});

â„šī¸ "[Stripe.js] It looks like you are using Payment Element in an iframe"

Why this happens: This is an informational warning from Stripe, not an error. The modal is designed to be embedded in an iframe.

✅ Solution

This warning can be safely ignored. The modal is configured with redirect: "if_required" to handle payments in-iframe when possible. Most payment methods work fine:

  • ✓
    Credit/Debit Cards
    Work perfectly in iframe
  • ✓
    Most Payment Methods
    Google Pay, Apple Pay, etc.
  • âš ī¸
    Some 3D Secure Flows
    May require redirect in some cases

❌ "Error: Missing required parameters: itemPrice, itemId..."

Why this happens: The modal requires certain parameters to be passed via POST body or postMessage, depending on the product type.

✅ Solution

Ensure you're passing all required parameters for your product type:

Product Type Required Parameters
ITEM itemPrice, itemId, itemName, playerEmail, playerLevel, playerCountry
NFT walletAddress, collectionAddress, tokenId, tokenPrice

🔐 "JWT token is required"

Why this happens: The modal needs a JWT token to authenticate with the Merso backend APIs for payment processing.

✅ Solution

Send the JWT token via postMessage after the iframe loads:

JavaScript
iframe.onload = () => {
  iframe.contentWindow.postMessage({
    type: 'api-config',
    jwtToken: 'your-jwt-token-here'
  }, '*');
};

🔄 Payment form not loading / stuck on processing

Why this happens: This can occur if the Stripe publishable key is missing or if there's a network error connecting to the backend.

✅ Solution

Check the following:

  • 1
    Verify Stripe key is configured
    Check STRIPE_PUBLISHABLE_KEY environment variable
  • 2
    Check browser console
    Look for network errors or API failures
  • 3
    Verify JWT token
    Ensure token is valid and not expired
  • 4
    Check CORS
    Verify your domain is allowed to embed the modal

đŸĻŠ "MetaMask not found or wallet address not provided"

Why this happens: Crypto payments require MetaMask (or another Web3 wallet) to be installed and a wallet address to be provided.

✅ Solution

For crypto payments:

  • 1
    Ensure MetaMask is installed
    Users need a Web3 wallet browser extension
  • 2
    Provide walletAddress parameter
    Pass the user's connected wallet address
  • 3
    User must approve connection
    MetaMask will prompt for approval

🔄 Modal shows previous state when reopened

Why this happens: Iframe content persists when hidden. If you hide and show the same iframe, it may retain its previous state.

✅ Solution

Reset the iframe when reopening or send a reset message:

JavaScript
// Option 1: Re-submit the form to reload the modal
function closeModal() {
  overlay.style.display = 'none';
}

function openModal() {
  document.getElementById('merso-form').submit();
  overlay.style.display = 'flex';
}

// Option 2: Send reset message via postMessage
function reopenModal() {
  iframe.contentWindow.postMessage({
    type: 'reset-modal'
  }, MODAL_URL);
  overlay.style.display = 'flex';
}

🌐 CORS errors when loading the modal

Why this happens: Cross-Origin Resource Sharing (CORS) restrictions may block the iframe from loading or communicating with your page.

✅ Solution

The modal server has CORS enabled by default. If you're self-hosting, ensure:

  • 1
    CORS is enabled
    The server uses cors({ origin: true })
  • 2
    HTTPS is used
    Mixed content (HTTP in HTTPS) is blocked
  • 3
    Check iframe sandbox
    If using sandbox attribute, allow necessary permissions

đŸ’Ŧ Still Need Help?