π Describe the Bug
The official docs at https://marketplace.gohighlevel.com/docs/marketplace-modules/Payments/ state that after the custom provider iframe dispatches custom_provider_ready, HighLevel sends payment_initiate_props to the iframe with payment details. In practice, this second postMessage never fires when the customer pays an invoice at link.fastpaydirect.com/invoice/{invoiceId}.
Verified behavior:
- Iframe loads at paymentsUrl and dispatches
{ type: "custom_provider_ready", loaded: true, addCardOnFileSupported: true } to parent.
- GHL's own console logs: "Calling processPayment, payment element ready" β confirms ready was received.
- GHL's backend call
POST /payments/custom-provider/initiate/invoice returns 201 Created with a valid transactionId.
- Expected next step per docs: GHL's frontend dispatches
payment_initiate_props to iframe.
- Actual: no postMessage is ever delivered to the iframe.
Manually dispatching payment_initiate_props via window.postMessage inside the iframe completes the flow successfully, proving the iframe handler is correct. The missing step is exclusively GHL's parent-to-iframe dispatch.
Happens identically in live mode and test mode. Reproduced on multiple invoices, after uninstalling/reinstalling the app, with all 11 required scopes granted (payments/orders., payments/custom-provider., invoices.readonly, etc.).
π API Endpoint
/payments/custom-provider/initiate/invoice (returns 201 OK but subsequent postMessage never dispatched)
β
Expected Behavior
Per the official documentation:
"Once the ready event is dispatched by Iframe, GHL dispatches a data event
sending all the data needed for the iframe to process the payment."
β https://marketplace.gohighlevel.com/docs/marketplace-modules/Payments/
After the iframe emits custom_provider_ready, GHL's parent window should send:
{
"type": "payment_initiate_props",
"publishableKey": "...",
"amount": 100,
"currency": "USD",
"mode": "payment",
"orderId": "...",
"transactionId": "...",
"contact": {...},
"locationId": "..."
}
This never occurs. The iframe waits indefinitely and the customer cannot pay.
π» Screenshots or Code Samples
Iframe sends (confirmed via browser console):
window.parent.postMessage({
type: 'custom_provider_ready',
loaded: true,
addCardOnFileSupported: true
}, '*')
GHL console log confirming receipt:
C0mnZJeE.js:1 responseData Proxy(Object)
C0mnZJeE.js:1 Calling processPayment, payment element ready
GHL backend request (succeeds):
POST https://backend.leadconnectorhq.com/payments/custom-provider/initiate/invoice
Body: {
"altId": "nWt0qbrzu7q8OAenxxnM",
"altType": "location",
"invoiceId": "69e7a6b3e701b65f####",
"amount": 1,
"providerId": "69e7cd11cd19ad6bcfbdf417"
}
Response: 201 Created
{ "transactionId": "69e76e874710e24f3001a110",
"traceId": "4341797a-8fd3-4c06-a8f5-411e5692bf96" }
Expected postMessage dispatch (never occurs):
// Expected per docs but never received:
{ type: 'payment_initiate_props', publishableKey, amount, ... }
Workaround proof (our side is correct):
// Manually dispatched in iframe console β full flow completes:
window.postMessage({
type: 'payment_initiate_props',
publishableKey: 'DC1B44DC-CE4C-43C9-1619-#######',
amount: 100, currency: 'USD', mode: 'payment',
orderId: '69e7a6b3e701b65f0fa4dea4',
transactionId: 'test-tx',
contact: { id: 'test', email: 'test@x.com', name: 'Test' }
}, '*')
// β payment form renders correctly
### Product Area
payments
### π Use Case
We're building a custom payment provider marketplace app (PAB Gateway) that our merchants install to collect credit card and ACH payments on their invoices, subscriptions, payment links, and products. When a customer clicks "Pay" on an invoice link (link.fastpaydirect.com/invoice/{id}), our iframe is supposed to load and display a card entry form so the customer can complete payment.
Our end-to-end implementation works correctly (verified via manual postMessage dispatch), but GHL's frontend never initiates the handshake. This blocks all payment collection through our provider.
### π¨ Why Should This Be Prioritized?
This bug blocks the entire customer payment flow for ALL custom payment providers on invoices. A merchant that installs a custom provider and sends invoices to customers finds that customers cannot pay β the iframe loads but never receives the required payment data. There is no workaround from the merchant side or from the integration developer side.
The behavior directly contradicts documented behavior, which makes it an integration-breaking bug that affects every marketplace app implementing custom payments on invoices.
### π§ Additional Context
Configuration:
Marketplace App ID: 69de0c9b227aeda4d8cd712a
Location ID: nWt0qbrzu7q8OAenxxnM
Provider ID: 69e7cd11cd19ad6bcfbdf417
paymentsUrl: https://quick2pay.dev-pabgw.com/s/embed
queryUrl: https://gateway.dev-pabgw.com/api/platforms/pay/query
Scopes granted (11): payments/orders.readonly, payments/orders.write, payments/orders.collectPayment, payments/integration.write, payments/transactions.readonly, payments/subscriptions.readonly, payments/custom-provider.readonly, payments/custom-provider.write, invoices.readonly, contacts.readonly, products.readonly, products/prices.readonly
Trace IDs from reproductions:
Live mode: 4341797a-8fd3-4c06-a8f5-411e5692bf96 (initiate/invoice)
Test mode: 893ffdf4-fed9-4156-ad50-f63da627a9c6 (initiate/invoice)
Environment:
Browser: Chrome latest
Reproduced consistently across incognito/regular windows
App version in Live state with all scopes and payment methods (One Time, Recurring, Off-Session) enabled
Observations:
GET /payments/integrations/entity-providers?...&entityId=undefined&includeDefault=true β this preflight query has entityId=undefined, though the invoice has a valid _id in the URL. Possibly a separate frontend issue but may be related.
Iframe receives no postMessages from link.fastpaydirect.com besides React DevTools extension noise.
Our response headers include no restrictive X-Frame-Options, no CSP frame-ancestors, no COEP/COOP/CORP β nothing blocking cross-origin embedding or messaging.
π Describe the Bug
The official docs at https://marketplace.gohighlevel.com/docs/marketplace-modules/Payments/ state that after the custom provider iframe dispatches
custom_provider_ready, HighLevel sendspayment_initiate_propsto the iframe with payment details. In practice, this second postMessage never fires when the customer pays an invoice at link.fastpaydirect.com/invoice/{invoiceId}.Verified behavior:
{ type: "custom_provider_ready", loaded: true, addCardOnFileSupported: true }to parent.POST /payments/custom-provider/initiate/invoicereturns 201 Created with a valid transactionId.payment_initiate_propsto iframe.Manually dispatching
payment_initiate_propsvia window.postMessage inside the iframe completes the flow successfully, proving the iframe handler is correct. The missing step is exclusively GHL's parent-to-iframe dispatch.Happens identically in live mode and test mode. Reproduced on multiple invoices, after uninstalling/reinstalling the app, with all 11 required scopes granted (payments/orders., payments/custom-provider., invoices.readonly, etc.).
π API Endpoint
/payments/custom-provider/initiate/invoice (returns 201 OK but subsequent postMessage never dispatched)
β Expected Behavior
Per the official documentation:
After the iframe emits
custom_provider_ready, GHL's parent window should send:{
"type": "payment_initiate_props",
"publishableKey": "...",
"amount": 100,
"currency": "USD",
"mode": "payment",
"orderId": "...",
"transactionId": "...",
"contact": {...},
"locationId": "..."
}
This never occurs. The iframe waits indefinitely and the customer cannot pay.
π» Screenshots or Code Samples
Iframe sends (confirmed via browser console):