package verify import ( "bytes" "context" "encoding/json" "fmt" "io" "net/http" "strings" "time" "bsm/full/module/base/passport/internal/config" "bsm/full/module/base/passport/internal/impl" "bsm/full/module/base/passport/internal/logic/common" "bsm/full/module/base/passport/internal/models" pb "bsm/full/module/base/passport/pb" "git.apinb.com/bsm-sdk/core/errcode" "git.apinb.com/bsm-sdk/core/printer" "git.apinb.com/bsm-sdk/core/service" ) type JumioInitRequest struct { CustomerInternalReference string `json:"customerInternalReference"` UserReference string `json:"userReference"` SuccessURL string `json:"successUrl"` ErrorURL string `json:"errorUrl"` CallbackURL string `json:"callbackUrl"` } type JumioInitResponse struct { Timestamp string `json:"timestamp"` ScanReference string `json:"scanReference"` ClientRedirectURL string `json:"clientRedirectUrl"` } func Request(ctx context.Context, in *pb.VerifyRequest) (reply *pb.StatusReply, err error) { auth, err := service.ParseMetaCtx(ctx, nil) if err != nil { return nil, err } var data string switch strings.ToLower(in.Provider) { case "jumio": id := fmt.Sprintf("ID_%d", auth.ID) resp, err := InitiateJumioScan(id, auth.Identity) if err != nil { printer.Error(err.Error()) return nil, errcode.ErrInternal } data = resp.ClientRedirectURL case "local": if !common.VerifyMapKeys(in.Args, []string{"type", "name", "number", "front", "back"}) { return nil, errcode.ErrInvalidArgument } err = LocalVerify(auth.ID, in.Args) if err != nil { printer.Error(err.Error()) return nil, errcode.ErrDB } default: return nil, errcode.ErrNotFound(404, "provider") } return &pb.StatusReply{ Details: data, Timeseq: time.Now().UnixMilli(), }, nil } func LocalVerify(authID uint, args map[string]string) error { err := impl.DBService.Model(&models.PassportData{}).Where("passport_id = ?", authID).Update("document_verify", 1).Error if err != nil { return err } err = impl.DBService.Model(&models.PassportVerify{}).Where("passport_id = ?", authID).Updates(map[string]any{ "document_verify_at": time.Now(), "document_type": args["type"], "document_name": args["name"], "document_number": args["number"], "document_front": args["front"], "document_back": args["back"], }).Error if err != nil { return err } return nil } func InitiateJumioScan(internalRef, userRef string) (*JumioInitResponse, error) { if config.Spec.Kyc == nil { return nil, fmt.Errorf("kyc config is missing") } reqBody := JumioInitRequest{ CustomerInternalReference: internalRef, UserReference: userRef, CallbackURL: config.Spec.Kyc.ApiArgs, } jsonBody, err := json.Marshal(reqBody) if err != nil { return nil, err } client := &http.Client{Timeout: 10 * time.Second} req, err := http.NewRequest(http.MethodPost, config.Spec.Kyc.BaseUrl, bytes.NewBuffer(jsonBody)) if err != nil { return nil, err } req.SetBasicAuth(config.Spec.Kyc.ApiToken, config.Spec.Kyc.ApiSecret) req.Header.Set("Content-Type", "application/json") req.Header.Set("User-Agent", "BSM-Passport/1.0") resp, err := client.Do(req) if err != nil { return nil, err } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { return nil, err } if resp.StatusCode != http.StatusOK { return nil, fmt.Errorf("jumio api error: status=%d body=%s", resp.StatusCode, string(body)) } var jumioResp JumioInitResponse err = json.Unmarshal(body, &jumioResp) if err != nil { return nil, err } return &jumioResp, nil }