mirror of
https://github.com/andwati/telecom-platform.git
synced 2026-10-18 11:02:54 +00:00
feat: Add ES2+ client for eSIM profile management operations
- Add ES2Client struct with HTTP client and configuration - Add NewES2Client with 30s timeout and TLS configuration - Add DownloadProfile for eSIM profile download requests - Add GetProfileStatus for profile state queries - Add DeleteProfile for profile removal operations - Add EnableProfile and DisableProfile for profile state management - Add request/response types for all ES2+ operations (EID, ICCID, profile type, confirmation code) - Add setHeaders helper
This commit is contained in:
@@ -0,0 +1,271 @@
|
||||
package es2
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/config"
|
||||
)
|
||||
|
||||
type ES2Client struct {
|
||||
httpClient *http.Client
|
||||
config *config.ES2Config
|
||||
baseURL string
|
||||
}
|
||||
|
||||
func NewES2Client(cfg *config.ES2Config) *ES2Client {
|
||||
return &ES2Client{
|
||||
httpClient: &http.Client{
|
||||
Timeout: 30 * time.Second,
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: cfg.InsecureSkipVerify,
|
||||
},
|
||||
},
|
||||
},
|
||||
config: cfg,
|
||||
baseURL: cfg.BaseURL,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ES2Client) DownloadProfile(ctx context.Context, req *DownloadProfileRequest) (*DownloadProfileResponse, error) {
|
||||
url := fmt.Sprintf("%s/es2plus/downloadProfile", c.baseURL)
|
||||
|
||||
payload, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal request: %w", err)
|
||||
}
|
||||
|
||||
httpReq, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(payload))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create request: %w", err)
|
||||
}
|
||||
|
||||
c.setHeaders(httpReq)
|
||||
|
||||
resp, err := c.httpClient.Do(httpReq)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to send request: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
var downloadResp DownloadProfileResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&downloadResp); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode response: %w", err)
|
||||
}
|
||||
|
||||
return &downloadResp, nil
|
||||
}
|
||||
|
||||
func (c *ES2Client) GetProfileStatus(ctx context.Context, req *GetProfileStatusRequest) (*GetProfileStatusResponse, error) {
|
||||
url := fmt.Sprintf("%s/es2plus/getProfileStatus", c.baseURL)
|
||||
|
||||
payload, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal request: %w", err)
|
||||
}
|
||||
|
||||
httpReq, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(payload))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create request: %w", err)
|
||||
}
|
||||
|
||||
c.setHeaders(httpReq)
|
||||
|
||||
resp, err := c.httpClient.Do(httpReq)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to send request: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
var statusResp GetProfileStatusResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&statusResp); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode response: %w", err)
|
||||
}
|
||||
|
||||
return &statusResp, nil
|
||||
}
|
||||
|
||||
func (c *ES2Client) DeleteProfile(ctx context.Context, req *DeleteProfileRequest) (*DeleteProfileResponse, error) {
|
||||
url := fmt.Sprintf("%s/es2plus/deleteProfile", c.baseURL)
|
||||
|
||||
payload, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal request: %w", err)
|
||||
}
|
||||
|
||||
httpReq, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(payload))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create request: %w", err)
|
||||
}
|
||||
|
||||
c.setHeaders(httpReq)
|
||||
|
||||
resp, err := c.httpClient.Do(httpReq)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to send request: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
var deleteResp DeleteProfileResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&deleteResp); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode response: %w", err)
|
||||
}
|
||||
|
||||
return &deleteResp, nil
|
||||
}
|
||||
|
||||
func (c *ES2Client) EnableProfile(ctx context.Context, req *EnableProfileRequest) (*EnableProfileResponse, error) {
|
||||
url := fmt.Sprintf("%s/es2plus/enableProfile", c.baseURL)
|
||||
|
||||
payload, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal request: %w", err)
|
||||
}
|
||||
|
||||
httpReq, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(payload))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create request: %w", err)
|
||||
}
|
||||
|
||||
c.setHeaders(httpReq)
|
||||
|
||||
resp, err := c.httpClient.Do(httpReq)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to send request: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
var enableResp EnableProfileResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&enableResp); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode response: %w", err)
|
||||
}
|
||||
|
||||
return &enableResp, nil
|
||||
}
|
||||
|
||||
func (c *ES2Client) DisableProfile(ctx context.Context, req *DisableProfileRequest) (*DisableProfileResponse, error) {
|
||||
url := fmt.Sprintf("%s/es2plus/disableProfile", c.baseURL)
|
||||
|
||||
payload, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal request: %w", err)
|
||||
}
|
||||
|
||||
httpReq, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(payload))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create request: %w", err)
|
||||
}
|
||||
|
||||
c.setHeaders(httpReq)
|
||||
|
||||
resp, err := c.httpClient.Do(httpReq)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to send request: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
var disableResp DisableProfileResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&disableResp); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode response: %w", err)
|
||||
}
|
||||
|
||||
return &disableResp, nil
|
||||
}
|
||||
|
||||
func (c *ES2Client) setHeaders(req *http.Request) {
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Accept", "application/json")
|
||||
req.Header.Set("User-Agent", "Telecom-Platform/1.0")
|
||||
|
||||
if c.config.APIKey != "" {
|
||||
req.Header.Set("Authorization", "Bearer "+c.config.APIKey)
|
||||
}
|
||||
|
||||
if c.config.FunctionalityRequesterID != "" {
|
||||
req.Header.Set("X-Admin-Protocol", "gsma-rsp")
|
||||
req.Header.Set("X-Request-ID", generateRequestID())
|
||||
}
|
||||
}
|
||||
|
||||
func generateRequestID() string {
|
||||
return fmt.Sprintf("%d", time.Now().UnixNano())
|
||||
}
|
||||
|
||||
type DownloadProfileRequest struct {
|
||||
EID string `json:"eid"`
|
||||
ICCID string `json:"iccid"`
|
||||
ProfileType string `json:"profileType"`
|
||||
ConfirmationCode string `json:"confirmationCode,omitempty"`
|
||||
}
|
||||
|
||||
type DownloadProfileResponse struct {
|
||||
ExecutionStatus string `json:"executionStatus"`
|
||||
StatusMessage string `json:"statusMessage"`
|
||||
}
|
||||
|
||||
type GetProfileStatusRequest struct {
|
||||
EID string `json:"eid"`
|
||||
ICCID string `json:"iccid"`
|
||||
}
|
||||
|
||||
type GetProfileStatusResponse struct {
|
||||
ExecutionStatus string `json:"executionStatus"`
|
||||
StatusMessage string `json:"statusMessage"`
|
||||
ProfileState string `json:"profileState,omitempty"`
|
||||
}
|
||||
|
||||
type DeleteProfileRequest struct {
|
||||
EID string `json:"eid"`
|
||||
ICCID string `json:"iccid"`
|
||||
}
|
||||
|
||||
type DeleteProfileResponse struct {
|
||||
ExecutionStatus string `json:"executionStatus"`
|
||||
StatusMessage string `json:"statusMessage"`
|
||||
}
|
||||
|
||||
type EnableProfileRequest struct {
|
||||
EID string `json:"eid"`
|
||||
ICCID string `json:"iccid"`
|
||||
}
|
||||
|
||||
type EnableProfileResponse struct {
|
||||
ExecutionStatus string `json:"executionStatus"`
|
||||
StatusMessage string `json:"statusMessage"`
|
||||
}
|
||||
|
||||
type DisableProfileRequest struct {
|
||||
EID string `json:"eid"`
|
||||
ICCID string `json:"iccid"`
|
||||
}
|
||||
|
||||
type DisableProfileResponse struct {
|
||||
ExecutionStatus string `json:"executionStatus"`
|
||||
StatusMessage string `json:"statusMessage"`
|
||||
}
|
||||
Reference in New Issue
Block a user