99 lines
2.8 KiB
Go
99 lines
2.8 KiB
Go
|
|
package handlers
|
||
|
|
|
||
|
|
import (
|
||
|
|
"errors"
|
||
|
|
"net/http"
|
||
|
|
|
||
|
|
apperrors "veza-backend-api/internal/errors"
|
||
|
|
"veza-backend-api/internal/services"
|
||
|
|
|
||
|
|
"github.com/gin-gonic/gin"
|
||
|
|
"go.uber.org/zap"
|
||
|
|
)
|
||
|
|
|
||
|
|
// KYCHandler handles seller identity verification endpoints (v0.13.5 TASK-MKT-001)
|
||
|
|
type KYCHandler struct {
|
||
|
|
kycService *services.KYCService
|
||
|
|
logger *zap.Logger
|
||
|
|
}
|
||
|
|
|
||
|
|
// NewKYCHandler creates a new KYC handler
|
||
|
|
func NewKYCHandler(kycService *services.KYCService, logger *zap.Logger) *KYCHandler {
|
||
|
|
return &KYCHandler{
|
||
|
|
kycService: kycService,
|
||
|
|
logger: logger,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// CreateVerificationRequest is the request body for starting KYC
|
||
|
|
type CreateVerificationRequest struct {
|
||
|
|
ReturnURL string `json:"return_url"`
|
||
|
|
}
|
||
|
|
|
||
|
|
// StartVerification creates a Stripe Identity verification session
|
||
|
|
func (h *KYCHandler) StartVerification(c *gin.Context) {
|
||
|
|
if h.kycService == nil {
|
||
|
|
RespondWithAppError(c, apperrors.NewServiceUnavailableError("KYC verification is not available"))
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
userID, ok := GetUserIDUUID(c)
|
||
|
|
if !ok {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
var req CreateVerificationRequest
|
||
|
|
_ = c.ShouldBindJSON(&req)
|
||
|
|
returnURL := req.ReturnURL
|
||
|
|
if returnURL == "" {
|
||
|
|
returnURL = c.Request.URL.Scheme + "://" + c.Request.Host + "/sell?kyc=complete"
|
||
|
|
}
|
||
|
|
|
||
|
|
session, err := h.kycService.CreateVerificationSession(c.Request.Context(), userID, returnURL)
|
||
|
|
if err != nil {
|
||
|
|
if errors.Is(err, services.ErrKYCAlreadyDone) {
|
||
|
|
RespondSuccess(c, http.StatusOK, gin.H{"status": "verified", "message": "Already verified"})
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if errors.Is(err, services.ErrKYCNotAvailable) {
|
||
|
|
RespondWithAppError(c, apperrors.NewServiceUnavailableError("KYC verification is not available"))
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if errors.Is(err, services.ErrNoStripeAccount) {
|
||
|
|
RespondWithAppError(c, apperrors.NewValidationError("Complete Stripe Connect onboarding first"))
|
||
|
|
return
|
||
|
|
}
|
||
|
|
h.logger.Error("StartVerification failed", zap.Error(err), zap.String("user_id", userID.String()))
|
||
|
|
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to start verification", err))
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
RespondSuccess(c, http.StatusCreated, session)
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetVerificationStatus returns the current KYC status for a seller
|
||
|
|
func (h *KYCHandler) GetVerificationStatus(c *gin.Context) {
|
||
|
|
if h.kycService == nil {
|
||
|
|
RespondSuccess(c, http.StatusOK, gin.H{"status": "not_available"})
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
userID, ok := GetUserIDUUID(c)
|
||
|
|
if !ok {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
status, err := h.kycService.GetVerificationStatus(c.Request.Context(), userID)
|
||
|
|
if err != nil {
|
||
|
|
if errors.Is(err, services.ErrKYCNotAvailable) {
|
||
|
|
RespondSuccess(c, http.StatusOK, gin.H{"status": "not_available"})
|
||
|
|
return
|
||
|
|
}
|
||
|
|
h.logger.Error("GetVerificationStatus failed", zap.Error(err), zap.String("user_id", userID.String()))
|
||
|
|
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to get verification status", err))
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
RespondSuccess(c, http.StatusOK, gin.H{"status": status})
|
||
|
|
}
|