diff --git a/configs/config.yaml b/configs/config.yaml index 6c00b25..cca15ea 100644 --- a/configs/config.yaml +++ b/configs/config.yaml @@ -53,6 +53,13 @@ wechat: mchCertificateSerialNumber: "6006B8208815DB5EAC5BF2E783CB9D34082C3772" #商户证书序列号 wechatPayPublicKeyID: "PUB_KEY_ID_0117109533612025031800326400002563" #微信支付公钥ID +wechatSubject: + - mchID: "1100040695" # 证书所属商户 + name: "福建峦峰网络科技有限公司" + mchApiV3Key: "d9af70585b18ae206d981548c766563f" + mchCertificateSerialNumber: "46712853869DB0EDAA9B4DF97DADEECD4CCDC85B" #商户证书序列号 + wechatPayPublicKeyID: "PUB_KEY_ID_0111000406952026032500382251001000" #微信支付公钥ID,有它则为新的“公私钥”模式 + cmb: sm2Prk: "8d39ff3d2559258c163f4510f082727f51531e1953ab203d5ab1ea4a6d94fd73" sm2Puk: "04d827a7dbaaa358ce45b8c7794a7f54819f5c175005a702370e47f135ef6f5f9732758b1474f218419fe9e87f90c28c3b05f08254c651db27df35fae67b77b2e4" # 公钥,给到招行密钥 diff --git a/internal/biz/multi.go b/internal/biz/multi.go index 21d7611..9869e38 100644 --- a/internal/biz/multi.go +++ b/internal/biz/multi.go @@ -7,8 +7,6 @@ import ( "fmt" "github.com/go-kratos/kratos/v2/log" "gorm.io/gorm" - "sync" - err2 "voucher/api/err" v1 "voucher/api/v1" "voucher/internal/biz/bo" "voucher/internal/biz/cmb" @@ -29,9 +27,6 @@ type MultiBiz struct { MultiNotifyDataRepo repo.MultiNotifyDataRepo MultiNotifyLogRepo repo.MultiNotifyLogRepo CmbMixRepo mixrepos.CmbMixRepo - - mu sync.RWMutex - NonExistentBatchData map[string]bool } func NewMultiBiz( @@ -53,34 +48,11 @@ func NewMultiBiz( MultiNotifyDataRepo: multiNotifyDataRepo, MultiNotifyLogRepo: multiNotifyLogRepo, CmbMixRepo: cmbMixRepo, - - NonExistentBatchData: make(map[string]bool), } } -func (this *MultiBiz) Get(uid string) bool { - - if _, ok := this.NonExistentBatchData[uid]; ok { - return ok - } - - return false -} - -func (this *MultiBiz) Add(uid string) { - - this.mu.Lock() - defer this.mu.Unlock() - - this.NonExistentBatchData[uid] = true -} - func (biz *MultiBiz) Notify(ctx context.Context, ip, source string, req *bo.WechatVoucherNotifyBo) error { - if biz.Get(req.PlainText.StockID) { - return nil - } - cl := vo.MultiNotifyLockKey.BuildCache([]string{ source, req.PlainText.StockID, @@ -89,26 +61,6 @@ func (biz *MultiBiz) Notify(ctx context.Context, ip, source string, req *bo.Wech return lock.NewMutex(biz.rdb.Rdb, cl.TTL).Lock(ctx, cl.Key, func(ctx context.Context) error { - product, err := biz.ProductRepo.GetByBatchNo(ctx, req.PlainText.StockID) - if err != nil { - // 数据库不存在该活动批次,过滤掉 - if errors.Is(err, gorm.ErrRecordNotFound) { - biz.Add(req.PlainText.StockID) - return nil - } - if err2.IsDbNotFound(err) { - biz.Add(req.PlainText.StockID) - return nil - } - return err - } - - // 不是多笔立减金,过滤掉 - if product.ActivityId == "" { - biz.Add(req.PlainText.StockID) - return nil - } - if req.PlainText.ConsumeInformation.ConsumeAmount == 0 { return fmt.Errorf("消费金额不能为0") } @@ -118,6 +70,10 @@ func (biz *MultiBiz) Notify(ctx context.Context, ip, source string, req *bo.Wech return err } + if order.ActivityId != "" { + return fmt.Errorf("批次活动ID不为空,不是多笔立减金,请检查") + } + if err = biz.Run(ctx, ip, source, req, order); err != nil { return err } diff --git a/internal/biz/provider_set.go b/internal/biz/provider_set.go index 1b2e794..293b190 100644 --- a/internal/biz/provider_set.go +++ b/internal/biz/provider_set.go @@ -5,4 +5,4 @@ import ( ) // ProviderSetBiz is biz providers. -var ProviderSetBiz = wire.NewSet(NewVoucherBiz, NewMultiBiz) +var ProviderSetBiz = wire.NewSet(NewVoucherBiz, NewMultiBiz, NewWechatBiz) diff --git a/internal/biz/wechat.go b/internal/biz/wechat.go new file mode 100644 index 0000000..e9761df --- /dev/null +++ b/internal/biz/wechat.go @@ -0,0 +1,26 @@ +package biz + +import ( + "context" + "net/http" + "voucher/internal/biz/bo" + "voucher/internal/biz/wechatrepo" +) + +type WechatBiz struct { + BankMultiActivityRepo wechatrepo.BankMultiActivityRepo +} + +func NewWechatBiz(bankMultiActivityRepo wechatrepo.BankMultiActivityRepo) *WechatBiz { + return &WechatBiz{BankMultiActivityRepo: bankMultiActivityRepo} +} + +func (biz *WechatBiz) CallBack(ctx context.Context, mchId string, headers *http.Header, respBody []byte) (*bo.WechatVoucherNotifyBo, error) { + + response, err := biz.BankMultiActivityRepo.Notify(ctx, mchId, headers, respBody) + if err != nil { + return nil, err + } + + return response, nil +} diff --git a/internal/biz/wechat_notify.go b/internal/biz/wechat_notify.go index be88e76..2ddc5bb 100644 --- a/internal/biz/wechat_notify.go +++ b/internal/biz/wechat_notify.go @@ -11,7 +11,7 @@ import ( "voucher/internal/pkg/lock" ) -func (this *VoucherBiz) WechatNotifyConsumer(ctx context.Context, tag string, req *bo.WechatVoucherNotifyBo) error { +func (this *VoucherBiz) WechatNotifyConsumer(ctx context.Context, ip, tag string, req *bo.WechatVoucherNotifyBo) error { c := vo.WechatNotifyConsumeLockKey.BuildCache([]string{tag, req.PlainText.StockID, req.PlainText.CouponID}) @@ -23,7 +23,7 @@ func (this *VoucherBiz) WechatNotifyConsumer(ctx context.Context, tag string, re } if order.ActivityId != "" { - return this.MultiBiz.Run(ctx, "127.0.0.1", "lsxd_"+req.PlainText.StockCreatorMchid, req, order) + return this.MultiBiz.Run(ctx, ip, "lsxd_"+req.PlainText.StockCreatorMchid, req, order) } if req.PlainText.Status.IsSended() { diff --git a/internal/biz/wechatrepo/bank_multi_activity.go b/internal/biz/wechatrepo/bank_multi_activity.go index 640efbf..626102e 100644 --- a/internal/biz/wechatrepo/bank_multi_activity.go +++ b/internal/biz/wechatrepo/bank_multi_activity.go @@ -1,9 +1,12 @@ package wechatrepo import ( + "context" + "net/http" "voucher/internal/biz/bo" ) type BankMultiActivityRepo interface { Order(order *bo.OrderBo) (couponId string, err error) + Notify(ctx context.Context, mchId string, headers *http.Header, respBody []byte) (response *bo.WechatVoucherNotifyBo, err error) } diff --git a/internal/conf/conf.pb.go b/internal/conf/conf.pb.go index 7f53e1e..298901e 100644 --- a/internal/conf/conf.pb.go +++ b/internal/conf/conf.pb.go @@ -26,18 +26,19 @@ type Bootstrap struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Server *Server `protobuf:"bytes,1,opt,name=server,proto3" json:"server,omitempty"` - Logs *Logs `protobuf:"bytes,2,opt,name=logs,proto3" json:"logs,omitempty"` - Data *Data `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"` - RocketMQ *RocketMQ `protobuf:"bytes,4,opt,name=rocketMQ,proto3" json:"rocketMQ,omitempty"` - Wechat *Wechat `protobuf:"bytes,5,opt,name=wechat,proto3" json:"wechat,omitempty"` - Cmb *Cmb `protobuf:"bytes,6,opt,name=cmb,proto3" json:"cmb,omitempty"` - WechatNotifyMQ *WechatNotifyMQ `protobuf:"bytes,7,opt,name=wechatNotifyMQ,proto3" json:"wechatNotifyMQ,omitempty"` - Alarm *Alarm `protobuf:"bytes,8,opt,name=alarm,proto3" json:"alarm,omitempty"` - Cron *Cron `protobuf:"bytes,9,opt,name=cron,proto3" json:"cron,omitempty"` - RdsMQ *RdsMQ `protobuf:"bytes,10,opt,name=rdsMQ,proto3" json:"rdsMQ,omitempty"` - AliYunSms *AliYunSms `protobuf:"bytes,11,opt,name=aliYunSms,proto3" json:"aliYunSms,omitempty"` - Tripartite *Tripartite `protobuf:"bytes,12,opt,name=tripartite,proto3" json:"tripartite,omitempty"` + Server *Server `protobuf:"bytes,1,opt,name=server,proto3" json:"server,omitempty"` + Logs *Logs `protobuf:"bytes,2,opt,name=logs,proto3" json:"logs,omitempty"` + Data *Data `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"` + RocketMQ *RocketMQ `protobuf:"bytes,4,opt,name=rocketMQ,proto3" json:"rocketMQ,omitempty"` + Wechat *Wechat `protobuf:"bytes,5,opt,name=wechat,proto3" json:"wechat,omitempty"` + Cmb *Cmb `protobuf:"bytes,6,opt,name=cmb,proto3" json:"cmb,omitempty"` + WechatNotifyMQ *WechatNotifyMQ `protobuf:"bytes,7,opt,name=wechatNotifyMQ,proto3" json:"wechatNotifyMQ,omitempty"` + Alarm *Alarm `protobuf:"bytes,8,opt,name=alarm,proto3" json:"alarm,omitempty"` + Cron *Cron `protobuf:"bytes,9,opt,name=cron,proto3" json:"cron,omitempty"` + RdsMQ *RdsMQ `protobuf:"bytes,10,opt,name=rdsMQ,proto3" json:"rdsMQ,omitempty"` + AliYunSms *AliYunSms `protobuf:"bytes,11,opt,name=aliYunSms,proto3" json:"aliYunSms,omitempty"` + Tripartite *Tripartite `protobuf:"bytes,12,opt,name=tripartite,proto3" json:"tripartite,omitempty"` + WechatSubject []*WechatSubject `protobuf:"bytes,13,rep,name=wechatSubject,proto3" json:"wechatSubject,omitempty"` } func (x *Bootstrap) Reset() { @@ -156,6 +157,13 @@ func (x *Bootstrap) GetTripartite() *Tripartite { return nil } +func (x *Bootstrap) GetWechatSubject() []*WechatSubject { + if x != nil { + return x.WechatSubject + } + return nil +} + type Server struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1143,6 +1151,85 @@ func (x *Logs) GetAccess() string { return "" } +type WechatSubject struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + MchID string `protobuf:"bytes,1,opt,name=mchID,proto3" json:"mchID,omitempty"` + Name string `protobuf:"bytes,4,opt,name=name,proto3" json:"name,omitempty"` + MchCertificateSerialNumber string `protobuf:"bytes,2,opt,name=mchCertificateSerialNumber,proto3" json:"mchCertificateSerialNumber,omitempty"` + WechatPayPublicKeyID string `protobuf:"bytes,3,opt,name=wechatPayPublicKeyID,proto3" json:"wechatPayPublicKeyID,omitempty"` + MchApiV3Key string `protobuf:"bytes,6,opt,name=mchApiV3Key,proto3" json:"mchApiV3Key,omitempty"` +} + +func (x *WechatSubject) Reset() { + *x = WechatSubject{} + if protoimpl.UnsafeEnabled { + mi := &file_conf_conf_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *WechatSubject) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WechatSubject) ProtoMessage() {} + +func (x *WechatSubject) ProtoReflect() protoreflect.Message { + mi := &file_conf_conf_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WechatSubject.ProtoReflect.Descriptor instead. +func (*WechatSubject) Descriptor() ([]byte, []int) { + return file_conf_conf_proto_rawDescGZIP(), []int{14} +} + +func (x *WechatSubject) GetMchID() string { + if x != nil { + return x.MchID + } + return "" +} + +func (x *WechatSubject) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *WechatSubject) GetMchCertificateSerialNumber() string { + if x != nil { + return x.MchCertificateSerialNumber + } + return "" +} + +func (x *WechatSubject) GetWechatPayPublicKeyID() string { + if x != nil { + return x.WechatPayPublicKeyID + } + return "" +} + +func (x *WechatSubject) GetMchApiV3Key() string { + if x != nil { + return x.MchApiV3Key + } + return "" +} + type Server_HTTP struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1158,7 +1245,7 @@ type Server_HTTP struct { func (x *Server_HTTP) Reset() { *x = Server_HTTP{} if protoimpl.UnsafeEnabled { - mi := &file_conf_conf_proto_msgTypes[14] + mi := &file_conf_conf_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1171,7 +1258,7 @@ func (x *Server_HTTP) String() string { func (*Server_HTTP) ProtoMessage() {} func (x *Server_HTTP) ProtoReflect() protoreflect.Message { - mi := &file_conf_conf_proto_msgTypes[14] + mi := &file_conf_conf_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1238,7 +1325,7 @@ type Data_Database struct { func (x *Data_Database) Reset() { *x = Data_Database{} if protoimpl.UnsafeEnabled { - mi := &file_conf_conf_proto_msgTypes[15] + mi := &file_conf_conf_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1251,7 +1338,7 @@ func (x *Data_Database) String() string { func (*Data_Database) ProtoMessage() {} func (x *Data_Database) ProtoReflect() protoreflect.Message { - mi := &file_conf_conf_proto_msgTypes[15] + mi := &file_conf_conf_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1328,7 +1415,7 @@ type Data_Redis struct { func (x *Data_Redis) Reset() { *x = Data_Redis{} if protoimpl.UnsafeEnabled { - mi := &file_conf_conf_proto_msgTypes[16] + mi := &file_conf_conf_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1341,7 +1428,7 @@ func (x *Data_Redis) String() string { func (*Data_Redis) ProtoMessage() {} func (x *Data_Redis) ProtoReflect() protoreflect.Message { - mi := &file_conf_conf_proto_msgTypes[16] + mi := &file_conf_conf_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1432,7 +1519,7 @@ type Cron_CommandMap struct { func (x *Cron_CommandMap) Reset() { *x = Cron_CommandMap{} if protoimpl.UnsafeEnabled { - mi := &file_conf_conf_proto_msgTypes[18] + mi := &file_conf_conf_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1445,7 +1532,7 @@ func (x *Cron_CommandMap) String() string { func (*Cron_CommandMap) ProtoMessage() {} func (x *Cron_CommandMap) ProtoReflect() protoreflect.Message { - mi := &file_conf_conf_proto_msgTypes[18] + mi := &file_conf_conf_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1490,7 +1577,7 @@ type RdsMQ_Queue struct { func (x *RdsMQ_Queue) Reset() { *x = RdsMQ_Queue{} if protoimpl.UnsafeEnabled { - mi := &file_conf_conf_proto_msgTypes[20] + mi := &file_conf_conf_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1503,7 +1590,7 @@ func (x *RdsMQ_Queue) String() string { func (*RdsMQ_Queue) ProtoMessage() {} func (x *RdsMQ_Queue) ProtoReflect() protoreflect.Message { - mi := &file_conf_conf_proto_msgTypes[20] + mi := &file_conf_conf_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1565,7 +1652,7 @@ type Tripartite_QiXing struct { func (x *Tripartite_QiXing) Reset() { *x = Tripartite_QiXing{} if protoimpl.UnsafeEnabled { - mi := &file_conf_conf_proto_msgTypes[21] + mi := &file_conf_conf_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1578,7 +1665,7 @@ func (x *Tripartite_QiXing) String() string { func (*Tripartite_QiXing) ProtoMessage() {} func (x *Tripartite_QiXing) ProtoReflect() protoreflect.Message { - mi := &file_conf_conf_proto_msgTypes[21] + mi := &file_conf_conf_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1608,7 +1695,7 @@ var file_conf_conf_proto_rawDesc = []byte{ 0x6f, 0x12, 0x0e, 0x76, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x22, 0xdd, 0x04, 0x0a, 0x09, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x12, + 0x6f, 0x22, 0xa2, 0x05, 0x0a, 0x09, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x12, 0x2e, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x76, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, @@ -1646,233 +1733,250 @@ var file_conf_conf_proto_rawDesc = []byte{ 0x69, 0x74, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x76, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x54, 0x72, 0x69, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x65, 0x52, 0x0a, 0x74, 0x72, 0x69, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, - 0x65, 0x22, 0xff, 0x01, 0x0a, 0x06, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x2f, 0x0a, 0x04, - 0x68, 0x74, 0x74, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x76, 0x6f, 0x75, - 0x63, 0x68, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x53, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x04, 0x68, 0x74, 0x74, 0x70, 0x1a, 0xc3, 0x01, - 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, - 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, - 0x12, 0x12, 0x0a, 0x04, 0x61, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x61, 0x64, 0x64, 0x72, 0x12, 0x33, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x69, 0x73, 0x4f, - 0x70, 0x65, 0x6e, 0x53, 0x77, 0x61, 0x67, 0x67, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0d, 0x69, 0x73, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x77, 0x61, 0x67, 0x67, 0x65, 0x72, 0x12, - 0x32, 0x0a, 0x14, 0x69, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x65, 0x71, - 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x69, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x65, 0x71, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x73, 0x22, 0x94, 0x05, 0x0a, 0x04, 0x44, 0x61, 0x74, 0x61, 0x12, 0x2d, 0x0a, 0x02, - 0x64, 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x76, 0x6f, 0x75, 0x63, 0x68, - 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x44, - 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x52, 0x02, 0x64, 0x62, 0x12, 0x30, 0x0a, 0x05, 0x72, - 0x65, 0x64, 0x69, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x76, 0x6f, 0x75, - 0x63, 0x68, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x44, 0x61, 0x74, 0x61, - 0x2e, 0x52, 0x65, 0x64, 0x69, 0x73, 0x52, 0x05, 0x72, 0x65, 0x64, 0x69, 0x73, 0x1a, 0xc5, 0x01, - 0x0a, 0x08, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x72, - 0x69, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x72, 0x69, 0x76, - 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x61, - 0x78, 0x49, 0x64, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x6d, 0x61, 0x78, - 0x49, 0x64, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x61, 0x78, 0x4f, 0x70, 0x65, 0x6e, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x6d, 0x61, 0x78, 0x4f, 0x70, 0x65, 0x6e, 0x12, 0x3b, - 0x0a, 0x0b, 0x6d, 0x61, 0x78, 0x4c, 0x69, 0x66, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, - 0x6d, 0x61, 0x78, 0x4c, 0x69, 0x66, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x69, - 0x73, 0x44, 0x65, 0x62, 0x75, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x73, - 0x44, 0x65, 0x62, 0x75, 0x67, 0x1a, 0xe2, 0x02, 0x0a, 0x05, 0x52, 0x65, 0x64, 0x69, 0x73, 0x12, - 0x18, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x64, 0x64, - 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x64, 0x64, 0x72, 0x12, 0x3b, 0x0a, - 0x0b, 0x72, 0x65, 0x61, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x72, - 0x65, 0x61, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x3d, 0x0a, 0x0c, 0x77, 0x72, - 0x69, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x77, 0x72, 0x69, - 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, - 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, - 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6f, 0x6f, 0x6c, 0x53, 0x69, 0x7a, - 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x6f, 0x6f, 0x6c, 0x53, 0x69, 0x7a, - 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x6d, 0x69, 0x6e, 0x49, 0x64, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x6e, - 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x6d, 0x69, 0x6e, 0x49, 0x64, 0x6c, 0x65, - 0x43, 0x6f, 0x6e, 0x6e, 0x73, 0x12, 0x43, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x6e, 0x4d, 0x61, 0x78, - 0x49, 0x64, 0x6c, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x6e, 0x4d, - 0x61, 0x78, 0x49, 0x64, 0x6c, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x64, 0x62, - 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x64, 0x62, 0x22, 0x97, 0x02, 0x0a, 0x08, 0x52, - 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x4d, 0x51, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x64, 0x64, 0x72, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x64, 0x64, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x61, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b, 0x65, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x63, - 0x72, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, - 0x63, 0x72, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x20, 0x0a, 0x0b, 0x73, 0x65, 0x63, 0x72, 0x65, - 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x65, - 0x63, 0x72, 0x65, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x42, 0x0a, 0x08, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x4d, 0x61, 0x70, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x76, 0x6f, - 0x75, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x6f, 0x63, - 0x6b, 0x65, 0x74, 0x4d, 0x51, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x61, 0x70, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x52, 0x08, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x61, 0x70, 0x1a, 0x55, 0x0a, - 0x0d, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, - 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, - 0x12, 0x2e, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x18, 0x2e, 0x76, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x61, 0x70, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x3a, 0x02, 0x38, 0x01, 0x22, 0x88, 0x01, 0x0a, 0x08, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x61, - 0x70, 0x12, 0x14, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x28, 0x0a, - 0x0f, 0x70, 0x65, 0x72, 0x43, 0x6f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x65, 0x43, 0x6e, 0x74, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x70, 0x65, 0x72, 0x43, 0x6f, 0x72, 0x6f, 0x75, - 0x74, 0x69, 0x6e, 0x65, 0x43, 0x6e, 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x69, 0x73, 0x4f, 0x70, 0x65, - 0x6e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x0e, 0x69, 0x73, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x22, - 0xa6, 0x01, 0x0a, 0x06, 0x57, 0x65, 0x63, 0x68, 0x61, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x63, - 0x68, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x63, 0x68, 0x49, 0x44, - 0x12, 0x3e, 0x0a, 0x1a, 0x6d, 0x63, 0x68, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, - 0x74, 0x65, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x1a, 0x6d, 0x63, 0x68, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, - 0x12, 0x32, 0x0a, 0x14, 0x77, 0x65, 0x63, 0x68, 0x61, 0x74, 0x50, 0x61, 0x79, 0x50, 0x75, 0x62, - 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x49, 0x44, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, - 0x77, 0x65, 0x63, 0x68, 0x61, 0x74, 0x50, 0x61, 0x79, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, - 0x65, 0x79, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0xff, 0x02, 0x0a, 0x03, 0x43, 0x6d, 0x62, - 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6d, - 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x61, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6d, 0x32, 0x50, 0x72, 0x6b, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6d, 0x32, 0x50, 0x72, 0x6b, 0x12, 0x16, 0x0a, 0x06, - 0x73, 0x6d, 0x32, 0x50, 0x75, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6d, - 0x32, 0x50, 0x75, 0x6b, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6d, 0x62, 0x53, 0x6d, 0x32, 0x50, 0x69, - 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6d, 0x62, 0x53, 0x6d, 0x32, 0x50, - 0x69, 0x6b, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6d, 0x62, 0x53, 0x6d, 0x32, 0x50, 0x75, 0x6b, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6d, 0x62, 0x53, 0x6d, 0x32, 0x50, 0x75, 0x6b, - 0x12, 0x1a, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x20, 0x0a, 0x0b, - 0x63, 0x6d, 0x62, 0x4b, 0x65, 0x79, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0b, 0x63, 0x6d, 0x62, 0x4b, 0x65, 0x79, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x14, - 0x0a, 0x05, 0x6f, 0x72, 0x67, 0x4e, 0x6f, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6f, - 0x72, 0x67, 0x4e, 0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x55, 0x72, - 0x6c, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x55, - 0x72, 0x6c, 0x12, 0x26, 0x0a, 0x0e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x4e, 0x6f, 0x74, 0x69, 0x66, - 0x79, 0x55, 0x72, 0x6c, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6d, 0x75, 0x6c, 0x74, - 0x69, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x55, 0x72, 0x6c, 0x12, 0x28, 0x0a, 0x0f, 0x6e, 0x6f, - 0x74, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x44, 0x61, 0x79, 0x73, 0x18, 0x0b, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0f, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, - 0x44, 0x61, 0x79, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x45, 0x6e, - 0x64, 0x44, 0x61, 0x79, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x6e, 0x6f, 0x74, - 0x69, 0x63, 0x65, 0x45, 0x6e, 0x64, 0x44, 0x61, 0x79, 0x73, 0x22, 0xc6, 0x02, 0x0a, 0x0e, 0x57, - 0x65, 0x63, 0x68, 0x61, 0x74, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x4d, 0x51, 0x12, 0x20, 0x0a, - 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b, 0x65, 0x79, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b, 0x65, 0x79, 0x49, 0x64, 0x12, - 0x28, 0x0a, 0x0f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b, 0x65, 0x79, 0x53, 0x65, 0x63, 0x72, - 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x4b, 0x65, 0x79, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x6e, 0x64, - 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x6e, 0x64, - 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, - 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, - 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, - 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x67, 0x72, 0x6f, - 0x75, 0x70, 0x49, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, 0x72, 0x6f, 0x75, - 0x70, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x54, - 0x61, 0x67, 0x55, 0x72, 0x6c, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x67, - 0x69, 0x73, 0x74, 0x65, 0x72, 0x54, 0x61, 0x67, 0x55, 0x72, 0x6c, 0x12, 0x26, 0x0a, 0x0e, 0x69, - 0x73, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x18, 0x0b, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x0e, 0x69, 0x73, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x6f, 0x6e, 0x73, 0x75, - 0x6d, 0x65, 0x72, 0x22, 0x9b, 0x01, 0x0a, 0x05, 0x41, 0x6c, 0x61, 0x72, 0x6d, 0x12, 0x1e, 0x0a, - 0x0a, 0x77, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x55, 0x52, 0x4c, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0a, 0x77, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x55, 0x52, 0x4c, 0x12, 0x16, 0x0a, - 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, - 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x74, 0x41, 0x6c, 0x6c, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x61, 0x74, 0x41, 0x6c, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x61, - 0x74, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, - 0x61, 0x74, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x77, 0x61, 0x72, - 0x6e, 0x69, 0x6e, 0x67, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x0e, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, - 0x73, 0x22, 0x84, 0x02, 0x0a, 0x04, 0x43, 0x72, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x73, - 0x4f, 0x70, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x69, 0x73, 0x4f, 0x70, - 0x65, 0x6e, 0x12, 0x44, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x61, 0x70, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x76, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, - 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x2e, 0x43, 0x6f, 0x6d, - 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x63, 0x6f, - 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x61, 0x70, 0x1a, 0x3e, 0x0a, 0x0a, 0x43, 0x6f, 0x6d, 0x6d, - 0x61, 0x6e, 0x64, 0x4d, 0x61, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x73, 0x4f, 0x70, 0x65, 0x6e, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x69, 0x73, 0x4f, 0x70, 0x65, 0x6e, 0x12, 0x18, - 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x1a, 0x5e, 0x0a, 0x0f, 0x43, 0x6f, 0x6d, 0x6d, - 0x61, 0x6e, 0x64, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, - 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x35, 0x0a, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x76, - 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x43, 0x72, - 0x6f, 0x6e, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x61, 0x70, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xc4, 0x04, 0x0a, 0x05, 0x52, 0x64, 0x73, - 0x4d, 0x51, 0x12, 0x3d, 0x0a, 0x0b, 0x77, 0x65, 0x63, 0x68, 0x61, 0x74, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x76, 0x6f, 0x75, 0x63, 0x68, 0x65, - 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x64, 0x73, 0x4d, 0x51, 0x2e, 0x51, - 0x75, 0x65, 0x75, 0x65, 0x52, 0x0b, 0x77, 0x65, 0x63, 0x68, 0x61, 0x74, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x12, 0x4f, 0x0a, 0x14, 0x77, 0x65, 0x63, 0x68, 0x61, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x53, - 0x6c, 0x69, 0x63, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x65, 0x12, 0x43, 0x0a, 0x0d, 0x77, 0x65, 0x63, 0x68, 0x61, 0x74, 0x53, 0x75, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x76, 0x6f, 0x75, 0x63, 0x68, + 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x57, 0x65, 0x63, 0x68, 0x61, 0x74, + 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x0d, 0x77, 0x65, 0x63, 0x68, 0x61, 0x74, 0x53, + 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x22, 0xff, 0x01, 0x0a, 0x06, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x12, 0x2f, 0x0a, 0x04, 0x68, 0x74, 0x74, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x76, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x2e, 0x52, 0x64, 0x73, 0x4d, 0x51, 0x2e, 0x51, 0x75, 0x65, 0x75, 0x65, 0x52, 0x14, 0x77, 0x65, - 0x63, 0x68, 0x61, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x51, 0x75, 0x65, - 0x72, 0x79, 0x12, 0x3d, 0x0a, 0x0b, 0x77, 0x65, 0x63, 0x68, 0x61, 0x74, 0x52, 0x65, 0x74, 0x72, - 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x76, 0x6f, 0x75, 0x63, 0x68, 0x65, - 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x64, 0x73, 0x4d, 0x51, 0x2e, 0x51, - 0x75, 0x65, 0x75, 0x65, 0x52, 0x0b, 0x77, 0x65, 0x63, 0x68, 0x61, 0x74, 0x52, 0x65, 0x74, 0x72, - 0x79, 0x12, 0x3d, 0x0a, 0x0b, 0x72, 0x65, 0x74, 0x72, 0x79, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x76, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, - 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x64, 0x73, 0x4d, 0x51, 0x2e, 0x51, 0x75, - 0x65, 0x75, 0x65, 0x52, 0x0b, 0x72, 0x65, 0x74, 0x72, 0x79, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, - 0x12, 0x47, 0x0a, 0x10, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x52, - 0x65, 0x74, 0x72, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x76, 0x6f, 0x75, - 0x63, 0x68, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x64, 0x73, 0x4d, - 0x51, 0x2e, 0x51, 0x75, 0x65, 0x75, 0x65, 0x52, 0x10, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x4e, 0x6f, - 0x74, 0x69, 0x66, 0x79, 0x52, 0x65, 0x74, 0x72, 0x79, 0x12, 0x3b, 0x0a, 0x0a, 0x75, 0x73, 0x65, - 0x64, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, - 0x76, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, - 0x64, 0x73, 0x4d, 0x51, 0x2e, 0x51, 0x75, 0x65, 0x75, 0x65, 0x52, 0x0a, 0x75, 0x73, 0x65, 0x64, - 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x1a, 0xa6, 0x01, 0x0a, 0x05, 0x51, 0x75, 0x65, 0x75, 0x65, - 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x73, 0x4f, 0x70, 0x65, 0x6e, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x69, 0x73, 0x4f, 0x70, 0x65, 0x6e, 0x12, 0x1a, 0x0a, 0x08, - 0x72, 0x65, 0x74, 0x72, 0x79, 0x4e, 0x75, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, - 0x72, 0x65, 0x74, 0x72, 0x79, 0x4e, 0x75, 0x6d, 0x12, 0x1e, 0x0a, 0x0a, 0x6e, 0x75, 0x6d, 0x57, - 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x6e, 0x75, - 0x6d, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x12, 0x35, 0x0a, 0x08, 0x77, 0x61, 0x69, 0x74, - 0x54, 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, + 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x04, 0x68, 0x74, + 0x74, 0x70, 0x1a, 0xc3, 0x01, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x12, 0x18, 0x0a, 0x07, 0x6e, + 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, + 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x64, 0x64, 0x72, 0x12, 0x33, 0x0a, 0x07, 0x74, 0x69, 0x6d, + 0x65, 0x6f, 0x75, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x77, 0x61, 0x69, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x22, - 0xb9, 0x01, 0x0a, 0x09, 0x41, 0x6c, 0x69, 0x59, 0x75, 0x6e, 0x53, 0x6d, 0x73, 0x12, 0x20, 0x0a, - 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b, 0x65, 0x79, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b, 0x65, 0x79, 0x49, 0x64, 0x12, - 0x28, 0x0a, 0x0f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b, 0x65, 0x79, 0x53, 0x65, 0x63, 0x72, - 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x4b, 0x65, 0x79, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x6e, 0x64, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x6e, 0x64, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x69, 0x67, 0x6e, 0x4e, 0x61, 0x6d, - 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x69, 0x67, 0x6e, 0x4e, 0x61, 0x6d, - 0x65, 0x12, 0x28, 0x0a, 0x0f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x57, 0x61, 0x72, - 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x74, 0x65, 0x6d, 0x70, - 0x6c, 0x61, 0x74, 0x65, 0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x22, 0x69, 0x0a, 0x0a, 0x54, - 0x72, 0x69, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x71, 0x69, 0x58, - 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x76, 0x6f, 0x75, 0x63, - 0x68, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x54, 0x72, 0x69, 0x70, 0x61, - 0x72, 0x74, 0x69, 0x74, 0x65, 0x2e, 0x51, 0x69, 0x58, 0x69, 0x6e, 0x67, 0x52, 0x06, 0x71, 0x69, - 0x58, 0x69, 0x6e, 0x67, 0x1a, 0x20, 0x0a, 0x06, 0x51, 0x69, 0x58, 0x69, 0x6e, 0x67, 0x12, 0x16, - 0x0a, 0x06, 0x61, 0x70, 0x70, 0x4b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x61, 0x70, 0x70, 0x4b, 0x65, 0x79, 0x22, 0x3a, 0x0a, 0x04, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x1a, - 0x0a, 0x08, 0x62, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x62, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x42, 0x17, 0x5a, 0x15, 0x76, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, 0x2f, 0x63, 0x70, - 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x3b, 0x63, 0x6f, 0x6e, 0x66, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x24, + 0x0a, 0x0d, 0x69, 0x73, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x77, 0x61, 0x67, 0x67, 0x65, 0x72, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x69, 0x73, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x77, 0x61, + 0x67, 0x67, 0x65, 0x72, 0x12, 0x32, 0x0a, 0x14, 0x69, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x52, 0x65, 0x71, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x14, 0x69, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x65, + 0x71, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x22, 0x94, 0x05, 0x0a, 0x04, 0x44, 0x61, 0x74, + 0x61, 0x12, 0x2d, 0x0a, 0x02, 0x64, 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, + 0x76, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x44, + 0x61, 0x74, 0x61, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x52, 0x02, 0x64, 0x62, + 0x12, 0x30, 0x0a, 0x05, 0x72, 0x65, 0x64, 0x69, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x76, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x2e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x52, 0x65, 0x64, 0x69, 0x73, 0x52, 0x05, 0x72, 0x65, 0x64, + 0x69, 0x73, 0x1a, 0xc5, 0x01, 0x0a, 0x08, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x12, + 0x16, 0x0a, 0x06, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, + 0x18, 0x0a, 0x07, 0x6d, 0x61, 0x78, 0x49, 0x64, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x07, 0x6d, 0x61, 0x78, 0x49, 0x64, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x61, 0x78, + 0x4f, 0x70, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x6d, 0x61, 0x78, 0x4f, + 0x70, 0x65, 0x6e, 0x12, 0x3b, 0x0a, 0x0b, 0x6d, 0x61, 0x78, 0x4c, 0x69, 0x66, 0x65, 0x74, 0x69, + 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x4c, 0x69, 0x66, 0x65, 0x74, 0x69, 0x6d, 0x65, + 0x12, 0x18, 0x0a, 0x07, 0x69, 0x73, 0x44, 0x65, 0x62, 0x75, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x07, 0x69, 0x73, 0x44, 0x65, 0x62, 0x75, 0x67, 0x1a, 0xe2, 0x02, 0x0a, 0x05, 0x52, + 0x65, 0x64, 0x69, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x12, + 0x0a, 0x04, 0x61, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x64, + 0x64, 0x72, 0x12, 0x3b, 0x0a, 0x0b, 0x72, 0x65, 0x61, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, + 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x0b, 0x72, 0x65, 0x61, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, + 0x3d, 0x0a, 0x0c, 0x77, 0x72, 0x69, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x0c, 0x77, 0x72, 0x69, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x1a, + 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6f, + 0x6f, 0x6c, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x6f, + 0x6f, 0x6c, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x6d, 0x69, 0x6e, 0x49, 0x64, 0x6c, + 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x6d, 0x69, + 0x6e, 0x49, 0x64, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x73, 0x12, 0x43, 0x0a, 0x0f, 0x63, 0x6f, + 0x6e, 0x6e, 0x4d, 0x61, 0x78, 0x49, 0x64, 0x6c, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0f, + 0x63, 0x6f, 0x6e, 0x6e, 0x4d, 0x61, 0x78, 0x49, 0x64, 0x6c, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, + 0x0e, 0x0a, 0x02, 0x64, 0x62, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x64, 0x62, 0x22, + 0x97, 0x02, 0x0a, 0x08, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x4d, 0x51, 0x12, 0x12, 0x0a, 0x04, + 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x64, 0x64, 0x72, + 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b, 0x65, 0x79, 0x12, 0x1c, + 0x0a, 0x09, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x20, 0x0a, 0x0b, + 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0b, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x42, + 0x0a, 0x08, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x61, 0x70, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x26, 0x2e, 0x76, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x2e, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x4d, 0x51, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4d, + 0x61, 0x70, 0x1a, 0x55, 0x0a, 0x0d, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x61, 0x70, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2e, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x76, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x61, 0x70, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x88, 0x01, 0x0a, 0x08, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x4d, 0x61, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x14, 0x0a, 0x05, + 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x70, + 0x69, 0x63, 0x12, 0x28, 0x0a, 0x0f, 0x70, 0x65, 0x72, 0x43, 0x6f, 0x72, 0x6f, 0x75, 0x74, 0x69, + 0x6e, 0x65, 0x43, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x70, 0x65, 0x72, + 0x43, 0x6f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x65, 0x43, 0x6e, 0x74, 0x12, 0x26, 0x0a, 0x0e, + 0x69, 0x73, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x69, 0x73, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x6f, 0x6e, 0x73, + 0x75, 0x6d, 0x65, 0x72, 0x22, 0xa6, 0x01, 0x0a, 0x06, 0x57, 0x65, 0x63, 0x68, 0x61, 0x74, 0x12, + 0x14, 0x0a, 0x05, 0x6d, 0x63, 0x68, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x6d, 0x63, 0x68, 0x49, 0x44, 0x12, 0x3e, 0x0a, 0x1a, 0x6d, 0x63, 0x68, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, + 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1a, 0x6d, 0x63, 0x68, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, + 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x32, 0x0a, 0x14, 0x77, 0x65, 0x63, 0x68, 0x61, 0x74, 0x50, + 0x61, 0x79, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x49, 0x44, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x14, 0x77, 0x65, 0x63, 0x68, 0x61, 0x74, 0x50, 0x61, 0x79, 0x50, 0x75, + 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0xff, 0x02, + 0x0a, 0x03, 0x43, 0x6d, 0x62, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x6d, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x61, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6d, 0x32, + 0x50, 0x72, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6d, 0x32, 0x50, 0x72, + 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6d, 0x32, 0x50, 0x75, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x73, 0x6d, 0x32, 0x50, 0x75, 0x6b, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6d, 0x62, + 0x53, 0x6d, 0x32, 0x50, 0x69, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6d, + 0x62, 0x53, 0x6d, 0x32, 0x50, 0x69, 0x6b, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6d, 0x62, 0x53, 0x6d, + 0x32, 0x50, 0x75, 0x6b, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6d, 0x62, 0x53, + 0x6d, 0x32, 0x50, 0x75, 0x6b, 0x12, 0x1a, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x41, 0x6c, 0x69, 0x61, + 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x41, 0x6c, 0x69, 0x61, + 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6d, 0x62, 0x4b, 0x65, 0x79, 0x41, 0x6c, 0x69, 0x61, 0x73, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6d, 0x62, 0x4b, 0x65, 0x79, 0x41, 0x6c, + 0x69, 0x61, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x72, 0x67, 0x4e, 0x6f, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x6f, 0x72, 0x67, 0x4e, 0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x6f, 0x74, + 0x69, 0x66, 0x79, 0x55, 0x72, 0x6c, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x6f, + 0x74, 0x69, 0x66, 0x79, 0x55, 0x72, 0x6c, 0x12, 0x26, 0x0a, 0x0e, 0x6d, 0x75, 0x6c, 0x74, 0x69, + 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x55, 0x72, 0x6c, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x55, 0x72, 0x6c, 0x12, + 0x28, 0x0a, 0x0f, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x44, 0x61, + 0x79, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, + 0x53, 0x74, 0x61, 0x72, 0x74, 0x44, 0x61, 0x79, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x6e, 0x6f, 0x74, + 0x69, 0x63, 0x65, 0x45, 0x6e, 0x64, 0x44, 0x61, 0x79, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0d, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x45, 0x6e, 0x64, 0x44, 0x61, 0x79, 0x73, 0x22, + 0xc6, 0x02, 0x0a, 0x0e, 0x57, 0x65, 0x63, 0x68, 0x61, 0x74, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, + 0x4d, 0x51, 0x12, 0x20, 0x0a, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b, 0x65, 0x79, 0x49, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b, + 0x65, 0x79, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x0f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b, 0x65, + 0x79, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x61, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b, 0x65, 0x79, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x1a, + 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, + 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, + 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, + 0x63, 0x65, 0x49, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, + 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x10, 0x0a, 0x03, + 0x74, 0x61, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x18, + 0x0a, 0x07, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0e, 0x72, 0x65, 0x67, 0x69, + 0x73, 0x74, 0x65, 0x72, 0x54, 0x61, 0x67, 0x55, 0x72, 0x6c, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x54, 0x61, 0x67, 0x55, 0x72, 0x6c, + 0x12, 0x26, 0x0a, 0x0e, 0x69, 0x73, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, + 0x65, 0x72, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x69, 0x73, 0x4f, 0x70, 0x65, 0x6e, + 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x22, 0x9b, 0x01, 0x0a, 0x05, 0x41, 0x6c, 0x61, + 0x72, 0x6d, 0x12, 0x1e, 0x0a, 0x0a, 0x77, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x55, 0x52, 0x4c, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x55, + 0x52, 0x4c, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x74, + 0x41, 0x6c, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x61, 0x74, 0x41, 0x6c, 0x6c, + 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x74, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x74, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x26, + 0x0a, 0x0e, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x73, + 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x4d, + 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x73, 0x22, 0x84, 0x02, 0x0a, 0x04, 0x43, 0x72, 0x6f, 0x6e, 0x12, + 0x16, 0x0a, 0x06, 0x69, 0x73, 0x4f, 0x70, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x06, 0x69, 0x73, 0x4f, 0x70, 0x65, 0x6e, 0x12, 0x44, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, + 0x6e, 0x64, 0x4d, 0x61, 0x70, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x76, 0x6f, + 0x75, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x43, 0x72, 0x6f, + 0x6e, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x61, 0x70, 0x1a, 0x3e, 0x0a, + 0x0a, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x61, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x69, + 0x73, 0x4f, 0x70, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x69, 0x73, 0x4f, + 0x70, 0x65, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x1a, 0x5e, 0x0a, + 0x0f, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x35, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1f, 0x2e, 0x76, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, + 0x61, 0x70, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xc4, 0x04, + 0x0a, 0x05, 0x52, 0x64, 0x73, 0x4d, 0x51, 0x12, 0x3d, 0x0a, 0x0b, 0x77, 0x65, 0x63, 0x68, 0x61, + 0x74, 0x51, 0x75, 0x65, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x76, + 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x64, + 0x73, 0x4d, 0x51, 0x2e, 0x51, 0x75, 0x65, 0x75, 0x65, 0x52, 0x0b, 0x77, 0x65, 0x63, 0x68, 0x61, + 0x74, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x4f, 0x0a, 0x14, 0x77, 0x65, 0x63, 0x68, 0x61, 0x74, + 0x54, 0x69, 0x6d, 0x65, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x76, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x64, 0x73, 0x4d, 0x51, 0x2e, 0x51, 0x75, 0x65, 0x75, + 0x65, 0x52, 0x14, 0x77, 0x65, 0x63, 0x68, 0x61, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x53, 0x6c, 0x69, + 0x63, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x3d, 0x0a, 0x0b, 0x77, 0x65, 0x63, 0x68, 0x61, + 0x74, 0x52, 0x65, 0x74, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x76, + 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x64, + 0x73, 0x4d, 0x51, 0x2e, 0x51, 0x75, 0x65, 0x75, 0x65, 0x52, 0x0b, 0x77, 0x65, 0x63, 0x68, 0x61, + 0x74, 0x52, 0x65, 0x74, 0x72, 0x79, 0x12, 0x3d, 0x0a, 0x0b, 0x72, 0x65, 0x74, 0x72, 0x79, 0x4e, + 0x6f, 0x74, 0x69, 0x66, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x76, 0x6f, + 0x75, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x64, 0x73, + 0x4d, 0x51, 0x2e, 0x51, 0x75, 0x65, 0x75, 0x65, 0x52, 0x0b, 0x72, 0x65, 0x74, 0x72, 0x79, 0x4e, + 0x6f, 0x74, 0x69, 0x66, 0x79, 0x12, 0x47, 0x0a, 0x10, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x4e, 0x6f, + 0x74, 0x69, 0x66, 0x79, 0x52, 0x65, 0x74, 0x72, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1b, 0x2e, 0x76, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x2e, 0x52, 0x64, 0x73, 0x4d, 0x51, 0x2e, 0x51, 0x75, 0x65, 0x75, 0x65, 0x52, 0x10, 0x6f, 0x72, + 0x64, 0x65, 0x72, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x52, 0x65, 0x74, 0x72, 0x79, 0x12, 0x3b, + 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x64, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x76, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x2e, 0x52, 0x64, 0x73, 0x4d, 0x51, 0x2e, 0x51, 0x75, 0x65, 0x75, 0x65, 0x52, + 0x0a, 0x75, 0x73, 0x65, 0x64, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x1a, 0xa6, 0x01, 0x0a, 0x05, + 0x51, 0x75, 0x65, 0x75, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x73, 0x4f, + 0x70, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x69, 0x73, 0x4f, 0x70, 0x65, + 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x74, 0x72, 0x79, 0x4e, 0x75, 0x6d, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x08, 0x72, 0x65, 0x74, 0x72, 0x79, 0x4e, 0x75, 0x6d, 0x12, 0x1e, 0x0a, + 0x0a, 0x6e, 0x75, 0x6d, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x0a, 0x6e, 0x75, 0x6d, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x12, 0x35, 0x0a, + 0x08, 0x77, 0x61, 0x69, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x77, 0x61, 0x69, 0x74, + 0x54, 0x69, 0x6d, 0x65, 0x22, 0xb9, 0x01, 0x0a, 0x09, 0x41, 0x6c, 0x69, 0x59, 0x75, 0x6e, 0x53, + 0x6d, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b, 0x65, 0x79, 0x49, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b, + 0x65, 0x79, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x0f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b, 0x65, + 0x79, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x61, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b, 0x65, 0x79, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x1a, + 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x69, + 0x67, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x69, + 0x67, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x0f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, + 0x74, 0x65, 0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, + 0x22, 0x69, 0x0a, 0x0a, 0x54, 0x72, 0x69, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x65, 0x12, 0x39, + 0x0a, 0x06, 0x71, 0x69, 0x58, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, + 0x2e, 0x76, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, + 0x54, 0x72, 0x69, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x65, 0x2e, 0x51, 0x69, 0x58, 0x69, 0x6e, + 0x67, 0x52, 0x06, 0x71, 0x69, 0x58, 0x69, 0x6e, 0x67, 0x1a, 0x20, 0x0a, 0x06, 0x51, 0x69, 0x58, + 0x69, 0x6e, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x70, 0x70, 0x4b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x70, 0x70, 0x4b, 0x65, 0x79, 0x22, 0x3a, 0x0a, 0x04, 0x4c, + 0x6f, 0x67, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x62, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x12, + 0x16, 0x0a, 0x06, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0xcf, 0x01, 0x0a, 0x0d, 0x57, 0x65, 0x63, 0x68, + 0x61, 0x74, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x63, 0x68, + 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x63, 0x68, 0x49, 0x44, 0x12, + 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x1a, 0x6d, 0x63, 0x68, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, + 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1a, 0x6d, 0x63, 0x68, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, + 0x62, 0x65, 0x72, 0x12, 0x32, 0x0a, 0x14, 0x77, 0x65, 0x63, 0x68, 0x61, 0x74, 0x50, 0x61, 0x79, + 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x49, 0x44, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x14, 0x77, 0x65, 0x63, 0x68, 0x61, 0x74, 0x50, 0x61, 0x79, 0x50, 0x75, 0x62, 0x6c, + 0x69, 0x63, 0x4b, 0x65, 0x79, 0x49, 0x44, 0x12, 0x20, 0x0a, 0x0b, 0x6d, 0x63, 0x68, 0x41, 0x70, + 0x69, 0x56, 0x33, 0x4b, 0x65, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6d, 0x63, + 0x68, 0x41, 0x70, 0x69, 0x56, 0x33, 0x4b, 0x65, 0x79, 0x42, 0x17, 0x5a, 0x15, 0x76, 0x6f, 0x75, + 0x63, 0x68, 0x65, 0x72, 0x2f, 0x63, 0x70, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x3b, 0x63, 0x6f, + 0x6e, 0x66, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1887,7 +1991,7 @@ func file_conf_conf_proto_rawDescGZIP() []byte { return file_conf_conf_proto_rawDescData } -var file_conf_conf_proto_msgTypes = make([]protoimpl.MessageInfo, 22) +var file_conf_conf_proto_msgTypes = make([]protoimpl.MessageInfo, 23) var file_conf_conf_proto_goTypes = []any{ (*Bootstrap)(nil), // 0: voucher.config.Bootstrap (*Server)(nil), // 1: voucher.config.Server @@ -1903,15 +2007,16 @@ var file_conf_conf_proto_goTypes = []any{ (*AliYunSms)(nil), // 11: voucher.config.AliYunSms (*Tripartite)(nil), // 12: voucher.config.Tripartite (*Logs)(nil), // 13: voucher.config.Logs - (*Server_HTTP)(nil), // 14: voucher.config.Server.HTTP - (*Data_Database)(nil), // 15: voucher.config.Data.Database - (*Data_Redis)(nil), // 16: voucher.config.Data.Redis - nil, // 17: voucher.config.RocketMQ.EventMapEntry - (*Cron_CommandMap)(nil), // 18: voucher.config.Cron.CommandMap - nil, // 19: voucher.config.Cron.CommandMapEntry - (*RdsMQ_Queue)(nil), // 20: voucher.config.RdsMQ.Queue - (*Tripartite_QiXing)(nil), // 21: voucher.config.Tripartite.QiXing - (*durationpb.Duration)(nil), // 22: google.protobuf.Duration + (*WechatSubject)(nil), // 14: voucher.config.WechatSubject + (*Server_HTTP)(nil), // 15: voucher.config.Server.HTTP + (*Data_Database)(nil), // 16: voucher.config.Data.Database + (*Data_Redis)(nil), // 17: voucher.config.Data.Redis + nil, // 18: voucher.config.RocketMQ.EventMapEntry + (*Cron_CommandMap)(nil), // 19: voucher.config.Cron.CommandMap + nil, // 20: voucher.config.Cron.CommandMapEntry + (*RdsMQ_Queue)(nil), // 21: voucher.config.RdsMQ.Queue + (*Tripartite_QiXing)(nil), // 22: voucher.config.Tripartite.QiXing + (*durationpb.Duration)(nil), // 23: google.protobuf.Duration } var file_conf_conf_proto_depIdxs = []int32{ 1, // 0: voucher.config.Bootstrap.server:type_name -> voucher.config.Server @@ -1926,31 +2031,32 @@ var file_conf_conf_proto_depIdxs = []int32{ 10, // 9: voucher.config.Bootstrap.rdsMQ:type_name -> voucher.config.RdsMQ 11, // 10: voucher.config.Bootstrap.aliYunSms:type_name -> voucher.config.AliYunSms 12, // 11: voucher.config.Bootstrap.tripartite:type_name -> voucher.config.Tripartite - 14, // 12: voucher.config.Server.http:type_name -> voucher.config.Server.HTTP - 15, // 13: voucher.config.Data.db:type_name -> voucher.config.Data.Database - 16, // 14: voucher.config.Data.redis:type_name -> voucher.config.Data.Redis - 17, // 15: voucher.config.RocketMQ.eventMap:type_name -> voucher.config.RocketMQ.EventMapEntry - 19, // 16: voucher.config.Cron.commandMap:type_name -> voucher.config.Cron.CommandMapEntry - 20, // 17: voucher.config.RdsMQ.wechatQuery:type_name -> voucher.config.RdsMQ.Queue - 20, // 18: voucher.config.RdsMQ.wechatTimeSliceQuery:type_name -> voucher.config.RdsMQ.Queue - 20, // 19: voucher.config.RdsMQ.wechatRetry:type_name -> voucher.config.RdsMQ.Queue - 20, // 20: voucher.config.RdsMQ.retryNotify:type_name -> voucher.config.RdsMQ.Queue - 20, // 21: voucher.config.RdsMQ.orderNotifyRetry:type_name -> voucher.config.RdsMQ.Queue - 20, // 22: voucher.config.RdsMQ.usedNotify:type_name -> voucher.config.RdsMQ.Queue - 21, // 23: voucher.config.Tripartite.qiXing:type_name -> voucher.config.Tripartite.QiXing - 22, // 24: voucher.config.Server.HTTP.timeout:type_name -> google.protobuf.Duration - 22, // 25: voucher.config.Data.Database.maxLifetime:type_name -> google.protobuf.Duration - 22, // 26: voucher.config.Data.Redis.readTimeout:type_name -> google.protobuf.Duration - 22, // 27: voucher.config.Data.Redis.writeTimeout:type_name -> google.protobuf.Duration - 22, // 28: voucher.config.Data.Redis.connMaxIdleTime:type_name -> google.protobuf.Duration - 4, // 29: voucher.config.RocketMQ.EventMapEntry.value:type_name -> voucher.config.EventMap - 18, // 30: voucher.config.Cron.CommandMapEntry.value:type_name -> voucher.config.Cron.CommandMap - 22, // 31: voucher.config.RdsMQ.Queue.waitTime:type_name -> google.protobuf.Duration - 32, // [32:32] is the sub-list for method output_type - 32, // [32:32] is the sub-list for method input_type - 32, // [32:32] is the sub-list for extension type_name - 32, // [32:32] is the sub-list for extension extendee - 0, // [0:32] is the sub-list for field type_name + 14, // 12: voucher.config.Bootstrap.wechatSubject:type_name -> voucher.config.WechatSubject + 15, // 13: voucher.config.Server.http:type_name -> voucher.config.Server.HTTP + 16, // 14: voucher.config.Data.db:type_name -> voucher.config.Data.Database + 17, // 15: voucher.config.Data.redis:type_name -> voucher.config.Data.Redis + 18, // 16: voucher.config.RocketMQ.eventMap:type_name -> voucher.config.RocketMQ.EventMapEntry + 20, // 17: voucher.config.Cron.commandMap:type_name -> voucher.config.Cron.CommandMapEntry + 21, // 18: voucher.config.RdsMQ.wechatQuery:type_name -> voucher.config.RdsMQ.Queue + 21, // 19: voucher.config.RdsMQ.wechatTimeSliceQuery:type_name -> voucher.config.RdsMQ.Queue + 21, // 20: voucher.config.RdsMQ.wechatRetry:type_name -> voucher.config.RdsMQ.Queue + 21, // 21: voucher.config.RdsMQ.retryNotify:type_name -> voucher.config.RdsMQ.Queue + 21, // 22: voucher.config.RdsMQ.orderNotifyRetry:type_name -> voucher.config.RdsMQ.Queue + 21, // 23: voucher.config.RdsMQ.usedNotify:type_name -> voucher.config.RdsMQ.Queue + 22, // 24: voucher.config.Tripartite.qiXing:type_name -> voucher.config.Tripartite.QiXing + 23, // 25: voucher.config.Server.HTTP.timeout:type_name -> google.protobuf.Duration + 23, // 26: voucher.config.Data.Database.maxLifetime:type_name -> google.protobuf.Duration + 23, // 27: voucher.config.Data.Redis.readTimeout:type_name -> google.protobuf.Duration + 23, // 28: voucher.config.Data.Redis.writeTimeout:type_name -> google.protobuf.Duration + 23, // 29: voucher.config.Data.Redis.connMaxIdleTime:type_name -> google.protobuf.Duration + 4, // 30: voucher.config.RocketMQ.EventMapEntry.value:type_name -> voucher.config.EventMap + 19, // 31: voucher.config.Cron.CommandMapEntry.value:type_name -> voucher.config.Cron.CommandMap + 23, // 32: voucher.config.RdsMQ.Queue.waitTime:type_name -> google.protobuf.Duration + 33, // [33:33] is the sub-list for method output_type + 33, // [33:33] is the sub-list for method input_type + 33, // [33:33] is the sub-list for extension type_name + 33, // [33:33] is the sub-list for extension extendee + 0, // [0:33] is the sub-list for field type_name } func init() { file_conf_conf_proto_init() } @@ -2128,7 +2234,7 @@ func file_conf_conf_proto_init() { } } file_conf_conf_proto_msgTypes[14].Exporter = func(v any, i int) any { - switch v := v.(*Server_HTTP); i { + switch v := v.(*WechatSubject); i { case 0: return &v.state case 1: @@ -2140,7 +2246,7 @@ func file_conf_conf_proto_init() { } } file_conf_conf_proto_msgTypes[15].Exporter = func(v any, i int) any { - switch v := v.(*Data_Database); i { + switch v := v.(*Server_HTTP); i { case 0: return &v.state case 1: @@ -2152,6 +2258,18 @@ func file_conf_conf_proto_init() { } } file_conf_conf_proto_msgTypes[16].Exporter = func(v any, i int) any { + switch v := v.(*Data_Database); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_conf_conf_proto_msgTypes[17].Exporter = func(v any, i int) any { switch v := v.(*Data_Redis); i { case 0: return &v.state @@ -2163,7 +2281,7 @@ func file_conf_conf_proto_init() { return nil } } - file_conf_conf_proto_msgTypes[18].Exporter = func(v any, i int) any { + file_conf_conf_proto_msgTypes[19].Exporter = func(v any, i int) any { switch v := v.(*Cron_CommandMap); i { case 0: return &v.state @@ -2175,7 +2293,7 @@ func file_conf_conf_proto_init() { return nil } } - file_conf_conf_proto_msgTypes[20].Exporter = func(v any, i int) any { + file_conf_conf_proto_msgTypes[21].Exporter = func(v any, i int) any { switch v := v.(*RdsMQ_Queue); i { case 0: return &v.state @@ -2187,7 +2305,7 @@ func file_conf_conf_proto_init() { return nil } } - file_conf_conf_proto_msgTypes[21].Exporter = func(v any, i int) any { + file_conf_conf_proto_msgTypes[22].Exporter = func(v any, i int) any { switch v := v.(*Tripartite_QiXing); i { case 0: return &v.state @@ -2206,7 +2324,7 @@ func file_conf_conf_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_conf_conf_proto_rawDesc, NumEnums: 0, - NumMessages: 22, + NumMessages: 23, NumExtensions: 0, NumServices: 0, }, diff --git a/internal/conf/conf.proto b/internal/conf/conf.proto index 1bc014f..aabe777 100644 --- a/internal/conf/conf.proto +++ b/internal/conf/conf.proto @@ -18,6 +18,7 @@ message Bootstrap { RdsMQ rdsMQ = 10; AliYunSms aliYunSms = 11; Tripartite tripartite = 12; + repeated WechatSubject wechatSubject = 13; } message Server { @@ -158,4 +159,12 @@ message Tripartite { message Logs { string business = 1; string access = 2; +} + +message WechatSubject { + string mchID = 1; + string name = 4; + string mchCertificateSerialNumber = 2; + string wechatPayPublicKeyID = 3; + string mchApiV3Key = 6; } \ No newline at end of file diff --git a/internal/data/wechatrepoimpl/bank_multi_activity.go b/internal/data/wechatrepoimpl/bank_multi_activity.go index 2e0fc0c..58bd146 100644 --- a/internal/data/wechatrepoimpl/bank_multi_activity.go +++ b/internal/data/wechatrepoimpl/bank_multi_activity.go @@ -1,9 +1,12 @@ package wechatrepoimpl import ( + "context" + "encoding/json" "errors" "fmt" "github.com/wechatpay-apiv3/wechatpay-go/core" + "net/http" err2 "voucher/api/err" "voucher/internal/biz/bo" "voucher/internal/biz/wechatrepo" @@ -55,3 +58,22 @@ func (w *BankMultiActivityImpl) Order(order *bo.OrderBo) (couponId string, err e return *resp.CouponId, nil } + +func (w *BankMultiActivityImpl) Notify(ctx context.Context, mchId string, headers *http.Header, respBody []byte) (response *bo.WechatVoucherNotifyBo, err error) { + + t, err := w.wx.Get(mchId) + if err != nil { + return + } + + decodeBodyStr, err := t.Notify(ctx, headers, respBody) + if err != nil { + return + } + + if err = json.Unmarshal([]byte(decodeBodyStr), &response); err != nil { + return nil, err + } + + return +} diff --git a/internal/data/wx.go b/internal/data/wx.go index fb9df64..6d268c0 100644 --- a/internal/data/wx.go +++ b/internal/data/wx.go @@ -24,6 +24,14 @@ func NewWx(c *conf.Bootstrap) (*Wx, error) { clients[c.Wechat.MchID] = client + for _, v := range c.WechatSubject { + cli, e := buildWechat(v) + if e != nil { + return nil, e + } + clients[v.MchID] = cli + } + return &Wx{Clients: clients}, nil } @@ -44,6 +52,33 @@ func (this *Wx) Get(mchId string) (*marketing.Marketing, error) { return nil, fmt.Errorf("微信调用client不存在[%s]", mchId) } +func buildWechat(wx *conf.WechatSubject) (*marketing.Marketing, error) { + + dir, err := os.Getwd() + if err != nil { + return nil, fmt.Errorf("商户ID[%s]商户名称[%s]获取目的地址有误[%v]", wx.MchID, wx.Name, err) + } + + filePath := fmt.Sprintf("%s/cert/wechat/%s", dir, wx.MchID) + if !helper.FileExists(filePath) { + panic(fmt.Sprintf("商户ID[%s]商户名称[%s]微信密钥证书信息不存在,请联系技术人员处理", wx.MchID, wx.Name)) + } + + cc, err := utils2.CreateMchConfig( + wx.MchID, // 商户号,是由微信支付系统生成并分配给每个商户的唯一标识符,商户号获取方式参考 https://pay.weixin.qq.com/doc/v3/merchant/4013070756 + wx.MchCertificateSerialNumber, // 商户API证书序列号,如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013053053 + fmt.Sprintf("%s/%s", filePath, "wechat_private_key.pem"), // 商户API证书私钥文件路径,本地文件路径 + wx.WechatPayPublicKeyID, // 微信支付公钥ID,如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013038816 + fmt.Sprintf("%s/%s", filePath, "pub_key.pem"), // 微信支付公钥文件路径,本地文件路径 + wx.MchApiV3Key, + ) + if err != nil { + return nil, err + } + + return &marketing.Marketing{MchConfig: cc}, nil +} + func buildWx(wx *conf.Wechat) (*marketing.Marketing, error) { dir, err := os.Getwd() @@ -62,6 +97,7 @@ func buildWx(wx *conf.Wechat) (*marketing.Marketing, error) { fmt.Sprintf("%s/%s", filePath, "wechat_private_key.pem"), // 商户API证书私钥文件路径,本地文件路径 wx.WechatPayPublicKeyID, // 微信支付公钥ID,如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013038816 fmt.Sprintf("%s/%s", filePath, "pub_key.pem"), // 微信支付公钥文件路径,本地文件路径 + "", ) if err != nil { return nil, err diff --git a/internal/pkg/wechat/srv/marketing/marketing.go b/internal/pkg/wechat/srv/marketing/marketing.go index 65203e0..71e0894 100644 --- a/internal/pkg/wechat/srv/marketing/marketing.go +++ b/internal/pkg/wechat/srv/marketing/marketing.go @@ -1,7 +1,9 @@ package marketing import ( + "context" "encoding/json" + "net/http" "net/url" "strings" "voucher/internal/pkg/wechat/srv" @@ -39,13 +41,13 @@ func (srv *Marketing) Send(openId string, req *SendReq) (response *SendResp, err } // Query @link https://pay.weixin.qq.com/doc/v3/merchant/4014569864 -func (srv *Marketing) Query(appid, openId, couponId string) (response *SendResp, err error) { +func (srv *Marketing) Query(appId, openId, couponId string) (response *SendResp, err error) { path := strings.Replace(queryPath, "{openid}", url.PathEscape(openId), -1) path = strings.Replace(path, "{coupon_id}", url.PathEscape(couponId), -1) var uv = url.Values{} - uv.Set("appid", appid) + uv.Set("appid", appId) path += "?" + uv.Encode() respBody, err := srv.Request2(utils.Host, utils.MethodGET, path, nil) @@ -59,3 +61,14 @@ func (srv *Marketing) Query(appid, openId, couponId string) (response *SendResp, return response, nil } + +// Notify . +func (srv *Marketing) Notify(_ context.Context, headers *http.Header, respBody []byte) (response string, err error) { + + bizStr, err := srv.GetDecodeBody(headers, respBody) + if err != nil { + return "", err + } + + return bizStr, nil +} diff --git a/internal/pkg/wechat/utils/aes.go b/internal/pkg/wechat/utils/aes.go new file mode 100644 index 0000000..d95fb4c --- /dev/null +++ b/internal/pkg/wechat/utils/aes.go @@ -0,0 +1,87 @@ +package utils + +import ( + "crypto/aes" + "crypto/cipher" + "encoding/base64" + "errors" + "fmt" +) + +const ( + keyLengthByte = 32 // AES-256 密钥长度(字节) + authTagLengthByte = 16 // GCM 认证标签长度(字节) +) + +// AesUtil 用于微信支付 AES-256-GCM 解密的工具类 +type AesUtil struct { + aesKey []byte // 32字节的AES密钥 +} + +// NewAesUtil 创建AesUtil实例,验证密钥长度 +func NewAesUtil(aesKey string) (*AesUtil, error) { + if len(aesKey) != keyLengthByte { + return nil, errors.New("无效的ApiV3Key,长度应为32个字节") + } + return &AesUtil{aesKey: []byte(aesKey)}, nil +} + +// DecryptToString 解密 AEAD_AES_256_GCM 加密的数据 +// associatedData: 附加认证数据 +// nonceStr: 随机数(12字节) +// ciphertext: 加密后的密文(Base64编码) +func (a *AesUtil) DecryptToString(associatedData, nonceStr, ciphertext string) (string, error) { + // 1. Base64解码密文 + cipherBytes, err := base64.StdEncoding.DecodeString(ciphertext) + if err != nil { + return "", fmt.Errorf("密文Base64解码失败: %w", err) + } + + // 2. 验证密文长度(需包含认证标签) + if len(cipherBytes) <= authTagLengthByte { + return "", errors.New("密文长度不足,无法解析认证标签") + } + + // 3. 分离密文和认证标签(GCM模式中,认证标签通常附加在密文末尾) + ctext := cipherBytes[:len(cipherBytes)-authTagLengthByte] + authTag := cipherBytes[len(cipherBytes)-authTagLengthByte:] + + // 4. 初始化AES-GCM加密器 + block, err := aes.NewCipher(a.aesKey) + if err != nil { + return "", fmt.Errorf("创建AES加密器失败: %w", err) + } + + gcm, err := cipher.NewGCM(block) + if err != nil { + return "", fmt.Errorf("创建GCM模式失败: %w", err) + } + + // 5. 构建附加数据(GCM的AAD) + additionalData := []byte(associatedData) + + // 6. 解密(GCM模式会自动验证认证标签) + plaintext, err := gcm.Open(nil, []byte(nonceStr), append(ctext, authTag...), additionalData) + if err != nil { + return "", fmt.Errorf("解密失败(可能是密钥错误或数据被篡改): %w", err) + } + + return string(plaintext), nil +} + +type Resource struct { + OriginalType string `json:"original_type"` + Algorithm string `json:"algorithm"` + Ciphertext string `json:"ciphertext"` // 如支付通知中的 encrypted_data + AssociatedData string `json:"associated_data"` // 微信支付回调的附加数据 通常为空字符串或回调相关信息 + Nonce string `json:"nonce"` // 12字节字符串 +} + +type WxNotifyBody struct { + Id string `json:"id"` + CreateTime string `json:"create_time"` + ResourceType string `json:"resource_type"` + EventType string `json:"event_type"` + Summary string `json:"summary"` + Resource Resource `json:"resource"` +} diff --git a/internal/pkg/wechat/utils/wxpay_utility.go b/internal/pkg/wechat/utils/wxpay_utility.go index f488688..15de6d0 100644 --- a/internal/pkg/wechat/utils/wxpay_utility.go +++ b/internal/pkg/wechat/utils/wxpay_utility.go @@ -42,6 +42,8 @@ type MchConfig struct { wechatPayPublicKeyFilePath string privateKey *rsa.PrivateKey wechatPayPublicKey *rsa.PublicKey + + aesKey string } // MchId 商户号 @@ -76,6 +78,7 @@ func CreateMchConfig( privateKeyFilePath string, wechatPayPublicKeyId string, wechatPayPublicKeyFilePath string, + aesKey string, ) (*MchConfig, error) { mchConfig := &MchConfig{ mchId: mchId, @@ -83,6 +86,7 @@ func CreateMchConfig( privateKeyFilePath: privateKeyFilePath, wechatPayPublicKeyId: wechatPayPublicKeyId, wechatPayPublicKeyFilePath: wechatPayPublicKeyFilePath, + aesKey: aesKey, } privateKey, err := LoadPrivateKeyWithPath(mchConfig.privateKeyFilePath) if err != nil { @@ -572,6 +576,35 @@ func (srv *MchConfig) Verify(request *http.Request) (string, error) { return EncryptOAEPWithPublicKey(string(respBody), srv.wechatPayPublicKey) } +func (srv *MchConfig) GetDecodeBody(headers *http.Header, respBody []byte) (string, error) { + + if respBody == nil { + return "", fmt.Errorf("request HttpBody is nil") + } + + err := ValidateResponse( + srv.WechatPayPublicKeyId(), + srv.WechatPayPublicKey(), + headers, + respBody, + ) + if err != nil { + return "", err + } + + var wxNotifyBody WxNotifyBody + if err = json.Unmarshal(respBody, &wxNotifyBody); err != nil { + return "", err + } + + aesUtil, err := NewAesUtil(srv.aesKey) + if err != nil { + return "", err + } + + return aesUtil.DecryptToString(wxNotifyBody.Resource.AssociatedData, wxNotifyBody.Resource.Nonce, wxNotifyBody.Resource.Ciphertext) +} + // BuildSortedQueryString 函数接受一个 map,返回按照字段名排序后的 URL 键值对格式字符串 func BuildSortedQueryString(params map[string]any) string { // 创建一个字符串切片,用于保存所有的键名 diff --git a/internal/pkg/wechat/utils/wxpay_utility_test.go b/internal/pkg/wechat/utils/wxpay_utility_test.go new file mode 100644 index 0000000..fc464bd --- /dev/null +++ b/internal/pkg/wechat/utils/wxpay_utility_test.go @@ -0,0 +1,68 @@ +package utils + +import ( + "crypto/rsa" + "reflect" + "testing" +) + +func TestMchConfig_Request(t *testing.T) { + type fields struct { + mchId string + certificateSerialNo string + privateKeyFilePath string + wechatPayPublicKeyId string + wechatPayPublicKeyFilePath string + privateKey *rsa.PrivateKey + wechatPayPublicKey *rsa.PublicKey + } + type args struct { + host string + method string + path string + reqBody []byte + } + tests := []struct { + name string + fields fields + args args + wantResponse []byte + wantErr bool + }{ + { + name: "test", + fields: fields{ + mchId: "1652322442", + certificateSerialNo: "certificateSerialNo", + privateKeyFilePath: "privateKeyFilePath", + wechatPayPublicKeyId: "wechatPayPublicKeyId", + wechatPayPublicKeyFilePath: "wechatPayPublicKeyFilePath", + }, + args: args{ + host: "https://api.mch.weixin.qq.com", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + srv := &MchConfig{ + mchId: tt.fields.mchId, + certificateSerialNo: tt.fields.certificateSerialNo, + privateKeyFilePath: tt.fields.privateKeyFilePath, + wechatPayPublicKeyId: tt.fields.wechatPayPublicKeyId, + wechatPayPublicKeyFilePath: tt.fields.wechatPayPublicKeyFilePath, + privateKey: tt.fields.privateKey, + wechatPayPublicKey: tt.fields.wechatPayPublicKey, + } + + gotResponse, err := srv.Request(tt.args.host, tt.args.method, tt.args.path, tt.args.reqBody) + if (err != nil) != tt.wantErr { + t.Errorf("Request() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(gotResponse, tt.wantResponse) { + t.Errorf("Request() gotResponse = %v, want %v", gotResponse, tt.wantResponse) + } + }) + } +} diff --git a/internal/server/http.go b/internal/server/http.go index 0941fe6..d6e9084 100644 --- a/internal/server/http.go +++ b/internal/server/http.go @@ -27,6 +27,7 @@ func NewHTTPServer( accessLogger *log2.AccessLogger, cmb *service.CmbService, tripartiteService *service.TripartiteService, + notifyService *service.NotifyService, ) *http.Server { //构建 server srv := buildHTTPServer(c, accessLogger, log) @@ -39,6 +40,11 @@ func NewHTTPServer( // 启星(启星-蓝色兄弟立减金代配) /voucher/qixing/v1/notify srv.Route("/voucher/").POST("qixing/v1/notify", tripartiteService.QiXingNotify) + // 通知url必须为公网可访问的URL,必须为HTTPS,不能携带参数 + // https://域名.cn/voucher/v1/notify/123456 123456为微信主体商户号 + // https://gateway.dev.cdlsxd.cn/voucher/v1/notify/123456 123456为微信主体商户号 测试环境 + // https://voucher.86698.cn/voucher/v1/notify/123456 123456为微信主体商户号 正式环境 + srv.Route("/voucher/").POST("/notify/v1/{mch_id}", notifyService.Notify) // 订单通知重试 -- 不健全 srv.Route("/voucher/").POST("orderNotifyRetry", cmb.OrderNotifyRetry) diff --git a/internal/service/notify.go b/internal/service/notify.go new file mode 100644 index 0000000..c34ac9f --- /dev/null +++ b/internal/service/notify.go @@ -0,0 +1,79 @@ +package service + +import ( + "fmt" + "github.com/go-kratos/kratos/v2/log" + "github.com/go-kratos/kratos/v2/transport/http" + "io" + http2 "net/http" + "voucher/internal/biz" + "voucher/internal/pkg/helper" +) + +type NotifyService struct { + WechatBiz *biz.WechatBiz + VoucherBiz *biz.VoucherBiz +} + +func NewNotifyService(wechatBiz *biz.WechatBiz, VoucherBiz *biz.VoucherBiz) *NotifyService { + return &NotifyService{WechatBiz: wechatBiz, VoucherBiz: VoucherBiz} +} + +// Notify https://pay.weixin.qq.com/doc/v3/merchant/4012285250 +func (srv *NotifyService) Notify(ctx http.Context) error { + + mchId := ctx.Vars().Get("mch_id") + if mchId == "" { + log.Errorf("微信回调通知,mchId参数不能为空") + return ctx.JSON(http2.StatusNetworkAuthenticationRequired, map[string]string{ + "code": "FAIL", + "message": "微信回调通知,mchId参数不能为空", + }) + } + + headers := ctx.Request().Header + if headers == nil { + log.Errorf("微信回调通知[%s],headers参数不能为空", mchId) + return ctx.JSON(http2.StatusNetworkAuthenticationRequired, map[string]string{ + "code": "FAIL", + "message": "微信回调通知,headers参数不能为空", + }) + } + + bodyBytes, err := io.ReadAll(ctx.Request().Body) + if err != nil { + log.Errorf("微信回调通知[%s],读取响应体失败: %v", mchId, err) + return fmt.Errorf("读取响应体失败: %w", err) + } + + if bodyBytes == nil { + log.Errorf("微信回调通知[%s],响应体不能为空", mchId) + return ctx.JSON(http2.StatusNetworkAuthenticationRequired, map[string]string{ + "code": "FAIL", + "message": "微信回调通知,响应体不能为空", + }) + } + + log.Warnf("微信回调通知[%s],headers:%+v,body:%s", mchId, headers, string(bodyBytes)) + + response, err := srv.WechatBiz.CallBack(ctx, mchId, &headers, bodyBytes) + if err != nil { + return ctx.JSON(http2.StatusNetworkAuthenticationRequired, map[string]string{ + "code": "FAIL", + "message": err.Error(), + }) + } + + ip := helper.GetClientIP(ctx) + + if err = srv.VoucherBiz.WechatNotifyConsumer(ctx, ip, "WECHAT_NOTIFY", response); err != nil { + + log.Errorf("微信回调通知[%s],headers:%+v,body:%s,err:%s", mchId, headers, string(bodyBytes), err.Error()) + return ctx.JSON(http2.StatusBadRequest, map[string]string{ + "code": "FAIL", + "message": err.Error(), + }) + } + + return ctx.JSON(http2.StatusOK, nil) +} diff --git a/internal/service/provider_set.go b/internal/service/provider_set.go index fd9e579..220ae5c 100644 --- a/internal/service/provider_set.go +++ b/internal/service/provider_set.go @@ -9,4 +9,5 @@ var ProviderSetService = wire.NewSet( NewVoucherService, NewCmbService, NewTripartiteService, + NewNotifyService, ) diff --git a/internal/service/voucher.go b/internal/service/voucher.go index b13c6d4..fddf7d1 100644 --- a/internal/service/voucher.go +++ b/internal/service/voucher.go @@ -133,5 +133,5 @@ func (v *VoucherService) WechatUseNotifyConsumer(ctx context.Context, tag, msg s return err } - return v.VoucherBiz.WechatNotifyConsumer(ctx, tag, req) + return v.VoucherBiz.WechatNotifyConsumer(ctx, "127.0.0.1", tag, req) } diff --git a/test/bank_multi_activity.go b/test/bank_multi_activity.go index 8edd220..84c0d2f 100644 --- a/test/bank_multi_activity.go +++ b/test/bank_multi_activity.go @@ -36,6 +36,7 @@ func marketing() *marketing2.Marketing { fmt.Sprintf("%s/%s", filePath, "wechat_private_key.pem"), // 商户API证书私钥文件路径,本地文件路径 wechatPayPublicKeyId, // 微信支付公钥ID,如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013038816 fmt.Sprintf("%s/%s", filePath, "pub_key.pem"), // 微信支付公钥文件路径,本地文件路径 + "", ) if err != nil { panic(err) @@ -67,6 +68,37 @@ func marketingFJxw() *marketing2.Marketing { fmt.Sprintf("%s/%s", filePath, "wechat_private_key.pem"), // 商户API证书私钥文件路径,本地文件路径 wechatPayPublicKeyId, // 微信支付公钥ID,如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013038816 fmt.Sprintf("%s/%s", filePath, "pub_key.pem"), // 微信支付公钥文件路径,本地文件路径 + "", + ) + if err != nil { + panic(err) + } + + return &marketing2.Marketing{MchConfig: c} +} + +func marketingFJLF() *marketing2.Marketing { + + dir, err := os.Getwd() + if err != nil { + panic(err) + } + + parentDir := filepath.Dir(dir) + + mchId := "1100040695" + wechatPayPublicKeyId := " PUB_KEY_ID_0111000406952026032500382251001000" + certificateSerialNo := "46712853869DB0EDAA9B4DF97DADEECD4CCDC85B" + + filePath := fmt.Sprintf("%s/cert/wechat/%s", parentDir, mchId) + + c, err := utils.CreateMchConfig( + mchId, // 商户号,是由微信支付系统生成并分配给每个商户的唯一标识符,商户号获取方式参考 https://pay.weixin.qq.com/doc/v3/merchant/4013070756 + certificateSerialNo, // 商户API证书序列号,如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013053053 + fmt.Sprintf("%s/%s", filePath, "wechat_private_key.pem"), // 商户API证书私钥文件路径,本地文件路径 + wechatPayPublicKeyId, // 微信支付公钥ID,如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013038816 + fmt.Sprintf("%s/%s", filePath, "pub_key.pem"), // 微信支付公钥文件路径,本地文件路径 + "", ) if err != nil { panic(err) @@ -112,4 +144,5 @@ func MarketingSend() { func MarketingQuery(appId, openId, couponId string) (response *marketing2.SendResp, err error) { return marketingFJxw().Query(appId, openId, couponId) + //return marketingFJLF().Query(appId, openId, couponId) } diff --git a/test/bank_multi_activity_test.go b/test/bank_multi_activity_test.go index 057fcca..453983b 100644 --- a/test/bank_multi_activity_test.go +++ b/test/bank_multi_activity_test.go @@ -1,8 +1,11 @@ package test import ( + "context" "encoding/base64" "encoding/json" + "fmt" + "net/http" "testing" "time" "voucher/internal/biz/bo" @@ -90,3 +93,67 @@ func Test_QixingNotifyData(t *testing.T) { // {"content":"base64(微信通知json对象数据)","timestamp":1765447477945,"ciphertext":"md5(base64(微信通知json对象数据)+key)"} //t.Logf(`{"content":"%s","timestamp":122345677890,"ciphertext":"%s"}`, content, ciphertext) } + +func Test_MarketingNotify(t *testing.T) { + + header := `{ + "Content-Type": [ + "application/json" + ], + "Wechatpay-Nonce": [ + "dF8R9izUJnPBjVLa2cAcCaa7j6QUgitl" + ], + "Wechatpay-Serial": [ + "PUB_KEY_ID_0116523224422025061800192371001800" + ], + "Wechatpay-Signature": [ + "SoXIiTRTr6jofXXxGlfO+wyf1IzXFXcsfvEU2EggQfRKFu+8h3TT6QMQ8zIf8dpkkTPexB/3igGiATrR3uZY4ZeOpRrhIFHSJj0Ala0Ri2Nt4zk+MuBQnhybSYJ4Cn3/sHC4i2HFoOSil7OqlSr79hjod3h0tjYVQLtZ4+Cjp0IeMNB4p5qmIuERuhtfRqcyqXik9/uYNYxw8/Wkf1mMnTsBxyXK3iHAoinXNrEiqCCrQHCfnORMYosr7l+Ox8v9u1c8FFt+rt09vKssVCqYaZ/XRala3mjslDRiluFKSuqb7/JO3AxQjBK6M0iSZOlnmiXSIAq+UxJg4cem6wHi+g==" + ], + "Wechatpay-Signature-Type": [ + "WECHATPAY2-SHA256-RSA2048" + ], + "Wechatpay-Timestamp": [ + "1753690220" + ], + "X-Forwarded-For": [ + "121.51.58.168" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-Real-Ip": [ + "121.51.58.168" + ] + }` + body := `{ + "id": "fd06376a-3e1b-5516-81f8-9b69cf1ba416", + "create_time": "2025-07-28T16:10:15+08:00", + "resource_type": "encrypt-resource", + "event_type": "MCHTRANSFER.BILL.FINISHED", + "summary": "商家转账单据终态通知", + "resource": { + "original_type": "mch_payment", + "algorithm": "AEAD_AES_256_GCM", + "ciphertext": "XJBIhrHgbe9NR5q/jLYmZKdT/3xuKm2x7EFu3T52Hj2hjPzarRSA2HCsGTxGojfD+CFyJHIULlL2adqLijAjpi3B6TaYKY4LqhtJ/RYSQtYNxYvBpWX1yLOWe8luJbWxmQvKZxIekFs8lGVgkPBUw0IfEAvJ6jHAGCcgxLIqxgOf6UtGUqxCCNp/V3xy8zCiHB0Mvlw8eXCTuG+ZESJIXvloVGNS79R6iNeqk4kNKRSaV86MNh1KQlmoBxZ4yEshD/vIlMulU3xEc+mM25y8vUS4Ot6pxEpUdUyjwcb9QTwTTnZzm6i+VWYymcItAVBQrvsKBMmqWnPtNXG8++13k3DeO1LyVKURmnWXXT1mImmGx/teN/1xPV5y6nChu/HTbcJGDQy2twuq6TPFbbYlTjZH047z/ZtozJNvGNeh", + "associated_data": "mch_payment", + "nonce": "YN3eW5H8mxLs" + } + }` + + fmt.Print(header) + fmt.Print(body) + + httpHeaders := make(http.Header) + if err := json.Unmarshal([]byte(header), &httpHeaders); err != nil { + fmt.Printf("headers Unmarshal err: %+v\n", err) + return + } + + bizContent, err := marketingFJLF().Notify(context.Background(), &httpHeaders, []byte(body)) + if err != nil { + fmt.Printf("notify err: %+v\n", err) + return + } + + fmt.Printf("bizContent: %+v\n", bizContent) +} diff --git a/test/coupon.go b/test/coupon.go index f63f57e..a258dda 100644 --- a/test/coupon.go +++ b/test/coupon.go @@ -24,6 +24,7 @@ var bc = &conf.Bootstrap{ }, } +// bc2 Callback{NotifyUrl:https://nsall.86698.cn/wechatPay/coupon_notify/fjxingwang, Mchid:1652465541} var bc2 = &conf.Bootstrap{ Wechat: &conf.Wechat{ MchID: "1652465541", // notifyUrl https://nsall.86698.cn/wechatPay/coupon_notify/fjxingwang @@ -33,6 +34,15 @@ var bc2 = &conf.Bootstrap{ }, } +var bcFJLF = &conf.Bootstrap{ + Wechat: &conf.Wechat{ + MchID: "1100040695", + MchCertificateSerialNumber: "46712853869DB0EDAA9B4DF97DADEECD4CCDC85B", + WechatPayPublicKeyID: "PUB_KEY_ID_0111000406952026032500382251001000", + Name: "福建峦峰", + }, +} + func SendCoupon() { ctx := context.Background() @@ -223,7 +233,7 @@ func WxResp(wxResp *cashcoupons.Stock) (reps *do.WxResp) { return req } -func QueryCallback() { +func QueryCallback(bc *conf.Bootstrap) { ctx := context.Background() @@ -235,9 +245,9 @@ func QueryCallback() { parentDir := filepath.Dir(dir) server := data.Server{ - MchID: bc2.Wechat.MchID, - MchCertificateSerialNumber: bc2.Wechat.MchCertificateSerialNumber, - WechatPayPublicKeyID: bc2.Wechat.WechatPayPublicKeyID, + MchID: bc.Wechat.MchID, + MchCertificateSerialNumber: bc.Wechat.MchCertificateSerialNumber, + WechatPayPublicKeyID: bc.Wechat.WechatPayPublicKeyID, Dir: parentDir, } client, err := data.GetClient(ctx, server) @@ -249,7 +259,46 @@ func QueryCallback() { svc := cashcoupons.CallBackUrlApiService{Client: client} response, _, err := svc.QueryCallback(ctx, cashcoupons.QueryCallbackRequest{ - Mchid: core.String("1652465541"), + Mchid: core.String(bc.Wechat.MchID), + }) + if err != nil { + fmt.Println(err) + return + } + + fmt.Printf("\nresp:%+v\n", response) + return +} + +func SetCallback(bc *conf.Bootstrap) { + + ctx := context.Background() + + dir, err := os.Getwd() + if err != nil { + fmt.Printf("os.Getwd() error = %v", err) + return + } + parentDir := filepath.Dir(dir) + + server := data.Server{ + MchID: bc.Wechat.MchID, + MchCertificateSerialNumber: bc.Wechat.MchCertificateSerialNumber, + WechatPayPublicKeyID: bc.Wechat.WechatPayPublicKeyID, + Dir: parentDir, + } + client, err := data.GetClient(ctx, server) + if err != nil { + fmt.Println(err) + return + } + + svc := cashcoupons.CallBackUrlApiService{Client: client} + + response, _, err := svc.SetCallback(ctx, cashcoupons.SetCallbackRequest{ + Mchid: core.String(bc.Wechat.MchID), + NotifyUrl: core.String("https://gateway.dev.cdlsxd.cn/voucher/v1/notify/" + bc.Wechat.MchID), + Switch: core.Bool(true), }) if err != nil { fmt.Println(err) diff --git a/test/coupon_test.go b/test/coupon_test.go index 61daa6f..2edf776 100644 --- a/test/coupon_test.go +++ b/test/coupon_test.go @@ -60,7 +60,23 @@ func Test_QueryCallback(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - QueryCallback() + QueryCallback(bcFJLF) + }) + } +} + +func Test_SetCallback(t *testing.T) { + tests := []struct { + name string + }{ + { + name: "设置券核销通知地址", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + + SetCallback(bcFJLF) }) } }