Files
satusehat-service/internal/satusehat/reference/kyc/service.go
T

81 lines
3.0 KiB
Go

package kyc
import (
"context"
"encoding/base64"
"encoding/json"
"service/internal/infrastructure/config"
"service/internal/interfaces/satusehat"
"service/pkg/crypto"
"service/pkg/errors"
"service/pkg/logger"
)
type Service interface {
GenerateURL(ctx context.Context, req GenerateURLRequest) (*satusehat.FHIRResponse, error)
HandleCallback(ctx context.Context, encryptedPayload string, token string) error
}
type service struct {
repo Repository
cfg config.SatuSehatConfig
}
func NewService(repo Repository, cfg config.SatuSehatConfig) Service {
return &service{repo: repo, cfg: cfg}
}
func (s *service) GenerateURL(ctx context.Context, req GenerateURLRequest) (*satusehat.FHIRResponse, error) {
// Gunakan public key statis dari konfigurasi (disimpan dalam format Base64 di .env)
pubKeyBytes, err := base64.StdEncoding.DecodeString(s.cfg.KYCPublicKeyB64)
if err != nil {
return nil, errors.InternalError().Message("Gagal mendecode Public Key dari konfigurasi").Cause(err).Build()
}
req.PublicKey = string(pubKeyBytes)
// Decode private key untuk mendekripsi balasan generate URL dari Kemenkes
privKeyBytes, err := base64.StdEncoding.DecodeString(s.cfg.KYCPrivateKeyB64)
if err != nil {
return nil, errors.InternalError().Message("Gagal mendecode Private Key dari konfigurasi").Cause(err).Build()
}
privKeyPEM := string(privKeyBytes)
// Lempar privKeyPEM ke repo agar Kemenkes response dapat didekripsi
return s.repo.GenerateURL(ctx, req, privKeyPEM)
}
func (s *service) HandleCallback(ctx context.Context, encryptedPayload string, token string) error {
// Validasi Security Token dari Kemenkes
expectedToken := s.cfg.WebhookSecret
if expectedToken == "" {
logger.Default().Warn("SATUSEHAT_WEBHOOK_SECRET belum dikonfigurasi. Validasi token webhook dilewati.")
} else if token != expectedToken {
logger.Default().Warn("Webhook KYC gagal divalidasi: Token tidak cocok", logger.String("received_token", token))
return errors.UnauthorizedError().Message("Invalid security webhook token").Build()
}
// 1. Dapatkan Private Key statis Anda dari config/env var
privKeyBytes, err := base64.StdEncoding.DecodeString(s.cfg.KYCPrivateKeyB64)
if err != nil {
return errors.InternalError().Message("Gagal mendecode Private Key dari konfigurasi").Cause(err).Build()
}
privKeyPEM := string(privKeyBytes)
// 2. Dekripsi payload yang masuk
decryptedBytes, err := crypto.DecryptSatuSehatPayload(encryptedPayload, privKeyPEM)
if err != nil {
return errors.InternalError().Message("Gagal mendekripsi payload webhook dari SatuSehat").Cause(err).Build()
}
// 3. Unmarshal ke bentuk Struct
var payload CallbackRequest
if err := json.Unmarshal(decryptedBytes, &payload); err != nil {
return errors.InternalError().Message("Gagal memparsing JSON hasil dekripsi").Cause(err).Build()
}
// TODO: Tambahkan logika update ke database lokal (misal: tabel user/agent) berdasarkan hasil KYC.
// Saat ini, kita log payload yang diterima dari Kemenkes.
logger.Default().Info("Menerima Webhook KYC dari SatuSehat", logger.Any("payload", payload))
return nil
}