Skip to main content

LINE OA Verification

Overview

POST /api/line-oa/verify lets an external system holding an api-key confirm which LINE OA its credentials are bound to, and whether that matches the OA it expects.

The caller submits a LINE OA channelId (optionally with channelSecret). The service searches the line_oa.line_login_info JSONB column and compares the OA it finds against the caller's api_key.line_oa_id. A match passes; a mismatch or a miss returns 404.

This feature has one important side effect: on every call it attempts, on a best-effort basis, to seed four starter audiences for the caller. As a result, the endpoint is commonly used as the "getting started" call that partners make first during onboarding.

Business Flow

  1. The request passes through the api-key middleware (see API Key Authentication), yielding apiClientId and apiKey.
  2. Loosely bind the body — the original had no DTO — reading channelId and the optional channelSecret. A malformed or empty body simply leaves zero values in place and execution continues, ultimately ending in a 404.
  3. Step 1 — resolve the api_key row with SELECT ... FROM api_key WHERE api_client_id=$1 AND key=$2 AND status='active'. A genuine database error surfaces as 500, not 404.
  4. Step 2 — find the LINE OA from JSONB with SELECT ... FROM line_oa WHERE line_login_info->>'channelId' = $1. When the body supplies channelSecret, the predicate AND line_login_info->>'channelSecret' = $2 is appended. Text extraction replaces the original TypeORM object-equality comparison so that an index can be used.
  5. Step 3 — seed the audience templates on a best-effort basis by calling audience.Service.CreateAudienceTemplate(apiClientId, apiKey), which creates the mookept-1 through mookept-4 slugs when they do not yet exist (see Managing Audience Members via Public API). Errors here are swallowed, matching the original try/catch, and the data field comes back as null.
  6. Step 4 — compare the identifiers:
    • If lineOa.ID equals apiKeyEntity.LineOaID, respond 200 with {code:"RES_SUCCESS_001", message:"verify success", data:(audience list)}.
    • On a mismatch, or if either side is missing, respond 404 with the message "Channel ID and Channel Secret is required" (originally coded LINE_OA_001).

:::note Two things worth knowing

  1. Seeding happens before the verification check. Calling with the wrong channelId still seeds audiences for the caller before the 404 is returned — deliberate parity with the original execution order.
  2. The Go port's error envelope follows the standard NestJS shape, {statusCode, message, error}. The code passed to NewException is dropped, as documented in a comment on httpx.NewException. :::

Key Files & Functions

MethodRouteAuthHandler
POST/api/line-oa/verifyapi-keyHandler.verify

All source lives under internal/lineoa/.

FileHighlights
handler.goRegister (wrapped in deps.APIKeyAuth()), Handler.verify, caller, type verifyBody, audienceTemplateAdapter
service.goService.Verify(ctx, apiClientID, apiKey, channelID, channelSecret), type VerifyResult, interfaces scopeResolver / lineOaFinder / templateCreator
repository.goRepository.FindByLineLoginInfo(ctx, channelID, channelSecret *string) — the JSONB predicate
entity.gostruct LineOa (22 columns) and LineLoginInfo (jsonb Scanner/Valuer)

channelSecret is intentionally a *string: omitting it drops the second predicate entirely, which differs from passing an empty string that would be compared against ''.

Connections to Other Services

  • Postgres — the line_oa table (JSONB column line_login_info), plus api_key, api_client, and audience, all accessed via the pgx simple protocol. That protocol choice is critical for JSONB and enum binding; see Core HTTP & Database Access.
  • The in-process audience modulelineoa.Register constructs its own audience.Service in order to call CreateAudienceTemplate, which is why AMQP and exchange configuration must be present even though this path never publishes a message.
  • cms-api — the line-oa-management module owns the contents of line_oa.line_login_info (channelId, channelSecret, lineLiffId, formLiffId), while api-key issues the caller's key.
  • Related database domains: line-oa-channel, api-client-key, and audience.
  • No Redis or RabbitMQ is used on the verify path itself, aside from the dependencies the audience service brings along.