external.md 7.56 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:223. The mapping is @RequestMapping (method-agnostic at the framework level); the per-API sysapi.sMethod column declares the expected verb for callers, and ApiCheckUtil enforces it at dispatch.

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, AES-decrypt the bearer token to recover the corpid, then validate that corpid against sysapibrand via BrandServiceImpl.selectByCorpid. If the brand row's iLossTime is non-zero, also check the token's embedded timestamp hasn't expired. (sysapithirdtoken is for outbound tokens — xly calling third-party APIs — not for validating inbound bearer tokens here.)
  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= GET / POST Issue a bearer token for an integrator's (corpid, corpsecret) pair. (Mapping is method-agnostic.)

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 Renders the BACK in-browser API debug/console page for the given sysapi row (returns a Thymeleaf view, not API execution).
/online/onlineword/{sApiCode} OnlineController Renders the "word"-style API documentation page.
/online/onlinelist OnlineController Renders the online-API listing page.
/online/getToken OnlineController Renders the in-browser token-acquisition helper page.
/pro/get/{sProName} ProContentController Renders the BACK page that displays a stored procedure's source.
/pro/getData/{sProName} ProContentController Returns the stored procedure's source text (not its result-set).
/pro/alert/{redisId} ProContentController Renders the alert/notification display page for the given Redis key.
/pro/getAlertValue/{redisId} ProContentController Returns the value cached in Redis under redisId.
/pro/executeSql ProContentController Executes a sSql payload directly (admin-tier dev tool).
/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. Owned by xlyFlow's DbToDbController, not xlyApi — listed here because the table lives in xlyApi's sysapi.sql.
sysapidbtodblog DB-to-DB sync run log. Same — written by xlyFlow.

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.