正在显示
9 个修改的文件
包含
372 行增加
和
1 行删除
| @@ -9,6 +9,6 @@ require ( | @@ -9,6 +9,6 @@ require ( | ||
| 9 | github.com/go-pg/pg/v10 v10.10.1 | 9 | github.com/go-pg/pg/v10 v10.10.1 |
| 10 | github.com/go-redis/redis v6.14.2+incompatible | 10 | github.com/go-redis/redis v6.14.2+incompatible |
| 11 | github.com/linmadan/egglib-go v0.0.0-20210527091316-06b0732fb5f6 | 11 | github.com/linmadan/egglib-go v0.0.0-20210527091316-06b0732fb5f6 |
| 12 | - github.com/sony/sonyflake v1.0.0 | 12 | + github.com/satori/go.uuid v1.2.0 // indirect |
| 13 | 13 | ||
| 14 | ) | 14 | ) |
pkg/application/web/auth/command/login.go
0 → 100644
| 1 | +package command | ||
| 2 | + | ||
| 3 | +import ( | ||
| 4 | + "fmt" | ||
| 5 | + | ||
| 6 | + "github.com/beego/beego/v2/core/validation" | ||
| 7 | +) | ||
| 8 | + | ||
| 9 | +type LoginCommand struct { | ||
| 10 | + Phone string `json:"phone" valid:"Required"` | ||
| 11 | + GrantType string `json:"grantType" valid:"Required"` //登录方式(signInPassword 密码登录、signInCaptcha 验证码登录) | ||
| 12 | + Password string `json:"password"` | ||
| 13 | + Captcha string `json:"captcha"` | ||
| 14 | +} | ||
| 15 | + | ||
| 16 | +func (orgAddCommand *LoginCommand) Valid(validation *validation.Validation) { | ||
| 17 | + | ||
| 18 | +} | ||
| 19 | + | ||
| 20 | +func (orgAddCommand *LoginCommand) ValidateCommand() error { | ||
| 21 | + valid := validation.Validation{} | ||
| 22 | + b, err := valid.Valid(orgAddCommand) | ||
| 23 | + if err != nil { | ||
| 24 | + return err | ||
| 25 | + } | ||
| 26 | + if !b { | ||
| 27 | + for _, validErr := range valid.Errors { | ||
| 28 | + return fmt.Errorf("%s %s", validErr.Key, validErr.Message) | ||
| 29 | + } | ||
| 30 | + } | ||
| 31 | + return nil | ||
| 32 | +} |
pkg/application/web/auth/dto/dto.go
0 → 100644
| 1 | +package dto | ||
| 2 | + | ||
| 3 | +type CompanyItem struct { | ||
| 4 | + CompanyId int `json:"companyId,string"` | ||
| 5 | + CompanyName string `json:"companyName"` | ||
| 6 | +} | ||
| 7 | + | ||
| 8 | +type OrgItem struct { | ||
| 9 | + OrganizationId int `json:"organizationId,string"` | ||
| 10 | + OrganizationName string `json:"organizationName"` | ||
| 11 | + CompanyId int `json:"companyId"` | ||
| 12 | +} |
| 1 | +package query | ||
| 2 | + | ||
| 3 | +import ( | ||
| 4 | + "fmt" | ||
| 5 | + | ||
| 6 | + "github.com/beego/beego/v2/core/validation" | ||
| 7 | + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/domain" | ||
| 8 | +) | ||
| 9 | + | ||
| 10 | +type GetCompanyOrgsByUserQuery struct { | ||
| 11 | + //操作人 | ||
| 12 | + Operator domain.Operator `json:"-"` | ||
| 13 | + Phone string `json:"phone" valid:"Required"` //手机号 | ||
| 14 | +} | ||
| 15 | + | ||
| 16 | +func (orgAddCommand *GetCompanyOrgsByUserQuery) Valid(validation *validation.Validation) { | ||
| 17 | + | ||
| 18 | +} | ||
| 19 | + | ||
| 20 | +func (orgAddCommand *GetCompanyOrgsByUserQuery) ValidateCommand() error { | ||
| 21 | + valid := validation.Validation{} | ||
| 22 | + b, err := valid.Valid(orgAddCommand) | ||
| 23 | + if err != nil { | ||
| 24 | + return err | ||
| 25 | + } | ||
| 26 | + if !b { | ||
| 27 | + for _, validErr := range valid.Errors { | ||
| 28 | + return fmt.Errorf("%s %s", validErr.Key, validErr.Message) | ||
| 29 | + } | ||
| 30 | + } | ||
| 31 | + return nil | ||
| 32 | +} |
pkg/application/web/auth/service/service.go
0 → 100644
| 1 | +package service | ||
| 2 | + | ||
| 3 | +import ( | ||
| 4 | + "errors" | ||
| 5 | + | ||
| 6 | + "github.com/linmadan/egglib-go/core/application" | ||
| 7 | + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/application/web/auth/command" | ||
| 8 | + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/application/web/auth/dto" | ||
| 9 | + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/application/web/auth/query" | ||
| 10 | + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/domain" | ||
| 11 | + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/infrastructure/cache" | ||
| 12 | + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/infrastructure/service_gateway/allied_creation_user" | ||
| 13 | + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/infrastructure/service_gateway/sms_serve" | ||
| 14 | +) | ||
| 15 | + | ||
| 16 | +type AuthService struct{} | ||
| 17 | + | ||
| 18 | +//AuthLogin 用户登录 | ||
| 19 | +func (srv AuthService) AuthLogin(loginCommand *command.LoginCommand) (interface{}, error) { | ||
| 20 | + var ( | ||
| 21 | + result interface{} | ||
| 22 | + err error | ||
| 23 | + ) | ||
| 24 | + switch loginCommand.GrantType { | ||
| 25 | + case "signInPassword": | ||
| 26 | + //账号密码登录 | ||
| 27 | + result, err = srv.SignInPassword(loginCommand.Phone, loginCommand.Password) | ||
| 28 | + case "signInCaptcha": | ||
| 29 | + //手机验证码登录 | ||
| 30 | + result, err = srv.SignInCaptcha(loginCommand.Phone, loginCommand.Captcha) | ||
| 31 | + default: | ||
| 32 | + err = errors.New("登录方式无法解析") | ||
| 33 | + } | ||
| 34 | + return result, err | ||
| 35 | +} | ||
| 36 | + | ||
| 37 | +//SignInPassword 使用账号密码校验 | ||
| 38 | +func (srv AuthService) SignInPassword(account string, password string) (interface{}, error) { | ||
| 39 | + creationUserGateway := allied_creation_user.NewHttplibAlliedCreationUser(domain.Operator{}) | ||
| 40 | + _, err := creationUserGateway.AuthCheckPassword(allied_creation_user.ReqAuthCheckPassword{ | ||
| 41 | + Password: password, | ||
| 42 | + Phone: account, | ||
| 43 | + }) | ||
| 44 | + if err != nil { | ||
| 45 | + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
| 46 | + } | ||
| 47 | + ltoken := domain.LoginToken{ | ||
| 48 | + UserId: 0, | ||
| 49 | + Account: account, | ||
| 50 | + Platform: domain.LoginPlatformApp, | ||
| 51 | + CompanyId: 0, | ||
| 52 | + } | ||
| 53 | + authcode, err := ltoken.GenerateAuthCode() | ||
| 54 | + if err != nil { | ||
| 55 | + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
| 56 | + } | ||
| 57 | + result := map[string]string{ | ||
| 58 | + "authCode": authcode, | ||
| 59 | + } | ||
| 60 | + return result, nil | ||
| 61 | +} | ||
| 62 | + | ||
| 63 | +//SignInCaptcha 使用手机验证码登录 | ||
| 64 | +func (srv AuthService) SignInCaptcha(phone string, captcha string) (interface{}, error) { | ||
| 65 | + smsServeGateway := sms_serve.NewHttplibHttplibSmsServe() | ||
| 66 | + err := smsServeGateway.CheckSmsCode(phone, captcha) | ||
| 67 | + if err != nil { | ||
| 68 | + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
| 69 | + } | ||
| 70 | + ltoken := domain.LoginToken{ | ||
| 71 | + UserId: 0, | ||
| 72 | + Account: phone, | ||
| 73 | + Platform: domain.LoginPlatformApp, | ||
| 74 | + CompanyId: 0, | ||
| 75 | + } | ||
| 76 | + authcode, err := ltoken.GenerateAuthCode() | ||
| 77 | + if err != nil { | ||
| 78 | + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
| 79 | + } | ||
| 80 | + result := map[string]string{ | ||
| 81 | + "authCode": authcode, | ||
| 82 | + } | ||
| 83 | + return result, nil | ||
| 84 | +} | ||
| 85 | + | ||
| 86 | +//GetCompanyOrgsByUser 获取登录用户的公司组织列表 | ||
| 87 | +func (srv AuthService) GetCompanyOrgsByUser(queryParam query.GetCompanyOrgsByUserQuery) (interface{}, error) { | ||
| 88 | + | ||
| 89 | + creationUserGateway := allied_creation_user.NewHttplibAlliedCreationUser(queryParam.Operator) | ||
| 90 | + result, err := creationUserGateway.UserSearch(allied_creation_user.ReqUserSearch{ | ||
| 91 | + Phone: queryParam.Phone, | ||
| 92 | + }) | ||
| 93 | + if err != nil { | ||
| 94 | + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
| 95 | + } | ||
| 96 | + var ( | ||
| 97 | + companys []dto.CompanyItem | ||
| 98 | + orgs []dto.OrgItem | ||
| 99 | + ) | ||
| 100 | + | ||
| 101 | + for _, v := range result.Users { | ||
| 102 | + companys = append(companys, dto.CompanyItem{ | ||
| 103 | + CompanyId: v.Company.CompanyId, | ||
| 104 | + CompanyName: v.Company.CompanyName, | ||
| 105 | + }) | ||
| 106 | + for _, vv := range v.UserOrg { | ||
| 107 | + orgs = append(orgs, dto.OrgItem{ | ||
| 108 | + OrganizationId: vv.OrgID, | ||
| 109 | + OrganizationName: vv.OrgName, | ||
| 110 | + CompanyId: v.Company.CompanyId, | ||
| 111 | + }) | ||
| 112 | + } | ||
| 113 | + } | ||
| 114 | + | ||
| 115 | + data := map[string]interface{}{ | ||
| 116 | + "companys": companys, | ||
| 117 | + "organizations": orgs, | ||
| 118 | + } | ||
| 119 | + return data, nil | ||
| 120 | +} | ||
| 121 | + | ||
| 122 | +//GetQrcode 获取扫码登录需要的二维码 | ||
| 123 | +func (srv AuthService) GetQrcode() (interface{}, error) { | ||
| 124 | + qrmsg := domain.QrcodeMessage{} | ||
| 125 | + imgBase64, err := qrmsg.GenerateImageBase64() | ||
| 126 | + if err != nil { | ||
| 127 | + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
| 128 | + } | ||
| 129 | + qrCache := cache.LoginQrcodeCache{} | ||
| 130 | + err = qrCache.Save(qrmsg) | ||
| 131 | + if err != nil { | ||
| 132 | + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
| 133 | + } | ||
| 134 | + data := map[string]interface{}{ | ||
| 135 | + "image": imgBase64, | ||
| 136 | + "token": qrmsg.Token, | ||
| 137 | + } | ||
| 138 | + return data, nil | ||
| 139 | +} | ||
| 140 | + | ||
| 141 | +//QrcodeLoginStatus 扫码登录状态 | ||
| 142 | +func (srv AuthService) QrcodeLoginStatus(queryParam query.QrcodeLoginStatusQuery) (interface{}, error) { | ||
| 143 | + qrmsg := domain.QrcodeMessage{} | ||
| 144 | + err := qrmsg.ParseToken(queryParam.Token) | ||
| 145 | + if err != nil { | ||
| 146 | + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
| 147 | + } | ||
| 148 | + qrCache := cache.LoginQrcodeCache{} | ||
| 149 | + qrmsgCache, err := qrCache.Get(qrmsg.Id) | ||
| 150 | + if err != nil { | ||
| 151 | + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
| 152 | + } | ||
| 153 | + data := map[string]interface{}{ | ||
| 154 | + "isLogin": qrmsgCache.IsLogin, | ||
| 155 | + } | ||
| 156 | + return data, nil | ||
| 157 | +} |
pkg/domain/qrcode.go
0 → 100644
| 1 | +package domain | ||
| 2 | + | ||
| 3 | +import ( | ||
| 4 | + "bytes" | ||
| 5 | + "encoding/base64" | ||
| 6 | + "fmt" | ||
| 7 | + "image/png" | ||
| 8 | + "time" | ||
| 9 | + | ||
| 10 | + "github.com/boombuler/barcode" | ||
| 11 | + "github.com/boombuler/barcode/qr" | ||
| 12 | + jwt "github.com/dgrijalva/jwt-go" | ||
| 13 | +) | ||
| 14 | + | ||
| 15 | +const ( | ||
| 16 | + qrcodeTokenSecret string = "bbe35ad433dd8e67" | ||
| 17 | + qrcodeCodeExpire int64 = 60 * 30 //15分钟过期 | ||
| 18 | +) | ||
| 19 | + | ||
| 20 | +type QrcodeMessage struct { | ||
| 21 | + jwt.StandardClaims | ||
| 22 | + Id string `json:"id"` | ||
| 23 | + Token string `json:"token"` | ||
| 24 | + IsLogin bool `json:"isLogin"` | ||
| 25 | + //用户id | ||
| 26 | + UserId int64 `json:"userId"` | ||
| 27 | + UserBaseId int64 `json:"userBaseId"` | ||
| 28 | + // 账号 | ||
| 29 | + Account string `json:"account"` | ||
| 30 | + // 公司id | ||
| 31 | + CompanyId int64 `json:"companyId"` | ||
| 32 | + // 组织id | ||
| 33 | + OrgId int64 `json:"orgId"` | ||
| 34 | +} | ||
| 35 | + | ||
| 36 | +func (qrmsg *QrcodeMessage) GenerateImageBase64() ([]byte, error) { | ||
| 37 | + nowTime := time.Now().Unix() | ||
| 38 | + qrmsg.StandardClaims = jwt.StandardClaims{ | ||
| 39 | + NotBefore: nowTime, | ||
| 40 | + IssuedAt: nowTime, | ||
| 41 | + ExpiresAt: nowTime + qrcodeCodeExpire, | ||
| 42 | + Issuer: "allied_creation_gateway", | ||
| 43 | + } | ||
| 44 | + qrmsg.Id = fmt.Sprintf("%d", time.Now().UnixNano()) | ||
| 45 | + token := jwt.NewWithClaims(jwt.SigningMethodHS256, *qrmsg) | ||
| 46 | + str, err := token.SignedString([]byte(qrcodeTokenSecret)) | ||
| 47 | + if err != nil { | ||
| 48 | + return nil, err | ||
| 49 | + } | ||
| 50 | + //初始化数据 | ||
| 51 | + qrmsg.Token = str | ||
| 52 | + qrmsg.IsLogin = false | ||
| 53 | + | ||
| 54 | + qrCode, err := qr.Encode(str, qr.M, qr.Auto) | ||
| 55 | + if err != nil { | ||
| 56 | + return nil, err | ||
| 57 | + } | ||
| 58 | + qrCode, err = barcode.Scale(qrCode, 200, 200) | ||
| 59 | + if err != nil { | ||
| 60 | + return nil, err | ||
| 61 | + } | ||
| 62 | + var buf bytes.Buffer | ||
| 63 | + err = png.Encode(&buf, qrCode) | ||
| 64 | + if err != nil { | ||
| 65 | + return nil, err | ||
| 66 | + } | ||
| 67 | + var result []byte | ||
| 68 | + base64.StdEncoding.Encode(result, buf.Bytes()) | ||
| 69 | + return result, err | ||
| 70 | +} | ||
| 71 | + | ||
| 72 | +func (qrmsg *QrcodeMessage) ParseToken(str string) error { | ||
| 73 | + tokenClaims, err := jwt.ParseWithClaims( | ||
| 74 | + str, | ||
| 75 | + qrmsg, | ||
| 76 | + func(token *jwt.Token) (interface{}, error) { | ||
| 77 | + return []byte(loginTokenSecret), nil | ||
| 78 | + }) | ||
| 79 | + if err != nil { | ||
| 80 | + return err | ||
| 81 | + } | ||
| 82 | + if claim, ok := tokenClaims.Claims.(*QrcodeMessage); ok && tokenClaims.Valid { | ||
| 83 | + *qrmsg = *claim | ||
| 84 | + } | ||
| 85 | + return nil | ||
| 86 | +} |
| 1 | package cache | 1 | package cache |
| 2 | 2 | ||
| 3 | +import ( | ||
| 4 | + "encoding/json" | ||
| 5 | + "time" | ||
| 6 | + | ||
| 7 | + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/domain" | ||
| 8 | +) | ||
| 9 | + | ||
| 3 | //二维码信息缓存 | 10 | //二维码信息缓存 |
| 4 | type LoginQrcodeCache struct { | 11 | type LoginQrcodeCache struct { |
| 5 | } | 12 | } |
| 13 | + | ||
| 14 | +func (lq LoginQrcodeCache) keyString(str string) string { | ||
| 15 | + str1 := KEY_PREFIX + "login:qrcode:" + str | ||
| 16 | + return str1 | ||
| 17 | +} | ||
| 18 | + | ||
| 19 | +func (lq LoginQrcodeCache) Save(qrcode domain.QrcodeMessage) error { | ||
| 20 | + nowTime := time.Now().Unix() | ||
| 21 | + exp := qrcode.ExpiresAt - nowTime | ||
| 22 | + if exp <= 0 { | ||
| 23 | + exp = 60 * 60 * 2 | ||
| 24 | + } | ||
| 25 | + key := lq.keyString(qrcode.Id) | ||
| 26 | + bt, _ := json.Marshal(qrcode) | ||
| 27 | + result := clientRedis.Set(key, string(bt), time.Duration(exp)) | ||
| 28 | + return result.Err() | ||
| 29 | +} | ||
| 30 | + | ||
| 31 | +func (lq LoginQrcodeCache) Remove(id string) error { | ||
| 32 | + keyStr := lq.keyString(id) | ||
| 33 | + result := clientRedis.Del(keyStr) | ||
| 34 | + return result.Err() | ||
| 35 | +} | ||
| 36 | + | ||
| 37 | +func (lq LoginQrcodeCache) Get(id string) (*domain.QrcodeMessage, error) { | ||
| 38 | + keyStr := lq.keyString(id) | ||
| 39 | + result := clientRedis.Get(keyStr) | ||
| 40 | + re, _ := result.Result() | ||
| 41 | + var data domain.QrcodeMessage | ||
| 42 | + err := json.Unmarshal([]byte(re), &data) | ||
| 43 | + if err != nil { | ||
| 44 | + return nil, err | ||
| 45 | + } | ||
| 46 | + return &data, err | ||
| 47 | +} |
| @@ -3,6 +3,11 @@ package allied_creation_cooperation | @@ -3,6 +3,11 @@ package allied_creation_cooperation | ||
| 3 | //确定预算分红激励 | 3 | //确定预算分红激励 |
| 4 | type ( | 4 | type ( |
| 5 | ReqDividendsEstimateIncentive struct { | 5 | ReqDividendsEstimateIncentive struct { |
| 6 | + // companyId | ||
| 7 | + // orgId | ||
| 8 | + // userId | ||
| 9 | + CooperationContractNumber string //合约编号 | ||
| 10 | + OrderOrReturnedOrderNum string //分红订单号/退货单号 | ||
| 6 | } | 11 | } |
| 7 | 12 | ||
| 8 | DataDividendsEstimateIncentive struct { | 13 | DataDividendsEstimateIncentive struct { |
-
请 注册 或 登录 后发表评论