package logic import ( "crypto/sha256" "encoding/binary" "encoding/hex" "fmt" "strings" deviceentity "spark-server/internal/module/device/entity" ) // FingerprintInput is the physical identity for one login/register. type FingerprintInput struct { DeviceType deviceentity.DeviceType IDFV string AndroidID string } func fingerprintHash(in FingerprintInput) (string, error) { if !in.DeviceType.Valid() { return "", fmt.Errorf("device_type") } idfv := strings.TrimSpace(in.IDFV) androidID := strings.TrimSpace(in.AndroidID) var tail string switch in.DeviceType { case deviceentity.TypeIOS, deviceentity.TypeMacOS: if idfv == "" { return "", fmt.Errorf("idfv") } tail = idfv case deviceentity.TypeAndroid, deviceentity.TypeHarmony: if androidID == "" { return "", fmt.Errorf("android_id") } tail = androidID default: switch { case idfv != "": tail = idfv case androidID != "": tail = androidID default: return "", fmt.Errorf("device_id") } } payload := fmt.Sprintf("%d:%s", in.DeviceType, tail) sum := sha256.Sum256([]byte(payload)) return hex.EncodeToString(sum[:]), nil } // DeviceIDFromFingerprint derives the stable business device id. func DeviceIDFromFingerprint(in FingerprintInput) (uint64, string, error) { hash, err := fingerprintHash(in) if err != nil { return 0, "", err } sum := sha256.Sum256([]byte(hash)) id := binary.BigEndian.Uint64(sum[:8]) if id == 0 { id = binary.BigEndian.Uint64(sum[1:9]) } if id == 0 { id = 1 } return id, hash, nil }