You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
488 lines
13 KiB
488 lines
13 KiB
package telecom |
|
|
|
import ( |
|
"bytes" |
|
"context" |
|
"crypto/des" |
|
"errors" |
|
"fmt" |
|
"math/rand" |
|
"strconv" |
|
"time" |
|
|
|
"go-common/app/interface/main/app-wall/model/telecom" |
|
"go-common/library/ecode" |
|
"go-common/library/log" |
|
"go-common/library/sync/errgroup" |
|
) |
|
|
|
const ( |
|
_sendSMSCaptcha = `{"captcha":"%v"}` |
|
_sendSMSFlow = `{"flow":"%v"}` |
|
_flowPackageID = 279 |
|
) |
|
|
|
// InOrdersSync insert OrdersSync |
|
func (s *Service) InOrdersSync(c context.Context, ip string, u *telecom.TelecomOrderJson) (err error) { |
|
if !s.iplimit(_telecomKey, ip) { |
|
err = ecode.AccessDenied |
|
return |
|
} |
|
if u == nil || u.Detail == nil { |
|
err = ecode.NothingFound |
|
return |
|
} |
|
var ( |
|
result int64 |
|
requestNo int |
|
phoneStr string |
|
detail = u.Detail |
|
) |
|
detail.TelecomJSONChange() |
|
requestNo, _ = strconv.Atoi(u.RequestNo) |
|
if detail.PhoneID == "" { |
|
if phoneStr, err = s.dao.PayPhone(c, int64(requestNo)); err != nil { |
|
log.Error("telecom_s.dao.PayPhone error(%v)", err) |
|
return |
|
} |
|
} else { |
|
phoneStr = detail.PhoneID |
|
} |
|
if result, err = s.dao.InOrderSync(c, requestNo, u.ResultType, phoneStr, detail); err != nil || result == 0 { |
|
log.Error("telecom_s.dao.OrdersSync (%v) error(%v) or result==0", u, err) |
|
return |
|
} |
|
if detail.OrderStatus == 3 { |
|
phoneInt, _ := strconv.Atoi(phoneStr) |
|
if err = s.dao.SendTelecomSMS(c, phoneInt, s.smsOrderTemplateOK); err != nil { |
|
log.Error("telecom_s.dao.SendTelecomSMS error(%v)", err) |
|
return |
|
} |
|
} |
|
return |
|
} |
|
|
|
// InRechargeSync insert RechargeSync |
|
func (s *Service) InRechargeSync(c context.Context, ip string, u *telecom.RechargeJSON) (err error) { |
|
if !s.iplimit(_telecomKey, ip) { |
|
err = ecode.AccessDenied |
|
return |
|
} |
|
var result int64 |
|
if result, err = s.dao.InRechargeSync(c, u); err != nil || result == 0 { |
|
log.Error("telecom_s.dao.InRechargeSync (%v) error(%v) or result==0", u, err) |
|
return |
|
} |
|
return |
|
} |
|
|
|
// telecomMessageOrder |
|
func (s *Service) TelecomMessageSync(c context.Context, ip string, u *telecom.TelecomMessageJSON) (err error) { |
|
if !s.iplimit(_telecomKey, ip) { |
|
err = ecode.AccessDenied |
|
return |
|
} |
|
if u == nil { |
|
err = ecode.ServerErr |
|
return |
|
} |
|
phoneInt, _ := strconv.Atoi(u.PhoneID) |
|
if err = s.dao.SendTelecomSMS(c, phoneInt, s.smsMsgTemplate); err != nil { |
|
log.Error("telecom_s.dao.SendTelecomSMS error(%v)", err) |
|
return |
|
} |
|
return |
|
} |
|
|
|
// telecomInfo |
|
func (s *Service) telecomInfo(c context.Context, phone int) (res map[int]*telecom.OrderInfo, err error) { |
|
var ( |
|
row *telecom.OrderInfo |
|
) |
|
res = map[int]*telecom.OrderInfo{} |
|
if row, err = s.dao.TelecomCache(c, phone); err == nil && row != nil { |
|
res[phone] = row |
|
s.pHit.Incr("telecom_cache") |
|
return |
|
} |
|
if res, err = s.dao.OrdersUserFlow(c, phone); err != nil { |
|
log.Error("telecom_s.dao.OrdersUserFlow phone (%v) error(%v)", phone, err) |
|
return |
|
} |
|
s.pMiss.Incr("telecom_cache") |
|
if user, ok := res[phone]; ok { |
|
if err = s.dao.AddTelecomCache(c, phone, user); err != nil { |
|
log.Error("telecom_s.dao.AddTelecomCache error(%v)", err) |
|
return |
|
} |
|
} |
|
return |
|
} |
|
|
|
// telecomInfoByOrderID |
|
func (s *Service) telecomInfoByOrderID(c context.Context, orderID int64) (res map[int64]*telecom.OrderInfo, err error) { |
|
var ( |
|
row *telecom.OrderInfo |
|
) |
|
res = map[int64]*telecom.OrderInfo{} |
|
if row, err = s.dao.TelecomOrderIDCache(c, orderID); err == nil && row != nil { |
|
res[orderID] = row |
|
s.pHit.Incr("telecom_orderid_cache") |
|
return |
|
} |
|
if res, err = s.dao.OrdersUserByOrderID(c, orderID); err != nil { |
|
log.Error("telecom_s.dao.OrdersUserByOrderID phone (%v) error(%v)", orderID, err) |
|
return |
|
} |
|
s.pMiss.Incr("telecom_orderid_cache") |
|
if user, ok := res[orderID]; ok { |
|
if err = s.dao.AddTelecomOrderIDCache(c, orderID, user); err != nil { |
|
log.Error("telecom_s.dao.AddTelecomOrderIDCache error(%v)", err) |
|
return |
|
} |
|
} |
|
return |
|
} |
|
|
|
// TelecomPay |
|
func (s *Service) TelecomPay(c context.Context, phone, isRepeatOrder, payChannel, payAction int, orderID int64, ipStr string) (res *telecom.Pay, msg string, err error) { |
|
var ( |
|
requestNo int64 |
|
t map[int]*telecom.OrderInfo |
|
rcode int |
|
beginTime time.Time |
|
firstOrderEndtime time.Time |
|
) |
|
if requestNo, err = s.seqdao.SeqID(c); err != nil { |
|
log.Error("telecom_s.seqdao.SeqID error (%v)", err) |
|
return |
|
} |
|
if t, err = s.telecomInfo(c, phone); err != nil { |
|
log.Error("telecom_s.telecomInfo phone(%v) error (%v)", phone, err) |
|
return |
|
} |
|
if user, ok := t[phone]; ok { |
|
beginTime = user.Begintime.Time() |
|
firstOrderEndtime = user.Endtime.Time() |
|
} |
|
if res, err, msg = s.dao.PayInfo(c, requestNo, phone, isRepeatOrder, payChannel, payAction, orderID, ipStr, beginTime, firstOrderEndtime); err != nil || res == nil { |
|
log.Error("telecom_s.dao.PayInfo requestNo (%v) phone (%v) isRepeatOrder (%v) payChannel (%v) payAction (%v) t.OrderID (%v) ipStr (%v) error (%v)", |
|
requestNo, phone, isRepeatOrder, payChannel, payAction, orderID, ipStr, err) |
|
return |
|
} |
|
phoneStr := strconv.Itoa(phone) |
|
if rcode, err = s.dao.AddPayPhone(c, requestNo, phoneStr); err != nil || rcode != 1 { |
|
log.Error("telecom_s.dao.AddPayPhone error (%v)", err) |
|
return |
|
} |
|
return |
|
} |
|
|
|
// CancelRepeatOrder |
|
func (s *Service) CancelRepeatOrder(c context.Context, phone int) (msg string, err error) { |
|
var ( |
|
res map[int]*telecom.OrderInfo |
|
) |
|
res, err = s.telecomInfo(c, phone) |
|
if err != nil { |
|
log.Error("telecom_s.telecomInfo phone(%v) error (%v)", phone, err) |
|
return |
|
} |
|
user, ok := res[phone] |
|
if !ok { |
|
err = ecode.NothingFound |
|
msg = "订单不存在" |
|
return |
|
} |
|
if msg, err = s.dao.CancelRepeatOrder(c, phone, user.SignNo); err != nil { |
|
log.Error("telecom_s.dao.CancelRepeatOrder phone(%v) signNo(%v) error (%v)", phone, user.SignNo, err) |
|
return |
|
} |
|
return |
|
} |
|
|
|
// OrderList user order list |
|
func (s *Service) OrderList(c context.Context, orderID int64, phone int) (res *telecom.SucOrder, msg string, err error) { |
|
if res, err, msg = s.dao.SucOrderList(c, phone); err != nil || res == nil { |
|
log.Error("telecom_s.dao.SucOrderList orderID (%v) phone (%v) error (%v)", orderID, phone, err) |
|
return |
|
} |
|
return |
|
} |
|
|
|
// PhoneFlow user flow |
|
func (s *Service) PhoneFlow(c context.Context, orderID int64, phone int) (res *telecom.OrderFlow, msg string, err error) { |
|
var t *telecom.SucOrder |
|
if t, err, msg = s.dao.SucOrderList(c, phone); err != nil || t == nil { |
|
log.Error("telecom_s.dao.SucOrderList orderID (%v) phone (%v) error (%v)", orderID, phone, err) |
|
return |
|
} |
|
res = &telecom.OrderFlow{ |
|
FlowBalance: t.FlowBalance, |
|
} |
|
if (t.FlowBalance/t.FlowPackageSize)*100 < s.flowPercentage { |
|
flow := strconv.Itoa(t.FlowBalance) |
|
dataJSON := fmt.Sprintf(_sendSMSFlow, flow) |
|
if err = s.dao.SendSMS(c, phone, s.smsFlowTemplate, dataJSON); err != nil { |
|
log.Error("telecom_s.dao.SendSMS phone(%v) error (%v)", phone, err) |
|
return |
|
} |
|
msg = "免流量量剩余不不⾜足10%,超出部分会按正常流量量资费计费" |
|
return |
|
} |
|
return |
|
} |
|
|
|
// OrderConsent user orderConsent |
|
func (s *Service) OrderConsent(c context.Context, phone int, orderID int64, captcha string) (res *telecom.PhoneConsent, msg string, err error) { |
|
var ( |
|
area string |
|
t *telecom.SucOrder |
|
captchaStr string |
|
order *telecom.OrderPhoneState |
|
) |
|
captchaStr, err = s.dao.PhoneCode(c, phone) |
|
if err != nil { |
|
log.Error("telecom_s.dao.PhoneCode error (%v)", err) |
|
msg = "验证码已过期" |
|
return |
|
} |
|
if captchaStr == "" || captchaStr != captcha { |
|
err = ecode.NotModified |
|
msg = "验证码错误" |
|
return |
|
} |
|
res = &telecom.PhoneConsent{ |
|
Consent: 0, |
|
} |
|
g, ctx := errgroup.WithContext(c) |
|
g.Go(func() error { |
|
if area, err, msg = s.dao.PhoneArea(ctx, phone); err != nil { |
|
log.Error("telecom_s.dao.PhoneArea phone(%v) error (%v)", phone, err) |
|
return err |
|
} |
|
return nil |
|
}) |
|
g.Go(func() error { |
|
if t, err, _ = s.dao.SucOrderList(ctx, phone); err != nil { |
|
if err == ecode.NothingFound { |
|
err = nil |
|
} else { |
|
log.Error("telecom_s.dao.SucOrderList sphone (%v) error (%v)", phone, err) |
|
} |
|
return err |
|
} |
|
return nil |
|
}) |
|
if orderID > 0 { |
|
g.Go(func() error { |
|
if order, err = s.dao.OrderState(ctx, orderID); err != nil { |
|
log.Error("telecom_s.dao.OrderState phone(%v) orderID(%v) error(%v)", phone, orderID, err) |
|
return err |
|
} |
|
return nil |
|
}) |
|
} |
|
if err = g.Wait(); err != nil { |
|
log.Error("telecom_errgroup.WithContext error(%v)", err) |
|
return |
|
} |
|
if len(area) >= 4 { |
|
a := area[:4] |
|
if _, ok := s.telecomArea[a]; !ok { |
|
return |
|
} |
|
} |
|
if order != nil && order.OrderState == 2 && order.FlowPackageID == _flowPackageID { |
|
res.Consent = 3 |
|
return |
|
} |
|
if t != nil && t.OrderID > 0 { |
|
res.Consent = 2 |
|
return |
|
} |
|
res.Consent = 1 |
|
return |
|
} |
|
|
|
// PhoneCode |
|
func (s *Service) PhoneCode(c context.Context, phone int, captcha string, now time.Time) (res *telecom.Pay, err error, msg string) { |
|
var ( |
|
captchaStr string |
|
order map[int]*telecom.OrderInfo |
|
) |
|
captchaStr, err = s.dao.PhoneCode(c, phone) |
|
if err != nil { |
|
log.Error("telecom_s.dao.PhoneCode error (%v)", err) |
|
msg = "验证码已过期" |
|
return |
|
} |
|
if captchaStr == "" || captchaStr != captcha { |
|
err = ecode.NotModified |
|
msg = "验证码错误" |
|
return |
|
} |
|
if order, err = s.telecomInfo(c, phone); err != nil { |
|
log.Error("telecom_s.telecomInfo phone(%v) error (%v)", phone, err) |
|
return |
|
} |
|
user, ok := order[phone] |
|
if !ok { |
|
err = ecode.NothingFound |
|
msg = "订单不存在" |
|
return |
|
} |
|
switch user.OrderState { |
|
case 2: |
|
err = ecode.NotModified |
|
msg = "订购中" |
|
case 3: |
|
if now.Unix() > int64(user.Endtime) { |
|
err = ecode.NotModified |
|
msg = "订单已过期" |
|
} else { |
|
res = &telecom.Pay{ |
|
OrderID: user.OrderID, |
|
} |
|
msg = "激活成功,麻麻再也不不⽤用担⼼心我的流量量了了(/≧▽≦)/" |
|
} |
|
case 4: |
|
err = ecode.NotModified |
|
msg = "订单失败" |
|
case 5: |
|
err = ecode.NotModified |
|
msg = "订单已过期" |
|
} |
|
return |
|
} |
|
|
|
// PhoneSendSMS |
|
func (s *Service) PhoneSendSMS(c context.Context, phone int) (err error) { |
|
var ( |
|
captcha string |
|
rcode int |
|
) |
|
r := rand.New(rand.NewSource(time.Now().UnixNano())) |
|
for i := 0; i < 6; i++ { |
|
captcha = captcha + strconv.Itoa(r.Intn(10)) |
|
} |
|
dataJSON := fmt.Sprintf(_sendSMSCaptcha, captcha) |
|
if err = s.dao.SendSMS(c, phone, s.smsTemplate, dataJSON); err != nil { |
|
log.Error("telecom_s.dao.SendSMS error (%v)", err) |
|
return |
|
} |
|
if rcode, err = s.dao.AddPhoneCode(c, phone, captcha); err != nil || rcode != 1 { |
|
log.Error("telecom_s.dao.AddPhoneCode error (%v)", err) |
|
return |
|
} |
|
return |
|
} |
|
|
|
// OrderState |
|
func (s *Service) OrderState(c context.Context, orderid int64) (t *telecom.OrderState, msg string, err error) { |
|
var ( |
|
orderState *telecom.OrderPhoneState |
|
torder map[int64]*telecom.OrderInfo |
|
userOrder *telecom.OrderInfo |
|
tSucOrder *telecom.SucOrder |
|
ok bool |
|
) |
|
g, ctx := errgroup.WithContext(c) |
|
log.Error("userOrder.PhoneID_test") |
|
g.Go(func() error { |
|
if orderState, err = s.dao.OrderState(ctx, orderid); err != nil { |
|
log.Error("telecom_s.dao.OrderState orderID error(%v)", orderid, err) |
|
return err |
|
} |
|
return nil |
|
}) |
|
g.Go(func() error { |
|
if torder, err = s.telecomInfoByOrderID(c, orderid); err != nil { |
|
log.Error("telecom_s.telecomInfoByOrderID error(%v)", orderid, err) |
|
return err |
|
} |
|
if userOrder, ok = torder[orderid]; ok { |
|
if tSucOrder, err, _ = s.dao.SucOrderList(ctx, userOrder.PhoneID); err != nil { |
|
if err == ecode.NothingFound { |
|
err = nil |
|
} else { |
|
log.Error("telecom_s.dao.SucOrderList sphone (%v) error (%v)", userOrder.PhoneID, err) |
|
} |
|
return err |
|
} |
|
} |
|
return nil |
|
}) |
|
if err = g.Wait(); err != nil { |
|
log.Error("telecom_errgroup.WithContext error(%v)", err) |
|
return |
|
} |
|
if orderState == nil { |
|
t = &telecom.OrderState{ |
|
OrderState: 1, |
|
} |
|
return |
|
} |
|
t = &telecom.OrderState{ |
|
OrderState: orderState.OrderState, |
|
FlowSize: orderState.FlowSize, |
|
} |
|
if tSucOrder != nil && tSucOrder.OrderID > 0 { |
|
t.FlowBalance = tSucOrder.FlowBalance |
|
t.FlowSize = tSucOrder.FlowPackageSize |
|
} |
|
if ok { |
|
t.IsRepeatorder = userOrder.IsRepeatorder |
|
if userOrder.IsRepeatorder == 0 { |
|
t.Endtime = userOrder.Endtime |
|
} |
|
} |
|
switch t.OrderState { |
|
case 6: |
|
if !ok { |
|
err = ecode.NothingFound |
|
msg = "订单不存在" |
|
return |
|
} |
|
t.Endtime = userOrder.Endtime |
|
} |
|
return |
|
} |
|
|
|
// telecomIp ip limit |
|
func (s *Service) iplimit(k, ip string) bool { |
|
key := fmt.Sprintf(_initIPlimitKey, k, ip) |
|
if _, ok := s.operationIPlimit[key]; ok { |
|
return true |
|
} |
|
return false |
|
} |
|
|
|
// DesDecrypt |
|
func (s *Service) DesDecrypt(src, key []byte) ([]byte, error) { |
|
block, err := des.NewCipher(key) |
|
if err != nil { |
|
return nil, err |
|
} |
|
out := make([]byte, len(src)) |
|
dst := out |
|
bs := block.BlockSize() |
|
if len(src)%bs != 0 { |
|
return nil, errors.New("crypto/cipher: input not full blocks") |
|
} |
|
for len(src) > 0 { |
|
block.Decrypt(dst, src[:bs]) |
|
src = src[bs:] |
|
dst = dst[bs:] |
|
} |
|
out = s.zeroUnPadding(out) |
|
return out, nil |
|
} |
|
|
|
// zeroUnPadding |
|
func (s *Service) zeroUnPadding(origData []byte) []byte { |
|
return bytes.TrimFunc(origData, |
|
func(r rune) bool { |
|
return r == rune(0) |
|
}) |
|
}
|
|
|