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) }) }