Overview
External Gateway mode is designed for teams who want UniBee to manage subscriptions, invoices, billing cycles and entitlements, while your own system or a third‑party gateway handles the actual payment and refunds. In this model:- UniBee handles:
- Subscription lifecycle and billing cycles
- Invoice generation and status
- Entitlement logic (activation, renewal, cancellation)
- Webhooks to your backend
- Your system handles:
- Creating payment orders
- Showing a checkout page / cashier
- Executing charge and refund on your own gateway
- Calling UniBee External Gateway APIs to report results
Data Flow at a Glance
| Direction | Description |
|---|---|
| UniBee → Your System | For payment attempts, UniBee creates or reuses a Payment and sends payment.created to tell you to charge. For refund tasks, UniBee sends refund.created to tell you to execute a refund. When users click “Pay” in UniBee UI, they stay on UniBee’s intermediate page until your backend calls Update External Gateway Payment Link (POST /merchant/payment/external_gateway_payment/update_link) to write paymentLink for that paymentId; then UniBee redirects the user to your payment URL. |
| Your System → UniBee | After your gateway finishes a charge, call Payment APIs (external_gateway_payment/mark_paid or mark_failed). After your gateway finishes a refund, call Refund APIs (external_gateway_refund/mark_success or mark_failed) to sync Payment/Refund/Invoice/Subscription states in UniBee. |
External Gateway Invoices.
1. Configuration and Security
1.1 Configure External Gateway in UniBee
Before integration, you need to configure one or more External Gateways in UniBee:- Log in as a merchant → Configuration → Payment Gateways.
- Add and configure an External Gateway (similar to other gateways).
- For each External Gateway, UniBee provides:
- A unique
gatewayId - An External Gateway API Key (also called GatewayKey) used only for HMAC signatures
- A unique
gatewayId to distinguish multiple external channels (e.g. custom_gateway_A, custom_gateway_B), and keep the GatewayKey strictly confidential.
1.2 Dual Authentication & Signature Rule
All External Gateway Payment / Refund APIs share the same security model:- Merchant OpenAPI auth
- HTTP header
Authorization: Bearer <UNIBEE_API_KEY>
- HTTP header
- Request body signature using the GatewayKey:
- Signature string (concatenate with
|in this exact order):- For payment APIs:
paymentId|externalTransactionId|timestamp - For refund APIs:
refundId|externalRefundId|timestamp
- For payment APIs:
- Algorithm:
HMAC-SHA256(GatewayKey, signatureString) - Encoding: hex string used as
signature - Anti‑replay:
timestampmust be within UniBee’s accepted time window (currently implemented as ±12 hours). Use current Unix timestamp in seconds.
2. Core APIs (Payment / Refund‑based)
The new External Gateway flow is built around Payment and Refund resources. All integration endpoints live under/merchant/payment/*:
2.1 Update External Gateway Payment Link
When your own gateway generates or changes a checkout URL, you can write it back to the UniBee Payment so invoice links / intermediate pages can redirect to the latest URL.- API: Update External Gateway Payment Link
Path:POST /merchant/payment/external_gateway_payment/update_link
paymentId— UniBee Payment IDexternalTransactionId— your order / payment IDpaymentLink— your hosted checkout URLtimestamp,signature— using the signing rule above
paymentLink.
2.2 Mark External Gateway Payment as Paid
After your external gateway confirms that a payment has succeeded, you report the result at the Payment level:- API: Mark External Gateway Payment As Paid
Path:POST /merchant/payment/external_gateway_payment/mark_paid
- Marks the corresponding Payment as Paid
- Transitions the related Invoice to Paid
- Triggers subscription activation / renewal logic
- Emits related webhooks (for example
invoice.paid,subscription.update.success)
paymentId— UniBee Payment IDexternalTransactionId— your payment order ID (used as an idempotency key)paidTime— timestamp when payment succeeded (optional)metadata— extra information (optional)timestamp,signature
Repeated calls with the same (paymentId, externalTransactionId) are idempotent and will not double‑charge or double‑record revenue.
2.3 Mark External Gateway Payment as Failed
When a payment attempt ultimately fails or you give up retries, you can explicitly mark the Payment as failed:- API: Mark External Gateway Payment As Failed
Path:POST /merchant/payment/external_gateway_payment/mark_failed
2.4 Report External Gateway Refund Result
Refunds are reported via dedicated Refund resources rather than directly on the invoice:- API: Mark External Gateway Refund As Success
Path:POST /merchant/payment/external_gateway_refund/mark_success - API: Mark External Gateway Refund As Failed
Path:POST /merchant/payment/external_gateway_refund/mark_failed
refundId— UniBee refund IDexternalRefundId— your external refund transaction IDtimestamp,signature— using the refund signing rule above
- UniBee sends
refund.createdwhen a refund task is created for an External flow. - Your system executes the refund in your gateway.
- Then your backend reports the final refund result with:
external_gateway_refund/mark_success, orexternal_gateway_refund/mark_failed.
- Create or obtain the corresponding Refund on UniBee side (implementation details depend on your setup).
- Call one of the Refund APIs to mark it successful or failed.
- UniBee will:
- Update refund status and amount
- Move the Invoice into partially or fully refunded states
- Emit refund‑related webhooks for your internal systems.
3. Webhooks: payment.created and refund.created
When UniBee decides it’s time to attempt payment for an External Gateway invoice (for example, before renewal, or when the user clicks “Pay”), it creates or reuses a Payment and sends a payment.created webhook.
payment.created is a payment-only trigger. Refund handling is a separate flow based on refundId and the External Gateway refund result APIs.
For External Gateway, refund execution should be driven by refund.created webhook events, not by payment.created.
3.1 Identifying External Payments
In your webhook handler:- Check
payment.gatewayIdin the payload and compare it with your known ExternalgatewayIds, or - Inspect the
gatewayobject and check that:gateway.gatewayType == 8(External), orgateway.gatewayName == "external"(depending on your configuration)
- Read
invoiceId,paymentId, amount and currency from the event. - Create/attach an order in your own system.
- Decide when/how to charge the user (immediately, or later).
- After the charge succeeds, call
external_gateway_payment/mark_paid; if there is a refund, report it viaexternal_gateway_refund/mark_success/mark_failed.
3.2 Typical Timing
- Renewal invoices are usually generated a few days before the period end.
- Around 2 hours before the billing period ends (configurable), UniBee:
- Creates or reuses a Payment
- Sends one
payment.createdevent for External gateways
- For subsequent automatic attempts, UniBee reuses the same Payment and does not send additional
payment.createdevents.
payment.created per Payment.
4. Integration Patterns
Pattern A: UniBee Checkout / Invoice Link + External Redirect
- Your app calls UniBee to create a subscription / invoice with an External Gateway.
- UniBee creates an External Gateway Payment for that invoice and returns an invoice or Checkout link.
- When the user clicks “Pay”, UniBee opens an External Gateway intermediate page:
- This page polls the current Payment and waits for a
paymentLink.
- This page polls the current Payment and waits for a
- Your backend calls
external_gateway_payment/update_linkwith your checkout URL. - Once the intermediate page sees a valid
paymentLink, it redirects the user to your checkout. - After the payment succeeds, your backend calls
external_gateway_payment/mark_paid, and UniBee updates the Payment / Invoice / Subscription state accordingly.
Pattern B: Your Own Checkout Only (No UniBee UI)
- Your backend calls UniBee to create subscriptions or invoices with an External Gateway and stores the
invoiceId/paymentId. - You use your own frontend and checkout; the user never visits UniBee’s pages.
- After the payment succeeds in your gateway, you call
external_gateway_payment/mark_paid. - If there is a refund, you report it via
external_gateway_refund/mark_success/mark_failed.
external_gateway_payment/update_link.
Pattern C: Invoice Email / Invoice Center
If you rely on UniBee’s invoice emails or invoice center:- Integrate
external_gateway_payment/update_linkso that the “Pay” button on the invoice always points to your latest valid checkout URL. - Whenever your order URL changes or expires, call this endpoint again; UniBee will always use the newest value.
5. Best Practices
-
Use UniBee as the source of truth for invoices and subscriptions
Even if your gateway handles the money, keep all invoices and subscription state in UniBee so reporting and entitlement logic stay consistent. -
Drive state from your gateway events
Only call the External Gateway Payment / Refund APIs after your own gateway definitively confirms the result (via its own webhook or API). -
Keep payment links fresh
If your checkout URLs can expire or change, always update them viaexternal_gateway_payment/update_linkbefore the user clicks “Pay”. -
Subscribe to UniBee webhooks
Subscribe to bothpayment.created(payment execution trigger) andrefund.created(refund execution trigger), and also consume result events such asinvoice.paid,invoice.refund.success,subscription.update.successfor downstream sync. -
Leverage idempotency
Use stable external IDs per operation (externalTransactionIdfor payment,externalRefundIdfor refund). Repeating the same call with the same key tuple is safe — UniBee treats it as idempotent and avoids duplicate state transitions.

