first push
This commit is contained in:
parent
28e50fa51c
commit
ebf4a8dcc5
25
.gitignore
vendored
Normal file
25
.gitignore
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# Binaries for programs and plugins
|
||||||
|
*.exe
|
||||||
|
*.exe~
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Test binary, built with `go test -c`
|
||||||
|
*.test
|
||||||
|
|
||||||
|
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||||
|
*.out
|
||||||
|
|
||||||
|
# Dependency directories (remove the comment below to include it)
|
||||||
|
# vendor/
|
||||||
|
logs.log
|
||||||
|
.idea
|
||||||
|
/docs/utils/
|
||||||
|
/cmd/logs/*
|
||||||
|
/cmd/cache/*
|
||||||
|
/cmd/log/*
|
||||||
|
/conf/conf.ini
|
||||||
|
/conf/dubbogo.yaml
|
||||||
|
/conf/sdk.yaml
|
||||||
|
/conf/log.yaml
|
9852
api/account/account.pb.go
Normal file
9852
api/account/account.pb.go
Normal file
File diff suppressed because it is too large
Load Diff
778
api/account/account.proto
Normal file
778
api/account/account.proto
Normal file
@ -0,0 +1,778 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
syntax = "proto3";
|
||||||
|
package account;
|
||||||
|
import "github.com/mwitkow/go-proto-validators@v0.3.2/validator.proto";
|
||||||
|
|
||||||
|
option go_package = "./;account";
|
||||||
|
|
||||||
|
service Account {
|
||||||
|
rpc Login (LoginRequest) returns (TokenInfo) {}
|
||||||
|
rpc RefreshToken (RefreshTokenRequest) returns (TokenInfo) {} //刷新token
|
||||||
|
rpc Logout (DecryptJwtRequest) returns (CommonResponse) {}
|
||||||
|
rpc OffLine (CommonRequest) returns (CommonResponse) {}
|
||||||
|
rpc OnlineLog (LoginInfosByUserIdRequest) returns (LoginLogsResponse) {}//根据用户id获取登录的信息
|
||||||
|
rpc OnlineLogById (OnlineLogByIdRequest) returns (LoginLog) {}//根据用户id获取登录的信息
|
||||||
|
rpc CheckPwd (CheckPwdRequest) returns (UpdateResponse) {}//检测密码是否正确
|
||||||
|
// rpc RegisterOrExist (RegistRequest) returns (RequestStatus) {}
|
||||||
|
rpc SendMsg (SendMsgRequest) returns (SendMsgStatusResponse) {} //登陆发送验证码
|
||||||
|
rpc SendCustomMsg (SendCustomMsgRequest) returns (SendMsgStatusResponse) {}//定制化发送内容
|
||||||
|
rpc SendExCustomMsg (SendCustomMsgRequest) returns (SendMsgStatusResponse) {}//定制化发送内容
|
||||||
|
rpc SendMsgRegister (SendMsgRequest) returns (SendMsgStatusResponse) {}//注册发送
|
||||||
|
rpc CheckMsg (CheckMsgRequest) returns (SendMsgStatusResponse) {}
|
||||||
|
rpc SendNewTelNumMsg (SendNewTelNumMsgRequest) returns (SendMsgStatusResponse) {}//发送新账号验证码,不携带新号码
|
||||||
|
rpc UpdateTelNum (SendNewTelNumMsgRequest) returns (SendMsgStatusResponse) {}//更新新手机号,校验新号码验证码
|
||||||
|
rpc Authentication (AuthenticationRequest) returns (RequestStatus) {}
|
||||||
|
rpc DecryptJwt (DecryptJwtRequest) returns (DecryptJwtResponse) {}//最好放在调用方
|
||||||
|
rpc Info (InfoRequest) returns (UserInfoResponse) {}
|
||||||
|
rpc JobNumGetInfo (JobNumGetInfoRequest) returns (InfoResponse) {}
|
||||||
|
rpc List (ListRequest) returns (ListResponse) {}
|
||||||
|
rpc RandList (ListRequest) returns (ListResponse) {}
|
||||||
|
rpc ListByIDs (ListByIDsRequest) returns (ListResponse) {}
|
||||||
|
rpc Remove (RemoveRequest) returns (RemoveResponse) {}
|
||||||
|
rpc Update (UpdateRequest) returns (UpdateResponse) {}
|
||||||
|
rpc UsersByTel (UsersByTelRequest) returns (ListResponse) {}
|
||||||
|
rpc UserByTel (UserByTelRequest) returns (InfoResponse) {}
|
||||||
|
rpc OnlySendMsg (SendMsgRequest) returns (SendMsgStatusResponse) {} //仅发验证码
|
||||||
|
rpc OnlyCheckMsg (CheckMsgRequest) returns (SendMsgStatusResponse) {}//仅校验之前发送的验证码
|
||||||
|
rpc MailAccountByNickName(MailAccountByNickNameRequest) returns(MaiAccountResponse){} //根据昵称姓名获取昵称的邮箱和拼音名称
|
||||||
|
rpc ListV2 (ListV2Request) returns (ListResponse) {}// 新版列表 查询
|
||||||
|
rpc QueryPersonnelWithTheSameName (QueryPersonnelWithTheSameNameRequest) returns (QueryPersonnelWithTheSameNameResponse) {}// 查询同名的员工
|
||||||
|
rpc UsersByJobNum (UsersByJobNumRequest) returns (ListResponse) {}
|
||||||
|
rpc RealName (RealNameRequest) returns (RealNameResponse) {}//实名认证
|
||||||
|
rpc Register (RegistRequest) returns (RegisterResponse) {}//注册
|
||||||
|
rpc UserList (UserListRequest) returns (UserListResponse) {}//用户列表
|
||||||
|
rpc CheckRealName (CheckRealNameRequest) returns (CheckRealNameResponse) {}//审核实名
|
||||||
|
}
|
||||||
|
message CheckRealNameResponse{
|
||||||
|
uint64 id =1;
|
||||||
|
string status =2;
|
||||||
|
}
|
||||||
|
message CheckRealNameRequest{
|
||||||
|
uint64 id = 1;
|
||||||
|
bool pass = 2;
|
||||||
|
string notPassRemarks = 3;
|
||||||
|
}
|
||||||
|
message UserListResponse{
|
||||||
|
uint64 count = 1;
|
||||||
|
uint64 page = 2;
|
||||||
|
uint64 pageSize = 3;
|
||||||
|
repeated UserListInfo userList = 4;
|
||||||
|
}
|
||||||
|
message UserListInfo{
|
||||||
|
uint64 id = 1;
|
||||||
|
int32 status = 2;
|
||||||
|
string name = 3;
|
||||||
|
int32 sex = 4;
|
||||||
|
string nationality = 5;
|
||||||
|
int32 documentType =6;
|
||||||
|
string certificatePicture = 7;
|
||||||
|
string validity = 8;
|
||||||
|
string placeOfResidence = 9;
|
||||||
|
string groupPhoto = 10;
|
||||||
|
string attachment = 11;
|
||||||
|
string registrationTime = 12;
|
||||||
|
string auditTime = 13;
|
||||||
|
string subNum = 14;
|
||||||
|
string notPassRemarks = 15;
|
||||||
|
string telNum = 16;
|
||||||
|
}
|
||||||
|
message UserListRequest{
|
||||||
|
string domain = 1;
|
||||||
|
string subNum = 2;
|
||||||
|
int32 realNameOrNot = 3;
|
||||||
|
string name = 4;
|
||||||
|
int32 sex = 5;
|
||||||
|
int32 documentType = 6;
|
||||||
|
int32 auditStatus = 7;
|
||||||
|
uint64 page = 8;
|
||||||
|
uint64 pageSize = 9;
|
||||||
|
}
|
||||||
|
message UserInfoResponse{
|
||||||
|
uint64 id = 1;
|
||||||
|
int32 status = 2;
|
||||||
|
string name = 3;
|
||||||
|
int32 sex = 4;
|
||||||
|
string nationality = 5;
|
||||||
|
int32 documentType =6;
|
||||||
|
string certificatePicture = 7;
|
||||||
|
string validity = 8;
|
||||||
|
string placeOfResidence = 9;
|
||||||
|
string groupPhoto = 10;
|
||||||
|
string attachment = 11;
|
||||||
|
string subNum = 12;
|
||||||
|
string notPassRemarks = 13;
|
||||||
|
}
|
||||||
|
message RealNameResponse{
|
||||||
|
uint64 id = 1;
|
||||||
|
string status = 2;
|
||||||
|
}
|
||||||
|
message RealNameRequest{
|
||||||
|
uint64 id = 1;
|
||||||
|
string name = 2;
|
||||||
|
int32 sex = 3;
|
||||||
|
string nationality = 4;
|
||||||
|
int32 documentType = 5;
|
||||||
|
string certificatePicture = 6;
|
||||||
|
string validity = 7;
|
||||||
|
string placeOfResidence = 8;
|
||||||
|
string groupPhoto = 9;
|
||||||
|
string attachment = 10;
|
||||||
|
}
|
||||||
|
message RegisterResponse{
|
||||||
|
uint64 ID = 1;
|
||||||
|
uint64 status = 2;
|
||||||
|
string token = 3;
|
||||||
|
}
|
||||||
|
message UsersByJobNumRequest{
|
||||||
|
string domain = 1 ;
|
||||||
|
repeated string jobNum =2 ;
|
||||||
|
}
|
||||||
|
message QueryPersonnelWithTheSameNameRequest{
|
||||||
|
repeated string names = 1 ;
|
||||||
|
string domain = 2 ;
|
||||||
|
string status = 3 ;
|
||||||
|
}
|
||||||
|
message QueryPersonnelWithTheSameNameResponse{
|
||||||
|
repeated string names = 1 ;
|
||||||
|
uint64 count = 2 ;
|
||||||
|
}
|
||||||
|
message ListV2Request {
|
||||||
|
string domain = 1 [json_name = "domain",(validator.field) = {string_not_empty: true,human_error: "70001"} ];
|
||||||
|
uint64 pageSize = 2 ;
|
||||||
|
uint64 page = 3 ;
|
||||||
|
string key = 4 ;
|
||||||
|
string nickName = 5;
|
||||||
|
string telNum = 6 ;
|
||||||
|
string status = 7 ;
|
||||||
|
string positionName = 8 ;
|
||||||
|
string jobNum = 9 ;
|
||||||
|
string mailAccount = 10 ;
|
||||||
|
string startEnterDate = 11 ;
|
||||||
|
string endEnterDate = 12 ;
|
||||||
|
uint32 positionId = 13 ;
|
||||||
|
uint32 departmentId = 14 ;
|
||||||
|
string departmentName =15 ;
|
||||||
|
repeated string departmentNames =16 ;
|
||||||
|
repeated uint32 positionIds =17 ;
|
||||||
|
repeated uint32 departmentIds =18 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SendClockInWechatRequest {
|
||||||
|
string domain = 1;
|
||||||
|
string telNum =2;
|
||||||
|
string operatedAt =3;
|
||||||
|
string clockType =4;
|
||||||
|
uint32 userId =5;
|
||||||
|
string ghId =6;
|
||||||
|
string address =7;
|
||||||
|
uint64 logId = 8;
|
||||||
|
}
|
||||||
|
message MailAccountByNickNameRequest {
|
||||||
|
string Domain = 1 [json_name = "domain",(validator.field) = {string_not_empty: true,human_error: "70001"}];
|
||||||
|
string NickName = 2 [json_name = "nickName",(validator.field) = {length_lt: 20,string_not_empty: true,human_error: "70005"}];
|
||||||
|
uint32 ID = 3 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CreateMaiAccountRequest {
|
||||||
|
uint32 ID = 1 ;
|
||||||
|
string nickName = 2;
|
||||||
|
string domain = 3 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MaiAccountResponse {
|
||||||
|
string englishName = 1 ;
|
||||||
|
string mailAccount = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message FddCreateUserRequest {
|
||||||
|
string openid = 1 ;
|
||||||
|
uint32 wxUserId = 2;
|
||||||
|
//string UserId = 3;
|
||||||
|
string customerId = 4;
|
||||||
|
bool isVerify = 5;
|
||||||
|
string transactionNo = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message WxBoxUserInfoRequest {
|
||||||
|
string openid = 2 ;
|
||||||
|
string ghId = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message WxGetOpenIdByCodeRequest {
|
||||||
|
string code = 1 ;
|
||||||
|
string state = 2 ;
|
||||||
|
string ghId = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message WxGetOpenIdByCodeResponse {
|
||||||
|
string openId = 1 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
message WxBoxTelNumByCodeResponse {
|
||||||
|
string telNum = 1 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
message WxBoxUserInfo {
|
||||||
|
string openId = 1 ;
|
||||||
|
string ghId = 2 ;
|
||||||
|
bool isNew = 3 ;
|
||||||
|
UserInfo user = 4 ;
|
||||||
|
uint32 wxUserId = 5 ;
|
||||||
|
FddInfo fdd = 6 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
message FddInfo {
|
||||||
|
uint64 ID = 1 ;
|
||||||
|
string customerId = 2 ;
|
||||||
|
bool isVerify = 3 ;
|
||||||
|
string transactionNo = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UserInfo {
|
||||||
|
uint64 ID = 1 ;
|
||||||
|
string nickName = 3 ;
|
||||||
|
string telNum = 5 ;
|
||||||
|
string avatar = 7 ;
|
||||||
|
string createAt = 8 ;
|
||||||
|
uint64 realNameID = 9 ;
|
||||||
|
string realName = 10;
|
||||||
|
string iDNum = 11;
|
||||||
|
string domain = 12;
|
||||||
|
string realIDImgA = 17;
|
||||||
|
string realIDImgB = 18;
|
||||||
|
string realNameIDName = 19;
|
||||||
|
string video = 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CommonRequest {
|
||||||
|
uint64 ID = 1 [json_name = "ID"];
|
||||||
|
}
|
||||||
|
|
||||||
|
message WxAppRequest {
|
||||||
|
string GhId = 1 [json_name = "ID"];
|
||||||
|
}
|
||||||
|
|
||||||
|
message WxAppResponse {
|
||||||
|
string AppID = 1 [json_name = "appID"];
|
||||||
|
string AppSecret = 2 [json_name = "appSecret"];
|
||||||
|
}
|
||||||
|
|
||||||
|
message WxUserUpdateRequest {
|
||||||
|
uint32 wxID = 1 [json_name = "wxId" ,(validator.field) = {string_not_empty: true,human_error: "缺少参数wxID"} ];
|
||||||
|
uint32 userID = 2 [json_name = "userID"];
|
||||||
|
}
|
||||||
|
|
||||||
|
message WxUserOrCreateRequest {
|
||||||
|
string OpenID = 1 [json_name = "openID" ,(validator.field) = {string_not_empty: true,human_error: "缺少openid"} ];
|
||||||
|
string GhID = 2 [json_name = "ghID" ,(validator.field) = {string_not_empty: true,human_error: "缺少参数ghid"} ];
|
||||||
|
}
|
||||||
|
|
||||||
|
message WxUserResponse {
|
||||||
|
string OpenID = 1 [json_name = "openID"];
|
||||||
|
uint32 UserID = 2 [json_name = "userID"];
|
||||||
|
string GhID = 3 [json_name = "ghID"];
|
||||||
|
string RoleAuth = 4 [json_name = "roleAuth"];
|
||||||
|
uint32 ID = 5 [json_name = "ID"];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
message LoginLogsResponse {
|
||||||
|
repeated LoginLog Data = 1 [json_name = "data"];
|
||||||
|
}
|
||||||
|
|
||||||
|
message LoginLog {
|
||||||
|
string Domain = 1 [json_name = "domain"];
|
||||||
|
uint64 ID = 2 [json_name = "ID"];
|
||||||
|
uint64 UserId = 3 [json_name = "userId"];
|
||||||
|
string Ip = 4 [json_name = "ip"];
|
||||||
|
string Token = 5 [json_name = "token"];
|
||||||
|
uint64 Status = 6 [json_name = "status"];
|
||||||
|
string ExpireDate = 7 [json_name = "expireDate"];
|
||||||
|
string LastDate = 8 [json_name = "lastDate"];
|
||||||
|
string LogoutDate = 9 [json_name = "logoutDate"];
|
||||||
|
string CreatedAt = 10 [json_name = "createdAt"];
|
||||||
|
string Address = 11 [json_name = "address"];
|
||||||
|
}
|
||||||
|
|
||||||
|
message OnlineLogByIdRequest {
|
||||||
|
string Domain = 1 [json_name = "domain"];
|
||||||
|
uint64 ID = 2 [json_name = "ID"];
|
||||||
|
}
|
||||||
|
|
||||||
|
message LoginInfosByUserIdRequest {
|
||||||
|
string Domain = 1 [json_name = "domain"];
|
||||||
|
uint64 UserId = 2 [json_name = "userId"];
|
||||||
|
}
|
||||||
|
|
||||||
|
message SendNewTelNumMsgRequest {
|
||||||
|
string Domain = 1 [json_name = "domain",(validator.field) = {string_not_empty: true,human_error: "70001"} ];
|
||||||
|
uint64 ID = 2 [json_name = "ID",(validator.field) = {string_not_empty: true,human_error: "缺少参数"} ];
|
||||||
|
string NewTelNum = 3 [json_name = "newTelNum"];
|
||||||
|
string Code = 4 [json_name = "code"];
|
||||||
|
string Project = 5 [json_name = "project"];
|
||||||
|
uint32 signNo = 6 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UserByTelRequest {
|
||||||
|
string Domain = 1 [json_name = "domain",(validator.field) = {string_not_empty: true,human_error: "70001"} ];
|
||||||
|
string Tel =2 [json_name = "tel"];
|
||||||
|
}
|
||||||
|
|
||||||
|
message CommonResponse {
|
||||||
|
}
|
||||||
|
|
||||||
|
message UsersByTelRequest {
|
||||||
|
string Domain = 1 [json_name = "domain",(validator.field) = {string_not_empty: true,human_error: "70001"} ];
|
||||||
|
repeated string Tels =2 [json_name = "tels"];
|
||||||
|
}
|
||||||
|
|
||||||
|
message ListByIDsRequest {
|
||||||
|
string Domain = 1 [json_name = "domain",(validator.field) = {string_not_empty: true,human_error: "70001"} ];
|
||||||
|
repeated uint64 IDs = 2 [json_name = "IDs"];
|
||||||
|
uint64 OrderType = 3 [json_name = "OrderType"];
|
||||||
|
uint64 Page = 4 [json_name = "page"];
|
||||||
|
uint64 PageSize = 5 [json_name = "pageSize"];
|
||||||
|
string NickName = 6 [json_name = "nickName"];
|
||||||
|
repeated string InvitationCode = 7 [json_name = "invitationCode"];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
message SendMsgRequest {
|
||||||
|
string Domain = 1 [json_name = "domain",(validator.field) = {string_not_empty: true,human_error: "70001"} ];
|
||||||
|
string TelNum = 2 [json_name = "telNum",(validator.field) = {regex: "^1\\d{10}$",human_error: "70002"}];
|
||||||
|
string Project = 3 [json_name = "project"];
|
||||||
|
uint32 signNo = 4;
|
||||||
|
uint32 mId = 5;
|
||||||
|
string scope = 6;//标记模块
|
||||||
|
}
|
||||||
|
|
||||||
|
message SendCustomMsgRequest {
|
||||||
|
string Domain = 1 [json_name = "domain",(validator.field) = {string_not_empty: true,human_error: "70001"} ];
|
||||||
|
string TelNum = 2 [json_name = "telNum",(validator.field) = {regex: "^1\\d{10}$",human_error: "70002"}];
|
||||||
|
string Project = 3 [json_name = "project"];
|
||||||
|
string Url = 4 [json_name = "Url"];
|
||||||
|
uint64 ID = 5 [json_name = "ID"];
|
||||||
|
uint64 MId = 6 [json_name = "mId"];
|
||||||
|
uint64 Location = 7 [json_name = "location"];
|
||||||
|
uint32 SigNo = 8 [json_name = "sigNo"];
|
||||||
|
}
|
||||||
|
|
||||||
|
message CheckMsgRequest {
|
||||||
|
string Domain = 1 [json_name = "domain",(validator.field) = {string_not_empty: true,human_error: "70001"} ];
|
||||||
|
string TelNum = 2 [json_name = "telNum",(validator.field) = {regex: "^1\\d{10}$",human_error: "70002"}];
|
||||||
|
string Code = 3 [json_name = "code",(validator.field) = {string_not_empty: true,human_error: "70003"} ];
|
||||||
|
string scope = 4;//标记模块
|
||||||
|
}
|
||||||
|
|
||||||
|
message SendMsgStatusResponse {
|
||||||
|
}
|
||||||
|
|
||||||
|
message RemoveRequest {
|
||||||
|
string Domain = 1 [json_name = "domain",(validator.field) = {string_not_empty: true,human_error: "70001"} ];
|
||||||
|
uint64 ID = 2 [json_name = "ID",(validator.field) = {int_gt: 0,human_error: "70004"} ];
|
||||||
|
string code = 3;
|
||||||
|
}
|
||||||
|
message WriteOffRequest{
|
||||||
|
uint64 id = 1;
|
||||||
|
string domain = 2;
|
||||||
|
uint64 userId = 3;
|
||||||
|
string tel = 4;
|
||||||
|
string jonNum = 5;
|
||||||
|
string userName = 6;
|
||||||
|
string enterDate = 7;
|
||||||
|
string positionName =8;
|
||||||
|
uint64 positionId = 9;
|
||||||
|
string siteName = 10;
|
||||||
|
uint64 siteId =11;
|
||||||
|
string authUrl =12;
|
||||||
|
string type =13;
|
||||||
|
uint32 status =14;
|
||||||
|
string submitDate=15;
|
||||||
|
}
|
||||||
|
message WriteOffListRequest{
|
||||||
|
uint64 page = 1;
|
||||||
|
uint64 pageSize =2;
|
||||||
|
string domain = 3;
|
||||||
|
string userName =4;
|
||||||
|
uint64 userId = 5;
|
||||||
|
uint64 siteId =6;
|
||||||
|
string type =7;
|
||||||
|
uint32 status =8;
|
||||||
|
}
|
||||||
|
message WriteOffApproveRequest{
|
||||||
|
uint64 id = 1;
|
||||||
|
uint32 status = 2;
|
||||||
|
}
|
||||||
|
message WriteOffListResponse{
|
||||||
|
int64 total = 1;
|
||||||
|
repeated WriteOffRequest writeOffList = 2;
|
||||||
|
}
|
||||||
|
message RemoveResponse {
|
||||||
|
}
|
||||||
|
|
||||||
|
message UpdateRequest {
|
||||||
|
uint64 ID = 1 [json_name = "ID"]; //ID
|
||||||
|
string Domain = 2 [json_name = "domain",(validator.field) = {string_not_empty: true,human_error: "70001"} ];
|
||||||
|
string NickName = 3 [json_name = "nickName"];
|
||||||
|
string Password = 4 [json_name = "password"]; //密码
|
||||||
|
string Avatar = 5 [json_name = "avatar"]; //头像
|
||||||
|
string Status = 7 [json_name = "status"];
|
||||||
|
string TelNum = 8 [json_name = "telNum"];
|
||||||
|
string EnterDate = 14 [json_name = "enterDate"];
|
||||||
|
Extend Extend = 17 [json_name = "extend"];
|
||||||
|
string Title = 18 [json_name = "title"];
|
||||||
|
string JobNum = 19 [json_name = "jobNum"];
|
||||||
|
string BirthDate = 20 [json_name = "birthDate"];
|
||||||
|
uint64 Sex = 21 [json_name = "sex"];
|
||||||
|
string IdNum = 22 [json_name = "idNum"];
|
||||||
|
string RealName = 23 [json_name = "realName"];
|
||||||
|
string InvitationCode = 24 [json_name = "invitationCode"];
|
||||||
|
string LeftDate = 25 [json_name = "leftDate"];
|
||||||
|
string Remark = 26 [json_name = "remark"];
|
||||||
|
string RecentImg = 27 [json_name = "recentImg"];
|
||||||
|
string ICNum = 28 [json_name = "icNum"];
|
||||||
|
string Train = 29 [json_name = "train"];
|
||||||
|
string Certificate = 30 [json_name = "certificate"];
|
||||||
|
repeated trainVideo TrainVideos = 31 [json_name = "trainVideos"];
|
||||||
|
Operator operator = 32;
|
||||||
|
string SecurityCode = 33 [json_name = "securityCode"];
|
||||||
|
}
|
||||||
|
|
||||||
|
message Operator {
|
||||||
|
uint32 ID = 1;
|
||||||
|
string Name = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message trainVideo {
|
||||||
|
string trainUUID = 1 [json_name = "trainUUID"];
|
||||||
|
string trainDesc = 2 [json_name = "trainDesc"];
|
||||||
|
string video = 3 [json_name = "video"];
|
||||||
|
string SecurityCode = 31 [json_name = "securityCode"];
|
||||||
|
}
|
||||||
|
|
||||||
|
message UpdateResponse {
|
||||||
|
}
|
||||||
|
|
||||||
|
message PrivacyInfoRequest {
|
||||||
|
uint64 ID = 1 [json_name = "ID"]; //ID
|
||||||
|
string Domain = 2 [json_name = "domain",(validator.field) = {string_not_empty: true,human_error: "70001"} ];
|
||||||
|
string SecurityCode = 3 [json_name = "securityCode"];
|
||||||
|
}
|
||||||
|
|
||||||
|
message ListRequest {
|
||||||
|
string Domain = 1 [json_name = "domain",(validator.field) = {string_not_empty: true,human_error: "70001"} ];
|
||||||
|
uint64 PageSize = 2 [json_name = "pageSize"];
|
||||||
|
uint64 Page = 3 [json_name = "page"];
|
||||||
|
string key = 4 [json_name = "key"];
|
||||||
|
string status = 5 ;
|
||||||
|
string telNum = 6;
|
||||||
|
string startEnterDate = 7;
|
||||||
|
string endEnterDate = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ListResponse {
|
||||||
|
string Status = 1 [json_name = "status"];
|
||||||
|
uint64 Count = 2 [json_name = "count"];
|
||||||
|
repeated AccountInfo Data = 3 [json_name = "data"];
|
||||||
|
uint64 AllCount = 4 [json_name = "allCount"];
|
||||||
|
}
|
||||||
|
|
||||||
|
message InfoRequest {
|
||||||
|
string Domain = 1 [json_name = "domain",(validator.field) = {string_not_empty: true,human_error: "70001"} ];
|
||||||
|
uint64 ID = 2 [json_name = "id"];
|
||||||
|
string scene = 3 ;//场景值 base-默认仅仅user数据
|
||||||
|
}
|
||||||
|
|
||||||
|
message InfoResponse {
|
||||||
|
string Status = 1 [json_name = "status"];
|
||||||
|
AccountInfo Info = 2 [json_name = "accountInfo"];
|
||||||
|
bool IsExist = 3 [json_name = "isExist"];
|
||||||
|
}
|
||||||
|
|
||||||
|
message DecryptJwtResponse {
|
||||||
|
string Domain = 1 [json_name = "status"];
|
||||||
|
uint64 ID = 2 [json_name = "id"];
|
||||||
|
string Account = 3 [json_name = "account"];
|
||||||
|
string NickName = 4 [json_name = "nickName"];
|
||||||
|
bool IsOffline = 5 [json_name = "isOffline"];
|
||||||
|
}
|
||||||
|
|
||||||
|
message DecryptJwtRequest {
|
||||||
|
string token = 1 [json_name = "token"];
|
||||||
|
string Domain = 2 [json_name = "Domain"];
|
||||||
|
}
|
||||||
|
|
||||||
|
message CheckPwdRequest {
|
||||||
|
string Token = 1 [json_name = "token"];
|
||||||
|
string Password = 2 [json_name = "password"];
|
||||||
|
}
|
||||||
|
|
||||||
|
message AuthenticationRequest {
|
||||||
|
string Name = 1 [json_name = "name"];
|
||||||
|
string IDNum = 2 [json_name = "idNum",(validator.field) = {length_eq: 18,human_error: "70006"}];
|
||||||
|
string Token = 3 [json_name = "token"];
|
||||||
|
}
|
||||||
|
|
||||||
|
message RequestStatus {
|
||||||
|
string Status = 1 [json_name = "status"];
|
||||||
|
uint64 ID = 2 [json_name = "ID"];
|
||||||
|
bool isExist = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RegistRequest {
|
||||||
|
string domain = 1;
|
||||||
|
string telNum = 2;
|
||||||
|
string code = 3;
|
||||||
|
string address = 4;
|
||||||
|
string telAreaCode = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message LoginRequest {
|
||||||
|
string Domain = 1 [json_name = "domain",(validator.field) = {string_not_empty: true,human_error: "70001"} ];
|
||||||
|
string TelNum = 2 [json_name = "telNum",(validator.field) = {regex: "^1\\d{10}$",human_error: "70002"}];
|
||||||
|
string Code = 3 [json_name = "code"];
|
||||||
|
string Password = 4 [json_name = "password"];
|
||||||
|
string Ip = 5 [json_name = "ip"];
|
||||||
|
bool passCheckIp = 6 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TokenInfo {
|
||||||
|
AccountInfo AccountInfo = 1 [json_name = "accountInfo"];
|
||||||
|
string Token = 2 [json_name = "token"];
|
||||||
|
string RefreshToken = 4 [json_name = "refresh"];
|
||||||
|
bool IsSampleAddress = 3 [json_name = "isSampleAddress"];
|
||||||
|
string nowAddress = 5 [json_name = "nowAddress"];
|
||||||
|
}
|
||||||
|
|
||||||
|
message Extend {
|
||||||
|
string JumpTo = 1 [json_name = "jumpTo"];
|
||||||
|
string Lang = 2 [json_name = "lang"];
|
||||||
|
bool CanScan = 3 [json_name = "canScan"];
|
||||||
|
bool ResolutionRatio = 4 [json_name = "resolutionRatio"];
|
||||||
|
}
|
||||||
|
|
||||||
|
message Department {
|
||||||
|
uint64 ID = 1 [json_name = "ID"];
|
||||||
|
string Name = 2 [json_name = "name"];
|
||||||
|
}
|
||||||
|
|
||||||
|
// The response message containing the greetings
|
||||||
|
message AccountInfo {
|
||||||
|
uint64 ID = 1 [json_name = "id"];
|
||||||
|
string Account = 2 [json_name = "account"];
|
||||||
|
string NickName = 3 [json_name = "nickName"];
|
||||||
|
int64 Type = 4 [json_name = "type"];
|
||||||
|
string TelNum = 5 [json_name = "telNum"];
|
||||||
|
int32 Status = 6 [json_name = "status"];
|
||||||
|
string Avatar = 7 [json_name = "avatar"];
|
||||||
|
string CreateAt = 8 [json_name = "createAt"];
|
||||||
|
uint64 RealNameID = 9 [json_name = "realNameID"];
|
||||||
|
string RealName = 10 [json_name = "realName"];
|
||||||
|
string IDNum = 11 [json_name = "iDNum"];
|
||||||
|
string MnemonicWords = 12 [json_name = "mnemonicWords"];
|
||||||
|
uint64 IsNeedChange = 13 [json_name = "isNeedChange"];
|
||||||
|
string EnterDate = 14 [json_name = "enterDate"];
|
||||||
|
float WorkYear = 15 [json_name = "workYear"];
|
||||||
|
string Domain = 16 [json_name = "domain"];
|
||||||
|
Extend Extend = 17 [json_name = "extend"];
|
||||||
|
string JobNum = 18 [json_name = "jobNum"];
|
||||||
|
string BirthDate = 19 [json_name = "birth_date"];
|
||||||
|
uint64 Age = 20 [json_name = "age"];
|
||||||
|
uint64 Sex = 21 [json_name = "sex"];
|
||||||
|
string Title = 22 [json_name = "title"];
|
||||||
|
repeated Department Departments = 23 [json_name = "departments"];
|
||||||
|
string Ip = 24 [json_name = "ip"];
|
||||||
|
string LoginDate = 25 [json_name = "loginDate"];
|
||||||
|
string InvitationCode = 26 [json_name = "invitationCode"];
|
||||||
|
uint64 NowLogId = 27 [json_name = "nowLogId"];
|
||||||
|
bool CanScan = 28 [json_name = "canScan"];
|
||||||
|
string LeftDate = 29 [json_name = "leftDate"];
|
||||||
|
repeated PositionUser Positions = 30 [json_name = "positions"];
|
||||||
|
string Remark = 31 [json_name = "remark"];
|
||||||
|
string recentImg =32;
|
||||||
|
repeated ClockUser clocks = 33;
|
||||||
|
string mailAccount = 34;
|
||||||
|
string ICNum = 35 [json_name = "icNum"];
|
||||||
|
string englishName = 36;
|
||||||
|
string Train = 37 [json_name = "train"];
|
||||||
|
string Certificate = 38 [json_name = "certificate"];
|
||||||
|
repeated trainVideo TrainVideos = 39 [json_name = "trainVideos"];
|
||||||
|
Operator operator = 40;
|
||||||
|
string updatedAt = 41;
|
||||||
|
string SecurityCode = 42 [json_name = "securityCode"];
|
||||||
|
string BlockAddr = 43 [json_name = "blockAddr"];
|
||||||
|
}
|
||||||
|
|
||||||
|
message UserInfoV2 {
|
||||||
|
uint64 ID = 1 ;
|
||||||
|
string Account = 2 ;
|
||||||
|
string NickName = 3 ;
|
||||||
|
string TelNum = 4 ;
|
||||||
|
string Status = 5 ;
|
||||||
|
string Avatar = 6 ;
|
||||||
|
string CreateAt = 7 ;
|
||||||
|
string RealName = 8;
|
||||||
|
string IDNum = 9;
|
||||||
|
string EnterDate = 10;
|
||||||
|
Extend Extend = 11;
|
||||||
|
string JobNum = 12;
|
||||||
|
string recentImg = 13;
|
||||||
|
string mailAccount = 14;
|
||||||
|
Operator operator = 15;
|
||||||
|
string updatedAt = 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RefreshTokenRequest {
|
||||||
|
string refreshToken = 1 ;
|
||||||
|
string domain = 2;
|
||||||
|
string ip = 3 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PositionUser {
|
||||||
|
uint64 PositionID = 1 [json_name = "positionID"];
|
||||||
|
string PositionName = 2 [json_name = "positionName"];
|
||||||
|
uint64 DepartmentId = 3 [json_name = "departmentId"];
|
||||||
|
string DepartmentCode = 4 [json_name = "departmentCode"];
|
||||||
|
string DepartmentName = 5 [json_name = "departmentName"];
|
||||||
|
uint64 UserId = 6 [json_name = "userId"];
|
||||||
|
string UserName = 7 [json_name = "userName"];
|
||||||
|
}
|
||||||
|
message JobNumGetInfoRequest{
|
||||||
|
string jobNum = 1;
|
||||||
|
string domain = 2;
|
||||||
|
}
|
||||||
|
message CreateClockDeviceRequest{
|
||||||
|
string deviceNum =1;
|
||||||
|
string deviceName =2;
|
||||||
|
string deviceSite = 3;
|
||||||
|
}
|
||||||
|
message UpdateClockDeviceRequest{
|
||||||
|
uint64 id = 1;
|
||||||
|
string deviceNum =2;
|
||||||
|
string deviceName =3;
|
||||||
|
string deviceSite = 4;
|
||||||
|
}
|
||||||
|
message ClockDeviceResponse{
|
||||||
|
uint64 id = 1;
|
||||||
|
}
|
||||||
|
message RemoveClockDeviceRequest{
|
||||||
|
uint64 id = 1;
|
||||||
|
}
|
||||||
|
message ClockDeviceListRequest{
|
||||||
|
uint64 id =1;
|
||||||
|
string deviceSite = 2;
|
||||||
|
string deviceNum = 3;
|
||||||
|
string deviceName = 4;
|
||||||
|
uint64 page = 5 ;
|
||||||
|
uint64 pageSize = 6 ;
|
||||||
|
repeated uint64 ids = 7;
|
||||||
|
}
|
||||||
|
message ClockDeviceListResponse{
|
||||||
|
uint64 count =1;
|
||||||
|
repeated ClockDeviceInfo data = 2;
|
||||||
|
}
|
||||||
|
message ClockUser{
|
||||||
|
uint64 id =1;
|
||||||
|
string createdAt =2;
|
||||||
|
string updatedAt =3;
|
||||||
|
string deletedAt =4;
|
||||||
|
uint64 deviceID =5;
|
||||||
|
uint64 userId =6;
|
||||||
|
uint64 status =7;
|
||||||
|
ClockDeviceInfo device = 8;
|
||||||
|
}
|
||||||
|
message ClockDeviceInfo {
|
||||||
|
uint64 id = 1 ;
|
||||||
|
string createAt = 2 ;
|
||||||
|
string updateAt = 3 ;
|
||||||
|
string deviceSite = 4;
|
||||||
|
string deviceNum = 5;
|
||||||
|
string deviceName = 6;
|
||||||
|
uint64 userNum = 7;
|
||||||
|
repeated ClockUserRel data = 8 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ClockDeviceInfoResponse{
|
||||||
|
uint64 count = 1;
|
||||||
|
repeated ClockUserRel data = 2 ;
|
||||||
|
}
|
||||||
|
message ClockUserRel {
|
||||||
|
uint64 id = 1 ;
|
||||||
|
string createAt = 2 ;
|
||||||
|
string updateAt = 3;
|
||||||
|
string nickName = 4 ;
|
||||||
|
string jobNum = 5 ;
|
||||||
|
string icNum = 6;
|
||||||
|
}
|
||||||
|
message ClockDeviceInfoRequest{
|
||||||
|
uint64 id = 1;
|
||||||
|
uint64 page = 2 ;
|
||||||
|
uint64 pageSize = 3 ;
|
||||||
|
}
|
||||||
|
message ClockBatchBindRequest{
|
||||||
|
uint64 id = 1;
|
||||||
|
repeated uint64 userId = 2;
|
||||||
|
repeated uint64 deviceId =3;
|
||||||
|
}
|
||||||
|
message ClockBatchListResponse{
|
||||||
|
repeated ClockUserDeviceBatch data = 1;
|
||||||
|
}
|
||||||
|
message ClockUserDeviceBatch{
|
||||||
|
uint64 userId = 1;
|
||||||
|
uint64 deviceId = 2;
|
||||||
|
string JobNum = 3;
|
||||||
|
string deviceNum = 4;
|
||||||
|
string deviceName = 5;
|
||||||
|
string workStatus = 6;
|
||||||
|
}
|
||||||
|
message ClockLogInfo{
|
||||||
|
uint64 id = 1;
|
||||||
|
string sn = 2;
|
||||||
|
string userId =3;
|
||||||
|
string recogType =4;
|
||||||
|
string recogTime =5;
|
||||||
|
float gender =6;
|
||||||
|
string photo =7;
|
||||||
|
float passStatus =8;
|
||||||
|
string userName =9;
|
||||||
|
float userType =10;
|
||||||
|
string confidence =11;
|
||||||
|
float reflectivity =12;
|
||||||
|
string cardNumber =13;
|
||||||
|
string passWord =14;
|
||||||
|
string qrCode =15;
|
||||||
|
string tel = 16;
|
||||||
|
string reasonVisit = 17;
|
||||||
|
string receiverTel = 18;
|
||||||
|
uint64 numOfPeople = 19;
|
||||||
|
}
|
||||||
|
message ClockLogReq{
|
||||||
|
uint64 id = 1;
|
||||||
|
uint64 page = 2;
|
||||||
|
uint64 pageSize = 3;
|
||||||
|
string userName = 4;
|
||||||
|
string recogType = 5;
|
||||||
|
string deviceNum = 6;
|
||||||
|
string recogDate = 7;
|
||||||
|
uint64 userId = 8;
|
||||||
|
}
|
||||||
|
message ClockLogListResponse{
|
||||||
|
repeated ClockLogInfo data =1;
|
||||||
|
uint64 count = 2;
|
||||||
|
}
|
535
api/account/account.validator.pb.go
Normal file
535
api/account/account.validator.pb.go
Normal file
@ -0,0 +1,535 @@
|
|||||||
|
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||||
|
// source: api/account/account.proto
|
||||||
|
|
||||||
|
package account
|
||||||
|
|
||||||
|
import (
|
||||||
|
fmt "fmt"
|
||||||
|
math "math"
|
||||||
|
proto "github.com/golang/protobuf/proto"
|
||||||
|
_ "github.com/mwitkow/go-proto-validators"
|
||||||
|
regexp "regexp"
|
||||||
|
github_com_mwitkow_go_proto_validators "github.com/mwitkow/go-proto-validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var _ = proto.Marshal
|
||||||
|
var _ = fmt.Errorf
|
||||||
|
var _ = math.Inf
|
||||||
|
|
||||||
|
func (this *CheckRealNameResponse) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *CheckRealNameRequest) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *UserListResponse) Validate() error {
|
||||||
|
for _, item := range this.UserList {
|
||||||
|
if item != nil {
|
||||||
|
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("UserList", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *UserListInfo) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *UserListRequest) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *UserInfoResponse) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *RealNameResponse) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *RealNameRequest) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *RegisterResponse) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *UsersByJobNumRequest) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *QueryPersonnelWithTheSameNameRequest) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *QueryPersonnelWithTheSameNameResponse) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *ListV2Request) Validate() error {
|
||||||
|
if this.Domain == "" {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Domain", fmt.Errorf(`70001`))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *SendClockInWechatRequest) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *MailAccountByNickNameRequest) Validate() error {
|
||||||
|
if this.Domain == "" {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Domain", fmt.Errorf(`70001`))
|
||||||
|
}
|
||||||
|
if this.NickName == "" {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("NickName", fmt.Errorf(`70005`))
|
||||||
|
}
|
||||||
|
if !(len(this.NickName) < 20) {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("NickName", fmt.Errorf(`70005`))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *CreateMaiAccountRequest) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *MaiAccountResponse) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *FddCreateUserRequest) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *WxBoxUserInfoRequest) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *WxGetOpenIdByCodeRequest) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *WxGetOpenIdByCodeResponse) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *WxBoxTelNumByCodeResponse) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *WxBoxUserInfo) Validate() error {
|
||||||
|
if this.User != nil {
|
||||||
|
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(this.User); err != nil {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("User", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if this.Fdd != nil {
|
||||||
|
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(this.Fdd); err != nil {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Fdd", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *FddInfo) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *UserInfo) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *CommonRequest) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *WxAppRequest) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *WxAppResponse) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *WxUserUpdateRequest) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *WxUserOrCreateRequest) Validate() error {
|
||||||
|
if this.OpenID == "" {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("OpenID", fmt.Errorf(`缺少openid`))
|
||||||
|
}
|
||||||
|
if this.GhID == "" {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("GhID", fmt.Errorf(`缺少参数ghid`))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *WxUserResponse) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *LoginLogsResponse) Validate() error {
|
||||||
|
for _, item := range this.Data {
|
||||||
|
if item != nil {
|
||||||
|
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Data", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *LoginLog) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *OnlineLogByIdRequest) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *LoginInfosByUserIdRequest) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *SendNewTelNumMsgRequest) Validate() error {
|
||||||
|
if this.Domain == "" {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Domain", fmt.Errorf(`70001`))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *UserByTelRequest) Validate() error {
|
||||||
|
if this.Domain == "" {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Domain", fmt.Errorf(`70001`))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *CommonResponse) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *UsersByTelRequest) Validate() error {
|
||||||
|
if this.Domain == "" {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Domain", fmt.Errorf(`70001`))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *ListByIDsRequest) Validate() error {
|
||||||
|
if this.Domain == "" {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Domain", fmt.Errorf(`70001`))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var _regex_SendMsgRequest_TelNum = regexp.MustCompile(`^1\d{10}$`)
|
||||||
|
|
||||||
|
func (this *SendMsgRequest) Validate() error {
|
||||||
|
if this.Domain == "" {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Domain", fmt.Errorf(`70001`))
|
||||||
|
}
|
||||||
|
if !_regex_SendMsgRequest_TelNum.MatchString(this.TelNum) {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("TelNum", fmt.Errorf(`70002`))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var _regex_SendCustomMsgRequest_TelNum = regexp.MustCompile(`^1\d{10}$`)
|
||||||
|
|
||||||
|
func (this *SendCustomMsgRequest) Validate() error {
|
||||||
|
if this.Domain == "" {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Domain", fmt.Errorf(`70001`))
|
||||||
|
}
|
||||||
|
if !_regex_SendCustomMsgRequest_TelNum.MatchString(this.TelNum) {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("TelNum", fmt.Errorf(`70002`))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var _regex_CheckMsgRequest_TelNum = regexp.MustCompile(`^1\d{10}$`)
|
||||||
|
|
||||||
|
func (this *CheckMsgRequest) Validate() error {
|
||||||
|
if this.Domain == "" {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Domain", fmt.Errorf(`70001`))
|
||||||
|
}
|
||||||
|
if !_regex_CheckMsgRequest_TelNum.MatchString(this.TelNum) {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("TelNum", fmt.Errorf(`70002`))
|
||||||
|
}
|
||||||
|
if this.Code == "" {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Code", fmt.Errorf(`70003`))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *SendMsgStatusResponse) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *RemoveRequest) Validate() error {
|
||||||
|
if this.Domain == "" {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Domain", fmt.Errorf(`70001`))
|
||||||
|
}
|
||||||
|
if !(this.ID > 0) {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("ID", fmt.Errorf(`70004`))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *WriteOffRequest) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *WriteOffListRequest) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *WriteOffApproveRequest) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *WriteOffListResponse) Validate() error {
|
||||||
|
for _, item := range this.WriteOffList {
|
||||||
|
if item != nil {
|
||||||
|
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("WriteOffList", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *RemoveResponse) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *UpdateRequest) Validate() error {
|
||||||
|
if this.Domain == "" {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Domain", fmt.Errorf(`70001`))
|
||||||
|
}
|
||||||
|
if this.Extend != nil {
|
||||||
|
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(this.Extend); err != nil {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Extend", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, item := range this.TrainVideos {
|
||||||
|
if item != nil {
|
||||||
|
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("TrainVideos", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if this.Operator != nil {
|
||||||
|
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(this.Operator); err != nil {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Operator", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *Operator) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *TrainVideo) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *UpdateResponse) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *PrivacyInfoRequest) Validate() error {
|
||||||
|
if this.Domain == "" {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Domain", fmt.Errorf(`70001`))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *ListRequest) Validate() error {
|
||||||
|
if this.Domain == "" {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Domain", fmt.Errorf(`70001`))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *ListResponse) Validate() error {
|
||||||
|
for _, item := range this.Data {
|
||||||
|
if item != nil {
|
||||||
|
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Data", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *InfoRequest) Validate() error {
|
||||||
|
if this.Domain == "" {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Domain", fmt.Errorf(`70001`))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *InfoResponse) Validate() error {
|
||||||
|
if this.Info != nil {
|
||||||
|
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(this.Info); err != nil {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Info", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *DecryptJwtResponse) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *DecryptJwtRequest) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *CheckPwdRequest) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *AuthenticationRequest) Validate() error {
|
||||||
|
if !(len(this.IDNum) == 18) {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("IDNum", fmt.Errorf(`70006`))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *RequestStatus) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *RegistRequest) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var _regex_LoginRequest_TelNum = regexp.MustCompile(`^1\d{10}$`)
|
||||||
|
|
||||||
|
func (this *LoginRequest) Validate() error {
|
||||||
|
if this.Domain == "" {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Domain", fmt.Errorf(`70001`))
|
||||||
|
}
|
||||||
|
if !_regex_LoginRequest_TelNum.MatchString(this.TelNum) {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("TelNum", fmt.Errorf(`70002`))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *TokenInfo) Validate() error {
|
||||||
|
if this.AccountInfo != nil {
|
||||||
|
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(this.AccountInfo); err != nil {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("AccountInfo", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *Extend) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *Department) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *AccountInfo) Validate() error {
|
||||||
|
if this.Extend != nil {
|
||||||
|
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(this.Extend); err != nil {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Extend", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, item := range this.Departments {
|
||||||
|
if item != nil {
|
||||||
|
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Departments", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, item := range this.Positions {
|
||||||
|
if item != nil {
|
||||||
|
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Positions", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, item := range this.Clocks {
|
||||||
|
if item != nil {
|
||||||
|
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Clocks", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, item := range this.TrainVideos {
|
||||||
|
if item != nil {
|
||||||
|
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("TrainVideos", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if this.Operator != nil {
|
||||||
|
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(this.Operator); err != nil {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Operator", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *UserInfoV2) Validate() error {
|
||||||
|
if this.Extend != nil {
|
||||||
|
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(this.Extend); err != nil {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Extend", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if this.Operator != nil {
|
||||||
|
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(this.Operator); err != nil {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Operator", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *RefreshTokenRequest) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *PositionUser) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *JobNumGetInfoRequest) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *CreateClockDeviceRequest) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *UpdateClockDeviceRequest) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *ClockDeviceResponse) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *RemoveClockDeviceRequest) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *ClockDeviceListRequest) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *ClockDeviceListResponse) Validate() error {
|
||||||
|
for _, item := range this.Data {
|
||||||
|
if item != nil {
|
||||||
|
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Data", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *ClockUser) Validate() error {
|
||||||
|
if this.Device != nil {
|
||||||
|
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(this.Device); err != nil {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Device", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *ClockDeviceInfo) Validate() error {
|
||||||
|
for _, item := range this.Data {
|
||||||
|
if item != nil {
|
||||||
|
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Data", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *ClockDeviceInfoResponse) Validate() error {
|
||||||
|
for _, item := range this.Data {
|
||||||
|
if item != nil {
|
||||||
|
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Data", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *ClockUserRel) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *ClockDeviceInfoRequest) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *ClockBatchBindRequest) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *ClockBatchListResponse) Validate() error {
|
||||||
|
for _, item := range this.Data {
|
||||||
|
if item != nil {
|
||||||
|
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Data", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *ClockUserDeviceBatch) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *ClockLogInfo) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *ClockLogReq) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *ClockLogListResponse) Validate() error {
|
||||||
|
for _, item := range this.Data {
|
||||||
|
if item != nil {
|
||||||
|
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Data", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
1679
api/account/account_triple.pb.go
Normal file
1679
api/account/account_triple.pb.go
Normal file
File diff suppressed because it is too large
Load Diff
199
cmd/app.go
Normal file
199
cmd/app.go
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"dubbo.apache.org/dubbo-go/v3/common/logger"
|
||||||
|
"dubbo.apache.org/dubbo-go/v3/config"
|
||||||
|
_ "dubbo.apache.org/dubbo-go/v3/imports"
|
||||||
|
"fmt"
|
||||||
|
appconfig "github.com/fonchain_enterprise/micro-account/cmd/config"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/blockchain"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/cache"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/common/dingding"
|
||||||
|
_ "github.com/fonchain_enterprise/micro-account/pkg/common/filter"
|
||||||
|
msgconfig "github.com/fonchain_enterprise/micro-account/pkg/config"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/infrsatructure/external"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/m"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/model"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/service"
|
||||||
|
"github.com/fonchain_enterprise/utils/zap_log"
|
||||||
|
"github.com/nacos-group/nacos-sdk-go/clients"
|
||||||
|
"github.com/nacos-group/nacos-sdk-go/common/constant"
|
||||||
|
"github.com/nacos-group/nacos-sdk-go/vo"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
//启动新日志
|
||||||
|
if err := bootstrap(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
//注册服务
|
||||||
|
config.SetProviderService(&service.AccountProvider{})
|
||||||
|
//config.SetProviderService(&service.CoinProvider{})
|
||||||
|
if err := config.Load(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
//logger.SetLogger(log.GetFakeLogger())
|
||||||
|
logger.SetLogger(zap_log.GetFakeLogger())
|
||||||
|
|
||||||
|
//dubbo日志
|
||||||
|
logger.Info("帐号微服务启动成功,git commit:", os.Getenv("GIT_COMMIT"))
|
||||||
|
|
||||||
|
select {}
|
||||||
|
}
|
||||||
|
|
||||||
|
func bootstrap() (err error) {
|
||||||
|
|
||||||
|
aliConfig, err := appconfig.LoadAliEnv(m.SERVER_CONFIG)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var configEnv *appconfig.Config
|
||||||
|
if aliConfig.System.Nacos == true {
|
||||||
|
fmt.Println("使用nacos")
|
||||||
|
configEnv, err = appconfig.LoadEnvFromFileInfo(loadAli(aliConfig))
|
||||||
|
} else {
|
||||||
|
fmt.Println("使用配置文件")
|
||||||
|
configEnv, err = appconfig.LoadEnv(m.SERVER_CONFIG)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("\n当前环境%s,版本号:%s\n", configEnv.System.Mode, configEnv.System.Version)
|
||||||
|
|
||||||
|
err = zap_log.InitZapLog("../conf/log.yaml")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
//数据库
|
||||||
|
mysqlConfig := model.MysqlConfig{
|
||||||
|
Db: configEnv.Mysql.Db,
|
||||||
|
DbHost: configEnv.Mysql.DbHost,
|
||||||
|
DbPort: configEnv.Mysql.DbPort,
|
||||||
|
DbUser: configEnv.Mysql.DbUser,
|
||||||
|
DbPassWord: configEnv.Mysql.DbPassWord,
|
||||||
|
DbName: configEnv.Mysql.DbName,
|
||||||
|
}
|
||||||
|
|
||||||
|
model.LoadEnv(mysqlConfig)
|
||||||
|
|
||||||
|
//redis
|
||||||
|
redisConfig := cache.RedisConfig{
|
||||||
|
RedisDB: configEnv.Redis.RedisDB,
|
||||||
|
RedisAddr: configEnv.Redis.RedisAddr,
|
||||||
|
RedisPw: configEnv.Redis.RedisPW,
|
||||||
|
RedisDbName: configEnv.Redis.RedisDBNAme,
|
||||||
|
}
|
||||||
|
|
||||||
|
cache.LoadRedis(redisConfig)
|
||||||
|
|
||||||
|
//chain
|
||||||
|
chainConfig := blockchain.ChainConfig{
|
||||||
|
IP: configEnv.Chain.IP,
|
||||||
|
AdminMnemonicWords: configEnv.Chain.AdminMnemonicWords,
|
||||||
|
AdminContractAccount: configEnv.Chain.AdminContractAccount,
|
||||||
|
ContractName: configEnv.Chain.ContractName,
|
||||||
|
ContractType: configEnv.Chain.ContractType,
|
||||||
|
}
|
||||||
|
|
||||||
|
blockchain.LoadEnv(chainConfig)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
msgInfo := msgconfig.MobileConfigTemplate{
|
||||||
|
AK: configEnv.Mobile.AK,
|
||||||
|
SK: configEnv.Mobile.SK,
|
||||||
|
URL: configEnv.Mobile.URL,
|
||||||
|
}
|
||||||
|
|
||||||
|
aliInfo := msgconfig.AliMessage{
|
||||||
|
AK: configEnv.AlMobile.AK,
|
||||||
|
AS: configEnv.AlMobile.AS,
|
||||||
|
URL: configEnv.AlMobile.URL,
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("飞鸽短信配置", msgInfo)
|
||||||
|
fmt.Println("阿里短信配置", aliInfo)
|
||||||
|
msgconfig.LoadData(msgInfo, aliInfo)
|
||||||
|
|
||||||
|
dingding.LoadAccessToken(configEnv.Mobile.DingDingKey)
|
||||||
|
|
||||||
|
//logger.SetLogger()
|
||||||
|
model.SetSendPhoneNUm(configEnv.System.Mode == "prod")
|
||||||
|
|
||||||
|
fmt.Println("是否创建邮箱", configEnv.Mail.IsProd)
|
||||||
|
external.LoadEnv(configEnv.Mail.Username, configEnv.Mail.Password, configEnv.Mail.Domain, configEnv.Mail.IsProd)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadAli(aliConfig *appconfig.AliConfig) string {
|
||||||
|
fmt.Println("ali", aliConfig)
|
||||||
|
clientConfig := constant.ClientConfig{
|
||||||
|
NamespaceId: aliConfig.Nacos.NamespaceId, // 如果需要支持多namespace,我们可以场景多个client,它们有不同的NamespaceId。当namespace是public时,此处填空字符串。
|
||||||
|
TimeoutMs: 5000,
|
||||||
|
NotLoadCacheAtStart: true,
|
||||||
|
LogDir: "/tmp/nacos/log",
|
||||||
|
CacheDir: "/tmp/nacos/cache",
|
||||||
|
Username: aliConfig.Nacos.Username,
|
||||||
|
Password: aliConfig.Nacos.Password,
|
||||||
|
LogLevel: "debug",
|
||||||
|
}
|
||||||
|
//配置连接信息
|
||||||
|
serverConfigs := []constant.ServerConfig{
|
||||||
|
{
|
||||||
|
IpAddr: aliConfig.Nacos.IpAddr,
|
||||||
|
ContextPath: "/nacos",
|
||||||
|
Port: 80,
|
||||||
|
Scheme: "http",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create naming client for service discovery
|
||||||
|
configClient, err := clients.CreateConfigClient(map[string]interface{}{
|
||||||
|
"serverConfigs": serverConfigs,
|
||||||
|
"clientConfig": clientConfig,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
logger.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
//读取文件
|
||||||
|
content, err := configClient.GetConfig(vo.ConfigParam{
|
||||||
|
DataId: aliConfig.Nacos.DataId, //此处对应之前的网页配置的名称
|
||||||
|
Group: aliConfig.Nacos.Group, //此处对应之前的网页配置的分组
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
logger.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return content
|
||||||
|
}
|
105
cmd/config/config.go
Normal file
105
cmd/config/config.go
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/BurntSushi/toml"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
/********start-配置信息*********/
|
||||||
|
|
||||||
|
//Baiduco 百度上链
|
||||||
|
type Mysql struct {
|
||||||
|
Db string
|
||||||
|
DbHost string
|
||||||
|
DbPort string
|
||||||
|
DbUser string
|
||||||
|
DbPassWord string
|
||||||
|
DbName string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Redis struct {
|
||||||
|
RedisDB string
|
||||||
|
RedisAddr string
|
||||||
|
RedisPW string
|
||||||
|
RedisDBNAme string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Chain struct {
|
||||||
|
IP string
|
||||||
|
AdminMnemonicWords string `toml:"MnemonicWords"`
|
||||||
|
AdminContractAccount string `toml:"ContractAccount"`
|
||||||
|
ContractName string
|
||||||
|
ContractType string
|
||||||
|
}
|
||||||
|
type System struct {
|
||||||
|
Mode string
|
||||||
|
Version string
|
||||||
|
Nacos bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type Mobile struct {
|
||||||
|
SK string
|
||||||
|
AK string
|
||||||
|
URL string
|
||||||
|
DingDingKey string
|
||||||
|
}
|
||||||
|
type Mail struct {
|
||||||
|
IsProd bool
|
||||||
|
Username string
|
||||||
|
Password string
|
||||||
|
Domain string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Mysql Mysql `toml:"mysql"`
|
||||||
|
Redis Redis `toml:"redis"`
|
||||||
|
Chain Chain `toml:"chain"`
|
||||||
|
System System `toml:"system"`
|
||||||
|
Mobile Mobile `toml:"mobile"`
|
||||||
|
Mail Mail `toml:"mail"`
|
||||||
|
AlMobile AlMobile `toml:"almobile"`
|
||||||
|
}
|
||||||
|
type AlMobile struct {
|
||||||
|
AS string
|
||||||
|
AK string
|
||||||
|
URL string
|
||||||
|
}
|
||||||
|
|
||||||
|
/********start-配置信息*********/
|
||||||
|
|
||||||
|
var AppConfig *Config
|
||||||
|
|
||||||
|
func newConfig() *Config {
|
||||||
|
return new(Config)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadEnv(path string) (*Config, error) {
|
||||||
|
_, err := os.Stat(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
AppConfig = newConfig()
|
||||||
|
if _, err := toml.DecodeFile(path, AppConfig); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return AppConfig, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadEnvFromFileInfo(data string) (*Config, error) {
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
if data == "" {
|
||||||
|
return nil, errors.New("nacos 配置文件为空")
|
||||||
|
}
|
||||||
|
|
||||||
|
AppConfig = newConfig()
|
||||||
|
if _, err := toml.Decode(data, AppConfig); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return AppConfig, nil
|
||||||
|
}
|
47
cmd/config/nacos.go
Normal file
47
cmd/config/nacos.go
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/BurntSushi/toml"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
/********start-配置信息*********/
|
||||||
|
type Nacos struct {
|
||||||
|
NamespaceId string
|
||||||
|
Username string
|
||||||
|
Password string
|
||||||
|
IpAddr string
|
||||||
|
DataId string
|
||||||
|
Group string
|
||||||
|
}
|
||||||
|
|
||||||
|
type AliConfig struct {
|
||||||
|
System System `toml:"system"`
|
||||||
|
Nacos Nacos `toml:"Nacos"`
|
||||||
|
}
|
||||||
|
|
||||||
|
/********start-配置信息*********/
|
||||||
|
|
||||||
|
var AliAppConfig *AliConfig
|
||||||
|
|
||||||
|
func newAliConfig() *AliConfig {
|
||||||
|
return new(AliConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadAliEnv(path string) (*AliConfig, error) {
|
||||||
|
data, err := ioutil.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
configStr := os.ExpandEnv(string(data))
|
||||||
|
|
||||||
|
AliAppConfig = newAliConfig()
|
||||||
|
|
||||||
|
if _, err := toml.Decode(configStr, AliAppConfig); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return AliAppConfig, nil
|
||||||
|
}
|
0
conf/.gitignore
vendored
Normal file
0
conf/.gitignore
vendored
Normal file
68
docs/account.sql
Normal file
68
docs/account.sql
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
-- --------------------------------------------------------
|
||||||
|
-- 主机: 127.0.0.1
|
||||||
|
-- 服务器版本: 5.7.38 - MySQL Community Server (GPL)
|
||||||
|
-- 服务器操作系统: Linux
|
||||||
|
-- HeidiSQL 版本: 12.0.0.6468
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||||
|
/*!40101 SET NAMES utf8 */;
|
||||||
|
/*!50503 SET NAMES utf8mb4 */;
|
||||||
|
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
|
||||||
|
/*!40103 SET TIME_ZONE='+00:00' */;
|
||||||
|
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
|
||||||
|
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
|
||||||
|
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
|
||||||
|
|
||||||
|
-- 导出 表 fontree-account.real_name 结构
|
||||||
|
CREATE TABLE IF NOT EXISTS `real_name` (
|
||||||
|
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`created_at` datetime DEFAULT NULL,
|
||||||
|
`updated_at` datetime DEFAULT NULL,
|
||||||
|
`deleted_at` int(11) DEFAULT NULL,
|
||||||
|
`name` varchar(256) NOT NULL,
|
||||||
|
`id_num` varchar(256) NOT NULL,
|
||||||
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
|
KEY `idx_real_name_deleted_at` (`deleted_at`) USING BTREE
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
|
||||||
|
CREATE TABLE `user` (
|
||||||
|
`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
`created_at` DATETIME NULL DEFAULT NULL,
|
||||||
|
`updated_at` DATETIME NULL DEFAULT NULL,
|
||||||
|
`deleted_at` INT(11) NULL DEFAULT '0' COMMENT '删除标志',
|
||||||
|
`account` VARCHAR(256) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
|
||||||
|
`mnemonic_words` VARCHAR(256) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
|
||||||
|
`tel_num` VARCHAR(256) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
|
||||||
|
`password_digest` VARCHAR(256) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
|
||||||
|
`nickname` VARCHAR(256) NOT NULL COLLATE 'utf8_general_ci',
|
||||||
|
`status` VARCHAR(256) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
|
||||||
|
`avatar` VARCHAR(1000) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
|
||||||
|
`real_name_id` BIGINT(20) UNSIGNED NULL DEFAULT NULL,
|
||||||
|
`auth` BIGINT(20) UNSIGNED NULL DEFAULT NULL,
|
||||||
|
`theme_id` BIGINT(20) UNSIGNED NULL DEFAULT NULL,
|
||||||
|
`domain` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
|
||||||
|
`public_key` VARCHAR(256) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
|
||||||
|
`is_need_change` TINYINT(4) NULL DEFAULT '1' COMMENT '是否强制重置密码',
|
||||||
|
`enter_date` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
|
||||||
|
`work_year` FLOAT(3,1) NULL DEFAULT NULL,
|
||||||
|
`extend` JSON NULL DEFAULT NULL COMMENT '扩展属性',
|
||||||
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
|
UNIQUE INDEX `unqiue_tel` (`domain`, `tel_num`, `deleted_at`) USING BTREE,
|
||||||
|
UNIQUE INDEX `account` (`account`, `id`, `deleted_at`) USING BTREE,
|
||||||
|
INDEX `idx_user_deleted_at` (`deleted_at`) USING BTREE
|
||||||
|
)
|
||||||
|
COLLATE='utf8_general_ci'
|
||||||
|
ENGINE=InnoDB
|
||||||
|
AUTO_INCREMENT=41
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- 数据导出被取消选择。
|
||||||
|
|
||||||
|
/*!40103 SET TIME_ZONE=IFNULL(@OLD_TIME_ZONE, 'system') */;
|
||||||
|
/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
|
||||||
|
/*!40014 SET FOREIGN_KEY_CHECKS=IFNULL(@OLD_FOREIGN_KEY_CHECKS, 1) */;
|
||||||
|
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||||
|
/*!40111 SET SQL_NOTES=IFNULL(@OLD_SQL_NOTES, 1) */;
|
||||||
|
INSERT INTO `user` (`id`, `created_at`, `updated_at`, `deleted_at`, `account`, `mnemonic_words`, `tel_num`, `password_digest`, `nickname`, `status`, `avatar`, `real_name_id`, `auth`, `theme_id`, `domain`, `public_key`) VALUES (40, '2022-08-03 06:06:17', '2022-08-04 02:42:17', 0, 'TenaGe8oL5KqsbJgmLFaD1zsyXU6k3Lgs', 'Fe9V/pftKfajtmR55FpMKJuI/9NsCc5Nnfgsxnb9E/IZOK76YGmz2BKDy9v2qqrA', '12233445566', '$2a$12$7C8drxzbuO3jbeMBkmzRfeQYPVJTUWByQcLmG/tljjnhokDEq79RC', '超级管理', 'notactive', '', 0, 0, NULL, 'fontree', '{"Curvname":"P-256","X":78545775124824610215124063665621548167623667204728303094007555226201575072468,"Y":50472501812965014802492291779217782793101961009658062700069826283252860388199}');
|
12
docs/env/ali/conf.ini
vendored
Normal file
12
docs/env/ali/conf.ini
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
[system]
|
||||||
|
Mode = "prod"
|
||||||
|
Version = "1.0.1"
|
||||||
|
Nacos = true
|
||||||
|
|
||||||
|
[Nacos]
|
||||||
|
NamespaceId = "${NamespaceId}"
|
||||||
|
Username = "${Username}"
|
||||||
|
Password = "${Password}"
|
||||||
|
IpAddr = "${IpAddr}"
|
||||||
|
Group = "${Group}"
|
||||||
|
DataId = "micro-account-conf"
|
34
docs/env/ali/dubbogo.yaml
vendored
Normal file
34
docs/env/ali/dubbogo.yaml
vendored
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
dubbo:
|
||||||
|
registries:
|
||||||
|
demoZK:
|
||||||
|
protocol: zookeeper
|
||||||
|
address: zookeeper:2181
|
||||||
|
protocols:
|
||||||
|
triple:
|
||||||
|
name: tri
|
||||||
|
port: 20001
|
||||||
|
provider:
|
||||||
|
services:
|
||||||
|
AccountProvider:
|
||||||
|
interface: com.fontree.microservices.common.Account # must be compatible with grpc or dubbo-java
|
||||||
|
auth: "true"
|
||||||
|
filter: echo,metrics,token,accesslog,tps,generic_service,execute,pshutdown,auth,fonValidateFilter
|
||||||
|
params:
|
||||||
|
.accessKeyId: "Accountksl"
|
||||||
|
.secretAccessKey: "BSDY-FDF1-Fontree_account"
|
||||||
|
CoinProvider:
|
||||||
|
interface: com.fontree.microservices.common.coin # must be compatible with grpc or dubbo-java
|
||||||
|
auth: "true"
|
||||||
|
filter: echo,metrics,token,accesslog,tps,generic_service,execute,pshutdown,auth,fonValidateFilter
|
||||||
|
params:
|
||||||
|
.accessKeyId: "Accountksl"
|
||||||
|
.secretAccessKey: "BSDY-FDF1-Fontree_account"
|
||||||
|
|
||||||
|
logger:
|
||||||
|
lumberjack-config:
|
||||||
|
filename: logs.log
|
||||||
|
maxsize: 1
|
||||||
|
maxage: 3
|
||||||
|
maxbackups: 5
|
||||||
|
localtime: true
|
||||||
|
compress: true
|
46
docs/env/ali/log.yaml
vendored
Normal file
46
docs/env/ali/log.yaml
vendored
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
logger:
|
||||||
|
zap-config:
|
||||||
|
level: info # 日志级别
|
||||||
|
development: false
|
||||||
|
disableCaller: false
|
||||||
|
disableStacktrace: false
|
||||||
|
encoding: "json"
|
||||||
|
# zap encoder 配置
|
||||||
|
encoderConfig:
|
||||||
|
messageKey: "message"
|
||||||
|
levelKey: "level"
|
||||||
|
timeKey: "time"
|
||||||
|
nameKey: "logger"
|
||||||
|
callerKey: "caller"
|
||||||
|
stacktraceKey: "stacktrace"
|
||||||
|
lineEnding: ""
|
||||||
|
levelEncoder: "capital"
|
||||||
|
timeEncoder: "iso8601"
|
||||||
|
durationEncoder: "seconds"
|
||||||
|
callerEncoder: "short"
|
||||||
|
nameEncoder: ""
|
||||||
|
EncodeDuration: zapcore.SecondsDurationEncoder,
|
||||||
|
params:
|
||||||
|
service: "my-service"
|
||||||
|
version: "1.0.0"
|
||||||
|
outputPaths:
|
||||||
|
- "stderr"
|
||||||
|
initialFields:
|
||||||
|
app: "account"
|
||||||
|
errorOutputPaths:
|
||||||
|
- "stderr"
|
||||||
|
lumberjack-config:
|
||||||
|
# 写日志的文件名称
|
||||||
|
filename: "logs/main.log"
|
||||||
|
# 每个日志文件长度的最大大小,单位是 MiB。默认 100MiB
|
||||||
|
maxSize: 10
|
||||||
|
# 日志保留的最大天数(只保留最近多少天的日志)
|
||||||
|
maxAge: 15
|
||||||
|
# 只保留最近多少个日志文件,用于控制程序总日志的大小
|
||||||
|
maxBackups: 10
|
||||||
|
# 是否使用本地时间,默认使用 UTC 时间
|
||||||
|
localTime: true
|
||||||
|
# 是否压缩日志文件,压缩方法 gzip
|
||||||
|
compress: false
|
||||||
|
CallerSkip: 4
|
||||||
|
|
18
docs/env/ali/sdk.yaml
vendored
Normal file
18
docs/env/ali/sdk.yaml
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# endorseService Info
|
||||||
|
# testNet addrs
|
||||||
|
# endorseServiceHost: "120.48.24.223:37101"
|
||||||
|
endorseServiceHost: "127.0.0.1:37101"
|
||||||
|
complianceCheck:
|
||||||
|
# 是否需要进行合规性背书
|
||||||
|
isNeedComplianceCheck: false
|
||||||
|
# 是否需要支付合规性背书费用
|
||||||
|
isNeedComplianceCheckFee: false
|
||||||
|
# 合规性背书费用
|
||||||
|
complianceCheckEndorseServiceFee: 400
|
||||||
|
# 支付合规性背书费用的收款地址
|
||||||
|
complianceCheckEndorseServiceFeeAddr: WwLgfAatHyKx2mCJruRaML4oVf7Chzp42
|
||||||
|
# 如果通过合规性检查,签发认证签名的地址
|
||||||
|
complianceCheckEndorseServiceAddr: WwLgfAatHyKx2mCJruRaML4oVf7Chzp42
|
||||||
|
#创建平行链所需要的最低费用
|
||||||
|
minNewChainAmount: "100"
|
||||||
|
crypto: "xchain"
|
37
docs/env/dev/conf.ini
vendored
Normal file
37
docs/env/dev/conf.ini
vendored
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
[system]
|
||||||
|
Mode = "dev"
|
||||||
|
Version = "1.0.2"
|
||||||
|
|
||||||
|
|
||||||
|
[mail]
|
||||||
|
IsProd = false
|
||||||
|
Username = "postmaster@fontree.cn"
|
||||||
|
Password = "Zaq12wsx"
|
||||||
|
Domain = "fontree.cn"
|
||||||
|
|
||||||
|
[mysql]
|
||||||
|
Db = "mysql"
|
||||||
|
DbHost = "172.16.100.30"
|
||||||
|
DbPort = "3306"
|
||||||
|
DbUser = "root"
|
||||||
|
DbPassWord = "IhQmhg8HZjDmU=Ove5PnA^D"
|
||||||
|
DbName = "fontree-account"
|
||||||
|
|
||||||
|
[redis]
|
||||||
|
RedisDB = "1"
|
||||||
|
RedisAddr = "172.16.100.114:6379"
|
||||||
|
RedisPW = "kP6tW4tS3qB2dW4aE6uI5cX2"
|
||||||
|
RedisDBNAme = "1"
|
||||||
|
|
||||||
|
[chain]
|
||||||
|
IP="127.0.0.1:37101"
|
||||||
|
MnemonicWords="知 睡 迷 纤 纲 耀 镜 婆 渡 考 拔 百"
|
||||||
|
ContractAccount="XC8214684261867838@xuper"
|
||||||
|
ContractName="fp001"
|
||||||
|
ContractType="wasm"
|
||||||
|
|
||||||
|
[mobile]
|
||||||
|
URL="https://api.4321.sh/sms/template"
|
||||||
|
AK="N7469940cf"
|
||||||
|
SK="74699ca8e1ea8f80"
|
||||||
|
DingDingKey="1a4e4b18d9aa35368450c980ceb8def2f11fa0ebb2dc0a3cfd970cd3b8efc6fb"
|
34
docs/env/dev/dubbogo.yaml
vendored
Normal file
34
docs/env/dev/dubbogo.yaml
vendored
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
dubbo:
|
||||||
|
registries:
|
||||||
|
demoZK:
|
||||||
|
protocol: zookeeper
|
||||||
|
address: 172.16.100.93:2181
|
||||||
|
protocols:
|
||||||
|
triple:
|
||||||
|
name: tri
|
||||||
|
port: 20001
|
||||||
|
provider:
|
||||||
|
services:
|
||||||
|
AccountProvider:
|
||||||
|
interface: com.fontree.microservices.common.Account # must be compatible with grpc or dubbo-java
|
||||||
|
auth: "true"
|
||||||
|
filter: echo,metrics,token,accesslog,sign,tps,generic_service,execute,pshutdown,auth,fonValidateFilter
|
||||||
|
params:
|
||||||
|
.accessKeyId: "Accountksl"
|
||||||
|
.secretAccessKey: "BSDY-FDF1-Fontree_account"
|
||||||
|
CoinProvider:
|
||||||
|
interface: com.fontree.microservices.common.coin # must be compatible with grpc or dubbo-java
|
||||||
|
auth: "true"
|
||||||
|
filter: echo,metrics,token,accesslog,tps,generic_service,execute,pshutdown,auth,fonValidateFilter
|
||||||
|
params:
|
||||||
|
.accessKeyId: "Accountksl"
|
||||||
|
.secretAccessKey: "BSDY-FDF1-Fontree_account"
|
||||||
|
|
||||||
|
# logger:
|
||||||
|
# lumberjack-config:
|
||||||
|
# filename: logs.log
|
||||||
|
# maxsize: 1
|
||||||
|
# maxage: 3
|
||||||
|
# maxbackups: 5
|
||||||
|
# localtime: true
|
||||||
|
# compress: true
|
32
docs/env/dev/log.yaml
vendored
Normal file
32
docs/env/dev/log.yaml
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
logger:
|
||||||
|
CallerSkip: 4
|
||||||
|
zap-config:
|
||||||
|
level: info # 日志级别
|
||||||
|
development: false
|
||||||
|
disableCaller: false
|
||||||
|
disableStacktrace: false
|
||||||
|
encoding: "console"
|
||||||
|
# zap encoder 配置
|
||||||
|
encoderConfig:
|
||||||
|
messageKey: "message"
|
||||||
|
levelKey: "level"
|
||||||
|
timeKey: "time"
|
||||||
|
nameKey: "logger"
|
||||||
|
callerKey: "caller"
|
||||||
|
stacktraceKey: "stacktrace"
|
||||||
|
lineEnding: ""
|
||||||
|
levelEncoder: "capitalColor"
|
||||||
|
timeEncoder: "iso8601"
|
||||||
|
durationEncoder: "seconds"
|
||||||
|
callerEncoder: "short"
|
||||||
|
nameEncoder: ""
|
||||||
|
EncodeDuration: zapcore.SecondsDurationEncoder,
|
||||||
|
params:
|
||||||
|
service: "my-service"
|
||||||
|
version: "1.0.0"
|
||||||
|
outputPaths:
|
||||||
|
- "stderr"
|
||||||
|
initialFields:
|
||||||
|
app: "account"
|
||||||
|
errorOutputPaths:
|
||||||
|
- "stderr"
|
18
docs/env/dev/sdk.yaml
vendored
Normal file
18
docs/env/dev/sdk.yaml
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# endorseService Info
|
||||||
|
# testNet addrs
|
||||||
|
# endorseServiceHost: "120.48.24.223:37101"
|
||||||
|
endorseServiceHost: "127.0.0.1:37101"
|
||||||
|
complianceCheck:
|
||||||
|
# 是否需要进行合规性背书
|
||||||
|
isNeedComplianceCheck: false
|
||||||
|
# 是否需要支付合规性背书费用
|
||||||
|
isNeedComplianceCheckFee: false
|
||||||
|
# 合规性背书费用
|
||||||
|
complianceCheckEndorseServiceFee: 400
|
||||||
|
# 支付合规性背书费用的收款地址
|
||||||
|
complianceCheckEndorseServiceFeeAddr: WwLgfAatHyKx2mCJruRaML4oVf7Chzp42
|
||||||
|
# 如果通过合规性检查,签发认证签名的地址
|
||||||
|
complianceCheckEndorseServiceAddr: WwLgfAatHyKx2mCJruRaML4oVf7Chzp42
|
||||||
|
#创建平行链所需要的最低费用
|
||||||
|
minNewChainAmount: "100"
|
||||||
|
crypto: "xchain"
|
29
docs/env/local/conf.ini
vendored
Normal file
29
docs/env/local/conf.ini
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
[system]
|
||||||
|
Mode = "dev"
|
||||||
|
Version = "1.0.1"
|
||||||
|
|
||||||
|
[mysql]
|
||||||
|
Db = "mysql"
|
||||||
|
DbHost = "127.0.0.1"
|
||||||
|
DbPort = "3306"
|
||||||
|
DbUser = "root"
|
||||||
|
DbPassWord = "123456"
|
||||||
|
DbName = "fontree-account-v2"
|
||||||
|
|
||||||
|
[redis]
|
||||||
|
RedisDB = "2"
|
||||||
|
RedisAddr = "127.0.0.1:6379"
|
||||||
|
RedisPW = ""
|
||||||
|
RedisDBNAme = "2"
|
||||||
|
|
||||||
|
[chain]
|
||||||
|
IP="127.0.0.1:37101"
|
||||||
|
MnemonicWords="知 睡 迷 纤 纲 耀 镜 婆 渡 考 拔 百"
|
||||||
|
ContractAccount="XC8214684261867838@xuper"
|
||||||
|
ContractName="fp001"
|
||||||
|
ContractType="wasm"
|
||||||
|
|
||||||
|
[mobile]
|
||||||
|
URL="https://api.4321.sh/sms/template"
|
||||||
|
AK="N7469940cf"
|
||||||
|
SK="74699ca8e1ea8f80"
|
34
docs/env/local/dubbogo.yaml
vendored
Normal file
34
docs/env/local/dubbogo.yaml
vendored
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
dubbo:
|
||||||
|
registries:
|
||||||
|
demoZK:
|
||||||
|
protocol: zookeeper
|
||||||
|
address: 127.0.0.1:2181
|
||||||
|
protocols:
|
||||||
|
triple:
|
||||||
|
name: tri
|
||||||
|
port: 20000
|
||||||
|
provider:
|
||||||
|
services:
|
||||||
|
AccountProvider:
|
||||||
|
interface: com.fontree.microservices.common.Account # must be compatible with grpc or dubbo-java
|
||||||
|
auth: "true"
|
||||||
|
filter: echo,metrics,token,accesslog,tps,generic_service,execute,pshutdown,auth,fonValidateFilter
|
||||||
|
params:
|
||||||
|
.accessKeyId: "Accountksl"
|
||||||
|
.secretAccessKey: "BSDY-FDF1-Fontree_account"
|
||||||
|
CoinProvider:
|
||||||
|
interface: com.fontree.microservices.common.coin # must be compatible with grpc or dubbo-java
|
||||||
|
auth: "true"
|
||||||
|
filter: echo,metrics,token,accesslog,tps,generic_service,execute,pshutdown,auth,fonValidateFilter
|
||||||
|
params:
|
||||||
|
.accessKeyId: "Accountksl"
|
||||||
|
.secretAccessKey: "BSDY-FDF1-Fontree_account"
|
||||||
|
|
||||||
|
# logger:
|
||||||
|
# lumberjack-config:
|
||||||
|
# filename: logs.log
|
||||||
|
# maxsize: 1
|
||||||
|
# maxage: 3
|
||||||
|
# maxbackups: 5
|
||||||
|
# localtime: true
|
||||||
|
# compress: true
|
32
docs/env/local/log.yaml
vendored
Normal file
32
docs/env/local/log.yaml
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
logger:
|
||||||
|
CallerSkip: 4
|
||||||
|
zap-config:
|
||||||
|
level: info # 日志级别
|
||||||
|
development: false
|
||||||
|
disableCaller: false
|
||||||
|
disableStacktrace: false
|
||||||
|
encoding: "console"
|
||||||
|
# zap encoder 配置
|
||||||
|
encoderConfig:
|
||||||
|
messageKey: "message"
|
||||||
|
levelKey: "level"
|
||||||
|
timeKey: "time"
|
||||||
|
nameKey: "logger"
|
||||||
|
callerKey: "caller"
|
||||||
|
stacktraceKey: "stacktrace"
|
||||||
|
lineEnding: ""
|
||||||
|
levelEncoder: "capitalColor"
|
||||||
|
timeEncoder: "iso8601"
|
||||||
|
durationEncoder: "seconds"
|
||||||
|
callerEncoder: "short"
|
||||||
|
nameEncoder: ""
|
||||||
|
EncodeDuration: zapcore.SecondsDurationEncoder,
|
||||||
|
params:
|
||||||
|
service: "my-service"
|
||||||
|
version: "1.0.0"
|
||||||
|
outputPaths:
|
||||||
|
- "stderr"
|
||||||
|
initialFields:
|
||||||
|
app: "account"
|
||||||
|
errorOutputPaths:
|
||||||
|
- "stderr"
|
18
docs/env/local/sdk.yaml
vendored
Normal file
18
docs/env/local/sdk.yaml
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# endorseService Info
|
||||||
|
# testNet addrs
|
||||||
|
# endorseServiceHost: "120.48.24.223:37101"
|
||||||
|
endorseServiceHost: "127.0.0.1:37101"
|
||||||
|
complianceCheck:
|
||||||
|
# 是否需要进行合规性背书
|
||||||
|
isNeedComplianceCheck: false
|
||||||
|
# 是否需要支付合规性背书费用
|
||||||
|
isNeedComplianceCheckFee: false
|
||||||
|
# 合规性背书费用
|
||||||
|
complianceCheckEndorseServiceFee: 400
|
||||||
|
# 支付合规性背书费用的收款地址
|
||||||
|
complianceCheckEndorseServiceFeeAddr: WwLgfAatHyKx2mCJruRaML4oVf7Chzp42
|
||||||
|
# 如果通过合规性检查,签发认证签名的地址
|
||||||
|
complianceCheckEndorseServiceAddr: WwLgfAatHyKx2mCJruRaML4oVf7Chzp42
|
||||||
|
#创建平行链所需要的最低费用
|
||||||
|
minNewChainAmount: "100"
|
||||||
|
crypto: "xchain"
|
223
go.mod
Normal file
223
go.mod
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
module github.com/fonchain_enterprise/micro-account
|
||||||
|
|
||||||
|
go 1.18
|
||||||
|
|
||||||
|
replace (
|
||||||
|
github.com/fonchain_enterprise/utils/aes => ../utils/aes
|
||||||
|
github.com/fonchain_enterprise/utils/baidu => ../utils/baidu
|
||||||
|
github.com/fonchain_enterprise/utils/chain => ../utils/chain
|
||||||
|
github.com/fonchain_enterprise/utils/feie => ../utils/feie
|
||||||
|
github.com/fonchain_enterprise/utils/jwt => ../utils/jwt
|
||||||
|
github.com/fonchain_enterprise/utils/mobile => ../utils/mobile
|
||||||
|
github.com/fonchain_enterprise/utils/rand => ../utils/rand
|
||||||
|
github.com/fonchain_enterprise/utils/zap_log => ../utils/zap_log
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
dubbo.apache.org/dubbo-go/v3 v3.0.2
|
||||||
|
github.com/BurntSushi/toml v1.3.2
|
||||||
|
github.com/PuerkitoBio/goquery v1.8.1
|
||||||
|
github.com/alibaba/sentinel-golang v1.0.4
|
||||||
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||||
|
github.com/dubbogo/grpc-go v1.42.9
|
||||||
|
github.com/dubbogo/triple v1.1.8
|
||||||
|
github.com/fonchain_enterprise/utils/aes v0.0.0-00010101000000-000000000000
|
||||||
|
github.com/fonchain_enterprise/utils/baidu v0.0.0-00010101000000-000000000000
|
||||||
|
github.com/fonchain_enterprise/utils/chain v0.0.0-00010101000000-000000000000
|
||||||
|
github.com/fonchain_enterprise/utils/feie v0.0.0-00010101000000-000000000000
|
||||||
|
github.com/fonchain_enterprise/utils/mobile v0.0.0-00010101000000-000000000000
|
||||||
|
github.com/fonchain_enterprise/utils/rand v0.0.0-00010101000000-000000000000
|
||||||
|
github.com/fonchain_enterprise/utils/zap_log v0.0.0-00010101000000-000000000000
|
||||||
|
github.com/go-redis/redis v6.15.9+incompatible
|
||||||
|
github.com/golang/protobuf v1.5.2
|
||||||
|
github.com/google/uuid v1.3.0
|
||||||
|
github.com/mozillazg/go-pinyin v0.20.0
|
||||||
|
github.com/mwitkow/go-proto-validators v0.3.2
|
||||||
|
github.com/nacos-group/nacos-sdk-go v1.1.1
|
||||||
|
github.com/natefinch/lumberjack v2.0.0+incompatible
|
||||||
|
github.com/pkg/errors v0.9.1
|
||||||
|
github.com/shopspring/decimal v1.4.0
|
||||||
|
go.uber.org/zap v1.21.0
|
||||||
|
golang.org/x/crypto v0.10.0
|
||||||
|
golang.org/x/text v0.10.0
|
||||||
|
google.golang.org/protobuf v1.28.0
|
||||||
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
|
gorm.io/driver/mysql v1.3.5
|
||||||
|
gorm.io/gorm v1.25.5
|
||||||
|
gorm.io/plugin/soft_delete v1.2.0
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
cloud.google.com/go v0.65.0 // indirect
|
||||||
|
contrib.go.opencensus.io/exporter/prometheus v0.4.1 // indirect
|
||||||
|
github.com/ChainSafe/go-schnorrkel v0.0.0-20200626160457-b38283118816 // indirect
|
||||||
|
github.com/RoaringBitmap/roaring v1.1.0 // indirect
|
||||||
|
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect
|
||||||
|
github.com/Workiva/go-datastructures v1.0.52 // indirect
|
||||||
|
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 // indirect
|
||||||
|
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.4 // indirect
|
||||||
|
github.com/alibabacloud-go/darabonba-openapi v0.2.1 // indirect
|
||||||
|
github.com/alibabacloud-go/debug v0.0.0-20190504072949-9472017b5c68 // indirect
|
||||||
|
github.com/alibabacloud-go/dysmsapi-20170525/v2 v2.0.18 // indirect
|
||||||
|
github.com/alibabacloud-go/endpoint-util v1.1.0 // indirect
|
||||||
|
github.com/alibabacloud-go/openapi-util v0.0.11 // indirect
|
||||||
|
github.com/alibabacloud-go/tea v1.2.1 // indirect
|
||||||
|
github.com/alibabacloud-go/tea-console v1.0.0 // indirect
|
||||||
|
github.com/alibabacloud-go/tea-utils v1.4.5 // indirect
|
||||||
|
github.com/alibabacloud-go/tea-xml v1.1.2 // indirect
|
||||||
|
github.com/aliyun/alibaba-cloud-sdk-go v1.61.18 // indirect
|
||||||
|
github.com/aliyun/credentials-go v1.1.2 // indirect
|
||||||
|
github.com/andybalholm/cascadia v1.3.1 // indirect
|
||||||
|
github.com/apache/dubbo-getty v1.4.8 // indirect
|
||||||
|
github.com/apache/dubbo-go-hessian2 v1.11.0 // indirect
|
||||||
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
|
github.com/bits-and-blooms/bitset v1.2.0 // indirect
|
||||||
|
github.com/btcsuite/btcd v0.20.1-beta // indirect
|
||||||
|
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d // indirect
|
||||||
|
github.com/buger/jsonparser v1.1.1 // indirect
|
||||||
|
github.com/census-instrumentation/opencensus-proto v0.2.1 // indirect
|
||||||
|
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||||
|
github.com/clbanning/mxj/v2 v2.5.6 // indirect
|
||||||
|
github.com/cloudflare/bn256 v0.0.0-20200818021822-8aba7cd1ae4c // indirect
|
||||||
|
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4 // indirect
|
||||||
|
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1 // indirect
|
||||||
|
github.com/consensys/gnark v0.2.1-alpha // indirect
|
||||||
|
github.com/consensys/gurvy v0.1.2-0.20200512111154-1662e289e29b // indirect
|
||||||
|
github.com/coreos/go-semver v0.3.0 // indirect
|
||||||
|
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
|
||||||
|
github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d // indirect
|
||||||
|
github.com/creasty/defaults v1.5.2 // indirect
|
||||||
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/dubbogo/go-zookeeper v1.0.4-0.20211212162352-f9d2183d89d5 // indirect
|
||||||
|
github.com/dubbogo/gost v1.11.25 // indirect
|
||||||
|
github.com/emicklei/go-restful/v3 v3.7.4 // indirect
|
||||||
|
github.com/emirpasic/gods v1.12.1-0.20201118132343-79df803e554c // indirect
|
||||||
|
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1 // indirect
|
||||||
|
github.com/envoyproxy/protoc-gen-validate v0.1.0 // indirect
|
||||||
|
github.com/fsnotify/fsnotify v1.5.4 // indirect
|
||||||
|
github.com/ghodss/yaml v1.0.0 // indirect
|
||||||
|
github.com/go-co-op/gocron v1.9.0 // indirect
|
||||||
|
github.com/go-errors/errors v1.0.1 // indirect
|
||||||
|
github.com/go-kit/kit v0.10.0 // indirect
|
||||||
|
github.com/go-kit/log v0.1.0 // indirect
|
||||||
|
github.com/go-logfmt/logfmt v0.5.0 // indirect
|
||||||
|
github.com/go-logr/logr v1.2.3 // indirect
|
||||||
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
|
github.com/go-ole/go-ole v1.2.4 // indirect
|
||||||
|
github.com/go-playground/locales v0.14.0 // indirect
|
||||||
|
github.com/go-playground/universal-translator v0.18.0 // indirect
|
||||||
|
github.com/go-playground/validator/v10 v10.11.0 // indirect
|
||||||
|
github.com/go-resty/resty/v2 v2.7.0 // indirect
|
||||||
|
github.com/go-sql-driver/mysql v1.6.0 // indirect
|
||||||
|
github.com/go-stack/stack v1.8.0 // indirect
|
||||||
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||||
|
github.com/golang/mock v1.5.0 // indirect
|
||||||
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
|
github.com/gorilla/websocket v1.4.2 // indirect
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
|
||||||
|
github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 // indirect
|
||||||
|
github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f // indirect
|
||||||
|
github.com/gtank/ristretto255 v0.1.2 // indirect
|
||||||
|
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||||
|
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||||
|
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||||
|
github.com/hashicorp/vault/sdk v0.3.0 // indirect
|
||||||
|
github.com/hyperledger/burrow v0.30.5 // indirect
|
||||||
|
github.com/ipfs/go-cid v0.0.7 // indirect
|
||||||
|
github.com/ipfs/go-ipfs-addr v0.0.1 // indirect
|
||||||
|
github.com/ipfs/go-log v1.0.4 // indirect
|
||||||
|
github.com/ipfs/go-log/v2 v2.1.1 // indirect
|
||||||
|
github.com/jinzhu/copier v0.3.5 // indirect
|
||||||
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
|
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||||
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
|
github.com/k0kubun/pp v3.0.1+incompatible // indirect
|
||||||
|
github.com/knadh/koanf v1.4.1 // indirect
|
||||||
|
github.com/leodido/go-urn v1.2.1 // indirect
|
||||||
|
github.com/libp2p/go-buffer-pool v0.0.2 // indirect
|
||||||
|
github.com/libp2p/go-libp2p-core v0.6.1 // indirect
|
||||||
|
github.com/libp2p/go-libp2p-crypto v0.1.0 // indirect
|
||||||
|
github.com/libp2p/go-libp2p-peer v0.2.0 // indirect
|
||||||
|
github.com/libp2p/go-openssl v0.0.7 // indirect
|
||||||
|
github.com/magiconair/properties v1.8.6 // indirect
|
||||||
|
github.com/mattn/go-colorable v0.1.7 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||||
|
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
||||||
|
github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 // indirect
|
||||||
|
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect
|
||||||
|
github.com/minio/sha256-simd v0.1.1 // indirect
|
||||||
|
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||||
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
|
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
|
github.com/mr-tron/base58 v1.2.0 // indirect
|
||||||
|
github.com/mschoch/smat v0.2.0 // indirect
|
||||||
|
github.com/multiformats/go-base32 v0.0.3 // indirect
|
||||||
|
github.com/multiformats/go-base36 v0.1.0 // indirect
|
||||||
|
github.com/multiformats/go-multiaddr v0.3.1 // indirect
|
||||||
|
github.com/multiformats/go-multibase v0.0.3 // indirect
|
||||||
|
github.com/multiformats/go-multihash v0.0.14 // indirect
|
||||||
|
github.com/multiformats/go-varint v0.0.6 // indirect
|
||||||
|
github.com/opentracing/opentracing-go v1.2.0 // indirect
|
||||||
|
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||||||
|
github.com/pelletier/go-toml v1.7.0 // indirect
|
||||||
|
github.com/pierrec/lz4 v2.5.2+incompatible // indirect
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
github.com/polarismesh/polaris-go v1.1.0 // indirect
|
||||||
|
github.com/prometheus/client_golang v1.12.2 // indirect
|
||||||
|
github.com/prometheus/client_model v0.2.0 // indirect
|
||||||
|
github.com/prometheus/common v0.32.1 // indirect
|
||||||
|
github.com/prometheus/procfs v0.7.3 // indirect
|
||||||
|
github.com/prometheus/statsd_exporter v0.21.0 // indirect
|
||||||
|
github.com/robfig/cron/v3 v3.0.1 // indirect
|
||||||
|
github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b // indirect
|
||||||
|
github.com/shirou/gopsutil v3.20.11+incompatible // indirect
|
||||||
|
github.com/shirou/gopsutil/v3 v3.21.6 // indirect
|
||||||
|
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect
|
||||||
|
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||||
|
github.com/spf13/afero v1.2.2 // indirect
|
||||||
|
github.com/spf13/cast v1.3.0 // indirect
|
||||||
|
github.com/spf13/jwalterweatherman v1.0.0 // indirect
|
||||||
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
|
github.com/spf13/viper v1.7.1 // indirect
|
||||||
|
github.com/stretchr/testify v1.8.1 // indirect
|
||||||
|
github.com/subosito/gotenv v1.2.0 // indirect
|
||||||
|
github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca // indirect
|
||||||
|
github.com/tendermint/go-amino v0.14.1 // indirect
|
||||||
|
github.com/tendermint/tendermint v0.33.1 // indirect
|
||||||
|
github.com/tjfoc/gmsm v1.3.2 // indirect
|
||||||
|
github.com/tklauser/go-sysconf v0.3.6 // indirect
|
||||||
|
github.com/tklauser/numcpus v0.2.2 // indirect
|
||||||
|
github.com/tmthrgd/go-hex v0.0.0-20190303111820-0bdcb15db631 // indirect
|
||||||
|
github.com/uber/jaeger-client-go v2.29.1+incompatible // indirect
|
||||||
|
github.com/uber/jaeger-lib v2.4.1+incompatible // indirect
|
||||||
|
github.com/ugorji/go/codec v1.2.7 // indirect
|
||||||
|
github.com/xuperchain/crypto v0.0.0-20201028025054-4d560674bcd6 // indirect
|
||||||
|
github.com/xuperchain/log15 v0.0.0-20190620081506-bc88a9198230 // indirect
|
||||||
|
github.com/xuperchain/xuper-sdk-go/v2 v2.0.0 // indirect
|
||||||
|
github.com/xuperchain/xuperchain v0.0.0-20210708031936-951e4ade7bdd // indirect
|
||||||
|
github.com/xuperchain/xupercore v0.0.0-20210608021245-b15f81dd9ecf // indirect
|
||||||
|
github.com/zouyx/agollo/v3 v3.4.5 // indirect
|
||||||
|
go.etcd.io/etcd/api/v3 v3.5.4 // indirect
|
||||||
|
go.etcd.io/etcd/client/pkg/v3 v3.5.4 // indirect
|
||||||
|
go.etcd.io/etcd/client/v3 v3.5.4 // indirect
|
||||||
|
go.opencensus.io v0.23.0 // indirect
|
||||||
|
go.opentelemetry.io/otel v1.7.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/trace v1.7.0 // indirect
|
||||||
|
go.uber.org/atomic v1.9.0 // indirect
|
||||||
|
go.uber.org/multierr v1.6.0 // indirect
|
||||||
|
golang.org/x/net v0.11.0 // indirect
|
||||||
|
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
|
||||||
|
golang.org/x/sync v0.1.0 // indirect
|
||||||
|
golang.org/x/sys v0.9.0 // indirect
|
||||||
|
google.golang.org/appengine v1.6.6 // indirect
|
||||||
|
google.golang.org/genproto v0.0.0-20211104193956-4c6863e31247 // indirect
|
||||||
|
google.golang.org/grpc v1.47.0 // indirect
|
||||||
|
gopkg.in/ini.v1 v1.56.0 // indirect
|
||||||
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
)
|
1
pkg/application/coin.go
Normal file
1
pkg/application/coin.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package application
|
5
pkg/application/init.go
Normal file
5
pkg/application/init.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package application
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
|
||||||
|
}
|
255
pkg/application/order.go
Normal file
255
pkg/application/order.go
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
package application
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/api/account"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/cmd/config"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/cache"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/common/jwt"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/common/redis_key"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/common/utils"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/m"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/model"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Logout 登出
|
||||||
|
func Logout(in *account.DecryptJwtRequest, status uint8) error {
|
||||||
|
var loginLog *model.LoginLog
|
||||||
|
|
||||||
|
//解析token
|
||||||
|
claims, err := jwt.ParseToken(in.Token, m.JWTSecret)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
//删除token信息
|
||||||
|
tokenKey := redis_key.GetTokenInfo(in.Domain, in.Token)
|
||||||
|
fmt.Print("删除token", tokenKey)
|
||||||
|
if merr := cache.RedisClient.Del(tokenKey).Err(); merr != nil {
|
||||||
|
return merr
|
||||||
|
}
|
||||||
|
|
||||||
|
//记录token信息
|
||||||
|
if err := model.DB.Model(&model.LoginLog{}).Where(&model.LoginLog{Token: in.Token}).First(&loginLog).Error; err != nil {
|
||||||
|
loginLog = &model.LoginLog{
|
||||||
|
UserId: claims.ID,
|
||||||
|
Token: in.Token,
|
||||||
|
Status: status,
|
||||||
|
ExpireDate: time.Now().Format("2006-01-02 15:04:05"),
|
||||||
|
LastDate: time.Now().Format("2006-01-02 15:04:05"),
|
||||||
|
LogoutDate: time.Now().Format("2006-01-02 15:04:05"),
|
||||||
|
}
|
||||||
|
model.DB.Model(&model.LoginLog{}).Create(loginLog)
|
||||||
|
} else {
|
||||||
|
//不存在
|
||||||
|
updateLog := &model.LoginLog{
|
||||||
|
Status: status,
|
||||||
|
LogoutDate: time.Now().Format("2006-01-02 15:04:05"),
|
||||||
|
}
|
||||||
|
|
||||||
|
model.DB.Model(&model.LoginLog{}).Where(&model.LoginLog{ID: loginLog.ID}).Updates(&updateLog)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateLastDate 更新最新操作时间
|
||||||
|
func UpdateLastDate(token string) {
|
||||||
|
var loginLog *model.LoginLog
|
||||||
|
|
||||||
|
if err := model.DB.Model(&model.LoginLog{}).Where(&model.LoginLog{Token: token}).First(&loginLog).Error; err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
updateObj := &model.LoginLog{LastDate: time.Now().Format("2006-01-02 15:04:05")}
|
||||||
|
|
||||||
|
model.DB.Model(&model.LoginLog{}).Where(&model.LoginLog{Token: token}).Updates(updateObj)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// OffByLogId 踢下线
|
||||||
|
func OffByLogId(id uint64) error {
|
||||||
|
var loginLog *model.LoginLog
|
||||||
|
|
||||||
|
if err := model.DB.Model(&model.LoginLog{}).First(&loginLog, id).Error; err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
in := &account.DecryptJwtRequest{
|
||||||
|
Token: loginLog.Token,
|
||||||
|
Domain: *loginLog.Domain,
|
||||||
|
}
|
||||||
|
|
||||||
|
return Logout(in, model.Status_Off)
|
||||||
|
}
|
||||||
|
|
||||||
|
func OnlineLogById(id uint64) (*account.LoginLog, error) {
|
||||||
|
var log *model.LoginLog
|
||||||
|
|
||||||
|
//失效时间大于当前时间
|
||||||
|
if err := model.DB.Model(&model.LoginLog{}).
|
||||||
|
First(&log, id).Error; err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
res := &account.LoginLog{
|
||||||
|
ID: uint64(log.ID),
|
||||||
|
UserId: uint64(log.UserId),
|
||||||
|
Ip: log.Ip,
|
||||||
|
Status: uint64(log.Status),
|
||||||
|
ExpireDate: log.ExpireDate,
|
||||||
|
LastDate: log.LastDate,
|
||||||
|
LogoutDate: log.LogoutDate,
|
||||||
|
Address: log.Address,
|
||||||
|
CreatedAt: log.CreatedAt.Format("2006-01-02 15:04:05"),
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// OnlineLogList 获取用户当前的在线记录
|
||||||
|
func OnlineLogList(in *account.LoginInfosByUserIdRequest) []*account.LoginLog {
|
||||||
|
var loginLogs []*model.LoginLog
|
||||||
|
var logs []*account.LoginLog
|
||||||
|
|
||||||
|
//失效时间大于当前时间
|
||||||
|
model.DB.Model(&model.LoginLog{}).
|
||||||
|
Where(&model.LoginLog{UserId: uint(in.UserId), Status: model.Status_In}).
|
||||||
|
Where("expire_date > ?", time.Now().Format("2006-01-02 15:04:05")).
|
||||||
|
Find(&loginLogs)
|
||||||
|
|
||||||
|
for _, t := range loginLogs {
|
||||||
|
|
||||||
|
temp := &account.LoginLog{
|
||||||
|
ID: uint64(t.ID),
|
||||||
|
UserId: uint64(t.UserId),
|
||||||
|
Ip: t.Ip,
|
||||||
|
//Token: t.Token,
|
||||||
|
Status: uint64(t.Status),
|
||||||
|
ExpireDate: t.ExpireDate,
|
||||||
|
LastDate: t.LastDate,
|
||||||
|
LogoutDate: t.LogoutDate,
|
||||||
|
}
|
||||||
|
|
||||||
|
logs = append(logs, temp)
|
||||||
|
}
|
||||||
|
|
||||||
|
return logs
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSampleAddress 获取用户当前的在线记录
|
||||||
|
func IsSampleAddress(nowIp string, userId uint64) (bool, error) {
|
||||||
|
var loginLog *model.LoginLog
|
||||||
|
|
||||||
|
if config.AppConfig.System.Mode == "dev" {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//失效时间大于当前时间
|
||||||
|
if err := model.DB.Model(&model.LoginLog{}).
|
||||||
|
Where(&model.LoginLog{UserId: uint(userId)}).
|
||||||
|
Where("status in (?)", []uint8{model.Status_In, model.Status_Out}).
|
||||||
|
Order("id desc").
|
||||||
|
First(&loginLog).Error; err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if loginLog.Ip == nowIp { //两个ip一样直接退出
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
location, err1 := utils.AliIpAddress(loginLog.Ip)
|
||||||
|
nowLocation, err2 := utils.AliIpAddress(nowIp)
|
||||||
|
|
||||||
|
fmt.Println("查询ip地址:", err1, err2, location, nowIp, nowLocation)
|
||||||
|
if err1 == nil && err2 == nil {
|
||||||
|
if location == nowLocation {
|
||||||
|
return true, nil
|
||||||
|
} else {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetIpAddressByIp 根据ip获取时间
|
||||||
|
func GetIpAddressByIp(nowIp string) string {
|
||||||
|
|
||||||
|
tempKey := redis_key.GetIpAddressKey(nowIp)
|
||||||
|
cache.RedisClient.Get(redis_key.GetIpAddressKey(nowIp))
|
||||||
|
val, _ := cache.RedisClient.Get(tempKey).Result()
|
||||||
|
|
||||||
|
if val != "" {
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
if err == redis.Nil {
|
||||||
|
fmt.Println("键 'mykey' 不存在")
|
||||||
|
} else if err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
fmt.Println("键 'mykey' 的值为:", val)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
location, _ := utils.AliIpAddress(nowIp)
|
||||||
|
|
||||||
|
cache.RedisClient.Set(tempKey, location, 3*24*time.Hour)
|
||||||
|
|
||||||
|
return location
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsPublicIp(ipString string) bool {
|
||||||
|
|
||||||
|
ip := net.ParseIP(ipString)
|
||||||
|
if ip == nil {
|
||||||
|
fmt.Println("Invalid IP")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if ip.IsLoopback() {
|
||||||
|
fmt.Println("Loopback IP")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if ip.To4() != nil {
|
||||||
|
if ip[0] == 10 {
|
||||||
|
fmt.Println("Private network IP")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if ip[0] == 172 && (ip[1]&0xf0) == 16 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if ip[0] == 192 && ip[1] == 168 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAddressByID(domain string, userId uint64) string {
|
||||||
|
var loginLog *model.LoginLog
|
||||||
|
|
||||||
|
//失效时间大于当前时间
|
||||||
|
if err := model.DB.Model(&model.LoginLog{}).
|
||||||
|
Where(&model.LoginLog{UserId: uint(userId), Domain: &domain}).
|
||||||
|
Where("status in (?)", []uint8{model.Status_In, model.Status_Out}).
|
||||||
|
Order("id desc").
|
||||||
|
First(&loginLog).Error; err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return loginLog.Address
|
||||||
|
}
|
36
pkg/application/order_test.go
Normal file
36
pkg/application/order_test.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package application
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/cache"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetIpAddressByIp2(t *testing.T) {
|
||||||
|
config := cache.RedisConfig{
|
||||||
|
RedisDB: "2",
|
||||||
|
RedisAddr: "127.0.0.1:6379",
|
||||||
|
RedisPw: "",
|
||||||
|
RedisDbName: "2",
|
||||||
|
}
|
||||||
|
|
||||||
|
cache.LoadRedis(config)
|
||||||
|
|
||||||
|
type args struct {
|
||||||
|
nowIp string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{args: args{nowIp: "58.210.42.242"}},
|
||||||
|
// TODO: Add test cases.
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if got := GetIpAddressByIp(tt.args.nowIp); got != tt.want {
|
||||||
|
t.Errorf("GetIpAddressByIp() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
58
pkg/application/token.go
Normal file
58
pkg/application/token.go
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
package application
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/m"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/model"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddRefreshToken 签发refreshtoken记录
|
||||||
|
func AddRefreshToken(token string) error {
|
||||||
|
|
||||||
|
var count int64
|
||||||
|
model.DB.Model(&model.RefreshToken{}).Where(&model.RefreshToken{RefreshToken: token}).Count(&count)
|
||||||
|
|
||||||
|
if count > 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//记录登录信息
|
||||||
|
refreshToken := &model.RefreshToken{
|
||||||
|
RefreshToken: token,
|
||||||
|
UseNum: 0,
|
||||||
|
LastUseDate: time.Now().Format("2006-01-02 15:04:05"),
|
||||||
|
IsForbid: model.IsForBid_No,
|
||||||
|
ExpireDate: time.Now().Add(time.Duration(m.RefreshTokenTime) * time.Hour).Format("2006-01-02 15:04:05"), //过期时间
|
||||||
|
}
|
||||||
|
|
||||||
|
return model.DB.Create(&refreshToken).Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func CheckRefreshToke(token string) error {
|
||||||
|
var refrshTokenObj *model.RefreshToken
|
||||||
|
|
||||||
|
if err := model.DB.Model(&model.RefreshToken{}).Where(&model.RefreshToken{RefreshToken: token}).First(&refrshTokenObj).Error; err != nil {
|
||||||
|
if err == gorm.ErrRecordNotFound {
|
||||||
|
return errors.New("this refresh_token is not exist")
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if refrshTokenObj.IsForbid == model.IsForBid_Yes {
|
||||||
|
return errors.New("this refresh_token is forbidden")
|
||||||
|
}
|
||||||
|
|
||||||
|
if refrshTokenObj.UseNum > 0 {
|
||||||
|
return errors.New("this refresh_token is used")
|
||||||
|
}
|
||||||
|
|
||||||
|
//记录登录信息
|
||||||
|
updateLog := &model.RefreshToken{
|
||||||
|
UseNum: refrshTokenObj.UseNum + 1,
|
||||||
|
LastUseDate: time.Now().Format("2006-01-02 15:04:05"),
|
||||||
|
}
|
||||||
|
|
||||||
|
return model.DB.Model(&model.RefreshToken{}).Where(&model.RefreshToken{ID: refrshTokenObj.ID}).Updates(&updateLog).Error
|
||||||
|
}
|
145
pkg/application/user.go
Normal file
145
pkg/application/user.go
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
package application
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/api/account"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/m"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
authDb = "fontree-auth_v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
func List(in *account.ListV2Request, limit int, offset int) ([]*model.User, int64) {
|
||||||
|
|
||||||
|
var list []*model.User
|
||||||
|
var count int64
|
||||||
|
|
||||||
|
fmt.Println("进入查看测试测试车")
|
||||||
|
//获取自己领导的部门
|
||||||
|
|
||||||
|
//Select("a.*,a.id as tid").
|
||||||
|
selectStr :=
|
||||||
|
`
|
||||||
|
ANY_VALUE(a.id) as id,
|
||||||
|
ANY_VALUE(a.created_at) as created_at,
|
||||||
|
ANY_VALUE(a.updated_at) as updated_at,
|
||||||
|
ANY_VALUE(a.deleted_at) as deleted_at,
|
||||||
|
ANY_VALUE(a.account) as account,
|
||||||
|
ANY_VALUE(a.mnemonic_words ) as mnemonic_words,
|
||||||
|
ANY_VALUE(a.tel_num) as tel_num,
|
||||||
|
ANY_VALUE(a.password_digest) as password_digest,
|
||||||
|
ANY_VALUE(a.nickname) as nickname,
|
||||||
|
ANY_VALUE(a.status) as status,
|
||||||
|
ANY_VALUE(a.avatar) as avatar,
|
||||||
|
ANY_VALUE(a.real_name_id) as real_name_id,
|
||||||
|
ANY_VALUE(a.auth) as auth,
|
||||||
|
ANY_VALUE(a.theme_id) as theme_id,
|
||||||
|
ANY_VALUE(a.domain) as domain,
|
||||||
|
ANY_VALUE(a.public_key) as public_key,
|
||||||
|
ANY_VALUE(a.is_need_change) as is_need_change,
|
||||||
|
ANY_VALUE(a.enter_date) as enter_date,
|
||||||
|
ANY_VALUE(a.extend) as extend,
|
||||||
|
ANY_VALUE(a.title) as title,
|
||||||
|
ANY_VALUE(a.job_num) as job_num,
|
||||||
|
ANY_VALUE(a.birth_date) as birth_date,
|
||||||
|
ANY_VALUE(a.sex) as sex,
|
||||||
|
ANY_VALUE(a.last_login_date) as last_login_date,
|
||||||
|
ANY_VALUE(a.ip) as ip,
|
||||||
|
ANY_VALUE(a.invitation_code) as invitation_code,
|
||||||
|
ANY_VALUE(a.left_date) as left_date,
|
||||||
|
ANY_VALUE(a.remark) as remark,
|
||||||
|
ANY_VALUE(a.recent_img) as recent_img,
|
||||||
|
ANY_VALUE(a.english_name) as english_name,
|
||||||
|
ANY_VALUE(a.mail_account) as mail_account,
|
||||||
|
ANY_VALUE(a.ic_num) as ic_num,
|
||||||
|
ANY_VALUE(a.train) as train,
|
||||||
|
ANY_VALUE(a.certificate) as certificate,
|
||||||
|
ANY_VALUE(a.operator) as operator
|
||||||
|
`
|
||||||
|
|
||||||
|
searchObj := model.DB.
|
||||||
|
Table("user as a").
|
||||||
|
Select(selectStr).
|
||||||
|
Joins("LEFT JOIN `"+authDb+"`.hierarchy_dep_position_user b ON b.user_id = a.id and b.deleted_at = 0").
|
||||||
|
Joins("LEFT JOIN `"+authDb+"`.hierarchy_position c ON c.id = b.position_id and c.deleted_at = 0").
|
||||||
|
Joins("LEFT JOIN `"+authDb+"`.hierarchy_hierarchy d ON d.id = b.department_id and d.deleted_at = 0").
|
||||||
|
Where("a.domain = ?", in.Domain).
|
||||||
|
Where("a.deleted_at = 0").
|
||||||
|
Order("a.id desc")
|
||||||
|
|
||||||
|
if in.NickName != "" {
|
||||||
|
searchObj = searchObj.Where("a.nickname like ?", "%"+in.NickName+"%")
|
||||||
|
}
|
||||||
|
|
||||||
|
if in.TelNum != "" {
|
||||||
|
searchObj = searchObj.Where("a.tel_num = ?", in.TelNum)
|
||||||
|
}
|
||||||
|
|
||||||
|
if in.Status != "" {
|
||||||
|
searchObj = searchObj.Where("a.status = ?", in.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
if in.PositionName != "" {
|
||||||
|
searchObj = searchObj.Where("c.name like ?", "%"+in.PositionName+"%")
|
||||||
|
}
|
||||||
|
|
||||||
|
if in.PositionId != 0 {
|
||||||
|
searchObj = searchObj.Where("b.position_id = ?", in.PositionId)
|
||||||
|
}
|
||||||
|
|
||||||
|
if in.DepartmentId != 0 {
|
||||||
|
searchObj = searchObj.Where("b.department_id = ?", in.DepartmentId)
|
||||||
|
}
|
||||||
|
if len(in.DepartmentIds) != 0 {
|
||||||
|
searchObj = searchObj.Where("b.department_id in (?)", in.DepartmentIds)
|
||||||
|
}
|
||||||
|
|
||||||
|
if in.DepartmentName != "" {
|
||||||
|
searchObj = searchObj.Where("d.name like ?", "%"+in.DepartmentName+"%")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(in.DepartmentNames) > 0 && len(in.DepartmentNames) <= 10 {
|
||||||
|
|
||||||
|
nameQueries := model.DB
|
||||||
|
for _, k := range in.DepartmentNames {
|
||||||
|
nameQueries = nameQueries.Or("d.name like ?", "%"+k+"%")
|
||||||
|
}
|
||||||
|
|
||||||
|
searchObj = searchObj.Where(nameQueries)
|
||||||
|
}
|
||||||
|
|
||||||
|
if in.JobNum != "" {
|
||||||
|
searchObj = searchObj.Where("a.job_num = ?", in.JobNum)
|
||||||
|
//searchObj = searchObj.Where(model.User{JobNum: in.JobNum})
|
||||||
|
}
|
||||||
|
|
||||||
|
if in.MailAccount != "" {
|
||||||
|
searchObj = searchObj.Where("a.mail_account = ?", in.MailAccount)
|
||||||
|
//searchObj = searchObj.Where(model.User{JobNum: in.JobNum})
|
||||||
|
}
|
||||||
|
|
||||||
|
if in.StartEnterDate != "" {
|
||||||
|
searchObj = searchObj.Where("a.enter_date >= ?", in.StartEnterDate)
|
||||||
|
//searchObj = searchObj.Where(model.User{JobNum: in.JobNum})
|
||||||
|
}
|
||||||
|
|
||||||
|
if in.EndEnterDate != "" {
|
||||||
|
searchObj = searchObj.Where("a.enter_date <= ?", in.EndEnterDate)
|
||||||
|
}
|
||||||
|
|
||||||
|
searchObj = searchObj.Where("a.deleted_at = 0")
|
||||||
|
searchObj.Select("COUNT(DISTINCT a.id)").Scan(&count)
|
||||||
|
searchObj.Select(selectStr).Group("a.id").Limit(limit).Offset(offset).Find(&list)
|
||||||
|
|
||||||
|
fmt.Println("进入查看测试测试车结束")
|
||||||
|
|
||||||
|
return list, count
|
||||||
|
}
|
||||||
|
|
||||||
|
func SynNickName(in *account.UpdateRequest) {
|
||||||
|
if in.Domain == m.DefaultDomain {
|
||||||
|
model.DB.Table(authDb+".hierarchy_department_user").Where("user_id = ?", in.ID).Update("user_name", in.NickName)
|
||||||
|
}
|
||||||
|
}
|
1
pkg/application/wechat.go
Normal file
1
pkg/application/wechat.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package application
|
25
pkg/blockchain/common.go
Normal file
25
pkg/blockchain/common.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package blockchain
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/fonchain_enterprise/utils/chain"
|
||||||
|
)
|
||||||
|
|
||||||
|
//ChainClient 区块链单例
|
||||||
|
var (
|
||||||
|
ChainClient chain.BlockChain
|
||||||
|
)
|
||||||
|
|
||||||
|
type ChainConfig struct {
|
||||||
|
IP string
|
||||||
|
AdminMnemonicWords string
|
||||||
|
AdminContractAccount string
|
||||||
|
ContractName string
|
||||||
|
ContractType string
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadEnv(chainConfig ChainConfig) {
|
||||||
|
//从本地读取环境变量
|
||||||
|
fmt.Println("1----", chainConfig)
|
||||||
|
ChainClient = chain.NewXuperChain(chainConfig.IP, chainConfig.AdminMnemonicWords, chainConfig.ContractName, chainConfig.ContractType, chainConfig.AdminContractAccount)
|
||||||
|
}
|
92
pkg/cache/common.go
vendored
Normal file
92
pkg/cache/common.go
vendored
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/fonchain_enterprise/utils/zap_log"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"dubbo.apache.org/dubbo-go/v3/common/logger"
|
||||||
|
"github.com/go-redis/redis"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RedisClient Redis缓存客户端单例
|
||||||
|
var (
|
||||||
|
RedisClient *redis.Client
|
||||||
|
)
|
||||||
|
var deleteScript = `
|
||||||
|
if redis.call("get",KEYS[1]) == ARGV[1] then
|
||||||
|
return redis.call("del",KEYS[1])
|
||||||
|
else
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
`
|
||||||
|
|
||||||
|
type RedisConfig struct {
|
||||||
|
RedisDB string
|
||||||
|
RedisAddr string
|
||||||
|
RedisPw string
|
||||||
|
RedisDbName string
|
||||||
|
}
|
||||||
|
|
||||||
|
//LoadRedis 在中间件中初始化redis链接
|
||||||
|
func LoadRedis(configEnv RedisConfig) {
|
||||||
|
db, _ := strconv.ParseUint(configEnv.RedisDbName, 10, 64)
|
||||||
|
client := redis.NewClient(&redis.Options{
|
||||||
|
Addr: configEnv.RedisAddr,
|
||||||
|
Password: configEnv.RedisPw,
|
||||||
|
DB: int(db),
|
||||||
|
})
|
||||||
|
_, err := client.Ping().Result()
|
||||||
|
if err != nil {
|
||||||
|
logger.Info(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
RedisClient = client
|
||||||
|
}
|
||||||
|
|
||||||
|
//LockConcurrency 锁死并发
|
||||||
|
func LockConcurrency(key string, value string, ms time.Duration) (bool, error) {
|
||||||
|
fmt.Println(ms)
|
||||||
|
setNx := RedisClient.SetNX(key, value, ms)
|
||||||
|
|
||||||
|
result, err := setNx.Result()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
zap_log.Error(fmt.Sprintf("锁死加解密的时候,redis 失效,err%s,%v", key, err))
|
||||||
|
//panic(err)
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if result {
|
||||||
|
zap_log.Info(fmt.Sprintf("新增key存在,设置成功%s", key))
|
||||||
|
} else {
|
||||||
|
zap_log.Info(fmt.Sprintf("新增key已存在,设置失败%s", key))
|
||||||
|
}
|
||||||
|
|
||||||
|
zap_log.Info(fmt.Sprintf("日志%v%v%s", result, err, key))
|
||||||
|
|
||||||
|
if setNx.Val() == false {
|
||||||
|
return false, errors.New("已经被人锁定")
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func Release(key, value string) error {
|
||||||
|
result, err := RedisClient.Eval(deleteScript, []string{key}, value).Result()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断Lua脚本执行的结果
|
||||||
|
if result == int64(1) {
|
||||||
|
fmt.Println("Lock released.")
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
fmt.Println("Failed to release lock, or lock was not held by this client.")
|
||||||
|
return errors.New("释放失败也可能是超时自动解锁了,请您刷新")
|
||||||
|
}
|
||||||
|
}
|
80
pkg/cache/common_test.go
vendored
Normal file
80
pkg/cache/common_test.go
vendored
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLockConcurrency(t *testing.T) {
|
||||||
|
config := RedisConfig{
|
||||||
|
RedisDB: "2",
|
||||||
|
RedisAddr: "127.0.0.1:6379",
|
||||||
|
RedisPw: "",
|
||||||
|
RedisDbName: "2",
|
||||||
|
}
|
||||||
|
|
||||||
|
LoadRedis(config)
|
||||||
|
|
||||||
|
type args struct {
|
||||||
|
key string
|
||||||
|
value string
|
||||||
|
ms time.Duration
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want bool
|
||||||
|
}{
|
||||||
|
// TODO: Add test cases.
|
||||||
|
{args: args{key: "a:b:c", value: "1", ms: 10000 * time.Millisecond}},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if got, _ := LockConcurrency(tt.args.key, tt.args.value, tt.args.ms); got != tt.want {
|
||||||
|
t.Errorf("LockConcurrency() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRelease(t *testing.T) {
|
||||||
|
|
||||||
|
config := RedisConfig{
|
||||||
|
RedisDB: "2",
|
||||||
|
RedisAddr: "127.0.0.1:6379",
|
||||||
|
RedisPw: "",
|
||||||
|
RedisDbName: "2",
|
||||||
|
}
|
||||||
|
|
||||||
|
LoadRedis(config)
|
||||||
|
|
||||||
|
key := "abe"
|
||||||
|
concurrency, err := LockConcurrency(key, "1", 10*time.Second)
|
||||||
|
fmt.Println(concurrency, err)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = Release(key, "2")
|
||||||
|
fmt.Println(err)
|
||||||
|
|
||||||
|
type args struct {
|
||||||
|
key string
|
||||||
|
value string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
// TODO: Add test cases.
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if err := Release(tt.args.key, tt.args.value); (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("Release() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
89
pkg/common/dingding/ding.go
Normal file
89
pkg/common/dingding/ding.go
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
package dingding
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DingClient
|
||||||
|
var (
|
||||||
|
//DingClient *DingConfig
|
||||||
|
)
|
||||||
|
|
||||||
|
type DingConfig struct {
|
||||||
|
AccessToken string
|
||||||
|
Url string
|
||||||
|
}
|
||||||
|
|
||||||
|
type DingMsg struct {
|
||||||
|
project string
|
||||||
|
AppMode string
|
||||||
|
Url string
|
||||||
|
Info string
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
type DingText struct {
|
||||||
|
Content string `json:"content"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DingMsgInfo struct {
|
||||||
|
Msgtype string `json:"msgtype"`
|
||||||
|
Text DingText `json:"text"`
|
||||||
|
}
|
||||||
|
var dingClient *DingConfig
|
||||||
|
|
||||||
|
func LoadAccessToken(accessToken string) {
|
||||||
|
dingClient = &DingConfig{
|
||||||
|
AccessToken: accessToken,
|
||||||
|
Url: "https://oapi.dingtalk.com/robot/send",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DingConfig) SendMsg(text string) {
|
||||||
|
|
||||||
|
url := d.Url + "?access_token=" + d.AccessToken
|
||||||
|
|
||||||
|
dingMsgInfo := DingMsgInfo{
|
||||||
|
Msgtype: "text",
|
||||||
|
Text: DingText{
|
||||||
|
Content: text,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
dingMsgInfoByte, _ := json.Marshal(dingMsgInfo)
|
||||||
|
|
||||||
|
res, err := http.Post(
|
||||||
|
url,
|
||||||
|
"application/json",
|
||||||
|
strings.NewReader(string(dingMsgInfoByte)))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("发送错误:", url, err, string(dingMsgInfoByte))
|
||||||
|
}
|
||||||
|
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func Send(info string) {
|
||||||
|
msg := DingMsg{
|
||||||
|
Info: info,
|
||||||
|
}
|
||||||
|
|
||||||
|
SendInfo(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SendInfo(msg DingMsg) {
|
||||||
|
|
||||||
|
text := "通知:\n" + msg.Info
|
||||||
|
|
||||||
|
if msg.Err != nil {
|
||||||
|
text = text + "错误:" + msg.Err.Error() + "/n"
|
||||||
|
}
|
||||||
|
|
||||||
|
dingClient.SendMsg(text)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
68
pkg/common/encryption/encryption.go
Normal file
68
pkg/common/encryption/encryption.go
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
package encryption
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/aes"
|
||||||
|
"crypto/cipher"
|
||||||
|
"crypto/md5"
|
||||||
|
"encoding/hex"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
SALT string = "c-1ha$i#nfon901"
|
||||||
|
)
|
||||||
|
|
||||||
|
func AesKey(id string) []byte {
|
||||||
|
var aesKey string
|
||||||
|
|
||||||
|
h := md5.New()
|
||||||
|
h.Write([]byte(id + SALT))
|
||||||
|
aesKey = hex.EncodeToString(h.Sum(nil))
|
||||||
|
|
||||||
|
return []byte(aesKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func PKCS7Padding(ciphertext []byte, blockSize int) []byte {
|
||||||
|
padding := blockSize - len(ciphertext)%blockSize
|
||||||
|
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
|
||||||
|
return append(ciphertext, padtext...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func PKCS7UnPadding(origData []byte) []byte {
|
||||||
|
length := len(origData)
|
||||||
|
unpadding := int(origData[length-1])
|
||||||
|
return origData[:(length - unpadding)]
|
||||||
|
}
|
||||||
|
|
||||||
|
//AES加密,CBC
|
||||||
|
func AesEncrypt(origData []byte, id string) ([]byte, error) {
|
||||||
|
|
||||||
|
key := AesKey(id)
|
||||||
|
|
||||||
|
block, err := aes.NewCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
blockSize := block.BlockSize()
|
||||||
|
origData = PKCS7Padding(origData, blockSize)
|
||||||
|
blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
|
||||||
|
crypted := make([]byte, len(origData))
|
||||||
|
blockMode.CryptBlocks(crypted, origData)
|
||||||
|
return crypted, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//AES解密
|
||||||
|
func AesDecrypt(crypted []byte, id string) ([]byte, error) {
|
||||||
|
key := AesKey(id)
|
||||||
|
|
||||||
|
block, err := aes.NewCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
blockSize := block.BlockSize()
|
||||||
|
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
|
||||||
|
origData := make([]byte, len(crypted))
|
||||||
|
blockMode.CryptBlocks(origData, crypted)
|
||||||
|
origData = PKCS7UnPadding(origData)
|
||||||
|
return origData, nil
|
||||||
|
}
|
70
pkg/common/filter/filter.go
Normal file
70
pkg/common/filter/filter.go
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package filter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/e"
|
||||||
|
perrors "github.com/pkg/errors"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
import (
|
||||||
|
"dubbo.apache.org/dubbo-go/v3/common/extension"
|
||||||
|
"dubbo.apache.org/dubbo-go/v3/filter"
|
||||||
|
"dubbo.apache.org/dubbo-go/v3/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
type validator interface {
|
||||||
|
Validate() error
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
extension.SetFilter("fonValidateFilter", NewFonValidateFilter)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFonValidateFilter() filter.Filter {
|
||||||
|
return &FonValidateFilter{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type FonValidateFilter struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FonValidateFilter) Invoke(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result {
|
||||||
|
if len(invocation.Arguments()) > 0 {
|
||||||
|
if v, ok := invocation.Arguments()[0].(validator); ok {
|
||||||
|
if err := v.Validate(); err != nil {
|
||||||
|
errMsg := err.Error()
|
||||||
|
re3, _ := regexp.Compile(`^invalid(.*): `)
|
||||||
|
rep := re3.ReplaceAllString(errMsg, "")
|
||||||
|
if errCode, err := strconv.ParseInt(rep, 10, 64); err == nil {
|
||||||
|
return &protocol.RPCResult{Err: perrors.Errorf("%v", e.GetMsg(int(errCode)))}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &protocol.RPCResult{Err: perrors.Errorf("%v", rep)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return invoker.Invoke(ctx, invocation)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FonValidateFilter) OnResponse(ctx context.Context, result protocol.Result, invoker protocol.Invoker, protocol protocol.Invocation) protocol.Result {
|
||||||
|
return result
|
||||||
|
}
|
100
pkg/common/jwt/jwt.go
Normal file
100
pkg/common/jwt/jwt.go
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
package jwt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/m"
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/dgrijalva/jwt-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Claims struct {
|
||||||
|
ID uint `json:"id"`
|
||||||
|
Account string `json:"account"`
|
||||||
|
Domain string `json:"domain"`
|
||||||
|
NickName string `json:"nickName"`
|
||||||
|
Phone string `json:"phone"`
|
||||||
|
jwt.StandardClaims
|
||||||
|
}
|
||||||
|
|
||||||
|
type RefreshClaims struct {
|
||||||
|
ID uint `json:"id"`
|
||||||
|
RId int `json:"rid"`
|
||||||
|
jwt.StandardClaims
|
||||||
|
}
|
||||||
|
|
||||||
|
func GenerateTotalToken(id uint, domain string, hour int, phone string, jwtSecret []byte) (string, string, error) {
|
||||||
|
token, err := GenerateToken(id, domain, hour, phone, jwtSecret)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
refreshToken, err := GenerateRefreshToken(id, domain, m.RefreshTokenTime, jwtSecret)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return token, refreshToken, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenerateToken 签发用户Token
|
||||||
|
func GenerateToken(id uint, domain string, hour int, phone string, jwtSecret []byte) (string, error) {
|
||||||
|
nowTime := time.Now()
|
||||||
|
expireTime := nowTime.Add(time.Duration(hour) * time.Hour)
|
||||||
|
claims := Claims{
|
||||||
|
ID: id,
|
||||||
|
//Account: account,
|
||||||
|
Domain: domain,
|
||||||
|
//NickName: nickName,
|
||||||
|
Phone: phone,
|
||||||
|
StandardClaims: jwt.StandardClaims{
|
||||||
|
ExpiresAt: expireTime.Unix(),
|
||||||
|
Issuer: "mall",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||||
|
token, err := tokenClaims.SignedString(jwtSecret)
|
||||||
|
return token, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseToken 验证用户token
|
||||||
|
func ParseToken(token string, jwtSecret []byte) (*Claims, error) {
|
||||||
|
tokenClaims, err := jwt.ParseWithClaims(token, &Claims{}, func(token *jwt.Token) (interface{}, error) {
|
||||||
|
return jwtSecret, nil
|
||||||
|
})
|
||||||
|
if tokenClaims != nil {
|
||||||
|
if claims, ok := tokenClaims.Claims.(*Claims); ok && tokenClaims.Valid {
|
||||||
|
return claims, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenerateRefreshToken 签发用户Token
|
||||||
|
func GenerateRefreshToken(id uint, domain string, hour int, jwtSecret []byte) (string, error) {
|
||||||
|
nowTime := time.Now()
|
||||||
|
expireTime := nowTime.Add(time.Duration(hour) * time.Hour)
|
||||||
|
claims := RefreshClaims{
|
||||||
|
ID: id,
|
||||||
|
RId: rand.Intn(999),
|
||||||
|
StandardClaims: jwt.StandardClaims{
|
||||||
|
ExpiresAt: expireTime.Unix(),
|
||||||
|
Issuer: domain,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||||
|
token, err := tokenClaims.SignedString(jwtSecret)
|
||||||
|
return token, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseRefreshToken 验证用户token
|
||||||
|
func ParseRefreshToken(token string, jwtSecret []byte) (*RefreshClaims, error) {
|
||||||
|
tokenClaims, err := jwt.ParseWithClaims(token, &RefreshClaims{}, func(token *jwt.Token) (interface{}, error) {
|
||||||
|
return jwtSecret, nil
|
||||||
|
})
|
||||||
|
if tokenClaims != nil {
|
||||||
|
if claims, ok := tokenClaims.Claims.(*RefreshClaims); ok && tokenClaims.Valid {
|
||||||
|
return claims, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
38
pkg/common/jwt/jwt_test.go
Normal file
38
pkg/common/jwt/jwt_test.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package jwt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/m"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParseToken(t *testing.T) {
|
||||||
|
|
||||||
|
str := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MjMzLCJhY2NvdW50IjoiVU1jektDWDVTRHpnZm43eDZkNTFLMTYxaThZNlhjdWVNIiwiZG9tYWluIjoiYXJ0aXN0aW5mbyIsIm5pY2tOYW1lIjoiMTM5NjIzMTA3NjUiLCJwaG9uZSI6IjEzOTYyMzEwNzY1IiwiZXhwIjoxNjg0NzYyMjY2LCJpc3MiOiJtYWxsIn0.8zG3OA9uRJnzxYorQ2_cK6FhQuMlsi7WF8zkIic1ggM"
|
||||||
|
str = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6NDAsImFjY291bnQiOiJUZW5hR2U4b0w1S3FzYkpnbUxGYUQxenN5WFU2azNMZ3MiLCJkb21haW4iOiJmb250cmVlIiwibmlja05hbWUiOiLotoXnuqfnrqHnkIYiLCJwaG9uZSI6IjEyMjMzNDQ1NTY2IiwiZXhwIjoxNjk3MTM3NTc0LCJpc3MiOiJtYWxsIn0.rHt4rYi8lgOhaHDscHjRsYBbSdcaz-uCXJyXroih62I"
|
||||||
|
|
||||||
|
claims, err := ParseToken(str, m.JWTSecret)
|
||||||
|
fmt.Println(err)
|
||||||
|
fmt.Println(claims)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseToken2(t *testing.T) {
|
||||||
|
t1 := time.Now()
|
||||||
|
fmt.Print(GenerateToken(70, "", "fontree", "耿阳"+
|
||||||
|
"", -m.TokenTime, "18205052627", m.JWTSecret))
|
||||||
|
|
||||||
|
fmt.Println(time.Now().Sub(t1))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRefreshToken(t *testing.T) {
|
||||||
|
str1, err := GenerateRefreshToken(70, "fontree", 20, m.JWTSecret)
|
||||||
|
fmt.Println(str1, err)
|
||||||
|
|
||||||
|
//str := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MjMzLCJhY2NvdW50IjoiVU1jektDWDVTRHpnZm43eDZkNTFLMTYxaThZNlhjdWVNIiwiZG9tYWluIjoiYXJ0aXN0aW5mbyIsIm5pY2tOYW1lIjoiMTM5NjIzMTA3NjUiLCJwaG9uZSI6IjEzOTYyMzEwNzY1IiwiZXhwIjoxNjg0NzYyMjY2LCJpc3MiOiJtYWxsIn0.8zG3OA9uRJnzxYorQ2_cK6FhQuMlsi7WF8zkIic1ggM"
|
||||||
|
claims, err := ParseRefreshToken(str1, m.JWTSecret)
|
||||||
|
fmt.Println(err)
|
||||||
|
fmt.Println(claims)
|
||||||
|
|
||||||
|
}
|
44
pkg/common/log/gorm.go
Normal file
44
pkg/common/log/gorm.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package log
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"gorm.io/gorm/logger"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewGormLogger() logger.Interface {
|
||||||
|
return &zapLogger{zapFakeLog.GetZapLogger()}
|
||||||
|
}
|
||||||
|
|
||||||
|
type zapLogger struct {
|
||||||
|
logger *zap.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *zapLogger) LogMode(level logger.LogLevel) logger.Interface {
|
||||||
|
newLogger := *l
|
||||||
|
return &newLogger
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *zapLogger) Info(ctx context.Context, s string, args ...interface{}) {
|
||||||
|
l.logger.Info(fmt.Sprintf(s, args...))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *zapLogger) Warn(ctx context.Context, s string, args ...interface{}) {
|
||||||
|
l.logger.Warn(fmt.Sprintf(s, args...))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *zapLogger) Error(ctx context.Context, s string, args ...interface{}) {
|
||||||
|
l.logger.Error(fmt.Sprintf(s, args...))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *zapLogger) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) {
|
||||||
|
if err != nil {
|
||||||
|
l.Error(ctx, "[%.3fms] [error] %v", time.Since(begin).Seconds()*1000, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
sql, rows := fc()
|
||||||
|
l.Info(ctx, "[%.3fms] [rows:%v] %s", time.Since(begin).Seconds()*1000, rows, sql)
|
||||||
|
}
|
35
pkg/common/log/init.go
Normal file
35
pkg/common/log/init.go
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package log
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
|
||||||
|
bytes, err := getConfig()
|
||||||
|
var info *DuInfo
|
||||||
|
|
||||||
|
if err = yaml.Unmarshal(bytes, &info); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
InitLogger(info.Config)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func getConfig() ([]byte, error) {
|
||||||
|
configFilePath := "../conf/log.yaml"
|
||||||
|
_, err := os.Stat(configFilePath)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
fmt.Println("-----------不存在")
|
||||||
|
} else {
|
||||||
|
|
||||||
|
fmt.Println("------------存在")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return ioutil.ReadFile(configFilePath)
|
||||||
|
}
|
141
pkg/common/log/log.go
Normal file
141
pkg/common/log/log.go
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package log
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/natefinch/lumberjack"
|
||||||
|
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"go.uber.org/zap/zapcore"
|
||||||
|
)
|
||||||
|
|
||||||
|
var zapFakeLog *ZapLoggerFake
|
||||||
|
|
||||||
|
type DuInfo struct {
|
||||||
|
Config *Config `yaml:"logger"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
LumberjackConfig *lumberjack.Logger `yaml:"lumberjack-config"`
|
||||||
|
ZapConfig *zap.Config `yaml:"zap-config"`
|
||||||
|
CallerSkip int
|
||||||
|
}
|
||||||
|
|
||||||
|
type ZapLoggerFake struct {
|
||||||
|
logger *zap.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
// InitLogger use for init logger by @conf
|
||||||
|
func InitLogger(conf *Config) {
|
||||||
|
var (
|
||||||
|
_ *zap.Logger
|
||||||
|
config = &Config{}
|
||||||
|
)
|
||||||
|
if conf == nil || conf.ZapConfig == nil {
|
||||||
|
zapLoggerEncoderConfig := zapcore.EncoderConfig{
|
||||||
|
TimeKey: "time",
|
||||||
|
LevelKey: "level",
|
||||||
|
NameKey: "logger",
|
||||||
|
CallerKey: "caller",
|
||||||
|
MessageKey: "message",
|
||||||
|
StacktraceKey: "stacktrace",
|
||||||
|
EncodeLevel: zapcore.CapitalColorLevelEncoder,
|
||||||
|
EncodeTime: zapcore.ISO8601TimeEncoder,
|
||||||
|
EncodeDuration: zapcore.SecondsDurationEncoder,
|
||||||
|
EncodeCaller: zapcore.ShortCallerEncoder,
|
||||||
|
}
|
||||||
|
config.ZapConfig = &zap.Config{
|
||||||
|
Level: zap.NewAtomicLevelAt(zap.InfoLevel),
|
||||||
|
Development: false,
|
||||||
|
Encoding: "console",
|
||||||
|
EncoderConfig: zapLoggerEncoderConfig,
|
||||||
|
OutputPaths: []string{"stderr"},
|
||||||
|
ErrorOutputPaths: []string{"stderr"},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
config.ZapConfig = conf.ZapConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
if conf != nil {
|
||||||
|
config.CallerSkip = conf.CallerSkip
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.CallerSkip == 0 { //因为包装了两层,所以设置3次
|
||||||
|
config.CallerSkip = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
var zapLogger *zap.Logger
|
||||||
|
if conf == nil || conf.LumberjackConfig == nil {
|
||||||
|
zapLogger, _ = config.ZapConfig.Build(zap.AddCaller(), zap.AddCallerSkip(config.CallerSkip))
|
||||||
|
} else {
|
||||||
|
config.LumberjackConfig = conf.LumberjackConfig
|
||||||
|
zapLogger = initZapLoggerWithSyncer(config)
|
||||||
|
}
|
||||||
|
|
||||||
|
zapFakeLog = &ZapLoggerFake{logger: zapLogger}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetFakeLogger() *ZapLoggerFake {
|
||||||
|
return zapFakeLog
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetZapLog() *zap.Logger {
|
||||||
|
return zapFakeLog.logger
|
||||||
|
}
|
||||||
|
|
||||||
|
// initZapLoggerWithSyncer init zap Logger with syncer
|
||||||
|
func initZapLoggerWithSyncer(conf *Config) *zap.Logger {
|
||||||
|
|
||||||
|
var fields []zapcore.Field
|
||||||
|
|
||||||
|
if len(conf.ZapConfig.InitialFields) > 0 {
|
||||||
|
for key, value := range conf.ZapConfig.InitialFields {
|
||||||
|
fields = append(fields, zap.Any(key, value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println("配置lumber", conf.LumberjackConfig)
|
||||||
|
|
||||||
|
core := zapcore.NewCore(
|
||||||
|
conf.getEncoder(),
|
||||||
|
conf.getLogWriter(),
|
||||||
|
zap.NewAtomicLevelAt(conf.ZapConfig.Level.Level()),
|
||||||
|
)
|
||||||
|
if len(fields) >= 1 {
|
||||||
|
core = core.With(fields)
|
||||||
|
}
|
||||||
|
|
||||||
|
return zap.New(core, zap.AddCaller(), zap.AddCallerSkip(conf.CallerSkip))
|
||||||
|
}
|
||||||
|
|
||||||
|
// getEncoder get encoder by config, zapcore support json and console encoder
|
||||||
|
func (c *Config) getEncoder() zapcore.Encoder {
|
||||||
|
if c.ZapConfig.Encoding == "json" {
|
||||||
|
return zapcore.NewJSONEncoder(c.ZapConfig.EncoderConfig)
|
||||||
|
} else if c.ZapConfig.Encoding == "console" {
|
||||||
|
return zapcore.NewConsoleEncoder(c.ZapConfig.EncoderConfig)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getLogWriter get Lumberjack writer by LumberjackConfig
|
||||||
|
func (c *Config) getLogWriter() zapcore.WriteSyncer {
|
||||||
|
return zapcore.AddSync(c.LumberjackConfig)
|
||||||
|
}
|
148
pkg/common/log/logging.go
Normal file
148
pkg/common/log/logging.go
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package log
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"go.uber.org/zap/zapcore"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *ZapLoggerFake) GetZapLogger() *zap.Logger {
|
||||||
|
return s.logger
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debug uses fmt.Sprint to construct and log a message.
|
||||||
|
func (s *ZapLoggerFake) Debug(args ...interface{}) {
|
||||||
|
s.logAndZap(zap.DebugLevel, "", args)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Info uses fmt.Sprint to construct and log a message.
|
||||||
|
func (s *ZapLoggerFake) Info(args ...interface{}) {
|
||||||
|
s.logAndZap(zap.InfoLevel, "", args)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warn uses fmt.Sprint to construct and log a message.
|
||||||
|
func (s *ZapLoggerFake) Warn(args ...interface{}) {
|
||||||
|
s.logAndZap(zap.WarnLevel, "", args)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error uses fmt.Sprint to construct and log a message.
|
||||||
|
func (s *ZapLoggerFake) Error(args ...interface{}) {
|
||||||
|
s.logAndZap(zap.ErrorLevel, "", args)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fatal uses fmt.Sprint to construct and log a message, then calls os.Exit.
|
||||||
|
func (s *ZapLoggerFake) Fatal(args ...interface{}) {
|
||||||
|
s.logAndZap(zap.FatalLevel, "", args)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debugf uses fmt.Sprintf to log a templated message.
|
||||||
|
func (s *ZapLoggerFake) Debugf(template string, args ...interface{}) {
|
||||||
|
s.log(zap.DebugLevel, template, args, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Infof uses fmt.Sprintf to log a templated message.
|
||||||
|
func (s *ZapLoggerFake) Infof(template string, args ...interface{}) {
|
||||||
|
s.log(zap.InfoLevel, template, args, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warnf uses fmt.Sprintf to log a templated message.
|
||||||
|
func (s *ZapLoggerFake) Warnf(template string, args ...interface{}) {
|
||||||
|
s.log(zap.WarnLevel, template, args, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Errorf uses fmt.Sprintf to log a templated message.
|
||||||
|
func (s *ZapLoggerFake) Errorf(template string, args ...interface{}) {
|
||||||
|
s.log(zap.ErrorLevel, template, args, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fatalf uses fmt.Sprintf to log a templated message, then calls os.Exit.
|
||||||
|
func (s *ZapLoggerFake) Fatalf(template string, args ...interface{}) {
|
||||||
|
s.log(zap.FatalLevel, template, args, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ZapLoggerFake) logAndZap(lvl zapcore.Level, template string, fmtArgs []interface{}) {
|
||||||
|
s.realLogAndZap(lvl, template, fmtArgs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ZapLoggerFake) realLogAndZap(lvl zapcore.Level, template string, fmtArgs []interface{}) {
|
||||||
|
|
||||||
|
if lvl < zap.DPanicLevel && !s.logger.Core().Enabled(lvl) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
args, context := s.sweetenFields(fmtArgs)
|
||||||
|
msg := getMessage(template, args)
|
||||||
|
if ce := s.logger.Check(lvl, msg); ce != nil {
|
||||||
|
ce.Write(context...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ZapLoggerFake) log(lvl zapcore.Level, template string, fmtArgs []interface{}, context []zap.Field) {
|
||||||
|
// If logging at this level is completely disabled, skip the overhead of
|
||||||
|
// string formatting.
|
||||||
|
if lvl < zap.DPanicLevel && !s.logger.Core().Enabled(lvl) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := getMessage(template, fmtArgs)
|
||||||
|
if ce := s.logger.Check(lvl, msg); ce != nil {
|
||||||
|
ce.Write(context...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// getMessage format with Sprint, Sprintf, or neither.
|
||||||
|
func getMessage(template string, fmtArgs []interface{}) string {
|
||||||
|
if len(fmtArgs) == 0 {
|
||||||
|
return template
|
||||||
|
}
|
||||||
|
|
||||||
|
if template != "" {
|
||||||
|
return fmt.Sprintf(template, fmtArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(fmtArgs) == 1 {
|
||||||
|
if str, ok := fmtArgs[0].(string); ok {
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fmt.Sprint(fmtArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ZapLoggerFake) sweetenFields(args []interface{}) ([]interface{}, []zap.Field) {
|
||||||
|
|
||||||
|
if len(args) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate enough space for the worst case; if users pass only structured
|
||||||
|
// fields, we shouldn't penalize them with extra allocations.
|
||||||
|
fields := make([]zap.Field, 0, len(args))
|
||||||
|
var newArgs []interface{}
|
||||||
|
|
||||||
|
for i := 0; i < len(args); i++ {
|
||||||
|
// This is a strongly-typed field. Consume it and move on.
|
||||||
|
if f, ok := args[i].(zap.Field); ok {
|
||||||
|
fields = append(fields, f)
|
||||||
|
} else {
|
||||||
|
newArgs = append(newArgs, args[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newArgs, fields
|
||||||
|
}
|
10
pkg/common/page/page.go
Normal file
10
pkg/common/page/page.go
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package page
|
||||||
|
|
||||||
|
func GetOffset(page uint64, pageSize uint64) int {
|
||||||
|
if page <= 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return int((page - 1) * pageSize)
|
||||||
|
}
|
||||||
|
|
94
pkg/common/redis_key/redis_key.go
Normal file
94
pkg/common/redis_key/redis_key.go
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
package redis_key
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/alibaba/sentinel-golang/util"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/common/utils"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
mobile = "mobile:"
|
||||||
|
token = "token:"
|
||||||
|
)
|
||||||
|
|
||||||
|
func UserDailyGetCoinKey(userId uint32) string {
|
||||||
|
return fmt.Sprintf("coin:micro:user::id:%d:daily:%s", userId, time.Now().Format(util.DateFormat))
|
||||||
|
}
|
||||||
|
|
||||||
|
func UserRegisterGetCoinKey(userId uint32) string {
|
||||||
|
return fmt.Sprintf("coin:micro:user::id:%d:register", userId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func UserCoinLock(domain string, key uint32) string {
|
||||||
|
return fmt.Sprintf("%s:lock:user:%d", domain, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAccountKey(domain, key string) string {
|
||||||
|
return domain + ":" + mobile + key
|
||||||
|
}
|
||||||
|
|
||||||
|
func VerityCode(domain, key string) string {
|
||||||
|
return domain + ":code:time:" + mobile + key
|
||||||
|
}
|
||||||
|
|
||||||
|
func BlackListKey(domain string) string {
|
||||||
|
return domain + ":blackList:" + mobile
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetOnlyAccountKey(domain, key string) string {
|
||||||
|
return domain + ":only:" + mobile + key
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetTokenInfo(domain, key string) string {
|
||||||
|
return domain + ":" + token + "info:" + utils.Get16MD5Encode(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetIpAddressKey(key string) string {
|
||||||
|
return "ip_address:" + key
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetTokenLogoutInfo(domain, key string) string {
|
||||||
|
return domain + ":" + token + "logout_err:" + key
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAccountRegisterKey(domain, key string) string {
|
||||||
|
return domain + ":register:" + mobile + key
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAccountKeyCountToday(domain, key string) string {
|
||||||
|
return domain + ":count:date:" + time.Now().Format("2006-01-02") + ":" + mobile + key
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAccountKeyCountTodayHour(domain, telNum, scope string) string {
|
||||||
|
return domain + ":count:date:" + scope + ":" + time.Now().Format("2006-01-02 15") + ":" + telNum
|
||||||
|
}
|
||||||
|
|
||||||
|
func MinLimit(domain, telNum, scope string) string {
|
||||||
|
return domain + ":count:min_limit:" + scope + ":" + telNum
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetChangeTelKey(domain, key string, id string) string {
|
||||||
|
return domain + ":changeTel:" + mobile + id + ":" + key
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetOneMinuteKey(domain, key string, id string) string {
|
||||||
|
return domain + ":minute:" + mobile + id + ":" + key
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetNowNewTelById(domain string, id string) string {
|
||||||
|
return domain + ":now_tel:" + id
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetBoxAccessToken(key string) string {
|
||||||
|
return "box:access_token:" + key
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetWxAccessToken(key string) string {
|
||||||
|
return "box:access_token:" + key
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCheckPasswordRate 限制解密 频率
|
||||||
|
func GetCheckPasswordRate(domain, tel string) string {
|
||||||
|
return domain + ":check:psd:" + mobile + tel
|
||||||
|
}
|
220
pkg/common/utils/idnum/idnum.go
Normal file
220
pkg/common/utils/idnum/idnum.go
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
package idnum
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var weight = [17]int{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}
|
||||||
|
var valid_value = [11]byte{'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'}
|
||||||
|
var valid_province = []string{
|
||||||
|
"11", // 北京市
|
||||||
|
"12", // 天津市
|
||||||
|
"13", // 河北省
|
||||||
|
"14", // 山西省
|
||||||
|
"15", // 内蒙古自治区
|
||||||
|
"21", // 辽宁省
|
||||||
|
"22", // 吉林省
|
||||||
|
"23", // 黑龙江省
|
||||||
|
"31", // 上海市
|
||||||
|
"32", // 江苏省
|
||||||
|
"33", // 浙江省
|
||||||
|
"34", // 安徽省
|
||||||
|
"35", // 福建省
|
||||||
|
"36", // 山西省
|
||||||
|
"37", // 山东省
|
||||||
|
"41", // 河南省
|
||||||
|
"42", // 湖北省
|
||||||
|
"43", // 湖南省
|
||||||
|
"44", // 广东省
|
||||||
|
"45", // 广西壮族自治区
|
||||||
|
"46", // 海南省
|
||||||
|
"50", // 重庆市
|
||||||
|
"51", // 四川省
|
||||||
|
"52", // 贵州省
|
||||||
|
"53", // 云南省
|
||||||
|
"54", // 西藏自治区
|
||||||
|
"61", // 陕西省
|
||||||
|
"62", // 甘肃省
|
||||||
|
"63", // 青海省
|
||||||
|
"64", // 宁夏回族自治区
|
||||||
|
"65", // 新疆维吾尔自治区
|
||||||
|
"71", // 台湾省
|
||||||
|
"81", // 香港特别行政区
|
||||||
|
"91", // 澳门特别行政区
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check citizen number 18 valid.
|
||||||
|
func IsValidCitizenNo18(citizenNo18 *[]byte) bool {
|
||||||
|
nLen := len(*citizenNo18)
|
||||||
|
if nLen != 18 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
nSum := 0
|
||||||
|
for i := 0; i < nLen-1; i++ {
|
||||||
|
n, _ := strconv.Atoi(string((*citizenNo18)[i]))
|
||||||
|
nSum += n * weight[i]
|
||||||
|
}
|
||||||
|
mod := nSum % 11
|
||||||
|
if valid_value[mod] == (*citizenNo18)[17] {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert citizen 15 to 18.
|
||||||
|
func Citizen15To18(citizenNo15 []byte) []byte {
|
||||||
|
nLen := len(citizenNo15)
|
||||||
|
if nLen != 15 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
citizenNo18 := make([]byte, 0)
|
||||||
|
citizenNo18 = append(citizenNo18, citizenNo15[:6]...)
|
||||||
|
citizenNo18 = append(citizenNo18, '1', '9')
|
||||||
|
citizenNo18 = append(citizenNo18, citizenNo15[6:]...)
|
||||||
|
|
||||||
|
sum := 0
|
||||||
|
for i, v := range citizenNo18 {
|
||||||
|
n, _ := strconv.Atoi(string(v))
|
||||||
|
sum += n * weight[i]
|
||||||
|
}
|
||||||
|
mod := sum % 11
|
||||||
|
citizenNo18 = append(citizenNo18, valid_value[mod])
|
||||||
|
|
||||||
|
return citizenNo18
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsLeapYear(nYear int) bool {
|
||||||
|
if nYear <= 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nYear%4 == 0 && nYear%100 != 0) || nYear%400 == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check birthday's year month day valid.
|
||||||
|
func CheckBirthdayValid(nYear, nMonth, nDay int) bool {
|
||||||
|
if nYear < 1900 || nMonth <= 0 || nMonth > 12 || nDay <= 0 || nDay > 31 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
curYear, curMonth, curDay := time.Now().Date()
|
||||||
|
if nYear == curYear {
|
||||||
|
if nMonth > int(curMonth) {
|
||||||
|
return false
|
||||||
|
} else if nMonth == int(curMonth) && nDay > curDay {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if 2 == nMonth {
|
||||||
|
if IsLeapYear(nYear) && nDay > 29 {
|
||||||
|
return false
|
||||||
|
} else if nDay > 28 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} else if 4 == nMonth || 6 == nMonth || 9 == nMonth || 11 == nMonth {
|
||||||
|
if nDay > 30 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check province code valid.
|
||||||
|
func CheckProvinceValid(citizenNo []byte) bool {
|
||||||
|
provinceCode := make([]byte, 0)
|
||||||
|
provinceCode = append(provinceCode, citizenNo[:2]...)
|
||||||
|
provinceStr := string(provinceCode)
|
||||||
|
|
||||||
|
for i, _ := range valid_province {
|
||||||
|
if provinceStr == valid_province[i] {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check citizen number valid.
|
||||||
|
func IsValidCitizenNo(citizenNo *[]byte) bool {
|
||||||
|
nLen := len(*citizenNo)
|
||||||
|
if nLen != 15 && nLen != 18 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, v := range *citizenNo {
|
||||||
|
n, _ := strconv.Atoi(string(v))
|
||||||
|
if n >= 0 && n <= 9 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if v == 'X' && i == 16 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !CheckProvinceValid(*citizenNo) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if nLen == 15 {
|
||||||
|
*citizenNo = Citizen15To18(*citizenNo)
|
||||||
|
if citizenNo == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} else if !IsValidCitizenNo18(citizenNo) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
nYear, _ := strconv.Atoi(string((*citizenNo)[6:10]))
|
||||||
|
nMonth, _ := strconv.Atoi(string((*citizenNo)[10:12]))
|
||||||
|
nDay, _ := strconv.Atoi(string((*citizenNo)[12:14]))
|
||||||
|
if !CheckBirthdayValid(nYear, nMonth, nDay) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get information from citizen number. Birthday, gender, province mask.
|
||||||
|
func GetCitizenNoInfo(citizenNo []byte) (err error, birthday string, isMale bool, addrMask int) {
|
||||||
|
err = nil
|
||||||
|
birthday = ""
|
||||||
|
isMale = false
|
||||||
|
addrMask = 0
|
||||||
|
if !IsValidCitizenNo(&citizenNo) {
|
||||||
|
err = errors.New("身份号错误,请重新录入")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Birthday information.
|
||||||
|
nYear, _ := strconv.Atoi(string(citizenNo[6:10]))
|
||||||
|
nMonth, _ := strconv.Atoi(string(citizenNo[10:12]))
|
||||||
|
nDay, _ := strconv.Atoi(string(citizenNo[12:14]))
|
||||||
|
birthday = time.Date(nYear, time.Month(nMonth), nDay, 0, 0, 0, 0, time.Local).Format("2006-01-02")
|
||||||
|
|
||||||
|
// Gender information.
|
||||||
|
genderMask, _ := strconv.Atoi(string(citizenNo[16]))
|
||||||
|
if genderMask%2 == 0 {
|
||||||
|
isMale = false
|
||||||
|
} else {
|
||||||
|
isMale = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Address code mask.
|
||||||
|
addrMask, _ = strconv.Atoi(string(citizenNo[:2]))
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
172
pkg/common/utils/idnum/idnum_net.go
Normal file
172
pkg/common/utils/idnum/idnum_net.go
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
package idnum
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/cache"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var param = map[string]string{
|
||||||
|
"grant_type": "client_credentials",
|
||||||
|
"client_id": "AlbWwhnZINIy1YqWP3agQA42",
|
||||||
|
"client_secret": "NL2nT4rnGHIcpopBI93a7G85WscluOEH",
|
||||||
|
}
|
||||||
|
|
||||||
|
type IDCheckRes struct {
|
||||||
|
ErrorCode int `json:"error_code"`
|
||||||
|
ErrorMsg string `json:"error_msg"`
|
||||||
|
LogID int `json:"log_id"`
|
||||||
|
Timestamp int `json:"timestamp"`
|
||||||
|
Cached int `json:"cached"`
|
||||||
|
Result interface{} `json:"result"`
|
||||||
|
}
|
||||||
|
type TokenInfo struct {
|
||||||
|
RefreshToken string `json:"refresh_token"`
|
||||||
|
ExpiresIn int `json:"expires_in"`
|
||||||
|
Scope string `json:"scope"`
|
||||||
|
SessionKey string `json:"session_key"`
|
||||||
|
AccessToken string `json:"access_token"`
|
||||||
|
SessionSecret string `json:"session_secret"`
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Tru89O1zosjSCIN2uUlEctbE
|
||||||
|
rLgGU2gwNvEQAo0UooTwArtvqBTaL3Y3
|
||||||
|
25346530
|
||||||
|
*/
|
||||||
|
|
||||||
|
func CheckIDNumFromNet(idNum string, name string) error {
|
||||||
|
var host = "https://aip.baidubce.com/rest/2.0/face/v3/person/idmatch"
|
||||||
|
accessToken, err := getAccessToken()
|
||||||
|
fmt.Println("1百度生成token---", accessToken, err)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
uri, err := url.Parse(host)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
query := uri.Query()
|
||||||
|
query.Set("access_token", accessToken)
|
||||||
|
uri.RawQuery = query.Encode()
|
||||||
|
|
||||||
|
var params = map[string]string{}
|
||||||
|
params["id_card_number"] = idNum
|
||||||
|
params["name"] = name
|
||||||
|
sendBody, err := json.Marshal(params)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
sendData := string(sendBody)
|
||||||
|
client := &http.Client{}
|
||||||
|
request, err := http.NewRequest("POST", uri.String(), strings.NewReader(sendData))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
request.Header.Set("Content-Type", "application/json")
|
||||||
|
response, err := client.Do(request)
|
||||||
|
defer response.Body.Close()
|
||||||
|
result, err := ioutil.ReadAll(response.Body)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Println(string(result))
|
||||||
|
var res IDCheckRes
|
||||||
|
|
||||||
|
err = json.Unmarshal(result, &res)
|
||||||
|
|
||||||
|
fmt.Println(string(result))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if res.ErrorCode != 0 {
|
||||||
|
if res.ErrorCode == 222351 {
|
||||||
|
return errors.New("不匹配或者身份证不存在")
|
||||||
|
}
|
||||||
|
return errors.New("实名认证未通过")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAccessToken() (string, error) {
|
||||||
|
|
||||||
|
var tokenInfo TokenInfo
|
||||||
|
var err error
|
||||||
|
key := "baidu:Id:access_token" + param["client_id"]
|
||||||
|
strCmd := cache.RedisClient.Get(key)
|
||||||
|
|
||||||
|
accessToken := strCmd.Val()
|
||||||
|
if accessToken != "" {
|
||||||
|
err := json.Unmarshal([]byte(accessToken), &tokenInfo)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return tokenInfo.AccessToken, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
accessToken, err = getNewAccessToken()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if merr := cache.RedisClient.Set(key, accessToken, 5*60*1000*time.Millisecond).Err(); merr != nil {
|
||||||
|
return "", merr
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.Unmarshal([]byte(accessToken), &tokenInfo)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return tokenInfo.AccessToken, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getNewAccessToken() (string, error) {
|
||||||
|
accessToken := ""
|
||||||
|
|
||||||
|
var host = "https://aip.baidubce.com/oauth/2.0/token"
|
||||||
|
|
||||||
|
uri, err := url.Parse(host)
|
||||||
|
fmt.Println(uri)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return accessToken, err
|
||||||
|
}
|
||||||
|
query := uri.Query()
|
||||||
|
for k, v := range param {
|
||||||
|
query.Set(k, v)
|
||||||
|
}
|
||||||
|
uri.RawQuery = query.Encode()
|
||||||
|
|
||||||
|
response, err := http.Get(uri.String())
|
||||||
|
|
||||||
|
fmt.Println(response)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return accessToken, err
|
||||||
|
}
|
||||||
|
result, err := ioutil.ReadAll(response.Body)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return accessToken, err
|
||||||
|
}
|
||||||
|
fmt.Println(string(result))
|
||||||
|
|
||||||
|
return string(result), err
|
||||||
|
}
|
25
pkg/common/utils/idnum/idnum_test.go
Normal file
25
pkg/common/utils/idnum/idnum_test.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package idnum
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
Status_1 = iota + 1
|
||||||
|
Status_2
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_fb_recursion(t *testing.T) {
|
||||||
|
|
||||||
|
citizenNo := []byte("370406199808220116")
|
||||||
|
err, birthday, isMale, add := GetCitizenNoInfo(citizenNo)
|
||||||
|
fmt.Println(birthday, isMale, add, err)
|
||||||
|
|
||||||
|
citizenNo = []byte("370406199808220116")
|
||||||
|
err, birthday, isMale, add = GetCitizenNoInfo(citizenNo)
|
||||||
|
fmt.Println(birthday, isMale, add, err)
|
||||||
|
fmt.Println(Status_1)
|
||||||
|
fmt.Println(Status_2)
|
||||||
|
|
||||||
|
}
|
406
pkg/common/utils/ip.go
Normal file
406
pkg/common/utils/ip.go
Normal file
@ -0,0 +1,406 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"golang.org/x/text/encoding/simplifiedchinese"
|
||||||
|
"io/ioutil"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// DefaultDict 默认字典
|
||||||
|
DefaultDict = "./conf/data.dat"
|
||||||
|
// IndexLen 索引长度
|
||||||
|
IndexLen = 7
|
||||||
|
// RedirectMode1 国家的类型, 指向另一个指向
|
||||||
|
RedirectMode1 = 0x01
|
||||||
|
// RedirectMode2 国家的类型, 指向一个指向
|
||||||
|
RedirectMode2 = 0x02
|
||||||
|
)
|
||||||
|
|
||||||
|
type Result struct {
|
||||||
|
IP string `json:"ip"`
|
||||||
|
Location Location `json:"location"`
|
||||||
|
AdInfo AdInfo `json:"ad_info"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ResultV2 struct {
|
||||||
|
IP string `json:"ip"`
|
||||||
|
City string `json:"city"`
|
||||||
|
Country string `json:"country"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Location struct {
|
||||||
|
Lat float64 `json:"lat"`
|
||||||
|
Lng float64 `json:"lng"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AdInfo struct {
|
||||||
|
Nation string `json:"nation"`
|
||||||
|
Province string `json:"province"`
|
||||||
|
City string `json:"city"`
|
||||||
|
District string `json:"district"`
|
||||||
|
AdcodE int `json:"adcode"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type IpResult struct {
|
||||||
|
Status int `json:"status"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
RequestID string `json:"request_id"`
|
||||||
|
Result Result `json:"result"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type IpResultV2 struct {
|
||||||
|
Ret int `json:"ret"`
|
||||||
|
Msg string `json:"Msg"`
|
||||||
|
LogId string `json:"log_id"`
|
||||||
|
Result ResultV2 `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type IPDict struct {
|
||||||
|
fileData []byte //文件数据
|
||||||
|
offset uint32 //当前下标定位
|
||||||
|
firstOffset uint32 //第一条IP记录的偏移地址
|
||||||
|
lastOffset uint32 //最后一条IP记录的偏移地址
|
||||||
|
totalIPNum uint32 //IP记录的总条数(不包含版本信息记录)
|
||||||
|
}
|
||||||
|
|
||||||
|
type IPLocation struct {
|
||||||
|
IP string `json:"ip"`
|
||||||
|
BeginIP string `json:"begin_ip"`
|
||||||
|
EndIP string `json:"end_ip"`
|
||||||
|
Country string `json:"country"`
|
||||||
|
Area string `json:"area"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewIPDict() *IPDict {
|
||||||
|
return &IPDict{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *IPDict) Load(fileName string) error {
|
||||||
|
filePath, err := dictPath(fileName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
dictFile, err := os.OpenFile(filePath, os.O_RDONLY, 0400)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer dictFile.Close()
|
||||||
|
q.fileData, err = ioutil.ReadAll(dictFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
buf := q.readBuf(8)
|
||||||
|
q.firstOffset = binary.LittleEndian.Uint32(buf[:4])
|
||||||
|
q.lastOffset = binary.LittleEndian.Uint32(buf[4:])
|
||||||
|
q.totalIPNum = (q.lastOffset - q.firstOffset) / IndexLen
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *IPDict) FindIP(ip string) (*IPLocation, error) {
|
||||||
|
if false == checkIPv4(ip) {
|
||||||
|
return nil, errors.New("IP format error")
|
||||||
|
}
|
||||||
|
res := IPLocation{IP: ip}
|
||||||
|
if nil == q.fileData {
|
||||||
|
err := q.Load(DefaultDict)
|
||||||
|
if nil != err {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
q.seekOffset(0)
|
||||||
|
index := q.findIndex(ip)
|
||||||
|
if index <= 0 {
|
||||||
|
return nil, errors.New("IP not fount")
|
||||||
|
}
|
||||||
|
q.seekOffset(index)
|
||||||
|
res.BeginIP = long2ip(q.getIPLong4()) //endIPOffset
|
||||||
|
endIPOffset := q.getRedirectOffset()
|
||||||
|
q.seekOffset(endIPOffset)
|
||||||
|
res.EndIP = long2ip(q.getIPLong4()) //endIPOffset
|
||||||
|
mode := q.readMode() // 标志字节
|
||||||
|
var country, area []byte
|
||||||
|
enc := simplifiedchinese.GBK.NewDecoder()
|
||||||
|
switch mode {
|
||||||
|
case RedirectMode1: // 标志字节为1,表示国家和区域信息都被同时重定向
|
||||||
|
countryOffset := q.getRedirectOffset() // 重定向地址
|
||||||
|
q.seekOffset(countryOffset)
|
||||||
|
mode2 := q.readMode() // 标志字节
|
||||||
|
switch mode2 {
|
||||||
|
case RedirectMode2: // 标志字节为2,表示国家信息又被重定向
|
||||||
|
q.seekOffset(q.getRedirectOffset()) // 重定向地址
|
||||||
|
country = q.readString(0)
|
||||||
|
q.seekOffset(countryOffset + 4) // 重定向地址
|
||||||
|
area = q.readArea()
|
||||||
|
default: // 否则,表示国家信息没有被重定向
|
||||||
|
country = q.readString(mode2)
|
||||||
|
area = q.readArea()
|
||||||
|
}
|
||||||
|
case RedirectMode2: // 标志字节为2,表示国家信息被重定向
|
||||||
|
q.seekOffset(q.getRedirectOffset()) // 重定向地址
|
||||||
|
country = q.readString(0)
|
||||||
|
q.seekOffset(endIPOffset + 8)
|
||||||
|
area = q.readArea()
|
||||||
|
default:
|
||||||
|
country = q.readString(mode)
|
||||||
|
area = q.readArea()
|
||||||
|
}
|
||||||
|
countryUTF8, _ := enc.String(string(country))
|
||||||
|
if strings.Trim(countryUTF8, " ") == "CZ88.NET" {
|
||||||
|
res.Country = ""
|
||||||
|
} else {
|
||||||
|
res.Country = countryUTF8
|
||||||
|
}
|
||||||
|
areaUTF8, _ := enc.String(string(area))
|
||||||
|
if strings.Trim(areaUTF8, " ") == "CZ88.NET" {
|
||||||
|
res.Area = ""
|
||||||
|
} else {
|
||||||
|
res.Area = areaUTF8
|
||||||
|
}
|
||||||
|
return &res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *IPDict) findIndex(ip string) uint32 {
|
||||||
|
if false == checkIPv4(ip) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if nil == q.fileData {
|
||||||
|
err := q.Load(DefaultDict)
|
||||||
|
if nil != err {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uIP := ip2long(ip) // 将输入的IP地址转化为可比较的IP地址
|
||||||
|
min := uint32(0) // 搜索的下边界
|
||||||
|
max := q.totalIPNum // 搜索的上边界
|
||||||
|
findIndex := q.lastOffset // 如果没有找到就返回最后一条IP记录(IPDict.Dat的版本信息)
|
||||||
|
for min <= max {
|
||||||
|
// 当上边界小于下边界时,查找失败
|
||||||
|
mid := (min + max) / 2 // 计算近似中间记录
|
||||||
|
q.seekOffset(q.firstOffset + mid*IndexLen)
|
||||||
|
cBeginIP := q.getIPLong4() // 获取中间记录的开始IP地址
|
||||||
|
if uIP < cBeginIP { // 用户的IP小于中间记录的开始IP地址时
|
||||||
|
max = mid - 1 // 将搜索的上边界修改为中间记录减一
|
||||||
|
} else {
|
||||||
|
q.seekOffset(q.getRedirectOffset())
|
||||||
|
cEndIP := q.getIPLong4() // 获取中间记录的开始IP地址
|
||||||
|
if uIP > cEndIP { // 用户的IP大于中间记录的结束IP地址时
|
||||||
|
min = mid + 1 // 将搜索的下边界修改为中间记录加一
|
||||||
|
} else {
|
||||||
|
// 用户的IP在中间记录的IP范围内时
|
||||||
|
findIndex = q.firstOffset + mid*IndexLen
|
||||||
|
break // 则表示找到结果,退出循环
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return findIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
//模拟文件读取Seek
|
||||||
|
func (q *IPDict) seekOffset(offset uint32) {
|
||||||
|
q.offset = offset
|
||||||
|
}
|
||||||
|
|
||||||
|
//模拟文件读取Read
|
||||||
|
func (q *IPDict) readBuf(length uint32) []byte {
|
||||||
|
q.offset = q.offset + length
|
||||||
|
return q.fileData[q.offset-length : q.offset] // 标志字节
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回读取的长整型数
|
||||||
|
func (q *IPDict) getIPLong4() uint32 {
|
||||||
|
buf := q.readBuf(4)
|
||||||
|
return binary.LittleEndian.Uint32(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回读取的3个字节的长整型数
|
||||||
|
func (q *IPDict) getRedirectOffset() uint32 {
|
||||||
|
buf := q.readBuf(3)
|
||||||
|
return binary.LittleEndian.Uint32([]byte{buf[0], buf[1], buf[2], 0})
|
||||||
|
}
|
||||||
|
|
||||||
|
// readString 获取字符
|
||||||
|
func (q *IPDict) readMode() byte {
|
||||||
|
return q.readBuf(1)[0] // 标志字节
|
||||||
|
}
|
||||||
|
|
||||||
|
// readString 获取字符串
|
||||||
|
func (q *IPDict) readString(char byte) []byte {
|
||||||
|
data := make([]byte, 0, 30)
|
||||||
|
if char != 0 {
|
||||||
|
data = append(data, char)
|
||||||
|
}
|
||||||
|
buf := q.readBuf(1)
|
||||||
|
for buf[0] != 0 {
|
||||||
|
data = append(data, buf[0])
|
||||||
|
buf = q.readBuf(1)
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
// readArea 获取地区字符串
|
||||||
|
func (q *IPDict) readArea() []byte {
|
||||||
|
mode := q.readMode()
|
||||||
|
switch mode { // 标志字节
|
||||||
|
case 0: // 结束标识
|
||||||
|
return []byte{}
|
||||||
|
case RedirectMode1:
|
||||||
|
case RedirectMode2: // 标志字节为1或2,表示区域信息被重定向
|
||||||
|
q.seekOffset(q.getRedirectOffset()) // 重定向地址
|
||||||
|
return q.readString(0)
|
||||||
|
}
|
||||||
|
return q.readString(mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
//数值IP转换字符串IP
|
||||||
|
func long2ip(ipInt uint32) string {
|
||||||
|
// need to do two bit shifting and “0xff” masking
|
||||||
|
ipInt64 := int64(ipInt)
|
||||||
|
b0 := strconv.FormatInt((ipInt64>>24)&0xff, 10)
|
||||||
|
b1 := strconv.FormatInt((ipInt64>>16)&0xff, 10)
|
||||||
|
b2 := strconv.FormatInt((ipInt64>>8)&0xff, 10)
|
||||||
|
b3 := strconv.FormatInt(ipInt64&0xff, 10)
|
||||||
|
return b0 + "." + b1 + "." + b2 + "." + b3
|
||||||
|
}
|
||||||
|
|
||||||
|
//字符串IP转换数值IP
|
||||||
|
func ip2long(ip string) uint32 {
|
||||||
|
bIP := net.ParseIP(ip).To4()
|
||||||
|
if nil == bIP {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return binary.BigEndian.Uint32(bIP)
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回字典绝对路径
|
||||||
|
func dictPath(dictFileName string) (string, error) {
|
||||||
|
if filepath.IsAbs(dictFileName) {
|
||||||
|
return dictFileName, nil
|
||||||
|
}
|
||||||
|
var dictFilePath string
|
||||||
|
cwd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
return dictFilePath, err
|
||||||
|
}
|
||||||
|
dictFilePath = filepath.Clean(filepath.Join(cwd, dictFileName))
|
||||||
|
return dictFilePath, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//检查ip地址
|
||||||
|
func checkIPv4(IP string) bool {
|
||||||
|
// 字符串这样切割
|
||||||
|
strList := strings.Split(IP, ".")
|
||||||
|
if len(strList) != 4 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, s := range strList {
|
||||||
|
if len(s) == 0 || (len(s) > 1 && s[0] == '0') {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// 直接访问字符串的值
|
||||||
|
if s[0] < '0' || s[0] > '9' {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// 字符串转数字
|
||||||
|
n, err := strconv.Atoi(s)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if n < 0 || n > 255 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetIpAddress(ip string) (string, error) {
|
||||||
|
IPDict := NewIPDict()
|
||||||
|
//载入IP字典
|
||||||
|
err := IPDict.Load("../conf/qqwry.dat")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
//查询IP
|
||||||
|
res, err := IPDict.FindIP(ip)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return res.Country, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetIpOnlyAddress(ip string) string {
|
||||||
|
IPDict := NewIPDict()
|
||||||
|
//载入IP字典
|
||||||
|
err := IPDict.Load("../conf/qqwry.dat")
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
//查询IP
|
||||||
|
res, err := IPDict.FindIP(ip)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return res.Country
|
||||||
|
}
|
||||||
|
|
||||||
|
func AliIpAddress(ip string) (string, error) {
|
||||||
|
|
||||||
|
url := "https://c2ba.api.huachen.cn/ip?ip=" + ip
|
||||||
|
|
||||||
|
client := &http.Client{
|
||||||
|
Timeout: 1 * time.Second,
|
||||||
|
}
|
||||||
|
//提交请求
|
||||||
|
reqest, err := http.NewRequest("GET", url, nil)
|
||||||
|
|
||||||
|
//增加header选项
|
||||||
|
reqest.Header.Add("Authorization", "APPCODE 89aaef07254149aabac798c911647673")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return "", err
|
||||||
|
//panic(err)
|
||||||
|
}
|
||||||
|
//处理返回结果
|
||||||
|
response, err := client.Do(reqest)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
resByte, err := ioutil.ReadAll(response.Body)
|
||||||
|
|
||||||
|
fmt.Println("1-------------", string(resByte))
|
||||||
|
var result IpResultV2
|
||||||
|
err = json.Unmarshal(resByte, &result)
|
||||||
|
fmt.Printf("1-------------%+v\n", result)
|
||||||
|
|
||||||
|
defer response.Body.Close()
|
||||||
|
|
||||||
|
return result.Result.Country + result.Result.City, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetIpOnlyAddressFromAli(ip string) string {
|
||||||
|
IPDict := NewIPDict()
|
||||||
|
//载入IP字典
|
||||||
|
err := IPDict.Load("../conf/qqwry.dat")
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
//查询IP
|
||||||
|
res, err := IPDict.FindIP(ip)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return res.Country
|
||||||
|
}
|
11
pkg/common/utils/ip_test.go
Normal file
11
pkg/common/utils/ip_test.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAliIpAddress(t *testing.T) {
|
||||||
|
|
||||||
|
fmt.Println(AliIpAddress("58.208.146.190"))
|
||||||
|
}
|
19
pkg/common/utils/phone.go
Normal file
19
pkg/common/utils/phone.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import "regexp"
|
||||||
|
|
||||||
|
// CheckMobile 检验手机号
|
||||||
|
func CheckMobile(phone string) bool {
|
||||||
|
// 匹配规则
|
||||||
|
// ^1第一位为一
|
||||||
|
// [345789]{1} 后接一位345789 的数字
|
||||||
|
// \\d \d的转义 表示数字 {9} 接9位
|
||||||
|
// $ 结束符
|
||||||
|
regRuler := "^1[345789]{1}\\d{9}$"
|
||||||
|
|
||||||
|
// 正则调用规则
|
||||||
|
reg := regexp.MustCompile(regRuler)
|
||||||
|
|
||||||
|
// 返回 MatchString 是否匹配
|
||||||
|
return reg.MatchString(phone)
|
||||||
|
}
|
45
pkg/common/utils/phone_test.go
Normal file
45
pkg/common/utils/phone_test.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/fonchain_enterprise/utils/feie"
|
||||||
|
"log"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGet16MD5Encode(t *testing.T) {
|
||||||
|
|
||||||
|
info := feie.PrintInfo{
|
||||||
|
Num: "1829",
|
||||||
|
Date: "4/27",
|
||||||
|
DrinkName: "测试",
|
||||||
|
Tag: []string{"香草*5", "焦糖*5", "果子*10"},
|
||||||
|
Code: "测试--徐嘉鸿 13834233425",
|
||||||
|
}
|
||||||
|
feie := &feie.Feie{
|
||||||
|
User: "chenyao@taifeng.ltd",
|
||||||
|
Ukey: "8mxyRrjhCKzB4Pde",
|
||||||
|
Url: "http://api.feieyun.cn/Api/Open/",
|
||||||
|
}
|
||||||
|
res, err := feie.Print("960233232", info)
|
||||||
|
fmt.Println(res, err)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDecimalToAny(t *testing.T) {
|
||||||
|
fmt.Println(DecimalToAny(69))
|
||||||
|
IPDict := NewIPDict()
|
||||||
|
//载入IP字典
|
||||||
|
err := IPDict.Load("../../../conf/qqwry.dat")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
//查询IP
|
||||||
|
res, err := IPDict.FindIP("114.218.158.24")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
log.Println(res)
|
||||||
|
log.Println(res.Area)
|
||||||
|
log.Println(res.Country)
|
||||||
|
}
|
52
pkg/common/utils/time.go
Normal file
52
pkg/common/utils/time.go
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SubYearFromNowBefore(t1 time.Time) float32 {
|
||||||
|
t2 := time.Now()
|
||||||
|
res := float64(SubMonth(t2, t1)) / 12.0
|
||||||
|
value, err := strconv.ParseFloat(fmt.Sprintf("%.1f", res), 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return float32(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SubYearFromStartAndEnd(start time.Time,end time.Time) float32 {
|
||||||
|
res := float64(SubMonth(end, start)) / 12.0
|
||||||
|
value, err := strconv.ParseFloat(fmt.Sprintf("%.1f", res), 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return float32(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SubMonth(t1, t2 time.Time) (month int) {
|
||||||
|
y1 := t1.Year()
|
||||||
|
y2 := t2.Year()
|
||||||
|
m1 := int(t1.Month())
|
||||||
|
m2 := int(t2.Month())
|
||||||
|
d1 := t1.Day()
|
||||||
|
d2 := t2.Day()
|
||||||
|
|
||||||
|
yearInterval := y1 - y2
|
||||||
|
// 如果 d1的 月-日 小于 d2的 月-日 那么 yearInterval-- 这样就得到了相差的年数
|
||||||
|
if m1 < m2 || (m1 == m2 && d1 < d2) {
|
||||||
|
yearInterval--
|
||||||
|
}
|
||||||
|
// 获取月数差值
|
||||||
|
monthInterval := (m1 + 12) - m2
|
||||||
|
|
||||||
|
if d1 < d2 {
|
||||||
|
monthInterval--
|
||||||
|
}
|
||||||
|
monthInterval %= 12
|
||||||
|
month = yearInterval*12 + monthInterval
|
||||||
|
return
|
||||||
|
}
|
55
pkg/common/utils/ucode.go
Normal file
55
pkg/common/utils/ucode.go
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/md5"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
var tenToAny map[int]string = map[int]string{
|
||||||
|
0: "0", 1: "1", 2: "2", 3: "3", 4: "4", 5: "5", 6: "6", 7: "7", 8: "8", 9: "9",
|
||||||
|
10: "a", 11: "b", 12: "c", 13: "d", 14: "e", 15: "f", 16: "g", 17: "h", 18: "i", 19: "j", 20: "k", 21: "l", 22: "m", 23: "n", 24: "o", 25: "p", 26: "q", 27: "r", 28: "s", 29: "t", 30: "u", 31: "v", 32: "w", 33: "x", 34: "y", 35: "z",
|
||||||
|
36: "A", 37: "B", 38: "C", 39: "D", 40: "E", 41: "F", 42: "G", 43: "H", 44: "I", 45: "J", 46: "K", 47: "L", 48: "M", 49: "N", 50: "O", 51: "P", 52: "Q", 53: "R", 54: "S", 55: "T", 56: "U", 57: "V", 58: "W", 59: "X", 60: "Y", 61: "Z",
|
||||||
|
}
|
||||||
|
|
||||||
|
//SetLangErr 设置英语
|
||||||
|
func SetLangErr() float32 {
|
||||||
|
return float32(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回一个16位md5加密后的字符串
|
||||||
|
func Get16MD5Encode(data string) string {
|
||||||
|
return GetMD5Encode(data)[8:24]
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetMD5Encode(data string) string {
|
||||||
|
h := md5.New()
|
||||||
|
h.Write([]byte(data))
|
||||||
|
return hex.EncodeToString(h.Sum(nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecimalToAny 10进制转任意进制
|
||||||
|
func DecimalToAny(num int) string {
|
||||||
|
n := len(tenToAny)
|
||||||
|
fmt.Println("1----", n)
|
||||||
|
new_num_str := ""
|
||||||
|
var remainder int
|
||||||
|
var remainder_string string
|
||||||
|
for num != 0 {
|
||||||
|
remainder = num % n
|
||||||
|
fmt.Println(remainder)
|
||||||
|
|
||||||
|
remainder_string = tenToAny[remainder]
|
||||||
|
new_num_str = remainder_string + new_num_str
|
||||||
|
num = num / n
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(new_num_str) < 8 {
|
||||||
|
j := 8 - len(new_num_str)
|
||||||
|
for i := 0; i < j; i++ {
|
||||||
|
new_num_str = "0" + new_num_str
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new_num_str
|
||||||
|
}
|
82
pkg/common/utils/utils.go
Normal file
82
pkg/common/utils/utils.go
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/shopspring/decimal"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
|
//HasEnglish 判断字符串是否包含英文
|
||||||
|
func HasEnglish(s string) bool {
|
||||||
|
for _, r := range s {
|
||||||
|
if unicode.Is(unicode.Latin, r) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
//HasChinese 判断字符串是否包含中文
|
||||||
|
func HasChinese(s string) bool {
|
||||||
|
for _, r := range s {
|
||||||
|
if unicode.Is(unicode.Han, r) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
//HasEnglishAndChinese 判断字符串是否同时包含英文和中文
|
||||||
|
func HasEnglishAndChinese(s string) bool {
|
||||||
|
return HasEnglish(s) && HasChinese(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
//FirstIsBiggerOrEqualDec 比较两个string转化成数字对比大小
|
||||||
|
func FirstIsBiggerOrEqualDec(dec1, dec2 decimal.Decimal) (bool, error) {
|
||||||
|
|
||||||
|
// 比较 decimal.Decimal 值
|
||||||
|
if dec1.LessThan(dec2) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//FirstIsBiggerOrEqual 比较两个string转化成数字对比大小
|
||||||
|
func FirstIsBiggerOrEqual(dec1 decimal.Decimal, b string) (bool, error) {
|
||||||
|
|
||||||
|
dec2, err := decimal.NewFromString(b)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 比较 decimal.Decimal 值
|
||||||
|
if dec1.LessThan(dec2) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//FirstIsBiggerOrEqualString 比较两个string转化成数字对比大小
|
||||||
|
func FirstIsBiggerOrEqualString(a, b string) (bool, error) {
|
||||||
|
|
||||||
|
dec1, err := decimal.NewFromString(a)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
dec2, err := decimal.NewFromString(b)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 比较 decimal.Decimal 值
|
||||||
|
if dec1.LessThan(dec2) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
|
||||||
|
}
|
66
pkg/common/utils/utils_test.go
Normal file
66
pkg/common/utils/utils_test.go
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func Test_hasEnglish(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
s string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want bool
|
||||||
|
}{
|
||||||
|
{args: args{s: "阿丽米罕·色依提"}, want: false},
|
||||||
|
// TODO: Add test cases.
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if got := HasEnglish(tt.args.s); got != tt.want {
|
||||||
|
t.Errorf("hasEnglish() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_hasEnglishAndChinese(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
s string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want bool
|
||||||
|
}{
|
||||||
|
|
||||||
|
{args: args{s: "阿丽米罕·色依提"}, want: false},
|
||||||
|
// TODO: Add test cases.
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if got := HasEnglishAndChinese(tt.args.s); got != tt.want {
|
||||||
|
t.Errorf("hasEnglishAndChinese() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_hasEnglishAndChinese1(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
s string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want bool
|
||||||
|
}{
|
||||||
|
{args: args{s: "阿丽米罕·色依提"}, want: false},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if got := HasEnglishAndChinese(tt.args.s); got != tt.want {
|
||||||
|
t.Errorf("hasEnglishAndChinese() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
141
pkg/common/verifica/mobile.go
Normal file
141
pkg/common/verifica/mobile.go
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
package verifica
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/config"
|
||||||
|
"github.com/fonchain_enterprise/utils/mobile"
|
||||||
|
)
|
||||||
|
|
||||||
|
const SIG_NO = 155123
|
||||||
|
const SIG_NO_SELLER = 159789
|
||||||
|
|
||||||
|
func SendMsg(telNum string, project string) (string, error) {
|
||||||
|
|
||||||
|
var sigNo uint
|
||||||
|
sigNo = SIG_NO
|
||||||
|
|
||||||
|
if project == "seller" {
|
||||||
|
sigNo = SIG_NO_SELLER
|
||||||
|
}
|
||||||
|
|
||||||
|
mobileTemplate := config.GetMobile()
|
||||||
|
if telNum == "" {
|
||||||
|
return "", errors.New("手机号不合法")
|
||||||
|
}
|
||||||
|
|
||||||
|
code := mobile.RandCode()
|
||||||
|
//content := "验证码模板:尊敬的用户,您的验证码为$$,15分钟内有效,请勿泄露。"
|
||||||
|
fmt.Println("发送短信请求参数:", telNum, mobile.TMP1, sigNo, code)
|
||||||
|
|
||||||
|
/**
|
||||||
|
TODO
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
if telNum == "15895559080" {
|
||||||
|
dingding.Send(fmt.Sprintf("尊敬的用户,您的验证码为%s,15分钟内有效,请勿泄露。", code))
|
||||||
|
return code, nil
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
fmt.Println("发送短信请求参数:", telNum, mobile.TMP1, sigNo, code)
|
||||||
|
return code, mobileTemplate.Send(telNum, mobile.TMP1, sigNo, code)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func SendMsgV2(telNum string, project string, tempSignNo uint) (string, error) {
|
||||||
|
|
||||||
|
var sigNo uint
|
||||||
|
sigNo = SIG_NO
|
||||||
|
if project == "seller" {
|
||||||
|
sigNo = SIG_NO_SELLER
|
||||||
|
}
|
||||||
|
|
||||||
|
mobileTemplate := config.GetMobile()
|
||||||
|
//mobileTemplate := config.GetAlMobile()
|
||||||
|
if telNum == "" {
|
||||||
|
return "", errors.New("手机号不合法")
|
||||||
|
}
|
||||||
|
|
||||||
|
code := mobile.RandCode()
|
||||||
|
//content := "验证码模板:尊敬的用户,您的验证码为$$,15分钟内有效,请勿泄露。"
|
||||||
|
|
||||||
|
/**
|
||||||
|
TODO
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
if telNum == "15895559080" {
|
||||||
|
dingding.Send(fmt.Sprintf("尊敬的用户,您的验证码为%s,15分钟内有效,请勿泄露。", code))
|
||||||
|
return code, nil
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
fmt.Println("发送短信请求参数:", telNum, mobile.TMP1, sigNo, code)
|
||||||
|
return code, mobileTemplate.Send(telNum, mobile.TMP1, sigNo, code)
|
||||||
|
//fmt.Println("发送短信请求参数:", telNum, mobile.Sign, mobile.AlTMP1, code)
|
||||||
|
//return code, mobileTemplate.SendAlSms(telNum, mobile.Sign, mobile.AlTMP1, code)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func SendCustomMsg(telNum string, url string, m uint) error {
|
||||||
|
|
||||||
|
var sigNo uint
|
||||||
|
sigNo = SIG_NO
|
||||||
|
|
||||||
|
mobileTemplate := config.GetMobile()
|
||||||
|
if telNum == "" {
|
||||||
|
return errors.New("手机号不合法")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
TODO
|
||||||
|
if telNum == "15895559080" {
|
||||||
|
arr := strings.Split(url, "||")
|
||||||
|
if len(arr) <= 1 {
|
||||||
|
fmt.Println("解析失败")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if m == 134802 {
|
||||||
|
dingding.Send(fmt.Sprintf("尊敬的用户,您的帐号登陆地址(%s)异常,请点击下线该帐号%s", arr[0], arr[1]))
|
||||||
|
return nil
|
||||||
|
} else if m == 136784 {
|
||||||
|
dingding.Send(fmt.Sprintf("尊敬的用户,%s等待您的审批,请点击查看%s", arr[0], arr[1]))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
fmt.Println(telNum, m, sigNo, url)
|
||||||
|
|
||||||
|
return mobileTemplate.Send(telNum, m, sigNo, url)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SendCustomCode(telNum string, templateId uint, sigNo uint) (string, error) {
|
||||||
|
|
||||||
|
mobileTemplate := config.GetMobile()
|
||||||
|
//mobileTemplate := config.GetAlMobile()
|
||||||
|
|
||||||
|
if telNum == "" {
|
||||||
|
return "", errors.New("手机号不合法")
|
||||||
|
}
|
||||||
|
|
||||||
|
code := mobile.RandCode()
|
||||||
|
|
||||||
|
fmt.Println("发送短信请求参数:", telNum, mobile.TMP1, sigNo, code)
|
||||||
|
//fmt.Println("发送短信请求参数:", telNum, mobile.Sign, mobile.AlTMP1, code)
|
||||||
|
|
||||||
|
return code, mobileTemplate.Send(telNum, templateId, sigNo, code)
|
||||||
|
//return code, mobileTemplate.SendAlSms(telNum, mobile.Sign, mobile.AlTMP1, code)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SendCustomSignNoMsg(telNum string, url string, m uint, sigNo uint) error {
|
||||||
|
|
||||||
|
mobileTemplate := config.GetMobile()
|
||||||
|
//mobileTemplate := config.GetAlMobile()
|
||||||
|
if telNum == "" {
|
||||||
|
return errors.New("手机号不合法")
|
||||||
|
}
|
||||||
|
return mobileTemplate.Send(telNum, m, sigNo, url)
|
||||||
|
//return mobileTemplate.SendAlSms(telNum, mobile.Sign, mobile.AlTMP1, url)
|
||||||
|
}
|
28
pkg/common/verifica/mobile_test.go
Normal file
28
pkg/common/verifica/mobile_test.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package verifica
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/config"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSendCustomMsg(t *testing.T) {
|
||||||
|
|
||||||
|
msgInfo := config.MobileConfigTemplate{
|
||||||
|
AK: "N7469940cf",
|
||||||
|
SK: "74699ca8e1ea8f80",
|
||||||
|
URL: "https://api.4321.sh/sms/template",
|
||||||
|
}
|
||||||
|
almsgInfo := config.AliMessage{
|
||||||
|
AK: "LTAI5tFLAxtbtTsD4xAEtWcr",
|
||||||
|
AS: "ooHMm6GuRs1InieHojZaTjEJAMquKX",
|
||||||
|
URL: "dysmsapi.aliyuncs.com",
|
||||||
|
}
|
||||||
|
fmt.Println("短信配置", msgInfo)
|
||||||
|
config.LoadData(msgInfo, almsgInfo)
|
||||||
|
|
||||||
|
mobileTemplate := config.GetMobile()
|
||||||
|
|
||||||
|
fmt.Println(mobileTemplate.Send("18362666451", 136784, 155123, "用印申请0||https://dwz.cn/gwc1q4D8"))
|
||||||
|
|
||||||
|
}
|
82
pkg/common/wechat/access_token.go
Normal file
82
pkg/common/wechat/access_token.go
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
package wechat
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/cache"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TokenInfo struct {
|
||||||
|
AccessToken string `json:"access_token"`
|
||||||
|
CreateDate string `json:"createDate"`
|
||||||
|
ErrCode int `json:"errcode"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func getNowAccessToken(appID, appSecret string) (openInfo *TokenInfo, err error) {
|
||||||
|
|
||||||
|
str := "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s"
|
||||||
|
url := fmt.Sprintf(str, appID, appSecret)
|
||||||
|
|
||||||
|
resp, err := http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode != 200 {
|
||||||
|
fmt.Printf("请求失败%d\n", resp.StatusCode)
|
||||||
|
return nil, errors.New(fmt.Sprintf("请求失败%d", resp.StatusCode))
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("返回数据是", string(body))
|
||||||
|
|
||||||
|
err = json.Unmarshal(body, &openInfo)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if openInfo.ErrCode != 0 {
|
||||||
|
fmt.Println("微信提示错误", string(body))
|
||||||
|
return nil, errors.New("微信提示错误:" + string(body))
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAccessToken(appID, appSecret string) (openInfo *TokenInfo, err error) {
|
||||||
|
|
||||||
|
key := "wx:token:" + appID
|
||||||
|
|
||||||
|
str := cache.RedisClient.Get(key)
|
||||||
|
if str.Val() != "" { //存在
|
||||||
|
err := json.Unmarshal([]byte(str.Val()), &openInfo)
|
||||||
|
return openInfo, err
|
||||||
|
}
|
||||||
|
|
||||||
|
//更新
|
||||||
|
openInfo, err = getNowAccessToken(appID, appSecret)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
openInfo.CreateDate = time.Now().Format("2006-01-02 15:04:05")
|
||||||
|
|
||||||
|
r, err := json.Marshal(openInfo)
|
||||||
|
|
||||||
|
fmt.Println(string(r))
|
||||||
|
|
||||||
|
_, err = cache.RedisClient.Set(key, string(r), 6500*time.Second).Result()
|
||||||
|
|
||||||
|
return openInfo, err
|
||||||
|
|
||||||
|
}
|
209
pkg/common/wechat/tempate/template.go
Normal file
209
pkg/common/wechat/tempate/template.go
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
package tempate
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/cache"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/common/redis_key"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/common/wechat"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ClockInTemplate struct {
|
||||||
|
ToUser string `json:"touser"`
|
||||||
|
TemplateID string `json:"template_id"`
|
||||||
|
ClientMsgID string `json:"client_msg_id"`
|
||||||
|
ClockInMsgData ClockInMsgData `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type StrangerClockInTemplate struct {
|
||||||
|
ToUser string `json:"touser"`
|
||||||
|
TemplateID string `json:"template_id"`
|
||||||
|
ClientMsgID string `json:"client_msg_id"`
|
||||||
|
Url string `json:"url"`
|
||||||
|
ClockInMsgData StrangerClockInMsgData `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Thing struct {
|
||||||
|
Value string `json:"value"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ClockInMsgData struct {
|
||||||
|
Time3 Thing `json:"time3"`
|
||||||
|
Name Thing `json:"thing1"`
|
||||||
|
Const2 Thing `json:"const2"`
|
||||||
|
Thing5 Thing `json:"thing5"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type StrangerClockInMsgData struct {
|
||||||
|
Thing2 Thing `json:"thing2"`
|
||||||
|
PhoneNumber10 Thing `json:"phone_number10"`
|
||||||
|
CharacterString14 Thing `json:"character_string14"`
|
||||||
|
Thing6 Thing `json:"thing6"`
|
||||||
|
Const11 Thing `json:"const11"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ClockInTemplateMsgInfo struct {
|
||||||
|
TemplateId string
|
||||||
|
OpenId string
|
||||||
|
OperatedAt string
|
||||||
|
Name string
|
||||||
|
Address string
|
||||||
|
ClockType string
|
||||||
|
VisitorSName string
|
||||||
|
VisitorSTel string
|
||||||
|
ReasonVisit string
|
||||||
|
NumberOfPeople uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
func SendStrangerWechatTempMsg(wechatObj wechat.Wechat, info ClockInTemplateMsgInfo, logID uint64) error {
|
||||||
|
appID := wechatObj.Appid
|
||||||
|
appSecret := wechatObj.AppSecret
|
||||||
|
accessToken, err := wechat.GetAccessToken(appID, appSecret)
|
||||||
|
URL := fmt.Sprintf("https://material.szjixun.cn/#/pages/control-gate/index?sn=%v&id=%v", info.Address, logID)
|
||||||
|
|
||||||
|
clockInTemplate := StrangerClockInTemplate{
|
||||||
|
ToUser: info.OpenId,
|
||||||
|
TemplateID: info.TemplateId,
|
||||||
|
ClientMsgID: uuid.New().String(),
|
||||||
|
Url: URL,
|
||||||
|
ClockInMsgData: StrangerClockInMsgData{
|
||||||
|
Thing2: Thing{info.VisitorSName}, //来访人员
|
||||||
|
PhoneNumber10: Thing{info.VisitorSTel}, //联系电话
|
||||||
|
CharacterString14: Thing{strconv.FormatUint(info.NumberOfPeople, 10)}, //随行人数
|
||||||
|
Thing6: Thing{info.Name}, //拜访人
|
||||||
|
Const11: Thing{info.ReasonVisit}, //拜访事由
|
||||||
|
},
|
||||||
|
}
|
||||||
|
msg, err := json.Marshal(clockInTemplate)
|
||||||
|
|
||||||
|
openInfo, err := sendTemplateMsg(accessToken.AccessToken, msg)
|
||||||
|
fmt.Println("提示设呢么", openInfo, err)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("123123--123", openInfo)
|
||||||
|
fmt.Println(openInfo.Errmsg)
|
||||||
|
fmt.Println(openInfo.Errcode)
|
||||||
|
|
||||||
|
if openInfo.Errcode != 40001 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("不顶用")
|
||||||
|
cache.RedisClient.Del(redis_key.GetWxAccessToken(appID))
|
||||||
|
|
||||||
|
return sendTemplateMsgAgain(appID, appSecret, msg)
|
||||||
|
}
|
||||||
|
func SendWechatTemplateMsg(wechatObj wechat.Wechat, info ClockInTemplateMsgInfo) error {
|
||||||
|
clockType := "上班"
|
||||||
|
appID := wechatObj.Appid
|
||||||
|
appSecret := wechatObj.AppSecret
|
||||||
|
templateId, openId, operatedAt, Name, address, _ := info.TemplateId, info.OpenId, info.OperatedAt, info.Name, info.Address, info.ClockType
|
||||||
|
|
||||||
|
accessToken, err := wechat.GetAccessToken(appID, appSecret)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if info.ClockType == "off" {
|
||||||
|
clockType = "下班"
|
||||||
|
}
|
||||||
|
|
||||||
|
clockInTemplate := ClockInTemplate{
|
||||||
|
ToUser: openId,
|
||||||
|
TemplateID: templateId,
|
||||||
|
ClientMsgID: uuid.New().String(),
|
||||||
|
ClockInMsgData: ClockInMsgData{
|
||||||
|
Time3: Thing{Value: operatedAt},
|
||||||
|
Name: Thing{Value: Name},
|
||||||
|
Const2: Thing{Value: clockType},
|
||||||
|
Thing5: Thing{Value: address},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
msg, err := json.Marshal(clockInTemplate)
|
||||||
|
|
||||||
|
openInfo, err := sendTemplateMsg(accessToken.AccessToken, msg)
|
||||||
|
fmt.Println("提示设呢么", openInfo, err)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("123123--123", openInfo)
|
||||||
|
fmt.Println(openInfo.Errmsg)
|
||||||
|
fmt.Println(openInfo.Errcode)
|
||||||
|
|
||||||
|
if openInfo.Errcode != 40001 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("不顶用")
|
||||||
|
cache.RedisClient.Del(redis_key.GetWxAccessToken(appID))
|
||||||
|
|
||||||
|
return sendTemplateMsgAgain(appID, appSecret, msg)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendTemplateMsgAgain(appID, appSecret string, msg []byte) error {
|
||||||
|
accessToken, err := wechat.GetAccessToken(appID, appSecret)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
openInfo, err := sendTemplateMsg(accessToken.AccessToken, msg)
|
||||||
|
fmt.Println("提示设呢么", openInfo, err)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("123123--123", openInfo)
|
||||||
|
fmt.Println(openInfo.Errmsg)
|
||||||
|
fmt.Println(openInfo.Errcode)
|
||||||
|
if openInfo.Errcode != 40001 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return errors.New(openInfo.Errmsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// "errcode": 0,
|
||||||
|
// "errmsg": "ok",
|
||||||
|
func sendTemplateMsg(accessToken string, code []byte) (res *wechat.CommonRes, err error) {
|
||||||
|
url := "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + accessToken
|
||||||
|
|
||||||
|
// 创建要发送的数据
|
||||||
|
|
||||||
|
// 发送POST请求
|
||||||
|
resp, err := http.Post(url, "application/json", bytes.NewBuffer(code))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("发送请求失败:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
|
||||||
|
if resp.StatusCode != 200 {
|
||||||
|
fmt.Printf("请求失败%d\n", resp.StatusCode)
|
||||||
|
return nil, errors.New(fmt.Sprintf("请求失败%d", resp.StatusCode))
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("2--返回数据是", string(body))
|
||||||
|
|
||||||
|
err = json.Unmarshal(body, &res)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, err
|
||||||
|
}
|
46
pkg/common/wechat/tempate/template_test.go
Normal file
46
pkg/common/wechat/tempate/template_test.go
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package tempate
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/cache"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/common/wechat"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSendWechatTemplateMsg(t *testing.T) {
|
||||||
|
|
||||||
|
redisConfig := cache.RedisConfig{
|
||||||
|
RedisDB: "1",
|
||||||
|
RedisAddr: "r-bp1mjimyh1ejg1mxclpd.redis.rds.aliyuncs.com:6379",
|
||||||
|
RedisPw: "fonchain_opv:kP6tW4tS3qB2dW4aE6uI5cX2",
|
||||||
|
RedisDbName: "1",
|
||||||
|
}
|
||||||
|
|
||||||
|
cache.LoadRedis(redisConfig)
|
||||||
|
|
||||||
|
type args struct {
|
||||||
|
appID string
|
||||||
|
appSecret string
|
||||||
|
templateId string
|
||||||
|
openId string
|
||||||
|
operatedAt string
|
||||||
|
Name string
|
||||||
|
address string
|
||||||
|
clockType string
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{args: args{appID: "wx72ffc6670d5ddb12", appSecret: "50bec0ef9a7883de5b2fb3a74b23aff4", templateId: "alklszCrWJsueAOFwdlrvo2rN-XXwHqE_oHl_55kQmo", openId: "o_ath6SpAdmfaLeZD8v1mc_c-XxU", operatedAt: "2023-07-18 13:48:12", Name: "耿阳", address: "顾廷龙", clockType: "off"}},
|
||||||
|
// TODO: Add test cases.
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if err := SendWechatTemplateMsg(wechat.Wechat{Appid: tt.args.appID, AppSecret: tt.args.appSecret}, ClockInTemplateMsgInfo{TemplateId: tt.args.templateId, OpenId: tt.args.openId, OperatedAt: tt.args.operatedAt, Name: tt.args.Name, Address: tt.args.address, ClockType: tt.args.clockType}); (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("SendWechatTemplateMsg() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
339
pkg/common/wechat/wechat.go
Normal file
339
pkg/common/wechat/wechat.go
Normal file
@ -0,0 +1,339 @@
|
|||||||
|
package wechat
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/cache"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/common/redis_key"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Wechat struct {
|
||||||
|
Appid string
|
||||||
|
AppSecret string
|
||||||
|
}
|
||||||
|
|
||||||
|
type OpenIDInfo struct {
|
||||||
|
AccessToken string `json:"access_token"`
|
||||||
|
ExpiresIn int `json:"expires_in"`
|
||||||
|
RefreshToken string `json:"refresh_token"`
|
||||||
|
Openid string `json:"openid"`
|
||||||
|
Scope string `json:"scope"`
|
||||||
|
IsSnapshotuser int `json:"is_snapshotuser"`
|
||||||
|
Unionid string `json:"unionid"`
|
||||||
|
Errmsg string `json:"errmsg"`
|
||||||
|
Errcode int `json:"errcode"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PhoneRes struct {
|
||||||
|
PhoneInfo *PhoneInfo `json:"phone_info"`
|
||||||
|
Errmsg string `json:"errmsg"`
|
||||||
|
Errcode int `json:"errcode"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CommonRes struct {
|
||||||
|
Errmsg string `json:"errmsg"`
|
||||||
|
Errcode int `json:"errcode"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PhoneInfo struct {
|
||||||
|
PhoneNumber string `json:"phoneNumber"`
|
||||||
|
PurePhoneNumber string `json:"purePhoneNumber"`
|
||||||
|
Errcode int `json:"errcode"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type BoxOpenId struct {
|
||||||
|
Openid string `json:"openid"`
|
||||||
|
Errmsg string `json:"errmsg"`
|
||||||
|
Errcode int `json:"errcode"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type BoxAccessToken struct {
|
||||||
|
AccessToken string `json:"access_token"`
|
||||||
|
ExpiresIn int `json:"expires_in"`
|
||||||
|
RefreshToken string `json:"refresh_token"`
|
||||||
|
Errmsg string `json:"errmsg"`
|
||||||
|
Errcode int `json:"errcode"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetOpenID(appID, appSecret, code string) (openInfo *OpenIDInfo, err error) {
|
||||||
|
|
||||||
|
var openIDInfo *OpenIDInfo
|
||||||
|
str := "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code"
|
||||||
|
url := fmt.Sprintf(str, appID, appSecret, code)
|
||||||
|
|
||||||
|
resp, err := http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode != 200 {
|
||||||
|
fmt.Printf("请求失败%d\n", resp.StatusCode)
|
||||||
|
return nil, errors.New(fmt.Sprintf("请求失败%d", resp.StatusCode))
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("返回数据是", string(body))
|
||||||
|
|
||||||
|
err = json.Unmarshal(body, &openInfo)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
fmt.Println(openIDInfo)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetBoxPhone(appID, appSecret, code string) (string, error) {
|
||||||
|
accessToken, err := GetBoxAccessToken(appID, appSecret)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
openInfo, err := getBoxPhone(accessToken, code)
|
||||||
|
fmt.Println("提示设呢么", openInfo, err)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("123123--123", openInfo)
|
||||||
|
fmt.Println(openInfo.Errmsg)
|
||||||
|
fmt.Println(openInfo.Errcode)
|
||||||
|
|
||||||
|
if openInfo.Errcode != 40001 && openInfo.PhoneInfo != nil {
|
||||||
|
return openInfo.PhoneInfo.PurePhoneNumber, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("不顶用")
|
||||||
|
cache.RedisClient.Del(redis_key.GetBoxAccessToken(appID))
|
||||||
|
|
||||||
|
return getBoxPhoneAgain(appID, appSecret, code)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func getBoxPhoneAgain(appID, appSecret, code string) (string, error) {
|
||||||
|
accessToken, err := GetBoxAccessToken(appID, appSecret)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
openInfo, err := getBoxPhone(accessToken, code)
|
||||||
|
fmt.Println("提示设呢么", openInfo, err)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("123123--123", openInfo)
|
||||||
|
fmt.Println(openInfo.Errmsg)
|
||||||
|
fmt.Println(openInfo.Errcode)
|
||||||
|
if openInfo.Errcode != 40001 && openInfo.PhoneInfo != nil {
|
||||||
|
return openInfo.PhoneInfo.PurePhoneNumber, nil
|
||||||
|
}
|
||||||
|
return "", errors.New(openInfo.Errmsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBoxOpenID 获取小程序的openid
|
||||||
|
func GetBoxOpenID(appID, appSecret, code string) (string, error) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
accessToken, err := GetBoxAccessToken(appID, appSecret)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
openInfo, err := getLoginOpenIdByCode(appID, appSecret, code)
|
||||||
|
fmt.Println("提示设呢么", openInfo, err)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return openInfo, nil
|
||||||
|
//cache.RedisClient.Del(redis_key.GetBoxAccessToken(appID))
|
||||||
|
|
||||||
|
//return getBoxOpenIDAgain(appID, appSecret, code)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getBoxOpenIDAgain(appID, appSecret, code string) (string, error) {
|
||||||
|
|
||||||
|
accessToken, err := GetBoxAccessToken(appID, appSecret)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
openInfo, err := getOpenIdByCode(accessToken, code)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if openInfo.Errcode != 0 {
|
||||||
|
return "", errors.New(openInfo.Errmsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
return openInfo.Openid, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getLoginOpenIdByCode(appId, appSecret, code string) (string, error) {
|
||||||
|
|
||||||
|
str := "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code"
|
||||||
|
url := fmt.Sprintf(str, appId, appSecret, code)
|
||||||
|
|
||||||
|
resp, err := http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
|
||||||
|
if resp.StatusCode != 200 {
|
||||||
|
fmt.Printf("请求失败%d\n", resp.StatusCode)
|
||||||
|
return "", errors.New(fmt.Sprintf("请求失败%d", resp.StatusCode))
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("2--返回数据是", string(body))
|
||||||
|
|
||||||
|
var openInfo OpenIDInfo
|
||||||
|
err = json.Unmarshal(body, &openInfo)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if openInfo.Errcode != 0 {
|
||||||
|
|
||||||
|
return "", errors.New(openInfo.Errmsg)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return openInfo.Openid, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func getOpenIdByCode(accessToken, code string) (openInfo *OpenIDInfo, err error) {
|
||||||
|
|
||||||
|
url := "https://api.weixin.qq.com/wxa/getpluginopenpid?access_token=" + accessToken
|
||||||
|
|
||||||
|
// 创建要发送的数据
|
||||||
|
|
||||||
|
data := []byte(fmt.Sprintf(`{"code": "%s"}`, code))
|
||||||
|
fmt.Println("1-------------", string(data))
|
||||||
|
fmt.Println("1-------------", accessToken)
|
||||||
|
|
||||||
|
// 发送POST请求
|
||||||
|
resp, err := http.Post(url, "application/json", bytes.NewBuffer(data))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("发送请求失败:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
|
||||||
|
if resp.StatusCode != 200 {
|
||||||
|
fmt.Printf("请求失败%d\n", resp.StatusCode)
|
||||||
|
return nil, errors.New(fmt.Sprintf("请求失败%d", resp.StatusCode))
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("2--返回数据是", string(body))
|
||||||
|
|
||||||
|
err = json.Unmarshal(body, &openInfo)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return openInfo, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// getBoxPhone 获取手机号
|
||||||
|
func getBoxPhone(accessToken, code string) (res *PhoneRes, err error) {
|
||||||
|
url := "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + accessToken
|
||||||
|
|
||||||
|
// 创建要发送的数据
|
||||||
|
data := []byte(fmt.Sprintf(`{"code": "%s"}`, code))
|
||||||
|
|
||||||
|
// 发送POST请求
|
||||||
|
resp, err := http.Post(url, "application/json", bytes.NewBuffer(data))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("发送请求失败:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
|
||||||
|
if resp.StatusCode != 200 {
|
||||||
|
fmt.Printf("请求失败%d\n", resp.StatusCode)
|
||||||
|
return nil, errors.New(fmt.Sprintf("请求失败%d", resp.StatusCode))
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("2--返回数据是", string(body))
|
||||||
|
|
||||||
|
err = json.Unmarshal(body, &res)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetBoxAccessToken(appID, appSecret string) (string, error) {
|
||||||
|
|
||||||
|
accessToken := cache.RedisClient.Get(redis_key.GetBoxAccessToken(appID)).Val()
|
||||||
|
|
||||||
|
if accessToken != "" {
|
||||||
|
return accessToken, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var openIDInfo *BoxAccessToken
|
||||||
|
|
||||||
|
str := "https://api.weixin.qq.com/cgi-bin/token?appid=%s&secret=%s&grant_type=client_credential"
|
||||||
|
url := fmt.Sprintf(str, appID, appSecret)
|
||||||
|
|
||||||
|
resp, err := http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode != 200 {
|
||||||
|
fmt.Printf("请求失败%d\n", resp.StatusCode)
|
||||||
|
return "", errors.New(fmt.Sprintf("请求失败%d", resp.StatusCode))
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("返回数据是", string(body))
|
||||||
|
|
||||||
|
err = json.Unmarshal(body, &openIDInfo)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
//记录下
|
||||||
|
fmt.Println("123123123", redis_key.GetBoxAccessToken(appID), openIDInfo.AccessToken)
|
||||||
|
fmt.Println(redis_key.GetBoxAccessToken(appID), openIDInfo.AccessToken)
|
||||||
|
cache.RedisClient.Set(redis_key.GetBoxAccessToken(appID), openIDInfo.AccessToken, 6000*time.Second)
|
||||||
|
|
||||||
|
return openIDInfo.AccessToken, nil
|
||||||
|
|
||||||
|
}
|
84
pkg/common/wechat/wechat_test.go
Normal file
84
pkg/common/wechat/wechat_test.go
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
package wechat
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/cache"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetOpenID(t *testing.T) {
|
||||||
|
|
||||||
|
redisConfig := cache.RedisConfig{
|
||||||
|
RedisDB: "2",
|
||||||
|
RedisAddr: "127.0.0.1:6379",
|
||||||
|
RedisPw: "",
|
||||||
|
RedisDbName: "2",
|
||||||
|
}
|
||||||
|
|
||||||
|
cache.LoadRedis(redisConfig)
|
||||||
|
|
||||||
|
type args struct {
|
||||||
|
appID string
|
||||||
|
appSecret string
|
||||||
|
code string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
wantOpenInfo *OpenIDInfo
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{name: "", args: args{appID: "wx2ab0adfa3346d44f", appSecret: "d85d38e7a055432254a09f00899971c8", code: "xxx"}, wantOpenInfo: &OpenIDInfo{}},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
gotOpenInfo, err := GetBoxOpenID(tt.args.appID, tt.args.appSecret, tt.args.code)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("GetOpenID() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(gotOpenInfo, tt.wantOpenInfo) {
|
||||||
|
t.Errorf("GetOpenID() gotOpenInfo = %v, want %v", gotOpenInfo, tt.wantOpenInfo)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetBoxPhone(t *testing.T) {
|
||||||
|
|
||||||
|
redisConfig := cache.RedisConfig{
|
||||||
|
RedisDB: "2",
|
||||||
|
RedisAddr: "127.0.0.1:6379",
|
||||||
|
RedisPw: "",
|
||||||
|
RedisDbName: "2",
|
||||||
|
}
|
||||||
|
|
||||||
|
cache.LoadRedis(redisConfig)
|
||||||
|
type args struct {
|
||||||
|
appID string
|
||||||
|
appSecret string
|
||||||
|
code string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want string
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
|
||||||
|
{name: "", args: args{appID: "wx2ab0adfa3346d44f", appSecret: "d85d38e7a055432254a09f00899971c8", code: "xxx"}},
|
||||||
|
// TODO: Add test cases.
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, err := GetBoxPhone(tt.args.appID, tt.args.appSecret, tt.args.code)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("GetBoxPhone() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if got != tt.want {
|
||||||
|
t.Errorf("GetBoxPhone() got = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
33
pkg/config/config.go
Normal file
33
pkg/config/config.go
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/fonchain_enterprise/utils/mobile"
|
||||||
|
)
|
||||||
|
|
||||||
|
var MobileConfig MobileConfigTemplate
|
||||||
|
var mobileTemplate mobile.Message
|
||||||
|
var mobileAlTemplate mobile.AliMessage
|
||||||
|
|
||||||
|
type MobileConfigTemplate struct {
|
||||||
|
AK string
|
||||||
|
SK string
|
||||||
|
URL string
|
||||||
|
}
|
||||||
|
type AliMessage struct {
|
||||||
|
AK string
|
||||||
|
AS string
|
||||||
|
URL string
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetMobile() mobile.Message {
|
||||||
|
return mobileTemplate
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAlMobile() mobile.AliMessage {
|
||||||
|
return mobileAlTemplate
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadData(info MobileConfigTemplate, alInfo AliMessage) {
|
||||||
|
mobileTemplate = mobile.NewFeiGe(info.AK, info.SK, info.URL)
|
||||||
|
mobileAlTemplate = mobile.NewAli(alInfo.AK, alInfo.AS, alInfo.URL)
|
||||||
|
}
|
1
pkg/domain/account.go
Normal file
1
pkg/domain/account.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package domain
|
1
pkg/domain/coin.go
Normal file
1
pkg/domain/coin.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package domain
|
203
pkg/domain/msg_code.go
Normal file
203
pkg/domain/msg_code.go
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
package domain
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/cache"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/common/redis_key"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/m"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CheckMsg(key string) error {
|
||||||
|
|
||||||
|
n, err := cache.RedisClient.Exists(key).Result()
|
||||||
|
fmt.Println("n", n)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if n == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
str := cache.RedisClient.Get(key)
|
||||||
|
|
||||||
|
num, err := str.Int()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if num > 30 {
|
||||||
|
return errors.New(m.Mobile_Send_Over)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckMsgPre 检测短信发送限制
|
||||||
|
func CheckMsgPre(domain string, telNum string, scope string) error {
|
||||||
|
|
||||||
|
key := redis_key.GetAccountKeyCountTodayHour(domain, telNum, scope)
|
||||||
|
|
||||||
|
//一分钟最多发一条
|
||||||
|
minStr := cache.RedisClient.Get(redis_key.MinLimit(domain, telNum, scope))
|
||||||
|
|
||||||
|
if minStr.Val() != "" {
|
||||||
|
return errors.New(m.Mobile_Sended)
|
||||||
|
}
|
||||||
|
|
||||||
|
//一个小时最多10次
|
||||||
|
n, err := cache.RedisClient.Exists(key).Result()
|
||||||
|
fmt.Println("n", n)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if n == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
str := cache.RedisClient.Get(key)
|
||||||
|
|
||||||
|
num, err := str.Int()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if num > 10 {
|
||||||
|
return errors.New(m.Mobile_Send_Over)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetOnlyRecordTelMsgCode 记录验证码
|
||||||
|
func SetOnlyRecordTelMsgCode(domain, tel, code, scope string) error {
|
||||||
|
|
||||||
|
//发送验证码
|
||||||
|
if merr := cache.RedisClient.Set(redis_key.GetOnlyAccountKey(domain, tel), code, 15*60*1000*time.Millisecond).Err(); merr != nil {
|
||||||
|
return merr
|
||||||
|
}
|
||||||
|
|
||||||
|
//发送验证码
|
||||||
|
if merr := cache.RedisClient.Set(redis_key.MinLimit(domain, tel, scope), code, 1*60*1000*time.Millisecond).Err(); merr != nil {
|
||||||
|
return merr
|
||||||
|
}
|
||||||
|
|
||||||
|
return SetTodayNum(domain, tel)
|
||||||
|
}
|
||||||
|
|
||||||
|
// InBlockList 黑名单
|
||||||
|
func InBlockList(domain string, tel string) bool {
|
||||||
|
|
||||||
|
isExist, err := cache.RedisClient.HExists(redis_key.BlackListKey(domain), tel).Result() //发送注册验证码 校验验证码时间限制
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if isExist == true {
|
||||||
|
fmt.Println("黑名单")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("白名单")
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// CodeLive 发送的验证码是否活着
|
||||||
|
func CodeLive(domain string, tel string) error {
|
||||||
|
|
||||||
|
str := cache.RedisClient.Get(redis_key.VerityCode(domain, tel)) //发送注册验证码 校验验证码时间限制
|
||||||
|
|
||||||
|
if str.Val() != "" {
|
||||||
|
return errors.New(m.Mobile_Sended)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetRecordTelMsgCode 发送短信成功之后记录部分信息
|
||||||
|
func SetRecordTelMsgCode(domain string, tel string, code string) error {
|
||||||
|
|
||||||
|
//发送验证码
|
||||||
|
if merr := cache.RedisClient.Set(redis_key.GetAccountKey(domain, tel), code, 15*60*1000*time.Millisecond).Err(); merr != nil {
|
||||||
|
return merr
|
||||||
|
}
|
||||||
|
|
||||||
|
//发送验证码
|
||||||
|
if merr := cache.RedisClient.Set(redis_key.VerityCode(domain, tel), code, 55*1000*time.Millisecond).Err(); merr != nil {
|
||||||
|
return merr
|
||||||
|
}
|
||||||
|
|
||||||
|
//注册的时候验证码
|
||||||
|
if merr := cache.RedisClient.Set(redis_key.GetAccountRegisterKey(domain, tel), code, 60*60*1000*time.Millisecond).Err(); merr != nil {
|
||||||
|
return merr
|
||||||
|
}
|
||||||
|
|
||||||
|
return SetTodayNum(domain, tel)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetRecordTelMsgCodeLogin 登录之后发送的短信
|
||||||
|
func SetRecordTelMsgCodeLogin(domain string, tel string, code string, id string) error {
|
||||||
|
|
||||||
|
//一分钟之内的
|
||||||
|
fmt.Println(redis_key.GetOneMinuteKey(domain, tel, id))
|
||||||
|
if merr := cache.RedisClient.Set(redis_key.GetOneMinuteKey(domain, tel, id), code, 1*60*1000*time.Millisecond).Err(); merr != nil {
|
||||||
|
return merr
|
||||||
|
}
|
||||||
|
|
||||||
|
//15分钟之内的
|
||||||
|
if merr := cache.RedisClient.Set(redis_key.GetChangeTelKey(domain, tel, id), code, 15*60*1000*time.Millisecond).Err(); merr != nil {
|
||||||
|
return merr
|
||||||
|
}
|
||||||
|
|
||||||
|
if merr := cache.RedisClient.Set(redis_key.GetNowNewTelById(domain, id), tel, 24*60*60*1000*time.Millisecond).Err(); merr != nil {
|
||||||
|
return merr
|
||||||
|
}
|
||||||
|
|
||||||
|
return SetTodayNum(domain, tel)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DelRecordTelMsgCodeLogin 登录之后发送的短信
|
||||||
|
func DelRecordTelMsgCodeLogin(domain string, tel string, id string) error {
|
||||||
|
|
||||||
|
//15分钟之内的
|
||||||
|
if merr := cache.RedisClient.Del(redis_key.GetChangeTelKey(domain, tel, id), redis_key.GetOneMinuteKey(domain, tel, id)).Err(); merr != nil {
|
||||||
|
return merr
|
||||||
|
}
|
||||||
|
|
||||||
|
return SetTodayNum(domain, tel)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTodayNum 当日记录发送记录
|
||||||
|
func SetTodayNum(domain string, tel string) error {
|
||||||
|
//当日记录发送记录
|
||||||
|
telTodayNum := redis_key.GetAccountKeyCountToday(domain, tel)
|
||||||
|
cache.RedisClient.Incr(telTodayNum)
|
||||||
|
cache.RedisClient.Expire(telTodayNum, 24*60*60*1000*time.Millisecond)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CheckRegisterCode(domain string, tel string, code string) error {
|
||||||
|
|
||||||
|
str := cache.RedisClient.Get(redis_key.GetAccountRegisterKey(domain, tel))
|
||||||
|
|
||||||
|
cacheCode := str.Val()
|
||||||
|
|
||||||
|
if cacheCode == "" {
|
||||||
|
return errors.New("没有发送数据")
|
||||||
|
}
|
||||||
|
|
||||||
|
if code != cacheCode {
|
||||||
|
return errors.New("验证码错误")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
78
pkg/domain/msg_code_test.go
Normal file
78
pkg/domain/msg_code_test.go
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
package domain
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/cache"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/common/redis_key"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCheckMsg(t *testing.T) {
|
||||||
|
|
||||||
|
config := cache.RedisConfig{
|
||||||
|
RedisDB: "2",
|
||||||
|
RedisAddr: "127.0.0.1:6379",
|
||||||
|
RedisPw: "",
|
||||||
|
RedisDbName: "2",
|
||||||
|
}
|
||||||
|
|
||||||
|
cache.LoadRedis(config)
|
||||||
|
|
||||||
|
key := redis_key.GetAccountKeyCountTodayHour("test", "18205052627", "")
|
||||||
|
//key := redis_key.GetAccountKeyCountToday("test", "18205052627")
|
||||||
|
|
||||||
|
//没有字段
|
||||||
|
cache.RedisClient.Del(key)
|
||||||
|
|
||||||
|
if err := CheckMsg(key); err != nil {
|
||||||
|
t.Errorf("验证不通过 :%s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
//字段数字小于10
|
||||||
|
/*
|
||||||
|
cache.RedisClient.Set(key, 8, 0)
|
||||||
|
if err := CheckMsg(key); err != nil {
|
||||||
|
t.Errorf("验证不通过: %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
cache.RedisClient.Set(key, 11, 0)
|
||||||
|
if err := CheckMsg(key); err == nil {
|
||||||
|
t.Errorf("验证不通过:超过设定参数,没有提示")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInBlockList(t *testing.T) {
|
||||||
|
config := cache.RedisConfig{
|
||||||
|
RedisDB: "2",
|
||||||
|
RedisAddr: "127.0.0.1:6379",
|
||||||
|
RedisPw: "",
|
||||||
|
RedisDbName: "2",
|
||||||
|
}
|
||||||
|
|
||||||
|
cache.LoadRedis(config)
|
||||||
|
type args struct {
|
||||||
|
domain string
|
||||||
|
tel string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want bool
|
||||||
|
}{
|
||||||
|
// TODO: Add test cases.
|
||||||
|
{args: args{domain: "test", tel: "18205052627"}, want: true},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if InBlockList(tt.args.domain, tt.args.tel) == true {
|
||||||
|
fmt.Println("黑名单")
|
||||||
|
} else {
|
||||||
|
fmt.Println("白名单")
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
90
pkg/e/code.go
Normal file
90
pkg/e/code.go
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
package e
|
||||||
|
|
||||||
|
var (
|
||||||
|
JWTSecret = []byte("asdfqwer1234")
|
||||||
|
)
|
||||||
|
var (
|
||||||
|
Acquire_Daily_Login = "daily_login"
|
||||||
|
Acquire_Register = "register"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
TimeFormatMin = "2006-01-02 15:04"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
Success = 200
|
||||||
|
Error = 500
|
||||||
|
ParamsError = 400
|
||||||
|
InvalidToken = 501
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
Failed = 1
|
||||||
|
Ok = 0
|
||||||
|
NotLogin = 401
|
||||||
|
SUCCESS = 200
|
||||||
|
UpdatePasswordSuccess = 201
|
||||||
|
DeleteSuccess = 204
|
||||||
|
NotExistInentifier = 202
|
||||||
|
ERROR = 500
|
||||||
|
InvalidParams = 400
|
||||||
|
|
||||||
|
//成员错误
|
||||||
|
ErrorExistNick = 10001
|
||||||
|
ErrorExistUser = 10002
|
||||||
|
ErrorNotExistUser = 10003
|
||||||
|
ErrorNotCompare = 10004
|
||||||
|
ErrorNotComparePassword = 10005
|
||||||
|
ErrorFailEncryption = 10006
|
||||||
|
ErrorNotExistProduct = 10007
|
||||||
|
ErrorNotExistAddress = 10008
|
||||||
|
ErrorExistFavorite = 10009
|
||||||
|
|
||||||
|
//店家错误
|
||||||
|
ErrorBossCheckTokenFail = 20001
|
||||||
|
ErrorBossCheckTokenTimeout = 20002
|
||||||
|
ErrorBossToken = 20003
|
||||||
|
ErrorBoss = 20004
|
||||||
|
ErrorBossInsufficientAuthority = 20005
|
||||||
|
ErrorBossProduct = 20006
|
||||||
|
|
||||||
|
//管理员错误
|
||||||
|
ErrorAuthCheckTokenFail = 30001 //token 错误
|
||||||
|
ErrorAuthCheckTokenTimeout = 30002 //token 过期
|
||||||
|
ErrorAuthToken = 30003
|
||||||
|
ErrorAuth = 30004
|
||||||
|
ErrorAuthInsufficientAuthority = 30005
|
||||||
|
ErrorReadFile = 30006
|
||||||
|
ErrorSendEmail = 30007
|
||||||
|
ErrorCallApi = 30008
|
||||||
|
ErrorUnmarshalJson = 30009
|
||||||
|
ErrorAdminFindUser = 30010
|
||||||
|
//数据库错误
|
||||||
|
ErrorDatabase = 40001
|
||||||
|
|
||||||
|
//对象存储错误
|
||||||
|
ErrorOss = 50001
|
||||||
|
ErrorUploadFile = 50002
|
||||||
|
|
||||||
|
//店铺错误
|
||||||
|
ErrorExistShopName = 60001
|
||||||
|
ErrorNotExistShopName = 60002
|
||||||
|
ErrorNotAdmin = 60003
|
||||||
|
|
||||||
|
ErrNoDomain = 70001
|
||||||
|
ErrTelNum = 70002
|
||||||
|
ErrNoCode = 70003
|
||||||
|
ErrNoID = 70004
|
||||||
|
ErrNickName = 70005
|
||||||
|
InvalidID = 70006
|
||||||
|
InvalidPas = 70007
|
||||||
|
ErrStatus = 70008
|
||||||
|
ErrNoType = 70009
|
||||||
|
ErrNoUserID = 70010
|
||||||
|
ErrNoName = 70011
|
||||||
|
ErrNoDepCode = 70012
|
||||||
|
ErrNoTitle = 70013
|
||||||
|
ErrNoUrl = 70014
|
||||||
|
ErrNoMethod = 70015
|
||||||
|
)
|
75
pkg/e/msg.go
Normal file
75
pkg/e/msg.go
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
package e
|
||||||
|
|
||||||
|
var MsgFlags = map[int]string{
|
||||||
|
SUCCESS: "ok",
|
||||||
|
UpdatePasswordSuccess: "修改密码成功",
|
||||||
|
NotExistInentifier: "该第三方账号未绑定",
|
||||||
|
ERROR: "fail",
|
||||||
|
InvalidParams: "请求参数错误",
|
||||||
|
|
||||||
|
ErrorExistNick: "已存在该昵称",
|
||||||
|
ErrorExistUser: "已存在该用户名",
|
||||||
|
ErrorNotExistUser: "该用户不存在",
|
||||||
|
ErrorNotCompare: "账号密码错误",
|
||||||
|
ErrorNotComparePassword: "两次密码输入不一致",
|
||||||
|
ErrorFailEncryption: "加密失败",
|
||||||
|
ErrorNotExistProduct: "该商品不存在",
|
||||||
|
ErrorNotExistAddress: "该收获地址不存在",
|
||||||
|
ErrorExistFavorite: "已收藏该商品",
|
||||||
|
|
||||||
|
ErrorBossCheckTokenFail: "商家的Token鉴权失败",
|
||||||
|
ErrorBossCheckTokenTimeout: "商家TOken已超时",
|
||||||
|
ErrorBossToken: "商家的Token生成失败",
|
||||||
|
ErrorBoss: "商家Token错误",
|
||||||
|
ErrorBossInsufficientAuthority: "商家权限不足",
|
||||||
|
ErrorBossProduct: "商家读文件错误",
|
||||||
|
|
||||||
|
ErrorAuthCheckTokenFail: "Token鉴权失败",
|
||||||
|
ErrorAuthCheckTokenTimeout: "TOken已超时",
|
||||||
|
ErrorAuthToken: "Token生成失败",
|
||||||
|
ErrorAuth: "Token错误",
|
||||||
|
ErrorAuthInsufficientAuthority: "权限不足",
|
||||||
|
ErrorReadFile: "读文件失败",
|
||||||
|
ErrorSendEmail: "发送邮件失败",
|
||||||
|
ErrorCallApi: "调用接口失败",
|
||||||
|
ErrorUnmarshalJson: "解码JSON失败",
|
||||||
|
|
||||||
|
ErrorUploadFile: "上传失败",
|
||||||
|
ErrorAdminFindUser: "管理员查询用户失败",
|
||||||
|
|
||||||
|
ErrorDatabase: "数据库操作出错,请重试",
|
||||||
|
|
||||||
|
ErrorOss: "OSS配置错误",
|
||||||
|
|
||||||
|
ErrorExistShopName: "店铺已被注册,请检查店铺名称和统一社会信用码",
|
||||||
|
ErrorNotExistShopName: "店铺不存在",
|
||||||
|
ErrorNotAdmin: "非管理员",
|
||||||
|
|
||||||
|
InvalidToken: "Token验证失败",
|
||||||
|
|
||||||
|
ErrNoDomain: "环境变量必须要有",
|
||||||
|
ErrTelNum: "手机号码错误",
|
||||||
|
ErrNoCode: "验证码必须要有",
|
||||||
|
ErrNoID: "ID缺少",
|
||||||
|
ErrNickName: "请填写正确的姓名项",
|
||||||
|
InvalidID: "身份证长度18位",
|
||||||
|
InvalidPas: "密码不小于6位",
|
||||||
|
|
||||||
|
ErrStatus: "状态非法",
|
||||||
|
ErrNoType: "缺少类型",
|
||||||
|
ErrNoUserID: "缺少用户ID",
|
||||||
|
ErrNoName: "缺少名称",
|
||||||
|
ErrNoDepCode: "缺少部门code",
|
||||||
|
ErrNoTitle: "缺少标题",
|
||||||
|
ErrNoUrl: "缺少url",
|
||||||
|
ErrNoMethod: "缺少method",
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMsg 获取状态码对应信息
|
||||||
|
func GetMsg(code int) string {
|
||||||
|
msg, ok := MsgFlags[code]
|
||||||
|
if ok {
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
return MsgFlags[ERROR]
|
||||||
|
}
|
331
pkg/infrsatructure/external/mail/webmail_account.go
vendored
Normal file
331
pkg/infrsatructure/external/mail/webmail_account.go
vendored
Normal file
@ -0,0 +1,331 @@
|
|||||||
|
package mail
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/PuerkitoBio/goquery"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"net/http/cookiejar"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
//LoginSuccessUrl = "https://mail.fontree.cn/iredadmin/dashboard?checknew" //登录后的重定向地址
|
||||||
|
CreateUrl = "http://106.12.56.142/admin/box/new?new=true"
|
||||||
|
LoginUrl = "http://106.12.56.142/admin/login"
|
||||||
|
)
|
||||||
|
|
||||||
|
type iredCookie struct {
|
||||||
|
Cookie string
|
||||||
|
Name string
|
||||||
|
ExpireAt *time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
type IRedMail struct {
|
||||||
|
IsProd bool `json:"isProd"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
Domain string
|
||||||
|
*iredCookie
|
||||||
|
}
|
||||||
|
|
||||||
|
type CreateAccountInfo struct {
|
||||||
|
Username string
|
||||||
|
Password string
|
||||||
|
Cn string
|
||||||
|
}
|
||||||
|
|
||||||
|
var ReadMail *IRedMail
|
||||||
|
|
||||||
|
func LoadEnv(userName, psw, domain string, isProd bool) {
|
||||||
|
|
||||||
|
ReadMail = &IRedMail{
|
||||||
|
IsProd: isProd,
|
||||||
|
Username: userName,
|
||||||
|
Password: psw,
|
||||||
|
Domain: domain,
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//CreateMailAccount 创建电子邮箱账号
|
||||||
|
func (m *IRedMail) CreateMailAccount(new CreateAccountInfo) error {
|
||||||
|
|
||||||
|
if m.IsProd != true {
|
||||||
|
fmt.Println("过滤创建邮箱帐号")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//0 登陆
|
||||||
|
cookies, err := m.login()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
//1 先去解析csrf_token
|
||||||
|
csrfToken, err := m.getCsrfTokenBeforeAdd()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Println(csrfToken, err)
|
||||||
|
*/
|
||||||
|
//1 先去解析csrf_token
|
||||||
|
err = m.createAccount(cookies, new)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// login 登陆超管
|
||||||
|
func (m *IRedMail) login() ([]*http.Cookie, error) {
|
||||||
|
|
||||||
|
cookies, csrfToken, err := m.getCsrfTokenAndCookieBeforeLogin()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
fmt.Println(cookies, csrfToken)
|
||||||
|
|
||||||
|
loginUrl := LoginUrl
|
||||||
|
values := url.Values{}
|
||||||
|
values.Set("email", m.Username)
|
||||||
|
values.Set("password", m.Password)
|
||||||
|
values.Set("_csrf_token", csrfToken)
|
||||||
|
// 忽略HTTPS证书验证
|
||||||
|
tr := &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
|
}
|
||||||
|
|
||||||
|
tempCookieJar, _ := cookiejar.New(nil)
|
||||||
|
u, err := url.Parse("http://106.12.56.142")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
tempCookieJar.SetCookies(u, cookies)
|
||||||
|
|
||||||
|
// 创建一个自定义Transport的HTTP客户端
|
||||||
|
//client := &http.Client{Transport: tr, Jar:cookies }
|
||||||
|
client := &http.Client{Transport: tr, Jar: tempCookieJar}
|
||||||
|
|
||||||
|
// 发起POST请求
|
||||||
|
res, err := client.PostForm(loginUrl, values)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送请求
|
||||||
|
defer res.Body.Close()
|
||||||
|
//fmt.Println(res.)
|
||||||
|
str, err := io.ReadAll(res.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
fmt.Println("成功")
|
||||||
|
fmt.Println(string(str))
|
||||||
|
|
||||||
|
/*
|
||||||
|
if res.Request.URL.String() != LoginSuccessUrl {
|
||||||
|
msg := res.Request.URL.Query().Get("msg")
|
||||||
|
return errors.New("超管登录失败提示:" + msg)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
for _, cookie := range res.Cookies() {
|
||||||
|
temp := &iredCookie{
|
||||||
|
Cookie: cookie.Value,
|
||||||
|
Name: cookie.Name,
|
||||||
|
}
|
||||||
|
m.iredCookie = temp
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
return res.Cookies(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getCsrfTokenAndCookieBeforeLogin 登陆前获取token
|
||||||
|
func (m *IRedMail) getCsrfTokenAndCookieBeforeLogin() ([]*http.Cookie, string, error) {
|
||||||
|
var csrfToken string
|
||||||
|
var isExist bool
|
||||||
|
cookieJar, _ := cookiejar.New(nil)
|
||||||
|
|
||||||
|
tr := &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建一个HTTP客户端,并设置cookie jar
|
||||||
|
client := &http.Client{
|
||||||
|
Jar: cookieJar,
|
||||||
|
Transport: tr,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建登录请求
|
||||||
|
loginURL := LoginUrl
|
||||||
|
req, err := http.NewRequest("GET", loginURL, nil)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("创建请求失败:", err)
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送登录请求
|
||||||
|
res, err := client.Do(req)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("请求错误", loginURL, err)
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer res.Body.Close()
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
str, err := io.ReadAll(res.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析HTML
|
||||||
|
doc, err := goquery.NewDocumentFromReader(strings.NewReader(string(str)))
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
doc.Find("input[name='_csrf_token']").Each(func(i int, s *goquery.Selection) {
|
||||||
|
csrfToken, isExist = s.Attr("value")
|
||||||
|
fmt.Println("查找1---", csrfToken, isExist) // 输出: testUser
|
||||||
|
})
|
||||||
|
|
||||||
|
if isExist == false {
|
||||||
|
return nil, "", errors.New("没有查找到csrf_token")
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.Cookies(), csrfToken, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getCsrfTokenBeforeAdd 登陆前获取token
|
||||||
|
func (m *IRedMail) getCsrfTokenBeforeAdd() (string, error) {
|
||||||
|
var csrfToken string
|
||||||
|
var isExist bool
|
||||||
|
cookieJar, _ := cookiejar.New(nil)
|
||||||
|
|
||||||
|
tr := &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建一个HTTP客户端,并设置cookie jar
|
||||||
|
client := &http.Client{
|
||||||
|
Jar: cookieJar,
|
||||||
|
Transport: tr,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建登录请求
|
||||||
|
loginURL := CreateUrl + m.Domain
|
||||||
|
req, err := http.NewRequest("GET", loginURL, nil)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("创建请求失败:", err)
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 向请求中添加cookie
|
||||||
|
cookie := &http.Cookie{
|
||||||
|
Name: m.iredCookie.Name,
|
||||||
|
Value: m.iredCookie.Cookie,
|
||||||
|
}
|
||||||
|
req.AddCookie(cookie)
|
||||||
|
|
||||||
|
// 发送登录请求
|
||||||
|
res, err := client.Do(req)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("请求错误", loginURL, err)
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer res.Body.Close()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
str, err := io.ReadAll(res.Body)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析HTML
|
||||||
|
doc, err := goquery.NewDocumentFromReader(strings.NewReader(string(str)))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
doc.Find("input[name='csrf_token']").Each(func(i int, s *goquery.Selection) {
|
||||||
|
csrfToken, isExist = s.Attr("value")
|
||||||
|
fmt.Println("查找1---", csrfToken, isExist) // 输出: testUser
|
||||||
|
})
|
||||||
|
|
||||||
|
if isExist == false {
|
||||||
|
return "", errors.New("没有查找到csrf_token")
|
||||||
|
}
|
||||||
|
|
||||||
|
return csrfToken, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// createAccount 创建用户mail
|
||||||
|
func (m *IRedMail) createAccount(cookies []*http.Cookie, info CreateAccountInfo) error {
|
||||||
|
cookieJar, _ := cookiejar.New(nil)
|
||||||
|
|
||||||
|
values := url.Values{}
|
||||||
|
values.Set("name", info.Cn)
|
||||||
|
values.Set("user", info.Username)
|
||||||
|
values.Set("domain", m.Domain)
|
||||||
|
values.Set("passwordPlaintext", info.Password)
|
||||||
|
|
||||||
|
tr := &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
|
}
|
||||||
|
u, err := url.Parse("http://106.12.56.142")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cookieJar.SetCookies(u, cookies)
|
||||||
|
|
||||||
|
// 创建一个HTTP客户端,并设置cookie jar
|
||||||
|
client := &http.Client{
|
||||||
|
Jar: cookieJar,
|
||||||
|
Transport: tr,
|
||||||
|
//CheckRedirect:
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建登录请求
|
||||||
|
loginURL := CreateUrl
|
||||||
|
req, err := http.NewRequest("POST", loginURL, strings.NewReader(values.Encode()))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("创建请求失败:", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
req.Header.Set("content-type", "application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
// 发送登录请求
|
||||||
|
res, err := client.Do(req)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("请求错误", loginURL, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
fmt.Println("状态码", res.StatusCode)
|
||||||
|
fmt.Println("状态码", res.Status)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
125
pkg/infrsatructure/external/mail/webmail_account_test.go
vendored
Normal file
125
pkg/infrsatructure/external/mail/webmail_account_test.go
vendored
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
package mail
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestIRedMail_getCsrfTokenAndCookieBeforeLogin(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
IsProd bool
|
||||||
|
Username string
|
||||||
|
Password string
|
||||||
|
Domain string
|
||||||
|
iredCookie *iredCookie
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
want []*http.Cookie
|
||||||
|
want1 string
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
// TODO: Add test cases.
|
||||||
|
{fields: fields{Username: "admin@fontree.cn", Password: "fontree567"}},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
m := &IRedMail{
|
||||||
|
IsProd: tt.fields.IsProd,
|
||||||
|
Username: tt.fields.Username,
|
||||||
|
Password: tt.fields.Password,
|
||||||
|
Domain: tt.fields.Domain,
|
||||||
|
iredCookie: tt.fields.iredCookie,
|
||||||
|
}
|
||||||
|
got, got1, err := m.getCsrfTokenAndCookieBeforeLogin()
|
||||||
|
fmt.Println("1------", got, got1)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("getCsrfTokenAndCookieBeforeLogin() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("getCsrfTokenAndCookieBeforeLogin() got = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
if got1 != tt.want1 {
|
||||||
|
t.Errorf("getCsrfTokenAndCookieBeforeLogin() got1 = %v, want %v", got1, tt.want1)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIRedMail_login(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
IsProd bool
|
||||||
|
Username string
|
||||||
|
Password string
|
||||||
|
Domain string
|
||||||
|
iredCookie *iredCookie
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
want []*http.Cookie
|
||||||
|
want1 string
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
// TODO: Add test cases.
|
||||||
|
{fields: fields{Username: "admin@fontree.cn", Password: "fontree567", IsProd: true}},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
m := &IRedMail{
|
||||||
|
IsProd: tt.fields.IsProd,
|
||||||
|
Username: tt.fields.Username,
|
||||||
|
Password: tt.fields.Password,
|
||||||
|
Domain: tt.fields.Domain,
|
||||||
|
iredCookie: tt.fields.iredCookie,
|
||||||
|
}
|
||||||
|
_, err := m.login()
|
||||||
|
fmt.Println("1------", err)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("login() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIRedMail_CreateAccount(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
IsProd bool
|
||||||
|
Username string
|
||||||
|
Password string
|
||||||
|
Domain string
|
||||||
|
iredCookie *iredCookie
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
want []*http.Cookie
|
||||||
|
want1 string
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
// TODO: Add test cases.
|
||||||
|
{fields: fields{Username: "admin@fontree.cn", Password: "fontree567", IsProd: true}},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
m := &IRedMail{
|
||||||
|
IsProd: tt.fields.IsProd,
|
||||||
|
Username: tt.fields.Username,
|
||||||
|
Password: tt.fields.Password,
|
||||||
|
Domain: tt.fields.Domain,
|
||||||
|
iredCookie: tt.fields.iredCookie,
|
||||||
|
}
|
||||||
|
err := m.CreateMailAccount(CreateAccountInfo{Cn: "耿阳", Username: "gengyang", Password: "Aa.123456"})
|
||||||
|
fmt.Println("1------", err)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("login() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
254
pkg/infrsatructure/external/mail_account.go
vendored
Normal file
254
pkg/infrsatructure/external/mail_account.go
vendored
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
package external
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/PuerkitoBio/goquery"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"net/http/cookiejar"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
LoginSuccessUrl = "https://mail.fontree.cn/iredadmin/dashboard?checknew" //登录后的重定向地址
|
||||||
|
CreateUrl = "https://mail.fontree.cn/iredadmin/create/user/"
|
||||||
|
LoginUrl = "https://mail.fontree.cn/iredadmin/login"
|
||||||
|
)
|
||||||
|
|
||||||
|
type iredCookie struct {
|
||||||
|
Cookie string
|
||||||
|
Name string
|
||||||
|
ExpireAt *time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
type IRedMail struct {
|
||||||
|
IsProd bool `json:"isProd"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
Domain string
|
||||||
|
*iredCookie
|
||||||
|
}
|
||||||
|
|
||||||
|
type CreateAccountInfo struct {
|
||||||
|
Username string
|
||||||
|
Password string
|
||||||
|
Cn string
|
||||||
|
}
|
||||||
|
|
||||||
|
var ReadMail *IRedMail
|
||||||
|
|
||||||
|
func LoadEnv(userName, psw, domain string, isProd bool) {
|
||||||
|
|
||||||
|
ReadMail = &IRedMail{
|
||||||
|
IsProd: isProd,
|
||||||
|
Username: userName,
|
||||||
|
Password: psw,
|
||||||
|
Domain: domain,
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//CreateMailAccount 创建电子邮箱账号
|
||||||
|
func (m *IRedMail) CreateMailAccount(new CreateAccountInfo) error {
|
||||||
|
|
||||||
|
if m.IsProd != true {
|
||||||
|
fmt.Println("过滤创建邮箱帐号")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//0 登陆
|
||||||
|
err := m.login()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
//1 先去解析csrf_token
|
||||||
|
csrfToken, err := m.getCsrfTokenBeforeAdd()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(csrfToken, err)
|
||||||
|
//1 先去解析csrf_token
|
||||||
|
err = m.createAccount(csrfToken, new)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// login 登陆超管
|
||||||
|
func (m *IRedMail) login() error {
|
||||||
|
|
||||||
|
loginUrl := LoginUrl
|
||||||
|
values := url.Values{}
|
||||||
|
values.Set("username", m.Username)
|
||||||
|
values.Set("password", m.Password)
|
||||||
|
values.Set("form_login", "Login")
|
||||||
|
values.Set("lang", "en_US")
|
||||||
|
// 创建一个表单数据
|
||||||
|
cookieJar, _ := cookiejar.New(nil)
|
||||||
|
// 忽略HTTPS证书验证
|
||||||
|
tr := &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建一个自定义Transport的HTTP客户端
|
||||||
|
client := &http.Client{Transport: tr, Jar: cookieJar}
|
||||||
|
|
||||||
|
// 发起POST请求
|
||||||
|
res, err := client.PostForm(loginUrl, values)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送请求
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
if res.Request.URL.String() != LoginSuccessUrl {
|
||||||
|
msg := res.Request.URL.Query().Get("msg")
|
||||||
|
return errors.New("超管登录失败提示:" + msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, cookie := range res.Cookies() {
|
||||||
|
temp := &iredCookie{
|
||||||
|
Cookie: cookie.Value,
|
||||||
|
Name: cookie.Name,
|
||||||
|
}
|
||||||
|
m.iredCookie = temp
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getCsrfTokenBeforeAdd 登陆前获取token
|
||||||
|
func (m *IRedMail) getCsrfTokenBeforeAdd() (string, error) {
|
||||||
|
var csrfToken string
|
||||||
|
var isExist bool
|
||||||
|
cookieJar, _ := cookiejar.New(nil)
|
||||||
|
|
||||||
|
tr := &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建一个HTTP客户端,并设置cookie jar
|
||||||
|
client := &http.Client{
|
||||||
|
Jar: cookieJar,
|
||||||
|
Transport: tr,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建登录请求
|
||||||
|
loginURL := CreateUrl + m.Domain
|
||||||
|
req, err := http.NewRequest("GET", loginURL, nil)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("创建请求失败:", err)
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 向请求中添加cookie
|
||||||
|
cookie := &http.Cookie{
|
||||||
|
Name: m.iredCookie.Name,
|
||||||
|
Value: m.iredCookie.Cookie,
|
||||||
|
}
|
||||||
|
req.AddCookie(cookie)
|
||||||
|
|
||||||
|
// 发送登录请求
|
||||||
|
res, err := client.Do(req)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("请求错误", loginURL, err)
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer res.Body.Close()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
str, err := io.ReadAll(res.Body)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析HTML
|
||||||
|
doc, err := goquery.NewDocumentFromReader(strings.NewReader(string(str)))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
doc.Find("input[name='csrf_token']").Each(func(i int, s *goquery.Selection) {
|
||||||
|
csrfToken, isExist = s.Attr("value")
|
||||||
|
fmt.Println("查找1---", csrfToken, isExist) // 输出: testUser
|
||||||
|
})
|
||||||
|
|
||||||
|
if isExist == false {
|
||||||
|
return "", errors.New("没有查找到csrf_token")
|
||||||
|
}
|
||||||
|
|
||||||
|
return csrfToken, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// createAccount 创建用户mail
|
||||||
|
func (m *IRedMail) createAccount(csrfToken string, info CreateAccountInfo) error {
|
||||||
|
cookieJar, _ := cookiejar.New(nil)
|
||||||
|
|
||||||
|
values := url.Values{}
|
||||||
|
values.Set("csrf_token", csrfToken)
|
||||||
|
values.Set("domainName", m.Domain)
|
||||||
|
values.Set("username", info.Username)
|
||||||
|
values.Set("newpw", info.Password)
|
||||||
|
values.Set("confirmpw", info.Password)
|
||||||
|
values.Set("cn", info.Cn)
|
||||||
|
values.Set("preferredLanguage", "zh_CN")
|
||||||
|
values.Set("mailQuota", "1024")
|
||||||
|
values.Set("submit_add_user", "Add")
|
||||||
|
|
||||||
|
tr := &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建一个HTTP客户端,并设置cookie jar
|
||||||
|
client := &http.Client{
|
||||||
|
Jar: cookieJar,
|
||||||
|
Transport: tr,
|
||||||
|
//CheckRedirect:
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建登录请求
|
||||||
|
loginURL := CreateUrl + m.Domain
|
||||||
|
req, err := http.NewRequest("POST", loginURL, strings.NewReader(values.Encode()))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("创建请求失败:", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
req.Header.Set("content-type", "application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
// 向请求中添加cookie
|
||||||
|
cookie := &http.Cookie{
|
||||||
|
Name: m.Name,
|
||||||
|
Value: m.Cookie,
|
||||||
|
}
|
||||||
|
req.AddCookie(cookie)
|
||||||
|
|
||||||
|
// 发送登录请求
|
||||||
|
res, err := client.Do(req)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("请求错误", loginURL, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
msg := res.Request.URL.Query().Get("msg")
|
||||||
|
if msg != "CREATED" {
|
||||||
|
return errors.New("生成mail账号失败:" + msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
76
pkg/infrsatructure/external/mail_account_test.go
vendored
Normal file
76
pkg/infrsatructure/external/mail_account_test.go
vendored
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
package external
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestIRedMail_login(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
Username string
|
||||||
|
Password string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
want string
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
// TODO: Add test cases.
|
||||||
|
{fields: fields{Username: "postmaster@fontree.cn", Password: "Zaq12wsx"}},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
m := &IRedMail{
|
||||||
|
Username: tt.fields.Username,
|
||||||
|
Password: tt.fields.Password,
|
||||||
|
}
|
||||||
|
err := m.login()
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("login() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIRedMail_CreateMailAccount(t *testing.T) {
|
||||||
|
|
||||||
|
type fields struct {
|
||||||
|
Username string
|
||||||
|
Password string
|
||||||
|
Domain string
|
||||||
|
iredCookie *iredCookie
|
||||||
|
}
|
||||||
|
type args struct {
|
||||||
|
new CreateAccountInfo
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
args args
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
// TODO: Add test cases.
|
||||||
|
{args: args{new: CreateAccountInfo{Username: "gengyang", Password: "Aa.123456", Cn: "耿阳"}}, fields: fields{
|
||||||
|
Username: "postmaster@fontree.cn",
|
||||||
|
Password: "Zaq12wsx",
|
||||||
|
Domain: "fontree.cn",
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
m := &IRedMail{
|
||||||
|
Username: tt.fields.Username,
|
||||||
|
Password: tt.fields.Password,
|
||||||
|
Domain: tt.fields.Domain,
|
||||||
|
iredCookie: tt.fields.iredCookie,
|
||||||
|
}
|
||||||
|
err := m.CreateMailAccount(tt.args.new)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("CreateMailAccount() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
63
pkg/m/msg.go
Normal file
63
pkg/m/msg.go
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
package m
|
||||||
|
|
||||||
|
import "github.com/fonchain_enterprise/utils/aes"
|
||||||
|
|
||||||
|
var Encryption aes.Encryption
|
||||||
|
var JWTSecret = []byte("asdfqwer1234")
|
||||||
|
|
||||||
|
const (
|
||||||
|
SERVER_CONFIG = "../conf/conf.ini"
|
||||||
|
DefaultDomain = "fontree"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ArtistTokenTime = 720
|
||||||
|
TokenTime = 12
|
||||||
|
RefreshTokenTime = 720
|
||||||
|
)
|
||||||
|
const (
|
||||||
|
SUCCESS = "success"
|
||||||
|
FAILED = "failed"
|
||||||
|
ExistFAILED = "exist"
|
||||||
|
)
|
||||||
|
const (
|
||||||
|
Unknown = 0
|
||||||
|
Unnamed = 1
|
||||||
|
UnderReview = 2
|
||||||
|
AuditFailure = 3
|
||||||
|
Pass = 4
|
||||||
|
)
|
||||||
|
const (
|
||||||
|
ERRORPWD = "账号或密码错误"
|
||||||
|
ERRORCODE = "账号或验证码错误"
|
||||||
|
ERRORCONFIG = "配置文件读取错误,请检查文件路径:"
|
||||||
|
ACCOUNT_EXIST = "账号已存在"
|
||||||
|
JOB_NUMBER_EXIST = "工号已存在"
|
||||||
|
Not_Found = "没有找到数据"
|
||||||
|
Not_Person_Verify = "您未进行实名认证"
|
||||||
|
Forbidden_Ip = "网络地址被禁用"
|
||||||
|
Mobile_Sended = "已经发送过,验证码尚可用"
|
||||||
|
Black_Mobile_Sended = "系统提示:已经发送过,验证码尚可用"
|
||||||
|
Mobile_Check_Pw_Over = "登陆频率过快,请稍候登陆"
|
||||||
|
Mobile_Send_Over = "您的手机号当天发送次数过多,请联系管理员通过密码登录"
|
||||||
|
Mobile_Code_Wrong = "您的手机号验证码错误,请确认之后注册"
|
||||||
|
Mobile_Wrong = "手机号不合法"
|
||||||
|
Mobile_Not_Change = "手机号未更改"
|
||||||
|
Mobile_New_Tel_Over = "新手机号过期"
|
||||||
|
Mobile_Wrong_Code = "验证码错误"
|
||||||
|
Mobile_Not_Send = "验证码未发送"
|
||||||
|
IdNum_Need_RealName = "身份证校验需要您的真实姓名"
|
||||||
|
EmailCreateWrong = "邮箱创建失败"
|
||||||
|
AccountDoesNotExist = "账号不存在"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
SEX_MAN = iota + 1
|
||||||
|
SEX_WOMAN
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
MailDomain = "fontree.cn"
|
||||||
|
MailRootUserName = "postmaster@fontree.cn"
|
||||||
|
MailRootPaw = "Zaq12wsx"
|
||||||
|
)
|
72
pkg/model/init.go
Normal file
72
pkg/model/init.go
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/cmd/config"
|
||||||
|
"github.com/fonchain_enterprise/utils/zap_log"
|
||||||
|
"gorm.io/gorm/logger"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gorm.io/driver/mysql"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
"gorm.io/gorm/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
var DB *gorm.DB
|
||||||
|
|
||||||
|
type MysqlConfig struct {
|
||||||
|
Db string
|
||||||
|
DbHost string
|
||||||
|
DbPort string
|
||||||
|
DbUser string
|
||||||
|
DbPassWord string
|
||||||
|
DbName string
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadEnv(config MysqlConfig) {
|
||||||
|
|
||||||
|
//MySQL数据库
|
||||||
|
path := strings.Join([]string{config.DbUser, ":", config.DbPassWord, "@tcp(", config.DbHost, ":",
|
||||||
|
config.DbPort, ")/", config.DbName, "?charset=utf8&parseTime=true&loc=Local"}, "")
|
||||||
|
|
||||||
|
fmt.Println(path)
|
||||||
|
//连接数据库
|
||||||
|
Database(path)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func Database(conn string) {
|
||||||
|
|
||||||
|
var ormLogger logger.Interface
|
||||||
|
if config.AppConfig.System.Mode != "prod" {
|
||||||
|
ormLogger = logger.Default.LogMode(logger.Info)
|
||||||
|
} else {
|
||||||
|
ormLogger = zap_log.NewGormLogger()
|
||||||
|
}
|
||||||
|
|
||||||
|
db, err := gorm.Open(mysql.New(mysql.Config{
|
||||||
|
DSN: conn, // DSN data source name
|
||||||
|
DefaultStringSize: 256, // string 类型字段的默认长度
|
||||||
|
DisableDatetimePrecision: true, // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持
|
||||||
|
DontSupportRenameIndex: true, // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
|
||||||
|
DontSupportRenameColumn: true, // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列
|
||||||
|
SkipInitializeWithVersion: false, // 根据版本自动配置
|
||||||
|
}), &gorm.Config{
|
||||||
|
//Logger: log2.NewGormLogger(),
|
||||||
|
Logger: ormLogger,
|
||||||
|
|
||||||
|
NamingStrategy: schema.NamingStrategy{
|
||||||
|
SingularTable: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
sqlDB, _ := db.DB()
|
||||||
|
sqlDB.SetMaxIdleConns(20) //设置连接池,空闲
|
||||||
|
sqlDB.SetMaxOpenConns(100) //打开
|
||||||
|
sqlDB.SetConnMaxLifetime(time.Second * 30)
|
||||||
|
DB = db
|
||||||
|
migration()
|
||||||
|
}
|
30
pkg/model/login_log.go
Normal file
30
pkg/model/login_log.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gorm.io/plugin/soft_delete"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
Status_In = 1
|
||||||
|
Status_Out = 2
|
||||||
|
Status_Off = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
//LoginLog 用户模型
|
||||||
|
type LoginLog struct {
|
||||||
|
ID uint `gorm:"primarykey"`
|
||||||
|
Domain *string `gorm:"type:varchar(32);column:domain;default:'';comment:domain" json:"domian"` //过期时间
|
||||||
|
CreatedAt time.Time
|
||||||
|
UpdatedAt time.Time
|
||||||
|
DeletedAt soft_delete.DeletedAt `gorm:"column:deleted_at;type:int(11)" json:"deletedAt"`
|
||||||
|
UserId uint `gorm:"type:int(11);column:user_id;default:0;comment:绑定的用户id" json:"userId"` //绑定的用户id
|
||||||
|
Uuid string `gorm:"type:char(16);column:uuid;default:'';comment:uuid" json:"uuid"` //绑定的用户id
|
||||||
|
Ip string `gorm:"type:varchar(50);column:ip;default:'';comment:ip地址" json:"Ip"` //登录的ip
|
||||||
|
Token string `gorm:"type:text;column:token;default:;comment:token信息" json:"token"` //token
|
||||||
|
Status uint8 `gorm:"type:tinyint;column:status;default:1;comment:状态(1-登陆中 2-登出)" json:"status"` //status状态
|
||||||
|
ExpireDate string `gorm:"type:varchar(32);column:expire_date;default:'';comment:token过期日期" json:"expire_date"` //过期时间
|
||||||
|
LastDate string `gorm:"type:varchar(32);column:last_date;default:'';comment:最后活跃时间" json:"lastDate"` //status状态
|
||||||
|
LogoutDate string `gorm:"type:varchar(32);column:logout_date;default:'';comment:登出时间" json:"logoutDate"` //status状态
|
||||||
|
Address string `gorm:"type:varchar(32);column:address;default:'';comment:地址" json:"address"` //status状态
|
||||||
|
}
|
80
pkg/model/migration.go
Normal file
80
pkg/model/migration.go
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 类型迁移
|
||||||
|
func migration() {
|
||||||
|
|
||||||
|
err := DB.AutoMigrate()
|
||||||
|
//err = DBOrder.AutoMigrate(
|
||||||
|
// &model.Pay{},
|
||||||
|
//)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("register table fail")
|
||||||
|
panic(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
//自动迁移模式
|
||||||
|
AddTable(&RefreshToken{})
|
||||||
|
AddTable(&LoginLog{})
|
||||||
|
AddTable(&User{})
|
||||||
|
AddTable(&RealName{})
|
||||||
|
|
||||||
|
//增加字段
|
||||||
|
AddColumn(&User{}, "title")
|
||||||
|
AddColumn(&User{}, "job_num")
|
||||||
|
AddColumn(&User{}, "birth_date")
|
||||||
|
AddColumn(&User{}, "sex")
|
||||||
|
AddColumn(&User{}, "operator")
|
||||||
|
|
||||||
|
AddColumn(&User{}, "last_login_date")
|
||||||
|
AddColumn(&User{}, "ip")
|
||||||
|
AddColumn(&User{}, "invitation_code")
|
||||||
|
AddColumn(&User{}, "english_name")
|
||||||
|
AddColumn(&User{}, "mail_account")
|
||||||
|
|
||||||
|
AddColumn(&LoginLog{}, "token")
|
||||||
|
AddColumn(&LoginLog{}, "status")
|
||||||
|
AddColumn(&LoginLog{}, "expire_date")
|
||||||
|
AddColumn(&LoginLog{}, "last_date")
|
||||||
|
AddColumn(&LoginLog{}, "logout_date")
|
||||||
|
AddColumn(&LoginLog{}, "address")
|
||||||
|
AddColumn(&LoginLog{}, "domain")
|
||||||
|
AddColumn(&LoginLog{}, "uuid")
|
||||||
|
AddColumn(&User{}, "domain")
|
||||||
|
AddColumn(&User{}, "left_date")
|
||||||
|
AddColumn(&User{}, "remark")
|
||||||
|
AddColumn(&User{}, "recent_img")
|
||||||
|
AddColumn(&RealName{}, "realid_img_a")
|
||||||
|
AddColumn(&RealName{}, "realid_img_b")
|
||||||
|
AddColumn(&RealName{}, "is_real")
|
||||||
|
AddColumn(&RealName{}, "video")
|
||||||
|
AddColumn(&User{}, "ic_num")
|
||||||
|
AddColumn(&User{}, "train")
|
||||||
|
AddColumn(&User{}, "certificate")
|
||||||
|
AddColumn(&User{}, "source")
|
||||||
|
AddColumn(&User{}, "security_code")
|
||||||
|
AddColumn(&User{}, "block_addr")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 数据迁移
|
||||||
|
func AddColumn(dst interface{}, column string) {
|
||||||
|
if DB.Migrator().HasColumn(dst, column) == false {
|
||||||
|
if err := DB.Migrator().AddColumn(dst, column); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddTable(dst interface{}) {
|
||||||
|
if DB.Migrator().HasTable(dst) == false {
|
||||||
|
if err := DB.Migrator().CreateTable(dst); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
23
pkg/model/real_name.go
Normal file
23
pkg/model/real_name.go
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gorm.io/plugin/soft_delete"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RealName 实名认证模型
|
||||||
|
type RealName struct {
|
||||||
|
ID uint `gorm:"primarykey"`
|
||||||
|
CreatedAt time.Time
|
||||||
|
UpdatedAt time.Time
|
||||||
|
DeletedAt soft_delete.DeletedAt `gorm:"uniqueIndex:udx_name"`
|
||||||
|
Name string `gorm:"column:name;comment:姓名" json:"name"`
|
||||||
|
Sex int `gorm:"column:sex;comment:性别:1男 2女" json:"sex"`
|
||||||
|
Nationality string `gorm:"column:nationality;comment:国籍" json:"nationality"`
|
||||||
|
DocumentType int `gorm:"column:document_type;comment:证件类型:1护照 2身份证 3驾驶证 4居住证 5自拍照 6社保卡" json:"documentType"`
|
||||||
|
CertificatePicture string `gorm:"type:varchar(500);column:certificate_picture;comment:证件照片" json:"certificatePicture"`
|
||||||
|
Validity string `gorm:"column:validity;comment:证件有效期" json:"validity"`
|
||||||
|
PlaceOfResidence string `gorm:"column:place_of_residence;comment:居住地" json:"placeOfResidence"`
|
||||||
|
GroupPhoto string `gorm:"column:group_photo;comment:证件合影" json:"groupPhoto"`
|
||||||
|
Attachment string `gorm:"column:attachment;comment:附件" json:"attachment"`
|
||||||
|
}
|
23
pkg/model/refresh_token.go
Normal file
23
pkg/model/refresh_token.go
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
IsForBid_Yes = 1
|
||||||
|
IsForBid_No = 2
|
||||||
|
UseNum_Max = 15
|
||||||
|
)
|
||||||
|
|
||||||
|
//RefreshToken 长期有效刷新token
|
||||||
|
type RefreshToken struct {
|
||||||
|
ID uint `gorm:"primarykey"`
|
||||||
|
CreatedAt time.Time
|
||||||
|
UpdatedAt time.Time
|
||||||
|
RefreshToken string `gorm:"uniqueIndex:un_token;type:varchar(256);column:refresh_token;default:'';comment:refresh_token" json:"refreshToken"`
|
||||||
|
ExpireDate string `gorm:"type:varchar(32);column:expire_date;default:'';comment:token过期日期" json:"expire_date"` //过期时间
|
||||||
|
UseNum uint8 `gorm:"type:tinyint;column:use_num;default:0;comment:使用次数" json:"useNum"` //使用次数
|
||||||
|
LastUseDate string `gorm:"type:varchar(32);column:last_use_date;default:'';comment:上次使用的时间" json:"lastUseDate"` //使用次数
|
||||||
|
IsForbid uint8 `gorm:"type:tinyint;column:status;default:1;comment:状态(1-禁用 2-可用)" json:"IsForbid"` //status状态
|
||||||
|
}
|
298
pkg/model/user.go
Normal file
298
pkg/model/user.go
Normal file
@ -0,0 +1,298 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql/driver"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/api/account"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/cache"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/common/redis_key"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/common/utils"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/common/verifica"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/domain"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/m"
|
||||||
|
"github.com/mozillazg/go-pinyin"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
"gorm.io/plugin/soft_delete"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Extend struct {
|
||||||
|
JumpTo string
|
||||||
|
Lang string
|
||||||
|
CanScan bool //是否可以扫码
|
||||||
|
ResolutionRatio bool //是否固定分辨率
|
||||||
|
}
|
||||||
|
|
||||||
|
type Operator struct {
|
||||||
|
ID uint32 `json:"ID"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// User 用户模型
|
||||||
|
type User struct {
|
||||||
|
ID uint `gorm:"primarykey"`
|
||||||
|
CreatedAt time.Time
|
||||||
|
UpdatedAt time.Time
|
||||||
|
DeletedAt soft_delete.DeletedAt `gorm:"column:deleted_at;type:int(11)" json:"deletedAt"`
|
||||||
|
Domain *string `gorm:"size:50"`
|
||||||
|
SubNum string `gorm:"column:sub_num;comment:用户编号" json:"subNum"`
|
||||||
|
TelNum string `gorm:"column:tel_num;comment:" json:"telNum"`
|
||||||
|
TelAreaCode string `gorm:"column:tel_area_code;comment:手机区号" json:"telAreaCode"`
|
||||||
|
Status int `gorm:"column:status;comment:状态 1:未实名 2:审核中 3:审核失败 4:审核通过" json:"status"`
|
||||||
|
RegistrationTime string `gorm:"column:registration_time;comment:注册时间" json:"registrationTime"`
|
||||||
|
AuditTime string `gorm:"column:audit_time;comment:审核时间" json:"auditTime"`
|
||||||
|
RealNameID uint
|
||||||
|
RealName *RealName `gorm:"foreignKey:RealNameID" json:"RealName"`
|
||||||
|
PasswordDigest string
|
||||||
|
NotPassRemarks string `gorm:"column:not_pass_remarks;comment:不通过备注" json:"notPassRemarks"`
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
PassWordCost = 12 //密码加密难度
|
||||||
|
Active string = "active" //激活用户
|
||||||
|
NOTActive string = "notactive" //未激活用户
|
||||||
|
USERLEFT string = "left" //离职
|
||||||
|
)
|
||||||
|
|
||||||
|
var SendPhoneNum = map[string]string{}
|
||||||
|
|
||||||
|
func SetSendPhoneNUm(IsProd bool) {
|
||||||
|
|
||||||
|
if IsProd == true {
|
||||||
|
SendPhoneNum["13788998899"] = "15895559080"
|
||||||
|
} else {
|
||||||
|
SendPhoneNum["13788998899"] = "18362666451"
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("是否是线上,同时手机号如何翻译", IsProd, SendPhoneNum)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Operator) Scan(src interface{}) error {
|
||||||
|
return json.Unmarshal(src.([]byte), j)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j Operator) Value() (driver.Value, error) {
|
||||||
|
v, err := json.Marshal(j)
|
||||||
|
return string(v), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Extend) Scan(src interface{}) error {
|
||||||
|
return json.Unmarshal(src.([]byte), j)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j Extend) Value() (driver.Value, error) {
|
||||||
|
v, err := json.Marshal(j)
|
||||||
|
return string(v), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func FormatExtend(extend *account.Extend) Extend {
|
||||||
|
var res Extend
|
||||||
|
res.JumpTo = extend.JumpTo
|
||||||
|
res.Lang = extend.Lang
|
||||||
|
res.ResolutionRatio = extend.ResolutionRatio
|
||||||
|
res.CanScan = extend.CanScan
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func FormatOperator(extend *account.Operator) Operator {
|
||||||
|
var res Operator
|
||||||
|
res.ID = extend.ID
|
||||||
|
res.Name = extend.Name
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPassword 设置密码
|
||||||
|
//func (user *User) SetPassword(password string) error {
|
||||||
|
// bytes, err := bcrypt.GenerateFromPassword([]byte(password), PassWordCost)
|
||||||
|
// if err != nil {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
// user.PasswordDigest = string(bytes)
|
||||||
|
// return nil
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//// GetWorkYear 获取工作时间长度
|
||||||
|
//func (user *User) GetWorkYear() float32 {
|
||||||
|
// if user.EnterDate == "" {
|
||||||
|
// return 0
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// t, err := time.ParseInLocation("2006-01-02", user.EnterDate, time.Local)
|
||||||
|
// if err != nil {
|
||||||
|
// return 0
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// //if user.LeftDate != "" {
|
||||||
|
// //
|
||||||
|
// // end, err := time.ParseInLocation("2006-01-02", user.LeftDate, time.Local)
|
||||||
|
// // if err == nil {
|
||||||
|
// // return utils.SubYearFromStartAndEnd(t, end)
|
||||||
|
// // }
|
||||||
|
// //}
|
||||||
|
//
|
||||||
|
// return utils.SubYearFromNowBefore(t)
|
||||||
|
//}
|
||||||
|
|
||||||
|
// ChangeNewTel 修改手机号
|
||||||
|
func (user *User) ChangeNewTel(code string) error {
|
||||||
|
nowNewTelKey := redis_key.GetNowNewTelById(*user.Domain, strconv.Itoa(int(user.ID)))
|
||||||
|
|
||||||
|
//0 校验当前修改到的手机号 以及账号唯一性
|
||||||
|
newTelNumObj := cache.RedisClient.Get(nowNewTelKey)
|
||||||
|
newTelNum := newTelNumObj.Val()
|
||||||
|
|
||||||
|
if newTelNum == "" {
|
||||||
|
return errors.New(m.Mobile_Wrong)
|
||||||
|
}
|
||||||
|
|
||||||
|
var count int64
|
||||||
|
DB.Model(&User{}).Where(&User{TelNum: newTelNum, Domain: user.Domain}).Count(&count)
|
||||||
|
|
||||||
|
if count > 0 {
|
||||||
|
return errors.New(m.ACCOUNT_EXIST)
|
||||||
|
}
|
||||||
|
|
||||||
|
if newTelNum == user.TelNum {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//检测验证码
|
||||||
|
str := cache.RedisClient.Get(redis_key.GetChangeTelKey(*user.Domain, newTelNum, strconv.Itoa(int(user.ID))))
|
||||||
|
|
||||||
|
if str.Val() == "" {
|
||||||
|
return errors.New(m.Mobile_Not_Send)
|
||||||
|
}
|
||||||
|
|
||||||
|
if str.Val() != code {
|
||||||
|
return errors.New(m.Mobile_Wrong_Code)
|
||||||
|
}
|
||||||
|
|
||||||
|
//修改完毕之后删除
|
||||||
|
domain.DelRecordTelMsgCodeLogin(*user.Domain, newTelNum, strconv.Itoa(int(user.ID)))
|
||||||
|
|
||||||
|
err := DB.Model(&user).Updates(&User{TelNum: newTelNum}).Error
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (user *User) NowNewTelNum() (string, error) {
|
||||||
|
|
||||||
|
str := cache.RedisClient.Get(redis_key.GetNowNewTelById(*user.Domain, strconv.Itoa(int(user.ID))))
|
||||||
|
if str.Val() == "" {
|
||||||
|
return "", errors.New(m.Mobile_New_Tel_Over)
|
||||||
|
}
|
||||||
|
|
||||||
|
return str.Val(), nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendNewTelMsg 给新手机号发送验证码
|
||||||
|
func (user *User) SendNewTelMsg(newTelNum, project string, signNo uint) error {
|
||||||
|
telTodayNum := redis_key.GetAccountKeyCountToday(*user.Domain, newTelNum)
|
||||||
|
if newTelNum == "" {
|
||||||
|
return errors.New("新手机号不能为空")
|
||||||
|
}
|
||||||
|
|
||||||
|
if user.TelNum == newTelNum {
|
||||||
|
return errors.New(m.Mobile_Not_Change)
|
||||||
|
}
|
||||||
|
|
||||||
|
if utils.CheckMobile(newTelNum) == false {
|
||||||
|
return errors.New(m.Mobile_Wrong)
|
||||||
|
}
|
||||||
|
|
||||||
|
//0 限制频率 (一个账号一分钟少于一次 同一一天最多10条)
|
||||||
|
fmt.Println(redis_key.GetOneMinuteKey(*user.Domain, newTelNum, strconv.Itoa(int(user.ID))))
|
||||||
|
str := cache.RedisClient.Get(redis_key.GetOneMinuteKey(*user.Domain, newTelNum, strconv.Itoa(int(user.ID))))
|
||||||
|
fmt.Println(str)
|
||||||
|
|
||||||
|
if str.Val() != "" {
|
||||||
|
return errors.New(m.Mobile_Sended)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := domain.CheckMsg(telTodayNum); err != nil {
|
||||||
|
return errors.New(m.Mobile_Send_Over)
|
||||||
|
}
|
||||||
|
|
||||||
|
//1 执行发送 并且记录code
|
||||||
|
code, err := verifica.SendMsgV2(newTelNum, project, signNo)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
//2 记录发送
|
||||||
|
err = domain.SetRecordTelMsgCodeLogin(*user.Domain, newTelNum, code, strconv.Itoa(int(user.ID)))
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckPassword 校验密码
|
||||||
|
func (user *User) CheckPassword(password string) bool {
|
||||||
|
err := bcrypt.CompareHashAndPassword([]byte(user.PasswordDigest), []byte(password))
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DomainCount(domain string) int64 {
|
||||||
|
|
||||||
|
var count int64
|
||||||
|
|
||||||
|
//获取自己领导的部门
|
||||||
|
DB.Model(&User{}).
|
||||||
|
Where(&User{Domain: &domain}).Count(&count)
|
||||||
|
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
|
||||||
|
func RandList(domain string, limit int) ([]*User, int64) {
|
||||||
|
|
||||||
|
var list []*User
|
||||||
|
var count int64
|
||||||
|
var departmentIds []uint
|
||||||
|
|
||||||
|
//获取自己领导的部门
|
||||||
|
searchObj := DB.Preload("RealName").
|
||||||
|
Where(&User{Domain: &domain}).
|
||||||
|
Limit(limit).
|
||||||
|
Order("rand()")
|
||||||
|
|
||||||
|
searchObj.Find(&list, departmentIds)
|
||||||
|
|
||||||
|
DB.Model(&User{}).Where(&User{Domain: &domain}).Count(&count)
|
||||||
|
|
||||||
|
return list, count
|
||||||
|
}
|
||||||
|
|
||||||
|
func SynInvitationCode(userId uint) error {
|
||||||
|
|
||||||
|
//保存实名信息
|
||||||
|
var user *User
|
||||||
|
|
||||||
|
if err := DB.Model(&User{}).First(user, userId).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
updateMap := map[string]interface{}{"invitation_code": utils.DecimalToAny(int(userId))}
|
||||||
|
return DB.Model(&User{}).Where(&User{ID: userId}).Updates(updateMap).Error
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetEnglishNameByName(nickName string) string {
|
||||||
|
|
||||||
|
fmt.Println(strings.ReplaceAll("hello word", " ", ""))
|
||||||
|
pinyinObj := pinyin.NewArgs()
|
||||||
|
pinyinObj.Style = pinyin.Normal
|
||||||
|
pinyinObj.Separator = ""
|
||||||
|
result := pinyin.Pinyin(strings.ReplaceAll(nickName, " ", ""), pinyinObj)
|
||||||
|
pinyinStr := ""
|
||||||
|
for _, s := range result {
|
||||||
|
fmt.Println(s)
|
||||||
|
pinyinStr += s[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.ReplaceAll(pinyinStr, " ", "")
|
||||||
|
}
|
186
pkg/model/user_test.go
Normal file
186
pkg/model/user_test.go
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/api/account"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/common/utils"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/infrsatructure/external"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/m"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDomainCount(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSynMailAccount(t *testing.T) {
|
||||||
|
|
||||||
|
//数据库
|
||||||
|
mysqlConfig := MysqlConfig{
|
||||||
|
Db: "mysql",
|
||||||
|
DbHost: "rm-bp176edrl1g6kcycblo.mysql.rds.aliyuncs.com",
|
||||||
|
DbPort: "3306",
|
||||||
|
DbUser: "fonchain_opv",
|
||||||
|
DbPassWord: "IhQmhg8HZjDmU=Ove5PnA^D",
|
||||||
|
DbName: "fontree-account",
|
||||||
|
}
|
||||||
|
|
||||||
|
LoadEnv(mysqlConfig)
|
||||||
|
|
||||||
|
external.LoadEnv("postmaster@fontree.cn", "Zaq12wsx", "fontree.cn", true)
|
||||||
|
|
||||||
|
var users []User
|
||||||
|
domain := m.DefaultDomain
|
||||||
|
DB.Model(&User{}).Where(&User{Domain: &domain}).Where("isNull(mail_account) and id >50 ").Where("status != 'left'").Limit(100).Find(&users)
|
||||||
|
fmt.Println(users)
|
||||||
|
if len(users) <= 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, user := range users {
|
||||||
|
|
||||||
|
var englishName, mailAccount, mailAccountPrefix string
|
||||||
|
var num int64
|
||||||
|
if utils.HasEnglishAndChinese(user.Nickname) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
englishName = user.Nickname
|
||||||
|
if utils.HasChinese(user.Nickname) {
|
||||||
|
englishName = GetEnglishNameByName(user.Nickname)
|
||||||
|
}
|
||||||
|
|
||||||
|
DB.Model(&User{}).Unscoped().Preload("DeletedAt").Where(&User{Domain: user.Domain, EnglishName: englishName}).Count(&num)
|
||||||
|
|
||||||
|
if num >= 1 {
|
||||||
|
mailAccount = fmt.Sprintf("%s%02d@%s", englishName, num+1, m.MailDomain)
|
||||||
|
mailAccountPrefix = fmt.Sprintf("%s%02d", englishName, num+1)
|
||||||
|
} else {
|
||||||
|
mailAccount = fmt.Sprintf("%s@%s", englishName, m.MailDomain)
|
||||||
|
mailAccountPrefix = fmt.Sprintf("%s", englishName)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
err := external.ReadMail.CreateMailAccount(external.CreateAccountInfo{Username: mailAccountPrefix, Password: "Aa.123456", Cn: user.Nickname})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
|
||||||
|
fmt.Println("2------", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := DB.Model(&User{}).Where(&User{ID: uint(user.ID)}).UpdateColumns(&User{MailAccount: mailAccount, EnglishName: englishName}).Error; err != nil {
|
||||||
|
fmt.Println("1------", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("设置成功一个", user.Nickname)
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetMemCry(t *testing.T) {
|
||||||
|
|
||||||
|
user := &User{
|
||||||
|
ID: 153,
|
||||||
|
MnemonicWords: "bbX/2x+VK1zMX/oETDqPyw67Sj16H2ex8J8+tp7gFoSVUpL1UXLAJbqcURigOOZU",
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(user.GetMemCry())
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNick(t *testing.T) {
|
||||||
|
|
||||||
|
fmt.Println(SendPhoneNum["13788998899"])
|
||||||
|
|
||||||
|
if _, ok := SendPhoneNum["13788998899"]; ok {
|
||||||
|
fmt.Println("1-----", SendPhoneNum["13788998899"])
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetEnglishNameByName(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
nickName string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{args: args{nickName: "阿丽米罕·色依提"}},
|
||||||
|
// TODO: Add test cases.
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if got := GetEnglishNameByName(tt.args.nickName); got != tt.want {
|
||||||
|
t.Errorf("GetEnglishNameByName() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUser_recordTrainVideo(t *testing.T) {
|
||||||
|
//数据库
|
||||||
|
mysqlConfig := MysqlConfig{
|
||||||
|
Db: "mysql",
|
||||||
|
DbHost: "172.16.100.93",
|
||||||
|
DbPort: "9061",
|
||||||
|
DbUser: "root",
|
||||||
|
DbPassWord: "123456",
|
||||||
|
DbName: "fontree-account",
|
||||||
|
}
|
||||||
|
//http://172.16.100.93:9010/salebot
|
||||||
|
LoadEnv(mysqlConfig)
|
||||||
|
|
||||||
|
external.LoadEnv("postmaster@fontree.cn", "Zaq12wsx", "fontree.cn", true)
|
||||||
|
|
||||||
|
var user *User
|
||||||
|
domain := m.DefaultDomain
|
||||||
|
DB.Model(&User{}).Where(&User{Domain: &domain, ID: 40}).Find(&user)
|
||||||
|
|
||||||
|
var trains []*account.TrainVideo
|
||||||
|
trains = append(trains, &account.TrainVideo{TrainUUID: "1", TrainDesc: "111--", Video: "x111x"})
|
||||||
|
trains = append(trains, &account.TrainVideo{TrainUUID: "2", TrainDesc: "2--", Video: "x2x"})
|
||||||
|
trains = append(trains, &account.TrainVideo{TrainUUID: "4", TrainDesc: "4--", Video: "x4x"})
|
||||||
|
|
||||||
|
err := user.recordTrainVideo(trains)
|
||||||
|
fmt.Println("err", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSynTrainVideo(t *testing.T) {
|
||||||
|
|
||||||
|
//数据库
|
||||||
|
mysqlConfig := MysqlConfig{
|
||||||
|
Db: "mysql",
|
||||||
|
DbHost: "172.16.100.93",
|
||||||
|
DbPort: "9061",
|
||||||
|
DbUser: "root",
|
||||||
|
DbPassWord: "123456",
|
||||||
|
DbName: "fontree-account",
|
||||||
|
}
|
||||||
|
|
||||||
|
LoadEnv(mysqlConfig)
|
||||||
|
|
||||||
|
var users []User
|
||||||
|
domain := m.DefaultDomain
|
||||||
|
DB.Model(&User{}).Where(&User{Domain: &domain}).Where("train != ''").Limit(1000).Find(&users)
|
||||||
|
//fmt.Println(users)
|
||||||
|
if len(users) <= 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(len(users))
|
||||||
|
for _, t1 := range users {
|
||||||
|
var trains []*account.TrainVideo
|
||||||
|
trains = append(trains, &account.TrainVideo{TrainUUID: "1", TrainDesc: "市场培训", Video: t1.Train})
|
||||||
|
|
||||||
|
err := t1.recordTrainVideo(trains)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(t1.ID, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
107
pkg/serializer/user.go
Normal file
107
pkg/serializer/user.go
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
package serializer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/fonchain_enterprise/micro-account/api/account"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/common/utils"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
type User struct {
|
||||||
|
ID uint `json:"id"`
|
||||||
|
Account string `json:"account"`
|
||||||
|
NickName string `json:"nickName"`
|
||||||
|
Type int `json:"type"`
|
||||||
|
TelNum string `json:"telNum"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
Avatar string `json:"avatar"`
|
||||||
|
CreateAt int64 `json:"createAt"`
|
||||||
|
RealNameID uint `json:"realNameId"`
|
||||||
|
RealName string `json:"realName"`
|
||||||
|
IDNum string `json:"idNum"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildUser 序列化用户
|
||||||
|
func BuildUser(user *model.User) *account.AccountInfo {
|
||||||
|
|
||||||
|
var realName = ""
|
||||||
|
var IdNum = ""
|
||||||
|
var videos []*account.TrainVideo
|
||||||
|
|
||||||
|
//if user.RealName != nil {
|
||||||
|
// realName = user.RealName.Name
|
||||||
|
// IdNum, _ = user.RealName.GetIDNum(user)
|
||||||
|
//}
|
||||||
|
|
||||||
|
//extend := &account.Extend{
|
||||||
|
// JumpTo: user.Extend.JumpTo,
|
||||||
|
// Lang: user.Extend.Lang,
|
||||||
|
// CanScan: user.Extend.CanScan,
|
||||||
|
// ResolutionRatio: user.Extend.ResolutionRatio,
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//if user.InvitationCode == "" {
|
||||||
|
// user.InvitationCode, _ = SynInvitationCode(user.ID)
|
||||||
|
//}
|
||||||
|
|
||||||
|
return &account.AccountInfo{
|
||||||
|
ID: uint64(user.ID),
|
||||||
|
TelNum: user.TelNum,
|
||||||
|
Status: int32(user.Status),
|
||||||
|
//Avatar: user.AvatarURL(),
|
||||||
|
CreateAt: user.CreatedAt.Format("2006-01-02 15:04:05"),
|
||||||
|
RealName: realName,
|
||||||
|
Domain: *user.Domain,
|
||||||
|
IDNum: IdNum,
|
||||||
|
TrainVideos: videos,
|
||||||
|
UpdatedAt: user.UpdatedAt.Format("2006-01-02 15:04:05"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func BuildUsers(items []*model.User) (users []*account.AccountInfo) {
|
||||||
|
for _, item := range items {
|
||||||
|
user := BuildUser(item)
|
||||||
|
users = append(users, user)
|
||||||
|
}
|
||||||
|
return users
|
||||||
|
}
|
||||||
|
func BuildUserList(user []*model.User) []*account.UserListInfo {
|
||||||
|
if len(user) == 0 {
|
||||||
|
return []*account.UserListInfo{}
|
||||||
|
}
|
||||||
|
var userList []*account.UserListInfo
|
||||||
|
for _, i := range user {
|
||||||
|
userList = append(userList, &account.UserListInfo{
|
||||||
|
Id: uint64(i.ID),
|
||||||
|
Status: int32(i.Status),
|
||||||
|
Name: i.RealName.Name,
|
||||||
|
Sex: int32(i.RealName.Sex),
|
||||||
|
Nationality: i.RealName.Nationality,
|
||||||
|
DocumentType: int32(i.RealName.DocumentType),
|
||||||
|
CertificatePicture: i.RealName.CertificatePicture,
|
||||||
|
Validity: i.RealName.Validity,
|
||||||
|
PlaceOfResidence: i.RealName.PlaceOfResidence,
|
||||||
|
GroupPhoto: i.RealName.GroupPhoto,
|
||||||
|
Attachment: i.RealName.Attachment,
|
||||||
|
RegistrationTime: i.RegistrationTime,
|
||||||
|
AuditTime: i.AuditTime,
|
||||||
|
SubNum: i.SubNum,
|
||||||
|
NotPassRemarks: i.NotPassRemarks,
|
||||||
|
TelNum: i.TelNum,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return userList
|
||||||
|
}
|
||||||
|
func SynInvitationCode(userId uint) (string, error) {
|
||||||
|
|
||||||
|
//保存实名信息
|
||||||
|
var user *model.User
|
||||||
|
|
||||||
|
if err := model.DB.Model(&model.User{}).First(&user, userId).Error; err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
invitationCode := utils.DecimalToAny(int(userId))
|
||||||
|
|
||||||
|
updateMap := map[string]interface{}{"invitation_code": invitationCode}
|
||||||
|
return invitationCode, model.DB.Model(&model.User{}).Where(&model.User{ID: userId}).Updates(updateMap).Error
|
||||||
|
|
||||||
|
}
|
31
pkg/serializer/user_test.go
Normal file
31
pkg/serializer/user_test.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package serializer
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestSynInvitationCode(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
userId uint
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want string
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
// TODO: Add test cases.
|
||||||
|
{name: "1", args: struct{ userId uint }{userId: 1964}, want: "", wantErr: true},
|
||||||
|
{name: "1", args: struct{ userId uint }{userId: 1978}, want: "", wantErr: true},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, err := SynInvitationCode(tt.args.userId)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("SynInvitationCode() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if got != tt.want {
|
||||||
|
t.Errorf("SynInvitationCode() got = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
905
pkg/service/account.go
Normal file
905
pkg/service/account.go
Normal file
@ -0,0 +1,905 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"dubbo.apache.org/dubbo-go/v3/common/logger"
|
||||||
|
_ "dubbo.apache.org/dubbo-go/v3/imports"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/api/account"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/application"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/cache"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/common/jwt"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/common/page"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/common/redis_key"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/common/verifica"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/domain"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/m"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/model"
|
||||||
|
"github.com/fonchain_enterprise/micro-account/pkg/serializer"
|
||||||
|
"github.com/fonchain_enterprise/utils/mobile"
|
||||||
|
uuid2 "github.com/google/uuid"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
"log"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AccountProvider struct {
|
||||||
|
account.UnimplementedAccountServer
|
||||||
|
}
|
||||||
|
|
||||||
|
// OffLine 踢出
|
||||||
|
func (a *AccountProvider) OffLine(ctx context.Context, in *account.CommonRequest) (*account.CommonResponse, error) {
|
||||||
|
|
||||||
|
response := &account.CommonResponse{}
|
||||||
|
|
||||||
|
err := application.OffByLogId(in.ID)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Logout 登出
|
||||||
|
func (a *AccountProvider) Logout(ctx context.Context, in *account.DecryptJwtRequest) (*account.CommonResponse, error) {
|
||||||
|
|
||||||
|
response := &account.CommonResponse{}
|
||||||
|
|
||||||
|
err := application.Logout(in, model.Status_Out)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// OnlineLogById 获取某个id的在线数据
|
||||||
|
func (a *AccountProvider) OnlineLogById(ctx context.Context, in *account.OnlineLogByIdRequest) (*account.LoginLog, error) {
|
||||||
|
response := &account.LoginLog{}
|
||||||
|
response, err := application.OnlineLogById(in.ID)
|
||||||
|
if err != nil {
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// OnlineLog 获取某个人的在线数据
|
||||||
|
func (a *AccountProvider) OnlineLog(ctx context.Context, in *account.LoginInfosByUserIdRequest) (*account.LoginLogsResponse, error) {
|
||||||
|
response := &account.LoginLogsResponse{}
|
||||||
|
response.Data = application.OnlineLogList(in)
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
func (a *AccountProvider) Login(ctx context.Context, in *account.LoginRequest) (*account.TokenInfo, error) {
|
||||||
|
timeNow := time.Now()
|
||||||
|
tokenInfo := &account.TokenInfo{IsSampleAddress: true}
|
||||||
|
//nowIpAddress := ""
|
||||||
|
|
||||||
|
var user *model.User
|
||||||
|
if err := model.DB.Preload("RealName").Where(&model.User{TelNum: in.TelNum, Domain: &in.Domain}).First(&user).Error; err != nil {
|
||||||
|
return nil, errors.New(m.AccountDoesNotExist)
|
||||||
|
}
|
||||||
|
|
||||||
|
if in.Code == "" && in.Password == "" {
|
||||||
|
return nil, errors.New(m.ERRORCODE)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("---------------add1---", time.Now().Sub(timeNow))
|
||||||
|
if in.Code != "" {
|
||||||
|
str := cache.RedisClient.Get(redis_key.GetAccountKey(in.Domain, in.TelNum)) // 登陆检测
|
||||||
|
code := str.Val()
|
||||||
|
if code != in.Code {
|
||||||
|
return nil, errors.New(m.ERRORCODE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("---------------add2---", time.Now().Sub(timeNow))
|
||||||
|
if in.Password != "" {
|
||||||
|
if !user.CheckPassword(in.Password) { //200毫秒
|
||||||
|
return nil, errors.New(m.ERRORPWD)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("---------------add3---", time.Now().Sub(timeNow))
|
||||||
|
|
||||||
|
//生成token
|
||||||
|
tokenTime := m.TokenTime
|
||||||
|
token, refreshToken, err := jwt.GenerateTotalToken(user.ID, in.Domain, tokenTime, user.TelNum, m.JWTSecret)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("---------------add4---", time.Now().Sub(timeNow))
|
||||||
|
|
||||||
|
if err := application.AddRefreshToken(refreshToken); err != nil {
|
||||||
|
logger.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
tokenInfo.Token = token
|
||||||
|
tokenInfo.RefreshToken = refreshToken
|
||||||
|
tokenInfo.AccountInfo = serializer.BuildUser(user)
|
||||||
|
|
||||||
|
fmt.Println("---------------add4---", time.Now().Sub(timeNow))
|
||||||
|
|
||||||
|
//tokenInfo.AccountInfo.NowLogId = application.LoginAddLog(user, token, in.Ip, nowIpAddress)
|
||||||
|
|
||||||
|
fmt.Println("---------------结束", time.Now().Sub(timeNow))
|
||||||
|
return tokenInfo, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AccountProvider) RefreshToken(_ context.Context, in *account.RefreshTokenRequest) (*account.TokenInfo, error) {
|
||||||
|
response := &account.TokenInfo{}
|
||||||
|
oldRefreshToken := in.RefreshToken
|
||||||
|
|
||||||
|
//验证
|
||||||
|
claims, err := jwt.ParseRefreshToken(oldRefreshToken, m.JWTSecret)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var user *model.User
|
||||||
|
if err := model.DB.Preload("RealName").Where(&model.User{ID: claims.ID, Domain: &in.Domain}).First(&user).Error; err != nil {
|
||||||
|
return nil, errors.New(m.Not_Found)
|
||||||
|
}
|
||||||
|
|
||||||
|
//生成token
|
||||||
|
token, refreshToken, err := jwt.GenerateTotalToken(user.ID, in.Domain, m.TokenTime, user.TelNum, m.JWTSecret)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
//refresh 是否合法
|
||||||
|
if err := application.CheckRefreshToke(oldRefreshToken); err != nil {
|
||||||
|
logger.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
//refresh 是否合法
|
||||||
|
if err := application.AddRefreshToken(refreshToken); err != nil {
|
||||||
|
logger.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
//nowIpAddress := application.GetIpAddressByIp(in.Ip) //400毫秒
|
||||||
|
//_ = application.LoginAddLog(user, token, in.Ip, nowIpAddress)
|
||||||
|
|
||||||
|
response.Token = token
|
||||||
|
response.RefreshToken = refreshToken
|
||||||
|
response.AccountInfo = serializer.BuildUser(user)
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AccountProvider) OnlySendMsg(_ context.Context, in *account.SendMsgRequest) (*account.SendMsgStatusResponse, error) {
|
||||||
|
response := &account.SendMsgStatusResponse{}
|
||||||
|
|
||||||
|
//telTodayNum := redis_key.GetAccountKeyCountToday(in.Domain, in.TelNum, in.Scope)
|
||||||
|
|
||||||
|
//校验(1-是否已经发送 2-是否今日发送超过指定数量)
|
||||||
|
/*str := cache.RedisClient.Get(redis_key.GetOnlyAccountKey(in.Domain, in.TelNum))
|
||||||
|
|
||||||
|
if str.Val() != "" {
|
||||||
|
return nil, errors.New(m.Mobile_Sended)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
if err := domain.CheckMsgPre(in.Domain, in.TelNum, in.Scope); err != nil {
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
|
||||||
|
//执行发送 并且记录code
|
||||||
|
//code, err := verifica.SendMsg(in.TelNum, in.Project)
|
||||||
|
|
||||||
|
//兼容老代码
|
||||||
|
sigNo := in.SignNo
|
||||||
|
if sigNo == 0 {
|
||||||
|
sigNo = verifica.SIG_NO
|
||||||
|
if in.Project == "seller" {
|
||||||
|
sigNo = verifica.SIG_NO_SELLER
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if in.MId == 0 {
|
||||||
|
in.MId = mobile.TMP1
|
||||||
|
}
|
||||||
|
|
||||||
|
code, err := verifica.SendCustomCode(in.TelNum, uint(in.MId), uint(sigNo))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = domain.SetOnlyRecordTelMsgCode(in.Domain, in.TelNum, code, in.Scope)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AccountProvider) OnlyCheckMsg(_ context.Context, in *account.CheckMsgRequest) (*account.SendMsgStatusResponse, error) {
|
||||||
|
response := &account.SendMsgStatusResponse{}
|
||||||
|
|
||||||
|
fmt.Println(in)
|
||||||
|
str := cache.RedisClient.Get(redis_key.GetOnlyAccountKey(in.Domain, in.TelNum))
|
||||||
|
code := str.Val()
|
||||||
|
|
||||||
|
if code == "" {
|
||||||
|
return nil, errors.New(m.Mobile_Not_Send)
|
||||||
|
}
|
||||||
|
|
||||||
|
if code != in.GetCode() {
|
||||||
|
return nil, errors.New(m.Mobile_Wrong_Code)
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendMsg 发送验证码
|
||||||
|
func (a *AccountProvider) SendMsg(_ context.Context, in *account.SendMsgRequest) (*account.SendMsgStatusResponse, error) {
|
||||||
|
response := &account.SendMsgStatusResponse{}
|
||||||
|
|
||||||
|
var user *model.User
|
||||||
|
|
||||||
|
if domain.InBlockList(in.Domain, in.TelNum) {
|
||||||
|
return nil, errors.New(m.Black_Mobile_Sended)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := model.DB.Where(&model.User{TelNum: in.TelNum, Domain: &in.Domain}).First(&user).Error; err != nil {
|
||||||
|
return nil, errors.New(m.Not_Found)
|
||||||
|
}
|
||||||
|
|
||||||
|
//此处不再校验验证码有效期
|
||||||
|
//校验(1-是否已经发送 2-是否今日发送超过指定数量)
|
||||||
|
/*
|
||||||
|
str := cache.RedisClient.Get(redis_key.GetAccountKey(in.Domain, in.TelNum)) // 发送验证码
|
||||||
|
|
||||||
|
if str.Val() != "" {
|
||||||
|
return nil, errors.New(m.Mobile_Sended)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
//是否存活 (1分钟冷却) (1-是否已经发送 2-是否今日发送超过指定数量) 55秒
|
||||||
|
if err := domain.CodeLive(in.Domain, in.TelNum); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
//今日是否达到上限
|
||||||
|
if err := domain.CheckMsg(redis_key.GetAccountKeyCountToday(in.Domain, in.TelNum)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
//执行发送 并且记录code
|
||||||
|
code, err := verifica.SendMsgV2(in.TelNum, in.Project, uint(in.SignNo))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = domain.SetRecordTelMsgCode(in.Domain, in.TelNum, code)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AccountProvider) SendMsgRegister(_ context.Context, in *account.SendMsgRequest) (*account.SendMsgStatusResponse, error) {
|
||||||
|
response := &account.SendMsgStatusResponse{}
|
||||||
|
|
||||||
|
telTodayNum := redis_key.GetAccountKeyCountToday(in.Domain, in.TelNum)
|
||||||
|
|
||||||
|
// 手机号是否存在
|
||||||
|
var count int64
|
||||||
|
model.DB.Model(&model.User{}).Where(&model.User{TelNum: in.TelNum, Domain: &in.Domain}).Count(&count)
|
||||||
|
|
||||||
|
if count > 0 {
|
||||||
|
return response, errors.New(m.ACCOUNT_EXIST)
|
||||||
|
}
|
||||||
|
|
||||||
|
//校验(1-是否已经发送 2-是否今日发送超过指定数量)
|
||||||
|
if err := domain.CodeLive(in.Domain, in.TelNum); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := domain.CheckMsg(telTodayNum); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
//执行发送 并且记录code
|
||||||
|
code, err := verifica.SendMsgV2(in.TelNum, in.Project, uint(in.SignNo))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = domain.SetRecordTelMsgCode(in.Domain, in.TelNum, code)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AccountProvider) CheckMsg(_ context.Context, in *account.CheckMsgRequest) (*account.SendMsgStatusResponse, error) {
|
||||||
|
response := &account.SendMsgStatusResponse{}
|
||||||
|
|
||||||
|
str := cache.RedisClient.Get(redis_key.GetAccountKey(in.Domain, in.TelNum)) //校验验证码
|
||||||
|
code := str.Val()
|
||||||
|
if code == "" {
|
||||||
|
return nil, errors.New(m.Mobile_Not_Send)
|
||||||
|
}
|
||||||
|
|
||||||
|
if code != in.GetCode() {
|
||||||
|
return nil, errors.New(m.Mobile_Wrong_Code)
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AccountProvider) RealName(_ context.Context, in *account.RealNameRequest) (*account.RealNameResponse, error) {
|
||||||
|
// 检查用户是否存在
|
||||||
|
var existingUser model.User
|
||||||
|
if err := model.DB.First(&existingUser, "id = ?", in.Id).Error; err != nil {
|
||||||
|
return &account.RealNameResponse{Status: m.FAILED}, err
|
||||||
|
}
|
||||||
|
// 如果用户已经实名
|
||||||
|
if existingUser.Status == m.Pass {
|
||||||
|
return &account.RealNameResponse{Status: m.FAILED}, errors.New("已实名")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果实名审核中
|
||||||
|
if existingUser.Status == m.UnderReview {
|
||||||
|
return &account.RealNameResponse{Status: m.FAILED}, errors.New("实名审核中,请勿重复提交")
|
||||||
|
}
|
||||||
|
// 检查用户是否已关联实名信息
|
||||||
|
if existingUser.RealNameID == 0 {
|
||||||
|
// 如果没有找到实名信息,创建一个新的 RealName 记录
|
||||||
|
newRealName := model.RealName{
|
||||||
|
Name: in.Name,
|
||||||
|
Sex: int(in.Sex),
|
||||||
|
Nationality: in.Nationality,
|
||||||
|
DocumentType: int(in.DocumentType),
|
||||||
|
CertificatePicture: in.CertificatePicture,
|
||||||
|
Validity: in.Validity,
|
||||||
|
PlaceOfResidence: in.PlaceOfResidence,
|
||||||
|
GroupPhoto: in.GroupPhoto,
|
||||||
|
Attachment: in.Attachment,
|
||||||
|
}
|
||||||
|
// 创建实名信息
|
||||||
|
if err := model.DB.Create(&newRealName).Error; err != nil {
|
||||||
|
return &account.RealNameResponse{Status: m.FAILED}, err
|
||||||
|
}
|
||||||
|
// 更新用户的实名信息 ID
|
||||||
|
existingUser.RealNameID = newRealName.ID
|
||||||
|
if err := model.DB.Save(&existingUser).Error; err != nil {
|
||||||
|
return &account.RealNameResponse{Status: m.FAILED}, err
|
||||||
|
}
|
||||||
|
// 返回成功
|
||||||
|
return &account.RealNameResponse{Status: m.SUCCESS}, nil
|
||||||
|
}
|
||||||
|
// 如果已存在实名信息,更新该信息
|
||||||
|
updateData := map[string]interface{}{
|
||||||
|
"status": m.UnderReview, // 审核中状态
|
||||||
|
"name": in.Name,
|
||||||
|
"sex": in.Sex,
|
||||||
|
"nationality": in.Nationality,
|
||||||
|
"document_type": in.DocumentType,
|
||||||
|
"certificate_picture": in.CertificatePicture,
|
||||||
|
"validity": in.Validity,
|
||||||
|
"place_of_residence": in.PlaceOfResidence,
|
||||||
|
"group_photo": in.GroupPhoto,
|
||||||
|
"attachment": in.Attachment,
|
||||||
|
}
|
||||||
|
// 更新 RealName 表中的数据
|
||||||
|
var existingRealName model.RealName
|
||||||
|
if err := model.DB.First(&existingRealName, "id = ?", existingUser.RealNameID).Error; err != nil {
|
||||||
|
return &account.RealNameResponse{Status: m.FAILED}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := model.DB.Model(&existingRealName).Updates(updateData).Error; err != nil {
|
||||||
|
return &account.RealNameResponse{Status: m.FAILED}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &account.RealNameResponse{Status: m.SUCCESS}, nil
|
||||||
|
}
|
||||||
|
func (a *AccountProvider) CheckRealName(ctx context.Context, in *account.CheckRealNameRequest) (*account.CheckRealNameResponse, error) {
|
||||||
|
// 根据用户 ID 查询用户
|
||||||
|
var user model.User
|
||||||
|
if err := model.DB.First(&user, "id = ?", in.Id).Error; err != nil {
|
||||||
|
return &account.CheckRealNameResponse{Status: m.FAILED}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 只有当用户处于“审核中”状态时才能进行审核更新
|
||||||
|
if user.Status != m.UnderReview {
|
||||||
|
return &account.CheckRealNameResponse{Status: m.FAILED}, errors.New("用户状态异常,无法进行审核")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据传入的审核结果更新用户状态和备注
|
||||||
|
if in.Pass {
|
||||||
|
user.Status = m.Pass
|
||||||
|
} else {
|
||||||
|
user.Status = m.AuditFailure
|
||||||
|
user.NotPassRemarks = in.NotPassRemarks
|
||||||
|
}
|
||||||
|
loc, err := time.LoadLocation("Asia/Shanghai")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("加载时区失败: %v", err)
|
||||||
|
}
|
||||||
|
user.AuditTime = time.Now().In(loc).Format("2006-01-02 15:04:05")
|
||||||
|
|
||||||
|
// 保存更新
|
||||||
|
if err := model.DB.Save(&user).Error; err != nil {
|
||||||
|
return &account.CheckRealNameResponse{Status: m.FAILED}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &account.CheckRealNameResponse{Status: m.SUCCESS}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register 注册
|
||||||
|
func (a *AccountProvider) Register(_ context.Context, in *account.RegistRequest) (*account.RegisterResponse, error) {
|
||||||
|
var err error
|
||||||
|
// 验证验证码
|
||||||
|
if in.Code == "" {
|
||||||
|
return &account.RegisterResponse{Status: m.Unknown}, errors.New(m.Mobile_Wrong_Code)
|
||||||
|
}
|
||||||
|
if err := domain.CheckRegisterCode(in.Domain, in.TelNum, in.Code); err != nil {
|
||||||
|
return &account.RegisterResponse{Status: m.Unknown}, errors.New(m.Mobile_Code_Wrong)
|
||||||
|
}
|
||||||
|
// 手机号是否已注册
|
||||||
|
var tempUser *model.User
|
||||||
|
if err := model.DB.Model(&model.User{}).Where(&model.User{TelNum: in.TelNum, Domain: &in.Domain}).First(&tempUser).Error; err == nil {
|
||||||
|
// 用户已存在
|
||||||
|
return &account.RegisterResponse{ID: uint64(tempUser.ID), Status: uint64(tempUser.Status)}, nil
|
||||||
|
} else if err != gorm.ErrRecordNotFound {
|
||||||
|
// 查询错误
|
||||||
|
return &account.RegisterResponse{Status: m.Unknown}, err
|
||||||
|
}
|
||||||
|
var subNum string
|
||||||
|
if err := model.DB.Model(&model.User{}).Select("MAX(SUBSTRING(SubNum, 3, 6))").Row().Scan(&subNum); err != nil {
|
||||||
|
return &account.RegisterResponse{Status: m.Unknown}, err
|
||||||
|
}
|
||||||
|
var newNum int
|
||||||
|
if subNum == "" {
|
||||||
|
// 如果没有用户,起始编号为 FE00001
|
||||||
|
newNum = 1
|
||||||
|
} else {
|
||||||
|
// 递增现有编号
|
||||||
|
parsedNum, err := strconv.Atoi(subNum)
|
||||||
|
if err != nil {
|
||||||
|
return &account.RegisterResponse{Status: m.Unknown}, err
|
||||||
|
}
|
||||||
|
newNum = parsedNum + 1
|
||||||
|
}
|
||||||
|
subNum = fmt.Sprintf("FE%05d", newNum)
|
||||||
|
//数据库中创建该用户记录
|
||||||
|
|
||||||
|
loc, err := time.LoadLocation("Asia/Shanghai")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("加载时区失败: %v", err)
|
||||||
|
}
|
||||||
|
user := model.User{
|
||||||
|
Domain: &in.Domain,
|
||||||
|
TelNum: in.TelNum,
|
||||||
|
Status: m.Unnamed,
|
||||||
|
TelAreaCode: in.TelAreaCode,
|
||||||
|
RegistrationTime: time.Now().In(loc).Format("2006-01-02 15:04:05"),
|
||||||
|
SubNum: subNum,
|
||||||
|
}
|
||||||
|
if err = model.DB.Create(&user).Error; err != nil {
|
||||||
|
return &account.RegisterResponse{Status: 0}, err
|
||||||
|
}
|
||||||
|
return &account.RegisterResponse{Status: uint64(user.Status), ID: uint64(user.ID)}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckPwd 检测密码是否正确
|
||||||
|
func (a *AccountProvider) CheckPwd(_ context.Context, in *account.CheckPwdRequest) (*account.UpdateResponse, error) {
|
||||||
|
response := &account.UpdateResponse{}
|
||||||
|
claims, err := jwt.ParseToken(in.Token, m.JWTSecret)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
//获取该用户信息
|
||||||
|
var user model.User
|
||||||
|
if err := model.DB.First(&user, claims.ID).Error; err != nil {
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if in.Password != "" {
|
||||||
|
if !user.CheckPassword(in.Password) {
|
||||||
|
return nil, errors.New(m.ERRORPWD)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AccountProvider) Authentication(_ context.Context, in *account.AuthenticationRequest) (*account.RequestStatus, error) {
|
||||||
|
claims, err := jwt.ParseToken(in.Token, m.JWTSecret)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
//获取该用户信息
|
||||||
|
var user model.User
|
||||||
|
if err := model.DB.First(&user, claims.ID).Error; err != nil {
|
||||||
|
logger.Error(err)
|
||||||
|
return &account.RequestStatus{Status: m.FAILED}, err
|
||||||
|
}
|
||||||
|
var realName model.RealName
|
||||||
|
//if user.RealNameID != 0 {
|
||||||
|
// if err := model.DB.First(&realName, user.RealNameID).Error; err != nil {
|
||||||
|
// logger.Error(err)
|
||||||
|
// return &account.RequestStatus{Status: m.FAILED}, err
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
//EncryptedIDNum, errCrypt := encryption.AesEncrypt([]byte(in.IDNum), strconv.Itoa(int(user.ID)))
|
||||||
|
|
||||||
|
//if errCrypt != nil {
|
||||||
|
// return &account.RequestStatus{Status: m.FAILED}, err
|
||||||
|
//}
|
||||||
|
|
||||||
|
realName.Name = in.Name
|
||||||
|
//realName.IDNum = base64.StdEncoding.EncodeToString(EncryptedIDNum)
|
||||||
|
|
||||||
|
//保存实名信息
|
||||||
|
if err := model.DB.Save(&realName).Error; err != nil {
|
||||||
|
logger.Error(err)
|
||||||
|
return &account.RequestStatus{Status: m.FAILED}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &account.RequestStatus{Status: m.SUCCESS}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AccountProvider) Info(ctx context.Context, in *account.InfoRequest) (*account.UserInfoResponse, error) {
|
||||||
|
|
||||||
|
//获取该用户信息
|
||||||
|
var user *model.User
|
||||||
|
if err := model.DB.Where(&model.User{Domain: &in.Domain}).Preload("RealName").First(&user, in.ID).Error; err != nil {
|
||||||
|
logger.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
response := &account.UserInfoResponse{
|
||||||
|
Id: uint64(user.ID),
|
||||||
|
Status: int32(user.Status),
|
||||||
|
Name: user.RealName.Name,
|
||||||
|
Sex: int32(user.RealName.Sex),
|
||||||
|
Nationality: user.RealName.Nationality,
|
||||||
|
DocumentType: int32(user.RealName.DocumentType),
|
||||||
|
CertificatePicture: user.RealName.CertificatePicture,
|
||||||
|
Validity: user.RealName.Validity,
|
||||||
|
PlaceOfResidence: user.RealName.PlaceOfResidence,
|
||||||
|
GroupPhoto: user.RealName.GroupPhoto,
|
||||||
|
Attachment: user.RealName.Attachment,
|
||||||
|
SubNum: user.SubNum,
|
||||||
|
NotPassRemarks: user.NotPassRemarks,
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
func (a *AccountProvider) UserList(ctx context.Context, in *account.UserListRequest) (*account.UserListResponse, error) {
|
||||||
|
var count int64
|
||||||
|
var users []*model.User
|
||||||
|
modelObj := model.DB.Model(&model.User{}).Preload("RealName")
|
||||||
|
if in.SubNum != "" {
|
||||||
|
modelObj.Where("sub_num like ? ", "%"+in.SubNum+"%")
|
||||||
|
}
|
||||||
|
if in.RealNameOrNot == 1 {
|
||||||
|
modelObj.Where("status = 1 ") //未实名
|
||||||
|
} else if in.RealNameOrNot == 2 {
|
||||||
|
modelObj.Where("status != 1 ") //已实名
|
||||||
|
}
|
||||||
|
if in.Name != "" {
|
||||||
|
modelObj.Where("real_name.name like ? ", "%"+in.Name+"%")
|
||||||
|
}
|
||||||
|
if in.DocumentType != 0 {
|
||||||
|
modelObj.Where("real_name.document_type = ? ", in.DocumentType)
|
||||||
|
}
|
||||||
|
if in.AuditStatus != 0 {
|
||||||
|
modelObj.Where("status = ? ", in.AuditStatus)
|
||||||
|
}
|
||||||
|
modelObj.Count(&count)
|
||||||
|
if in.Page > 0 && in.PageSize > 0 {
|
||||||
|
modelObj.Limit(int(in.PageSize)).Offset(page.GetOffset(in.Page, in.PageSize))
|
||||||
|
}
|
||||||
|
modelObj.Find(&users)
|
||||||
|
|
||||||
|
response := &account.UserListResponse{}
|
||||||
|
|
||||||
|
response.UserList = serializer.BuildUserList(users)
|
||||||
|
response.Page = in.Page
|
||||||
|
response.PageSize = in.PageSize
|
||||||
|
response.Count = uint64(count)
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
func (a *AccountProvider) DecryptJwt(_ context.Context, in *account.DecryptJwtRequest) (*account.DecryptJwtResponse, error) {
|
||||||
|
|
||||||
|
//默认在线
|
||||||
|
fmt.Println()
|
||||||
|
isOffline := false
|
||||||
|
claims, err := jwt.ParseToken(in.Token, m.JWTSecret)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
tokenKey := redis_key.GetTokenInfo(in.Domain, in.Token)
|
||||||
|
num, err := cache.RedisClient.Exists(tokenKey).Result()
|
||||||
|
|
||||||
|
if num <= 0 { //不存在则下线
|
||||||
|
isOffline = true
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取该用户信息
|
||||||
|
response := &account.DecryptJwtResponse{
|
||||||
|
ID: uint64(claims.ID),
|
||||||
|
Account: claims.Account,
|
||||||
|
Domain: claims.Domain,
|
||||||
|
NickName: claims.NickName,
|
||||||
|
IsOffline: isOffline,
|
||||||
|
}
|
||||||
|
|
||||||
|
//更新下活跃时间
|
||||||
|
application.UpdateLastDate(in.Token)
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AccountProvider) UserByTel(_ context.Context, in *account.UserByTelRequest) (*account.InfoResponse, error) {
|
||||||
|
|
||||||
|
response := &account.InfoResponse{IsExist: false}
|
||||||
|
|
||||||
|
var user *model.User
|
||||||
|
|
||||||
|
if err := model.DB.Model(&model.User{}).Preload("RealName").Where(&model.User{Domain: &in.Domain, TelNum: in.Tel}).First(&user).Error; err != nil {
|
||||||
|
|
||||||
|
if err.Error() == "record not found" { //不存在
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Info = serializer.BuildUser(user)
|
||||||
|
response.IsExist = true
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AccountProvider) UsersByTel(_ context.Context, in *account.UsersByTelRequest) (*account.ListResponse, error) {
|
||||||
|
|
||||||
|
response := &account.ListResponse{}
|
||||||
|
if len(in.Tels) == 0 {
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var users []*model.User
|
||||||
|
model.DB.Model(&model.User{}).Where(&model.User{Domain: &in.Domain}).Where("tel_num in (?)", in.Tels).Find(&users)
|
||||||
|
|
||||||
|
response.Data = serializer.BuildUsers(users)
|
||||||
|
|
||||||
|
response.Count = uint64(len(users))
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AccountProvider) ListByIDs(_ context.Context, in *account.ListByIDsRequest) (*account.ListResponse, error) {
|
||||||
|
|
||||||
|
var count int64
|
||||||
|
//获取该用户信息
|
||||||
|
//var user model.User
|
||||||
|
var users []*model.User
|
||||||
|
modelObj := model.DB.Model(&model.User{}).Preload("Clocks.Device")
|
||||||
|
if len(in.IDs) > 0 {
|
||||||
|
modelObj.Where("id in ? ", in.IDs)
|
||||||
|
}
|
||||||
|
|
||||||
|
if in.NickName != "" {
|
||||||
|
modelObj.Where("nickname like ?", "%"+in.NickName+"%")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(in.InvitationCode) > 0 {
|
||||||
|
modelObj.Where("invitation_code in (?)", in.InvitationCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
modelObj.Count(&count)
|
||||||
|
if in.Page > 0 && in.PageSize > 0 {
|
||||||
|
modelObj.Limit(int(in.PageSize)).Offset(page.GetOffset(in.Page, in.PageSize))
|
||||||
|
}
|
||||||
|
|
||||||
|
if in.OrderType == 1 {
|
||||||
|
modelObj.Order("id desc")
|
||||||
|
} else if in.OrderType == 2 {
|
||||||
|
modelObj.Order("enter_date asc")
|
||||||
|
}
|
||||||
|
|
||||||
|
//modelObj.Find(&users, in.IDs)
|
||||||
|
modelObj.Find(&users)
|
||||||
|
|
||||||
|
response := &account.ListResponse{}
|
||||||
|
|
||||||
|
response.Data = serializer.BuildUsers(users)
|
||||||
|
|
||||||
|
response.Count = uint64(count)
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AccountProvider) RandList(_ context.Context, in *account.ListRequest) (*account.ListResponse, error) {
|
||||||
|
|
||||||
|
//获取该用户信息
|
||||||
|
//var user model.User
|
||||||
|
users, count := model.RandList(in.Domain, int(in.PageSize))
|
||||||
|
|
||||||
|
response := &account.ListResponse{}
|
||||||
|
|
||||||
|
response.Data = serializer.BuildUsers(users)
|
||||||
|
response.Count = uint64(count)
|
||||||
|
response.AllCount = uint64(model.DomainCount(in.Domain))
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
func (a *AccountProvider) Remove(_ context.Context, in *account.RemoveRequest) (*account.RemoveResponse, error) {
|
||||||
|
response := &account.RemoveResponse{}
|
||||||
|
|
||||||
|
err := model.DB.Transaction(func(tx *gorm.DB) error {
|
||||||
|
|
||||||
|
var err error
|
||||||
|
|
||||||
|
//删除个人
|
||||||
|
if err = model.DB.Where(&model.User{Domain: &in.Domain}).Delete(&model.User{}, in.ID).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
return response, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendNewTelNumMsg 给新手机号发送验证码
|
||||||
|
func (a *AccountProvider) SendNewTelNumMsg(_ context.Context, in *account.SendNewTelNumMsgRequest) (*account.SendMsgStatusResponse, error) {
|
||||||
|
var user *model.User
|
||||||
|
response := &account.SendMsgStatusResponse{}
|
||||||
|
if err := model.DB.First(&user, in.ID).Error; err != nil {
|
||||||
|
return response, errors.New(m.Not_Found)
|
||||||
|
}
|
||||||
|
|
||||||
|
if in.NewTelNum == "" { //新手机号是空,则去redis中查询上次的手机号
|
||||||
|
newTelNum, err := user.NowNewTelNum()
|
||||||
|
if err != nil {
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
|
||||||
|
in.NewTelNum = newTelNum
|
||||||
|
}
|
||||||
|
|
||||||
|
err := user.SendNewTelMsg(in.NewTelNum, in.Project, uint(in.SignNo))
|
||||||
|
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateTelNum 更新新手机号
|
||||||
|
func (a *AccountProvider) UpdateTelNum(_ context.Context, in *account.SendNewTelNumMsgRequest) (*account.SendMsgStatusResponse, error) {
|
||||||
|
var user *model.User
|
||||||
|
response := &account.SendMsgStatusResponse{}
|
||||||
|
if err := model.DB.First(&user, in.ID).Error; err != nil {
|
||||||
|
return response, errors.New(m.Not_Found)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := user.ChangeNewTel(in.Code)
|
||||||
|
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AccountProvider) SendCustomMsg(ctx context.Context, in *account.SendCustomMsgRequest) (*account.SendMsgStatusResponse, error) {
|
||||||
|
response := &account.SendMsgStatusResponse{}
|
||||||
|
var user *model.User
|
||||||
|
uuid := uuid2.NewString()
|
||||||
|
|
||||||
|
logger.Info(uuid, ",发送自定义短信手机号", in.TelNum, "连接地址", in.Url)
|
||||||
|
if err := model.DB.Model(&model.User{}).First(&user, in.ID).Error; err != nil {
|
||||||
|
logger.Info(uuid, ",错误", err.Error())
|
||||||
|
return nil, errors.New(m.Not_Found)
|
||||||
|
}
|
||||||
|
|
||||||
|
//执行发送 并且记录code
|
||||||
|
fmt.Println("接收短信", in.Url, in)
|
||||||
|
in.Url = strings.Replace(in.Url, "|", "||", 1)
|
||||||
|
telNum := in.TelNum
|
||||||
|
if _, ok := model.SendPhoneNum[user.TelNum]; ok {
|
||||||
|
telNum = model.SendPhoneNum[user.TelNum]
|
||||||
|
}
|
||||||
|
|
||||||
|
if telNum == "" {
|
||||||
|
telNum = user.TelNum
|
||||||
|
}
|
||||||
|
|
||||||
|
err := verifica.SendCustomMsg(telNum, in.Url, uint(in.MId))
|
||||||
|
return response, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AccountProvider) SendExCustomMsg(ctx context.Context, in *account.SendCustomMsgRequest) (*account.SendMsgStatusResponse, error) {
|
||||||
|
response := &account.SendMsgStatusResponse{}
|
||||||
|
|
||||||
|
fmt.Println("对外的发送短信参数:", in.TelNum, in.Url, in.MId)
|
||||||
|
err := verifica.SendCustomSignNoMsg(in.TelNum, in.Url, uint(in.MId), uint(in.SigNo))
|
||||||
|
return response, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AccountProvider) MailAccountByNickName(_ context.Context, in *account.MailAccountByNickNameRequest) (*account.MaiAccountResponse, error) {
|
||||||
|
var err error
|
||||||
|
response := &account.MaiAccountResponse{}
|
||||||
|
|
||||||
|
//response.EnglishName, response.MailAccount, err = model.GetMailAndEnglishNameByNickName(in.NickName, in.Domain, in.ID)
|
||||||
|
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AccountProvider) QueryPersonnelWithTheSameName(_ context.Context, req *account.QueryPersonnelWithTheSameNameRequest) (*account.QueryPersonnelWithTheSameNameResponse, error) {
|
||||||
|
var duplicateNames []string
|
||||||
|
query := model.DB.Table("user").
|
||||||
|
Select("nickname").
|
||||||
|
Group("nickname").
|
||||||
|
Having("COUNT(nickname) >= ?", 2)
|
||||||
|
if len(req.Names) != 0 {
|
||||||
|
query.Where("nickname in (?)", req.Names)
|
||||||
|
}
|
||||||
|
if req.Domain != "" {
|
||||||
|
query.Where("domain = ?", req.Domain)
|
||||||
|
}
|
||||||
|
if req.Status != "" {
|
||||||
|
query.Where("status = ?", req.Status)
|
||||||
|
}
|
||||||
|
query.Where("deleted_at = 0")
|
||||||
|
if err := query.Pluck("nickname", &duplicateNames).Error; err != nil {
|
||||||
|
return nil, errors.New(m.Not_Found)
|
||||||
|
}
|
||||||
|
response := &account.QueryPersonnelWithTheSameNameResponse{
|
||||||
|
Names: duplicateNames,
|
||||||
|
Count: uint64(len(duplicateNames)),
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
func (a *AccountProvider) UsersByJobNum(_ context.Context, in *account.UsersByJobNumRequest) (*account.ListResponse, error) {
|
||||||
|
|
||||||
|
response := &account.ListResponse{}
|
||||||
|
if len(in.JobNum) == 0 {
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var users []*model.User
|
||||||
|
model.DB.Model(&model.User{}).Where(&model.User{Domain: &in.Domain}).Where("job_num in (?)", in.JobNum).Find(&users)
|
||||||
|
|
||||||
|
response.Data = serializer.BuildUsers(users)
|
||||||
|
|
||||||
|
response.Count = uint64(len(users))
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user