76 lines
2.5 KiB
Go
76 lines
2.5 KiB
Go
package handler
|
|
|
|
import (
|
|
"net/http"
|
|
"strings"
|
|
|
|
"go-backend-template/internal/constants"
|
|
"go-backend-template/internal/contract"
|
|
"go-backend-template/internal/logger"
|
|
"go-backend-template/internal/util"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
type DukcapilHandler struct {
|
|
dukcapilService DukcapilService
|
|
}
|
|
|
|
func NewDukcapilHandler(dukcapilService DukcapilService) *DukcapilHandler {
|
|
return &DukcapilHandler{dukcapilService: dukcapilService}
|
|
}
|
|
|
|
// FaceMatch handles POST /api/v1/dukcapil/face-match (1:N face recognition).
|
|
func (h *DukcapilHandler) FaceMatch(c *gin.Context) {
|
|
var req contract.FaceMatchRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
logger.FromContext(c.Request.Context()).WithError(err).Error("DukcapilHandler::FaceMatch -> request binding failed")
|
|
h.sendValidationError(c, "Invalid request body", constants.MalformedFieldErrorCode)
|
|
return
|
|
}
|
|
|
|
if strings.TrimSpace(req.TransactionID) == "" {
|
|
h.sendValidationError(c, "transaction_id is required", constants.MissingFieldErrorCode)
|
|
return
|
|
}
|
|
if strings.TrimSpace(req.TransactionSource) == "" {
|
|
h.sendValidationError(c, "transaction_source is required", constants.MissingFieldErrorCode)
|
|
return
|
|
}
|
|
if strings.TrimSpace(req.Threshold) == "" {
|
|
h.sendValidationError(c, "threshold is required", constants.MissingFieldErrorCode)
|
|
return
|
|
}
|
|
if strings.TrimSpace(req.Image) == "" {
|
|
h.sendValidationError(c, "image is required (base64-encoded)", constants.MissingFieldErrorCode)
|
|
return
|
|
}
|
|
|
|
res, err := h.dukcapilService.FaceMatch(c.Request.Context(), &req)
|
|
if err != nil {
|
|
logger.FromContext(c.Request.Context()).WithError(err).Error("DukcapilHandler::FaceMatch -> upstream call failed")
|
|
c.JSON(http.StatusBadGateway, &contract.ErrorResponse{
|
|
Error: "upstream_error",
|
|
Message: err.Error(),
|
|
Code: http.StatusBadGateway,
|
|
Details: map[string]interface{}{"entity": constants.DukcapilHandlerEntity},
|
|
})
|
|
return
|
|
}
|
|
|
|
logger.FromContext(c.Request.Context()).Infof("DukcapilHandler::FaceMatch -> tid=%s errorCode=%s matches=%d", res.TID, res.ErrorCode, len(res.Matches))
|
|
util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(res), "DukcapilHandler::FaceMatch")
|
|
}
|
|
|
|
func (h *DukcapilHandler) sendValidationError(c *gin.Context, message, code string) {
|
|
c.JSON(http.StatusBadRequest, &contract.ErrorResponse{
|
|
Error: "validation_error",
|
|
Message: message,
|
|
Code: http.StatusBadRequest,
|
|
Details: map[string]interface{}{
|
|
"error_code": code,
|
|
"entity": constants.DukcapilHandlerEntity,
|
|
},
|
|
})
|
|
}
|