by Robin at 20240617

This commit is contained in:
Leufolium 2024-06-17 22:25:43 +08:00
parent 70422fce3a
commit 6159759111
37 changed files with 1087 additions and 66 deletions

View File

@ -104,6 +104,8 @@ const LocalConfigPath = "C:/Users/PC/Desktop/service/etc/mix/mix-local.yaml"
const ReservedUserIdRegexesConfig = PackageRootPath + "/etc/mix/resource/reg_reserved_user_id_config.xml"
const EsbRoutingTableConfig = PackageRootPath + "/etc/mix/resource/esb_routing_table_config.xml"
// H5调用路径
const H5CallUrl = "/api/streamer/list_ext_by_user_id"

View File

@ -214,6 +214,8 @@ var ErrCodeMsgMap = map[ErrCode]string{
ErrCodeWorkerIdSrvFail: "用户职业者id映射表服务错误",
ErrCodeWorkerIdNotExist: "用户职业者id映射表不存在",
ErrCodeHvyogoSrvFail: "慧用工接口服务错误",
}
const (
@ -519,6 +521,10 @@ const (
ErrCodeMediaNotExist ErrCode = -60002 // 媒体不存在
ErrCodeMediaUploadFail ErrCode = -60003 // 媒体上传失败
// Hvyogo: 61xxx
ErrCodeHvyogoSrvOk ErrCode = ErrCodeOk
ErrCodeHvyogoSrvFail ErrCode = -61001 // 慧用工接口服务错误
// Websocket: 1xxxxx
ErrCodeHandleWsFail ErrCode = -100001 // 长链连接失败

View File

@ -0,0 +1,7 @@
package interfaces
type HvyogoSignable interface {
GetArgString() string
SetSign(string)
GetCooperatorId() string
}

View File

@ -1,9 +1,14 @@
package request
import "fmt"
// 自由职业者网签查询报文
type HYG10000001Req struct {
CooperatorId string `json:"cooperatorId"`
Timestamp string `json:"timestamp"`
WorkerId string `json:"workerId"`
Sign string `json:"sign"`
*HYGBaseReq
Timestamp string `json:"timestamp"`
WorkerId string `json:"workerId"`
}
func (req *HYG10000001Req) GetArgString() string {
return fmt.Sprintf("cooperatorId=%s&timestamp=%s&workerId=%s", req.CooperatorId, req.Timestamp, req.WorkerId)
}

View File

@ -1,9 +1,14 @@
package request
import "fmt"
// 自由职业者信息详情查询
type HYG10000002Req struct {
CooperatorId string `json:"cooperatorId"`
Timestamp string `json:"timestamp"`
WorkerId string `json:"workerId"`
Sign string `json:"sign"`
*HYGBaseReq
Timestamp string `json:"timestamp"`
WorkerId string `json:"workerId"`
}
func (req *HYG10000002Req) GetArgString() string {
return fmt.Sprintf("cooperatorId=%s&timestamp=%s&workerId=%s", req.CooperatorId, req.Timestamp, req.WorkerId)
}

View File

@ -2,7 +2,7 @@ package request
// 下发(打款)报文
type HYG10010001Req struct {
CooperatorId string `json:"cooperatorId"` // 商户id
*HYGBaseReq
Timestamp string `json:"timestamp"` // 时间戳
WorkerName string `json:"workerName"` // 收款人姓名
ReceiptChannel int `json:"receiptChannel"` // 收款渠道
@ -19,5 +19,8 @@ type HYG10010001Req struct {
WorkTime string `json:"workTime"` // 服务时间
PositionId string `json:"positionId"` // 任务ID
WeChatAppId string `json:"weChatAppId"` // 微信下发指定AppID
Sign string `json:"sign"` // 签名
}
func (req *HYG10010001Req) GetArgString() string {
return ""
}

View File

@ -0,0 +1,14 @@
package request
type HYGBaseReq struct {
CooperatorId string `json:"cooperatorId"`
Sign string `json:"sign"`
}
func (req *HYGBaseReq) SetSign(sign string) {
req.Sign = sign
}
func (req *HYGBaseReq) GetCooperatorId() string {
return req.CooperatorId
}

View File

@ -0,0 +1,6 @@
package request
type HYGCommonReq struct {
CooperatorId string `json:"cooperatorId"`
BusinessBody string `json:"businessBody"`
}

View File

@ -1,10 +0,0 @@
package response
// 自由职业者网签查询报文
type HYG10000001Resp struct {
WorkerId string `json:"workerId"`
AgreeState string `json:"agreeState"`
AgreeDesc string `json:"agreeDesc"`
IdCardFront string `json:"idCardFront"`
IdCardBack string `json:"idCardBack"`
}

View File

@ -1,20 +0,0 @@
package response
// 自由职业者详细信息查询报文
type HYG10000002Resp struct {
WorkerId string `json:"workerId"` // 自由职业者ID
WorkerName string `json:"workerName"` // 自由职业者名称
WorkerMobile string `json:"workerMobile"` // 自由职业者手机号
IdentNo string `json:"identNo"` // 自由职业者证件号
CertificateType int `json:"certificateType"` // 自由职业者证件类型
BankCardNo string `json:"bankCardNo"` // 收款账号
SignState int `json:"signState"` // 签约状态
SignTime string `json:"signTime"` // 签约时间
SignDesc string `json:"signDesc"` // 签约状态描述
VerifiedStatus int `json:"verifiedStatus"` // 实名认证状态
VerifiedTime string `json:"verifiedTime"` // 实名认证时间
VerifiedDesc string `json:"verifiedDesc"` // 实名认证描述
WorkerCfcaSignFlag bool `json:"workerCfcaSignFlag"` // 职业者签约方式
CreateTime string `json:"createTime"` // 创建时间
UpdateTime string `json:"updateTime"` // 最后更新时间
}

View File

@ -1,7 +0,0 @@
package response
// 下发(打款)报文
type HYG10010001Resp struct {
DistributeAmount string `json:"distributeAmount"` // 下发金额(与上送金额相同)
DistributeId string `json:"distributeId"` // 慧用工平台处理单号
}

View File

@ -0,0 +1,36 @@
package proto
import "service/api/base"
type ApiQueryAgreeStateReq struct {
base.BaseRequest
}
type ApiQueryAgreeStateData struct {
StatusCode string `json:"status_code" deepcopier:"field:StatusCode"` // 返回码
StatusText string `json:"status_text" deepcopier:"field:StatusText"` // 返回信息
AgreeState string `json:"agree_state" deepcopier:"field:AgreeState"` // 签约状态
AgreeDesc string `json:"agree_desc" deepcopier:"field:AgreeDesc"` // 签约状态描述
}
type ApiQueryAgreeStateResp struct {
base.BaseResponse
Data *ApiQueryAgreeStateData `json:"data"`
}
type ApiSingleDistributeReq struct {
base.BaseRequest
DistributeAmount string `json:"distribute_amount"`
}
type ApiSingleDistributeData struct {
StatusCode string `json:"status_code"` // 返回码
StatusText string `json:"status_text"` // 返回信息
DistributeAmount string `json:"distribute_amount"` // 下发金额
DistributeId string `json:"distribute_id"` // 慧用工平台处理单号
}
type ApiSingleDistributeResp struct {
base.BaseResponse
Data *ApiSingleDistributeData `json:"data"`
}

View File

@ -1,6 +1,6 @@
package proto
type HvyogoCallbackReq struct {
type ExtAgreeCallbackReq struct {
CooperatorId string `json:"cooperatorId"` // 商户对接唯一标识,手机号
BusinessBody string `json:"businessBody" jcrypto:"hyg_aes"` // AES加密后的字符串
}

View File

@ -1,8 +1,45 @@
package proto
type HvyogoVO struct {
type ExtAgreeCallbackVO struct {
WorkerId string `json:"workerId"` // 职业者id
AgreeState string `json:"agreeState"` // 签约状态
AgreeDesc string `json:"agreeDesc"` // 签约状态描述
WorkerMobile string `json:"workerMobile"` // 自由职业者手机号
}
type WorkerAgreeStateVO struct {
StatusCode string `json:"statusCode"`
StatusText string `json:"statusText"`
WorkerId string `json:"workerId"`
AgreeState string `json:"agreeState"`
AgreeDesc string `json:"agreeDesc"`
IdCardFront string `json:"idCardFront"`
IdCardBack string `json:"idCardBack"`
}
type WorkerFindDetailsVO struct {
StatusCode string `json:"statusCode"`
StatusText string `json:"statusText"`
WorkerId string `json:"workerId"` // 自由职业者ID
WorkerName string `json:"workerName"` // 自由职业者名称
WorkerMobile string `json:"workerMobile"` // 自由职业者手机号
IdentNo string `json:"identNo"` // 自由职业者证件号
CertificateType int `json:"certificateType"` // 自由职业者证件类型
BankCardNo string `json:"bankCardNo"` // 收款账号
SignState int `json:"signState"` // 签约状态
SignTime string `json:"signTime"` // 签约时间
SignDesc string `json:"signDesc"` // 签约状态描述
VerifiedStatus int `json:"verifiedStatus"` // 实名认证状态
VerifiedTime string `json:"verifiedTime"` // 实名认证时间
VerifiedDesc string `json:"verifiedDesc"` // 实名认证描述
WorkerCfcaSignFlag bool `json:"workerCfcaSignFlag"` // 职业者签约方式
CreateTime string `json:"createTime"` // 创建时间
UpdateTime string `json:"updateTime"` // 最后更新时间
}
type SingleDistributeVO struct {
StatusCode string `json:"statusCode"`
StatusText string `json:"statusText"`
DistributeAmount string `json:"distributeAmount"` // 下发金额(与上送金额相同)
DistributeId string `json:"distributeId"` // 慧用工平台处理单号
}

View File

@ -50,13 +50,10 @@ type OpUpdateResp struct {
// op 列表
type OpListByMidReq struct {
base.BaseRequest
Mid int64 `json:"mid"`
}
type OpListByMidData struct {
WorkerId *dbstruct.WorkerId `json:"worker_id"`
Offset int `json:"offset"`
More int `json:"more"`
}
type OpListByMidResp struct {

View File

@ -86,11 +86,18 @@ func main() {
service.DefaultImageAuditTaskResultHandler = service.NewImageAuditTaskResultHandler()
service.DefaultTextAuditTaskResultHandler = service.NewTextAuditTaskResultHandler()
service.DefaultVideoModerationTaskResultHandler = service.NewVideoModerationTaskResultHandler()
service.DefaultEsbService = service.NewEsbService()
service.DefaultHvyogoService = service.NewHvyogoService()
err = service.DefaultService.Init(cfg)
if err != nil {
msg := fmt.Sprintf("Service init fail, err: %v", err)
PrintAndExit(msg)
}
err = service.DefaultEsbService.Init()
if err != nil {
msg := fmt.Sprintf("EsbService init fail, err: %v", err)
PrintAndExit(msg)
}
// 初始化媒体填充服务
mediafiller.Init(cfg.ServerInfo)

View File

@ -0,0 +1,42 @@
package controller
import (
"service/api/errcode"
"service/api/message/response"
hvyogoproto "service/api/proto/hvyogo/proto"
"service/app/mix/service"
"service/bizcommon/util"
"service/library/logger"
"github.com/gin-gonic/gin"
)
func ApiHvyogoQueryAgreeState(ctx *gin.Context) {
req := ctx.MustGet("client_req").(*hvyogoproto.ApiQueryAgreeStateReq)
// 存入数据
data, ec := service.DefaultService.ApiHvyogoQueryAgreeState(ctx, req)
if ec != errcode.ErrCodeWorkerIdSrvOk {
logger.Error("ApiHygQueryAgreeState fail, req: %v, ec: %v", util.ToJson(req), ec)
response.ReplyErrCodeMsg(ctx, ec)
return
}
ReplyOk(ctx, data)
}
func ApiHvyogoSingleDistribute(ctx *gin.Context) {
req := ctx.MustGet("client_req").(*hvyogoproto.ApiSingleDistributeReq)
// 存入数据
data, ec := service.DefaultService.ApiHvyogoSingleDistribute(ctx, req)
if ec != errcode.ErrCodeWorkerIdSrvOk {
logger.Error("ApiHygSingleDistribute fail, req: %v, ec: %v", util.ToJson(req), ec)
response.ReplyErrCodeMsg(ctx, ec)
return
}
ReplyOk(ctx, data)
}

View File

@ -11,14 +11,14 @@ import (
"github.com/gin-gonic/gin"
)
func HvyogoCallback(ctx *gin.Context) {
func ExtAgreeCallback(ctx *gin.Context) {
req := ctx.MustGet("client_req").(*hvyogoproto.HvyogoCallbackReq)
req := ctx.MustGet("client_req").(*hvyogoproto.ExtAgreeCallbackReq)
// 存入数据
ec := service.DefaultService.SaveHvyogoCallback(ctx, req)
ec := service.DefaultService.SaveAgreeCallback(ctx, req)
if ec != errcode.ErrCodeWorkerIdSrvOk {
logger.Error("SaveHvyogoCallback fail, req: %v, ec: %v", util.ToJson(req), ec)
logger.Error("SaveAgreeCallback fail, req: %v, ec: %v", util.ToJson(req), ec)
response.ReplyErrCodeMsg(ctx, ec)
return
}

View File

@ -261,6 +261,11 @@ func Init(r *gin.Engine) {
apiZoneCollaboratorGroup.POST("delete", middleware.JSONParamValidator(zone_collaborator_proto.ApiDeleteReq{}), middleware.JwtAuthenticator(), ApiDeleteZoneCollaborator)
apiZoneCollaboratorGroup.POST("list", middleware.JSONParamValidator(zone_collaborator_proto.ApiListReq{}), middleware.JwtAuthenticator(), ApiGetZoneCollaboratorList)
// 慧用工
apiHvyogoGroup := r.Group("/api/hvyogo")
apiHvyogoGroup.POST("query_agree_state", middleware.JSONParamValidator(hvyogoproto.ApiQueryAgreeStateReq{}), middleware.JwtAuthenticator(), ApiHvyogoQueryAgreeState)
apiHvyogoGroup.POST("single_distribute", middleware.JSONParamValidator(hvyogoproto.ApiSingleDistributeReq{}), middleware.JwtAuthenticator(), ApiHvyogoSingleDistribute)
// =============================== 以下是服务,只允许内网调用 ===============================
// op相关直接调用服务不调用gateway
@ -307,8 +312,9 @@ func Init(r *gin.Engine) {
opVasPayGroup.POST("zone_refund_list", middleware.JSONParamValidator(zoneproto.OpZoneRefundListParam{}), OpZoneRefundList)
opVasPayGroup.POST("manual_unlock_wechat", middleware.JSONParamValidator(zoneproto.OpManualUnlockWechatParam{}), OpManualUnlockWechat)
extEsbGroup := r.Group("/ext/hvyogo")
extEsbGroup.POST("agree_callback", middleware.JSONParamValidator(hvyogoproto.HvyogoCallbackReq{}), middleware.RequestDecryptor(), HvyogoCallback)
// 慧用工
extHvyogoGroup := r.Group("/ext/hvyogo")
extHvyogoGroup.POST("agree_callback", middleware.JSONParamValidator(hvyogoproto.ExtAgreeCallbackReq{}), middleware.RequestDecryptor(), ExtAgreeCallback)
// 验证码
opVeriCodeGroup := r.Group("/op/veri_code", PrepareOp())

View File

@ -5260,7 +5260,7 @@ func (m *Mongo) GetWorkerIdByMid(ctx *gin.Context, req *workeridproto.OpListByMi
workerId := &dbstruct.WorkerId{}
col := m.getColWorkerId()
query := qmgo.M{
"mid": req.Mid,
"mid": req.BaseRequest.Mid,
"del_flag": 0,
}
err := col.Find(ctx, query).One(workerId)

View File

@ -5,6 +5,7 @@ import (
"service/api/base"
"service/api/consts"
"service/api/errcode"
"service/api/message/request"
accountproto "service/api/proto/account/proto"
account_cancellationproto "service/api/proto/account_cancellation/proto"
accountrelationproto "service/api/proto/accountrelation/proto"
@ -12,6 +13,7 @@ import (
contact_customer_service_proto "service/api/proto/contact_customer_service/proto"
contact_customer_service_sessionproto "service/api/proto/contact_customer_service_session/proto"
feedbackproto "service/api/proto/feedback/proto"
hvyogoproto "service/api/proto/hvyogo/proto"
loginproto "service/api/proto/login/proto"
momentproto "service/api/proto/moment/proto"
moment_audit_taskproto "service/api/proto/moment_audit_task/proto"
@ -25,6 +27,7 @@ import (
userwxaddcheckproto "service/api/proto/userwxaddcheck/proto"
vasproto "service/api/proto/vas/proto"
vericodeproto "service/api/proto/vericode/proto"
workeridproto "service/api/proto/worker_id/proto"
zoneproto "service/api/proto/zone/proto"
zone_collaborator_proto "service/api/proto/zone_collaborator/proto"
zone_third_partner_proto "service/api/proto/zone_third_partner/proto"
@ -37,6 +40,7 @@ import (
"service/dbstruct"
"service/library/apollo"
"service/library/logger"
"service/library/mycrypto"
interceptor "service/library/taginterceptor"
"time"
@ -45,6 +49,7 @@ import (
"github.com/gin-gonic/gin"
"github.com/qiniu/qmgo"
"github.com/ulule/deepcopier"
)
// 发送验证码
@ -3252,3 +3257,69 @@ func (s *Service) ApiGetZoneCollaboratorList(ctx *gin.Context, req *zone_collabo
return
}
func (s *Service) ApiHvyogoQueryAgreeState(ctx *gin.Context, req *hvyogoproto.ApiQueryAgreeStateReq) (data *hvyogoproto.ApiQueryAgreeStateData, ec errcode.ErrCode) {
// 1.查询手机号
account, err := _DefaultAccount.OpListByMid(ctx, &accountproto.OpListByMidReq{
Mid: goproto.Int64(req.BaseRequest.Mid),
})
if err != nil {
logger.Error("OpListByMid fail, err: %v", err)
ec = errcode.ErrCodeAccountSrvFail
return
}
if account == nil {
logger.Error("No account entity was found")
ec = errcode.ErrCodeAccountNotExist
return
}
bytes, err := mycrypto.CryptoServiceInstance().AES.Decrypt([]byte(util.DerefString(account.MobilePhone)))
if err != nil {
logger.Error("AES Decrypt fail, err: %v", err)
ec = errcode.ErrCodeDecryptionInterceptFail
return
}
// 2.查询workerId
workerId, err := _DefaultWorkerId.OpListByMid(ctx, &workeridproto.OpListByMidReq{
BaseRequest: req.BaseRequest,
})
if err != nil {
logger.Error("_DefaultWorkerId OpListByMid fail, err: %v", err)
ec = errcode.ErrCodeWorkerIdSrvFail
return
}
if workerId == nil {
logger.Error("No worker_id entity was found")
ec = errcode.ErrCodeWorkerIdNotExist
return
}
// 3.组装查询报文
msg := &request.HYG10000001Req{
HYGBaseReq: &request.HYGBaseReq{
CooperatorId: string(bytes),
},
WorkerId: workerId.GetWorkerId(),
}
// 4.调用查询接口
resp, err := DefaultHvyogoService.WorkerAgreeState(msg)
if err != nil {
logger.Error("DefaultHvyogoService WorkerAgreeState fail, err: %v", err)
ec = errcode.ErrCodeHvyogoSrvFail
return
}
// 5.组装返回结果
data = &hvyogoproto.ApiQueryAgreeStateData{}
deepcopier.Copy(resp).To(data)
return
}
func (s *Service) ApiHvyogoSingleDistribute(ctx *gin.Context, req *hvyogoproto.ApiSingleDistributeReq) (data *hvyogoproto.ApiSingleDistributeData, ec errcode.ErrCode) {
return
}

View File

@ -1,5 +1,17 @@
package service
import (
"bytes"
"io"
"net/http"
"service/api/consts"
"service/library/logger"
"github.com/beevik/etree"
)
var DefaultEsbService *EsbService
type EsbService struct {
RoutingTable map[string]string
}
@ -9,10 +21,57 @@ func NewEsbService() *EsbService {
}
func (s *EsbService) Init() (err error) {
// 初始化路由表
s.RoutingTable = make(map[string]string)
fullPath := consts.EsbRoutingTableConfig
doc := etree.NewDocument()
if err := doc.ReadFromFile(fullPath); err != nil {
logger.Error("read xml failed:%v.", err)
}
root := doc.SelectElement("esb_routing_table")
if root == nil {
logger.Error("read node esb_routing_table failed")
}
msgs := root.FindElements("./msg")
if msgs == nil {
logger.Error("read node msg failed")
}
for _, msg := range msgs {
name := msg.SelectAttrValue("name", "")
url := msg.Text()
s.RoutingTable[name] = url
}
return
}
// 发送消息
func (s *EsbService) SendMsg(msgNo string, msg string) (err error) {
func (s *EsbService) SendMsg(msgNo string, msg []byte) (resp []byte, err error) {
// 取路由地址
url := s.RoutingTable[msgNo]
// 组装请求报文
req, err := http.NewRequest("POST", url, bytes.NewBuffer(msg))
if err != nil {
logger.Error("http NewRequest fail, err: %v", err)
return
}
req.Header.Set("Content-Type", "application/json")
client := http.DefaultClient
response, err := client.Do(req)
if err != nil {
logger.Error("client Do fail, err: %v", err)
return
}
defer response.Body.Close()
resp, err = io.ReadAll(response.Body)
if err != nil {
logger.Error("response read fail, err: %v", err)
return
}
return
}

View File

@ -1,3 +1,142 @@
package service
func (s *Service)
import (
"encoding/json"
"fmt"
"service/api/message/request"
"service/api/message/response"
"service/bizcommon/util"
"service/library/logger"
"service/library/mycrypto"
"time"
hvyogoproto "service/api/proto/hvyogo/proto"
)
var DefaultHvyogoService *HvyogoService
type HvyogoService struct{}
func NewHvyogoService() *HvyogoService {
return new(HvyogoService)
}
func (s *HvyogoService) WorkerAgreeState(req *request.HYG10000001Req) (vo *hvyogoproto.WorkerAgreeStateVO, err error) {
// 写参
req.Timestamp = fmt.Sprint(time.Now().Unix())
// 加签
msg, err := DefaultService.utilSignHvyogoMessage(req)
if err != nil {
logger.Error("utilSignHvyogoMessage fail, req: %v, err: %v", util.ToJson(req), err)
return
}
// 发送消息
resp, err := DefaultEsbService.SendMsg("HYG10000001", msg)
if err != nil {
logger.Error("SendMsg fail, req: %v, err: %v", util.ToJson(req), err)
return
}
// 处理返回数据
vo = &hvyogoproto.WorkerAgreeStateVO{}
err = afterReceiving(resp, vo)
if err != nil {
logger.Error("afterReceiving fail, req: %v, err: %v", util.ToJson(req), err)
return
}
return
}
func (s *HvyogoService) WorkerFindDetail(req *request.HYG10000002Req) (vo *hvyogoproto.WorkerFindDetailsVO, err error) {
// 写参
req.Timestamp = fmt.Sprint(time.Now().Unix())
// 加签
msg, err := DefaultService.utilSignHvyogoMessage(req)
if err != nil {
logger.Error("utilSignHvyogoMessage fail, req: %v, err: %v", util.ToJson(req), err)
return
}
// 发送消息
resp, err := DefaultEsbService.SendMsg("HYG10000002", msg)
if err != nil {
logger.Error("SendMsg fail, req: %v, err: %v", util.ToJson(req), err)
return
}
// 处理返回数据
vo = &hvyogoproto.WorkerFindDetailsVO{}
err = afterReceiving(resp, vo)
if err != nil {
logger.Error("afterReceiving fail, req: %v, err: %v", util.ToJson(req), err)
return
}
return
}
func (s *HvyogoService) SingleDistribute(req *request.HYG10010001Req) (vo *hvyogoproto.SingleDistributeVO, err error) {
// 写参
req.Timestamp = fmt.Sprint(time.Now().Unix())
// 加签
msg, err := DefaultService.utilSignHvyogoMessage(req)
if err != nil {
logger.Error("utilSignHvyogoMessage fail, req: %v, err: %v", util.ToJson(req), err)
return
}
// 发送消息
resp, err := DefaultEsbService.SendMsg("HYG10010001", msg)
if err != nil {
logger.Error("SendMsg fail, req: %v, err: %v", util.ToJson(req), err)
return
}
// 处理返回数据
vo = &hvyogoproto.SingleDistributeVO{}
err = afterReceiving(resp, vo)
if err != nil {
logger.Error("afterReceiving fail, req: %v, err: %v", util.ToJson(req), err)
return
}
return
}
func afterReceiving(resp []byte, vo any) (err error) {
baseResponse := &response.HygBaseResponse{}
err = json.Unmarshal(resp, baseResponse)
if err != nil {
logger.Error("json Unmarshal fail, err: %v", err)
return
}
aesEncryptedStr, ok := baseResponse.Data.(string)
if !ok {
err = fmt.Errorf("type assertion fail")
logger.Error("Type assertion fail, err: %v", err)
return
}
// 解码aes
bytes, err := mycrypto.CryptoServiceInstance().HygAES.Decrypt([]byte(aesEncryptedStr))
if err != nil {
logger.Error("Decryption fail, err: %v", err)
return
}
// 解析至VO
err = json.Unmarshal(bytes, vo)
if err != nil {
logger.Error("json Unmarshal fail, err: %v", err)
return
}
err = json.Unmarshal(resp, vo)
if err != nil {
logger.Error("json Unmarshal fail, err: %v", err)
return
}
return
}

View File

@ -4114,11 +4114,11 @@ func (s *Service) OpGetWorkerIdByMid(ctx *gin.Context, req *workeridproto.OpList
return
}
func (s *Service) SaveHvyogoCallback(ctx *gin.Context, req *hvyogoproto.HvyogoCallbackReq) (ec errcode.ErrCode) {
func (s *Service) SaveAgreeCallback(ctx *gin.Context, req *hvyogoproto.ExtAgreeCallbackReq) (ec errcode.ErrCode) {
ec = errcode.ErrCodeWorkerIdSrvOk
// 解析BusinessBody
vo := &hvyogoproto.HvyogoVO{}
vo := &hvyogoproto.ExtAgreeCallbackVO{}
if err := json.Unmarshal([]byte(req.BusinessBody), vo); err != nil {
logger.Error("Unmarshal fail, req: %v, err: %v", util.ToJson(req), err)
ec = errcode.ErrCodeAssertionFail

View File

@ -1,10 +1,12 @@
package service
import (
"encoding/json"
"fmt"
"service/api/consts"
"service/api/errcode"
"service/api/interfaces"
"service/api/message/request"
accountproto "service/api/proto/account/proto"
accountrelationproto "service/api/proto/accountrelation/proto"
contact_customer_service_sessionproto "service/api/proto/contact_customer_service_session/proto"
@ -28,6 +30,7 @@ import (
"service/dbstruct"
"service/library/apollo"
"service/library/logger"
"service/library/mycrypto"
"service/library/redis"
"strconv"
"strings"
@ -2091,3 +2094,38 @@ func (s *Service) utilAssembleDailyStatementZoneInfo(zoneprofits, zonerefunds []
return
}
func (s *Service) utilSignHvyogoMessage(msg interfaces.HvyogoSignable) ([]byte, error) {
// 1.RSA加密生成签名
msg.GetArgString()
sign := ""
// 2.设置签名
msg.SetSign(sign)
// 3.AES加密
bytes, err := json.Marshal(msg)
if err != nil {
logger.Error("json Marshal fail, err :%v", err)
return make([]byte, 0), err
}
aesEncryptedBytes, err := mycrypto.CryptoServiceInstance().HygAES.Encrypt(bytes)
if err != nil {
logger.Error("HygAES Encryption fail, err :%v", err)
return make([]byte, 0), err
}
// 4.生成最终报文
result := &request.HYGCommonReq{
CooperatorId: msg.GetCooperatorId(),
BusinessBody: string(aesEncryptedBytes),
}
resultBytes, err := json.Marshal(result)
if err != nil {
logger.Error("json Marshal fail, err :%v", err)
return make([]byte, 0), err
}
return resultBytes, nil
}

View File

@ -7,5 +7,11 @@ type WorkerId struct {
Ct *int64 `json:"ct" bson:"ct"` // 创建时间
Ut *int64 `json:"ut" bson:"ut"` // 更新时间
DelFlag *int64 `json:"del_flag" bson:"del_flag"` // 删除标记
}
func (p *WorkerId) GetWorkerId() string {
if p == nil || p.WorkerId == nil {
return ""
}
return *p.WorkerId
}

View File

@ -12,7 +12,7 @@ app:
port: 9999
mix_mongo:
uri: "mongodb://127.0.0.1:27017"
uri: "mongodb://admin:Wishpal%402023@127.0.0.1:27017"
username: ""
password: ""
max_pool_size: 16
@ -22,7 +22,7 @@ mix_mongo:
mix_mysql:
uri: "127.0.0.1:3306"
username: "root"
password: "11111111"
password: "Wishpal@2023"
timeout: 3
read_timeout_s: 5
write_timeout_s: 3
@ -98,6 +98,10 @@ redis:
server_info:
file_server_domain_name: "https://file.wishpaldev.tech/"
main_server_ips: "101.37.77.228"
main_server_ports: "9999"
main_server_users: "root"
main_server_passwords: "Wishpal@2024"
xxl_job:
server_addr: "http://127.0.0.1:9800/xxl-job-admin"
@ -107,6 +111,16 @@ xxl_job:
registry_key: "golang-jobs-executor"
log_path: "/Users/erwin/log/wishpal-ironfan/"
ding_talk_robot:
access_token: "65f11ade605568c34f33ff79ed4c20c1721bd6da18511d8e08a6ed9666c4b8b4"
secret: "SECcc49257b2681b6488ab4be8ee815c61027a7254e2be3239c229de38b22207b5b"
elastic_search:
uri: "http://127.0.0.1:9200"
username: "elastic"
password: "Wishpal@2024"
sniff: false
sd:
host: "https://consul.tiefen.fun"
service_name: "local_test"

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<esb_routing_table>
<msg name = "HYG10000001"></msg>
<msg name = "HYG10000002"></msg>
<msg name = "HYG10010001"></msg>
</esb_routing_table>

1
go.mod
View File

@ -117,6 +117,7 @@ require (
github.com/stretchr/testify v1.9.0
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
github.com/ulule/deepcopier v0.0.0-20200430083143-45decc6639b6
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.1.1 // indirect
github.com/xdg-go/stringprep v1.0.3 // indirect

2
go.sum
View File

@ -546,6 +546,8 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/ulule/deepcopier v0.0.0-20200430083143-45decc6639b6 h1:TtyC78WMafNW8QFfv3TeP3yWNDG+uxNkk9vOrnDu6JA=
github.com/ulule/deepcopier v0.0.0-20200430083143-45decc6639b6/go.mod h1:h8272+G2omSmi30fBXiZDMkmHuOgonplfKIKjQWzlfs=
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.1.1 h1:VOMT+81stJgXW3CpHyqHN3AXDYIMsx56mEFrB37Mb/E=

24
vendor/github.com/ulule/deepcopier/.gitignore generated vendored Normal file
View File

@ -0,0 +1,24 @@
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
*.test
*.prof

4
vendor/github.com/ulule/deepcopier/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,4 @@
language: go
go:
- 1.13
script: make test

22
vendor/github.com/ulule/deepcopier/LICENSE generated vendored Normal file
View File

@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2015 Ulule
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

5
vendor/github.com/ulule/deepcopier/Makefile generated vendored Normal file
View File

@ -0,0 +1,5 @@
.PHONY: test
test:
cd tests; go test -race
cd tests; go test -cover
cd tests; go test -v

129
vendor/github.com/ulule/deepcopier/README.md generated vendored Normal file
View File

@ -0,0 +1,129 @@
# Deepcopier
[![Build Status](https://secure.travis-ci.org/ulule/deepcopier.svg?branch=master)](http://travis-ci.org/ulule/deepcopier)
This package is meant to make copying of structs to/from others structs a bit easier.
## Installation
```bash
go get -u github.com/ulule/deepcopier
```
## Usage
```golang
// Deep copy instance1 into instance2
Copy(instance1).To(instance2)
// Deep copy instance1 into instance2 and passes the following context (which
// is basically a map[string]interface{}) as first argument
// to methods of instance2 that defined the struct tag "context".
Copy(instance1).WithContext(map[string]interface{}{"foo": "bar"}).To(instance2)
// Deep copy instance2 into instance1
Copy(instance1).From(instance2)
// Deep copy instance2 into instance1 and passes the following context (which
// is basically a map[string]interface{}) as first argument
// to methods of instance1 that defined the struct tag "context".
Copy(instance1).WithContext(map[string]interface{}{"foo": "bar"}).From(instance2)
```
Available options for `deepcopier` struct tag:
| Option | Description |
| --------- | -------------------------------------------------------------------- |
| `field` | Field or method name in source instance |
| `skip` | Ignores the field |
| `context` | Takes a `map[string]interface{}` as first argument (for methods) |
| `force` | Set the value of a `sql.Null*` field (instead of copying the struct) |
**Options example:**
```golang
type Source struct {
Name string
SkipMe string
SQLNullStringToSQLNullString sql.NullString
SQLNullStringToString sql.NullString
}
func (Source) MethodThatTakesContext(c map[string]interface{}) string {
return "whatever"
}
type Destination struct {
FieldWithAnotherNameInSource string `deepcopier:"field:Name"`
SkipMe string `deepcopier:"skip"`
MethodThatTakesContext string `deepcopier:"context"`
SQLNullStringToSQLNullString sql.NullString
SQLNullStringToString string `deepcopier:"force"`
}
```
Example:
```golang
package main
import (
"fmt"
"github.com/ulule/deepcopier"
)
// Model
type User struct {
// Basic string field
Name string
// Deepcopier supports https://golang.org/pkg/database/sql/driver/#Valuer
Email sql.NullString
}
func (u *User) MethodThatTakesContext(ctx map[string]interface{}) string {
// do whatever you want
return "hello from this method"
}
// Resource
type UserResource struct {
DisplayName string `deepcopier:"field:Name"`
SkipMe string `deepcopier:"skip"`
MethodThatTakesContext string `deepcopier:"context"`
Email string `deepcopier:"force"`
}
func main() {
user := &User{
Name: "gilles",
Email: sql.NullString{
Valid: true,
String: "gilles@example.com",
},
}
resource := &UserResource{}
deepcopier.Copy(user).To(resource)
fmt.Println(resource.DisplayName)
fmt.Println(resource.Email)
}
```
Looking for more information about the usage?
We wrote [an introduction article](https://github.com/ulule/deepcopier/blob/master/examples/rest-usage/README.rst).
Have a look and feel free to give us your feedback.
## Contributing
* Ping us on twitter [@oibafsellig](https://twitter.com/oibafsellig), [@thoas](https://twitter.com/thoas)
* Fork the [project](https://github.com/ulule/deepcopier)
* Help us improving and fixing [issues](https://github.com/ulule/deepcopier/issues)
Don't hesitate ;)

362
vendor/github.com/ulule/deepcopier/deepcopier.go generated vendored Normal file
View File

@ -0,0 +1,362 @@
package deepcopier
import (
"database/sql/driver"
"fmt"
"reflect"
"strings"
)
const (
// TagName is the deepcopier struct tag name.
TagName = "deepcopier"
// FieldOptionName is the from field option name for struct tag.
FieldOptionName = "field"
// ContextOptionName is the context option name for struct tag.
ContextOptionName = "context"
// SkipOptionName is the skip option name for struct tag.
SkipOptionName = "skip"
// ForceOptionName is the skip option name for struct tag.
ForceOptionName = "force"
)
type (
// TagOptions is a map that contains extracted struct tag options.
TagOptions map[string]string
// Options are copier options.
Options struct {
// Context given to WithContext() method.
Context map[string]interface{}
// Reversed reverses struct tag checkings.
Reversed bool
}
)
// DeepCopier deep copies a struct to/from a struct.
type DeepCopier struct {
dst interface{}
src interface{}
ctx map[string]interface{}
}
// Copy sets source or destination.
func Copy(src interface{}) *DeepCopier {
return &DeepCopier{src: src}
}
// WithContext injects the given context into the builder instance.
func (dc *DeepCopier) WithContext(ctx map[string]interface{}) *DeepCopier {
dc.ctx = ctx
return dc
}
// To sets the destination.
func (dc *DeepCopier) To(dst interface{}) error {
dc.dst = dst
return process(dc.dst, dc.src, Options{Context: dc.ctx})
}
// From sets the given the source as destination and destination as source.
func (dc *DeepCopier) From(src interface{}) error {
dc.dst = dc.src
dc.src = src
return process(dc.dst, dc.src, Options{Context: dc.ctx, Reversed: true})
}
// process handles copy.
func process(dst interface{}, src interface{}, args ...Options) error {
var (
options = Options{}
srcValue = reflect.Indirect(reflect.ValueOf(src))
dstValue = reflect.Indirect(reflect.ValueOf(dst))
srcFieldNames = getFieldNames(src)
srcMethodNames = getMethodNames(src)
)
if len(args) > 0 {
options = args[0]
}
if !dstValue.CanAddr() {
return fmt.Errorf("destination %+v is unaddressable", dstValue.Interface())
}
for _, f := range srcFieldNames {
var (
srcFieldValue = srcValue.FieldByName(f)
srcFieldType, srcFieldFound = srcValue.Type().FieldByName(f)
srcFieldName = srcFieldType.Name
dstFieldName = srcFieldName
tagOptions TagOptions
)
if !srcFieldFound {
continue
}
if options.Reversed {
tagOptions = getTagOptions(srcFieldType.Tag.Get(TagName))
if v, ok := tagOptions[FieldOptionName]; ok && v != "" {
dstFieldName = v
}
} else {
if name, opts := getRelatedField(dst, srcFieldName); name != "" {
dstFieldName, tagOptions = name, opts
}
}
if _, ok := tagOptions[SkipOptionName]; ok {
continue
}
var (
dstFieldType, dstFieldFound = dstValue.Type().FieldByName(dstFieldName)
dstFieldValue = dstValue.FieldByName(dstFieldName)
)
if !dstFieldFound {
continue
}
// Force option for empty interfaces and nullable types
_, force := tagOptions[ForceOptionName]
// Valuer -> ptr
if isNullableType(srcFieldType.Type) && dstFieldValue.Kind() == reflect.Ptr && force {
// We have same nullable type on both sides
if srcFieldValue.Type().AssignableTo(dstFieldType.Type) {
dstFieldValue.Set(srcFieldValue)
continue
}
v, _ := srcFieldValue.Interface().(driver.Valuer).Value()
if v == nil {
continue
}
valueType := reflect.TypeOf(v)
ptr := reflect.New(valueType)
ptr.Elem().Set(reflect.ValueOf(v))
if valueType.AssignableTo(dstFieldType.Type.Elem()) {
dstFieldValue.Set(ptr)
}
continue
}
// Valuer -> value
if isNullableType(srcFieldType.Type) {
// We have same nullable type on both sides
if srcFieldValue.Type().AssignableTo(dstFieldType.Type) {
dstFieldValue.Set(srcFieldValue)
continue
}
if force {
v, _ := srcFieldValue.Interface().(driver.Valuer).Value()
if v == nil {
continue
}
rv := reflect.ValueOf(v)
if rv.Type().AssignableTo(dstFieldType.Type) {
dstFieldValue.Set(rv)
}
}
continue
}
if dstFieldValue.Kind() == reflect.Interface {
if force {
dstFieldValue.Set(srcFieldValue)
}
continue
}
// Ptr -> Value
if srcFieldType.Type.Kind() == reflect.Ptr && !srcFieldValue.IsNil() && dstFieldType.Type.Kind() != reflect.Ptr {
indirect := reflect.Indirect(srcFieldValue)
if indirect.Type().AssignableTo(dstFieldType.Type) {
dstFieldValue.Set(indirect)
continue
}
}
// Other types
if srcFieldType.Type.AssignableTo(dstFieldType.Type) {
dstFieldValue.Set(srcFieldValue)
}
}
for _, m := range srcMethodNames {
name, opts := getRelatedField(dst, m)
if name == "" {
continue
}
if _, ok := opts[SkipOptionName]; ok {
continue
}
method := reflect.ValueOf(src).MethodByName(m)
if !method.IsValid() {
return fmt.Errorf("method %s is invalid", m)
}
var (
dstFieldType, _ = dstValue.Type().FieldByName(name)
dstFieldValue = dstValue.FieldByName(name)
_, withContext = opts[ContextOptionName]
_, force = opts[ForceOptionName]
)
args := []reflect.Value{}
if withContext {
args = []reflect.Value{reflect.ValueOf(options.Context)}
}
var (
result = method.Call(args)[0]
resultInterface = result.Interface()
resultValue = reflect.ValueOf(resultInterface)
resultType = resultValue.Type()
)
// Value -> Ptr
if dstFieldValue.Kind() == reflect.Ptr && force {
ptr := reflect.New(resultType)
ptr.Elem().Set(resultValue)
if ptr.Type().AssignableTo(dstFieldType.Type) {
dstFieldValue.Set(ptr)
}
continue
}
// Ptr -> value
if resultValue.Kind() == reflect.Ptr && force {
if resultValue.Elem().Type().AssignableTo(dstFieldType.Type) {
dstFieldValue.Set(resultValue.Elem())
}
continue
}
if resultType.AssignableTo(dstFieldType.Type) && result.IsValid() {
dstFieldValue.Set(result)
}
}
return nil
}
// getTagOptions parses deepcopier tag field and returns options.
func getTagOptions(value string) TagOptions {
options := TagOptions{}
for _, opt := range strings.Split(value, ";") {
o := strings.Split(opt, ":")
// deepcopier:"keyword; without; value;"
if len(o) == 1 {
options[o[0]] = ""
}
// deepcopier:"key:value; anotherkey:anothervalue"
if len(o) == 2 {
options[strings.TrimSpace(o[0])] = strings.TrimSpace(o[1])
}
}
return options
}
// getRelatedField returns first matching field.
func getRelatedField(instance interface{}, name string) (string, TagOptions) {
var (
value = reflect.Indirect(reflect.ValueOf(instance))
fieldName string
tagOptions TagOptions
)
for i := 0; i < value.NumField(); i++ {
var (
vField = value.Field(i)
tField = value.Type().Field(i)
tagOptions = getTagOptions(tField.Tag.Get(TagName))
)
if tField.Type.Kind() == reflect.Struct && tField.Anonymous {
if n, o := getRelatedField(vField.Interface(), name); n != "" {
return n, o
}
}
if v, ok := tagOptions[FieldOptionName]; ok && v == name {
return tField.Name, tagOptions
}
if tField.Name == name {
return tField.Name, tagOptions
}
}
return fieldName, tagOptions
}
// getMethodNames returns instance's method names.
func getMethodNames(instance interface{}) []string {
var methods []string
t := reflect.TypeOf(instance)
for i := 0; i < t.NumMethod(); i++ {
methods = append(methods, t.Method(i).Name)
}
return methods
}
// getFieldNames returns instance's field names.
func getFieldNames(instance interface{}) []string {
var (
fields []string
v = reflect.Indirect(reflect.ValueOf(instance))
t = v.Type()
)
if t.Kind() != reflect.Struct {
return nil
}
for i := 0; i < v.NumField(); i++ {
var (
vField = v.Field(i)
tField = v.Type().Field(i)
)
// Is exportable?
if tField.PkgPath != "" {
continue
}
if tField.Type.Kind() == reflect.Struct && tField.Anonymous {
fields = append(fields, getFieldNames(vField.Interface())...)
continue
}
fields = append(fields, tField.Name)
}
return fields
}
// isNullableType returns true if the given type is a nullable one.
func isNullableType(t reflect.Type) bool {
return t.ConvertibleTo(reflect.TypeOf((*driver.Valuer)(nil)).Elem())
}

3
vendor/modules.txt vendored
View File

@ -430,6 +430,9 @@ github.com/twitchyliquid64/golang-asm/unsafeheader
# github.com/ugorji/go/codec v1.2.12
## explicit; go 1.11
github.com/ugorji/go/codec
# github.com/ulule/deepcopier v0.0.0-20200430083143-45decc6639b6
## explicit; go 1.14
github.com/ulule/deepcopier
# github.com/xdg-go/pbkdf2 v1.0.0
## explicit; go 1.9
github.com/xdg-go/pbkdf2