From c27e3945d53a77c3692529766f8946ff37b11254 Mon Sep 17 00:00:00 2001 From: AmirMahdi Qiasvand Date: Mon, 15 Sep 2025 16:52:05 +0330 Subject: [PATCH] feat: add kyc service http handler and docs --- docs/docs.go | 79 ++++++++++++++++++++++ docs/swagger.json | 79 ++++++++++++++++++++++ docs/swagger.yaml | 52 ++++++++++++++ internal/api/dto/auth.go | 10 +++ internal/api/http/handlers/auth_handler.go | 31 +++++++++ internal/api/http/setup.go | 2 + internal/usecase/auth_service.go | 1 + 7 files changed, 254 insertions(+) diff --git a/docs/docs.go b/docs/docs.go index 1bd9670..e8f8d6b 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -171,6 +171,58 @@ const docTemplate = `{ } } }, + "/auth/verify-kyc": { + "post": { + "description": "Verify user KYC with national ID and birth date", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "auth" + ], + "summary": "Verify user KYC", + "parameters": [ + { + "description": "KYC Verify Request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.KYCVerifyRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/dto.KYCVerifyResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, "/auth/verify-otp": { "post": { "description": "Verify the provided OTP code for the phone number", @@ -279,6 +331,33 @@ const docTemplate = `{ } } }, + "dto.KYCVerifyRequest": { + "type": "object", + "required": [ + "birthDate", + "nationalId", + "userId" + ], + "properties": { + "birthDate": { + "type": "string" + }, + "nationalId": { + "type": "string" + }, + "userId": { + "type": "string" + } + } + }, + "dto.KYCVerifyResponse": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + }, "dto.OTPProviderReq": { "type": "object", "properties": { diff --git a/docs/swagger.json b/docs/swagger.json index a03419f..b629186 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -160,6 +160,58 @@ } } }, + "/auth/verify-kyc": { + "post": { + "description": "Verify user KYC with national ID and birth date", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "auth" + ], + "summary": "Verify user KYC", + "parameters": [ + { + "description": "KYC Verify Request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.KYCVerifyRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/dto.KYCVerifyResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, "/auth/verify-otp": { "post": { "description": "Verify the provided OTP code for the phone number", @@ -268,6 +320,33 @@ } } }, + "dto.KYCVerifyRequest": { + "type": "object", + "required": [ + "birthDate", + "nationalId", + "userId" + ], + "properties": { + "birthDate": { + "type": "string" + }, + "nationalId": { + "type": "string" + }, + "userId": { + "type": "string" + } + } + }, + "dto.KYCVerifyResponse": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + }, "dto.OTPProviderReq": { "type": "object", "properties": { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index adc198c..7be45f2 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -34,6 +34,24 @@ definitions: timeStamp: type: string type: object + dto.KYCVerifyRequest: + properties: + birthDate: + type: string + nationalId: + type: string + userId: + type: string + required: + - birthDate + - nationalId + - userId + type: object + dto.KYCVerifyResponse: + properties: + message: + type: string + type: object dto.OTPProviderReq: properties: receptor: @@ -164,6 +182,40 @@ paths: summary: Send OTP code tags: - auth + /auth/verify-kyc: + post: + consumes: + - application/json + description: Verify user KYC with national ID and birth date + parameters: + - description: KYC Verify Request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.KYCVerifyRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/dto.KYCVerifyResponse' + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + summary: Verify user KYC + tags: + - auth /auth/verify-otp: post: consumes: diff --git a/internal/api/dto/auth.go b/internal/api/dto/auth.go index 2a41ee9..6039b9b 100644 --- a/internal/api/dto/auth.go +++ b/internal/api/dto/auth.go @@ -41,3 +41,13 @@ type OTPVerifyRequest struct { type OTPVerifyResponse struct { Message string `json:"message"` } + +type KYCVerifyRequest struct { + UserID string `json:"userId" validate:"required,uuid"` + NationalID string `json:"nationalId" validate:"required"` + BirthDate string `json:"birthDate" validate:"required"` +} + +type KYCVerifyResponse struct { + Message string `json:"message"` +} diff --git a/internal/api/http/handlers/auth_handler.go b/internal/api/http/handlers/auth_handler.go index 432e7c0..056eb2f 100644 --- a/internal/api/http/handlers/auth_handler.go +++ b/internal/api/http/handlers/auth_handler.go @@ -153,6 +153,37 @@ func (h *AuthHandler) VerifyOTP(c *fiber.Ctx) error { }) } +// VerifyKYC verifies user KYC information +// @Summary Verify user KYC +// @Description Verify user KYC with national ID and birth date +// @Tags auth +// @Accept json +// @Produce json +// @Param request body dto.KYCVerifyRequest true "KYC Verify Request" +// @Success 200 {object} dto.KYCVerifyResponse +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /auth/verify-kyc [post] +func (h *AuthHandler) VerifyKYC(c *fiber.Ctx) error { + var req dto.KYCVerifyRequest + if err := c.BodyParser(&req); err != nil { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ + "error": "invalid request body", + }) + } + + err := h.authService.VerifyKYC(c.Context(), req.UserID, req.NationalID, req.BirthDate) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ + "error": err.Error(), + }) + } + + return c.Status(fiber.StatusOK).JSON(dto.KYCVerifyResponse{ + Message: "KYC verified successfully", + }) +} + func (h *AuthHandler) HelloWorld(c *fiber.Ctx) error { return c.Status(fiber.StatusOK).JSON(fiber.Map{ "message": "Hello, World!", diff --git a/internal/api/http/setup.go b/internal/api/http/setup.go index 6a72028..4c05f47 100644 --- a/internal/api/http/setup.go +++ b/internal/api/http/setup.go @@ -49,4 +49,6 @@ func registerPublicRoutes(router fiber.Router, app *app.AppContainer) { authgroup.Post("/authenticate", authHandler.Authenticate) authgroup.Post("/send-otp", authHandler.SendOTP) authgroup.Post("/verify-otp", authHandler.VerifyOTP) + // add JWT middleware for KYC + authgroup.Post("/verify-kyc", authHandler.VerifyKYC) } diff --git a/internal/usecase/auth_service.go b/internal/usecase/auth_service.go index 7daab5b..e4b2916 100644 --- a/internal/usecase/auth_service.go +++ b/internal/usecase/auth_service.go @@ -23,6 +23,7 @@ type AuthService interface { Authenticate(ctx context.Context, pubKey string, signature string, chainID uint, ipAddress, userAgent string) (*UserToken, error) SendOTPCode(ctx context.Context, phone string) (string, error) VerifyOTP(ctx context.Context, phone, code string) error + VerifyKYC(ctx context.Context, userID, nationalID, birthDate string) error } type authService struct {