# Paymenter Connector Setup (Read-Only + Managed) Start in `read_only` to validate sync, then move to `managed` for full in-plugin checkout. ## Goal - Keep package/payment authority in CHD billing backend. - Let the plugin sync entitlements from CHD. - Optionally allow direct purchase/upgrade initiation from the plugin in `managed` mode. ## Admin Settings (NuQloud -> Billing + Entitlements) 1. `Managed By CHD` = enabled 2. `Billing Provider` = `Paymenter` 3. `Connector Mode`: - `Read-only` for sync-only - `Managed` for registration + checkout + entitlements 4. `CHD Billing Base URL` = your connector API base URL 5. `CHD Entitlements Sync Path` = endpoint path (default: `/api/sovereign/v1/entitlements/sync`) 6. `CHD Instance ID` = unique tenant/instance identifier 7. `CHD Instance Token` = bearer token for connector auth 8. Optional `CHD Instance Secret` = HMAC signing secret 9. `CHD Catalog Path` = endpoint path (default: `/api/sovereign/v1/billing/catalog`) 10. `Catalog Category ID` = Paymenter/connector category id for NuQloud products (optional but recommended) 11. `Catalog Audience Key` = audience rule key from CHD Admin catalog config (optional) Then: - Click `Save Billing Connectivity` - Click `Test Connector (No Apply)` - Click `Sync Entitlements From CHD` - For managed checkout: click `Connect Installation + Sync` once, then `Start Buying Services` ## Connector Request From Plugin Method: `POST` Path: `{CHD Billing Base URL}{CHD Entitlements Sync Path}` Headers: - `Authorization: Bearer ` (if provided) - `X-SC-Signature: ` (if provided) Body JSON: ```json { "instanceId": "my-cloud-instance-001", "nextcloudPublicUrl": "https://cloud.example.com", "sovereignMode": "powered", "billingProvider": "paymenter", "billingSyncMode": "read_only", "appVersion": "v1", "source": "nextcloud-plugin" } ``` For managed checkout, plugin also sends billing profile fields to connector (`billingProfile`) so the Paymenter customer record can be updated before checkout link generation. ## Catalog Discovery Request (Managed + Read-Only UI) Method: `POST` Path: `{CHD Billing Base URL}{CHD Catalog Path}` Body JSON includes: 1. `instanceId` 2. `nextcloudPublicUrl` 3. `packageTier` 4. `billingProvider` 5. `billingSyncMode` 6. `categoryId` (when configured) 7. `catalogContract: "sc.billing.catalog.v1"` 8. optional context: `audience`, `billingScope`, `billingSubject`, `catalogContext` ## Connector Response (Required) Return either: 1. Wrapped: ```json { "entitlements": { "packageTier": "nuqloud_starter", "billingEnabled": true, "creditsBalance": 500, "monthlyCredits": 500, "encryptedCapacityGb": 10, "replicationTarget": 2, "userPublishingEnabled": true, "qappsEnabled": true } } ``` 2. Flat (same keys at top level). ## Keys Applied By Plugin - `packageTier` - `billingEnabled` - `creditsBalance` - `monthlyCredits` - `encryptedCapacityGb` - `replicationTarget` - `userPublishingEnabled` - `qappsEnabled` ## Safety - `Test Connector (No Apply)` validates connectivity/shape only. - `Sync Entitlements From CHD` applies values locally. - Package/credits entitlement fields remain read-only in admin UI. - Local admins do not directly override paid entitlement values. ## Next (Post-Sandbox) When sandbox passes, keep same API shape and switch only base URL/token to production connector. Canonical catalog schema reference: - `docs/product/connector-catalog-contract-v1.md` ## Legacy Env Mapping (Old -> Current) Use this when migrating older connector `.env` files. ### Core (typically keep) - `PORT` -> unchanged. Runtime listen port. - `HOST` -> unchanged. Runtime bind host. - `LOG_LEVEL` -> unchanged. Connector logging level. - `CONNECTOR_MODE` -> unchanged (`paymenter` for production). - `INSTANCE_REGISTRY_PATH` -> unchanged. Where instance state is stored. - `ALLOW_UNKNOWN_INSTANCES` -> unchanged. Security toggle for unknown instance requests. - `ADMIN_API_TOKEN` -> unchanged. Required for CHD admin endpoints. - `CHD_ADMIN_API_TOKEN` -> alias for `ADMIN_API_TOKEN`. - `SOVEREIGN_ADMIN_API_TOKEN` -> alias for `ADMIN_API_TOKEN`. - `REGISTRATION_TOKEN` -> unchanged. Protects install/register endpoint. - `PAYMENTER_BASE_URL` -> unchanged. - `PAYMENTER_API_TOKEN` -> unchanged. - `PAYMENTER_TIMEOUT_MS` -> unchanged. - `PAYMENTER_TRUST_SCOPED_QUERY_RESULTS` -> unchanged. Keep `false` in production unless you intentionally trust upstream scoped list responses. ### Domain verification (keep if used) - `CHD_DOMAIN_VERIFY_REQUIRED` -> unchanged. - `CHD_DOMAIN_VERIFY_TTL_SECONDS` -> unchanged. - `CHD_DOMAIN_VERIFY_PATH_TEMPLATE` -> unchanged. - `CHD_DOMAIN_VERIFY_TIMEOUT_MS` -> unchanged. ### Catalog/product mapping These are still valid, but CHD Admin JSON can override product maps. - `PAYMENTER_PACKAGE_PRODUCT_MAP` -> unchanged. - `PAYMENTER_ONE_TIME_PRODUCT_MAP` -> unchanged. - `PAYMENTER_ADDON_PRODUCT_MAP` -> unchanged (new split naming for monthly add-ons). - `PAYMENTER_ONE_TIME_LABEL_MAP` -> unchanged. - `PAYMENTER_ADDON_LABEL_MAP` -> unchanged. - `PAYMENTER_PACKAGE_PRICE_MAP` -> unchanged (fallback pricing). - `PAYMENTER_ADDON_PRICE_MAP` -> unchanged (fallback pricing for monthly add-ons). - `PAYMENTER_ONE_TIME_PRICE_MAP` -> unchanged (fallback pricing). - `PAYMENTER_PACKAGE_CHECKOUT_PATH_MAP` -> unchanged (public checkout path fallback). - `PAYMENTER_ONE_TIME_CHECKOUT_PATH_MAP` -> unchanged (public checkout path fallback). - `PAYMENTER_ADDON_CHECKOUT_PATH_MAP` -> unchanged. - `PAYMENTER_CATALOG_CATEGORY_ID` -> unchanged. - `PAYMENTER_CHECKOUT_CATEGORY_SLUG` -> optional storefront category slug used to generate public checkout links from product/category data. - `PAYMENTER_CHECKOUT_PATH_TEMPLATE` -> optional storefront template, example `/products/{category}/{productSlug}/checkout`. Precedence: 1. `ADMIN_CATALOG_CONFIG_PATH` JSON (CHD Admin plugin-managed) for product maps/audience rules 2. CHD Admin fallback price maps (`packagePriceMap`, `addonPriceMap`, `oneTimePriceMap`) are used when live Paymenter catalog data does not provide a price label. 3. `.env` map values above as fallback defaults ### Paymenter endpoint overrides (optional) Still supported and unchanged: - `PAYMENTER_USERS_ENDPOINT` - `PAYMENTER_ORDERS_ENDPOINT` - `PAYMENTER_SERVICES_ENDPOINT` - `PAYMENTER_CREDITS_ENDPOINT` - `PAYMENTER_INVOICES_ENDPOINT` - `PAYMENTER_INVOICE_ITEMS_ENDPOINT_TEMPLATE` - `PAYMENTER_PRODUCTS_ENDPOINT` - `PAYMENTER_ADDONS_ENDPOINT` - `PAYMENTER_PROPERTIES_ENDPOINT` - `PAYMENTER_CREATE_USER_ENDPOINT` - `PAYMENTER_CREATE_ORDER_ENDPOINT` - `PAYMENTER_CHECKOUT_LINK_ENDPOINT` Connector checkout resolution order: 1. explicit mapped `checkoutPath` 2. generated storefront path from `PAYMENTER_CHECKOUT_CATEGORY_SLUG` + `PAYMENTER_CHECKOUT_PATH_TEMPLATE` 3. custom `PAYMENTER_CHECKOUT_LINK_ENDPOINT` 4. order creation 5. invoice + invoice-item fallback ### Customer + property mapping - `PAYMENTER_CUSTOMER_EXTERNAL_FIELD` -> unchanged. - `PAYMENTER_QORTAL_ADDRESS_PROPERTY_KEY` -> unchanged. - `PAYMENTER_QORTAL_ADDRESS_PROPERTY_NAME` -> unchanged. - `PAYMENTER_QORTAL_ADDRESS_MODEL_TYPE` -> unchanged. - `PAYMENTER_QORTAL_ADDRESS_UPSERT_ENDPOINT` -> unchanged. - `PAYMENTER_QORTAL_ADDRESS_UPSERT_TOKEN` -> unchanged. - `QORTAL_ADDRESS_UPSERT_ENDPOINT` -> legacy alias (still accepted). - `QORTAL_ADDRESS_UPSERT_TOKEN` -> legacy alias (still accepted). ### SSO bridge keys - `SSO_BRIDGE_ENABLED` -> unchanged. - `SSO_BRIDGE_PAYMENTER_SSO_URL` -> unchanged. - `SSO_BRIDGE_VERIFY_TOKEN` -> unchanged. - `SSO_BRIDGE_VERIFY_PATH` -> unchanged. - `SSO_BRIDGE_TOKEN_TTL_SECONDS` -> unchanged. - `SSO_BRIDGE_REDIRECT_ALLOWLIST` -> unchanged. - `SSO_PAYMENTER_URL` -> alias for `SSO_BRIDGE_PAYMENTER_SSO_URL`. - `SSO_VERIFY_TOKEN` -> alias for `SSO_BRIDGE_VERIFY_TOKEN`. - `SSO_VERIFY_PATH` -> alias for `SSO_BRIDGE_VERIFY_PATH`. ### No longer used (safe to remove) - `SOVEREIGN_CONNECTOR_BASE_URL` - `SOVEREIGN_SSO_VERIFY_PATH` - `SOVEREIGN_SSO_VERIFY_TOKEN` - `SOVEREIGN_SSO_TIMEOUT_SECONDS` ### Mock-mode defaults (optional in production) Only relevant when `CONNECTOR_MODE=mock`: - `DEFAULT_PACKAGE_TIER` - `DEFAULT_BILLING_ENABLED` - `DEFAULT_CREDITS_BALANCE` - `DEFAULT_MONTHLY_CREDITS` - `DEFAULT_ENCRYPTED_CAPACITY_GB` - `DEFAULT_REPLICATION_TARGET` - `DEFAULT_USER_PUBLISHING_ENABLED` - `DEFAULT_QAPPS_ENABLED` ## Webhook Clarification Connector endpoint: - `POST /api/sovereign/v1/events/paymenter/post-payment` Purpose: - Trigger entitlement refresh immediately after payment events. - Update instance state fields such as `lastPaymentEventAt`, `lastPaymentEventType`, and `lastResolvedEntitlements`. Auth: - If `PAYMENTER_WEBHOOK_TOKEN` is set, Paymenter must send header `X-SC-Webhook-Token` with that value. - If token is empty, endpoint is still callable (not recommended for production). Recommended Paymenter webhook target: - `https:///api/sovereign/v1/events/paymenter/post-payment` If you are unsure whether Paymenter is calling it, check connector logs for: - `payment webhook processed` - `missing_webhook_token` - `invalid_webhook_token`