Реализована интеграция с СМС провайдером

This commit is contained in:
mi
2026-07-23 11:49:15 +03:00
parent cc0163eb94
commit b1ed714d5b
89 changed files with 5934 additions and 202 deletions
+314
View File
@@ -0,0 +1,314 @@
openapi: 3.1.0
info:
title: HAN SMS Service
version: 1.0.0
description: Durable internal SMS ordering and i-Digital delivery callbacks.
servers:
- url: http://sms-service:8080
paths:
/internal/sms/v1/send:
post:
operationId: orderSms
security:
- serviceBearer: []
parameters:
- $ref: "#/components/parameters/RequestId"
- $ref: "#/components/parameters/Traceparent"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/SendRequest"
responses:
"202":
description: New order durably committed; provider has not necessarily been called.
content:
application/json:
schema:
$ref: "#/components/schemas/SendResponse"
"200":
description: Idempotent replay of an existing order.
content:
application/json:
schema:
$ref: "#/components/schemas/SendResponse"
"401":
$ref: "#/components/responses/Unauthorized"
"409":
$ref: "#/components/responses/IdempotencyConflict"
"422":
$ref: "#/components/responses/InvalidRequest"
"429":
$ref: "#/components/responses/RateLimited"
"503":
$ref: "#/components/responses/Unavailable"
/internal/sms/v1/messages/{sms_message_id}:
get:
operationId: readSmsOrder
security:
- serviceBearer: []
parameters:
- name: sms_message_id
in: path
required: true
schema:
type: string
format: uuid
- $ref: "#/components/parameters/RequestId"
responses:
"200":
description: Redacted message diagnostics; never contains OTP, body, or full phone.
content:
application/json:
schema:
$ref: "#/components/schemas/Message"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
/callbacks/idgtl/sms:
post:
operationId: acceptIdgtlCallback
security:
- callbackBasic: []
requestBody:
required: true
content:
application/json:
schema:
type: array
minItems: 1
maxItems: 1000
items:
$ref: "#/components/schemas/IdgtlCallbackItem"
responses:
"204":
description: Valid callback items committed; invalid items were safely ignored.
"401":
$ref: "#/components/responses/Unauthorized"
"422":
$ref: "#/components/responses/InvalidRequest"
webhooks:
idgtlDeliveryStatus:
post:
summary: The same payload accepted at /callbacks/idgtl/sms.
security:
- callbackBasic: []
requestBody:
required: true
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/IdgtlCallbackItem"
responses:
"204":
description: Callback committed.
components:
securitySchemes:
serviceBearer:
type: http
scheme: bearer
bearerFormat: opaque-service-token
callbackBasic:
type: http
scheme: basic
parameters:
RequestId:
name: X-Request-ID
in: header
required: false
schema:
type: string
maxLength: 128
Traceparent:
name: traceparent
in: header
required: false
schema:
type: string
pattern: "^[\\da-f]{2}-[\\da-f]{32}-[\\da-f]{16}-[\\da-f]{2}$"
schemas:
SendRequest:
type: object
additionalProperties: false
required:
- idempotency_key
- template_code
- locale
- phone_e164
- substitutions
- customer_ref
- message_ttl_sec
properties:
idempotency_key:
type: string
minLength: 8
maxLength: 192
template_code:
const: auth_otp
locale:
const: ru
phone_e164:
type: string
pattern: "^\\+[1-9]\\d{7,14}$"
substitutions:
type: object
additionalProperties: false
required: [code, ttl_min]
properties:
code:
type: string
pattern: "^\\d{4,10}$"
ttl_min:
oneOf:
- type: string
pattern: "^\\d{1,3}$"
- type: integer
minimum: 1
maximum: 1440
customer_ref:
type: string
minLength: 1
maxLength: 128
message_ttl_sec:
type: integer
minimum: 60
maximum: 86400
SendResponse:
type: object
additionalProperties: false
required: [sms_message_id, ordered_at]
properties:
sms_message_id:
type: string
format: uuid
ordered_at:
type: string
format: date-time
Message:
type: object
additionalProperties: false
description: Deliberately excludes phone_e164, body_rendered, and substitutions.
required:
- sms_message_id
- ordered_at
- updated_at
- requester_service
- process
- channel
- provider
- phone_masked
- template_code
- send_status
- delivery_status
- attempt_count
properties:
sms_message_id: {type: string, format: uuid}
ordered_at: {type: string, format: date-time}
updated_at: {type: string, format: date-time}
requester_service: {const: keycloak}
process: {const: auth_otp}
channel: {const: SMS}
provider: {const: idgtl}
phone_masked: {type: string}
template_code: {const: auth_otp}
customer_ref: {type: [string, "null"]}
send_status:
enum: [pending, accepted, rejected, failed, uncertain, skipped]
delivery_status:
enum: [unknown, sent, delivered, undelivered, unsent]
provider_message_id: {type: [string, "null"]}
accepted_at: {type: [string, "null"], format: date-time}
sent_at: {type: [string, "null"], format: date-time}
delivered_at: {type: [string, "null"], format: date-time}
attempt_count: {type: integer, minimum: 0}
provider_error_code: {type: [string, "null"]}
IdgtlCallbackItem:
type: object
required:
- channelType
- messageUuid
- externalMessageId
- callbackEvent
- status
- statusTime
properties:
channelType:
const: SMS
messageUuid:
type: string
externalMessageId:
type: string
callbackEvent:
type: string
status:
enum: [sent, delivered, undelivered, unsent]
statusTime:
type: string
format: date-time
errorCode:
type: [string, "null"]
parts:
type: [integer, "null"]
minimum: 0
price:
type: [number, "null"]
minimum: 0
currency:
type: [string, "null"]
minLength: 3
maxLength: 3
Error:
type: object
additionalProperties: false
required: [error]
properties:
error:
type: object
additionalProperties: false
required: [code, message, request_id, details]
properties:
code: {type: string}
message: {type: string}
request_id: {type: string}
details:
oneOf:
- type: object
- type: array
responses:
Unauthorized:
description: Missing or invalid credentials.
content:
application/json:
schema: {$ref: "#/components/schemas/Error"}
IdempotencyConflict:
description: The key was already used with another meaningful payload.
content:
application/json:
schema: {$ref: "#/components/schemas/Error"}
InvalidRequest:
description: Strict request or callback validation failed.
content:
application/json:
schema: {$ref: "#/components/schemas/Error"}
RateLimited:
description: Caller and destination rate limit exceeded.
headers:
Retry-After:
schema: {type: integer}
content:
application/json:
schema: {$ref: "#/components/schemas/Error"}
Unavailable:
description: The order could not be durably committed.
content:
application/json:
schema: {$ref: "#/components/schemas/Error"}
NotFound:
description: Message was not found in the caller scope.
content:
application/json:
schema: {$ref: "#/components/schemas/Error"}