vietguys/send_otp.go

107 lines
2.1 KiB
Go

package vietguys
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strings"
"git.selly.red/Selly-Modules/mongodb"
)
// SendOTPResult ...
type SendOTPResult struct {
Carrier string
Error int
ErrorCode int
MsgID string
Message string
Log string
}
// SendOTP to phone number
// Phone format: 84935123456
// Content must have "%s", for otp code substitution
func (s Service) SendOTP(phone, ip, contentFormat string) error {
// Generate otp code
otpCode := randomOTPCode()
// Format content
content := fmt.Sprintf(contentFormat, otpCode)
// Just remove char "+" if existed
strings.Replace(phone, "+", "", 1)
// Check that phone or ip is not over quota
canSend := s.checkCanSend(phone, ip)
if canSend {
return errors.New("ip or phone has reached over limited quota per day")
}
// Create payload
params := url.Values{}
params.Add("u", s.User)
params.Add("pwd", s.Password)
params.Add("from", s.From)
params.Add("json", "1")
params.Add("phone", phone)
params.Add("sms", content)
payload := strings.NewReader(params.Encode())
// Create request
client := s.Client
req, err := http.NewRequest(http.MethodPost, s.Endpoint, payload)
if err != nil {
return err
}
// Add necessary headers
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
// Call
res, err := client.Do(req)
if err != nil {
return err
}
// Make sure close body
defer res.Body.Close()
// Ready body
body, err := ioutil.ReadAll(res.Body)
rawResult := string(body)
fmt.Println(rawResult)
if err != nil {
fmt.Println("error : ", err.Error())
return err
}
var result SendOTPResult
if err = json.Unmarshal(body, &result); err != nil {
return err
}
go func() {
// Save log to db
log := Log{
ID: mongodb.NewObjectID(),
Carrier: result.Carrier,
Type: SMSTypeOTP,
Code: otpCode,
IsCodeValid: true,
PhoneNumber: phone,
IP: ip,
Content: content,
CreatedAt: now(),
Success: result.Error == 0,
Result: rawResult,
}
s.saveLog(log)
}()
return nil
}