external.md 6.67 KB

External API (xlyApi)

xlyApi is the API surface external integrators consume. It runs as its own Spring Boot WAR (entry class xlyApi/src/main/java/com/xly/ApiApplicationBoot.java) at context-path /xlyApi, with its own application-*.yml files.

The defining design choice: most external endpoints are not hard-coded in Java — they are rows in sysapi. New external APIs are registered as data, like the rest of xly. The runtime's job is to look up the sApiCode, validate the caller, and execute whatever the metadata says.

The data-driven dispatcher — /api/invoke/{sApiCode}

The single most important endpoint:

POST /xlyApi/api/invoke/{sApiCode}
Authorization: Bearer <token>      (or query param ?authorizationt=<token>)
Content-Type: application/json
{ ...request body, passed through as `sBody` to the handler... }

Handler: ApiController.invoke() at xlyApi/src/main/java/com/xly/api/web/ApiController.java.

The flow:

  1. Read the Authorization header (fallback: authorizationt query parameter).
  2. Look up the sysapi row keyed by sApiCode (via ApiServiceImpl.invokeSELECT … FROM sysapi WHERE sApiCode = #{sApiCode}).
  3. If the row's bHasToken flag is set, validate the token against sysapithirdtoken (or the equivalent token store the row points at).
  4. Run the SQL template stored in sysapi.sDataSql with the request body merged into the parameter map.
  5. Log the call to sysapilog.
  6. Return the result wrapped in AjaxResult.

So adding a new external API is an admin/PM task: insert a row into sysapi, supply the SQL template, set the flags, give the integrator the sApiCode and a token. No Java code change.

sysapi columns of interest

Column Meaning
sApiCode The path variable consumers send. Must be unique per tenant.
sApiName Human label.
sApiUrl / sApiUrlRef Computed URL — sApiUrlRef + sApiCode — for outbound dispatches.
sMethod The HTTP method this API expects (GET, POST, …).
sHeader, sBody, sBodyNode, sBodyType Templates describing the inbound request shape.
sDataSql The SQL template the runtime executes. References to #{xxx} are filled from request params.
sDataTest, sDataTestNode Sample request/response used by the BACK API tester (POST /api/apiTest).
bHasToken 1 → require a token in Authorization; 0 → public.

API administration endpoints

/api/list/..., /api/data/..., /api/add, /api/edit, /api/remove are the admin surface for managing sysapi rows themselves (the BACK "自定义接口" screen calls these). POST /api/getSqlTemple produces a SQL skeleton for a given API name; POST /api/apiTest runs an end-to-end dry-run against the test fixture in sDataTest.

Token endpoints — /token/*

Endpoint Method Purpose
/token/getToken?corpid=&corpsecret= POST Issue a bearer token for an integrator's (corpid, corpsecret) pair.

The token returned is what /api/invoke/{sApiCode} expects in Authorization. The full implementation is in xlyApi/src/main/java/com/xly/api/web/TokenController.java and its service.

For third-party tokens that xly itself fetches (so it can call out-of-cluster APIs on behalf of a customer), see /thirdtoken/*, backed by sysapithirdtoken (table comment: 第三方token获取接口).

Other curated surfaces

These are smaller specialised APIs hosted in the same WAR:

Endpoint root Controller Purpose
/online/api/{sApiCode} OnlineController Read-only execution of a sysapi row (no write). Useful for public-data endpoints.
/online/onlineword/{sApiCode} OnlineController Variant returning a "word"-style template payload.
/online/onlinelist, /online/getToken OnlineController Listing of online APIs and their token issuance.
/pro/get/{sProName} ProContentController Fetch metadata about a stored procedure by name.
/pro/getData/{sProName} ProContentController Execute the named stored procedure and return its result-set.
/pro/alert/{redisId}, /pro/getAlertValue/{redisId} ProContentController Read alert/notification values keyed by Redis id.
/pro/executeSql ProContentController Execute a parameterised SQL template (admin-tier).
/thirdparty/* ThirdPartyController CRUD over third-party-API definitions and the checkPartyApi validator. Backed by sysapithirdparty.
/thirdtoken/* ThirdTokenController CRUD over outbound-token configs. Backed by sysapithirdtoken.
/brand/* BrandController CRUD over the partner-supplier list (sysapibrand).
/json/*, /json/jsonEdit/{sDomId} JsonController JSON-tree edit helpers used by the BACK API editor.
/interfaceDefine/callthirdparty/{interfaceInvoke} InterfaceController Dispatch an outbound call defined in sysapithirdparty.
/gpt/chatGpt GptController Pass-through for the experimental GPT/chat surface — out-of-scope of the framework wiki.

Backing tables (DB-level surface)

These tables hold the API metadata. All carry sBrandsId / sSubsidiaryId for tenant scoping.

Table Role
sysapi API definitions used by /api/invoke.
sysapilog Per-call audit log.
sysapibrand Partner / supplier directory.
sysapithirdparty Outbound third-party endpoint definitions.
sysapithirdtoken Outbound third-party token configs.
sysapidbtodb DB-to-DB sync API definitions.
sysapidbtodblog DB-to-DB sync run log.

How an integrator uses this

A typical first integration:

  1. Have an admin register your API. Insert a row into sysapi (via the BACK self-service screen or directly): pick sApiCode, write sDataSql, set bHasToken = 1 if you want token auth, save.
  2. Get a token. POST /xlyApi/token/getToken?corpid=<your_id>&corpsecret=<your_secret>.
  3. Call the API. POST /xlyApi/api/invoke/<your_sApiCode> with the token in Authorization and your payload as the JSON body.
  4. Inspect the log. sysapilog records every call, the response iStatus, and the body. The BACK admin screen surfaces the same.

What this API is not

  • Not OpenAPI-described — the contract for any given sApiCode is whatever its sysapi.sDataSql and sBody rows say. Get the spec from the team that registered the API, not from a /swagger endpoint here.
  • Not a thin wrapper over xlyEntry's internal API — these are intentionally separate surfaces. Calling /business/* on xlyEntry from outside is not supported.
  • Not the inbound webhook receiver — push events from third parties go through xlyInterface.