// Service: VClaim (vclaim) // Description: BPJS VClaim service for eligibility and SEP management package peserta import ( "context" "encoding/json" "net/http" "strings" "time" "api-service/internal/config" "api-service/internal/models" services "api-service/internal/services/bpjs" "api-service/pkg/logger" "github.com/gin-gonic/gin" "github.com/go-playground/validator/v10" "github.com/google/uuid" ) // PesertaData represents peserta information from BPJS type PesertaData struct { NoKartu string `json:"noKartu"` NIK string `json:"nik"` Nama string `json:"nama"` Pisa string `json:"pisa"` Sex string `json:"sex"` TanggalLahir string `json:"tglLahir"` TglCetakKartu string `json:"tglCetakKartu"` TglTAT string `json:"tglTAT"` TglTMT string `json:"tglTMT"` StatusPeserta struct { Kode string `json:"kode"` Keterangan string `json:"keterangan"` } `json:"statusPeserta"` ProvUmum struct { KdProvider string `json:"kdProvider"` NmProvider string `json:"nmProvider"` } `json:"provUmum"` JenisPeserta struct { Kode string `json:"kode"` Keterangan string `json:"keterangan"` } `json:"jenisPeserta"` HakKelas struct { Kode string `json:"kode"` Keterangan string `json:"keterangan"` } `json:"hakKelas"` Umur struct { UmurSekarang string `json:"umurSekarang"` UmurSaatPelayanan string `json:"umurSaatPelayanan"` } `json:"umur"` Informasi struct { Dinsos interface{} `json:"dinsos"` ProlanisPRB string `json:"prolanisPRB"` NoSKTM interface{} `json:"noSKTM"` ESEP interface{} `json:"eSEP"` } `json:"informasi"` Cob struct { NoAsuransi interface{} `json:"noAsuransi"` NmAsuransi interface{} `json:"nmAsuransi"` TglTMT interface{} `json:"tglTMT"` TglTAT interface{} `json:"tglTAT"` } `json:"cob"` MR struct { NoMR string `json:"noMR"` NoTelepon string `json:"noTelepon"` } `json:"mr,omitempty"` } // PesertaResponse represents peserta API response type PesertaResponse struct { models.BaseResponse Data *PesertaData `json:"data,omitempty"` MetaData interface{} `json:"metaData,omitempty"` } // VClaimHandler handles VClaim BPJS services type VClaimHandler struct { service services.VClaimService validator *validator.Validate logger logger.Logger config config.BpjsConfig } // VClaimHandlerConfig contains configuration for VClaimHandler type VClaimHandlerConfig struct { BpjsConfig config.BpjsConfig Logger logger.Logger Validator *validator.Validate } // NewVClaimHandler creates a new VClaimHandler func NewVClaimHandler(cfg VClaimHandlerConfig) *VClaimHandler { return &VClaimHandler{ service: services.NewService(cfg.BpjsConfig), validator: cfg.Validator, logger: cfg.Logger, config: cfg.BpjsConfig, } } // GetPesertaBynokartu godoc // @Summary Get PesertaBynokartu data // @Description Get participant eligibility information by card number // @Tags Peserta // @Accept json // @Produce json // @Security ApiKeyAuth // @Param X-Request-ID header string false "Request ID for tracking" // @Param nokartu path string true "nokartu" example("example_value") // @Success 200 {object} peserta.PesertaResponse "Successfully retrieved PesertaBynokartu data" // @Failure 400 {object} models.ErrorResponseBpjs "Bad request - invalid parameters" // @Failure 401 {object} models.ErrorResponseBpjs "Unauthorized - invalid API credentials" // @Failure 404 {object} models.ErrorResponseBpjs "Not found - PesertaBynokartu not found" // @Failure 500 {object} models.ErrorResponseBpjs "Internal server error" // @Router /peserta/:nokartu [get] func (h *VClaimHandler) GetPesertaBynokartu(c *gin.Context) { ctx, cancel := context.WithTimeout(c.Request.Context(), 30*time.Second) defer cancel() // Generate request ID if not present requestID := c.GetHeader("X-Request-ID") if requestID == "" { requestID = uuid.New().String() c.Header("X-Request-ID", requestID) } h.logger.Info("Processing GetPesertaBynokartu request", map[string]interface{}{ "request_id": requestID, "nokartu": c.Param("nokartu"), "tglsep": c.Param("tglsep"), }) // Extract path parameters nokartu := c.Param("nokartu") tglsep := c.Param("tglsep") if nokartu == "" { h.logger.Error("Missing required parameter nokartu", map[string]interface{}{ "request_id": requestID, }) c.JSON(http.StatusBadRequest, models.ErrorResponseBpjs{ Status: "error", Message: "Missing required parameter nokartu", RequestID: requestID, }) return } // Call service method var response PesertaResponse endpoint := "/Peserta/nokartu/:nokartu/tglSEP/:tglsep" endpoint = strings.Replace(endpoint, ":nokartu", nokartu, 1) endpoint = strings.Replace(endpoint, ":tglsep", tglsep, 1) resp, err := h.service.GetRawResponse(ctx, endpoint) if err != nil { h.logger.Error("Failed to get PesertaBynokartu", map[string]interface{}{ "error": err.Error(), "request_id": requestID, }) c.JSON(http.StatusInternalServerError, models.ErrorResponseBpjs{ Status: "error", Message: "Internal server error", RequestID: requestID, }) return } // Map the raw response response.MetaData = resp.MetaData if resp.Response != nil { response.Data = &PesertaData{} if respStr, ok := resp.Response.(string); ok { // Decrypt the response string consID, secretKey, _, tstamp, _ := h.config.SetHeader() decryptedResp, err := services.ResponseVclaim(respStr, consID+secretKey+tstamp) if err != nil { h.logger.Error("Failed to decrypt response", map[string]interface{}{ "error": err.Error(), "request_id": requestID, }) } else { json.Unmarshal([]byte(decryptedResp), response.Data) } } else if respMap, ok := resp.Response.(map[string]interface{}); ok { // Response is already unmarshaled JSON if pesertaMap, exists := respMap["peserta"]; exists { pesertaBytes, _ := json.Marshal(pesertaMap) json.Unmarshal(pesertaBytes, response.Data) } else { // Try to unmarshal the whole response respBytes, _ := json.Marshal(resp.Response) json.Unmarshal(respBytes, response.Data) } } } // Ensure response has proper fields response.Status = "success" response.RequestID = requestID c.JSON(http.StatusOK, response) } // GetPesertaBynik godoc // @Summary Get PesertaBynik data // @Description Get participant eligibility information by NIK // @Tags Peserta // @Accept json // @Produce json // @Security ApiKeyAuth // @Param X-Request-ID header string false "Request ID for tracking" // @Param nik path string true "nik" example("example_value") // @Success 200 {object} peserta.PesertaResponse "Successfully retrieved PesertaBynik data" // @Failure 400 {object} models.ErrorResponseBpjs "Bad request - invalid parameters" // @Failure 401 {object} models.ErrorResponseBpjs "Unauthorized - invalid API credentials" // @Failure 404 {object} models.ErrorResponseBpjs "Not found - PesertaBynik not found" // @Failure 500 {object} models.ErrorResponseBpjs "Internal server error" // @Router /peserta/nik/:nik [get] func (h *VClaimHandler) GetPesertaBynik(c *gin.Context) { ctx, cancel := context.WithTimeout(c.Request.Context(), 30*time.Second) defer cancel() // Generate request ID if not present requestID := c.GetHeader("X-Request-ID") if requestID == "" { requestID = uuid.New().String() c.Header("X-Request-ID", requestID) } h.logger.Info("Processing GetPesertaBynik request", map[string]interface{}{ "request_id": requestID, "endpoint": "/peserta/nik/:nik", "nik": c.Param("nik"), }) // Extract path parameters nik := c.Param("nik") if nik == "" { h.logger.Error("Missing required parameter nik", map[string]interface{}{ "request_id": requestID, }) c.JSON(http.StatusBadRequest, models.ErrorResponseBpjs{ Status: "error", Message: "Missing required parameter nik", RequestID: requestID, }) return } // Call service method var response PesertaResponse endpoint := "/peserta/nik/:nik" endpoint = strings.Replace(endpoint, ":nik", nik, 1) resp, err := h.service.GetRawResponse(ctx, endpoint) if err != nil { h.logger.Error("Failed to get PesertaBynik", map[string]interface{}{ "error": err.Error(), "request_id": requestID, }) c.JSON(http.StatusInternalServerError, models.ErrorResponseBpjs{ Status: "error", Message: "Internal server error", RequestID: requestID, }) return } // Map the raw response response.MetaData = resp.MetaData if resp.Response != nil { response.Data = &PesertaData{} if respStr, ok := resp.Response.(string); ok { // Decrypt the response string consID, secretKey, _, tstamp, _ := h.config.SetHeader() decryptedResp, err := services.ResponseVclaim(respStr, consID+secretKey+tstamp) if err != nil { h.logger.Error("Failed to decrypt response", map[string]interface{}{ "error": err.Error(), "request_id": requestID, }) } else { json.Unmarshal([]byte(decryptedResp), response.Data) } } else if respMap, ok := resp.Response.(map[string]interface{}); ok { // Response is already unmarshaled JSON if pesertaMap, exists := respMap["peserta"]; exists { pesertaBytes, _ := json.Marshal(pesertaMap) json.Unmarshal(pesertaBytes, response.Data) } else { // Try to unmarshal the whole response respBytes, _ := json.Marshal(resp.Response) json.Unmarshal(respBytes, response.Data) } } } // Ensure response has proper fields response.Status = "success" response.RequestID = requestID c.JSON(http.StatusOK, response) }