作者 tangxuhui

添加 web 端登录 和获取登录用二维码

... ... @@ -9,6 +9,6 @@ require (
github.com/go-pg/pg/v10 v10.10.1
github.com/go-redis/redis v6.14.2+incompatible
github.com/linmadan/egglib-go v0.0.0-20210527091316-06b0732fb5f6
github.com/sony/sonyflake v1.0.0
github.com/satori/go.uuid v1.2.0 // indirect
)
... ...
package command
import (
"fmt"
"github.com/beego/beego/v2/core/validation"
)
type LoginCommand struct {
Phone string `json:"phone" valid:"Required"`
GrantType string `json:"grantType" valid:"Required"` //登录方式(signInPassword 密码登录、signInCaptcha 验证码登录)
Password string `json:"password"`
Captcha string `json:"captcha"`
}
func (orgAddCommand *LoginCommand) Valid(validation *validation.Validation) {
}
func (orgAddCommand *LoginCommand) ValidateCommand() error {
valid := validation.Validation{}
b, err := valid.Valid(orgAddCommand)
if err != nil {
return err
}
if !b {
for _, validErr := range valid.Errors {
return fmt.Errorf("%s %s", validErr.Key, validErr.Message)
}
}
return nil
}
... ...
package dto
type CompanyItem struct {
CompanyId int `json:"companyId,string"`
CompanyName string `json:"companyName"`
}
type OrgItem struct {
OrganizationId int `json:"organizationId,string"`
OrganizationName string `json:"organizationName"`
CompanyId int `json:"companyId"`
}
... ...
package query
import (
"fmt"
"github.com/beego/beego/v2/core/validation"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/domain"
)
type GetCompanyOrgsByUserQuery struct {
//操作人
Operator domain.Operator `json:"-"`
Phone string `json:"phone" valid:"Required"` //手机号
}
func (orgAddCommand *GetCompanyOrgsByUserQuery) Valid(validation *validation.Validation) {
}
func (orgAddCommand *GetCompanyOrgsByUserQuery) ValidateCommand() error {
valid := validation.Validation{}
b, err := valid.Valid(orgAddCommand)
if err != nil {
return err
}
if !b {
for _, validErr := range valid.Errors {
return fmt.Errorf("%s %s", validErr.Key, validErr.Message)
}
}
return nil
}
... ...
package query
type QrcodeLoginStatusQuery struct {
Token string `json:"token"`
}
... ...
package service
import (
"errors"
"github.com/linmadan/egglib-go/core/application"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/application/web/auth/command"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/application/web/auth/dto"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/application/web/auth/query"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/infrastructure/cache"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/infrastructure/service_gateway/allied_creation_user"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/infrastructure/service_gateway/sms_serve"
)
type AuthService struct{}
//AuthLogin 用户登录
func (srv AuthService) AuthLogin(loginCommand *command.LoginCommand) (interface{}, error) {
var (
result interface{}
err error
)
switch loginCommand.GrantType {
case "signInPassword":
//账号密码登录
result, err = srv.SignInPassword(loginCommand.Phone, loginCommand.Password)
case "signInCaptcha":
//手机验证码登录
result, err = srv.SignInCaptcha(loginCommand.Phone, loginCommand.Captcha)
default:
err = errors.New("登录方式无法解析")
}
return result, err
}
//SignInPassword 使用账号密码校验
func (srv AuthService) SignInPassword(account string, password string) (interface{}, error) {
creationUserGateway := allied_creation_user.NewHttplibAlliedCreationUser(domain.Operator{})
_, err := creationUserGateway.AuthCheckPassword(allied_creation_user.ReqAuthCheckPassword{
Password: password,
Phone: account,
})
if err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
ltoken := domain.LoginToken{
UserId: 0,
Account: account,
Platform: domain.LoginPlatformApp,
CompanyId: 0,
}
authcode, err := ltoken.GenerateAuthCode()
if err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
result := map[string]string{
"authCode": authcode,
}
return result, nil
}
//SignInCaptcha 使用手机验证码登录
func (srv AuthService) SignInCaptcha(phone string, captcha string) (interface{}, error) {
smsServeGateway := sms_serve.NewHttplibHttplibSmsServe()
err := smsServeGateway.CheckSmsCode(phone, captcha)
if err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
ltoken := domain.LoginToken{
UserId: 0,
Account: phone,
Platform: domain.LoginPlatformApp,
CompanyId: 0,
}
authcode, err := ltoken.GenerateAuthCode()
if err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
result := map[string]string{
"authCode": authcode,
}
return result, nil
}
//GetCompanyOrgsByUser 获取登录用户的公司组织列表
func (srv AuthService) GetCompanyOrgsByUser(queryParam query.GetCompanyOrgsByUserQuery) (interface{}, error) {
creationUserGateway := allied_creation_user.NewHttplibAlliedCreationUser(queryParam.Operator)
result, err := creationUserGateway.UserSearch(allied_creation_user.ReqUserSearch{
Phone: queryParam.Phone,
})
if err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
var (
companys []dto.CompanyItem
orgs []dto.OrgItem
)
for _, v := range result.Users {
companys = append(companys, dto.CompanyItem{
CompanyId: v.Company.CompanyId,
CompanyName: v.Company.CompanyName,
})
for _, vv := range v.UserOrg {
orgs = append(orgs, dto.OrgItem{
OrganizationId: vv.OrgID,
OrganizationName: vv.OrgName,
CompanyId: v.Company.CompanyId,
})
}
}
data := map[string]interface{}{
"companys": companys,
"organizations": orgs,
}
return data, nil
}
//GetQrcode 获取扫码登录需要的二维码
func (srv AuthService) GetQrcode() (interface{}, error) {
qrmsg := domain.QrcodeMessage{}
imgBase64, err := qrmsg.GenerateImageBase64()
if err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
qrCache := cache.LoginQrcodeCache{}
err = qrCache.Save(qrmsg)
if err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
data := map[string]interface{}{
"image": imgBase64,
"token": qrmsg.Token,
}
return data, nil
}
//QrcodeLoginStatus 扫码登录状态
func (srv AuthService) QrcodeLoginStatus(queryParam query.QrcodeLoginStatusQuery) (interface{}, error) {
qrmsg := domain.QrcodeMessage{}
err := qrmsg.ParseToken(queryParam.Token)
if err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
qrCache := cache.LoginQrcodeCache{}
qrmsgCache, err := qrCache.Get(qrmsg.Id)
if err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
data := map[string]interface{}{
"isLogin": qrmsgCache.IsLogin,
}
return data, nil
}
... ...
package domain
import (
"bytes"
"encoding/base64"
"fmt"
"image/png"
"time"
"github.com/boombuler/barcode"
"github.com/boombuler/barcode/qr"
jwt "github.com/dgrijalva/jwt-go"
)
const (
qrcodeTokenSecret string = "bbe35ad433dd8e67"
qrcodeCodeExpire int64 = 60 * 30 //15分钟过期
)
type QrcodeMessage struct {
jwt.StandardClaims
Id string `json:"id"`
Token string `json:"token"`
IsLogin bool `json:"isLogin"`
//用户id
UserId int64 `json:"userId"`
UserBaseId int64 `json:"userBaseId"`
// 账号
Account string `json:"account"`
// 公司id
CompanyId int64 `json:"companyId"`
// 组织id
OrgId int64 `json:"orgId"`
}
func (qrmsg *QrcodeMessage) GenerateImageBase64() ([]byte, error) {
nowTime := time.Now().Unix()
qrmsg.StandardClaims = jwt.StandardClaims{
NotBefore: nowTime,
IssuedAt: nowTime,
ExpiresAt: nowTime + qrcodeCodeExpire,
Issuer: "allied_creation_gateway",
}
qrmsg.Id = fmt.Sprintf("%d", time.Now().UnixNano())
token := jwt.NewWithClaims(jwt.SigningMethodHS256, *qrmsg)
str, err := token.SignedString([]byte(qrcodeTokenSecret))
if err != nil {
return nil, err
}
//初始化数据
qrmsg.Token = str
qrmsg.IsLogin = false
qrCode, err := qr.Encode(str, qr.M, qr.Auto)
if err != nil {
return nil, err
}
qrCode, err = barcode.Scale(qrCode, 200, 200)
if err != nil {
return nil, err
}
var buf bytes.Buffer
err = png.Encode(&buf, qrCode)
if err != nil {
return nil, err
}
var result []byte
base64.StdEncoding.Encode(result, buf.Bytes())
return result, err
}
func (qrmsg *QrcodeMessage) ParseToken(str string) error {
tokenClaims, err := jwt.ParseWithClaims(
str,
qrmsg,
func(token *jwt.Token) (interface{}, error) {
return []byte(loginTokenSecret), nil
})
if err != nil {
return err
}
if claim, ok := tokenClaims.Claims.(*QrcodeMessage); ok && tokenClaims.Valid {
*qrmsg = *claim
}
return nil
}
... ...
package cache
import (
"encoding/json"
"time"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/domain"
)
//二维码信息缓存
type LoginQrcodeCache struct {
}
func (lq LoginQrcodeCache) keyString(str string) string {
str1 := KEY_PREFIX + "login:qrcode:" + str
return str1
}
func (lq LoginQrcodeCache) Save(qrcode domain.QrcodeMessage) error {
nowTime := time.Now().Unix()
exp := qrcode.ExpiresAt - nowTime
if exp <= 0 {
exp = 60 * 60 * 2
}
key := lq.keyString(qrcode.Id)
bt, _ := json.Marshal(qrcode)
result := clientRedis.Set(key, string(bt), time.Duration(exp))
return result.Err()
}
func (lq LoginQrcodeCache) Remove(id string) error {
keyStr := lq.keyString(id)
result := clientRedis.Del(keyStr)
return result.Err()
}
func (lq LoginQrcodeCache) Get(id string) (*domain.QrcodeMessage, error) {
keyStr := lq.keyString(id)
result := clientRedis.Get(keyStr)
re, _ := result.Result()
var data domain.QrcodeMessage
err := json.Unmarshal([]byte(re), &data)
if err != nil {
return nil, err
}
return &data, err
}
... ...
... ... @@ -3,6 +3,11 @@ package allied_creation_cooperation
//确定预算分红激励
type (
ReqDividendsEstimateIncentive struct {
// companyId
// orgId
// userId
CooperationContractNumber string //合约编号
OrderOrReturnedOrderNum string //分红订单号/退货单号
}
DataDividendsEstimateIncentive struct {
... ...