From 92ba4e6e45fc9dfc84393a3a9e9bf39848c3f13f Mon Sep 17 00:00:00 2001 From: Alejandro Gomez Auad Date: Wed, 6 May 2026 01:43:24 +0000 Subject: [PATCH] Agregados los metodo GetDocumentReference en ips/client/client.go y CreateQR y Validate en vhl/client/client.go --- internal/ips/client/client.go | 63 ++++++++++++++---- internal/vhl/client/client.go | 119 ++++++++++++++++++++++++++++++---- 2 files changed, 156 insertions(+), 26 deletions(-) diff --git a/internal/ips/client/client.go b/internal/ips/client/client.go index 930d263..6b696c7 100644 --- a/internal/ips/client/client.go +++ b/internal/ips/client/client.go @@ -3,7 +3,6 @@ package client import ( "encoding/json" "fmt" - "io" "ips-lacpass-backend/pkg/errors" "ips-lacpass-backend/pkg/utils" "net/http" @@ -49,21 +48,61 @@ func request(client *http.Client, req *http.Request) (*http.Response, error) { } func (c *IpsClient) GetDocumentReference(identifier string) (*Bundle, error) { - // TODO: To be implemented by the participant - return nil, &errors.HttpError{ - StatusCode: 500, - Body: []map[string]interface{}{{"error": "Not implemented error", "message": "this method is not implemented yet"}}, - Err: fmt.Errorf("failed to get document reference"), + req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/DocumentReference?identifier=%s", c.BaseURL, identifier), nil) + if err != nil { + return nil, &errors.HttpError{ + StatusCode: http.StatusInternalServerError, + Body: []map[string]interface{}{{"error": "internal_error", "message": "Failed to create request"}}, + Err: err, + } } + req.Header.Set("Accept", "application/fhir+json, application/json") + + resp, err := request(c.Client, req) + if err != nil { + return nil, err + } + defer utils.CloseBody(resp.Body) + + var bundle Bundle + if err := json.NewDecoder(resp.Body).Decode(&bundle); err != nil { + return nil, &errors.HttpError{ + StatusCode: http.StatusInternalServerError, + Body: []map[string]interface{}{{"error": "internal_error", "message": "Failed to decode DocumentReference bundle"}}, + Err: fmt.Errorf("failed to decode DocumentReference bundle: %w", err), + } + } + + return &bundle, nil } func (c *IpsClient) GetIpsBundle(url string) (map[string]interface{}, error) { - // TODO: To be implemented by the participant - return nil, &errors.HttpError{ - StatusCode: 500, - Body: []map[string]interface{}{{"error": "Not implemented error", "message": "this method is not implemented yet"}}, - Err: fmt.Errorf("failed to get document reference"), + req, err := http.NewRequest(http.MethodGet, url, nil) + if err != nil { + return nil, &errors.HttpError{ + StatusCode: http.StatusInternalServerError, + Body: []map[string]interface{}{{"error": "internal_error", "message": "Failed to create request"}}, + Err: err, + } } + req.Header.Set("Accept", "application/fhir+json, application/json") + + resp, err := request(c.Client, req) + if err != nil { + return nil, err + } + defer utils.CloseBody(resp.Body) + + var bundle map[string]interface{} + if err := json.NewDecoder(resp.Body).Decode(&bundle); err != nil { + return nil, &errors.HttpError{ + StatusCode: http.StatusInternalServerError, + Body: []map[string]interface{}{{"error": "internal_error", "message": "Failed to decode IPS bundle"}}, + Err: fmt.Errorf("failed to decode IPS bundle: %w", err), + } + } + + return bundle, nil } func (c *IpsClient) GetIpsICVP(idBundle string, immunizationId *string) (string, error) { @@ -73,4 +112,4 @@ func (c *IpsClient) GetIpsICVP(idBundle string, immunizationId *string) (string, Body: []map[string]interface{}{{"error": "Not implemented error", "message": "this method is not implemented yet"}}, Err: fmt.Errorf("failed to get document reference"), } -} \ No newline at end of file +} diff --git a/internal/vhl/client/client.go b/internal/vhl/client/client.go index e33e8cd..6d49255 100644 --- a/internal/vhl/client/client.go +++ b/internal/vhl/client/client.go @@ -9,6 +9,7 @@ import ( "ips-lacpass-backend/pkg/errors" "ips-lacpass-backend/pkg/utils" "net/http" + "net/url" ) type VhlClient struct { @@ -27,29 +28,119 @@ func NewClient(baseURL string, icvpValidatorUrl string) VhlClient { func (c *VhlClient) CreateQr(ctx context.Context, body CreateQrRequest) (*QrData, error) { // TODO: To be implemented by the participant - return nil, &errors.HttpError{ - StatusCode: 500, - Body: []map[string]interface{}{{"error": "Not implemented error", "message": "this method is not implemented yet"}}, - Err: fmt.Errorf("failed to get document reference"), + resp, err := c.Client.Post(fmt.Sprintf("%s/v2/vshcIssuance", c.BaseURL), "application/json", bytes.NewBuffer(body)) + if resp.StatusCode != http.StatusOK { + return nil, &errors.HttpError{ + StatusCode: 500, + Body: []map[string]interface{}{{"error": "Not implemented error", "message": "this method is not implemented yet"}}, + Err: fmt.Errorf("failed to get document reference"), + } } + return resp, nil } func (c *VhlClient) Validate(ctx context.Context, qrData string) (*QRValidationResponse, error) { - // TODO: To be implemented by the participant - return nil, &errors.HttpError{ - StatusCode: 500, - Body: []map[string]interface{}{{"error": "Not implemented error", "message": "this method is not implemented yet"}}, - Err: fmt.Errorf("failed to get document reference"), + body, err := json.Marshal(QrValidationRequest{QRCodeContent: qrData}) + if err != nil { + return nil, fmt.Errorf("failed to marshal validation payload: %w", err) } + resp, err := c.Client.Post(fmt.Sprintf("%s/v2/vshcValidation", c.BaseURL), "application/json", bytes.NewBuffer(body)) + if err != nil { + return nil, &errors.HttpError{ + StatusCode: http.StatusBadGateway, + Body: []map[string]interface{}{{"error": "service_unavailable", "message": "Failed to connect to VHL service"}}, + Err: err, + } + } + defer utils.CloseBody(resp.Body) + + if resp.StatusCode != http.StatusOK { + bodyBytes, readErr := io.ReadAll(resp.Body) + if readErr != nil { + return nil, &errors.HttpError{ + StatusCode: resp.StatusCode, + Body: []map[string]interface{}{{"error": "internal_error", "message": "Failed to read response body"}}, + Err: readErr, + } + } + return nil, &errors.HttpError{ + StatusCode: resp.StatusCode, + Body: []map[string]interface{}{{"error": "service_error", "message": string(bodyBytes)}}, + Err: fmt.Errorf("unexpected status code %d: %s", resp.StatusCode, string(bodyBytes)), + } + } + + var valResp QRValidationResponse + if err := json.NewDecoder(resp.Body).Decode(&valResp); err != nil { + return nil, &errors.HttpError{ + StatusCode: http.StatusInternalServerError, + Body: []map[string]interface{}{{"error": "internal_error", "message": "Failed to decode response"}}, + Err: err, + } + } + return &valResp, nil } func (c *VhlClient) GetIpsUrl(ctx context.Context, shLink string, passCode string) (*VhlManifestResponse, error) { - // TODO: To be implemented by the participant - return nil, &errors.HttpError{ - StatusCode: 500, - Body: []map[string]interface{}{{"error": "Not implemented error", "message": "this method is not implemented yet"}}, - Err: fmt.Errorf("failed to get document reference"), + u, err := url.Parse(fmt.Sprintf("%s/ips-url", c.BaseURL)) + if err != nil { + return nil, &errors.HttpError{ + StatusCode: http.StatusInternalServerError, + Body: []map[string]interface{}{{"error": "internal_error", "message": "Failed to create request"}}, + Err: err, + } } + + q := u.Query() + q.Set("shLink", shLink) + q.Set("passCode", passCode) + u.RawQuery = q.Encode() + + req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil) + if err != nil { + return nil, &errors.HttpError{ + StatusCode: http.StatusInternalServerError, + Body: []map[string]interface{}{{"error": "internal_error", "message": "Failed to create request"}}, + Err: err, + } + } + req.Header.Set("Accept", "application/json") + + resp, err := c.Client.Do(req) + if err != nil { + return nil, &errors.HttpError{ + StatusCode: http.StatusBadGateway, + Body: []map[string]interface{}{{"error": "service_unavailable", "message": "Failed to connect to VHL service"}}, + Err: err, + } + } + defer utils.CloseBody(resp.Body) + + if resp.StatusCode != http.StatusOK { + bodyBytes, readErr := io.ReadAll(resp.Body) + if readErr != nil { + return nil, &errors.HttpError{ + StatusCode: resp.StatusCode, + Body: []map[string]interface{}{{"error": "internal_error", "message": "Failed to read response body"}}, + Err: readErr, + } + } + return nil, &errors.HttpError{ + StatusCode: resp.StatusCode, + Body: []map[string]interface{}{{"error": "service_error", "message": string(bodyBytes)}}, + Err: fmt.Errorf("unexpected status code %d: %s", resp.StatusCode, string(bodyBytes)), + } + } + + var manifest VhlManifestResponse + if err := json.NewDecoder(resp.Body).Decode(&manifest); err != nil { + return nil, &errors.HttpError{ + StatusCode: http.StatusInternalServerError, + Body: []map[string]interface{}{{"error": "internal_error", "message": "Failed to decode manifest response"}}, + Err: err, + } + } + return &manifest, nil } func (c *VhlClient) ICVPValidate(ctx context.Context, qrData string) (*ICVPQRValidationResponse, error) {