作者 yangfu

Merge remote-tracking branch 'origin/test'

正在显示 67 个修改的文件 包含 2070 行增加88 行删除
... ... @@ -7,10 +7,15 @@ aliyun_logs_access ="${aliyun_logs_access||F:/log/app.log}"
#阿里云基础配置
AccessKeyID ="LTAI4FhiZ3UktC6N1u3H5GFC"
AccessKeySecret ="UyspWwdni55CYQ02hUCint4qY2jNYO"
#AccessKeyID ="LTAI4Fz1LUBW2fXp6QWaJHRS"
#AccessKeySecret ="aLZXwK8pgrs10Ws03qcN7NsrSXFVsg"
#阿里云->绑定域名 cname = https://media.goexample.live/
cname ="https://media.fjmaimaimai.com/"
cname ="https://media.goexample.live/"
#友盟推送
UMENG_API_HOST = "http://msg.umeng.com"
#数据库相关
MYSQL_USER = "${MYSQL_USER||root}"
MYSQL_PASSWORD = "${MYSQL_PASSWORD||sutianxia2018}"
MYSQL_HOST = "${MYSQL_HOST||101.37.68.23}"
MYSQL_PORT = "${MYSQL_PORT||3306}"
MYSQL_DB_NAME = "${MYSQL_DB_NAME||mmm_open_dev}"
\ No newline at end of file
... ...
... ... @@ -7,5 +7,12 @@ AccessKeySecret ="aLZXwK8pgrs10Ws03qcN7NsrSXFVsg"
log_level = "${LOG_LEVEL||debug}"
aliyun_logs_access ="${aliyun_logs_access||F:/log/app.log}"
#阿里云 https://media.goexample.live/
#阿里云
cname ="https://media.fjmaimaimai.com/"
#数据库相关
MYSQL_USER = "${MYSQL_USER||root}"
MYSQL_PASSWORD = "${MYSQL_PASSWORD||sutianxia2018}"
MYSQL_HOST = "${MYSQL_HOST||101.37.68.23}"
MYSQL_PORT = "${MYSQL_PORT||3306}"
MYSQL_DB_NAME = "${MYSQL_DB_NAME||mmm_open_dev}"
... ...
... ... @@ -8,4 +8,11 @@ AccessKeyID ="LTAI4Fz1LUBW2fXp6QWaJHRS"
AccessKeySecret ="aLZXwK8pgrs10Ws03qcN7NsrSXFVsg"
#阿里云
cname ="https://media.fjmaimaimai.com/"
\ No newline at end of file
cname ="https://media.fjmaimaimai.com/"
#数据库相关
MYSQL_USER = "${MYSQL_USER||root}"
MYSQL_PASSWORD = "${MYSQL_PASSWORD||sutianxia2018}"
MYSQL_HOST = "${MYSQL_HOST||101.37.68.23}"
MYSQL_PORT = "${MYSQL_PORT||3306}"
MYSQL_DB_NAME = "${MYSQL_DB_NAME||mmm_open}"
\ No newline at end of file
... ...
... ... @@ -8,4 +8,11 @@ AccessKeyID ="LTAI4Fz1LUBW2fXp6QWaJHRS"
AccessKeySecret ="aLZXwK8pgrs10Ws03qcN7NsrSXFVsg"
#阿里云
cname ="https://media.fjmaimaimai.com/"
\ No newline at end of file
cname ="https://media.fjmaimaimai.com/"
#数据库相关
MYSQL_USER = "${MYSQL_USER||root}"
MYSQL_PASSWORD = "${MYSQL_PASSWORD||sutianxia2018}"
MYSQL_HOST = "${MYSQL_HOST||101.37.68.23}"
MYSQL_PORT = "${MYSQL_PORT||3306}"
MYSQL_DB_NAME = "${MYSQL_DB_NAME||mmm_open_test}"
\ No newline at end of file
... ...
... ... @@ -3,11 +3,26 @@ module openapi
go 1.12
require (
github.com/ajg/form v1.5.1 // indirect
github.com/aliyun/alibaba-cloud-sdk-go v1.60.348
github.com/aliyun/aliyun-sts-go-sdk v0.0.0-20171106034748-98d3903a2309
github.com/astaxie/beego v1.10.0
github.com/fatih/structs v1.1.0 // indirect
github.com/gavv/httpexpect v2.0.0+incompatible
github.com/go-sql-driver/mysql v1.4.1
github.com/google/go-querystring v1.0.0 // indirect
github.com/imkira/go-interpol v1.1.0 // indirect
github.com/klauspost/cpuid v1.2.3 // indirect
github.com/moul/http2curl v1.0.0 // indirect
github.com/onsi/ginkgo v1.10.3
github.com/onsi/gomega v1.7.1
github.com/satori/go.uuid v1.2.0
github.com/sergi/go-diff v1.1.0 // indirect
github.com/valyala/fasthttp v1.13.1 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 // indirect
github.com/yudai/gojsondiff v1.0.0 // indirect
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect
gitlab.fjmaimaimai.com/mmm-go/gocomm v0.0.1
)
... ...
package main
import (
"fmt"
"github.com/astaxie/beego"
"gitlab.fjmaimaimai.com/mmm-go/gocomm/config"
"gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/log"
"openapi/internal/utils"
_ "openapi/routers"
"time"
_ "openapi/pkg/infrastructure/bgorm"
_ "openapi/pkg/log"
_ "openapi/pkg/port/beego"
)
func init() {
time.Local = time.FixedZone("CST", 3600*8)
log.InitLog(config.Logger{
Filename: beego.AppConfig.String("aliyun_logs_access"),
Level: fmt.Sprintf("%v", utils.ResolveLogLevel(beego.AppConfig.String("log_level"))),
})
}
func main() {
defer func() {
log.Info("open-api on stop!")
log.Info("server on stop!")
}()
log.Info("open-api on start!")
log.Info("Beego Run Mode:", beego.BConfig.RunMode)
log.Info("server on start!")
//constant.DebugConfig()
beego.Run()
}
... ...
package push
import (
"fmt"
"gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/log"
protocol "openapi/pkg/domain"
"openapi/pkg/infrastructure/push"
"openapi/pkg/infrastructure/push/getui"
"openapi/pkg/infrastructure/repository"
"openapi/pkg/infrastructure/utils"
"strings"
)
//推送信息
func Notification(header *protocol.RequestHeader, request *protocol.PushInfoRequest) (rsp *protocol.PushInfoResponse, err error) {
var (
repApp, _ = repository.NewAppInfoRepository(nil)
repDevice, _ = repository.NewPushDeviceRepository(nil)
appInfo *protocol.AppInfo
receivers []string
deviceList []*protocol.Device
requestOriginal *protocol.PushInfoOriginalRequest = &protocol.PushInfoOriginalRequest{
Type: request.Type,
Title: request.Title,
Content: request.Content,
Ext: request.Ext,
}
)
rsp = &protocol.PushInfoResponse{}
if appInfo, err = repApp.FindOne(map[string]interface{}{"project_key": request.ProjectKey}); err != nil {
log.Error(err)
err = protocol.NewCustomMessage(1, fmt.Sprintf("project_key:%v not found", request.ProjectKey))
return
}
if deviceList, err = repDevice.Find(map[string]interface{}{"receivers": request.Receivers}); err != nil {
log.Error(err)
err = nil
return
}
if len(deviceList) == 0 {
err = protocol.NewSuccessWithMessage(fmt.Sprintf("接收人:%v 未查询到注册的设备信息!", request.Receivers))
return
}
for i := range deviceList {
receivers = append(receivers, deviceList[i].ClientId)
}
requestOriginal.AppKey = appInfo.AppKey
requestOriginal.AppId = appInfo.AppId
requestOriginal.Secret = appInfo.AppMasterSecret
requestOriginal.ClientIdList = receivers
return NotificationOriginal(header, requestOriginal)
}
func NotificationOriginal(header *protocol.RequestHeader, request *protocol.PushInfoOriginalRequest) (rsp *protocol.PushInfoResponse, err error) {
var (
sendData = make(map[string]interface{})
clientIds []string
options []push.Option = []push.Option{
push.DebugModule(true),
push.AppId(request.AppId),
push.AppKey(request.AppKey),
push.AppMasterSecret(request.Secret),
push.MsgType(request.Type),
push.Title(request.Title),
push.Content(request.Content),
//push.TransmissionContent(utils.JsonAssertString(request.Ext)),
}
)
if v, ok := request.Ext["transData"]; ok {
options = append(options, push.TransmissionContent(utils.JsonAssertString(v)))
}
clientIds = request.ClientIdList
switch len(clientIds) {
case 0:
err = protocol.NewCustomMessage(2, "clientId/deviceToken 不能同时为空.")
return
case 1:
options = append(options,
push.PushType(push.PushToSingle),
push.ClientId(clientIds[0]),
)
break
default:
options = append(options,
push.PushType(push.PushToList),
push.ClientIds(clientIds),
)
break
}
var pushService push.INotification = &getui.GetuiNotification{}
err = pushService.Init(options...)
if err != nil {
log.Error(err)
return
}
if err = pushService.Send(sendData); err != nil {
log.Error(err)
return
}
rsp = &protocol.PushInfoResponse{}
return
}
//更新设备信息
func UpdateDevice(header *protocol.RequestHeader, request *protocol.UpdateDeviceRequest) (rsp *protocol.UpdateDeviceResponse, err error) {
var (
device *protocol.Device
)
rsp = &protocol.UpdateDeviceResponse{}
rep, _ := repository.NewPushDeviceRepository(nil)
if device, err = rep.FindOne(map[string]interface{}{"uid": request.Muid}); err != nil {
if err == protocol.ERR_DB_NOT_FOUND {
err = nil
rep.Save(request)
return
}
log.Error(err)
return
}
if device.ClientId == strings.TrimSpace(request.ClientId) && device.DeviceToken == strings.TrimSpace(request.DeviceToken) {
err = protocol.NewSuccessWithMessage("更新成功")
return
}
if err = rep.UpdateDevice(request.Muid, request.ClientId, request.DeviceToken); err != nil {
log.Error(err)
}
err = protocol.NewSuccessWithMessage("更新成功")
return
}
... ...
package vod
package service
import (
"openapi/internal/aliyun"
"openapi/protocol"
protocol "openapi/pkg/domain"
"openapi/pkg/infrastructure/aliyun"
)
//错误处理
... ...
package vod
package service
import (
"github.com/astaxie/beego"
"gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/log"
"openapi/internal/aliyun"
"openapi/internal/utils"
"openapi/protocol"
"openapi/pkg/constant"
protocol "openapi/pkg/domain"
"openapi/pkg/infrastructure/aliyun"
"openapi/pkg/infrastructure/utils"
)
//创建视频上传凭证
... ... @@ -44,7 +44,7 @@ func CreateUploadVideo(header *protocol.RequestHeader, request *aliyun.CreateUpl
return
}
rsp.FileName = fileName
rsp.FileURL = up.GetFileUrl(beego.AppConfig.String("cname"))
rsp.FileURL = up.GetFileUrl(constant.CName)
return
}
... ...
package constant
import (
"fmt"
"gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/log"
)
var (
LogFilePath string = "F:/log/app.log"
LogLevel string = "error"
)
func init() {
LogLevel = config.StringDefault("log_level", LogLevel)
LogFilePath = config.StringDefault("aliyun_logs_access", LogFilePath)
}
func DebugConfig() {
for i := range config.HistorySort {
k := config.HistorySort[i]
v, ok := config.History[k]
if !ok {
continue
}
log.Debug(fmt.Sprintf("【load config】 %v=%v", k, v))
}
}
... ...
package constant
import (
"github.com/astaxie/beego"
)
var config = NewConfigLoader()
type ConfigLoader struct {
History map[string]interface{}
HistorySort []string
}
func NewConfigLoader() *ConfigLoader {
return &ConfigLoader{
History: make(map[string]interface{}),
HistorySort: make([]string, 0),
}
}
func (c *ConfigLoader) String(key string) (ret string, ok bool) {
if ret = beego.AppConfig.String(key); len(ret) != 0 {
ok = true
c.SetHistory(key, ret)
return
}
return
}
func (c *ConfigLoader) StringDefault(key string, defaultValue string) string {
if ret, ok := c.String(key); ok {
return ret
}
return defaultValue
}
func (c *ConfigLoader) SetHistory(key string, value interface{}) {
if _, ok := c.History[key]; !ok {
c.History[key] = value
c.HistorySort = append(c.HistorySort, key)
}
}
... ...
package constant
import "fmt"
var MYSQL_DB_NAME = "mmm_open_dev"
var MYSQL_USER = "root"
var MYSQL_PASSWORD = "sutianxia2018"
var MYSQL_HOST = "101.37.68.23"
var MYSQL_PORT = "3306"
var MYSQL_DATA_SOURCE = ""
var MYSQL_MAX_IDLE = 100
var MYSQL_MAX_OPEN = 100
func init() {
MYSQL_USER = config.StringDefault("MYSQL_USER", MYSQL_USER)
MYSQL_PASSWORD = config.StringDefault("MYSQL_PASSWORD", MYSQL_PASSWORD)
MYSQL_HOST = config.StringDefault("MYSQL_HOST", MYSQL_HOST)
MYSQL_PORT = config.StringDefault("MYSQL_PORT", MYSQL_PORT)
MYSQL_DB_NAME = config.StringDefault("MYSQL_DB_NAME", MYSQL_DB_NAME)
MYSQL_DATA_SOURCE = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?loc=Asia%%2FShanghai&charset=utf8mb4",
MYSQL_USER,
MYSQL_PASSWORD,
MYSQL_HOST,
MYSQL_PORT,
MYSQL_DB_NAME,
)
}
... ...
package constant
var (
RegionID = "cn-shanghai"
AccessKeyID string = "LTAI4FhiZ3UktC6N1u3H5GFC"
AccessKeySecret string = "UyspWwdni55CYQ02hUCint4qY2jNYO"
CName string = "https://media.goexample.live/"
)
func init() {
AccessKeyID = config.StringDefault("AccessKeyID", AccessKeyID)
AccessKeySecret = config.StringDefault("AccessKeySecret", AccessKeySecret)
CName = config.StringDefault("cname", CName)
}
... ...
package protocol
package domain
const RelateSplit = "/"
... ...
package protocol
package domain
import (
"encoding/json"
"fmt"
)
var (
ERR_DB_NOT_FOUND = fmt.Errorf("db:not found")
)
//CustomErrParse 解析自定义错误结构体
... ...
package protocol
package domain
import (
"fmt"
... ...
package protocol
package domain
var errmessge ErrorMap = map[int]string{
0: "成功",
... ...
package domain
/*PushInfo 推送信息*/
type PushInfoOriginalRequest struct {
Type int `json:"msgType"`
ClientIdList []string `json:"clientId"`
AppKey string `json:"appKey" valid:"Required"`
Secret string `json:"secret" valid:"Required"`
AppId string `json:"appId" valid:"Required"`
Title string `json:"title" valid:"Required"`
Content string `json:"content" valid:"Required"`
Ext map[string]interface{} `json:"ext"` //key->transData:透传数据
}
type PushInfoResponse struct {
}
/*PushInfo 推送信息*/
type PushInfoRequest struct {
Type int `json:"msgType"`
Receivers []int64 `json:"receivers"` //接受用户id列表
ProjectKey string `json:"project"` //ability
Title string `json:"title" valid:"Required"`
Content string `json:"content" valid:"Required"`
Ext map[string]interface{} `json:"ext"` //key->transData:透传数据
}
/*UpdateDevice 更新设备*/
type UpdateDeviceRequest struct {
Muid int64 `json:"muid" valid:"Required;"` //企业平台中的用户 UID
ClientId string `json:"clientId" valid:"Required"`
DeviceToken string `json:"deviceToken"`
}
type UpdateDeviceResponse struct {
}
//设备信息
type Device struct {
Uid int64
ClientId string
DeviceToken string
}
//应用信息
type AppInfo struct {
Id int
AppKey string
AppMasterSecret string
AppId string
ProjectName string
ProjectKey string
}
... ...
package protocol
package domain
import "mime/multipart"
... ... @@ -10,7 +10,6 @@ const (
/*Image */
type FileRequest struct {
//Xxx string`json:"xxx" valid:"Required"`
Files []*multipart.FileHeader
FileType string
}
... ...
package aliyun
import "github.com/astaxie/beego"
var (
RegionID = "cn-shanghai"
AccessKeyID = beego.AppConfig.String("AccessKeyID")
AccessKeySecret = beego.AppConfig.String("AccessKeySecret")
//RegionID = "cn-shanghai"
//AccessKeyID = beego.AppConfig.String("AccessKeyID")
//AccessKeySecret = beego.AppConfig.String("AccessKeySecret")
)
const (
... ...
... ... @@ -9,7 +9,8 @@ import (
"gitlab.fjmaimaimai.com/mmm-go/gocomm/common"
"gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/log"
comm_time "gitlab.fjmaimaimai.com/mmm-go/gocomm/time"
"openapi/internal/utils"
"openapi/pkg/constant"
"openapi/pkg/infrastructure/utils"
"path"
"path/filepath"
"time"
... ... @@ -17,13 +18,13 @@ import (
//客户端
func DefaultVodClient() (client *vod.Client, err error) {
return InitVodClient(AccessKeyID, AccessKeySecret)
return InitVodClient(constant.AccessKeyID, constant.AccessKeySecret)
}
//初始化客户端
func InitVodClient(accessKeyId string, accessKeySecret string) (client *vod.Client, err error) {
// 点播服务接入区域
regionId := RegionID
regionId := constant.RegionID
// 创建授权对象
credential := &credentials.AccessKeyCredential{
accessKeyId,
... ... @@ -73,7 +74,7 @@ func RefreshUploadVideo(client *vod.Client, r *RefreshUploadVideoRequest) (respo
if up, e := ParseUploadAddress(rsp.UploadAddress); e != nil {
log.Error(e)
} else {
response.FileURL = up.GetFileUrl(beego.AppConfig.String("cname"))
response.FileURL = up.GetFileUrl(constant.CName)
}
return
}
... ...
package bgorm
import (
"github.com/astaxie/beego/orm"
_ "github.com/go-sql-driver/mysql"
"openapi/pkg/constant"
_ "openapi/pkg/infrastructure/bgorm/model"
)
func init() {
aliasName := "default"
_ = orm.RegisterDataBase(aliasName, "mysql", constant.MYSQL_DATA_SOURCE)
orm.SetMaxIdleConns(aliasName, constant.MYSQL_MAX_IDLE)
orm.SetMaxOpenConns(aliasName, constant.MYSQL_MAX_OPEN)
}
... ...
package models
import (
"errors"
"fmt"
"reflect"
"strings"
"github.com/astaxie/beego/orm"
)
type PushAppInfo struct {
Id int `orm:"column(id);auto" description:"编号"`
AppKey string `orm:"column(app_key);size(255);null" description:"推送key "`
AppMasterSecret string `orm:"column(app_master_secret);size(255);null" description:"推送服务端密钥"`
AppId string `orm:"column(app_id);size(255);null" description:"推送应用编号"`
ProjectName string `orm:"column(project_name);size(255);null" description:"项目名称 能力展示"`
ProjectKey string `orm:"column(project_key);size(255);null" description:"项目唯一标识 ability"`
}
func (t *PushAppInfo) TableName() string {
return "push_app_info"
}
func init() {
orm.RegisterModel(new(PushAppInfo))
}
// AddPushAppInfo insert a new PushAppInfo into database and returns
// last inserted Id on success.
func AddPushAppInfo(m *PushAppInfo) (id int64, err error) {
o := orm.NewOrm()
id, err = o.Insert(m)
return
}
// GetPushAppInfoById retrieves PushAppInfo by Id. Returns error if
// Id doesn't exist
func GetPushAppInfoById(id int) (v *PushAppInfo, err error) {
o := orm.NewOrm()
v = &PushAppInfo{Id: id}
if err = o.Read(v); err == nil {
return v, nil
}
return nil, err
}
// GetAllPushAppInfo retrieves all PushAppInfo matches certain condition. Returns empty list if
// no records exist
func GetAllPushAppInfo(query map[string]string, fields []string, sortby []string, order []string,
offset int64, limit int64) (ml []interface{}, err error) {
o := orm.NewOrm()
qs := o.QueryTable(new(PushAppInfo))
// query k=v
for k, v := range query {
// rewrite dot-notation to Object__Attribute
k = strings.Replace(k, ".", "__", -1)
if strings.Contains(k, "isnull") {
qs = qs.Filter(k, (v == "true" || v == "1"))
} else {
qs = qs.Filter(k, v)
}
}
// order by:
var sortFields []string
if len(sortby) != 0 {
if len(sortby) == len(order) {
// 1) for each sort field, there is an associated order
for i, v := range sortby {
orderby := ""
if order[i] == "desc" {
orderby = "-" + v
} else if order[i] == "asc" {
orderby = v
} else {
return nil, errors.New("Error: Invalid order. Must be either [asc|desc]")
}
sortFields = append(sortFields, orderby)
}
qs = qs.OrderBy(sortFields...)
} else if len(sortby) != len(order) && len(order) == 1 {
// 2) there is exactly one order, all the sorted fields will be sorted by this order
for _, v := range sortby {
orderby := ""
if order[0] == "desc" {
orderby = "-" + v
} else if order[0] == "asc" {
orderby = v
} else {
return nil, errors.New("Error: Invalid order. Must be either [asc|desc]")
}
sortFields = append(sortFields, orderby)
}
} else if len(sortby) != len(order) && len(order) != 1 {
return nil, errors.New("Error: 'sortby', 'order' sizes mismatch or 'order' size is not 1")
}
} else {
if len(order) != 0 {
return nil, errors.New("Error: unused 'order' fields")
}
}
var l []PushAppInfo
qs = qs.OrderBy(sortFields...)
if _, err = qs.Limit(limit, offset).All(&l, fields...); err == nil {
if len(fields) == 0 {
for _, v := range l {
ml = append(ml, v)
}
} else {
// trim unused fields
for _, v := range l {
m := make(map[string]interface{})
val := reflect.ValueOf(v)
for _, fname := range fields {
m[fname] = val.FieldByName(fname).Interface()
}
ml = append(ml, m)
}
}
return ml, nil
}
return nil, err
}
// UpdatePushAppInfo updates PushAppInfo by Id and returns error if
// the record to be updated doesn't exist
func UpdatePushAppInfoById(m *PushAppInfo) (err error) {
o := orm.NewOrm()
v := PushAppInfo{Id: m.Id}
// ascertain id exists in the database
if err = o.Read(&v); err == nil {
var num int64
if num, err = o.Update(m); err == nil {
fmt.Println("Number of records updated in database:", num)
}
}
return
}
// DeletePushAppInfo deletes PushAppInfo by Id and returns error if
// the record to be deleted doesn't exist
func DeletePushAppInfo(id int) (err error) {
o := orm.NewOrm()
v := PushAppInfo{Id: id}
// ascertain id exists in the database
if err = o.Read(&v); err == nil {
var num int64
if num, err = o.Delete(&PushAppInfo{Id: id}); err == nil {
fmt.Println("Number of records deleted in database:", num)
}
}
return
}
... ...
package models
import (
"time"
"github.com/astaxie/beego/orm"
)
type PushDeviceInfo struct {
Id int `orm:"column(id);auto"`
Uid int64 `orm:"column(uid);null" description:"企业平台用户id (muid)"`
ClientId string `orm:"column(client_id);size(100);null" description:"设备识别码 推送标识"`
DeviceToken string `orm:"column(device_token);size(100);null" description:"设备识别码 推送标识"`
CreateAt time.Time `orm:"column(create_at);type(timestamp);null" description:"创建时间"`
UpdateAt time.Time `orm:"column(update_at);type(timestamp);null" description:"更新时间"`
}
func (t *PushDeviceInfo) TableName() string {
return "push_device_info"
}
func init() {
orm.RegisterModel(new(PushDeviceInfo))
}
... ...
package push
/*
PushType 推送类型
*/
const (
PushToSingle = iota + 1 //单推
PushToList //群推
)
/*
MsgType 消息类型 -> 决定发送的模板样式
*/
const (
SystemTransmission = iota //系统消息透传
SystemNotification //系统通知
)
... ...
package getui
import (
"crypto/sha256"
"fmt"
"github.com/astaxie/beego/httplib"
"gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/log"
"openapi/pkg/infrastructure/push"
"openapi/pkg/infrastructure/utils"
"strings"
"sync"
"time"
)
const (
host = "https://restapi.getui.com"
pushSingle = "push_single"
saveListBody = "save_list_body"
pushList = "push_list"
authSign = "auth_sign "
)
var (
authtoken = ""
expire time.Time
authMux sync.RWMutex
expireSpan = time.Second * 600 //token 10分钟过期
)
const (
error_not_auth = "not_auth"
)
//GetuiNotification 个推消息推送
type GetuiNotification struct {
Options *push.Options
Request *httplib.BeegoHTTPRequest
retry int
}
func (notify *GetuiNotification) Init(options ...push.Option) error {
notify.Options = &push.Options{}
for _, o := range options {
o(notify.Options)
}
notify.retry = 3
return nil
}
func (notify *GetuiNotification) Send(option map[string]interface{}) (err error) {
retry := 1
for {
switch notify.Options.PushType {
case push.PushToSingle:
err = notify.pushToSingle(option)
case push.PushToList:
err = notify.pushToList(option)
default:
err = notify.pushToSingle(option)
}
if err == nil {
break
}
//重试
if err != nil && retry > notify.retry {
return err
}
log.Error(fmt.Sprintf("【个推】 重试:%v 失败:%v", retry, err))
retry++
if retry > notify.retry {
break
}
}
return nil
}
//pushToSingle 单推
func (notify *GetuiNotification) pushToSingle(option map[string]interface{}) (err error) {
var token string
if token, err = notify.GetAuthToken(); err != nil {
return err
}
var (
result *Result
url = notify.Url(notify.Options.AppId, pushSingle)
m = notify.Message(pushSingle)
)
notify.Request = httplib.Post(url)
notify.Request.Header("authtoken", token)
notify.Request.JSONBody(m)
if err = notify.Request.ToJSON(&result); err != nil {
return err
}
notify.print(url, m, result, result)
if err = handleResult(url, result); err != nil {
return err
}
return nil
}
//pushToList 群推
//步骤1.获取token
//步骤2.save_list_body保存消息共同体
//步骤3.push_list
func (notify *GetuiNotification) pushToList(option map[string]interface{}) (err error) {
var (
token string
taskId string
)
if token, err = notify.GetAuthToken(); err != nil {
return err
}
if taskId, err = notify.saveListBody(token, option); err != nil {
return err
}
var (
result *Result
url = notify.Url(notify.Options.AppId, pushList)
m = struct {
Cid []string `json:"cid"`
TaskId string `json:"taskid"`
NeedDetail bool `json:"need_detail"`
}{
Cid: notify.Options.ClientIds,
TaskId: taskId,
NeedDetail: true,
}
)
notify.Request = httplib.Post(url)
notify.Request.Header("authtoken", token)
notify.Request.JSONBody(m)
if err = notify.Request.ToJSON(&result); err != nil {
return err
}
notify.print(url, m, result, result)
if err = handleResult(url, result); err != nil {
return err
}
return nil
}
//saveListBody 保存消息共同体
func (notify *GetuiNotification) saveListBody(token string, option map[string]interface{}) (taskId string, err error) {
var (
result *Result
url = notify.Url(notify.Options.AppId, saveListBody)
m = notify.Message(saveListBody)
)
notify.Request = httplib.Post(url)
notify.Request.Header("authtoken", token)
notify.Request.JSONBody(m)
if err = notify.Request.ToJSON(&result); err != nil {
return
}
notify.print(url, m, result, result)
if err = handleResult(url, result); err != nil {
return
}
taskId = result.TaskId
return
}
//Message 组装消息体
func (notify *GetuiNotification) Message(method string) interface{} {
var m interface{}
switch notify.Options.MsgType {
case push.SystemNotification:
t := NewNotificationTemplate(notify.Options)
if method == saveListBody {
t.ClientId = ""
t.RequestId = ""
}
m = t
break
case push.SystemTransmission:
t := NewTransmissionTemplate(notify.Options)
if method == saveListBody {
t.ClientId = ""
t.RequestId = ""
}
m = t
break
default:
m = NewNotificationTemplate(notify.Options)
break
}
return m
}
//Url 组装请求地址
func (notify *GetuiNotification) Url(param string, method string) string {
return fmt.Sprintf("%v/v1/%v/%v", host, param, method)
}
//GetAuthToken 获取token
func (notify *GetuiNotification) GetAuthToken() (token string, err error) {
if authtoken != "" && expire.Unix() > time.Now().Unix() {
token = authtoken
return
}
authMux.Lock()
defer authMux.Unlock()
url := notify.Url(notify.Options.AppId, authSign)
notify.Request = httplib.Post(strings.TrimSpace(url))
req := &AuthSignRequest{
Timestamp: fmt.Sprintf("%v", time.Now().Unix()*1000), //"1589797286000",//
AppKey: notify.Options.AppKey,
}
req.Sign = sign(req.AppKey, req.Timestamp, notify.Options.AppMasterSecret)
_, err = notify.Request.JSONBody(req)
if err != nil {
return
}
var rsp *AuthSignResponse
err = notify.Request.ToJSON(&rsp)
notify.print(url, req, rsp, rsp.Result)
if err != nil {
return
}
if err = handleResult(url, rsp.Result); err != nil {
return
}
authtoken = rsp.AuthToken
token = rsp.AuthToken
expire = time.Now().Add(expireSpan)
log.Info(fmt.Sprintf("【个推】token:%v expire:%v", token, expire))
return
}
//打印日志 debug_module=true print debug log
func (notify *GetuiNotification) print(url string, v interface{}, rsp interface{}, result *Result) {
if !notify.Options.DebugModule {
return
}
log.Error(fmt.Sprintf("【个推】 url:%v \n request:%v \n response:%v 结果:%v", url, utils.JsonAssertString(v), utils.JsonAssertString(rsp), result.Result))
}
//处理结果
func handleResult(url string, result *Result) (err error) {
if strings.ToLower(result.Result) == "ok" {
return
}
switch result.Result {
case error_not_auth:
setToken("")
break
}
err = fmt.Errorf("grequest fail,url:%v error:%v", url, result.Result)
return err
}
func sign(appkey, timestamp, mastersecret string) string {
sha := sha256.New()
sha.Write([]byte(appkey + timestamp + mastersecret))
return fmt.Sprintf("%x", sha.Sum(nil))
}
func setToken(token string) {
authMux.Lock()
defer authMux.Unlock()
authtoken = ""
}
... ...
package getui
import (
"openapi/pkg/infrastructure/push"
"openapi/pkg/infrastructure/utils"
"testing"
)
func TestGetui(t *testing.T) {
var param = make(map[string]interface{})
param["A"] = "A1"
param["B"] = 2
param["transData"] = struct{ Id int }{Id: 10}
notification := &GetuiNotification{}
err := notification.Init(
push.DebugModule(true),
push.AppId("TkpBI4awmg9fBUx3NWKXS6"),
push.AppKey("5AjJeDOSOZ5ojQpXJFjhg9"),
push.AppMasterSecret("9VnM8MaA6n84Y5VnOIaSvA"),
//单推
push.PushType(push.PushToSingle),
push.ClientId("b5fff5f6b0af551da5f381fa47991828"),
//群推
//push.PushType(push.PushToList),
//push.ClientIds([]string{"b5fff5f6b0af551da5f381fa47991828"}),
push.MsgType(push.SystemTransmission), //push.SystemNotification
push.Title("测试 hello"),
push.Content("hello content"),
push.TransmissionContent(utils.JsonAssertString(param["transData"])),
push.Extra(param),
)
if err != nil {
t.Fatal(err)
}
err = notification.Send(param)
if err != nil {
t.Fatal(err)
}
}
func TestGetuiPrd(t *testing.T) {
var param = make(map[string]interface{})
param["A"] = "A1"
param["B"] = 2
param["transData"] = struct {
Id int `json:"id"`
}{Id: 1}
notification := &GetuiNotification{}
err := notification.Init(
push.DebugModule(true),
push.AppId("WgrbaaStTk7JElrXOCgUg6"),
push.AppKey("FG5lbqVrHa5rS9NVfxNP7"),
push.AppMasterSecret("FW3jMNLJrRARYKv2iqA5H5"),
//单推
//push.PushType(push.PushToSingle),
//push.ClientId("502f4fd7ba5df15ac6b3d5c561efd9ca"),
//群推
push.PushType(push.PushToList),
push.ClientIds([]string{"502f4fd7ba5df15ac6b3d5c561efd9ca"}),
push.MsgType(push.SystemTransmission),
push.Title("hello"),
push.Content("hello content"),
push.TransmissionContent(utils.JsonAssertString(param["transData"])),
push.Extra(param),
)
if err != nil {
t.Fatal(err)
}
err = notification.Send(param)
if err != nil {
t.Fatal(err)
}
}
... ...
package getui
import (
"gitlab.fjmaimaimai.com/mmm-go/gocomm/identity/uid"
"openapi/pkg/infrastructure/push"
)
//1.消息模板
type NotificationTemplate struct {
*Template
Notification *Notification `json:"notification"`
}
//1.新建通知模板
func NewNotificationTemplate(options *push.Options) *NotificationTemplate {
return &NotificationTemplate{
Template: NewTemplate(options),
Notification: &Notification{
Style: (&Style{}).SetStyle0(options),
Transmission: NewTransmission(options),
},
}
}
//2.透传模板
type TransmissionTemplate struct {
*Template
Transmission *Transmission `json:"transmission"`
PushInfo *PushInfo `json:"push_info"`
}
//2.新建透传模板
func NewTransmissionTemplate(options *push.Options) *TransmissionTemplate {
return &TransmissionTemplate{
Template: NewTemplate(options),
Transmission: NewTransmission(options),
PushInfo: NewPushInfo(options),
}
}
type Template struct {
ClientId string `json:"cid,omitempty"`
RequestId string `json:"requestid,omitempty"`
Message *Message `json:"message"`
}
type Notification struct {
Style *Style `json:"style"`
*Transmission
}
type Message struct {
AppKey string `json:"appkey"`
IsOffline bool `json:"is_offline"`
MsgType string `json:"msgtype"`
}
//透传
type Transmission struct {
TransmissionType bool `json:"transmission_type"` //收到消息是否立即启动应用,true为立即启动,false则广播等待启动,默认是否
TransmissionContent string `json:"transmission_content,omitempty"` //透传内容
DurationBegin string `json:"duration_begin,omitempty"`
DurationEnd string `json:"duration_end,omitempty"`
}
func (o *Transmission) SetTransmissionType(t bool) {
o.TransmissionType = t
}
func (o *Transmission) SetTransmissionContent(s string) {
o.TransmissionContent = s
}
func (o *Transmission) SetDuration(begin, end string) {
o.DurationBegin = begin
o.DurationEnd = end
}
func NewTemplate(options *push.Options) *Template {
return &Template{
Message: NewMessage(options),
ClientId: options.ClientId,
RequestId: genRequestId(),
}
}
func NewTransmission(options *push.Options) *Transmission {
t := &Transmission{}
if len(options.TransmissionContent) == 0 {
//t.SetTransmissionType(false)
return t
}
t.SetTransmissionType(false)
t.SetTransmissionContent(options.TransmissionContent)
return t
}
func NewMessage(options *push.Options) *Message {
return &Message{
AppKey: options.AppKey,
IsOffline: true,
MsgType: resolveMsgType(options.MsgType),
}
}
func resolveMsgType(msgType int) string {
/*
消息应用类型,
可选项:notification、link、notypopload、startactivity, transmission
*/
switch msgType {
case push.SystemNotification:
return "notification"
case push.SystemTransmission:
return "transmission"
}
return "notification"
}
func genRequestId() string {
return uid.NewV1().StringNoDash()
}
//样式 0:系统样式 1:个推样式 4:纯图样式 6:展开通知样式
type Style struct {
Type int `json:"type"` //样式类型
Text string `json:"text"` //通知内容
Title string `json:"title"` //通知标题
Logo string `json:"logo,omitempty"` //通知的图标名称,包含后缀名(需要在客户端开发时嵌入),如“push.png”
//IsRing bool `json:"is_ring"` //收到通知是否响铃:true响铃,false不响铃。默认响铃
//IsVibrate bool `json:"is_vibrate"` //收到通知是否振动:true振动,false不振动。默认振动
NotifyId int `json:"notify_id"` //需要被覆盖的消息已经增加了notifyId字段,用于实现下发消息的覆盖。新的消息使用相同的notifyId下发。
}
//设置默认样式 0
func (s *Style) SetStyle0(options *push.Options) *Style {
s.Type = 0
s.Title = options.Title
s.Text = options.Content
s.Logo = "push.png" //TODO:设置Logo地址
s.NotifyId = 1
return s
}
//认证请求/应答
type AuthSignRequest struct {
Sign string `json:"sign"`
Timestamp string `json:"timestamp"`
AppKey string `json:"appkey"`
}
type AuthSignResponse struct {
*Result
AuthToken string `json:"auth_token"`
}
//应答结果
type Result struct {
Result string `json:"result"`
TaskId string `json:"taskid"`
Status string `json:"status"`
Desc string `json:"desc"`
}
//透传附加的推送信息
func NewPushInfo(options *push.Options) (v *PushInfo) {
v = &PushInfo{
Aps: NewAps(options),
}
return
}
func NewAps(options *push.Options) (v *Aps) {
v = &Aps{
Alert: NewAlert(options),
AutoBadge: "+1",
ContentAvailable: 1,
}
return
}
func NewAlert(options *push.Options) (v *Alert) {
v = &Alert{
Title: options.Title,
Body: options.Content,
}
return
}
type PushInfo struct {
Aps *Aps `json:"aps"`
}
type Aps struct {
Alert *Alert `json:"alert"`
AutoBadge string `json:"autoBadge"` //用于计算应用上面未读数字
ContentAvailable int `json:"content-available"` //推送直接带有透传数据 0:有通知栏消息 1:无通知栏消息
Payload string `json:"payload,omitempty"`
}
type Alert struct {
Title string `json:"title"`
Body string `json:"body"`
}
... ...
package push
type Options struct {
AppId string
AppKey string
AppSecret string
AppMasterSecret string
ClientId string
ClientIds []string
MsgType int //消息类型
PushType int //推送类型
Title string
Content string
Extra interface{} //扩展数据
TransmissionContent string //透传内容
DebugModule bool
}
type Option func(o *Options)
//个推appId
func AppId(id string) Option {
return func(o *Options) {
o.AppId = id
}
}
//个推appKey
func AppKey(key string) Option {
return func(o *Options) {
o.AppKey = key
}
}
//个推appSecret
func AppSecret(secret string) Option {
return func(o *Options) {
o.AppSecret = secret
}
}
//个推appMasterSecret
func AppMasterSecret(secret string) Option {
return func(o *Options) {
o.AppMasterSecret = secret
}
}
//个推 app clientId
func ClientId(clientId string) Option {
return func(o *Options) {
o.ClientId = clientId
}
}
func ClientIds(clientId []string) Option {
return func(o *Options) {
o.ClientIds = clientId
}
}
//消息类型
func MsgType(msgType int) Option {
return func(o *Options) {
o.MsgType = msgType
}
}
//推送类型
func PushType(pushType int) Option {
return func(o *Options) {
o.PushType = pushType
}
}
//消息内容
func Title(title string) Option {
return func(o *Options) {
o.Title = title
}
}
func Content(content string) Option {
return func(o *Options) {
o.Content = content
}
}
func Extra(extra interface{}) Option {
return func(o *Options) {
o.Extra = extra
}
}
func TransmissionContent(content string) Option {
return func(o *Options) {
o.TransmissionContent = content
}
}
func DebugModule(module bool) Option {
return func(o *Options) {
o.DebugModule = module
}
}
const (
Message = iota + 1
Notification
)
... ...
package push
type INotification interface {
Init(option ...Option) error
Send(option map[string]interface{}) error
}
... ...
package umeng
const (
Android = iota + 1
IPhone
IPad
)
const (
ProjectDefault = "default"
)
var UMAppAuths UMAppAuth
func init() {
UMAppAuths = map[string]*AppAuth{
ProjectDefault: NewAppAuth(ProjectDefault).
AddAuth(Android, Auth{}).
AddAuth(IPhone, Auth{}),
}
}
type UMAppAuth map[string]*AppAuth
func (a UMAppAuth) DefaultAppAuth() *AppAuth {
return a.GetAppAuth(ProjectDefault)
}
func (a UMAppAuth) GetAppAuth(appName string) *AppAuth {
if auth, ok := a[appName]; ok {
return auth
}
return a.GetAppAuth(ProjectDefault)
}
type AppAuth struct {
AppName string //app名称
AppAuthMap map[int]Auth //android ios ipad
}
//新建
func NewAppAuth(appName string) *AppAuth {
return &AppAuth{
AppName: appName,
AppAuthMap: make(map[int]Auth),
}
}
//添加凭证
func (a *AppAuth) AddAuth(t int, auth Auth) *AppAuth {
if _, ok := a.AppAuthMap[t]; !ok {
a.AppAuthMap[t] = auth
}
return a
}
//凭证
type Auth struct {
AppKey string //应用唯一标识
AppMasterSecret string //服务器秘钥,用于服务器端调用API请求时对发送内容做签名验证
}
... ...
package umeng
import (
"crypto/md5"
"encoding/json"
"fmt"
"github.com/astaxie/beego/httplib"
"io/ioutil"
"net/http"
"openapi/pkg/infrastructure/push"
"strings"
"time"
)
var (
Host = "http://msg.umeng.com"
ApiSend = "/api/send"
UploadPath = "/upload"
)
var FiledErrorFormat = "缺少字段:%v"
var FiledErrorFormatFunc = func(filed string) error {
return fmt.Errorf(FiledErrorFormat, filed)
}
const (
AppKey = "appkey"
Timestamp = "timestamp"
Type = "type"
ProductionMode = "production_mode"
DeviceTokens = "device_tokens"
Payload = "payload"
Policy = "policy"
Description = "description"
DisplayType = "displayType"
Body = "body"
Ticker = "ticker" // 必填,通知栏提示文字
Title = "title" // 必填,通知标题
Text = "text" //必填,通知文字描述
/*
// 可选,默认为"go_app",值可以为:
// "go_app": 打开应用
// "go_url": 跳转到URL
// "go_activity": 打开特定的activity
// "go_custom": 用户自定义内容。
*/
AfterOpen = "after_open"
Extra = "extra"
)
const (
Message = "message"
Notification = "notification"
)
const (
ExpireSpan = time.Second * 60 * 60 * 24
)
type SetPayload func(msg *UnicastMsg, option map[string]interface{}) error
type UmengNotification struct {
Auth *Auth
Request *httplib.BeegoHTTPRequest
}
func (notify *UmengNotification) Init(options ...push.Option) error {
return nil
}
func (notify *UmengNotification) Send(option map[string]interface{}) error {
var (
setPayload SetPayload = SetAndroidPayload
body []byte
err error
httpRsp *http.Response
ret = make(map[string]interface{})
data []byte
)
if option["DeviceType"].(int) == 1 {
setPayload = SetAndroidPayload
}
if body, err = notify.PostBody(option, setPayload); err != nil {
return err
}
notify.Request = httplib.Post(notify.Url(ApiSend, body))
notify.Request.Body(body)
if httpRsp, err = notify.Request.DoRequest(); err != nil {
return err
}
data, err = ioutil.ReadAll(httpRsp.Body)
defer httpRsp.Body.Close()
if err != nil {
return err
}
if err = json.Unmarshal(data, &ret); err != nil {
return err
}
if status, ok := ret["ret"]; ok {
if strings.EqualFold(fmt.Sprintf("%v", status), "SUCCESS") {
return nil
}
return fmt.Errorf("response:%v fail", ret)
}
return fmt.Errorf("response:%v invaild", ret)
}
func (notify *UmengNotification) PostBody(option map[string]interface{}, setPayload SetPayload) (body []byte, err error) {
var postData = new(UnicastMsg)
postData.AppKey = notify.Auth.AppKey
postData.Timestamp = fmt.Sprintf("%v", time.Now().Unix())
postData.ProductionMode = fmt.Sprintf("%v", true)
postData.Type = fmt.Sprintf("%v", option[Type])
postData.DeviceTokens = fmt.Sprintf("%v", option[DeviceTokens])
postData.Policy = MsgPolicy{ExpireTime: time.Now().Add(ExpireSpan).Format("2006-01-02 15:04:05")}
if err = setPayload(postData, option); err != nil {
return
}
postData.Description = fmt.Sprintf("%v", option[Title])
if body, err = json.Marshal(postData); err != nil {
return
}
return
}
func (notify *UmengNotification) Url(method string, body []byte) string {
var url string = fmt.Sprintf("%v%v", Host, method)
sign := fmt.Sprintf("%x", md5.Sum([]byte("POST"+url+string(body)+notify.Auth.AppMasterSecret)))
url = fmt.Sprintf("%v?sign=%v", url, sign)
return url
}
type UnicastMsg struct {
AppKey string `json:"appkey"`
Timestamp string `json:"timestamp"`
Type string `json:"type"` //发送类型 单播 列播...
ProductionMode string `json:"production_mode"`
DeviceTokens string `json:"device_tokens"`
Payload MsgPayload `json:"payload"`
Policy MsgPolicy `json:"policy"`
Description string `json:"description"`
}
type MsgPayload map[string]interface{}
type MsgPolicy struct {
ExpireTime string `json:"expire_time"`
}
//设置payload
func SetAndroidPayload(msg *UnicastMsg, option map[string]interface{}) error {
msg.Payload = make(map[string]interface{})
var (
displayType string
ok bool
)
if _, ok = option[DisplayType]; !ok {
return FiledErrorFormatFunc(DisplayType)
}
displayType = option[DisplayType].(string)
switch displayType {
case Message:
break
case Notification:
var payloadBody = make(map[string]interface{})
//if _,ok =option[Title];!ok{
// return FiledErrorFormatFunc(Title)
//}
//if _,ok =option[Text];!ok{
// return FiledErrorFormatFunc(Text)
//}
//if _,ok =option[Extra];ok{
// payloadBody[Extra]=option[Extra]
//}
payloadBody[Ticker] = option[Title]
payloadBody[Title] = option[Title]
payloadBody[Text] = option[Text]
payloadBody[AfterOpen] = "go_app"
msg.Payload[Body] = payloadBody
break
default:
return FiledErrorFormatFunc(DisplayType)
break
}
return nil
}
... ...
package repository
import (
"github.com/astaxie/beego/orm"
"openapi/pkg/domain"
"openapi/pkg/infrastructure/bgorm/model"
)
type AppInfoRepository struct {
}
func (repository *AppInfoRepository) FindOne(queryOptions map[string]interface{}) (*domain.AppInfo, error) {
o := orm.NewOrm()
model := new(models.PushAppInfo)
qs := o.QueryTable(model).Filter("project_key", queryOptions["project_key"])
err := qs.One(model)
if err != nil {
return nil, err
}
return repository.transformBgormModelToDomainModel(model)
}
func (repository *AppInfoRepository) Find(queryOptions map[string]interface{}) (rsp []*domain.AppInfo, err error) {
return
}
func (repository *AppInfoRepository) transformBgormModelToDomainModel(model *models.PushAppInfo) (*domain.AppInfo, error) {
return &domain.AppInfo{
Id: model.Id,
AppKey: model.AppKey,
AppMasterSecret: model.AppMasterSecret,
AppId: model.AppId,
ProjectName: model.ProjectName,
ProjectKey: model.ProjectKey,
}, nil
}
func NewAppInfoRepository(transactionContext interface{}) (*AppInfoRepository, error) {
if transactionContext == nil {
return &AppInfoRepository{}, nil
} else {
return &AppInfoRepository{}, nil
}
}
... ...
package repository
import (
"github.com/astaxie/beego/orm"
"openapi/pkg/domain"
"openapi/pkg/infrastructure/bgorm/model"
"strings"
"time"
)
type PushDeviceRepository struct {
}
func (repository *PushDeviceRepository) Save(device *domain.UpdateDeviceRequest) error {
o := orm.NewOrm()
m := &models.PushDeviceInfo{
Uid: device.Muid,
ClientId: strings.TrimSpace(device.ClientId),
DeviceToken: strings.TrimSpace(device.DeviceToken),
CreateAt: time.Now(),
UpdateAt: time.Now(),
}
_, err := o.Insert(m)
return err
}
func (repository *PushDeviceRepository) FindOne(queryOptions map[string]interface{}) (*domain.Device, error) {
o := orm.NewOrm()
model := new(models.PushDeviceInfo)
qs := o.QueryTable(model.TableName()).Filter("uid", queryOptions["uid"])
err := qs.One(model)
if err != nil {
err = domain.ERR_DB_NOT_FOUND
return nil, err
}
return repository.transformBgormModelToDomainModel(model)
}
func (repository *PushDeviceRepository) Find(queryOptions map[string]interface{}) (rsp []*domain.Device, err error) {
o := orm.NewOrm()
model := new(models.PushDeviceInfo)
var ms []*models.PushDeviceInfo
qs := o.QueryTable(model.TableName()).Filter("uid__in", queryOptions["receivers"])
qs.All(&ms)
if len(ms) == 0 {
return
}
for i := range ms {
v, _ := repository.transformBgormModelToDomainModel(ms[i])
rsp = append(rsp, v)
}
return
}
func (repository *PushDeviceRepository) UpdateDevice(uid int64, clientId, deviceToken string) error {
o := orm.NewOrm()
_, err := o.Raw("UPDATE push_device_info SET client_id=?,device_token = ?,update_at=now() where uid=?", clientId, deviceToken, uid).Exec()
if err != nil {
return err
}
return nil
}
func (repository *PushDeviceRepository) transformBgormModelToDomainModel(model *models.PushDeviceInfo) (*domain.Device, error) {
return &domain.Device{
Uid: model.Uid,
ClientId: model.ClientId,
DeviceToken: model.DeviceToken,
}, nil
}
func NewPushDeviceRepository(transactionContext interface{}) (*PushDeviceRepository, error) {
if transactionContext == nil {
return &PushDeviceRepository{}, nil
} else {
return &PushDeviceRepository{}, nil
}
}
... ...
... ... @@ -90,6 +90,13 @@ func JsonUnmarshal(jsonData string, v interface{}) {
}
}
func JsonAssertString(v interface{}) string {
if data, e := json.Marshal(v); e == nil {
return string(data)
}
return ""
}
//深度拷贝
func DeepCopy(dst, src interface{}) error {
var buf bytes.Buffer
... ...
package log
import (
"fmt"
"gitlab.fjmaimaimai.com/mmm-go/gocomm/config"
"gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/log"
"openapi/pkg/constant"
"openapi/pkg/infrastructure/utils"
)
func init() {
log.InitLog(config.Logger{
Filename: constant.LogFilePath,
Level: fmt.Sprintf("%v", utils.ResolveLogLevel(constant.LogLevel)),
})
}
... ...
package beego
import (
_ "openapi/pkg/port/beego/routers"
)
func init() {
}
... ...
... ... @@ -7,7 +7,7 @@ import (
"fmt"
"github.com/astaxie/beego/plugins/cors"
"gitlab.fjmaimaimai.com/mmm-go/gocomm/time"
"openapi/protocol"
protocol "openapi/pkg/domain"
"strconv"
"strings"
... ...
package v1
import (
"encoding/json"
"gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/log"
push "openapi/pkg/application/push/service"
protocol "openapi/pkg/domain"
"openapi/pkg/port/beego/controllers"
)
type PushController struct {
controllers.BaseController
}
//推送信息 PushInfo
// @router /pushInfo [post]
func (this *PushController) PushInfo() {
var msg *protocol.ResponseMessage
defer func() {
this.Resp(msg)
}()
var request *protocol.PushInfoRequest
if err := json.Unmarshal(this.ByteBody, &request); err != nil {
log.Error(err)
msg = protocol.BadRequestParam(1)
return
}
if b, m := this.Valid(request); !b {
msg = m
return
}
header := controllers.GetRequestHeader(this.Ctx)
msg = protocol.NewReturnResponse(push.Notification(header, request))
}
//原生推送信息 PushInfoOriginal
// @router /pushInfoOriginal [post]
func (this *PushController) PushInfoOriginal() {
var msg *protocol.ResponseMessage
defer func() {
this.Resp(msg)
}()
var request *protocol.PushInfoOriginalRequest
if err := json.Unmarshal(this.ByteBody, &request); err != nil {
log.Error(err)
msg = protocol.BadRequestParam(1)
return
}
if b, m := this.Valid(request); !b {
msg = m
return
}
header := controllers.GetRequestHeader(this.Ctx)
msg = protocol.NewReturnResponse(push.NotificationOriginal(header, request))
}
//UpdateDevice
//@router /updateDevice [post]
func (this *PushController) UpdateDevice() {
var msg *protocol.ResponseMessage
defer func() {
this.Resp(msg)
}()
var request *protocol.UpdateDeviceRequest
if err := json.Unmarshal(this.ByteBody, &request); err != nil {
log.Error(err)
msg = protocol.BadRequestParam(1)
return
}
if b, m := this.Valid(request); !b {
msg = m
return
}
header := controllers.GetRequestHeader(this.Ctx)
msg = protocol.NewReturnResponse(push.UpdateDevice(header, request))
}
... ...
... ... @@ -3,10 +3,10 @@ package v1
import (
"encoding/json"
"gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/log"
"openapi/controllers"
"openapi/internal/aliyun"
"openapi/protocol"
"openapi/services/vod"
vod "openapi/pkg/application/vod/service"
"openapi/pkg/domain"
"openapi/pkg/infrastructure/aliyun"
"openapi/pkg/port/beego/controllers"
)
type VodController struct {
... ... @@ -16,14 +16,14 @@ type VodController struct {
//创建视频上传凭证 CreateUploadVideo
// @router /createUploadVideo [post]
func (this *VodController) CreateUploadVideo() {
var msg *protocol.ResponseMessage
var msg *domain.ResponseMessage
defer func() {
this.Resp(msg)
}()
var request *aliyun.CreateUploadVideoRequest
if err := json.Unmarshal(this.ByteBody, &request); err != nil {
log.Error(err)
msg = protocol.BadRequestParam(1)
msg = domain.BadRequestParam(1)
return
}
if b, m := this.Valid(request); !b {
... ... @@ -34,13 +34,13 @@ func (this *VodController) CreateUploadVideo() {
request.FileName = aliyun.DefaultVideoFileName
}
header := controllers.GetRequestHeader(this.Ctx)
msg = protocol.NewReturnResponse(vod.CreateUploadVideo(header, request))
msg = domain.NewReturnResponse(vod.CreateUploadVideo(header, request))
}
//创建视频上传凭证(多个) CreateUploadVideos
// @router /createUploadVideos [post]
func (this *VodController) CreateUploadVideos() {
var msg *protocol.ResponseMessage
var msg *domain.ResponseMessage
var response *aliyun.CreateUploadVideosResponse = &aliyun.CreateUploadVideosResponse{
List: make([]*aliyun.CreateUploadVideoResponse, 0),
}
... ... @@ -50,7 +50,7 @@ func (this *VodController) CreateUploadVideos() {
var request *aliyun.CreateUploadVideosRequest
if err := json.Unmarshal(this.ByteBody, &request); err != nil {
log.Error(err)
msg = protocol.BadRequestParam(1)
msg = domain.BadRequestParam(1)
return
}
if b, m := this.Valid(request); !b {
... ... @@ -60,7 +60,7 @@ func (this *VodController) CreateUploadVideos() {
header := controllers.GetRequestHeader(this.Ctx)
var err error
if len(request.Items) == 0 {
msg = protocol.BadRequestParam(2)
msg = domain.BadRequestParam(2)
}
for i := range request.Items {
r := request.Items[i]
... ... @@ -71,20 +71,20 @@ func (this *VodController) CreateUploadVideos() {
response.List = append(response.List, rsp)
}
}
msg = protocol.NewReturnResponse(response, err)
msg = domain.NewReturnResponse(response, err)
}
//刷新视频上传凭证 RefreshUploadVideo
// @router /refreshUploadVideo [post]
func (this *VodController) RefreshUploadVideo() {
var msg *protocol.ResponseMessage
var msg *domain.ResponseMessage
defer func() {
this.Resp(msg)
}()
var request *aliyun.RefreshUploadVideoRequest
if err := json.Unmarshal(this.ByteBody, &request); err != nil {
log.Error(err)
msg = protocol.BadRequestParam(1)
msg = domain.BadRequestParam(1)
return
}
if b, m := this.Valid(request); !b {
... ... @@ -92,20 +92,20 @@ func (this *VodController) RefreshUploadVideo() {
return
}
header := controllers.GetRequestHeader(this.Ctx)
msg = protocol.NewReturnResponse(vod.RefreshUploadVideo(header, request))
msg = domain.NewReturnResponse(vod.RefreshUploadVideo(header, request))
}
//创建图片上传凭证 CreateUploadImage
// @router /createUploadImage [post]
func (this *VodController) CreateUploadImage() {
var msg *protocol.ResponseMessage
var msg *domain.ResponseMessage
defer func() {
this.Resp(msg)
}()
var request *aliyun.CreateUploadImageRequest
if err := json.Unmarshal(this.ByteBody, &request); err != nil {
log.Error(err)
msg = protocol.BadRequestParam(1)
msg = domain.BadRequestParam(1)
return
}
if b, m := this.Valid(request); !b {
... ... @@ -114,13 +114,13 @@ func (this *VodController) CreateUploadImage() {
}
header := controllers.GetRequestHeader(this.Ctx)
msg = protocol.NewReturnResponse(vod.CreateUploadImage(header, request))
msg = domain.NewReturnResponse(vod.CreateUploadImage(header, request))
}
//创建图片上传凭证 CreateUploadImages
// @router /createUploadImages [post]
func (this *VodController) CreateUploadImages() {
var msg *protocol.ResponseMessage
var msg *domain.ResponseMessage
defer func() {
this.Resp(msg)
}()
... ... @@ -132,7 +132,7 @@ func (this *VodController) CreateUploadImages() {
)
if err := json.Unmarshal(this.ByteBody, &request); err != nil {
log.Error(err)
msg = protocol.BadRequestParam(1)
msg = domain.BadRequestParam(1)
return
}
if b, m := this.Valid(request); !b {
... ... @@ -141,7 +141,7 @@ func (this *VodController) CreateUploadImages() {
}
var err error
if len(request.Items) == 0 {
msg = protocol.BadRequestParam(2)
msg = domain.BadRequestParam(2)
}
header := controllers.GetRequestHeader(this.Ctx)
for i := range request.Items {
... ... @@ -153,20 +153,20 @@ func (this *VodController) CreateUploadImages() {
response.List = append(response.List, rsp)
}
}
msg = protocol.NewReturnResponse(response, err)
msg = domain.NewReturnResponse(response, err)
}
//获取视频播放地址 GetPlayInfo
// @router /getPlayInfo [post]
func (this *VodController) GetPlayInfo() {
var msg *protocol.ResponseMessage
var msg *domain.ResponseMessage
defer func() {
this.Resp(msg)
}()
var request *aliyun.GetPlayInfoRequest
if err := json.Unmarshal(this.ByteBody, &request); err != nil {
log.Error(err)
msg = protocol.BadRequestParam(1)
msg = domain.BadRequestParam(1)
return
}
if b, m := this.Valid(request); !b {
... ... @@ -174,20 +174,20 @@ func (this *VodController) GetPlayInfo() {
return
}
header := controllers.GetRequestHeader(this.Ctx)
msg = protocol.NewReturnResponse(vod.GetPlayInfo(header, request))
msg = domain.NewReturnResponse(vod.GetPlayInfo(header, request))
}
//获取视频播放凭证 GetVideoPlayAuth
// @router /getVideoPlayAuth [post]
func (this *VodController) GetVideoPlayAuth() {
var msg *protocol.ResponseMessage
var msg *domain.ResponseMessage
defer func() {
this.Resp(msg)
}()
var request *aliyun.GetVideoPlayAuthRequest
if err := json.Unmarshal(this.ByteBody, &request); err != nil {
log.Error(err)
msg = protocol.BadRequestParam(1)
msg = domain.BadRequestParam(1)
return
}
if b, m := this.Valid(request); !b {
... ... @@ -195,5 +195,5 @@ func (this *VodController) GetVideoPlayAuth() {
return
}
header := controllers.GetRequestHeader(this.Ctx)
msg = protocol.NewReturnResponse(vod.GetVideoPlayAuth(header, request))
msg = domain.NewReturnResponse(vod.GetVideoPlayAuth(header, request))
}
... ...
... ... @@ -7,7 +7,31 @@ import (
func init() {
beego.GlobalControllerRouter["openapi/controllers/v1:VodController"] = append(beego.GlobalControllerRouter["openapi/controllers/v1:VodController"],
beego.GlobalControllerRouter["openapi/pkg/port/beego/controllers/v1:PushController"] = append(beego.GlobalControllerRouter["openapi/pkg/port/beego/controllers/v1:PushController"],
beego.ControllerComments{
Method: "PushInfo",
Router: `/pushInfo`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Params: nil})
beego.GlobalControllerRouter["openapi/pkg/port/beego/controllers/v1:PushController"] = append(beego.GlobalControllerRouter["openapi/pkg/port/beego/controllers/v1:PushController"],
beego.ControllerComments{
Method: "PushInfoOriginal",
Router: `/pushInfoOriginal`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Params: nil})
beego.GlobalControllerRouter["openapi/pkg/port/beego/controllers/v1:PushController"] = append(beego.GlobalControllerRouter["openapi/pkg/port/beego/controllers/v1:PushController"],
beego.ControllerComments{
Method: "UpdateDevice",
Router: `/updateDevice`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Params: nil})
beego.GlobalControllerRouter["openapi/pkg/port/beego/controllers/v1:VodController"] = append(beego.GlobalControllerRouter["openapi/pkg/port/beego/controllers/v1:VodController"],
beego.ControllerComments{
Method: "CreateUploadImage",
Router: `/createUploadImage`,
... ... @@ -15,7 +39,7 @@ func init() {
MethodParams: param.Make(),
Params: nil})
beego.GlobalControllerRouter["openapi/controllers/v1:VodController"] = append(beego.GlobalControllerRouter["openapi/controllers/v1:VodController"],
beego.GlobalControllerRouter["openapi/pkg/port/beego/controllers/v1:VodController"] = append(beego.GlobalControllerRouter["openapi/pkg/port/beego/controllers/v1:VodController"],
beego.ControllerComments{
Method: "CreateUploadImages",
Router: `/createUploadImages`,
... ... @@ -23,7 +47,7 @@ func init() {
MethodParams: param.Make(),
Params: nil})
beego.GlobalControllerRouter["openapi/controllers/v1:VodController"] = append(beego.GlobalControllerRouter["openapi/controllers/v1:VodController"],
beego.GlobalControllerRouter["openapi/pkg/port/beego/controllers/v1:VodController"] = append(beego.GlobalControllerRouter["openapi/pkg/port/beego/controllers/v1:VodController"],
beego.ControllerComments{
Method: "CreateUploadVideo",
Router: `/createUploadVideo`,
... ... @@ -31,7 +55,7 @@ func init() {
MethodParams: param.Make(),
Params: nil})
beego.GlobalControllerRouter["openapi/controllers/v1:VodController"] = append(beego.GlobalControllerRouter["openapi/controllers/v1:VodController"],
beego.GlobalControllerRouter["openapi/pkg/port/beego/controllers/v1:VodController"] = append(beego.GlobalControllerRouter["openapi/pkg/port/beego/controllers/v1:VodController"],
beego.ControllerComments{
Method: "CreateUploadVideos",
Router: `/createUploadVideos`,
... ... @@ -39,7 +63,7 @@ func init() {
MethodParams: param.Make(),
Params: nil})
beego.GlobalControllerRouter["openapi/controllers/v1:VodController"] = append(beego.GlobalControllerRouter["openapi/controllers/v1:VodController"],
beego.GlobalControllerRouter["openapi/pkg/port/beego/controllers/v1:VodController"] = append(beego.GlobalControllerRouter["openapi/pkg/port/beego/controllers/v1:VodController"],
beego.ControllerComments{
Method: "GetPlayInfo",
Router: `/getPlayInfo`,
... ... @@ -47,7 +71,7 @@ func init() {
MethodParams: param.Make(),
Params: nil})
beego.GlobalControllerRouter["openapi/controllers/v1:VodController"] = append(beego.GlobalControllerRouter["openapi/controllers/v1:VodController"],
beego.GlobalControllerRouter["openapi/pkg/port/beego/controllers/v1:VodController"] = append(beego.GlobalControllerRouter["openapi/pkg/port/beego/controllers/v1:VodController"],
beego.ControllerComments{
Method: "GetVideoPlayAuth",
Router: `/getVideoPlayAuth`,
... ... @@ -55,7 +79,7 @@ func init() {
MethodParams: param.Make(),
Params: nil})
beego.GlobalControllerRouter["openapi/controllers/v1:VodController"] = append(beego.GlobalControllerRouter["openapi/controllers/v1:VodController"],
beego.GlobalControllerRouter["openapi/pkg/port/beego/controllers/v1:VodController"] = append(beego.GlobalControllerRouter["openapi/pkg/port/beego/controllers/v1:VodController"],
beego.ControllerComments{
Method: "RefreshUploadVideo",
Router: `/refreshUploadVideo`,
... ...
... ... @@ -2,8 +2,9 @@ package routers
import (
"github.com/astaxie/beego"
"openapi/controllers"
"openapi/controllers/v1"
"openapi/pkg/constant"
"openapi/pkg/port/beego/controllers"
"openapi/pkg/port/beego/controllers/v1"
)
var nsV1 *beego.Namespace
... ... @@ -11,8 +12,8 @@ var nsV1 *beego.Namespace
func init() {
nsV1 := beego.NewNamespace("v1",
beego.NSNamespace("vod", beego.NSBefore(controllers.AllowOption), beego.NSInclude(&v1.VodController{})),
//beego.NSNamespace("vod", beego.NSBefore(controllers.FilterComm), beego.NSBefore(controllers.AllowOption), beego.NSInclude(&v1.VodController{})),
beego.NSNamespace("push", beego.NSBefore(controllers.AllowOption), beego.NSInclude(&v1.PushController{})),
)
beego.SetStaticPath("/log", beego.AppConfig.String("aliyun_logs_access"))
beego.SetStaticPath("/log", constant.LogFilePath)
beego.AddNamespace(nsV1)
}
... ...
package push
import (
"github.com/gavv/httpexpect"
"github.com/onsi/ginkgo"
"net/http"
)
var _ = ginkgo.Describe("消息推送测试", func() {
ginkgo.Describe("消息推送测试", func() {
ginkgo.Context("", func() {
ginkgo.It("", func() {
httpExpect := httpexpect.New(ginkgo.GinkgoT(), server.URL)
body := map[string]interface{}{
"mmmType": 1,
"deviceToken": "",
"clientId": "b5fff5f6b0af551da5f381fa47991828",
"appkey": "5AjJeDOSOZ5ojQpXJFjhg9",
"secret": "9VnM8MaA6n84Y5VnOIaSvA",
"appId": "TkpBI4awmg9fBUx3NWKXS6",
"title": " hello",
"content": " hello content",
"ext": map[string]interface{}{"transData": "trans-content"},
}
httpExpect.POST("/v1/push/pushInfo").
WithJSON(body).
Expect().
Status(http.StatusOK).
JSON().
Object().
ContainsKey("code").ValueEqual("code", 0).
ContainsKey("msg").ValueEqual("msg", "成功")
})
})
})
})
... ...
package push
import (
"github.com/astaxie/beego"
"github.com/onsi/ginkgo"
"github.com/onsi/gomega"
"net/http"
"net/http/httptest"
_ "openapi/pkg/port/beego"
"testing"
)
func TestPush(t *testing.T) {
gomega.RegisterFailHandler(ginkgo.Fail)
ginkgo.RunSpecs(t, "Beego Port Config Correlations Test Case Suite")
}
var handler http.Handler
var server *httptest.Server
var _ = ginkgo.BeforeSuite(func() {
handler = beego.BeeApp.Handlers
beego.BConfig.CopyRequestBody = true
server = httptest.NewServer(handler)
})
var _ = ginkgo.AfterSuite(func() {
server.Close()
})
... ...
package vod
import (
"github.com/gavv/httpexpect"
"github.com/onsi/ginkgo"
"net/http"
)
var _ = ginkgo.Describe("创建图片上传凭证(单图片)", func() {
ginkgo.Describe("创建图片上传凭证(单图片)", func() {
ginkgo.Context("", func() {
ginkgo.It("", func() {
httpExpect := httpexpect.New(ginkgo.GinkgoT(), server.URL)
body := map[string]interface{}{
"fileName": "test.jpg",
}
httpExpect.POST("/v1/vod/createUploadImage").
WithJSON(body).
WithHeader("x-mmm-appproject", "opportunity").
Expect().
Status(http.StatusOK).
JSON().
Object().
ContainsKey("code").ValueEqual("code", 0).
ContainsKey("msg").ValueEqual("msg", "成功")
})
})
})
})
... ...
package vod
import (
"github.com/gavv/httpexpect"
"github.com/onsi/ginkgo"
"net/http"
)
var _ = ginkgo.Describe("创建图片上传凭证(多图片)", func() {
ginkgo.Describe("创建图片上传凭证(多图片)", func() {
ginkgo.Context("", func() {
ginkgo.It("", func() {
httpExpect := httpexpect.New(ginkgo.GinkgoT(), server.URL)
body := map[string]interface{}{
"items": []struct {
FileName string `json:"fileName"`
}{{FileName: "test.jpg"}},
}
httpExpect.POST("/v1/vod/createUploadImages").
WithJSON(body).
WithHeader("x-mmm-appproject", "opportunity").
Expect().
Status(http.StatusOK).
JSON().
Object().
ContainsKey("code").ValueEqual("code", 0).
ContainsKey("msg").ValueEqual("msg", "成功")
})
})
})
})
... ...
package vod
import (
"github.com/gavv/httpexpect"
"github.com/onsi/ginkgo"
"net/http"
)
var _ = ginkgo.Describe("创建视频上传凭证(单视频)", func() {
ginkgo.Describe("创建视频上传凭证(单视频)", func() {
ginkgo.Context("", func() {
ginkgo.It("", func() {
httpExpect := httpexpect.New(ginkgo.GinkgoT(), server.URL)
body := map[string]interface{}{
"fileName": "test.mp4",
}
httpExpect.POST("/v1/vod/createUploadVideos").
WithJSON(body).
WithHeader("x-mmm-appproject", "opportunity").
Expect().
Status(http.StatusOK).
JSON().
Object().
ContainsKey("code").ValueEqual("code", 0).
ContainsKey("msg").ValueEqual("msg", "成功")
})
})
})
})
... ...
package vod
import (
"github.com/gavv/httpexpect"
"github.com/onsi/ginkgo"
"net/http"
)
var _ = ginkgo.Describe("创建视频上传凭证(多视频)", func() {
ginkgo.Describe("创建视频上传凭证(多视频)", func() {
ginkgo.Context("", func() {
ginkgo.It("", func() {
httpExpect := httpexpect.New(ginkgo.GinkgoT(), server.URL)
body := map[string]interface{}{
"items": []struct {
FileName string `json:"fileName"`
}{{FileName: "test.mp4"}},
}
httpExpect.POST("/v1/vod/createUploadVideos").
WithJSON(body).
WithHeader("x-mmm-appproject", "opportunity").
Expect().
Status(http.StatusOK).
JSON().
Object().
ContainsKey("code").ValueEqual("code", 0).
ContainsKey("msg").ValueEqual("msg", "成功")
})
})
})
})
... ...
package vod
import (
"github.com/gavv/httpexpect"
"github.com/onsi/ginkgo"
"net/http"
)
var _ = ginkgo.Describe("获取播放信息测试", func() {
ginkgo.Describe("获取播放信息测试", func() {
ginkgo.Context("", func() {
ginkgo.It("", func() {
httpExpect := httpexpect.New(ginkgo.GinkgoT(), server.URL)
body := map[string]interface{}{
"videoId": "7be8e50dd65e45d285908bf28c8e94b2",
}
httpExpect.POST("/v1/vod/getPlayInfo").
WithJSON(body).
WithHeader("x-mmm-appproject", "opportunity").
Expect().
Status(http.StatusOK).
JSON().
Object().
ContainsKey("code").ValueEqual("code", 0).
ContainsKey("msg").ValueEqual("msg", "成功")
})
})
})
})
... ...
package vod
import (
"github.com/gavv/httpexpect"
"github.com/onsi/ginkgo"
"net/http"
)
var _ = ginkgo.Describe("获取播放凭证测试", func() {
ginkgo.Describe("获取播放凭证测试", func() {
ginkgo.Context("", func() {
ginkgo.It("", func() {
httpExpect := httpexpect.New(ginkgo.GinkgoT(), server.URL)
body := map[string]interface{}{
"videoId": "7be8e50dd65e45d285908bf28c8e94b2",
}
httpExpect.POST("/v1/vod/getVideoPlayAuth").
WithJSON(body).
WithHeader("x-mmm-appproject", "opportunity").
Expect().
Status(http.StatusOK).
JSON().
Object().
ContainsKey("code").ValueEqual("code", 0).
ContainsKey("msg").ValueEqual("msg", "成功")
})
})
})
})
... ...
package vod
import (
"github.com/gavv/httpexpect"
"github.com/onsi/ginkgo"
"net/http"
)
var _ = ginkgo.Describe("刷新视频上次凭证", func() {
ginkgo.Describe("刷新视频上次凭证", func() {
ginkgo.Context("", func() {
ginkgo.It("", func() {
httpExpect := httpexpect.New(ginkgo.GinkgoT(), server.URL)
body := map[string]interface{}{
"videoId": "1023bc472c69499dbe332afa785ee610",
}
httpExpect.POST("/v1/vod/refreshUploadVideo").
WithJSON(body).
WithHeader("x-mmm-appproject", "opportunity").
Expect().
Status(http.StatusOK).
JSON().
Object().
ContainsKey("code").ValueEqual("code", 0).
ContainsKey("msg").ValueEqual("msg", "成功")
})
})
})
})
... ...
package vod
import (
"github.com/astaxie/beego"
"github.com/onsi/ginkgo"
"github.com/onsi/gomega"
"net/http"
"net/http/httptest"
_ "openapi/pkg/port/beego"
"testing"
)
func TestPush(t *testing.T) {
gomega.RegisterFailHandler(ginkgo.Fail)
ginkgo.RunSpecs(t, "Beego Port Config Correlations Test Case Suite")
}
var handler http.Handler
var server *httptest.Server
var _ = ginkgo.BeforeSuite(func() {
handler = beego.BeeApp.Handlers
beego.BConfig.CopyRequestBody = true
server = httptest.NewServer(handler)
})
var _ = ginkgo.AfterSuite(func() {
server.Close()
})
... ...