1增加接码过期时间
This commit is contained in:
@ -23,9 +23,13 @@ type SmsPhone struct {
|
||||
Code string `json:"code" gorm:"type:varchar(10);comment:验证码"`
|
||||
Status int `json:"status" gorm:"type:tinyint;comment:状态 1-等待验证码 2-已获取"`
|
||||
ExpireTime *time.Time `json:"expireTime" gorm:"type:datetime;comment:过期时间"`
|
||||
StartTime *time.Time `json:"startTime" gorm:"type:datetime;comment:开始时间"`
|
||||
EndTime *time.Time `json:"endTime" gorm:"type:datetime;comment:结束时间 单次接码结束时间"`
|
||||
Actived int `json:"actived" gorm:"type:tinyint;comment:是否激活(长期租赁如果第一次没接收到验证码 则不会激活号码) 1-未激活 2-已激活 3-已失效"`
|
||||
Price decimal.Decimal `json:"price" gorm:"type:decimal(10,2);comment:价格"`
|
||||
AutoRenewal int `json:"autoRenewal" gorm:"type:tinyint;comment:是否自动续费 1-自动续费 2-手动续费"`
|
||||
Remark string `json:"remark" gorm:"type:varchar(255);comment:备注"`
|
||||
PlatformName string `json:"platformName" gorm:"-"`
|
||||
models.ModelTime
|
||||
models.ControlBy
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@ type SmsReceiveLog struct {
|
||||
UserId int `json:"userId" gorm:"type:bigint;comment:用户id"`
|
||||
Service string `json:"service" gorm:"type:varchar(30);comment:服务"`
|
||||
ServiceCode string `json:"serviceCode" gorm:"type:varchar(30);comment:服务code"`
|
||||
MessageId int `json:"messageId" gorm:"type:int;comment:短信id"`
|
||||
MessageId string `json:"messageId" gorm:"type:int;comment:短信id"`
|
||||
Phone string `json:"phone" gorm:"type:varchar(30);comment:号码"`
|
||||
Code string `json:"code" gorm:"type:varchar(20);comment:验证码"`
|
||||
Status int `json:"status" gorm:"type:tinyint;comment:状态 0-等待验证码 1-成功 2-失败"`
|
||||
|
||||
@ -150,8 +150,10 @@ type WeakUpReq struct {
|
||||
}
|
||||
|
||||
type WeakUpResp struct {
|
||||
ActivationId string `json:"activationId" comment:"激活id"`
|
||||
MessageId string `json:"messageId" commment:"消息id"`
|
||||
ActivationId string `json:"activationId" comment:"激活id"`
|
||||
MessageId string `json:"messageId" commment:"消息id"`
|
||||
StartTime *time.Time `json:"startTime" comment:"接码开始时间"`
|
||||
EndTime *time.Time `json:"endTime" comment:"接码过期时间"`
|
||||
}
|
||||
|
||||
func (s *WeakUpReq) Validate() error {
|
||||
@ -190,9 +192,12 @@ type SmsPhoneCleanMyPhoneReq struct {
|
||||
}
|
||||
|
||||
type SmsPhoneGetPhoneResp struct {
|
||||
Phone string `json:"phone"`
|
||||
EndAt *time.Time `json:"endTime"`
|
||||
Id string `json:"id"`
|
||||
Phone string `json:"phone"`
|
||||
EndAt *time.Time `json:"endTime"`
|
||||
StartTime *time.Time `json:"-" comment:"唤醒后单次接码开始时间"`
|
||||
EndTime *time.Time `json:"-" comment:"唤醒后单次接码过期时间"`
|
||||
MessageId string `json:"-" comment:"消息id"`
|
||||
Id string `json:"id"`
|
||||
}
|
||||
|
||||
type DaisysmsPriceResp struct {
|
||||
@ -208,6 +213,8 @@ type OpenGetNumberResp struct {
|
||||
Number string `json:"number"`
|
||||
ActivationId string `json:"activationId"`
|
||||
ExpireTime *time.Time `json:"expireTime"`
|
||||
StartTime *time.Time `json:"startTime"`
|
||||
EndTime *time.Time `json:"endTime"`
|
||||
}
|
||||
|
||||
type OpenWakeUpReq struct {
|
||||
|
||||
@ -212,3 +212,13 @@ type TextVerifiedSmsItemResp struct {
|
||||
ParsedCode string `json:"parsedCode"`
|
||||
Encrypted bool `json:"encrypted"`
|
||||
}
|
||||
|
||||
type TextVerifiedGetNumbersResp struct {
|
||||
HasNext bool `json:"hasNext" comment:"是否有下一页"`
|
||||
Links TextVerifiedGetNumbersLinksResp `json:"links"`
|
||||
Data []VerificationDTO `json:"data"`
|
||||
}
|
||||
|
||||
type TextVerifiedGetNumbersLinksResp struct {
|
||||
Next *TextVerifiedResp `json:"next"`
|
||||
}
|
||||
|
||||
@ -115,7 +115,7 @@ func (e MemberRecharge) CustomRecharge(req *dto.MemberRechargeCustomRechargeReq,
|
||||
return errors.New("server error")
|
||||
}
|
||||
|
||||
cacheExpireDuration := time.Duration(orderExpireTime+1) * time.Minute
|
||||
cacheExpireDuration := time.Duration(orderExpireTime+10) * time.Minute
|
||||
key := fmt.Sprintf("pre_order:%s", amount)
|
||||
err = e.Orm.Transaction(func(tx *gorm.DB) error {
|
||||
if err1 := tx.Create(&data).Error; err1 != nil {
|
||||
|
||||
@ -36,6 +36,8 @@ func (e SmsPhone) OpenGetNumber(req *dto.GetNumberReq, userId int) (dto.OpenGetN
|
||||
resp.ActivationId = smsPhone.NewActivationId
|
||||
resp.ExpireTime = smsPhone.ExpireTime
|
||||
resp.Number = smsPhone.Phone
|
||||
resp.StartTime = smsPhone.StartTime
|
||||
resp.EndTime = smsPhone.EndTime
|
||||
|
||||
return resp, statuscode.Success
|
||||
}
|
||||
@ -64,7 +66,7 @@ func (e *SmsPhone) CancelNumber(req *dto.SmsPhoneCancelNumberReq, userId int) in
|
||||
|
||||
if code == statuscode.Success {
|
||||
err := e.Orm.Transaction(func(tx *gorm.DB) error {
|
||||
if err1 := e.Orm.Model(data).Updates(map[string]interface{}{"status": 3, "code": "", "actived": "3", "auto_renewal": 2}).Error; err1 != nil {
|
||||
if err1 := e.Orm.Model(data).Updates(map[string]interface{}{"status": 3, "code": "", "actived": "3", "auto_renewal": 2, "deleted_at": time.Now()}).Error; err1 != nil {
|
||||
e.Log.Errorf("更新短信号码失败, %s", err1)
|
||||
return err1
|
||||
}
|
||||
@ -143,21 +145,27 @@ func (e *SmsPhone) WeakUp(req *dto.WeakUpReq, userId int, defult bool) (dto.Weak
|
||||
}
|
||||
|
||||
if smsPhone.Status != 1 || defult {
|
||||
newActivationId, messageId, code := e.WeakUpManage(&smsPhone)
|
||||
newActivationId, messageId, startTime, endTime, code := e.WeakUpManage(&smsPhone)
|
||||
|
||||
if code == statuscode.ServerError {
|
||||
return result, code
|
||||
} else if code == statuscode.Success {
|
||||
if err := e.Orm.Model(smsPhone).Updates(map[string]interface{}{"new_activation_id": newActivationId, "status": 1, "code": "", "message_id": messageId}).Error; err != nil {
|
||||
if err := e.Orm.Model(smsPhone).
|
||||
Updates(map[string]interface{}{
|
||||
"new_activation_id": newActivationId, "status": 1, "code": "",
|
||||
"message_id": messageId, "start_time": startTime, "end_time": endTime}).Error; err != nil {
|
||||
e.Log.Errorf("更新短信号码失败, %s", err)
|
||||
return result, statuscode.ServerError
|
||||
}
|
||||
|
||||
result.ActivationId = newActivationId
|
||||
result.MessageId = messageId
|
||||
result.StartTime = startTime
|
||||
result.EndTime = endTime
|
||||
} else if code == statuscode.SmsLongNumWaitCode {
|
||||
e.Log.Info("无须唤醒")
|
||||
if err := e.Orm.Model(smsPhone).Updates(map[string]interface{}{"status": 1, "code": ""}).Error; err != nil {
|
||||
if err := e.Orm.Model(smsPhone).
|
||||
Updates(map[string]interface{}{"status": 1, "code": "", "start_time": startTime, "end_time": endTime}).
|
||||
Error; err != nil {
|
||||
e.Log.Errorf("更新短信号码失败, %s", err)
|
||||
return result, statuscode.ServerError
|
||||
}
|
||||
@ -171,18 +179,18 @@ func (e *SmsPhone) WeakUp(req *dto.WeakUpReq, userId int, defult bool) (dto.Weak
|
||||
|
||||
// 唤醒号码
|
||||
// returns newActivationId,messageId, code
|
||||
func (e *SmsPhone) WeakUpManage(req *models.SmsPhone) (string, string, int) {
|
||||
func (e *SmsPhone) WeakUpManage(req *models.SmsPhone) (string, string, *time.Time, *time.Time, int) {
|
||||
switch req.PlatformCode {
|
||||
case global.SmsPlatformDaisysms:
|
||||
service := SmsDaisysms{Service: e.Service}
|
||||
id, code := service.getExtraActivation(req.ActivationId)
|
||||
return strconv.Itoa(id), "", code
|
||||
return strconv.Itoa(id), "", nil, nil, code
|
||||
case global.SmsPlatformTextVerified:
|
||||
service := SmsTextVerified{Service: e.Service}
|
||||
|
||||
return service.getExtraActivation(req.NewActivationId)
|
||||
resp, code := service.getExtraActivation(req.NewActivationId)
|
||||
return resp.ReservationId, resp.Id, resp.UsageWindowStart, resp.UsageWindowEnd, code
|
||||
default:
|
||||
return "", "", statuscode.SmsPlatformUnavailable
|
||||
return "", "", nil, nil, statuscode.SmsPlatformUnavailable
|
||||
}
|
||||
}
|
||||
|
||||
@ -201,6 +209,17 @@ func (e *SmsPhone) GetMyPage(req *dto.SmsPhoneGetPageReq, userId int, phone *[]m
|
||||
return statuscode.ServerError
|
||||
}
|
||||
|
||||
dictService := SysDictData{}
|
||||
dictService.Orm = e.Orm
|
||||
dictService.Log = e.Log
|
||||
dictDatas, _ := dictService.GetMapByType("sms_platform")
|
||||
|
||||
for index := range *phone {
|
||||
if dict, ok := dictDatas[(*phone)[index].PlatformCode]; ok {
|
||||
(*phone)[index].PlatformName = dict.DictLabel
|
||||
}
|
||||
}
|
||||
|
||||
return statuscode.Success
|
||||
}
|
||||
|
||||
@ -281,7 +300,7 @@ func (e *SmsPhone) DoGetNumber(balanceService *MemberBalance, req *dto.GetNumber
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
activationId, phone, code, expireTime := e.GetNumberManage(req.PlatformCode, req.Type, req.ServiceCode, price, req.Period)
|
||||
activationId, phone, code, expireTime, startTime, endTime := e.GetNumberManage(req.PlatformCode, req.Type, req.ServiceCode, price, req.Period)
|
||||
|
||||
if code != statuscode.Success {
|
||||
return decimal.Decimal{}, models.SmsPhone{}, code
|
||||
@ -299,6 +318,8 @@ func (e *SmsPhone) DoGetNumber(balanceService *MemberBalance, req *dto.GetNumber
|
||||
smsPhone.MessageId = activationId
|
||||
smsPhone.NewActivationId = activationId
|
||||
smsPhone.Actived = 1
|
||||
smsPhone.StartTime = startTime
|
||||
smsPhone.EndTime = endTime
|
||||
|
||||
smsPhone.Price = price
|
||||
if req.Type == 1 {
|
||||
@ -310,6 +331,10 @@ func (e *SmsPhone) DoGetNumber(balanceService *MemberBalance, req *dto.GetNumber
|
||||
smsPhone.ExpireTime = &now
|
||||
}
|
||||
|
||||
//平台不允许取消
|
||||
if req.PlatformCode == global.SmsPlatformTextVerified {
|
||||
smsPhone.Actived = 2
|
||||
}
|
||||
} else {
|
||||
if expireTime != nil {
|
||||
smsPhone.ExpireTime = expireTime
|
||||
@ -355,24 +380,30 @@ func (e *SmsPhone) DoGetNumber(balanceService *MemberBalance, req *dto.GetNumber
|
||||
}
|
||||
|
||||
// 租赁号码
|
||||
func (e *SmsPhone) GetNumberManage(platformCode string, typ int, serviceCode string, price decimal.Decimal, period int) (string, string, int, *time.Time) {
|
||||
// return activationId 激活id
|
||||
// phone 号码
|
||||
// code 状态码
|
||||
// *expirateTime 号码过期时间
|
||||
// *startTime 长效号码单次接码开始使用(textverified有用)
|
||||
// *endTime 长效号码单次接码过期时间(textverified有用)
|
||||
func (e *SmsPhone) GetNumberManage(platformCode string, typ int, serviceCode string, price decimal.Decimal, period int) (string, string, int, *time.Time, *time.Time, *time.Time) {
|
||||
switch platformCode {
|
||||
case global.SmsPlatformDaisysms:
|
||||
service := SmsDaisysms{Service: e.Service}
|
||||
activationId, phone, code := service.GetNumberForApi(typ, serviceCode, price, period)
|
||||
|
||||
return strconv.Itoa(activationId), phone, code, nil
|
||||
return strconv.Itoa(activationId), phone, code, nil, nil, nil
|
||||
case global.SmsPlatformTextVerified:
|
||||
service := SmsTextVerified{Service: e.Service}
|
||||
resp, code := service.GetNumberForApi(typ, serviceCode, price, period)
|
||||
resp, code := service.GetNumberAndWakeUp(typ, serviceCode, price, period)
|
||||
|
||||
if code != statuscode.Success {
|
||||
return "", "", code, nil
|
||||
return "", "", code, nil, resp.StartTime, resp.EndTime
|
||||
}
|
||||
|
||||
return resp.Id, resp.Phone, code, resp.EndAt
|
||||
return resp.Id, resp.Phone, code, resp.EndAt, resp.StartTime, resp.EndTime
|
||||
default:
|
||||
return "", "", statuscode.SmsPlatformUnavailable, nil
|
||||
return "", "", statuscode.SmsPlatformUnavailable, nil, nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
@ -416,11 +447,17 @@ func (e *SmsPhone) SyncCodes() error {
|
||||
}
|
||||
|
||||
for _, item := range phones {
|
||||
code, codeStatus := e.GetCodeManage(item.PlatformCode, item.NewActivationId, item.Type, item.UpdatedAt.Unix())
|
||||
code, codeStatus := e.GetCodeManage(item.PlatformCode, item.NewActivationId,
|
||||
item.Type, item.UserId, item.Service, item.ServiceCode)
|
||||
|
||||
if code == "" {
|
||||
expireTime := item.UpdatedAt.Add(time.Second * 150)
|
||||
if item.PlatformCode == global.SmsPlatformTextVerified && expireTime.Before(time.Now()) {
|
||||
var expireTime time.Time
|
||||
|
||||
if item.EndTime != nil {
|
||||
expireTime = *item.EndTime
|
||||
}
|
||||
|
||||
if (item.Status == 3 && item.Actived == 2) || (item.PlatformCode == global.SmsPlatformTextVerified && expireTime.Before(time.Now())) {
|
||||
if err := e.Orm.Model(&item).Updates(map[string]interface{}{"status": 3, "updated_at": time.Now()}).Error; err != nil {
|
||||
e.Log.Errorf("手机号一睡眠 %s", item.Phone)
|
||||
}
|
||||
@ -473,7 +510,7 @@ func (e *SmsPhone) SyncCodes() error {
|
||||
}
|
||||
|
||||
// 获取验证码
|
||||
func (e *SmsPhone) GetCodeManage(platformCode string, messageId string, typ int, unixTime int64) (string, int) {
|
||||
func (e *SmsPhone) GetCodeManage(platformCode string, messageId string, typ int, userId int, smsService, serviceCode string) (string, int) {
|
||||
switch platformCode {
|
||||
case global.SmsPlatformDaisysms:
|
||||
service := SmsDaisysms{Service: e.Service}
|
||||
@ -481,98 +518,224 @@ func (e *SmsPhone) GetCodeManage(platformCode string, messageId string, typ int,
|
||||
return service.GetCodeForApi(messageId)
|
||||
case global.SmsPlatformTextVerified:
|
||||
service := SmsTextVerified{Service: e.Service}
|
||||
return service.GetCode(messageId, typ, unixTime)
|
||||
return service.GetCode(messageId, typ, userId, smsService, serviceCode)
|
||||
default:
|
||||
return "", statuscode.SmsPlatformUnavailable
|
||||
}
|
||||
}
|
||||
|
||||
// 自动续期
|
||||
func (e SmsServices) AutoRenewal() error {
|
||||
var datas []models.SmsPhone
|
||||
var data models.SmsPhone
|
||||
startTime := time.Now().Add(-24 * time.Hour)
|
||||
endTime := time.Now().Add(24 * time.Hour)
|
||||
|
||||
smsServices := SmsServices{Service: e.Service}
|
||||
serviceMap := smsServices.GetMapAll()
|
||||
|
||||
configService := SysConfig{Service: e.Service}
|
||||
mapDatas, _ := configService.GetMapByKeys([]string{"renew_number_premium_daisysms", "renew_number_premium_textverified"})
|
||||
|
||||
if err := e.Orm.Model(&models.SmsPhone{}).Where("auto_renewal =1 and type =1 and actived =2 and expire_time >=? and expire_time <?", startTime, endTime).Find(&datas).Error; err != nil {
|
||||
// AutoRenewal 自动续期处理
|
||||
// 处理即将到期的长期号码自动续费逻辑
|
||||
func (e *SmsPhone) AutoRenewal() error {
|
||||
// 获取24小时内到期的自动续费号码
|
||||
expiredPhones, err := e.getExpiredPhones()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, item := range datas {
|
||||
percent := decimal.NewFromInt(1)
|
||||
price := decimal.Zero
|
||||
// 获取服务配置映射
|
||||
serviceMap, premiumMap, err := e.getRenewalConfigs()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if service, ok := serviceMap[item.PlatformCode+"_"+item.ServiceCode]; !ok {
|
||||
// 处理每个到期号码
|
||||
for _, phone := range expiredPhones {
|
||||
if err := e.processPhoneRenewal(phone, serviceMap, premiumMap); err != nil {
|
||||
e.Log.Errorf("处理号码续费失败 [PhoneID: %d]: %v", phone.Id, err)
|
||||
continue
|
||||
} else {
|
||||
price = service.LongPrice
|
||||
switch {
|
||||
case item.PlatformCode == global.SmsPlatformDaisysms:
|
||||
p, ok := mapDatas["renew_number_premium_daisysms"]
|
||||
val, _ := decimal.NewFromString(p.ConfigValue)
|
||||
|
||||
if ok && val.Cmp(decimal.Zero) > 0 {
|
||||
per := decimal.NewFromInt(100).Add(val)
|
||||
percent = per.Div(decimal.NewFromInt(100)).Truncate(2)
|
||||
}
|
||||
case item.PlatformCode == global.SmsPlatformTextVerified:
|
||||
p, ok := mapDatas["renew_number_premium_textverified"]
|
||||
val, _ := decimal.NewFromString(p.ConfigValue)
|
||||
|
||||
if ok && val.Cmp(decimal.Zero) > 0 {
|
||||
per := decimal.NewFromInt(100).Add(val)
|
||||
percent = per.Div(decimal.NewFromInt(100)).Truncate(2)
|
||||
}
|
||||
}
|
||||
|
||||
renewLog := models.SmsRenewalLog{}
|
||||
renewLog.UserId = item.UserId
|
||||
renewLog.PhoneId = item.Id
|
||||
renewLog.Type = item.Type
|
||||
renewLog.Amount = price.Mul(percent).Truncate(2)
|
||||
renewLog.BeforeTime = *item.ExpireTime
|
||||
renewLog.Period = 30
|
||||
|
||||
if err := e.Orm.Transaction(func(tx *gorm.DB) error {
|
||||
db := tx.Exec("UPDATE member_balance set balance = balance - ? where user_id = ? and balance >= ?", price, item.UserId, price)
|
||||
|
||||
if db.Error != nil {
|
||||
return db.Error
|
||||
}
|
||||
|
||||
if db.RowsAffected == 0 {
|
||||
return errors.New("余额不足")
|
||||
}
|
||||
|
||||
if err1 := tx.Create(&renewLog).Error; err1 != nil {
|
||||
|
||||
return errors.New("创建续费日志失败")
|
||||
}
|
||||
|
||||
newExpireTime := item.ExpireTime.AddDate(0, 0, 30)
|
||||
if err1 := tx.Model(data).Where("id =?", item.Id).Update("expire_time", newExpireTime).Error; err1 != nil {
|
||||
return err1
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
e.Log.Errorf("自动续期失败:%s", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getExpiredPhones 获取即将到期的自动续费号码
|
||||
func (e *SmsPhone) getExpiredPhones() ([]models.SmsPhone, error) {
|
||||
var phones []models.SmsPhone
|
||||
startTime := time.Now().Add(-24 * time.Hour)
|
||||
endTime := time.Now().Add(24 * time.Hour)
|
||||
|
||||
err := e.Orm.Model(&models.SmsPhone{}).
|
||||
Where("auto_renewal = 1 AND type = 1 AND actived = 2 AND expire_time >= ? AND expire_time < ?", startTime, endTime).
|
||||
Find(&phones).Error
|
||||
|
||||
return phones, err
|
||||
}
|
||||
|
||||
// getRenewalConfigs 获取续费相关配置
|
||||
func (e *SmsPhone) getRenewalConfigs() (map[string]models.SmsServices, map[string]dto.GetSysConfigByKEYForServiceResp, error) {
|
||||
smsServices := SmsServices{Service: e.Service}
|
||||
serviceMap := smsServices.GetMapAll()
|
||||
|
||||
configService := SysConfig{Service: e.Service}
|
||||
configKeys := []string{"renew_number_premium_daisysms", "renew_number_premium_textverified"}
|
||||
premiumMap, err := configService.GetMapByKeys(configKeys)
|
||||
|
||||
return serviceMap, premiumMap, err
|
||||
}
|
||||
|
||||
// processPhoneRenewal 处理单个号码的续费
|
||||
func (e *SmsPhone) processPhoneRenewal(phone models.SmsPhone, serviceMap map[string]models.SmsServices, premiumMap map[string]dto.GetSysConfigByKEYForServiceResp) error {
|
||||
// 获取服务价格
|
||||
service, exists := serviceMap[phone.PlatformCode+"_"+phone.ServiceCode]
|
||||
if !exists {
|
||||
return errors.New("服务不存在")
|
||||
}
|
||||
|
||||
// 计算续费价格
|
||||
renewalPrice := e.calculateRenewalPrice(service.LongPrice, phone.PlatformCode, premiumMap)
|
||||
if renewalPrice.IsZero() {
|
||||
return errors.New("续费价格计算失败")
|
||||
}
|
||||
|
||||
// 创建续费日志
|
||||
renewLog := e.createRenewalLog(phone, renewalPrice)
|
||||
|
||||
// 执行续费事务
|
||||
return e.executeRenewalTransaction(phone, renewalPrice, renewLog)
|
||||
}
|
||||
|
||||
// calculateRenewalPrice 计算续费价格
|
||||
func (e *SmsPhone) calculateRenewalPrice(basePrice decimal.Decimal, platformCode string, premiumMap map[string]dto.GetSysConfigByKEYForServiceResp) decimal.Decimal {
|
||||
percent := decimal.NewFromInt(1)
|
||||
|
||||
var configKey string
|
||||
switch platformCode {
|
||||
case global.SmsPlatformDaisysms:
|
||||
configKey = "renew_number_premium_daisysms"
|
||||
case global.SmsPlatformTextVerified:
|
||||
configKey = "renew_number_premium_textverified"
|
||||
default:
|
||||
return basePrice
|
||||
}
|
||||
|
||||
if config, exists := premiumMap[configKey]; exists {
|
||||
if val, err := decimal.NewFromString(config.ConfigValue); err == nil && val.Cmp(decimal.Zero) > 0 {
|
||||
percent = decimal.NewFromInt(100).Add(val).Div(decimal.NewFromInt(100))
|
||||
}
|
||||
}
|
||||
|
||||
return basePrice.Mul(percent).Truncate(2)
|
||||
}
|
||||
|
||||
// createRenewalLog 创建续费日志
|
||||
func (e *SmsPhone) createRenewalLog(phone models.SmsPhone, amount decimal.Decimal) models.SmsRenewalLog {
|
||||
return models.SmsRenewalLog{
|
||||
UserId: phone.UserId,
|
||||
PhoneId: phone.Id,
|
||||
Type: phone.Type,
|
||||
Amount: amount,
|
||||
BeforeTime: *phone.ExpireTime,
|
||||
Period: 30,
|
||||
}
|
||||
}
|
||||
|
||||
// executeRenewalTransaction 执行续费事务
|
||||
func (e *SmsPhone) executeRenewalTransaction(phone models.SmsPhone, price decimal.Decimal, renewLog models.SmsRenewalLog) error {
|
||||
err := e.Orm.Transaction(func(tx *gorm.DB) error {
|
||||
// 扣除余额
|
||||
result := tx.Exec("UPDATE member_balance SET balance = balance - ? WHERE user_id = ? AND balance >= ?", price, phone.UserId, price)
|
||||
if result.Error != nil {
|
||||
return result.Error
|
||||
}
|
||||
if result.RowsAffected == 0 {
|
||||
return errors.New("余额不足")
|
||||
}
|
||||
|
||||
// 创建续费日志
|
||||
if err := tx.Create(&renewLog).Error; err != nil {
|
||||
return errors.New("创建续费日志失败")
|
||||
}
|
||||
|
||||
// 更新到期时间
|
||||
newExpireTime := phone.ExpireTime.AddDate(0, 0, 30)
|
||||
params := map[string]interface{}{
|
||||
"expire_time": newExpireTime,
|
||||
"remark": "",
|
||||
}
|
||||
|
||||
if err := tx.Model(&models.SmsPhone{}).Where("id = ?", phone.Id).
|
||||
Updates(params).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err.Error() == "余额不足" {
|
||||
|
||||
return e.handleInsufficientBalance(phone)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// handleInsufficientBalance 处理余额不足情况
|
||||
func (e *SmsPhone) handleInsufficientBalance(phone models.SmsPhone) error {
|
||||
params := map[string]interface{}{
|
||||
"auto_renewal": 2,
|
||||
"remark": "余额不足,取消自动续费",
|
||||
}
|
||||
// 取消自动续费
|
||||
if err := e.Orm.Model(&models.SmsPhone{}).
|
||||
Where("id = ?", phone.Id).
|
||||
Updates(params).Error; err != nil {
|
||||
e.Log.Errorf("余额不足,取消自动续费失败: %v", err)
|
||||
}
|
||||
|
||||
// 调用平台取消续费接口
|
||||
code := e.ChangeAutoRenewManage(phone.PlatformCode, phone.ActivationId, false)
|
||||
if code != statuscode.Success {
|
||||
params["auto_renewal"] = 1
|
||||
params["remark"] = ""
|
||||
// 如果平台取消失败,恢复自动续费状态
|
||||
if err := e.Orm.Model(&models.SmsPhone{}).
|
||||
Where("id = ?", phone.Id).
|
||||
Updates(params).Error; err != nil {
|
||||
e.Log.Errorf("恢复自动续费状态失败: %v", err)
|
||||
}
|
||||
e.Log.Errorf("平台取消自动续费失败,状态码: %d", code)
|
||||
}
|
||||
|
||||
return errors.New("余额不足")
|
||||
}
|
||||
|
||||
// ChangeAutoRenew 修改自动续期
|
||||
func (e *SmsPhone) ChangeAutoRenew(req *dto.SmsPhoneChangeAutoRenewReq, userId int) int {
|
||||
var data models.SmsPhone
|
||||
|
||||
if req.AutoRenew == 1 {
|
||||
smsServices := SmsServices{Service: e.Service}
|
||||
balanceService := MemberBalance{Service: e.Service}
|
||||
balance := balanceService.GetBalance(userId)
|
||||
|
||||
if err := e.Orm.Model(data).Where("id =? or activation_id =?", req.Id, req.ActivationId).First(&data).Error; err != nil {
|
||||
e.Log.Errorf("修改自动续期 数据不存在 id:%d err:%s", req.Id, err.Error())
|
||||
return statuscode.SmsNotExisted
|
||||
}
|
||||
|
||||
if data.ExpireTime.Before(time.Now()) {
|
||||
return statuscode.SmsRentalCantRenew
|
||||
}
|
||||
|
||||
serviceItem, err := smsServices.GetByCode(data.PlatformCode, data.ServiceCode)
|
||||
|
||||
if err != nil {
|
||||
e.Log.Errorf("短信服务报错:%v", err)
|
||||
return statuscode.ServerError
|
||||
}
|
||||
configService := SysConfig{Service: e.Service}
|
||||
configKeys := []string{"renew_number_premium_daisysms", "renew_number_premium_textverified"}
|
||||
premiumMap, _ := configService.GetMapByKeys(configKeys)
|
||||
|
||||
price := e.calculateRenewalPrice(serviceItem.LongPrice, serviceItem.PlatformCode, premiumMap)
|
||||
|
||||
if balance.Cmp(price) < 0 {
|
||||
return statuscode.BalanceNotEnough
|
||||
}
|
||||
}
|
||||
|
||||
if req.Id > 0 {
|
||||
if err := e.Orm.Model(data).Where("id =? and user_id =?", req.Id, userId).First(&data).Error; err != nil {
|
||||
e.Log.Errorf("修改自动续期 数据不存在 id:%d err:%s", req.Id, err.Error())
|
||||
|
||||
@ -2,6 +2,7 @@ package service
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-admin-team/go-admin-core/sdk/service"
|
||||
"gorm.io/gorm"
|
||||
@ -38,7 +39,7 @@ func (e SmsReceiveLog) WebHook(req *dto.SmsReceiveWebHookReq) error {
|
||||
UserId: phoneLog.UserId,
|
||||
Service: phoneLog.Service,
|
||||
ServiceCode: phoneLog.ServiceCode,
|
||||
MessageId: req.MessageID,
|
||||
MessageId: strconv.Itoa(req.MessageID),
|
||||
Phone: phoneLog.Phone,
|
||||
Code: req.Code,
|
||||
Status: 2,
|
||||
|
||||
@ -13,7 +13,7 @@ import (
|
||||
)
|
||||
|
||||
func initSetting() *gorm.DB {
|
||||
dsn := "root:123456@tcp(127.0.0.1:3306)/proxy_server?charset=utf8mb4&parseTime=True&loc=Local&timeout=1000ms"
|
||||
dsn := "root:123456@tcp(127.0.0.1:3306)/proxy-server-prod?charset=utf8mb4&parseTime=True&loc=Local&timeout=1000ms"
|
||||
db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
|
||||
sdk.Runtime.SetDb("default", db)
|
||||
config.ExtConfig.TrxGridUrl = "https://api.trongrid.io"
|
||||
|
||||
@ -32,7 +32,7 @@ type SmsTextVerified struct {
|
||||
// 获取收到的验证码
|
||||
// messageId 短效或长效号码的ID
|
||||
// typ 0-短效 1-长效
|
||||
func (e SmsTextVerified) GetCode(messageId string, typ int, unixTime int64) (string, int) {
|
||||
func (e SmsTextVerified) GetCode(messageId string, typ int, userId int, service, serviceCode string) (string, int) {
|
||||
reservationType := ""
|
||||
|
||||
if typ == 0 {
|
||||
@ -58,23 +58,84 @@ func (e SmsTextVerified) GetCode(messageId string, typ int, unixTime int64) (str
|
||||
return "", statuscode.ServerError
|
||||
}
|
||||
|
||||
messageIds := []string{}
|
||||
|
||||
if len(resp.Data) > 0 {
|
||||
for _, v := range resp.Data {
|
||||
// 2. 解析时间字符串
|
||||
// time.RFC3339Nano 是一个预定义的格式常量,
|
||||
// 它能够解析包含纳秒和时区信息的 ISO 8601 字符串。
|
||||
messageIds = append(messageIds, v.Id)
|
||||
}
|
||||
}
|
||||
|
||||
if len(messageIds) > 0 {
|
||||
receiveLogs := make([]models.SmsReceiveLog, 0)
|
||||
receiveMaps := make(map[string]string, 0)
|
||||
|
||||
if err := e.Orm.Model(&models.SmsReceiveLog{}).
|
||||
Where("message_id in ?", messageIds).
|
||||
Select("message_id").
|
||||
Find(&receiveLogs).Error; err != nil {
|
||||
e.Log.Errorf("获取短信接收记录失败, error: %v", err)
|
||||
return "", statuscode.ServerError
|
||||
}
|
||||
|
||||
for _, v := range receiveLogs {
|
||||
receiveMaps[v.MessageId] = v.MessageId
|
||||
}
|
||||
|
||||
// 查找最新验证码并存储所有新验证码
|
||||
var latestSms *dto.TextVerifiedSmsItemResp
|
||||
var latestTime time.Time
|
||||
var newSmsData []dto.TextVerifiedSmsItemResp
|
||||
|
||||
// 遍历所有验证码数据
|
||||
for _, v := range resp.Data {
|
||||
// 解析时间字符串
|
||||
t, err := time.Parse(time.RFC3339Nano, v.CreatedAt)
|
||||
if err != nil {
|
||||
fmt.Println("时间解析失败:", err)
|
||||
e.Log.Errorf("时间解析失败: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
// 3. 将解析后的 time.Time 对象转换为 Unix 时间戳
|
||||
// t.Unix() 返回以秒为单位的整数时间戳
|
||||
unixTimestamp := t.Unix()
|
||||
// 检查是否为新验证码(数据库中不存在)
|
||||
if _, ok := receiveMaps[v.Id]; !ok {
|
||||
newSmsData = append(newSmsData, v)
|
||||
}
|
||||
|
||||
if unixTimestamp >= unixTime {
|
||||
parsedCode = v.ParsedCode
|
||||
break
|
||||
// 选择最新的验证码(包括已存在的)
|
||||
if latestSms == nil || t.After(latestTime) {
|
||||
latestSms = &v
|
||||
latestTime = t
|
||||
}
|
||||
}
|
||||
|
||||
// 批量保存所有新验证码到数据库
|
||||
if len(newSmsData) > 0 {
|
||||
var receiveLogs []models.SmsReceiveLog
|
||||
for _, sms := range newSmsData {
|
||||
receiveLog := models.SmsReceiveLog{
|
||||
UserId: userId,
|
||||
Service: service,
|
||||
ServiceCode: serviceCode,
|
||||
MessageId: sms.Id,
|
||||
Phone: "1" + sms.To,
|
||||
Code: sms.ParsedCode,
|
||||
Status: 2,
|
||||
}
|
||||
receiveLogs = append(receiveLogs, receiveLog)
|
||||
}
|
||||
|
||||
// 批量插入数据库
|
||||
if err := e.Orm.Create(&receiveLogs).Error; err != nil {
|
||||
e.Log.Errorf("批量创建短信接收记录失败, error: %v", err)
|
||||
return "", statuscode.ServerError
|
||||
}
|
||||
|
||||
e.Log.Infof("成功存储 %d 条新验证码记录", len(newSmsData))
|
||||
|
||||
// 返回最新的验证码
|
||||
if latestSms != nil {
|
||||
parsedCode = latestSms.ParsedCode
|
||||
e.Log.Infof("返回最新验证码: %s, messageId: %s, 时间: %s", parsedCode, latestSms.Id, latestSms.CreatedAt)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -97,6 +158,7 @@ const (
|
||||
renewRental = "/api/pub/v2/reservations/rental/renewable/%s/renew" //长效续期
|
||||
updateRentalRenewStatus = "/api/pub/v2/reservations/rental/renewable/%s" // 更改续租状态
|
||||
getSmsCode = "/api/pub/v2/sms?reservationId=%s&reservationType=%s" //获取短信验证码
|
||||
getNumbers = "/api/pub/v2/reservations/rental/renewable" //获取长效号码列表 Get
|
||||
)
|
||||
|
||||
var idPattern = regexp.MustCompile(`^[a-zA-Z0-9_]{28}$`)
|
||||
@ -284,12 +346,33 @@ func (e *SmsTextVerified) SyncPrices() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 获取号码并唤醒
|
||||
func (e *SmsTextVerified) GetNumberAndWakeUp(tye int, serviceCode string, price decimal.Decimal, period int) (dto.SmsPhoneGetPhoneResp, int) {
|
||||
resp, code := e.GetNumberForApi(tye, serviceCode, price, period)
|
||||
|
||||
if code != statuscode.Success {
|
||||
return resp, code
|
||||
}
|
||||
|
||||
wakeUpResp, code := e.getExtraActivation(resp.Id)
|
||||
|
||||
if code != statuscode.Success {
|
||||
return resp, code
|
||||
}
|
||||
|
||||
resp.MessageId = wakeUpResp.Id
|
||||
resp.StartTime = wakeUpResp.UsageWindowStart
|
||||
resp.EndTime = wakeUpResp.UsageWindowEnd
|
||||
|
||||
return resp, code
|
||||
}
|
||||
|
||||
// 号码租赁
|
||||
// getType 0-短效 1-长效
|
||||
// service 服务code
|
||||
// maxPrice 最大价格
|
||||
// period 时长(月=30天)
|
||||
func (e SmsTextVerified) GetNumberForApi(typ int, serviceCode string, price decimal.Decimal, period int) (dto.SmsPhoneGetPhoneResp, int) {
|
||||
func (e *SmsTextVerified) GetNumberForApi(typ int, serviceCode string, price decimal.Decimal, period int) (dto.SmsPhoneGetPhoneResp, int) {
|
||||
//这个平台的所有号码都是美国号码 默认国家代码都是 +1
|
||||
var err error
|
||||
var createResp dto.TextVerifiedResp
|
||||
@ -477,12 +560,13 @@ func (e *SmsTextVerified) GetRentalDetail(id string) (dto.VerificationRentalDeta
|
||||
}
|
||||
|
||||
// 唤醒号码
|
||||
// returns activationId,messageId, code
|
||||
func (e SmsTextVerified) getExtraActivation(id string) (string, string, int) {
|
||||
// returns activationId,messageId,startTime(可用开始时间),endTime(可用结束时间), code,
|
||||
func (e SmsTextVerified) getExtraActivation(id string) (dto.TextVerifiedWakeUpResp, int) {
|
||||
client, code := e.GetTextVerifiedAuthClient()
|
||||
result := dto.TextVerifiedWakeUpResp{}
|
||||
|
||||
if code != statuscode.Success {
|
||||
return "", "", code
|
||||
return result, code
|
||||
}
|
||||
|
||||
req := dto.TextVerifiedWakeUpReq{
|
||||
@ -497,31 +581,35 @@ func (e SmsTextVerified) getExtraActivation(id string) (string, string, int) {
|
||||
|
||||
if err != nil {
|
||||
e.Log.Errorf("唤醒号码失败 id:%s error: %v", id, err)
|
||||
return "", "", statuscode.ServerError
|
||||
return result, statuscode.ServerError
|
||||
} else if status == http.StatusCreated || status == http.StatusOK {
|
||||
if resp.Method != "" && resp.Href != "" {
|
||||
bytes, err := e.doRequest(&resp)
|
||||
|
||||
if err != nil {
|
||||
e.Log.Errorf("唤醒号码失败 id:%s error: %v", id, err)
|
||||
return "", "", statuscode.ServerError
|
||||
return result, statuscode.ServerError
|
||||
}
|
||||
|
||||
detailResp := dto.TextVerifiedWakeUpResp{}
|
||||
|
||||
if err := sonic.Unmarshal(bytes, &detailResp); err != nil {
|
||||
e.Log.Errorf("唤醒号码反序列化失败 id:%s error: %v", id, err)
|
||||
return "", "", statuscode.ServerError
|
||||
return result, statuscode.ServerError
|
||||
}
|
||||
|
||||
return detailResp.ReservationId, detailResp.Id, statuscode.Success
|
||||
result.Id = detailResp.Id
|
||||
result.ReservationId = detailResp.ReservationId
|
||||
result.UsageWindowEnd = detailResp.UsageWindowEnd
|
||||
result.UsageWindowStart = detailResp.UsageWindowStart
|
||||
return result, statuscode.Success
|
||||
} else {
|
||||
e.Log.Errorf("唤醒号码失败 id:%s error: %v", id, err)
|
||||
return "", "", statuscode.ServerError
|
||||
return result, statuscode.ServerError
|
||||
}
|
||||
}
|
||||
|
||||
return "", "", statuscode.ServerError
|
||||
return result, statuscode.ServerError
|
||||
}
|
||||
|
||||
// 获取价格
|
||||
@ -826,7 +914,121 @@ func (e *SmsTextVerified) Renew(activationId string, status bool) int {
|
||||
}
|
||||
}
|
||||
|
||||
// 重新初始化短信记录
|
||||
func (e *SmsTextVerified) InitSmsLogs() error {
|
||||
// phones, err := e.GetNumbers()
|
||||
|
||||
// if err != nil {
|
||||
// e.Log.Errorf("获取长效号码列表失败 %v", err)
|
||||
// return fmt.Errorf("获取长效号码列表失败 %v", err)
|
||||
// }
|
||||
|
||||
// numbers := make([]string, 0)
|
||||
|
||||
// for _, v := range phones {
|
||||
// numbers = append(numbers, v.Number)
|
||||
// }
|
||||
|
||||
phoneLogs, err := e.GetUserByNumber("textverified")
|
||||
|
||||
if err != nil {
|
||||
e.Log.Errorf("获取系统内号码记录失败 %v", err)
|
||||
return fmt.Errorf("获取系统内号码记录失败 %v", err)
|
||||
}
|
||||
|
||||
if len(phoneLogs) > 0 {
|
||||
for _, v := range phoneLogs {
|
||||
e.GetCode(v.ActivationId, v.Type, v.UserId, v.Service, v.ServiceCode)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 根据电话号码获取系统内记录
|
||||
func (e *SmsTextVerified) GetUserByNumber(platformCode string) ([]models.SmsPhone, error) {
|
||||
var result []models.SmsPhone
|
||||
|
||||
if err := e.Orm.Model(&models.SmsPhone{}).Where("platform_code = ?", platformCode).Find(&result).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// 获取号码
|
||||
func (e *SmsTextVerified) GetNumbers() ([]dto.VerificationDTO, error) {
|
||||
client, code := e.GetTextVerifiedAuthClient()
|
||||
result := make([]dto.VerificationDTO, 0)
|
||||
|
||||
if code != statuscode.Success {
|
||||
e.Log.Errorf("获取长效号码列表失败 %d", code)
|
||||
return result, fmt.Errorf("获取长效号码列表失败 %d", code)
|
||||
}
|
||||
|
||||
resp := dto.TextVerifiedGetNumbersResp{}
|
||||
statusCode, err := client.Get(getNumbers, map[string]string{}, resp)
|
||||
|
||||
if err != nil {
|
||||
e.Log.Errorf("获取长效号码列表失败 %v", err)
|
||||
return result, fmt.Errorf("获取长效号码列表失败 %v", err)
|
||||
}
|
||||
|
||||
if statusCode == http.StatusOK {
|
||||
// 添加第一页数据
|
||||
result = append(result, resp.Data...)
|
||||
|
||||
// 处理分页数据
|
||||
if resp.HasNext {
|
||||
paginatedData, err := e.fetchPaginatedData(resp.Links.Next)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
result = append(result, paginatedData...)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
} else if statusCode == http.StatusUnauthorized {
|
||||
return e.GetNumbers()
|
||||
} else {
|
||||
e.Log.Errorf("获取长效号码列表失败 %d", statusCode)
|
||||
return result, fmt.Errorf("获取长效号码列表失败 %d", statusCode)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取授权header头
|
||||
// fetchPaginatedData 获取分页数据的通用方法
|
||||
// 处理TextVerified API的分页响应,自动获取所有页面的数据
|
||||
func (e *SmsTextVerified) fetchPaginatedData(nextLink *dto.TextVerifiedResp) ([]dto.VerificationDTO, error) {
|
||||
var result []dto.VerificationDTO
|
||||
|
||||
for nextLink != nil {
|
||||
nextData, err := e.doRequest(nextLink)
|
||||
if err != nil {
|
||||
e.Log.Errorf("获取分页数据失败: %v", err)
|
||||
return result, fmt.Errorf("获取分页数据失败: %v", err)
|
||||
}
|
||||
|
||||
nextResp := dto.TextVerifiedGetNumbersResp{}
|
||||
err = sonic.Unmarshal(nextData, &nextResp)
|
||||
if err != nil {
|
||||
e.Log.Errorf("解析分页数据失败: %v", err)
|
||||
return result, fmt.Errorf("解析分页数据失败: %v", err)
|
||||
}
|
||||
|
||||
result = append(result, nextResp.Data...)
|
||||
|
||||
// 检查是否还有下一页
|
||||
if nextResp.HasNext {
|
||||
nextLink = nextResp.Links.Next
|
||||
} else {
|
||||
nextLink = nil
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (e *SmsTextVerified) GetAuthHeader() (map[string]string, error) {
|
||||
token, err := e.GetToken()
|
||||
if err != nil {
|
||||
|
||||
@ -51,3 +51,18 @@ func TestSyncTextVerifiedServices(t *testing.T) {
|
||||
t.Log("SyncTextVerifiedServices succeeded")
|
||||
}
|
||||
}
|
||||
|
||||
func TestInitSmsLogs(t *testing.T) {
|
||||
db := initSetting()
|
||||
|
||||
s := SmsTextVerified{}
|
||||
s.Orm = db
|
||||
s.Log = logger.NewHelper(logger.DefaultLogger)
|
||||
|
||||
err := s.InitSmsLogs()
|
||||
if err != nil {
|
||||
t.Errorf("InitSmsLogs failed: %v", err)
|
||||
} else {
|
||||
t.Log("InitSmsLogs succeeded")
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,11 +37,11 @@ func (j RenewalJob) Exec(args interface{}) error {
|
||||
|
||||
// 定时短信续期任务
|
||||
func (j SmsRenewalJob) Exec(args interface{}) error {
|
||||
smsService := service.SmsServices{}
|
||||
smsService.Orm = GetDb()
|
||||
smsService.Log = logger.NewHelper(logger.DefaultLogger)
|
||||
smsPhoneService := service.SmsPhone{}
|
||||
smsPhoneService.Orm = GetDb()
|
||||
smsPhoneService.Log = logger.NewHelper(logger.DefaultLogger)
|
||||
|
||||
return smsService.AutoRenewal()
|
||||
return smsPhoneService.AutoRenewal()
|
||||
}
|
||||
|
||||
// 过期任务
|
||||
|
||||
@ -41,6 +41,7 @@ var StatusCodeZh = map[int]string{
|
||||
SmsInvalidType: "短信验证码_无效类型",
|
||||
SmsOutOfStockOrUnavailable: "短信验证码_缺货或服务不可用",
|
||||
SmsRentalRefundNotPermitted: "短信验证码_租赁退款不允许",
|
||||
SmsRentalCantRenew: "短信验证码_无法续期",
|
||||
}
|
||||
|
||||
var StatusCodeEn = map[int]string{
|
||||
@ -74,6 +75,7 @@ var StatusCodeEn = map[int]string{
|
||||
SmsInvalidType: "sms type invalid",
|
||||
SmsOutOfStockOrUnavailable: "sms out of stock or unavailable",
|
||||
SmsRentalRefundNotPermitted: "sms rental refund not permitted",
|
||||
SmsRentalCantRenew: "sms rental can not renewal",
|
||||
}
|
||||
|
||||
// GetMsg 获取状态码对应的消息
|
||||
@ -161,4 +163,6 @@ const (
|
||||
SmsOutOfStockOrUnavailable = 20024
|
||||
// 短信-租赁退款不允许
|
||||
SmsRentalRefundNotPermitted = 20025
|
||||
// 短信-无法续期
|
||||
SmsRentalCantRenew = 20026
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user