feat: add zohal pkg and http util

This commit is contained in:
AmirMahdi Qiasvand 2025-09-14 14:28:23 +03:30
parent 68d33d5ad9
commit 667d2ce2f4
4 changed files with 180 additions and 5 deletions

View File

@ -5,8 +5,8 @@ type Config struct {
JWT JWT `mapstructure:"jwt"` JWT JWT `mapstructure:"jwt"`
DB DB `mapstructure:"db"` DB DB `mapstructure:"db"`
Redis Redis `mapstructure:"redis"` Redis Redis `mapstructure:"redis"`
KYCProvider KYC `mapstructure:"kyc"`
} }
type Server struct { type Server struct {
Host string `mapstructure:"host"` Host string `mapstructure:"host"`
Port int `mapstructure:"port"` Port int `mapstructure:"port"`
@ -31,3 +31,8 @@ type JWT struct {
RefreshTokenExpMinutes uint `mapstructure:"refresh_token_exp_minutes"` RefreshTokenExpMinutes uint `mapstructure:"refresh_token_exp_minutes"`
TokenSecret string `mapstructure:"token_secret"` TokenSecret string `mapstructure:"token_secret"`
} }
type KYC struct {
APIKey string `mapstructure:"api_key"`
URL string `mapstructure:"url"`
}

57
pkg/util/http.go Normal file
View File

@ -0,0 +1,57 @@
package util
import (
"bytes"
"context"
"encoding/json"
"net/http"
"sync"
)
type HttpClient struct {
client *http.Client
once sync.Once
}
func NewHttpClient() *HttpClient {
return &HttpClient{
http.DefaultClient,
sync.Once{},
}
}
func (h *HttpClient) getClient() *http.Client {
h.once.Do(func() {
h.client = &http.Client{}
})
return h.client
}
func (h *HttpClient) HttpRequest(ctx context.Context, method, url string, body interface{}, headers map[string]string) (*http.Response, error) {
payload, err := json.Marshal(body)
if err != nil {
return nil, err
}
req, err := http.NewRequestWithContext(ctx, method, url, bytes.NewBuffer(payload))
if err != nil {
return nil, err
}
for headerTitle, headerValue := range headers {
req.Header.Set(headerTitle, headerValue)
}
resp, err := h.getClient().Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
return &http.Response{
Status: "200 ok",
StatusCode: 200,
Body: resp.Body,
}, nil
}

50
pkg/zohal/types.go Normal file
View File

@ -0,0 +1,50 @@
package zohal
type respMatched struct {
Matched bool `json:"matched"`
}
type personIdentity struct {
Matched bool `json:"matched"`
LastName string `json:"last_name"`
FirstName string `json:"first_name"`
FatherName string `json:"father_name"`
NationalCode string `json:"national_code"`
IsDead bool `json:"is_dead"`
Alive bool `json:"alive"`
}
type respBody[T any] struct {
Data T `json:"data"`
Message string `json:"message"`
}
type zohalResp[T any] struct {
StatusCode int `json:"status_code"`
Body respBody[T] `json:"response_body"`
}
type (
// https://service.zohal.io/api/v0/services/inquiry/shahkar
ZohalShahkarReq struct {
Phone string `json:"mobile"`
NationalID string `json:"national_code"`
}
ZohalShahkarResp struct {
zohalResp[respMatched]
}
// https://service.zohal.io/api/v0/services/inquiry/national_identity_inquiry
ZohalIdentityReq struct {
NationalID string `json:"national_code"`
BirthDate string `json:"birth_date"`
}
ZohalIdentityResp struct {
zohalResp[personIdentity]
}
// https://service.zohal.io/api/v0/services/inquiry/check_iban_with_national_code
ZohalIbanReq struct {
NationalID string `json:"national_code"`
IBAN string `json:"IBAN"`
BirthDate string `json:"birth_date"`
}
ZohalIbanResp struct {
zohalResp[respMatched]
}
)

63
pkg/zohal/zohal.go Normal file
View File

@ -0,0 +1,63 @@
package zohal
import (
"backend/config"
"backend/pkg/util"
"backend/pkg/validate/common"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
)
type Zohal struct {
cfg config.KYC
}
func (z *Zohal) Shahkar(ctx context.Context, phone, nationalID string) (ZohalShahkarResp, error) {
var req ZohalShahkarReq
var resp ZohalShahkarResp
ok, err := common.IsValidPhone(phone)
if !ok {
return resp, err
}
ok, err = common.IsValidNationalID(nationalID)
if !ok {
return resp, err
}
header := make(map[string]string)
header["Content-Type"] = "application/json"
header["Accept"] = "application/json"
header["Authorization"] = fmt.Sprintf("Bearer %s", z.cfg.APIKey)
req.Phone = phone
req.NationalID = nationalID
u, err := url.Parse(z.cfg.URL)
if err != nil {
return resp, err
}
u = u.JoinPath("inquiry", "shahkar")
client := util.NewHttpClient()
clientResp, err := client.HttpRequest(ctx, http.MethodPost, u.String(), req, header)
if err != nil {
return resp, err
}
bodyBytes, err := io.ReadAll(clientResp.Body)
if err != nil {
return resp, err
}
err = json.Unmarshal(bodyBytes, &resp)
if err != nil {
return resp, err
}
return resp, err
}