From 1bc08c90bd83d5d21f204b156169bfb88bccd8fc Mon Sep 17 00:00:00 2001 From: Maksimov V Vladimir Date: Wed, 3 Dec 2025 19:45:24 +0300 Subject: [PATCH] flash call --- common.go | 6 +++ flash_call.go | 113 +++++++++++++++++++++++++++++++++++----------- flashcall_test.go | 25 +++++++++- sms.go | 6 --- status.go | 56 +++-------------------- 5 files changed, 122 insertions(+), 84 deletions(-) create mode 100644 common.go diff --git a/common.go b/common.go new file mode 100644 index 0000000..3c87ebb --- /dev/null +++ b/common.go @@ -0,0 +1,6 @@ +package sigmasms + +type Payload struct { + Sender string `json:"sender"` + Text string `json:"text"` +} diff --git a/flash_call.go b/flash_call.go index f3d320b..c67ebf1 100644 --- a/flash_call.go +++ b/flash_call.go @@ -1,46 +1,105 @@ package sigmasms import ( - "bytes" - "encoding/json" - "net/http" + "crypto/rand" + "fmt" + "log" + "time" + + "github.com/google/uuid" ) +/* +{ + "recipient": "+79999999999", + "type": "flashcall", + "payload": { + "sender": "Имя отправителя", + "text": "1234" + } +} +*/ + type FlashCallRequest struct { - APIKey string `json:"api_key"` - Phone string `json:"phone"` - CodeLen int `json:"code_len"` // 4, 5, 6 + Recepient string `json:"recipient"` + Type string `json:"type"` + Payload Payload `json:"payload"` } type FlashCallResponse struct { - Status string `json:"status"` - CallID string `json:"call_id"` - From string `json:"from"` // номер, с которого звонили - Code string `json:"code"` // обычно это последние digits из from + ID uuid.UUID `json:"id"` + Price float64 `json:"price"` + Recepient string `json:"recipient"` + Status string `json:"status"` + Error string `json:"error"` } -func FlashCall(apiKey, phone string, codeLen int) (*FlashCallResponse, error) { - body := FlashCallRequest{ - APIKey: apiKey, - Phone: phone, - CodeLen: codeLen, +// GenerateRandomDigits генерирует строку из четырёх случайных цифр. +func GenerateFreshcCallCode() (string, error) { + var b [2]byte + _, err := rand.Read(b[:]) + if err != nil { + return "", err } - data, _ := json.Marshal(body) + // Превращаем 2 байта в число + num := int(b[0])<<8 | int(b[1]) + // Ограничиваем диапазон 0–9999 + num = num % 10000 - resp, err := http.Post( - "https://voice.sigmasms.ru/flashcall", - "application/json", - bytes.NewReader(data), - ) + // Возвращаем строку с ведущими нулями + return fmt.Sprintf("%04d", num), nil +} + +func FlashCall(apiKey, phone, sender string, code string) (*FlashCallResponse, error) { + req := FlashCallRequest{ + Recepient: phone, + Type: "flashcall", + Payload: Payload{ + Sender: sender, + Text: code, + }, + } + + var resp FlashCallResponse + + err := requestPost("https://user.sigmasms.ru/api/sendings", apiKey, &req, &resp) if err != nil { return nil, err } - defer resp.Body.Close() - var result FlashCallResponse - if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { - return nil, err - } - return &result, nil + return &resp, nil +} + +func FlashCallWait(apiKey, phone, sender string, code string) (transactionID uuid.UUID, err error) { + var resp *FlashCallResponse + if resp, err = FlashCall(apiKey, phone, sender, code); err != nil { + log.Println(err) + return + } else { + if resp.Status == "failed" { + err = fmt.Errorf("flashcall send error: %s", resp.Error) + return + } + transactionID = resp.ID + var sResp *StatusResponse + mainLoop: + for resp.Status == "pending" { + time.Sleep(time.Millisecond * 100) + sResp, err = RequestStatus(resp.ID, apiKey) + if err != nil { + return + } + resp.Status = sResp.State.Status + switch resp.Status { + case "pending", "sent": + continue mainLoop + case "seen", "delivered": + return + default: + err = fmt.Errorf("sms status: %s", sResp.State.Status) + } + } + } + return } diff --git a/flashcall_test.go b/flashcall_test.go index 48c7d01..564093b 100644 --- a/flashcall_test.go +++ b/flashcall_test.go @@ -18,7 +18,20 @@ func loadToken(t *testing.T) string { func TestFlashCall(t *testing.T) { token := loadToken(t) - log.Println(token) + code, _ := GenerateFreshcCallCode() + log.Println(code) + FlashCall(token, "+79857770038", "NG.Market", code) +} + +func TestFlashCallWait(t *testing.T) { + token := loadToken(t) + code, _ := GenerateFreshcCallCode() + log.Println(code) + trID, err := FlashCallWait(token, "+79857770038", "NG.Market", code) + if err != nil { + t.Fatal(err) + } + t.Log(trID) } func TestSMS(t *testing.T) { @@ -42,10 +55,18 @@ func TestSMSWait(t *testing.T) { func TestStatus(t *testing.T) { token := loadToken(t) - id, _ := uuid.Parse("9987bf00-c082-4dec-b25f-875eb528cf34") + id, _ := uuid.Parse("518095e8-a62d-4af1-ad1f-2a56e955cf55") status, err := RequestStatus(id, token) if err != nil { t.Fatal(err) } t.Log(status) } + +func TestFreshCallCode(t *testing.T) { + code, err := GenerateFreshcCallCode() + if err != nil { + t.Fatal(err) + } + t.Log(code) +} diff --git a/sms.go b/sms.go index a71e148..d79d396 100644 --- a/sms.go +++ b/sms.go @@ -23,11 +23,6 @@ var ( TypeSMS = "sms" ) -type Payload struct { - Sender string `json:"sender"` - Text string `json:"text"` -} - type SendSMSResponse struct { Error string `json:"error"` ID uuid.UUID `json:"id"` @@ -84,7 +79,6 @@ func SendSMSWait(apiKey, phone, sender, text string) (transactionID uuid.UUID, e for resp.Status == "pending" { time.Sleep(time.Millisecond * 100) sResp, err = RequestStatus(resp.ID, apiKey) - log.Println(sResp.State.Status, err) if err != nil { return } diff --git a/status.go b/status.go index 4db0de7..313a990 100644 --- a/status.go +++ b/status.go @@ -4,50 +4,7 @@ import ( "github.com/google/uuid" ) -/* -{ - "id": "9987bf00-c082-4dec-b25f-875eb528cf34", - "chainId": "9987bf00-c082-4dec-b25f-875eb528cf34", - "groupId": null, - "type": "sms", - "createdAt": "2025-12-02T16:13:27.265Z", - "updatedAt": "2025-12-02T16:13:34.194Z", - "meta": { - "billing": { - "id": "4dbd2a09-0a77-4e70-8706-3a9851fcb587", - "amount": -7.49, - "refunded": false, - "TariffId": "9d9c19a9-5ac9-4963-9e4b-d69f78e811e0" - }, - "billings": { - "ids": [ - "4dbd2a09-0a77-4e70-8706-3a9851fcb587" - ] - }, - "stats": { - "segments": 1, - "characters": 6 - }, - "patternId": false, - "_recipientData": { - "mcc": "250", - "mnc": "01", - "code": "Мобильные ТелеСистемы ПАО_250_01", - "type": "def", - "group": "Russia | MTS", - "operator": "Мобильные ТелеСистемы ПАО" - } - }, - "state": { - "status": "delivered", - "error": false, - "extendedStatus": null - }, - "OwnerId": "99f5860a-a342-48fc-8e2e-3d4a26cdb79f" -} -*/ - -type ReceepientData struct { +type RecepientData struct { MCC string `json:"mcc"` MNC string `json:"mnc"` Code string `json:"code"` @@ -73,11 +30,11 @@ type Stats struct { } type Meta struct { - Billing Billing `json:"billing"` - Billings Billings `json:"billings"` - Stats Stats `json:"stats"` - PatternID bool `json:"patternId"` - RecipientData ReceepientData `json:"_recipientData"` + Billing Billing `json:"billing"` + Billings Billings `json:"billings"` + Stats Stats `json:"stats"` + PatternID bool `json:"patternId"` + RecepientData RecepientData `json:"_recipientData"` } type State struct { @@ -94,6 +51,7 @@ type StatusResponse struct { UpdatedAt string `json:"updatedAt"` State State `json:"state"` Meta *Meta `json:"meta"` + OwnerID uuid.UUID `json:"OwnerId"` } // 9987bf00-c082-4dec-b25f-875eb528cf34