mirror of
https://github.com/xxjwxc/public.git
synced 2025-09-26 20:01:19 +08:00
new
new
This commit is contained in:
49
file/file.go
Normal file
49
file/file.go
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package file
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"public/tools"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
//上传单个文件
|
||||||
|
func UploadFile(r *http.Request, w http.ResponseWriter, field, file_type string) (result bool, file_name string) {
|
||||||
|
//接受post请求
|
||||||
|
if r.Method == "POST" {
|
||||||
|
r.ParseMultipartForm(32 << 20)
|
||||||
|
file_name = GetFileName(file_type)
|
||||||
|
//开始存储文件
|
||||||
|
{
|
||||||
|
file, _, err := r.FormFile(field) //文件name
|
||||||
|
defer file.Close()
|
||||||
|
if err != nil {
|
||||||
|
result = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !tools.CheckFileIsExist(tools.GetModelPath() + "/file/" + field + "/") {
|
||||||
|
err1 := os.Mkdir(tools.GetModelPath()+"/file/"+field+"/", os.ModePerm) //创建文件夹
|
||||||
|
if err1 != nil {
|
||||||
|
result = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := os.OpenFile(tools.GetModelPath()+"/file/"+field+"/"+file_name, os.O_WRONLY|os.O_CREATE, 0666)
|
||||||
|
defer f.Close()
|
||||||
|
if err != nil {
|
||||||
|
result = false
|
||||||
|
}
|
||||||
|
io.Copy(f, file)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
result = false
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetFileName(exp string) string {
|
||||||
|
return fmt.Sprintf("%d%s.%s", tools.GetUtcTime(time.Now()), tools.GetRandomString(4), exp)
|
||||||
|
}
|
95
goleveldb/goleveldb.go
Normal file
95
goleveldb/goleveldb.go
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
package goleveldb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"../../data/config"
|
||||||
|
"../log"
|
||||||
|
"github.com/syndtr/goleveldb/leveldb"
|
||||||
|
)
|
||||||
|
|
||||||
|
var m_db *leveldb.DB = nil
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Clear();
|
||||||
|
creat()
|
||||||
|
}
|
||||||
|
|
||||||
|
func creat(){
|
||||||
|
if m_db == nil{
|
||||||
|
var err error
|
||||||
|
m_db, err = leveldb.OpenFile(config.GetLevelDbDir(), nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Print(log.Log_Error, err.Error())
|
||||||
|
m_db.Close()
|
||||||
|
m_db = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
清空数据
|
||||||
|
*/
|
||||||
|
func Clear() bool {
|
||||||
|
Close();
|
||||||
|
os.RemoveAll(config.GetLevelDbDir());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
关闭
|
||||||
|
*/
|
||||||
|
func Close(){
|
||||||
|
if m_db != nil{
|
||||||
|
m_db.Close()
|
||||||
|
m_db = nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*获取
|
||||||
|
*/
|
||||||
|
func Get(key []byte) (data []byte, err error) {
|
||||||
|
data = nil
|
||||||
|
data, err = m_db.Get(key, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
设置
|
||||||
|
*/
|
||||||
|
func Set(key, value []byte) error {
|
||||||
|
err := m_db.Put(key, value, nil)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
删除
|
||||||
|
*/
|
||||||
|
func Delete(key []byte) error {
|
||||||
|
return m_db.Delete(key, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*获取
|
||||||
|
*/
|
||||||
|
func Getkv(key string) (data []byte, err error) {
|
||||||
|
return Get([]byte(key))
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*获取
|
||||||
|
*/
|
||||||
|
func Setkv(key string, value []byte) error {
|
||||||
|
return Set([]byte(key), value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
删除
|
||||||
|
*/
|
||||||
|
func Deletekv(key string) error {
|
||||||
|
return Delete([]byte(key))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
274
message/message.go
Normal file
274
message/message.go
Normal file
@@ -0,0 +1,274 @@
|
|||||||
|
/*
|
||||||
|
消息定义接口
|
||||||
|
*/
|
||||||
|
package message
|
||||||
|
|
||||||
|
import (
|
||||||
|
"data/config"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"public/tools"
|
||||||
|
|
||||||
|
"github.com/bitly/go-simplejson"
|
||||||
|
)
|
||||||
|
|
||||||
|
const ( //消息id定义
|
||||||
|
NormalMessageId = 0 ////默认的返回值,为0,自增
|
||||||
|
ServerMaintenance = 1 //服务器维护中 请稍后再试,服务器出错会回这个信息,暂时不用
|
||||||
|
AccountDisabled = 2 //帐号被禁用
|
||||||
|
AppidOverdue = 3 //appid过期
|
||||||
|
|
||||||
|
UnknownError = 101 //未知错误
|
||||||
|
TokenFailure = 102 //token失效
|
||||||
|
HTMLSuccess = 200 //成功
|
||||||
|
BlockingAcess = 405 //禁止访问( 禁用请求中所指定的方法)
|
||||||
|
|
||||||
|
NewReport = 2001 //新消息
|
||||||
|
NewHeart = 2002 //心跳
|
||||||
|
|
||||||
|
ParameterInvalid = 1001 //参数无效
|
||||||
|
AppidParameterInvalid = 1002 //appid参数无效
|
||||||
|
EncryptCheckError = 1003 //密文校验失败
|
||||||
|
UserNameDoNotExist = 1004 //用户名不存在或密码错误
|
||||||
|
DuplicateKeyError = 1005 //键值对重复
|
||||||
|
InValidOp = 1007 //无效操作
|
||||||
|
NotFindError = 1006 //未找到
|
||||||
|
InValidAuthorize = 1008 //授权码错误
|
||||||
|
HasusedError = 1009 //已被使用
|
||||||
|
HasActvError = 1010 //已被激活
|
||||||
|
ActvFailure = 1011 //|激活码被禁止使用
|
||||||
|
UserExisted = 1012 //用户已存在
|
||||||
|
VerifyTimeError = 1013 //验证码请求过于平凡
|
||||||
|
MailSendFaild = 1014 //邮箱发送失败
|
||||||
|
SMSSendFaild = 1015 //手机发送失败
|
||||||
|
PhoneParameterError = 1016 //手机号格式有问题
|
||||||
|
VerifyError = 1017 //验证码错误
|
||||||
|
UserNotExisted = 1018 //用户不存在
|
||||||
|
TopicExisted = 1019 //topic已经存在
|
||||||
|
TopicNotExisted = 1020 //topic不存在
|
||||||
|
BundleIdNotExisted = 1021 //bundle_id不存在
|
||||||
|
TopicStartFail = 1022 //topic开启处理失败
|
||||||
|
TopicTypeNotExisted = 1023 //topic处理类型不存在
|
||||||
|
TopicIsNotNull = 1024 //topic不能为空
|
||||||
|
DeviceNotExisted = 1025 //设备不存在
|
||||||
|
StateExisted = 1027 //状态已存在
|
||||||
|
LastMenuNotExisted = 1028 //上级菜单不存在
|
||||||
|
MenuNotExisted = 1029 //菜单不存在
|
||||||
|
UserMenuNotExisted = 1030 //用户权限不存在
|
||||||
|
DeviceIdNotExisted = 1031 //设备ID不存在
|
||||||
|
GoodsDealTypeNotExisted = 1032 //商品处理类型不存在
|
||||||
|
GoodsIdNotExisted = 1033 //商品不存在
|
||||||
|
GoodsBeInDiscount = 1034 //商品正在打折
|
||||||
|
GoodsPayTypeNotExisted = 1035 //商品可支付类型不存在
|
||||||
|
GoodsIdExisted = 1036 //商品已存在
|
||||||
|
OrderIdNotExisted = 1043 //订单不存在
|
||||||
|
GoodsBeNotInDiscount = 1044 //商品未打折
|
||||||
|
NotifyIsNotMatch = 1045 //会话不匹配
|
||||||
|
GoodsIsDiscountRecovery = 1046 //商品已恢复原价
|
||||||
|
InvitationUserNotExisted = 1047 //邀请用户不存在
|
||||||
|
// InvitationUserLevelIsFull = 1048 //邀请用户级数已满
|
||||||
|
UserNotAuthorize = 1049 //用户未授权
|
||||||
|
ApplicantIsExisted = 1050 //申请人已存在
|
||||||
|
ApplicantNotExisted = 1051 //申请人不存在
|
||||||
|
CreditOrderNotVaild = 1052 //订单无效
|
||||||
|
RepeatWxWithdraw = 1053 //微信零钱重复提现
|
||||||
|
WxWithdrawAmountError = 1054 //提现金额错误
|
||||||
|
WxWithdrawError = 1055 //微信提现失败
|
||||||
|
RepeatSubmission = 1056 //重复提交
|
||||||
|
BundleExisted = 1057 //bundle已存在
|
||||||
|
AuthExisted = 1058 //权限已存在
|
||||||
|
AuthNotExisted = 1059 //权限不存在
|
||||||
|
RoomTypeNotExisted = 1060 //房型不存在
|
||||||
|
RoomTypeExisted = 1061 //房型已存在
|
||||||
|
RoomNoNotExisted = 1062 //房间不存在
|
||||||
|
RoomNoExisted = 1063 //房间已存在
|
||||||
|
RateTypeExisted = 1064 //房价代码或房价名称已存在
|
||||||
|
RateTypeNotExisted = 1065 //房价代码不存在
|
||||||
|
FileNotExisted = 1066 //文件不存在
|
||||||
|
RoomNoInvaild = 1067 //房间未启用
|
||||||
|
ClassExisted = 1068 //班次已存在
|
||||||
|
ClassNotExisted = 1069 //班次不存在
|
||||||
|
CheckTimeError = 1070 //系统时间与营业时间不匹配
|
||||||
|
CurrentClassIsShift = 1071 //当前班次已交班
|
||||||
|
PayPriceError = 1072 //支付金额错误
|
||||||
|
StockNotEnough = 1073 //存量不足
|
||||||
|
DBSaveError = 1074 //数据存储错误
|
||||||
|
DBAddError = 1075 //数据添加错误
|
||||||
|
DBUpdateError = 1076 //数据更新错误
|
||||||
|
DBDeleteError = 1077 //数据删除错误
|
||||||
|
TimeError = 1078 //时间错误
|
||||||
|
OrderInfoError = 1079 //预定信息错误
|
||||||
|
NotVaildError = 1080 //不允许
|
||||||
|
Overdue = 1081 //已过期
|
||||||
|
MaxOverError = 1082 //超过最大值
|
||||||
|
MinOverError = 1083 //低于最小值
|
||||||
|
ExistedError = 1084 //已存在
|
||||||
|
NotBindError = 1085 //未绑定
|
||||||
|
BindError = 1086 //绑定失败
|
||||||
|
)
|
||||||
|
|
||||||
|
//消息翻译
|
||||||
|
var MessageMap = map[int]string{
|
||||||
|
NormalMessageId: "",
|
||||||
|
ServerMaintenance: "服务器维护中 请稍后再试",
|
||||||
|
AccountDisabled: "帐号被禁用",
|
||||||
|
AppidOverdue: "appid过期",
|
||||||
|
|
||||||
|
UnknownError: "未知错误",
|
||||||
|
TokenFailure: "Token失效",
|
||||||
|
HTMLSuccess: "成功",
|
||||||
|
BlockingAcess: "禁止访问",
|
||||||
|
|
||||||
|
NewReport: "新消息返回",
|
||||||
|
NewHeart: "心跳消息",
|
||||||
|
|
||||||
|
ParameterInvalid: "参数无效",
|
||||||
|
AppidParameterInvalid: "授权参数无效",
|
||||||
|
EncryptCheckError: "密文校验失败",
|
||||||
|
UserNameDoNotExist: "用户名不存在或密码错误",
|
||||||
|
DuplicateKeyError: "键值对重复",
|
||||||
|
NotFindError: "未找到",
|
||||||
|
InValidOp: "无效操作",
|
||||||
|
InValidAuthorize: "授权码错误或未找到",
|
||||||
|
HasusedError: "已被使用",
|
||||||
|
HasActvError: "已被激活",
|
||||||
|
ActvFailure: "激活码被禁止使用",
|
||||||
|
UserExisted: "用户已存在",
|
||||||
|
VerifyTimeError: "验证码请求过于平凡",
|
||||||
|
MailSendFaild: "邮箱发送失败",
|
||||||
|
SMSSendFaild: "手机发送失败",
|
||||||
|
PhoneParameterError: "手机号格式有问题",
|
||||||
|
VerifyError: "验证码错误",
|
||||||
|
UserNotExisted: "用户不存在",
|
||||||
|
TopicExisted: "Topic已存在",
|
||||||
|
TopicNotExisted: "Topic不存在",
|
||||||
|
BundleIdNotExisted: "Bundle_id不存在",
|
||||||
|
TopicStartFail: "Topic开启处理失败",
|
||||||
|
TopicTypeNotExisted: "Topic处理类型不存在",
|
||||||
|
TopicIsNotNull: "Topic不能为空",
|
||||||
|
DeviceNotExisted: "设备不存在",
|
||||||
|
StateExisted: "状态已存在",
|
||||||
|
LastMenuNotExisted: "父菜单或根菜单不存在",
|
||||||
|
MenuNotExisted: "菜单不存在",
|
||||||
|
UserMenuNotExisted: "用户权限不存在",
|
||||||
|
DeviceIdNotExisted: "设备ID不存在",
|
||||||
|
GoodsDealTypeNotExisted: "商品处理类型不存在",
|
||||||
|
GoodsIdNotExisted: "商品不存在",
|
||||||
|
GoodsBeInDiscount: "商品正在折扣期",
|
||||||
|
GoodsPayTypeNotExisted: "商品可支付类型不存在",
|
||||||
|
GoodsIdExisted: "商品已存在",
|
||||||
|
OrderIdNotExisted: "订单不存在",
|
||||||
|
GoodsBeNotInDiscount: "商品未打折",
|
||||||
|
NotifyIsNotMatch: "会话不匹配",
|
||||||
|
GoodsIsDiscountRecovery: "商品已恢复原价",
|
||||||
|
InvitationUserNotExisted: "邀请用户不存在",
|
||||||
|
// InvitationUserLevelIsFull: "邀请用户级数已满",
|
||||||
|
UserNotAuthorize: "用户未授权",
|
||||||
|
ApplicantIsExisted: "申请人已存在",
|
||||||
|
ApplicantNotExisted: "申请人不存在",
|
||||||
|
CreditOrderNotVaild: "订单无效",
|
||||||
|
RepeatWxWithdraw: "微信零钱一天内多次提现",
|
||||||
|
WxWithdrawAmountError: "微信零钱提现金额错误",
|
||||||
|
WxWithdrawError: "微信零钱提现失败",
|
||||||
|
RepeatSubmission: "重复提交",
|
||||||
|
BundleExisted: "bundle已存在",
|
||||||
|
AuthExisted: "权限已存在",
|
||||||
|
AuthNotExisted: "权限不存在",
|
||||||
|
RoomTypeNotExisted: "房型不存在",
|
||||||
|
RoomTypeExisted: "房型已存在",
|
||||||
|
RoomNoNotExisted: "房间不存在",
|
||||||
|
RoomNoExisted: "房间已存在",
|
||||||
|
RateTypeExisted: "房价代码或房价名称已存在",
|
||||||
|
RateTypeNotExisted: "房价代码不存在",
|
||||||
|
FileNotExisted: "文件不存在",
|
||||||
|
RoomNoInvaild: "房间未启用",
|
||||||
|
ClassExisted: "班次已存在",
|
||||||
|
ClassNotExisted: "班次不存在",
|
||||||
|
CheckTimeError: "系统时间与营业时间不匹配",
|
||||||
|
CurrentClassIsShift: "当前班次已完成交班",
|
||||||
|
PayPriceError: "支付金额错误",
|
||||||
|
StockNotEnough: "存量不足",
|
||||||
|
DBSaveError: "数据存储错误",
|
||||||
|
DBAddError: "数据添加错误",
|
||||||
|
DBUpdateError: "数据更新错误",
|
||||||
|
DBDeleteError: "数据删除错误",
|
||||||
|
TimeError: "时间错误",
|
||||||
|
OrderInfoError: "预定信息有误",
|
||||||
|
NotVaildError: "不允许",
|
||||||
|
Overdue: "已过期",
|
||||||
|
MaxOverError: "超过最大值",
|
||||||
|
MinOverError: "低于最小值",
|
||||||
|
ExistedError: "已存在",
|
||||||
|
NotBindError: "未绑定",
|
||||||
|
BindError: "绑定失败",
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
type MessageBody struct {
|
||||||
|
State bool `json:"state"`
|
||||||
|
Code int `json:"code,omitempty"`
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
Data interface{} `json:"data,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取错误消息 参数(int,string)
|
||||||
|
func GetErrorMsg(errorCode ...interface{}) (msg MessageBody) {
|
||||||
|
if len(errorCode) == 0 {
|
||||||
|
log.Println("未知")
|
||||||
|
msg.State = false
|
||||||
|
msg.Code = -1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
msg.State = false
|
||||||
|
for _, e := range errorCode {
|
||||||
|
switch v := e.(type) {
|
||||||
|
case int:
|
||||||
|
msg.Code = int(int(v))
|
||||||
|
msg.Error = MessageMap[msg.Code]
|
||||||
|
case string:
|
||||||
|
msg.Error = string(v)
|
||||||
|
fmt.Println(v)
|
||||||
|
case interface{}:
|
||||||
|
{
|
||||||
|
if config.OnIsDev() {
|
||||||
|
msg.Error = onCheckParam(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func onCheckParam(op interface{}) string {
|
||||||
|
//过滤可不填项
|
||||||
|
b, _ := json.Marshal(op)
|
||||||
|
|
||||||
|
js, _ := simplejson.NewJson(b)
|
||||||
|
|
||||||
|
mp, _ := js.Map()
|
||||||
|
for k, v := range mp {
|
||||||
|
tmp := tools.AsString(v)
|
||||||
|
if len(tmp) > 0 && tmp != "0" { //过滤
|
||||||
|
delete(mp, k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//----------------------end
|
||||||
|
|
||||||
|
b, _ = json.Marshal(mp)
|
||||||
|
return string(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
//成功消息
|
||||||
|
func GetSuccessMsg(errorCode ...int) (msg MessageBody) {
|
||||||
|
msg.State = true
|
||||||
|
if len(errorCode) == 0 {
|
||||||
|
msg.Code = NormalMessageId
|
||||||
|
} else {
|
||||||
|
msg.Code = errorCode[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
msg.Error = MessageMap[msg.Code]
|
||||||
|
return
|
||||||
|
}
|
20
message/msg_test.go
Normal file
20
message/msg_test.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package message
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Test struct {
|
||||||
|
State bool `json:"state"`
|
||||||
|
Code int `json:"code"`
|
||||||
|
Error string `json:"error"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_sing(t *testing.T) {
|
||||||
|
var test Test
|
||||||
|
test.State = true
|
||||||
|
test.Error = ""
|
||||||
|
|
||||||
|
fmt.Println(onCheckParam(test))
|
||||||
|
}
|
53
myaes/myaes.go
Normal file
53
myaes/myaes.go
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
package myaes
|
||||||
|
|
||||||
|
import "crypto/cipher"
|
||||||
|
|
||||||
|
type Tobytes struct {
|
||||||
|
Cip cipher.Block
|
||||||
|
Pdgtext []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
//使用AES加密文本,加密的文本不能为空
|
||||||
|
func (a *Tobytes) Encrypt(src []byte) (dst []byte) {
|
||||||
|
src = a.padding(src)
|
||||||
|
dst = make([]byte, len(src))
|
||||||
|
var index int = 0
|
||||||
|
for len(src) > 0 {
|
||||||
|
a.Cip.Encrypt(dst[index:index+a.Cip.BlockSize()], src)
|
||||||
|
index += a.Cip.BlockSize()
|
||||||
|
src = src[a.Cip.BlockSize():]
|
||||||
|
}
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
//使用AES解密文本
|
||||||
|
func (a *Tobytes) Decrypt(src []byte) (dst []byte) {
|
||||||
|
if len(src)%a.Cip.BlockSize() != 0 {
|
||||||
|
return src
|
||||||
|
}
|
||||||
|
dst = make([]byte, len(src))
|
||||||
|
var index int = 0
|
||||||
|
for len(src) > 0 {
|
||||||
|
a.Cip.Decrypt(dst[index:index+a.Cip.BlockSize()], src)
|
||||||
|
index += a.Cip.BlockSize()
|
||||||
|
src = src[a.Cip.BlockSize():]
|
||||||
|
}
|
||||||
|
return a.unpadding(dst)
|
||||||
|
}
|
||||||
|
|
||||||
|
//使用AES加密文本的时候文本必须定长,即必须是16,24,32的整数倍,
|
||||||
|
func (a *Tobytes) padding(src []byte) (dst []byte) {
|
||||||
|
pdg := a.Cip.BlockSize() - len(src)%a.Cip.BlockSize()
|
||||||
|
p := a.Pdgtext[:pdg]
|
||||||
|
p[pdg-1] = byte(pdg)
|
||||||
|
return append(src, p...)
|
||||||
|
}
|
||||||
|
|
||||||
|
//使用AES解密文本,解密收删除padding的文本
|
||||||
|
func (a *Tobytes) unpadding(src []byte) (dst []byte) {
|
||||||
|
length := len(src)
|
||||||
|
if length <= 0 {
|
||||||
|
return src
|
||||||
|
}
|
||||||
|
return src[:(length - int(src[length-1]))]
|
||||||
|
}
|
35
mycache/my_test.go
Normal file
35
mycache/my_test.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package mycache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Tweet is a structure used for serializing/deserializing data in Elasticsearch.
|
||||||
|
type Tweet struct {
|
||||||
|
User string `json:"user"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
Retweets int `json:"retweets"`
|
||||||
|
Image string `json:"image,omitempty"`
|
||||||
|
Created time.Time `json:"created,omitempty"`
|
||||||
|
Tags []string `json:"tags,omitempty"`
|
||||||
|
Location string `json:"location,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_cache(t *testing.T) {
|
||||||
|
//获取
|
||||||
|
cache := OnGetCache("_cache")
|
||||||
|
var tp interface{}
|
||||||
|
tp, b := cache.Value("key")
|
||||||
|
if b {
|
||||||
|
tmp := tp.(Tweet)
|
||||||
|
fmt.Println(tmp)
|
||||||
|
} else {
|
||||||
|
var tmp Tweet
|
||||||
|
//添加
|
||||||
|
cache.Add("key", tmp, 24*time.Hour)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
77
mycache/mycache.go
Normal file
77
mycache/mycache.go
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
key/value 内存缓存,支持基于超时的自动无效功能
|
||||||
|
*/
|
||||||
|
package mycache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/muesli/cache2go"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MyCache struct {
|
||||||
|
cache *cache2go.CacheTable
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
初始化一个cache
|
||||||
|
cachename 缓存名字
|
||||||
|
*/
|
||||||
|
func OnGetCache(cachename string) (mc MyCache) {
|
||||||
|
mc.cache = cache2go.Cache(cachename)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
添加一个缓存
|
||||||
|
lifeSpan:缓存时间,0表示永不超时
|
||||||
|
*/
|
||||||
|
func (mc *MyCache) Add(key interface{}, value interface{}, lifeSpan time.Duration) *cache2go.CacheItem {
|
||||||
|
return mc.cache.Add(key, lifeSpan, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
查找一个cache
|
||||||
|
value 返回的值
|
||||||
|
*/
|
||||||
|
|
||||||
|
func (mc *MyCache) Value(key interface{}) (value interface{}, b bool) {
|
||||||
|
b = false
|
||||||
|
res, err := mc.cache.Value(key)
|
||||||
|
if err == nil {
|
||||||
|
value = res.Data()
|
||||||
|
b = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
判断key是否存在
|
||||||
|
*/
|
||||||
|
func (mc *MyCache) IsExist(key interface{}) bool {
|
||||||
|
return mc.cache.Exists(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
删除一个cache
|
||||||
|
*/
|
||||||
|
func (mc *MyCache) Delete(key interface{}) error {
|
||||||
|
_, err := mc.cache.Delete(key)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
获取原始cache2go操作类
|
||||||
|
*/
|
||||||
|
func (mc *MyCache) GetCache2go() *cache2go.CacheTable {
|
||||||
|
return mc.cache
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
清空表內容
|
||||||
|
*/
|
||||||
|
func (mc *MyCache) Clear() bool {
|
||||||
|
mc.cache.Flush()
|
||||||
|
return true
|
||||||
|
}
|
54
mycatch/mycatch.go
Normal file
54
mycatch/mycatch.go
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
错误信息日志记录(panic信息,不可度量的)
|
||||||
|
注意:每个 goroutine 开始部分都需要写上:defer mycatch.Dmp()
|
||||||
|
类似于
|
||||||
|
go func(){
|
||||||
|
defer mycatch.Dmp()
|
||||||
|
}()
|
||||||
|
*/
|
||||||
|
package mycatch
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime/debug"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Dmp() {
|
||||||
|
errstr := ""
|
||||||
|
if err := recover(); err != nil {
|
||||||
|
errstr += (fmt.Sprintf("%v\r\n", err)) //输出panic信息
|
||||||
|
errstr += ("--------------------------------------------\r\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
errstr += (string(debug.Stack())) //输出堆栈信息
|
||||||
|
OnPrintErr(errstr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func OnPrintErr(errstring string) {
|
||||||
|
file, _ := exec.LookPath(os.Args[0])
|
||||||
|
path, _ := filepath.Abs(file)
|
||||||
|
path = filepath.Dir(path)
|
||||||
|
|
||||||
|
now := time.Now() //获取当前时间
|
||||||
|
pid := os.Getpid() //获取进程ID
|
||||||
|
|
||||||
|
os.MkdirAll(path+"/err", os.ModePerm) //生成多级目录
|
||||||
|
|
||||||
|
time_str := now.Format("2006-01-02") //设定时间格式
|
||||||
|
fname := fmt.Sprintf("%s/err/panic_%s-%x.log", path, time_str, pid) //保存错误信息文件名:程序名-进程ID-当前时间(年月日时分秒)
|
||||||
|
fmt.Println("panic to file ", fname)
|
||||||
|
|
||||||
|
f, err := os.OpenFile(fname, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
f.WriteString("=========================" + now.Format("2006-01-02 15:04:05 ========================= \r\n"))
|
||||||
|
f.WriteString(errstring) //输出堆栈信息
|
||||||
|
f.WriteString("=========================end=========================")
|
||||||
|
}
|
3
mydef/mydef.go
Normal file
3
mydef/mydef.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
package mydef
|
||||||
|
|
||||||
|
type ParamsCallFunc func(...interface{})
|
59
mydraw/my_test.go
Normal file
59
mydraw/my_test.go
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
package mydraw
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"public/mydraw"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMytest(t *testing.T) {
|
||||||
|
pen, b := mydraw.OnGetPen("./luximr.ttf", 0, 0, 0, 255)
|
||||||
|
if b {
|
||||||
|
var hdc mydraw.HDC
|
||||||
|
hdc.SetBg("./src.png")
|
||||||
|
pen.Dpi = 200
|
||||||
|
pen.FontSize = 16
|
||||||
|
pen.StartPoint.X = 150
|
||||||
|
pen.StartPoint.Y = 78
|
||||||
|
hdc.DrawText(pen, "哈哈")
|
||||||
|
pen.FontSize = 12
|
||||||
|
pen.StartPoint.X = 150
|
||||||
|
pen.StartPoint.Y = 160
|
||||||
|
hdc.DrawText(pen, "男")
|
||||||
|
pen.StartPoint.X = 350
|
||||||
|
pen.StartPoint.Y = 160
|
||||||
|
hdc.DrawText(pen, "汉")
|
||||||
|
pen.StartPoint.X = 150
|
||||||
|
pen.StartPoint.Y = 240
|
||||||
|
hdc.DrawText(pen, "1996")
|
||||||
|
pen.StartPoint.X = 300
|
||||||
|
pen.StartPoint.Y = 240
|
||||||
|
hdc.DrawText(pen, "6")
|
||||||
|
pen.StartPoint.X = 370
|
||||||
|
pen.StartPoint.Y = 240
|
||||||
|
hdc.DrawText(pen, "26")
|
||||||
|
|
||||||
|
pen.StartPoint.X = 150
|
||||||
|
pen.StartPoint.Y = 275
|
||||||
|
|
||||||
|
str := []rune("北京市海淀区西北旺东路100号中关村科技园")
|
||||||
|
//str := "北京市海淀区西北旺东路100号中关村科技园"
|
||||||
|
|
||||||
|
for i := 0; i < len(str); i += 11 {
|
||||||
|
var end = i + 11
|
||||||
|
if end > len(str) {
|
||||||
|
end = len(str)
|
||||||
|
}
|
||||||
|
pen.StartPoint.Y += 40
|
||||||
|
tmp := str[i:end]
|
||||||
|
hdc.DrawText(pen, string(tmp))
|
||||||
|
}
|
||||||
|
|
||||||
|
pen.StartPoint.X = 300
|
||||||
|
pen.StartPoint.Y = 520
|
||||||
|
hdc.DrawText(pen, "310666196606266666")
|
||||||
|
|
||||||
|
b = hdc.Save("./out.png")
|
||||||
|
fmt.Println(b)
|
||||||
|
}
|
||||||
|
}
|
126
mydraw/mydraw.go
Normal file
126
mydraw/mydraw.go
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
package mydraw
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"image"
|
||||||
|
"image/color"
|
||||||
|
"image/draw"
|
||||||
|
"image/jpeg"
|
||||||
|
"image/png"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"public/mylog"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/golang/freetype"
|
||||||
|
"github.com/golang/freetype/truetype"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Pen struct {
|
||||||
|
FontSize float64
|
||||||
|
Dpi float64
|
||||||
|
Font *truetype.Font
|
||||||
|
StartPoint image.Point
|
||||||
|
Color *image.Uniform
|
||||||
|
}
|
||||||
|
|
||||||
|
type HDC struct {
|
||||||
|
//Bg image.Image
|
||||||
|
Rgba *image.RGBA
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取画笔
|
||||||
|
func OnGetPen(fontPath string, R, G, B, A uint8) (pen Pen, b bool) {
|
||||||
|
b = false
|
||||||
|
pen.Color = image.NewUniform(color.RGBA{R: R, G: G, B: B, A: A})
|
||||||
|
pen.Dpi = 72
|
||||||
|
pen.FontSize = 10
|
||||||
|
pen.StartPoint = image.Point{0, 0}
|
||||||
|
// 读字体数据
|
||||||
|
fontBytes, err := ioutil.ReadFile(fontPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
pen.Font, err = freetype.ParseFont(fontBytes)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
b = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *HDC) SetBg(imagePath string) bool {
|
||||||
|
file, _ := os.Open(imagePath)
|
||||||
|
defer file.Close()
|
||||||
|
//var err error
|
||||||
|
img, _, err := image.Decode(file)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("err = ", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Rgba = image.NewRGBA(img.Bounds())
|
||||||
|
draw.Draw(this.Rgba, this.Rgba.Bounds(), img, image.ZP, draw.Src)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *HDC) GetBgSize() (w, h int) {
|
||||||
|
b := this.Rgba.Bounds()
|
||||||
|
w = b.Max.X
|
||||||
|
h = b.Max.Y
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//图片上画文字
|
||||||
|
func (this *HDC) DrawText(pen Pen, text string) bool {
|
||||||
|
if this.Rgba == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
c := freetype.NewContext()
|
||||||
|
c.SetDPI(pen.Dpi)
|
||||||
|
c.SetFont(pen.Font)
|
||||||
|
c.SetFontSize(pen.FontSize)
|
||||||
|
c.SetClip(this.Rgba.Bounds())
|
||||||
|
c.SetDst(this.Rgba)
|
||||||
|
//c.SetSrc(image.NewUniform(color.RGBA{255, 255, 255, 255}))
|
||||||
|
c.SetSrc(pen.Color)
|
||||||
|
|
||||||
|
// Draw the text.
|
||||||
|
pt := freetype.Pt(pen.StartPoint.X, pen.StartPoint.Y+int(c.PointToFixed(pen.FontSize)>>6))
|
||||||
|
for _, s := range strings.Split(text, "\r\n") {
|
||||||
|
_, err := c.DrawString(s, pt)
|
||||||
|
if err != nil {
|
||||||
|
mylog.Println("c.DrawString(%s) error(%v)", s, err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
pt.Y += c.PointToFixed(pen.FontSize * 1.5)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
//保存图片
|
||||||
|
func (this *HDC) Save(imagePath string) bool {
|
||||||
|
output, err := os.OpenFile(imagePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
|
||||||
|
if err != nil {
|
||||||
|
mylog.Error(err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
defer output.Close()
|
||||||
|
|
||||||
|
if strings.HasSuffix(imagePath, ".png") || strings.HasSuffix(imagePath, ".PNG") {
|
||||||
|
err = png.Encode(output, this.Rgba)
|
||||||
|
} else {
|
||||||
|
err = jpeg.Encode(output, this.Rgba, nil)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
|
||||||
|
mylog.Println("image encode error(%v)", err)
|
||||||
|
//mylog.Error(err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
50
myecharts/common.go
Normal file
50
myecharts/common.go
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
package myecharts
|
||||||
|
|
||||||
|
func getDefaltOption() EcOption {
|
||||||
|
return EcOption{
|
||||||
|
XAxis: EcxAxis{Type: "category"},
|
||||||
|
YAxis: EcxAxis{Type: "value"},
|
||||||
|
Legend: EcLegend{Show: true},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置显示x轴还是y轴,且设置数据内容
|
||||||
|
//data 为轴坐标内容
|
||||||
|
func (ep *EcOption) OnSetAxis(data []string, axisLabel AxisLabel, isy bool) {
|
||||||
|
V := EcxAxis{Type: "value", AxisLabel: axisLabel}
|
||||||
|
k := EcxAxis{Type: "category", Data: data}
|
||||||
|
if isy {
|
||||||
|
ep.YAxis = k
|
||||||
|
ep.XAxis = V
|
||||||
|
} else {
|
||||||
|
ep.XAxis = k
|
||||||
|
ep.YAxis = V
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//图例组件。(顶部分类器)
|
||||||
|
func (ep *EcOption) OnSetLegend(data []string) {
|
||||||
|
ep.Legend.Data = data
|
||||||
|
ep.Legend.Show = true
|
||||||
|
}
|
||||||
|
|
||||||
|
//添加一个数据
|
||||||
|
func (ep *EcOption) OnAddOneSeries(name string, data interface{}) {
|
||||||
|
var tmp = EcSeries{Name: name, Type: ep._type, Data: data}
|
||||||
|
ep.Series = append(ep.Series, tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
//添加一个数据
|
||||||
|
func (ep *EcOption) OnAddOneSeriesInt(name string, data []int) {
|
||||||
|
var tmp []interface{}
|
||||||
|
for _, v := range data {
|
||||||
|
tmp = append(tmp, float32(v))
|
||||||
|
}
|
||||||
|
ep.OnAddOneSeries(name, tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
func (ep *EcOption) SetEcToolTip(ecToolTip EcToolTip) {
|
||||||
|
//EcToolTip{Show: true, Trigger: "axis", AxisPointer: EcAxisPointer{Type: "shadow"}}
|
||||||
|
ep.Tooltip = ecToolTip
|
||||||
|
}
|
90
myecharts/def.go
Normal file
90
myecharts/def.go
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
package myecharts
|
||||||
|
|
||||||
|
//echarts option 根数据
|
||||||
|
type EcOption struct {
|
||||||
|
Color []string `json:"color,omitempty"` //调色盘颜色列表。如果系列没有设置颜色,则会依次循环从该列表中取颜色作为系列颜色。
|
||||||
|
//标题组件,包含主标题和副标题。
|
||||||
|
Title EcTitle `json:"title,omitempty"`
|
||||||
|
Tooltip EcToolTip `json:"tooltip,omitempty"`
|
||||||
|
Grid EcGrid `json:"grid,omitempty"`
|
||||||
|
XAxis EcxAxis `json:"xAxis,omitempty"` //直角坐标系 grid 中的 x 轴
|
||||||
|
YAxis EcxAxis `json:"yAxis,omitempty"` //直角坐标系 grid 中的 y 轴
|
||||||
|
Legend EcLegend `json:"legend,omitempty"` //图例组件。
|
||||||
|
Series []EcSeries `json:"series,omitempty"` //数据内容
|
||||||
|
Toolbox Toolbox `json:"toolbox,omitempty"` //
|
||||||
|
_type string
|
||||||
|
}
|
||||||
|
|
||||||
|
//系列列表。每个系列通过 type 决定自己的图表类型
|
||||||
|
type EcSeries struct {
|
||||||
|
Name string `json:"name,omitempty"` //系列名称
|
||||||
|
Type string `json:"type,omitempty"` //line:线 bar:柱状图
|
||||||
|
Data interface{} `json:"data,omitempty"` //系列中的数据内容数组
|
||||||
|
}
|
||||||
|
|
||||||
|
//图例组件。
|
||||||
|
type EcLegend struct {
|
||||||
|
Show bool `json:"show,omitempty"`
|
||||||
|
Data []string `json:"data,omitempty"` //图例的数据数组
|
||||||
|
}
|
||||||
|
|
||||||
|
//直角坐标系内绘图网格
|
||||||
|
type EcxAxis struct {
|
||||||
|
Type string `json:"type,omitempty"`
|
||||||
|
Data []string `json:"data,omitempty"`
|
||||||
|
AxisLabel AxisLabel `json:"axisLabel,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
type AxisLabel struct {
|
||||||
|
Formatter string `json:"formatter,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//直角坐标系内绘图网格
|
||||||
|
type EcGrid struct {
|
||||||
|
Left string `json:"left,omitempty"` //组件离容器左侧的距离。
|
||||||
|
Right string `json:"right,omitempty"`
|
||||||
|
Bottom string `json:"bottom,omitempty"`
|
||||||
|
ContainLabel bool `json:"containLabel,omitempty"` //grid 区域是否包含坐标轴的刻度标签
|
||||||
|
}
|
||||||
|
|
||||||
|
//提示框组件。
|
||||||
|
type EcToolTip struct {
|
||||||
|
Show bool `json:"show,omitempty"`
|
||||||
|
/*
|
||||||
|
触发类型。
|
||||||
|
'item' 数据项图形触发,主要在散点图,饼图等无类目轴的图表中使用。
|
||||||
|
'axis' 坐标轴触发,主要在柱状图,折线图等会使用类目轴的图表中使用。
|
||||||
|
'none' 什么都不触发。
|
||||||
|
*/
|
||||||
|
Trigger string `json:"trigger,omitempty"`
|
||||||
|
//坐标轴指示器配置项。
|
||||||
|
AxisPointer EcAxisPointer `json:"axisPointer,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//坐标轴指示器配置项。
|
||||||
|
type EcAxisPointer struct {
|
||||||
|
/*
|
||||||
|
'line' 直线指示器
|
||||||
|
'shadow' 阴影指示器
|
||||||
|
'none' 无指示器
|
||||||
|
'cross' 十字准星指示器
|
||||||
|
*/
|
||||||
|
Type string `json:"type,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//标题组件,包含主标题和副标题。
|
||||||
|
type EcTitle struct {
|
||||||
|
Text string `json:"text,omitempty"` //主标题文本,支持使用 \n 换行。
|
||||||
|
SubText string `json:"subtext,omitempty"` //副标题文本,支持使用 \n 换行。
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
type Toolbox struct {
|
||||||
|
Show bool `json:"show,omitempty"` //
|
||||||
|
Feature Feature `json:"feature,omitempty"` //
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
type Feature struct {
|
||||||
|
}
|
26
myecharts/myecharts.go
Normal file
26
myecharts/myecharts.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package myecharts
|
||||||
|
|
||||||
|
//获取线图基础数据
|
||||||
|
/*
|
||||||
|
t_str
|
||||||
|
line:线
|
||||||
|
bar:柱
|
||||||
|
pie:饼
|
||||||
|
scatter:散点(气泡) effectScatter:带有涟漪特效动画的散点 radar:雷达
|
||||||
|
tree:树 treemap:面积 sunburst:旭日图 boxplot:箱形图 candlestick:K线图 sankey:桑基图
|
||||||
|
heatmap:热力图 map:地图 parallel: 平行坐标系的系列 lines:线图 graph:关系图
|
||||||
|
funnel:漏斗图 gauge:仪表盘 pictorialBar:象形柱图 themeRiver:主题河流 custom:自定义系列
|
||||||
|
*/
|
||||||
|
func OnGetBaseInfo(t_str string) (ec EcOption) {
|
||||||
|
ec = getDefaltOption()
|
||||||
|
ec._type = t_str
|
||||||
|
return ec
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
获取基础柱状图
|
||||||
|
*/
|
||||||
|
func OnGetBarInfo(ecToolTip EcToolTip) (ec EcOption) {
|
||||||
|
ec = OnGetBaseInfo("bar")
|
||||||
|
return ec
|
||||||
|
}
|
391
myelastic/myelastic.go
Normal file
391
myelastic/myelastic.go
Normal file
@@ -0,0 +1,391 @@
|
|||||||
|
package myelastic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/olivere/elastic"
|
||||||
|
)
|
||||||
|
|
||||||
|
//
|
||||||
|
type MyElastic struct {
|
||||||
|
Client *elastic.Client
|
||||||
|
Err error
|
||||||
|
Ctx context.Context
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
func OnInitES(url string) MyElastic {
|
||||||
|
var es MyElastic
|
||||||
|
es.Ctx = context.Background()
|
||||||
|
es.Client, es.Err = elastic.NewClient(elastic.SetURL(url))
|
||||||
|
if es.Err != nil {
|
||||||
|
log.Println(es.Err)
|
||||||
|
//mylog.Error(es.Err)
|
||||||
|
//panic(es.Err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return es
|
||||||
|
}
|
||||||
|
|
||||||
|
//func (es *MyElastic) Model(refs interface{}) *MyElastic {
|
||||||
|
// if reflect.ValueOf(refs).Type().Kind() != reflect.Ptr {
|
||||||
|
// mylog.Println("Model: attempt to Model into a pointer")
|
||||||
|
// panic(0)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// es.Element = refs
|
||||||
|
// return es
|
||||||
|
//}
|
||||||
|
|
||||||
|
/*
|
||||||
|
创建索引(相当于数据库)
|
||||||
|
mapping 如果为空("")则表示不创建模型
|
||||||
|
*/
|
||||||
|
func (es *MyElastic) CreateIndex(index_name, mapping string) (result bool) {
|
||||||
|
es.Err = nil
|
||||||
|
exists, err := es.Client.IndexExists(index_name).Do(es.Ctx)
|
||||||
|
if err != nil {
|
||||||
|
es.Err = err
|
||||||
|
log.Println(es.Err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !exists {
|
||||||
|
var re *elastic.IndicesCreateResult
|
||||||
|
if len(mapping) == 0 {
|
||||||
|
re, es.Err = es.Client.CreateIndex(index_name).Do(es.Ctx)
|
||||||
|
} else {
|
||||||
|
re, es.Err = es.Client.CreateIndex(index_name).BodyString(mapping).Do(es.Ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
if es.Err != nil {
|
||||||
|
log.Println(es.Err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return re.Acknowledged
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
排序查询
|
||||||
|
返回json数据集合
|
||||||
|
*/
|
||||||
|
func (es *MyElastic) SortQuery(index_name string, builder []elastic.Sorter, query []elastic.Query) (bool, []string) {
|
||||||
|
|
||||||
|
searchResult := es.Client.Search().Index(index_name)
|
||||||
|
|
||||||
|
if len(builder) > 0 {
|
||||||
|
for _, v := range builder {
|
||||||
|
searchResult = searchResult.SortBy(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(query) > 0 {
|
||||||
|
for _, v := range query {
|
||||||
|
searchResult = searchResult.Query(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
es_result, err := searchResult.Do(es.Ctx) // execute
|
||||||
|
if err != nil {
|
||||||
|
log.Println(es.Err)
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
//log.Println("Found a total of %d entity\n", es_result.TotalHits())
|
||||||
|
|
||||||
|
if es_result.Hits.TotalHits > 0 {
|
||||||
|
var result []string
|
||||||
|
//log.Println("Found a total of %d entity\n", searchResult.Hits.TotalHits)
|
||||||
|
for _, hit := range es_result.Hits.Hits {
|
||||||
|
|
||||||
|
result = append(result, string(*hit.Source))
|
||||||
|
|
||||||
|
}
|
||||||
|
return true, result
|
||||||
|
} else {
|
||||||
|
// No hits
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
排序查询
|
||||||
|
返回原始Hit
|
||||||
|
builder:排序
|
||||||
|
agg:聚合 类似group_by sum
|
||||||
|
query:查询
|
||||||
|
*/
|
||||||
|
func (es *MyElastic) SortQueryReturnHits(index_name string, from, size int, builder []elastic.Sorter, query []elastic.Query) (bool, []*elastic.SearchHit) {
|
||||||
|
|
||||||
|
searchResult := es.Client.Search().Index(index_name)
|
||||||
|
|
||||||
|
if len(builder) > 0 {
|
||||||
|
for _, v := range builder {
|
||||||
|
searchResult = searchResult.SortBy(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(query) > 0 {
|
||||||
|
for _, v := range query {
|
||||||
|
searchResult = searchResult.Query(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if size > 0 {
|
||||||
|
searchResult = searchResult.From(from)
|
||||||
|
searchResult = searchResult.Size(size)
|
||||||
|
}
|
||||||
|
es_result, err := searchResult.Do(es.Ctx) // execute
|
||||||
|
if err != nil {
|
||||||
|
log.Println(es.Err)
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// log.Println("wwwwww", es_result.Aggregations)
|
||||||
|
if es_result.Hits.TotalHits > 0 {
|
||||||
|
|
||||||
|
return true, es_result.Hits.Hits
|
||||||
|
} else {
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
添加记录,覆盖添加
|
||||||
|
*/
|
||||||
|
func (es *MyElastic) Add(index_name, type_name, id string, data interface{}) (result bool) {
|
||||||
|
result = false
|
||||||
|
// Index a tweet (using JSON serialization)
|
||||||
|
if len(id) > 0 {
|
||||||
|
_, es.Err = es.Client.Index().
|
||||||
|
Index(index_name).
|
||||||
|
Type(type_name).
|
||||||
|
Id(id).
|
||||||
|
BodyJson(data).
|
||||||
|
Do(es.Ctx)
|
||||||
|
} else {
|
||||||
|
_, es.Err = es.Client.Index().
|
||||||
|
Index(index_name).
|
||||||
|
Type(type_name).
|
||||||
|
BodyJson(data).
|
||||||
|
Do(es.Ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
if es.Err != nil {
|
||||||
|
log.Println(es.Err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
_, es.Err = es.Client.Flush().Index(index_name).Do(es.Ctx)
|
||||||
|
if es.Err != nil {
|
||||||
|
log.Println(es.Err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
添加记录,覆盖添加
|
||||||
|
index_name
|
||||||
|
type_name
|
||||||
|
query interface{} //查询条件
|
||||||
|
out *[]Param //查询结果
|
||||||
|
*/
|
||||||
|
func (es *MyElastic) SearchMap(index_name, type_name string, query interface{}, out *[]map[string]interface{}) (result bool) {
|
||||||
|
es_search := es.Client.Search()
|
||||||
|
if len(type_name) > 0 {
|
||||||
|
es_search = es_search.Type(type_name)
|
||||||
|
}
|
||||||
|
if len(index_name) > 0 {
|
||||||
|
es_search = es_search.Index(index_name)
|
||||||
|
}
|
||||||
|
var es_result *elastic.SearchResult
|
||||||
|
es_result, es.Err = es_search.Source(query).Do(es.Ctx)
|
||||||
|
if es.Err != nil {
|
||||||
|
log.Println(es.Err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if es_result.Hits == nil {
|
||||||
|
log.Println(errors.New("expected SearchResult.Hits != nil; got nil"))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, hit := range es_result.Hits.Hits {
|
||||||
|
tmp := make(map[string]interface{})
|
||||||
|
err := json.Unmarshal(*hit.Source, &tmp)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(es.Err)
|
||||||
|
} else {
|
||||||
|
*out = append(*out, tmp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
添加记录,覆盖添加
|
||||||
|
index_name
|
||||||
|
type_name
|
||||||
|
query interface{} //查询条件
|
||||||
|
out *[]Param //查询结果
|
||||||
|
*/
|
||||||
|
func (es *MyElastic) Search(index_name, type_name string, query interface{}, out interface{}) (result bool) {
|
||||||
|
|
||||||
|
sliceValue := reflect.Indirect(reflect.ValueOf(out))
|
||||||
|
|
||||||
|
if sliceValue.Kind() != reflect.Slice {
|
||||||
|
log.Println(errors.New("needs a pointer to a slice"))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
sliceElementType := sliceValue.Type().Elem()
|
||||||
|
es_search := es.Client.Search()
|
||||||
|
if len(type_name) > 0 {
|
||||||
|
es_search = es_search.Type(type_name)
|
||||||
|
}
|
||||||
|
if len(index_name) > 0 {
|
||||||
|
es_search = es_search.Index(index_name)
|
||||||
|
}
|
||||||
|
var es_result *elastic.SearchResult
|
||||||
|
es_result, es.Err = es_search.Source(query).Do(es.Ctx)
|
||||||
|
if es.Err != nil {
|
||||||
|
log.Println(es.Err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if es_result.Hits == nil {
|
||||||
|
log.Println(errors.New("expected SearchResult.Hits != nil; got nil"))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, hit := range es_result.Hits.Hits {
|
||||||
|
newValue := reflect.New(sliceElementType)
|
||||||
|
|
||||||
|
item := make(map[string]interface{})
|
||||||
|
err := json.Unmarshal(*hit.Source, &item)
|
||||||
|
//fmt.Println(string(*hit.Source))
|
||||||
|
|
||||||
|
err = scanMapIntoStruct(newValue.Interface(), item)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
} else {
|
||||||
|
sliceValue.Set(reflect.Append(sliceValue, reflect.Indirect(reflect.ValueOf(newValue.Interface()))))
|
||||||
|
//out = append(out, tmp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func scanMapIntoStruct(obj interface{}, objMap map[string]interface{}) error {
|
||||||
|
dataStruct := reflect.Indirect(reflect.ValueOf(obj))
|
||||||
|
if dataStruct.Kind() != reflect.Struct {
|
||||||
|
return errors.New("expected a pointer to a struct")
|
||||||
|
}
|
||||||
|
|
||||||
|
dataStructType := dataStruct.Type()
|
||||||
|
|
||||||
|
for i := 0; i < dataStructType.NumField(); i++ {
|
||||||
|
field := dataStructType.Field(i)
|
||||||
|
fieldv := dataStruct.Field(i)
|
||||||
|
|
||||||
|
err := scanMapElement(fieldv, field, objMap)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func scanMapElement(fieldv reflect.Value, field reflect.StructField, objMap map[string]interface{}) error {
|
||||||
|
|
||||||
|
objFieldName := field.Name
|
||||||
|
bb := field.Tag
|
||||||
|
sqlTag := bb.Get("json")
|
||||||
|
|
||||||
|
if bb.Get("json") == "-" || sqlTag == "-" || reflect.ValueOf(bb).String() == "-" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlTags := strings.Split(sqlTag, ",")
|
||||||
|
sqlFieldName := objFieldName
|
||||||
|
if len(sqlTags[0]) > 0 {
|
||||||
|
sqlFieldName = sqlTags[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
data, ok := objMap[sqlFieldName]
|
||||||
|
if !ok || data == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// fmt.Println("================")
|
||||||
|
// fmt.Println(field.Type.Kind())
|
||||||
|
// fmt.Println(sqlFieldName)
|
||||||
|
var v interface{}
|
||||||
|
switch field.Type.Kind() {
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
x := int(data.(float64))
|
||||||
|
v = x
|
||||||
|
case reflect.Slice:
|
||||||
|
if fieldv.Type().String() == "[]uint8" {
|
||||||
|
x := []byte(data.(string))
|
||||||
|
v = x
|
||||||
|
} else if fieldv.Type().String() == "[]string" {
|
||||||
|
mp := data.([]interface{})
|
||||||
|
var ss []string
|
||||||
|
for _, v := range mp {
|
||||||
|
ss = append(ss, v.(string))
|
||||||
|
}
|
||||||
|
v = ss
|
||||||
|
} else if fieldv.Type().String() == "[]int" {
|
||||||
|
mp := data.([]interface{})
|
||||||
|
var ss []int
|
||||||
|
for _, v := range mp {
|
||||||
|
ss = append(ss, int(v.(float64)))
|
||||||
|
}
|
||||||
|
v = ss
|
||||||
|
|
||||||
|
} else {
|
||||||
|
v = data
|
||||||
|
}
|
||||||
|
|
||||||
|
case reflect.Struct:
|
||||||
|
if fieldv.Type().String() == "time.Time" {
|
||||||
|
x, err := time.Parse("2006-01-02 15:04:05", data.(string))
|
||||||
|
if err != nil {
|
||||||
|
x, err = time.Parse("2006-01-02 15:04:05.000 -0700", data.(string))
|
||||||
|
if err != nil {
|
||||||
|
if err != nil {
|
||||||
|
x, err = time.Parse("2006-01-02T15:04:05.999999999Z07:00", data.(string))
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("unsupported time format: " + data.(string))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
v = x
|
||||||
|
} else {
|
||||||
|
v = data
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
v = data
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldv.Set(reflect.ValueOf(v))
|
||||||
|
// fmt.Println("================")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
BIN
myelastic/test.rar
Normal file
BIN
myelastic/test.rar
Normal file
Binary file not shown.
87
myfile/myfile.go
Normal file
87
myfile/myfile.go
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
package myfile
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"public/tools"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
//上传单个文件
|
||||||
|
func UploadOneFile(r *http.Request, field, file_type, dir string) (result bool, file_name string) {
|
||||||
|
//接受post请求
|
||||||
|
if r.Method == "POST" {
|
||||||
|
r.ParseMultipartForm(32 << 20)
|
||||||
|
file_name = getFileName(file_type)
|
||||||
|
//开始存储文件
|
||||||
|
{
|
||||||
|
file, _, err := r.FormFile(field) //文件name
|
||||||
|
defer file.Close()
|
||||||
|
if err != nil {
|
||||||
|
result = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !tools.CheckFileIsExist(tools.GetModelPath() + "/file/" + dir + "/") {
|
||||||
|
err1 := os.Mkdir(tools.GetModelPath()+"/file/"+dir+"/", os.ModePerm) //创建文件夹
|
||||||
|
if err1 != nil {
|
||||||
|
result = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := os.OpenFile(tools.GetModelPath()+"/file/"+dir+"/"+file_name, os.O_WRONLY|os.O_CREATE, 0666)
|
||||||
|
defer f.Close()
|
||||||
|
if err != nil {
|
||||||
|
result = false
|
||||||
|
}
|
||||||
|
io.Copy(f, file)
|
||||||
|
result = true
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
result = false
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//多文件上传
|
||||||
|
func UploadMoreFile(r *http.Request, field, file_type, dir string) (result bool, optionDirs []string) {
|
||||||
|
//接受post请求
|
||||||
|
if r.Method == "POST" {
|
||||||
|
r.ParseMultipartForm(32 << 20)
|
||||||
|
files := r.MultipartForm.File[field]
|
||||||
|
l := len(files)
|
||||||
|
// optionDirs := make([]string, l)
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
file, err := files[i].Open()
|
||||||
|
defer file.Close()
|
||||||
|
if err != nil {
|
||||||
|
result = false
|
||||||
|
}
|
||||||
|
file_name := getFileName(file_type)
|
||||||
|
|
||||||
|
if !tools.CheckFileIsExist(tools.GetModelPath() + "/file/" + dir + "/") {
|
||||||
|
err1 := os.Mkdir(tools.GetModelPath()+"/file/"+dir+"/", os.ModePerm) //创建文件夹
|
||||||
|
if err1 != nil {
|
||||||
|
result = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f, err := os.OpenFile(tools.GetModelPath()+"/file/"+dir+"/"+file_name, os.O_WRONLY|os.O_CREATE, 0666)
|
||||||
|
defer f.Close()
|
||||||
|
if err != nil {
|
||||||
|
result = false
|
||||||
|
}
|
||||||
|
io.Copy(f, file)
|
||||||
|
optionDirs = append(optionDirs, file_name)
|
||||||
|
result = true
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
result = false
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func getFileName(exp string) string {
|
||||||
|
return fmt.Sprintf("%d%s.%s", tools.GetUtcTime(time.Now()), tools.GetRandomString(4), exp)
|
||||||
|
}
|
132
myhttp/myfile.go
Normal file
132
myhttp/myfile.go
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
package myhttp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"data/config"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"mime/multipart"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"public/mylog"
|
||||||
|
"public/tools"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
多文件上传
|
||||||
|
dir:空则使用文件后缀做dir
|
||||||
|
*/
|
||||||
|
func UploadMoreFile(r *http.Request, dir string) (result bool, optionDirs []string) {
|
||||||
|
//接受post请求
|
||||||
|
if r.Method == "POST" {
|
||||||
|
r.ParseMultipartForm(32 << 20)
|
||||||
|
if r.MultipartForm == nil {
|
||||||
|
result = false
|
||||||
|
} else {
|
||||||
|
for _, files := range r.MultipartForm.File {
|
||||||
|
for _, v := range files {
|
||||||
|
var _dir = dir
|
||||||
|
file, _ := v.Open()
|
||||||
|
defer file.Close()
|
||||||
|
ext := getFileType(v.Filename)
|
||||||
|
if len(ext) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if len(_dir) == 0 {
|
||||||
|
_dir = ext
|
||||||
|
}
|
||||||
|
|
||||||
|
abs_dir := tools.GetModelPath() + config.File_host + "/" + _dir + "/"
|
||||||
|
file_name := getFileName(ext)
|
||||||
|
if !tools.CheckFileIsExist(abs_dir) {
|
||||||
|
tools.BuildDir(abs_dir)
|
||||||
|
//err := os.MkdirAll(tools.GetModelPath()+config.File_host+"/"+_dir+"/", os.ModePerm) //生成多级目录
|
||||||
|
}
|
||||||
|
|
||||||
|
//存在则覆盖
|
||||||
|
f, err := os.OpenFile(abs_dir+file_name,
|
||||||
|
os.O_WRONLY|os.O_CREATE, 0666)
|
||||||
|
defer f.Close()
|
||||||
|
if err != nil {
|
||||||
|
mylog.Error(err)
|
||||||
|
result = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
io.Copy(f, file)
|
||||||
|
optionDirs = append(optionDirs, config.Url_host+config.File_host+"/"+_dir+"/"+file_name)
|
||||||
|
result = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = false
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func getFileName(exp string) string {
|
||||||
|
return fmt.Sprintf("%d%s.%s", tools.GetUtcTime(time.Now()), tools.GetRandomString(4), exp)
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取文件后缀
|
||||||
|
func getFileType(exp string) string {
|
||||||
|
fileSuffix := path.Ext(exp) //获取文件后缀
|
||||||
|
if len(fileSuffix) > 1 {
|
||||||
|
return fileSuffix[1:]
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
//模拟客戶端文件上传
|
||||||
|
//fieldname注意与服务器端保持一致
|
||||||
|
func PostFile(filename, fieldname string, targetUrl string) (e error, result string) {
|
||||||
|
bodyBuf := &bytes.Buffer{}
|
||||||
|
bodyWriter := multipart.NewWriter(bodyBuf)
|
||||||
|
|
||||||
|
//关键的一步操作
|
||||||
|
fileWriter, err := bodyWriter.CreateFormFile(fieldname, filename)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("error writing to buffer")
|
||||||
|
e = err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//打开文件句柄操作
|
||||||
|
fh, err := os.Open(filename)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("error opening file")
|
||||||
|
e = err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer fh.Close()
|
||||||
|
|
||||||
|
//iocopy
|
||||||
|
_, err = io.Copy(fileWriter, fh)
|
||||||
|
if err != nil {
|
||||||
|
e = err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
contentType := bodyWriter.FormDataContentType()
|
||||||
|
bodyWriter.Close()
|
||||||
|
|
||||||
|
resp, err := http.Post(targetUrl, contentType, bodyBuf)
|
||||||
|
if err != nil {
|
||||||
|
e = err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
resp_body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
e = err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println(resp.Status)
|
||||||
|
fmt.Println(string(resp_body))
|
||||||
|
result = string(resp_body)
|
||||||
|
return
|
||||||
|
}
|
143
myhttp/myhttp.go
Normal file
143
myhttp/myhttp.go
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
package myhttp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"public/mylog"
|
||||||
|
)
|
||||||
|
|
||||||
|
//发送修改密码
|
||||||
|
func OnPostJson(url, jsonstr string) []byte {
|
||||||
|
//解析这个 URL 并确保解析没有出错。
|
||||||
|
body := bytes.NewBuffer([]byte(jsonstr))
|
||||||
|
resp, err := http.Post(url, "application/json;charset=utf-8", body)
|
||||||
|
if err != nil {
|
||||||
|
return []byte("")
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
body1, err1 := ioutil.ReadAll(resp.Body)
|
||||||
|
if err1 != nil {
|
||||||
|
return []byte("")
|
||||||
|
}
|
||||||
|
|
||||||
|
return body1
|
||||||
|
}
|
||||||
|
|
||||||
|
//发送get 请求
|
||||||
|
func OnGetJson(url, params string) string {
|
||||||
|
//解析这个 URL 并确保解析没有出错。
|
||||||
|
var urls = url
|
||||||
|
if len(params) > 0 {
|
||||||
|
urls += "?" + params
|
||||||
|
}
|
||||||
|
resp, err := http.Get(urls)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
body1, err1 := ioutil.ReadAll(resp.Body)
|
||||||
|
if err1 != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(body1)
|
||||||
|
}
|
||||||
|
|
||||||
|
//发送get 请求 返回对象
|
||||||
|
func SendGet(url, params string, obj interface{}) bool {
|
||||||
|
//解析这个 URL 并确保解析没有出错。
|
||||||
|
var urls = url
|
||||||
|
if len(params) > 0 {
|
||||||
|
urls += "?" + params
|
||||||
|
}
|
||||||
|
resp, err := http.Get(urls)
|
||||||
|
if err != nil {
|
||||||
|
mylog.Error(err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
mylog.Error(err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
log.Println((string(body)))
|
||||||
|
err = json.Unmarshal([]byte(body), &obj)
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//发送GET请求
|
||||||
|
func SendGetEx(url string, reponse interface{}) bool {
|
||||||
|
resp, e := http.Get(url)
|
||||||
|
if e != nil {
|
||||||
|
mylog.Error(e)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
mylog.Error(e)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
mylog.Debug(string(body))
|
||||||
|
err = json.Unmarshal(body, &reponse)
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//form 方式发送post请求
|
||||||
|
func OnPostForm(url string, data url.Values) (body []byte) {
|
||||||
|
resp, err := http.PostForm(url, data)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
body, err = ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//发送POST请求
|
||||||
|
func SendPost(requestBody interface{}, responseBody interface{}, url string) bool {
|
||||||
|
postData, err := json.Marshal(requestBody)
|
||||||
|
client := &http.Client{}
|
||||||
|
req, _ := http.NewRequest("POST", url, bytes.NewReader(postData))
|
||||||
|
req.Header.Add("Accept", "application/json")
|
||||||
|
req.Header.Add("Content-Type", "application/json;charset=utf-8")
|
||||||
|
// req.Header.Add("Authorization", authorization)
|
||||||
|
resp, e := client.Do(req)
|
||||||
|
if e != nil {
|
||||||
|
mylog.Error(e)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
mylog.Error(e)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// result := string(body)
|
||||||
|
mylog.Debug(string(body))
|
||||||
|
|
||||||
|
err = json.Unmarshal(body, &responseBody)
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//像指定client 发送json 包
|
||||||
|
//msg message.MessageBody
|
||||||
|
func WriteJson(w http.ResponseWriter, msg interface{}) {
|
||||||
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
|
js, err := json.Marshal(msg)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, string(js))
|
||||||
|
}
|
64
myleveldb/my_test.go
Normal file
64
myleveldb/my_test.go
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
package myleveldb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"public/myleveldb"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Tweet is a structure used for serializing/deserializing data in Elasticsearch.
|
||||||
|
type Tweet struct {
|
||||||
|
User string `json:"user"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
Retweets int `json:"retweets"`
|
||||||
|
Image string `json:"image,omitempty"`
|
||||||
|
Created time.Time `json:"created,omitempty"`
|
||||||
|
Tags []string `json:"tags,omitempty"`
|
||||||
|
Location string `json:"location,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_order(t *testing.T) {
|
||||||
|
fmt.Println("ssss")
|
||||||
|
//初始化db
|
||||||
|
ldb := myleveldb.OnInitDB("./database")
|
||||||
|
defer ldb.OnDestoryDB()
|
||||||
|
|
||||||
|
// var www Tweet
|
||||||
|
// www.Location = "xiexiaojun"
|
||||||
|
// www.Created = time.Now()
|
||||||
|
// www.Tags = append(www.Tags, "12334444", "ssss", "wwwww")
|
||||||
|
// b := ldb.Add([]byte("wwww"), www)
|
||||||
|
// fmt.Println(b)
|
||||||
|
// fmt.Println(www.Tags)
|
||||||
|
|
||||||
|
var eee Tweet
|
||||||
|
bb := ldb.Get("wwww", &eee)
|
||||||
|
fmt.Println(bb)
|
||||||
|
fmt.Println(eee.Location)
|
||||||
|
fmt.Println(eee.Created)
|
||||||
|
fmt.Println(eee.Tags)
|
||||||
|
|
||||||
|
// var temp []myleveldb.Param
|
||||||
|
// for i := 0; i < 10; i++ {
|
||||||
|
// var www Tweet
|
||||||
|
// www.Location = "xiexiaojun" + strconv.Itoa(i)
|
||||||
|
// www.Created = time.Now()
|
||||||
|
// temp = append(temp, myleveldb.Param{"key" + strconv.Itoa(i), www})
|
||||||
|
// }
|
||||||
|
//bbb := ldb.AddList(temp)
|
||||||
|
//fmt.Println(bbb)
|
||||||
|
|
||||||
|
bb = ldb.Get("key9", &eee)
|
||||||
|
fmt.Println(bb)
|
||||||
|
fmt.Println(eee.Location)
|
||||||
|
fmt.Println(eee.Created)
|
||||||
|
fmt.Println(eee.Tags)
|
||||||
|
|
||||||
|
var tmp []myleveldb.Param
|
||||||
|
bb = ldb.Model(&Tweet{}).Find(&tmp, "key3", "key7") //查找
|
||||||
|
|
||||||
|
fmt.Println(tmp)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
172
myleveldb/myleveldb.go
Normal file
172
myleveldb/myleveldb.go
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
package myleveldb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"public/mylog"
|
||||||
|
"public/tools"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/syndtr/goleveldb/leveldb"
|
||||||
|
"github.com/syndtr/goleveldb/leveldb/iterator"
|
||||||
|
"github.com/syndtr/goleveldb/leveldb/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Param struct {
|
||||||
|
Key string
|
||||||
|
Value interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func OnInitDB(dataSourceName string) MyLevelDB {
|
||||||
|
var L MyLevelDB
|
||||||
|
L.DB, L.E = leveldb.OpenFile(dataSourceName, nil)
|
||||||
|
if L.E != nil {
|
||||||
|
mylog.Error(L.E)
|
||||||
|
}
|
||||||
|
// L.op = &opt.ReadOptions{
|
||||||
|
// false,
|
||||||
|
// opt.NoStrict,
|
||||||
|
// }
|
||||||
|
return L
|
||||||
|
}
|
||||||
|
|
||||||
|
type MyLevelDB struct {
|
||||||
|
DB *leveldb.DB
|
||||||
|
E error
|
||||||
|
//op *opt.ReadOptions
|
||||||
|
Value interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (L *MyLevelDB) OnDestoryDB() {
|
||||||
|
if L.DB != nil {
|
||||||
|
L.DB.Close()
|
||||||
|
L.DB = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取数据
|
||||||
|
func (L *MyLevelDB) Get(key string, value interface{}) (b bool) {
|
||||||
|
if L.DB != nil {
|
||||||
|
var err error
|
||||||
|
var by []byte
|
||||||
|
if by, err = L.DB.Get([]byte(key), nil /*L.op*/); err != nil {
|
||||||
|
//mylog.Error(err)
|
||||||
|
} else {
|
||||||
|
if err := tools.DecodeByte(by, value); err != nil {
|
||||||
|
//错误处理
|
||||||
|
mylog.Error(err)
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (L *MyLevelDB) Model(refs interface{}) *MyLevelDB {
|
||||||
|
if reflect.ValueOf(refs).Type().Kind() == reflect.Ptr {
|
||||||
|
mylog.Println("Model: attempt to Model into a non-pointer")
|
||||||
|
panic(0)
|
||||||
|
}
|
||||||
|
L.Value = refs
|
||||||
|
return L
|
||||||
|
}
|
||||||
|
|
||||||
|
//模糊查找
|
||||||
|
/*
|
||||||
|
t value的类型
|
||||||
|
values 为返回结果
|
||||||
|
args 传一个参数:表示模糊搜索
|
||||||
|
args 传2个参数:表示范围搜索
|
||||||
|
*/
|
||||||
|
func (L *MyLevelDB) Find(values *[]Param, args ...string) (b bool) {
|
||||||
|
if L.DB != nil && L.Value != nil {
|
||||||
|
n := len(args)
|
||||||
|
var it iterator.Iterator
|
||||||
|
|
||||||
|
if n == 1 { //模糊查找
|
||||||
|
it = L.DB.NewIterator(util.BytesPrefix([]byte(args[0])), nil)
|
||||||
|
} else {
|
||||||
|
it = L.DB.NewIterator(&util.Range{Start: []byte(args[0]), Limit: []byte(args[1])}, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
for it.Next() {
|
||||||
|
tmp := L.Value
|
||||||
|
if err := tools.DecodeByte(it.Value(), tmp); err != nil {
|
||||||
|
//错误处理
|
||||||
|
mylog.Error(err)
|
||||||
|
}
|
||||||
|
*values = append(*values, Param{string(it.Key()), tmp})
|
||||||
|
}
|
||||||
|
|
||||||
|
it.Release()
|
||||||
|
//iter := L.DB.NewIterator(nil, nil)
|
||||||
|
} else {
|
||||||
|
if L.Value == nil {
|
||||||
|
panic("not call Model()")
|
||||||
|
}
|
||||||
|
mylog.Print(mylog.Log_Error, "not init.")
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
//添加数据
|
||||||
|
//注意:只支持基础类型
|
||||||
|
func (L *MyLevelDB) Add(key string, value interface{}) bool {
|
||||||
|
if L.DB != nil {
|
||||||
|
by, err := tools.EncodeByte(value)
|
||||||
|
if err != nil {
|
||||||
|
//错误处理
|
||||||
|
mylog.Error(err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if err = L.DB.Put([]byte(key), by, nil); err != nil {
|
||||||
|
mylog.Error(err)
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
//添加一组数据(比一个一个添加速度快很多)
|
||||||
|
//注意:只支持基础类型
|
||||||
|
func (L *MyLevelDB) AddList(array []Param) bool {
|
||||||
|
if L.DB != nil {
|
||||||
|
batch := new(leveldb.Batch)
|
||||||
|
for _, p := range array {
|
||||||
|
by, err := tools.EncodeByte(p.Value)
|
||||||
|
if err != nil {
|
||||||
|
//错误处理
|
||||||
|
mylog.Error(err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
batch.Put([]byte(p.Key), by)
|
||||||
|
}
|
||||||
|
err := L.DB.Write(batch, nil)
|
||||||
|
if err != nil {
|
||||||
|
//错误处理
|
||||||
|
mylog.Error(err)
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
删除
|
||||||
|
*/
|
||||||
|
func (L *MyLevelDB) Delete(key string) bool {
|
||||||
|
if L.DB != nil {
|
||||||
|
err := L.DB.Delete([]byte(key), nil)
|
||||||
|
if err != nil {
|
||||||
|
mylog.Error(err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
BIN
myleveldb/test2018-03-29.rar
Normal file
BIN
myleveldb/test2018-03-29.rar
Normal file
Binary file not shown.
83
mylog/def.go
Normal file
83
mylog/def.go
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
package mylog
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
日志详细信息
|
||||||
|
*/
|
||||||
|
type LogInfo struct {
|
||||||
|
Service string `json:"service"` //服务名
|
||||||
|
Group string `json:"group"` //服务组
|
||||||
|
Type string `json:"type"` //日志的类型()
|
||||||
|
Action string `json:"action"` //动作
|
||||||
|
Path string `json:"path"` //路径,地址,深度
|
||||||
|
Ip string `json:"ip"` //ip地址
|
||||||
|
Topic string `json:"topic"`
|
||||||
|
Bundle string `json:"bundle"`
|
||||||
|
Pid string `json:"pid"`
|
||||||
|
Data interface{} `json:"data"`
|
||||||
|
Creat_time time.Time `json:"created"`
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
向es发送数据结构信息
|
||||||
|
*/
|
||||||
|
type EsLogInfo struct {
|
||||||
|
Info LogInfo `json:"loginfo"` //信息
|
||||||
|
Es_index string `json:"es_index"` //索引
|
||||||
|
Es_type string `json:"es_type"` //类型
|
||||||
|
Es_id string `json:"es_id"` //id
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
Http_log_index = "http_log"
|
||||||
|
)
|
||||||
|
|
||||||
|
const mapping = `
|
||||||
|
{
|
||||||
|
"settings":{
|
||||||
|
"number_of_shards": 1,
|
||||||
|
"number_of_replicas": 5
|
||||||
|
},
|
||||||
|
"mappings":{
|
||||||
|
"` + Http_log_index + `":{
|
||||||
|
"properties":{
|
||||||
|
"service":{
|
||||||
|
"type":"keyword"
|
||||||
|
},
|
||||||
|
"group":{
|
||||||
|
"type":"keyword"
|
||||||
|
},
|
||||||
|
"type":{
|
||||||
|
"type":"text"
|
||||||
|
},
|
||||||
|
"action":{
|
||||||
|
"type":"keyword"
|
||||||
|
},
|
||||||
|
"path":{
|
||||||
|
"type":"text"
|
||||||
|
},
|
||||||
|
"ip":{
|
||||||
|
"type":"text"
|
||||||
|
},
|
||||||
|
"topic":{
|
||||||
|
"type":"keyword"
|
||||||
|
},
|
||||||
|
"bundle":{
|
||||||
|
"type":"keyword"
|
||||||
|
},
|
||||||
|
"pid":{
|
||||||
|
"type":"keyword"
|
||||||
|
},
|
||||||
|
"data":{
|
||||||
|
"type":"text"
|
||||||
|
},
|
||||||
|
"created":{
|
||||||
|
"type":"date"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`
|
122
mylog/myeslog.go
Normal file
122
mylog/myeslog.go
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
package mylog
|
||||||
|
|
||||||
|
import (
|
||||||
|
"data/config"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"public/myelastic"
|
||||||
|
"public/myqueue"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ptr_que *myqueue.MyQueue = nil
|
||||||
|
var elastic myelastic.MyElastic
|
||||||
|
var isSaveFile bool = true //默认存文件
|
||||||
|
var isSaveToEs bool = false //默认不保存
|
||||||
|
var local_Log_file string = "log" //默认存放文件的目录
|
||||||
|
var exe_path string
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
if config.IsRunTesting() { //测试时候不创建
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
file, _ := exec.LookPath(os.Args[0])
|
||||||
|
path, _ := filepath.Abs(file)
|
||||||
|
exe_path = filepath.Dir(path)
|
||||||
|
|
||||||
|
BuildDir(local_Log_file)
|
||||||
|
ptr_que = myqueue.NewSyncQueue()
|
||||||
|
es_path := config.GetEsAddrUrl()
|
||||||
|
if len(es_path) > 0 {
|
||||||
|
elastic = myelastic.OnInitES(es_path)
|
||||||
|
elastic.CreateIndex(Http_log_index, mapping)
|
||||||
|
}
|
||||||
|
go onConsumerLog()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
发送日志请求
|
||||||
|
*/
|
||||||
|
func OnLog(es_index, es_type, es_id string, data LogInfo) {
|
||||||
|
// local, _ := time.LoadLocation("Local")
|
||||||
|
// data.Creat_time = time.Now().In(local)
|
||||||
|
b, err := json.Marshal(data.Data)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("OnLog error:", err)
|
||||||
|
}
|
||||||
|
data.Data = string(b)
|
||||||
|
var info EsLogInfo
|
||||||
|
info.Es_index = es_index
|
||||||
|
info.Es_type = es_type
|
||||||
|
info.Es_id = es_id
|
||||||
|
info.Info = data
|
||||||
|
|
||||||
|
ptr_que.Push(info) //加入日志队列
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
更新本地存储文件地址
|
||||||
|
isSave:是否本地存储
|
||||||
|
LogFile:本地存储相对程序位置(log/ ==> 当前可执行文件的 log/目录)
|
||||||
|
*/
|
||||||
|
func InitLogFileInfo(isSave, isSaveEs bool, LogFile string) {
|
||||||
|
isSaveFile = isSave
|
||||||
|
isSaveToEs = isSaveEs
|
||||||
|
local_Log_file = LogFile
|
||||||
|
if isSave {
|
||||||
|
BuildDir(local_Log_file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BuildDir(logfile string) {
|
||||||
|
os.MkdirAll(exe_path+"/"+logfile, os.ModePerm) //生成多级目录
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
消费者 消费日志
|
||||||
|
*/
|
||||||
|
func onConsumerLog() {
|
||||||
|
for {
|
||||||
|
var info EsLogInfo
|
||||||
|
info = ptr_que.Pop().(EsLogInfo)
|
||||||
|
|
||||||
|
if isSaveToEs && elastic.Client != nil {
|
||||||
|
if !elastic.Add(info.Es_index, info.Es_type, info.Es_id, info.Info) {
|
||||||
|
log.Println("elastic add error ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if isSaveFile {
|
||||||
|
saveLogTofile(info)
|
||||||
|
}
|
||||||
|
Debug(info)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var _f *os.File
|
||||||
|
var _err error
|
||||||
|
var saveFaile string
|
||||||
|
|
||||||
|
func saveLogTofile(info EsLogInfo) {
|
||||||
|
|
||||||
|
time_str := time.Now().Format("2006-01-02-15") //设定时间格式
|
||||||
|
fname := fmt.Sprintf("%s/%s/%s.log", exe_path, local_Log_file, time_str)
|
||||||
|
if saveFaile != fname {
|
||||||
|
if _f != nil {
|
||||||
|
_f.Close()
|
||||||
|
}
|
||||||
|
_f, _err = os.OpenFile(fname, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666)
|
||||||
|
if _err != nil {
|
||||||
|
log.Println(_err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b, _ := json.Marshal(info)
|
||||||
|
_f.WriteString(string(b) + "\r\n") //输出堆栈信息
|
||||||
|
}
|
101
mylog/mylog.go
Normal file
101
mylog/mylog.go
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
package mylog
|
||||||
|
|
||||||
|
import (
|
||||||
|
"data/config"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime/debug"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
file, _ := exec.LookPath(os.Args[0])
|
||||||
|
path, _ := filepath.Abs(file)
|
||||||
|
path = filepath.Dir(path)
|
||||||
|
os.MkdirAll(path+"/err", os.ModePerm) //生成多级目录
|
||||||
|
}
|
||||||
|
|
||||||
|
const ( //
|
||||||
|
Log_Error = iota //打印 Error 及以上级别
|
||||||
|
Log_warning //打印 warning 及以上级别
|
||||||
|
Log_Info //默认的返回值,为0,自增 //打印 Info 及以上级别
|
||||||
|
)
|
||||||
|
|
||||||
|
//
|
||||||
|
func Print(log_level int, describ string) {
|
||||||
|
log.Println(describ)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
func Println(describ ...interface{}) {
|
||||||
|
for _, e := range describ {
|
||||||
|
switch v := e.(type) {
|
||||||
|
case string:
|
||||||
|
log.Println(v)
|
||||||
|
case []byte:
|
||||||
|
log.Println(string(v))
|
||||||
|
default:
|
||||||
|
log.Println(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
func Info(describ string) {
|
||||||
|
log.Println(describ)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
func Error(err error) {
|
||||||
|
log.Println(err)
|
||||||
|
SaveError(err.Error(), "err")
|
||||||
|
}
|
||||||
|
|
||||||
|
//保存错误信息
|
||||||
|
func SaveError(errstring, flag string) {
|
||||||
|
file, _ := exec.LookPath(os.Args[0])
|
||||||
|
path, _ := filepath.Abs(file)
|
||||||
|
path = filepath.Dir(path)
|
||||||
|
|
||||||
|
now := time.Now() //获取当前时间
|
||||||
|
time_str := now.Format("2006-01-02_15") //设定时间格式
|
||||||
|
fname := fmt.Sprintf("%s/err/%s_%s.log", path, flag, time_str) //保存错误信息文件名:程序名-进程ID-当前时间(年月日时分秒)
|
||||||
|
|
||||||
|
f, err := os.OpenFile(fname, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
f.WriteString("=========================" + now.Format("2006-01-02 15:04:05 ========================= \r\n"))
|
||||||
|
f.WriteString(errstring + "\r\n") //输出堆栈信息
|
||||||
|
f.WriteString(string(debug.Stack()) + "\r\n") //输出堆栈信息)
|
||||||
|
f.WriteString("=========================end=========================\r\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
func Debug(describ ...interface{}) {
|
||||||
|
if config.OnIsDev() {
|
||||||
|
for _, e := range describ {
|
||||||
|
switch v := e.(type) {
|
||||||
|
case string:
|
||||||
|
log.Println(v)
|
||||||
|
case []byte:
|
||||||
|
log.Println(string(v))
|
||||||
|
default:
|
||||||
|
log.Println(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//刷新
|
||||||
|
func Flush() {
|
||||||
|
|
||||||
|
}
|
144
mynsq/mynsq.go
Normal file
144
mynsq/mynsq.go
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
package mynsq
|
||||||
|
|
||||||
|
import (
|
||||||
|
"data/config"
|
||||||
|
"log"
|
||||||
|
"public/mylog"
|
||||||
|
|
||||||
|
"github.com/nsqio/go-nsq"
|
||||||
|
)
|
||||||
|
|
||||||
|
var producer *nsq.Producer = nil
|
||||||
|
var consumerMap map[int]*nsq.Consumer = nil
|
||||||
|
var cosumerTopics map[string][]int = nil
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
consumerMap = make(map[int]*nsq.Consumer)
|
||||||
|
cosumerTopics = make(map[string][]int)
|
||||||
|
cnf := nsq.NewConfig()
|
||||||
|
var err error
|
||||||
|
producer, err = nsq.NewProducer(config.GetNsqAddr(), cnf)
|
||||||
|
if err != nil {
|
||||||
|
mylog.Print(mylog.Log_Error, err.Error())
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//发消息
|
||||||
|
func ProduceMsg(topic string, message []byte) bool {
|
||||||
|
|
||||||
|
if producer == nil {
|
||||||
|
//channel 锁住
|
||||||
|
cnf := nsq.NewConfig()
|
||||||
|
var err error
|
||||||
|
producer, err = nsq.NewProducer(config.GetNsqAddr(), cnf)
|
||||||
|
if err != nil {
|
||||||
|
mylog.Print(mylog.Log_Error, err.Error())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if producer != nil {
|
||||||
|
err := producer.Publish(topic, message)
|
||||||
|
if err != nil {
|
||||||
|
mylog.Print(mylog.Log_Error, err.Error())
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
//单个nsqd处理消息
|
||||||
|
//index 表示consumer 索引(用于开关使用)
|
||||||
|
func StartConsumeMsg(index int, topic, channel, nsqd string, handler nsq.Handler) bool {
|
||||||
|
StopConsumeMsgByIndex(index)
|
||||||
|
//第一次初始化 进入
|
||||||
|
if consumerMap[index] == nil {
|
||||||
|
conf := nsq.NewConfig()
|
||||||
|
//最大允许向两台NSQD服务器接受消息,默认是1
|
||||||
|
//config.MaxInFlight = 2
|
||||||
|
var err error
|
||||||
|
consumerMap[index], err = nsq.NewConsumer(topic, channel, conf)
|
||||||
|
if nil != err {
|
||||||
|
log.Println(err)
|
||||||
|
mylog.Print(mylog.Log_Error, err.Error())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
//开始正式启动(后台,非阻塞方式)
|
||||||
|
consumerMap[index].AddHandler(handler)
|
||||||
|
err = consumerMap[index].ConnectToNSQD(nsqd)
|
||||||
|
if nil != err {
|
||||||
|
log.Println(err)
|
||||||
|
mylog.Print(mylog.Log_Error, err.Error())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
cosumerTopics[topic] = append(cosumerTopics[topic], index)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetConsumeSize() int {
|
||||||
|
return len(consumerMap)
|
||||||
|
}
|
||||||
|
|
||||||
|
//停止消费
|
||||||
|
func StopConsumeMsgByIndex(index int) {
|
||||||
|
if consumerMap[index] != nil {
|
||||||
|
consumerMap[index].Stop()
|
||||||
|
consumerMap[index] = nil
|
||||||
|
|
||||||
|
for k, v := range cosumerTopics {
|
||||||
|
for i := range v {
|
||||||
|
if v[i] == index {
|
||||||
|
cosumerTopics[k] = append(v[:i], v[i+1:]...)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//停止某个topic下全部消费
|
||||||
|
func StopConsumeMsgByTopic(topic string) {
|
||||||
|
v, ok := cosumerTopics[topic]
|
||||||
|
if ok {
|
||||||
|
for i := range v {
|
||||||
|
if consumerMap[v[i]] != nil {
|
||||||
|
consumerMap[v[i]].Stop()
|
||||||
|
consumerMap[v[i]] = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var temp []int
|
||||||
|
cosumerTopics[topic] = temp
|
||||||
|
}
|
||||||
|
|
||||||
|
//停止所有topic的全部消费
|
||||||
|
func StopAllConsumeMsg() {
|
||||||
|
cosumerTopics = make(map[string][]int)
|
||||||
|
size := GetConsumeSize()
|
||||||
|
for i := 0; i < size; i++ {
|
||||||
|
StopConsumeMsgByIndex(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
consumerMap = make(map[int]*nsq.Consumer)
|
||||||
|
}
|
||||||
|
|
||||||
|
//func TestNSQ() {
|
||||||
|
// for k, v := range cosumerTopics {
|
||||||
|
// log.Println("topic is", k)
|
||||||
|
// for _, vv := range v {
|
||||||
|
// log.Println("consumer index is", vv)
|
||||||
|
// log.Println("consumer is ", consumerMap[vv])
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
89
myqueue/myqueue.go
Normal file
89
myqueue/myqueue.go
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
package myqueue
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"gopkg.in/eapache/queue.v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MyQueue struct {
|
||||||
|
lock sync.Mutex
|
||||||
|
popable *sync.Cond
|
||||||
|
buffer *queue.Queue
|
||||||
|
closed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建
|
||||||
|
func NewSyncQueue() *MyQueue {
|
||||||
|
ch := &MyQueue{
|
||||||
|
buffer: queue.New(),
|
||||||
|
}
|
||||||
|
ch.popable = sync.NewCond(&ch.lock)
|
||||||
|
return ch
|
||||||
|
}
|
||||||
|
|
||||||
|
// 取出队列,(阻塞模式)
|
||||||
|
func (q *MyQueue) Pop() (v interface{}) {
|
||||||
|
c := q.popable
|
||||||
|
buffer := q.buffer
|
||||||
|
|
||||||
|
q.lock.Lock()
|
||||||
|
for buffer.Length() == 0 && !q.closed {
|
||||||
|
c.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
if buffer.Length() > 0 {
|
||||||
|
v = buffer.Peek()
|
||||||
|
buffer.Remove()
|
||||||
|
}
|
||||||
|
|
||||||
|
q.lock.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//试着取出队列(非阻塞模式)返回ok == false 表示空
|
||||||
|
func (q *MyQueue) TryPop() (v interface{}, ok bool) {
|
||||||
|
buffer := q.buffer
|
||||||
|
|
||||||
|
q.lock.Lock()
|
||||||
|
|
||||||
|
if buffer.Length() > 0 {
|
||||||
|
v = buffer.Peek()
|
||||||
|
buffer.Remove()
|
||||||
|
ok = true
|
||||||
|
} else if q.closed {
|
||||||
|
ok = true
|
||||||
|
}
|
||||||
|
|
||||||
|
q.lock.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 插入队列,非阻塞
|
||||||
|
func (q *MyQueue) Push(v interface{}) {
|
||||||
|
q.lock.Lock()
|
||||||
|
if !q.closed {
|
||||||
|
q.buffer.Add(v)
|
||||||
|
q.popable.Signal()
|
||||||
|
}
|
||||||
|
q.lock.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取队列长度
|
||||||
|
func (q *MyQueue) Len() (l int) {
|
||||||
|
q.lock.Lock()
|
||||||
|
l = q.buffer.Length()
|
||||||
|
q.lock.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close MyQueue
|
||||||
|
// After close, Pop will return nil without block, and TryPop will return v=nil, ok=True
|
||||||
|
func (q *MyQueue) Close() {
|
||||||
|
q.lock.Lock()
|
||||||
|
if !q.closed {
|
||||||
|
q.closed = true
|
||||||
|
q.popable.Signal()
|
||||||
|
}
|
||||||
|
q.lock.Unlock()
|
||||||
|
}
|
9
myrunner/error.go
Normal file
9
myrunner/error.go
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package myrunner
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
//任务执行超时
|
||||||
|
var ErrTimeOut = errors.New("run time out")
|
||||||
|
|
||||||
|
//任务执行中断
|
||||||
|
var ErrInterruput = errors.New("run interruput")
|
102
myrunner/myrunner.go
Normal file
102
myrunner/myrunner.go
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
package myrunner
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
//后台执行任何限时任务,而且我们还可以控制这个执行者,比如强制终止它等
|
||||||
|
type Runner struct {
|
||||||
|
tasks []func() //要执行的任务
|
||||||
|
complete chan error //用于通知任务全部完成
|
||||||
|
timeout <-chan time.Time //这些任务在多久内完成 只能接收
|
||||||
|
interrupt chan os.Signal //可以控制强制终止的信号
|
||||||
|
}
|
||||||
|
|
||||||
|
//工厂方法
|
||||||
|
func New(tm time.Duration) *Runner {
|
||||||
|
return &Runner{
|
||||||
|
complete: make(chan error), //同步通道,main routine等待,一致要任务完成或者被强制终止
|
||||||
|
timeout: time.After(tm),
|
||||||
|
interrupt: make(chan os.Signal, 1), //至少接收到一个操作系统的中断信息
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
func (r *Runner) Add(tasks ...func()) {
|
||||||
|
r.tasks = append(r.tasks, tasks...)
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
func (r *Runner) run() error {
|
||||||
|
for _, task := range r.tasks {
|
||||||
|
if r.isInterrupt() {
|
||||||
|
return ErrInterruput
|
||||||
|
}
|
||||||
|
task()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//检查是否接收到了中断信号
|
||||||
|
func (r *Runner) isInterrupt() bool {
|
||||||
|
select {
|
||||||
|
case <-r.interrupt:
|
||||||
|
signal.Stop(r.interrupt)
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//开始执行所有任务,并且监视通道事件
|
||||||
|
func (r *Runner) Start() error {
|
||||||
|
//希望接收哪些系统信号
|
||||||
|
signal.Notify(r.interrupt, os.Interrupt) //如果有系统中断的信号,发给r.interrupt
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
r.complete <- r.run()
|
||||||
|
}()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case err := <-r.complete:
|
||||||
|
return err
|
||||||
|
case <-r.timeout:
|
||||||
|
return ErrTimeOut
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
调用示例:
|
||||||
|
func main() {
|
||||||
|
log.Println("...开始执行任务...")
|
||||||
|
|
||||||
|
timeout := 2 * time.Second
|
||||||
|
r := New(timeout)
|
||||||
|
|
||||||
|
r.Add(createTask(0), createTask(1), createTask(2))
|
||||||
|
|
||||||
|
if err := r.Start(); err != nil {
|
||||||
|
switch err {
|
||||||
|
case ErrTimeOut:
|
||||||
|
log.Println(err)
|
||||||
|
os.Exit(1) //退出
|
||||||
|
case ErrInterruput:
|
||||||
|
log.Println(err)
|
||||||
|
os.Exit(2)
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Println("...任务执行结束...")
|
||||||
|
}
|
||||||
|
|
||||||
|
func createTask(param int) func() {
|
||||||
|
return func() {
|
||||||
|
log.Printf("正在执行任务%d", param)
|
||||||
|
time.Sleep(time.Duration(param) * time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
24
mysign/def.go
Normal file
24
mysign/def.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package mysign
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
const (
|
||||||
|
_sign_data = "_sign_data"
|
||||||
|
)
|
||||||
|
|
||||||
|
//签名地址
|
||||||
|
type Sign_client_tbl struct {
|
||||||
|
Id int `gorm:"primary_key"`
|
||||||
|
App_key string //key
|
||||||
|
App_secret string //secret
|
||||||
|
Expire_time time.Time //超时时间
|
||||||
|
Strict_sign int //是否强制验签:0:用户自定义,1:强制
|
||||||
|
Strict_verify int //是否强制验证:0:用户自定义,1:强制
|
||||||
|
Token_expire_time int //token过期时间
|
||||||
|
}
|
||||||
|
|
||||||
|
//签名必须带的头标记
|
||||||
|
type Sing_head struct {
|
||||||
|
Appid string `json:"appid,omitempty"` //appid
|
||||||
|
Signature string `json:"signature,omitempty"` //签名
|
||||||
|
}
|
96
mysign/sign.go
Normal file
96
mysign/sign.go
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
package mysign
|
||||||
|
|
||||||
|
import (
|
||||||
|
"data/config"
|
||||||
|
"public/mycache"
|
||||||
|
"public/mylog"
|
||||||
|
"public/mysqldb"
|
||||||
|
"public/tools"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
OnInit()
|
||||||
|
}
|
||||||
|
|
||||||
|
func OnInit() {
|
||||||
|
str_db := config.GetDbUrl()
|
||||||
|
//fmt.Println("dddddddddddddd:", str_db)
|
||||||
|
if len(str_db) > 0 {
|
||||||
|
var db mysqldb.MySqlDB
|
||||||
|
defer db.OnDestoryDB()
|
||||||
|
orm := db.OnGetDBOrm(str_db)
|
||||||
|
if orm.HasTable(&Sign_client_tbl{}) { //有这个表
|
||||||
|
now := time.Now()
|
||||||
|
var list []Sign_client_tbl
|
||||||
|
err := orm.Where("expire_time > ?", now).Find(&list).Error
|
||||||
|
if err != nil {
|
||||||
|
mylog.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cache := mycache.OnGetCache(_sign_data)
|
||||||
|
for _, v := range list { //保存数据到缓存
|
||||||
|
cache.Add(v.App_key, v, v.Expire_time.Sub(now))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetOne(appKey string) (sign Sign_client_tbl) {
|
||||||
|
cache := mycache.OnGetCache(_sign_data)
|
||||||
|
tp, b := cache.Value(appKey)
|
||||||
|
if b {
|
||||||
|
sign = tp.(Sign_client_tbl)
|
||||||
|
} else {
|
||||||
|
str_db := config.GetDbUrl()
|
||||||
|
if len(str_db) > 0 {
|
||||||
|
var db mysqldb.MySqlDB
|
||||||
|
defer db.OnDestoryDB()
|
||||||
|
orm := db.OnGetDBOrm(str_db)
|
||||||
|
if orm.HasTable(&Sign_client_tbl{}) { //有这个表
|
||||||
|
now := time.Now()
|
||||||
|
err := orm.Where("app_key = ? and expire_time > ?", appKey, now).Find(&sign).Error
|
||||||
|
if err != nil {
|
||||||
|
mylog.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cache := mycache.OnGetCache(_sign_data)
|
||||||
|
cache.Add(sign.App_key, sign, sign.Expire_time.Sub(now))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
生成验签
|
||||||
|
*/
|
||||||
|
func OnGetSign(appkey string, parm ...interface{}) string {
|
||||||
|
var sign Sign_client_tbl
|
||||||
|
if len(appkey) > 0 {
|
||||||
|
sign = GetOne(appkey)
|
||||||
|
}
|
||||||
|
//是否强制验证码
|
||||||
|
if sign.Id == 0 || sign.Strict_sign == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
//开始验签
|
||||||
|
var strKey string
|
||||||
|
for _, v := range parm {
|
||||||
|
strKey += tools.AsString(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
mylog.Debug("strKey:" + strKey)
|
||||||
|
mylog.Debug("md5:", tools.Md5Encoder(strKey))
|
||||||
|
return tools.Md5Encoder(strKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
开始验签
|
||||||
|
*/
|
||||||
|
func OnCheckSign(appkey, signature string, parm ...interface{}) bool {
|
||||||
|
return strings.EqualFold(signature, OnGetSign(appkey, parm...))
|
||||||
|
}
|
20
mysign/sign_test.go
Normal file
20
mysign/sign_test.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package mysign
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"public/message"
|
||||||
|
"public/tools"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_sing(t *testing.T) {
|
||||||
|
now := time.Now()
|
||||||
|
str := "1" + tools.GetTimeString(now)
|
||||||
|
str += "1.0001"
|
||||||
|
fmt.Println(str)
|
||||||
|
ttt := tools.Md5Encoder(str)
|
||||||
|
fmt.Println(ttt)
|
||||||
|
fmt.Println(OnCheckSign("wwwthings", ttt, 1, now, 1.0001))
|
||||||
|
fmt.Println(message.GetSuccessMsg())
|
||||||
|
}
|
59
mysqlbeedb/mysqlbeedb.go
Normal file
59
mysqlbeedb/mysqlbeedb.go
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
orm := db.OnCreatDB()
|
||||||
|
var sum int64 = 0
|
||||||
|
for {
|
||||||
|
sum++
|
||||||
|
var user User_account_tbl
|
||||||
|
user.Id = sum
|
||||||
|
|
||||||
|
orm.SetTable("user_account_tbls")
|
||||||
|
err := orm.Where("id=?", sum).Find(&user)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("-----------:", err)
|
||||||
|
} else {
|
||||||
|
log.Println(user)
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(time.Second * 2)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
package mysqlbeedb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"public/mylog"
|
||||||
|
|
||||||
|
"data/config"
|
||||||
|
|
||||||
|
"github.com/astaxie/beedb"
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MySqlDB struct {
|
||||||
|
DB *sql.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *MySqlDB) OnGetDBOrm(dataSourceName string) (orm beedb.Model) {
|
||||||
|
if i.DB == nil {
|
||||||
|
var err error
|
||||||
|
i.DB, err = sql.Open("mysql", dataSourceName)
|
||||||
|
if err != nil {
|
||||||
|
mylog.Print(mylog.Log_Error, fmt.Sprintf("Got error when connect database, the error is '%v'", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
orm = beedb.New(i.DB)
|
||||||
|
|
||||||
|
if config.OnIsDev() {
|
||||||
|
beedb.OnDebug = true
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *MySqlDB) OnDestoryDB() {
|
||||||
|
if i.DB != nil {
|
||||||
|
i.DB.Close()
|
||||||
|
i.DB = nil
|
||||||
|
}
|
||||||
|
}
|
36
mysqldb/log.go
Normal file
36
mysqldb/log.go
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package mysqldb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"public/mylog"
|
||||||
|
|
||||||
|
"github.com/jinzhu/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
var LogFormatter = func(values ...interface{}) (messages []interface{}) {
|
||||||
|
if len(values) > 1 {
|
||||||
|
var (
|
||||||
|
currentTime = "\t[" + gorm.NowFunc().Format("2006-01-02 15:04:05") + "]"
|
||||||
|
source = fmt.Sprintf("(%v)\t", values[1])
|
||||||
|
)
|
||||||
|
messages = []interface{}{source, currentTime}
|
||||||
|
messages = append(messages, "\t [")
|
||||||
|
messages = append(messages, values[2:]...)
|
||||||
|
messages = append(messages, "]")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
type DbLog struct {
|
||||||
|
gorm.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
func (db DbLog) Print(values ...interface{}) {
|
||||||
|
msg := LogFormatter(values...)
|
||||||
|
str := fmt.Sprint(msg...)
|
||||||
|
mylog.SaveError(str, "sql")
|
||||||
|
}
|
66
mysqldb/mysqldb.go
Normal file
66
mysqldb/mysqldb.go
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
orm := db.OnCreatDB()
|
||||||
|
var sum int64 = 0
|
||||||
|
for {
|
||||||
|
sum++
|
||||||
|
var user User_account_tbl
|
||||||
|
user.Id = sum
|
||||||
|
|
||||||
|
orm.SetTable("user_account_tbls")
|
||||||
|
err := orm.Where("id=?", sum).Find(&user)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("-----------:", err)
|
||||||
|
} else {
|
||||||
|
log.Println(user)
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(time.Second * 2)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
package mysqldb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"public/mylog"
|
||||||
|
|
||||||
|
"data/config"
|
||||||
|
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
"github.com/jinzhu/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MySqlDB struct {
|
||||||
|
DB *gorm.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *MySqlDB) OnGetDBOrm(dataSourceName string) (orm *gorm.DB) {
|
||||||
|
if i.DB == nil {
|
||||||
|
var err error
|
||||||
|
i.DB, err = gorm.Open("mysql", dataSourceName)
|
||||||
|
if err != nil {
|
||||||
|
mylog.Print(mylog.Log_Error, fmt.Sprintf("Got error when connect database, the error is '%v'", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i.DB.SingularTable(true) //全局禁用表名复数
|
||||||
|
orm = i.DB
|
||||||
|
|
||||||
|
if config.OnIsDev() {
|
||||||
|
orm.LogMode(true)
|
||||||
|
//beedb.OnDebug = true
|
||||||
|
} else {
|
||||||
|
orm.SetLogger(DbLog{})
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *MySqlDB) OnDestoryDB() {
|
||||||
|
if i.DB != nil {
|
||||||
|
i.DB.Close()
|
||||||
|
i.DB = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
|
||||||
|
}
|
BIN
mysqldb/mysqldb2018-05-04.rar
Normal file
BIN
mysqldb/mysqldb2018-05-04.rar
Normal file
Binary file not shown.
208
mywebsocket/mywebsocket.go
Normal file
208
mywebsocket/mywebsocket.go
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
package mywebsocket
|
||||||
|
|
||||||
|
/*
|
||||||
|
说明:第一个包 初始化client唯一id。消息id为100
|
||||||
|
*/
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
"public/mycache"
|
||||||
|
"public/mylog"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/ant0ine/go-json-rest/rest"
|
||||||
|
|
||||||
|
"golang.org/x/net/websocket"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ClientBody struct {
|
||||||
|
Code int `json:"code,omitempty"`
|
||||||
|
Data interface{} `json:"data,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type WSMessageType uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
WS_Login WSMessageType = 1 // 链接
|
||||||
|
WS_Close WSMessageType = 2 // 断线
|
||||||
|
)
|
||||||
|
|
||||||
|
type HandlerReadFunc func(string, string, ClientBody, *websocket.Conn) //ID , MESSAGEID,内容
|
||||||
|
type HandlerStateFunc func(string, string, WSMessageType) //状态发声改变回调
|
||||||
|
|
||||||
|
var mutex sync.Mutex
|
||||||
|
|
||||||
|
/*
|
||||||
|
写数据
|
||||||
|
pathExp:请求的根路径
|
||||||
|
clientid:发送人id
|
||||||
|
body:发送内容
|
||||||
|
*/
|
||||||
|
func WriteData(pathExp string, clientid string, body ClientBody) bool {
|
||||||
|
|
||||||
|
wb, err := json.Marshal(body)
|
||||||
|
if err != nil {
|
||||||
|
mylog.Debug("error:", err.Error())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
cache := mycache.OnGetCache("websocket" + pathExp)
|
||||||
|
tp, b := cache.Value(clientid)
|
||||||
|
|
||||||
|
if b {
|
||||||
|
b_r := false
|
||||||
|
tmp := tp.([]*websocket.Conn)
|
||||||
|
for i := 0; i < len(tmp); i++ {
|
||||||
|
if _, err = tmp[i].Write(wb); err != nil {
|
||||||
|
mylog.Debug("Can't send", err.Error())
|
||||||
|
defer tmp[i].Close()
|
||||||
|
} else {
|
||||||
|
b_r = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return b_r
|
||||||
|
} else {
|
||||||
|
mylog.Debug("not find client:" + clientid)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//websocket 初始化接口
|
||||||
|
/*
|
||||||
|
pathExp 域,
|
||||||
|
handlerFunc 读到的消息回调
|
||||||
|
stateFunc 连接消息回调
|
||||||
|
timeOut 读取超时回调(0则永不超时)
|
||||||
|
isMult 是否多用户登录
|
||||||
|
*/
|
||||||
|
func InitWebSocket(pathExp string, handlerFunc HandlerReadFunc, stateFunc HandlerStateFunc, timeOut time.Duration, isMult bool) *rest.Route {
|
||||||
|
wsHandler := websocket.Handler(func(ws *websocket.Conn) {
|
||||||
|
mylog.Debug("enter")
|
||||||
|
var err error
|
||||||
|
var msg = make([]byte, 1024)
|
||||||
|
var n int
|
||||||
|
n, err = ws.Read(msg)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
mylog.Debug("ws:close")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var clientid string
|
||||||
|
var clientBody ClientBody
|
||||||
|
|
||||||
|
err = json.Unmarshal(msg[:n], &clientBody)
|
||||||
|
if err != nil {
|
||||||
|
mylog.Debug("Unmarshal:" + err.Error())
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
if clientBody.Code != 100 {
|
||||||
|
mylog.Debug("messageid error")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
clientid = clientBody.Data.(string)
|
||||||
|
//保存缓存
|
||||||
|
cache := mycache.OnGetCache("websocket" + pathExp)
|
||||||
|
var tmp []*websocket.Conn
|
||||||
|
|
||||||
|
mutex.Lock()
|
||||||
|
|
||||||
|
tp, b := cache.Value(clientid)
|
||||||
|
if b && isMult { //多用户
|
||||||
|
tmp = tp.([]*websocket.Conn)
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = append(tmp, ws)
|
||||||
|
cache.Add(clientid, tmp, 2*time.Hour) //2小时过期
|
||||||
|
mutex.Unlock()
|
||||||
|
|
||||||
|
//------------------end
|
||||||
|
mylog.Debug("init success:" + clientid)
|
||||||
|
if stateFunc != nil {
|
||||||
|
stateFunc(pathExp, clientid, WS_Login)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ch := make(chan bool, 1)
|
||||||
|
if timeOut > 0 {
|
||||||
|
go func(ws *websocket.Conn) {
|
||||||
|
var after <-chan time.Time
|
||||||
|
loop:
|
||||||
|
after = time.After(timeOut)
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case b := <-ch: //继续下一个等待
|
||||||
|
if !b {
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
goto loop
|
||||||
|
}
|
||||||
|
case <-after: //超时处理
|
||||||
|
mylog.Print(mylog.Log_Info, "time out:"+clientid)
|
||||||
|
ws.Close()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}(ws)
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
n, err = ws.Read(msg)
|
||||||
|
if err != nil {
|
||||||
|
if timeOut > 0 {
|
||||||
|
ch <- false
|
||||||
|
}
|
||||||
|
mylog.Debug("ws:close")
|
||||||
|
break
|
||||||
|
} else if timeOut > 0 {
|
||||||
|
ch <- true
|
||||||
|
}
|
||||||
|
var body ClientBody
|
||||||
|
err = json.Unmarshal(msg[:n], &body)
|
||||||
|
if err != nil {
|
||||||
|
mylog.Debug("r:" + err.Error())
|
||||||
|
} else {
|
||||||
|
if handlerFunc != nil {
|
||||||
|
handlerFunc(pathExp, clientid, body, ws)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//删除缓存
|
||||||
|
cache := mycache.OnGetCache("websocket" + pathExp)
|
||||||
|
var tmp []*websocket.Conn
|
||||||
|
|
||||||
|
mutex.Lock()
|
||||||
|
tp, b := cache.Value(clientid)
|
||||||
|
if b {
|
||||||
|
tmp = tp.([]*websocket.Conn)
|
||||||
|
}
|
||||||
|
i := 0
|
||||||
|
for ; i < len(tmp); i++ {
|
||||||
|
if tmp[i] == ws {
|
||||||
|
tmp = append(tmp[:i], tmp[i+1:]...) // 最后面的“...”不能省略
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if i == 0 || len(tmp) == 0 || !isMult {
|
||||||
|
cache.Delete(clientid)
|
||||||
|
mylog.Debug("delete all: " + clientid)
|
||||||
|
} else {
|
||||||
|
cache.Add(clientid, tmp, 2*time.Hour) //2小时过期
|
||||||
|
mylog.Debug("delete one: " + clientid)
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex.Unlock()
|
||||||
|
if stateFunc != nil {
|
||||||
|
stateFunc(pathExp, clientid, WS_Close)
|
||||||
|
}
|
||||||
|
//------------------end
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
return rest.Get(pathExp, func(w rest.ResponseWriter, r *rest.Request) {
|
||||||
|
//mylog.Debug("-------------")
|
||||||
|
wsHandler.ServeHTTP(w.(http.ResponseWriter), r.Request)
|
||||||
|
})
|
||||||
|
}
|
41
serializing/serializing.go
Normal file
41
serializing/serializing.go
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package serializing
|
||||||
|
|
||||||
|
import(
|
||||||
|
"bytes"
|
||||||
|
"encoding/gob"
|
||||||
|
)
|
||||||
|
/*
|
||||||
|
适用类型:二进制到struct相互转换
|
||||||
|
|
||||||
|
使用方法:
|
||||||
|
b, err := serializing.Encode(data)
|
||||||
|
if err != nil {
|
||||||
|
//错误处理
|
||||||
|
}
|
||||||
|
if err := serializing.Decode(b, &to); err != nil {
|
||||||
|
//错误处理
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
功能:序列化
|
||||||
|
*/
|
||||||
|
func Encode(data interface{})([]byte, error){
|
||||||
|
buf := bytes.NewBuffer(nil)
|
||||||
|
enc := gob.NewEncoder(buf)
|
||||||
|
err := enc.Encode(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return buf.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
功能:反序列化
|
||||||
|
*/
|
||||||
|
func Decode(data []byte,to interface{}) error{
|
||||||
|
buf := bytes.NewBuffer(data)
|
||||||
|
dec := gob.NewDecoder(buf)
|
||||||
|
return dec.Decode(to)
|
||||||
|
}
|
12
server/def.go
Normal file
12
server/def.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
const (
|
||||||
|
Stopped = 1
|
||||||
|
StartPending = 2
|
||||||
|
StopPending = 3
|
||||||
|
Running = 4
|
||||||
|
ContinuePending = 5
|
||||||
|
PausePending = 6
|
||||||
|
Paused = 7
|
||||||
|
NOTFIND = 8
|
||||||
|
)
|
137
server/server.go
Normal file
137
server/server.go
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"data/config"
|
||||||
|
|
||||||
|
"github.com/jander/golog/logger"
|
||||||
|
"github.com/kardianos/service"
|
||||||
|
)
|
||||||
|
|
||||||
|
func OnStart(callBack func()) {
|
||||||
|
name, displayName, desc := config.GetServiceConfig()
|
||||||
|
p := &program{callBack}
|
||||||
|
sc := &service.Config{
|
||||||
|
Name: name,
|
||||||
|
DisplayName: displayName,
|
||||||
|
Description: desc,
|
||||||
|
}
|
||||||
|
s, err := service.New(p, sc)
|
||||||
|
//var s, err = service.NewService(name, displayName, desc)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("%s unable to start: %s", displayName, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Service \"%s\" do.\n", displayName)
|
||||||
|
|
||||||
|
if len(os.Args) > 1 {
|
||||||
|
var err error
|
||||||
|
verb := os.Args[1]
|
||||||
|
switch verb {
|
||||||
|
case "install":
|
||||||
|
{
|
||||||
|
err = s.Install()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Failed to install: %s\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Printf("Service \"%s\" installed.\n", displayName)
|
||||||
|
}
|
||||||
|
case "remove":
|
||||||
|
{
|
||||||
|
err = s.Uninstall()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Failed to remove: %s\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Printf("Service \"%s\" removed.\n", displayName)
|
||||||
|
}
|
||||||
|
case "run":
|
||||||
|
{
|
||||||
|
err = s.Run()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Failed to run: %s\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Printf("Service \"%s\" run.\n", displayName)
|
||||||
|
}
|
||||||
|
case "start":
|
||||||
|
{
|
||||||
|
err = s.Start()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Failed to start: %s\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println("starting check service:", displayName)
|
||||||
|
|
||||||
|
ticker := time.NewTicker(1 * time.Second)
|
||||||
|
<-ticker.C
|
||||||
|
|
||||||
|
st, err := IsStart(name)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
if st == Stopped || st == StopPending {
|
||||||
|
fmt.Printf("Service \"%s\" is Stopped.\n", displayName)
|
||||||
|
fmt.Println("can't to start service.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Printf("Service \"%s\" started.\n", displayName)
|
||||||
|
}
|
||||||
|
case "stop":
|
||||||
|
{
|
||||||
|
err = s.Stop()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Failed to stop: %s\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
st, err := IsStart(name)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
if st == Running || st == StartPending {
|
||||||
|
fmt.Printf("Service \"%s\" is Started.\n", displayName)
|
||||||
|
fmt.Println("can't to stop service.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Printf("Service \"%s\" stopped.\n", displayName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
fmt.Print("Failed to read args\n")
|
||||||
|
//return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = s.Run(); err != nil {
|
||||||
|
logger.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type program struct {
|
||||||
|
callBack func()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *program) Start(s service.Service) error {
|
||||||
|
go p.run()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (p *program) run() {
|
||||||
|
p.callBack()
|
||||||
|
}
|
||||||
|
func (p *program) Stop(s service.Service) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type ServiceTools interface {
|
||||||
|
IsStart(name string) (status int, err error)
|
||||||
|
}
|
32
server/server_linux.go
Normal file
32
server/server_linux.go
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WindowsServiceTools struct {
|
||||||
|
i ServiceTools
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsStart(name string) (st int, err error) {
|
||||||
|
f, _ := exec.Command("service", name, "status").Output()
|
||||||
|
|
||||||
|
st = NOTFIND
|
||||||
|
str := string(f)
|
||||||
|
a := strings.Split(str, "\n")
|
||||||
|
for _, v := range a {
|
||||||
|
if strings.Index(v, "Active:") > 0 {
|
||||||
|
fmt.Println("====info===:", v)
|
||||||
|
if strings.Index(v, "inactive") > 0 { //不活动的
|
||||||
|
st = Stopped
|
||||||
|
} else if strings.Index(v, "activating") > 0 { //活动的
|
||||||
|
st = Running
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
30
server/server_windows.go
Normal file
30
server/server_windows.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/btcsuite/winsvc/mgr"
|
||||||
|
"github.com/btcsuite/winsvc/svc"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WindowsServiceTools struct {
|
||||||
|
i ServiceTools
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsStart(name string) (st int, err error) {
|
||||||
|
var m *mgr.Mgr
|
||||||
|
m, err = mgr.Connect()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
defer m.Disconnect()
|
||||||
|
|
||||||
|
s, err := m.OpenService(name)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
defer s.Close()
|
||||||
|
|
||||||
|
var ss svc.Status
|
||||||
|
ss, err = s.Query()
|
||||||
|
st = int(ss.State)
|
||||||
|
return
|
||||||
|
}
|
15
sign/def.go
Normal file
15
sign/def.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package sign
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
const (
|
||||||
|
_sign_data = "_sign_data"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Sign_client_tbl struct {
|
||||||
|
Id int `gorm:"primary_key"`
|
||||||
|
App_key string //key
|
||||||
|
App_secret string //secret
|
||||||
|
Expire_time time.Time //超时时间
|
||||||
|
Strict_verify int //是否强制验证:0:用户自定义,1:强制
|
||||||
|
}
|
93
sign/sign.go
Normal file
93
sign/sign.go
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
package sign
|
||||||
|
|
||||||
|
import (
|
||||||
|
"data/config"
|
||||||
|
"public/mycache"
|
||||||
|
"public/mylog"
|
||||||
|
"public/mysqldb"
|
||||||
|
"public/tools"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
OnInit()
|
||||||
|
}
|
||||||
|
|
||||||
|
func OnInit() {
|
||||||
|
str_db := config.GetDbUrl()
|
||||||
|
if len(str_db) > 0 {
|
||||||
|
var db mysqldb.MySqlDB
|
||||||
|
defer db.OnDestoryDB()
|
||||||
|
orm := db.OnGetDBOrm(str_db)
|
||||||
|
if orm.HasTable(&Sign_client_tbl{}) { //有这个表
|
||||||
|
now := time.Now()
|
||||||
|
var list []Sign_client_tbl
|
||||||
|
err := orm.Where("expire_time > ?", now).Find(&list).Error
|
||||||
|
if err != nil {
|
||||||
|
mylog.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cache := mycache.OnGetCache(_sign_data)
|
||||||
|
for _, v := range list { //保存数据到缓存
|
||||||
|
cache.Add(v.App_key, v, v.Expire_time.Sub(now))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getOne(appKey string) (sign Sign_client_tbl) {
|
||||||
|
str_db := config.GetDbUrl()
|
||||||
|
if len(str_db) > 0 {
|
||||||
|
var db mysqldb.MySqlDB
|
||||||
|
defer db.OnDestoryDB()
|
||||||
|
orm := db.OnGetDBOrm(str_db)
|
||||||
|
if orm.HasTable(&Sign_client_tbl{}) { //有这个表
|
||||||
|
now := time.Now()
|
||||||
|
err := orm.Where("app_key = ? and expire_time > ?", appKey, now).Find(&sign).Error
|
||||||
|
if err != nil {
|
||||||
|
mylog.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cache := mycache.OnGetCache(_sign_data)
|
||||||
|
cache.Add(sign.App_key, sign, sign.Expire_time.Sub(now))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
生成验签
|
||||||
|
*/
|
||||||
|
func OnGetSign(appkey string, parm ...interface{}) string {
|
||||||
|
var sign Sign_client_tbl
|
||||||
|
if len(appkey) > 0 {
|
||||||
|
cache := mycache.OnGetCache(_sign_data)
|
||||||
|
tp, b := cache.Value(appkey)
|
||||||
|
if b {
|
||||||
|
sign = tp.(Sign_client_tbl)
|
||||||
|
} else {
|
||||||
|
sign = getOne(appkey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if sign.Id == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
//开始验签
|
||||||
|
var strKey string
|
||||||
|
for _, v := range parm {
|
||||||
|
strKey += tools.AsString(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return tools.Md5Encoder(strKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
开始验签
|
||||||
|
*/
|
||||||
|
func OnCheckSign(appkey, signature string, parm ...interface{}) bool {
|
||||||
|
return strings.EqualFold(signature, OnGetSign(appkey, parm))
|
||||||
|
}
|
20
sign/sign_test.go
Normal file
20
sign/sign_test.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package sign
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"public/message"
|
||||||
|
"public/tools"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_sing(t *testing.T) {
|
||||||
|
now := time.Now()
|
||||||
|
str := "1" + tools.GetTimeString(now)
|
||||||
|
str += "1.0001"
|
||||||
|
fmt.Println(str)
|
||||||
|
ttt := tools.Md5Encoder(str)
|
||||||
|
fmt.Println(ttt)
|
||||||
|
fmt.Println(OnCheckSign("wwwthings", ttt, 1, now, 1.0001))
|
||||||
|
fmt.Println(message.GetSuccessMsg())
|
||||||
|
}
|
8
timerDeal/cron.go
Normal file
8
timerDeal/cron.go
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package timerDeal
|
||||||
|
|
||||||
|
//cron
|
||||||
|
// c := cron.New()
|
||||||
|
// c.AddFunc("0 30 * * * *", func() { fmt.Println("Every hour on the half hour") })
|
||||||
|
// c.AddFunc("@hourly", func() { fmt.Println("Every hour") })
|
||||||
|
// c.AddFunc("@every 1h30m", func() { fmt.Println("Every hour thirty") })
|
||||||
|
// c.Start()
|
37
timerDeal/timerDeal.go
Normal file
37
timerDeal/timerDeal.go
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package timerDeal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TimerDeal struct {
|
||||||
|
f_list []func()
|
||||||
|
f_d_timeout time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
//增加一个回调
|
||||||
|
func (t *TimerDeal) AddOneCall(f func()) {
|
||||||
|
t.f_list = append(t.f_list, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
//设置超时时间
|
||||||
|
func (t *TimerDeal) SetCallBackTimer(d time.Duration) {
|
||||||
|
t.f_d_timeout = d
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TimerDeal) OnSart() {
|
||||||
|
//time.Tick()
|
||||||
|
go t.onTick()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TimerDeal) onTick() {
|
||||||
|
ticker := time.NewTicker(t.f_d_timeout)
|
||||||
|
for {
|
||||||
|
time := <-ticker.C
|
||||||
|
for _, v := range t.f_list {
|
||||||
|
v()
|
||||||
|
}
|
||||||
|
log.Println("timer callback:", time.String())
|
||||||
|
}
|
||||||
|
}
|
47
timerDeal/timetask.go
Normal file
47
timerDeal/timetask.go
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
package timerDeal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"public/mydef"
|
||||||
|
"public/mylog"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
主要为定时任务
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
超时回调
|
||||||
|
t:超时时间
|
||||||
|
fun:回调接口
|
||||||
|
args:回调接口传入的参数
|
||||||
|
*/
|
||||||
|
func OnDealTimeOut(t time.Duration, fun mydef.ParamsCallFunc, parms ...interface{}) {
|
||||||
|
go func() {
|
||||||
|
ticker := time.NewTicker(t)
|
||||||
|
<-ticker.C
|
||||||
|
mylog.Debug("timer 执行.....")
|
||||||
|
//以下为定时执行的操作
|
||||||
|
fun(parms...)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
每月事件
|
||||||
|
day : 几号
|
||||||
|
hour, min, sec : 几点(当天的0点偏移秒数)
|
||||||
|
callback : 时间回调
|
||||||
|
*/
|
||||||
|
func OnPeMonth(day int, hour, min, sec int, callback func()) {
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
next := time.Now().AddDate(0, 1, 0)
|
||||||
|
next = time.Date(next.Year(), next.Month(), day, hour, min, sec, 0, next.Location())
|
||||||
|
t := time.NewTimer(next.Sub(time.Now()))
|
||||||
|
log.Println("next time callback:", next)
|
||||||
|
<-t.C
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
52
tools/check.go
Normal file
52
tools/check.go
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
package tools
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
//检测参数
|
||||||
|
func CheckParam(params ...string) bool {
|
||||||
|
for _, value := range params {
|
||||||
|
if len(value) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
//判断是否是手机号
|
||||||
|
func IsPhone(mobileNum string) bool {
|
||||||
|
tmp := `^(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\d{8}$`
|
||||||
|
reg := regexp.MustCompile(tmp)
|
||||||
|
return reg.MatchString(mobileNum)
|
||||||
|
}
|
||||||
|
|
||||||
|
//判断用户是否是邮件用户
|
||||||
|
func IsMail(username string) (isMail bool) {
|
||||||
|
isMail = false
|
||||||
|
if strings.Contains(username, "@") {
|
||||||
|
isMail = true //是邮箱
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//判断是否在测试环境下使用
|
||||||
|
func IsRunTesting() bool {
|
||||||
|
if len(os.Args) > 1 {
|
||||||
|
fmt.Println(os.Args[1])
|
||||||
|
return strings.HasPrefix(os.Args[1], "-test")
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
//判断是否是18或15位身份证
|
||||||
|
func IsIdCard(cardNo string) bool {
|
||||||
|
//18位身份证 ^(\d{17})([0-9]|X)$
|
||||||
|
if m, _ := regexp.MatchString(`(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)`, cardNo); !m {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
139
tools/convert.go
Normal file
139
tools/convert.go
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
package tools
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/gob"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"public/mylog"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RawBytes []byte
|
||||||
|
|
||||||
|
var errNilPtr = errors.New("destination pointer is nil")
|
||||||
|
|
||||||
|
func cloneBytes(b []byte) []byte {
|
||||||
|
if b == nil {
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
c := make([]byte, len(b))
|
||||||
|
copy(c, b)
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AsString(src interface{}) string {
|
||||||
|
switch v := src.(type) {
|
||||||
|
case string:
|
||||||
|
return v
|
||||||
|
case []byte:
|
||||||
|
return string(v)
|
||||||
|
case int:
|
||||||
|
return strconv.Itoa(v)
|
||||||
|
case int32:
|
||||||
|
return strconv.FormatInt(int64(v), 10)
|
||||||
|
case int64:
|
||||||
|
return strconv.FormatInt(v, 10)
|
||||||
|
case float32:
|
||||||
|
return strconv.FormatFloat(float64(v), 'f', -1, 64)
|
||||||
|
case float64:
|
||||||
|
return strconv.FormatFloat(v, 'f', -1, 64)
|
||||||
|
case time.Time:
|
||||||
|
return GetTimeStr(v)
|
||||||
|
case bool:
|
||||||
|
return strconv.FormatBool(v)
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
b, _ := json.Marshal(v)
|
||||||
|
mylog.Println(string(b))
|
||||||
|
return string(b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%v", src)
|
||||||
|
}
|
||||||
|
|
||||||
|
//编码二进制
|
||||||
|
func EncodeByte(data interface{}) ([]byte, error) {
|
||||||
|
buf := bytes.NewBuffer(nil)
|
||||||
|
enc := gob.NewEncoder(buf)
|
||||||
|
err := enc.Encode(data)
|
||||||
|
if err != nil {
|
||||||
|
mylog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return buf.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//解码二进制
|
||||||
|
func DecodeByte(data []byte, to interface{}) error {
|
||||||
|
buf := bytes.NewBuffer(data)
|
||||||
|
dec := gob.NewDecoder(buf)
|
||||||
|
return dec.Decode(to)
|
||||||
|
}
|
||||||
|
|
||||||
|
//byte转16进制字符串
|
||||||
|
func ByteToHex(data []byte) string {
|
||||||
|
buffer := new(bytes.Buffer)
|
||||||
|
for _, b := range data {
|
||||||
|
|
||||||
|
s := strconv.FormatInt(int64(b&0xff), 16)
|
||||||
|
if len(s) == 1 {
|
||||||
|
buffer.WriteString("0")
|
||||||
|
}
|
||||||
|
buffer.WriteString(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
//16进制字符串转[]byte
|
||||||
|
func HexToBye(hex string) []byte {
|
||||||
|
length := len(hex) / 2
|
||||||
|
slice := make([]byte, length)
|
||||||
|
rs := []rune(hex)
|
||||||
|
|
||||||
|
for i := 0; i < length; i++ {
|
||||||
|
s := string(rs[i*2 : i*2+2])
|
||||||
|
value, _ := strconv.ParseInt(s, 16, 10)
|
||||||
|
slice[i] = byte(value & 0xFF)
|
||||||
|
}
|
||||||
|
return slice
|
||||||
|
}
|
||||||
|
|
||||||
|
//Emoji表情解码
|
||||||
|
func UnicodeEmojiDecode(s string) string {
|
||||||
|
//emoji表情的数据表达式
|
||||||
|
re := regexp.MustCompile("\\[[\\\\u0-9a-zA-Z]+\\]")
|
||||||
|
//提取emoji数据表达式
|
||||||
|
reg := regexp.MustCompile("\\[\\\\u|]")
|
||||||
|
src := re.FindAllString(s, -1)
|
||||||
|
for i := 0; i < len(src); i++ {
|
||||||
|
e := reg.ReplaceAllString(src[i], "")
|
||||||
|
p, err := strconv.ParseInt(e, 16, 32)
|
||||||
|
if err == nil {
|
||||||
|
s = strings.Replace(s, src[i], string(rune(p)), -1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
//Emoji表情转换
|
||||||
|
func UnicodeEmojiCode(s string) string {
|
||||||
|
ret := ""
|
||||||
|
rs := []rune(s)
|
||||||
|
for i := 0; i < len(rs); i++ {
|
||||||
|
if len(string(rs[i])) == 4 {
|
||||||
|
u := `[\u` + strconv.FormatInt(int64(rs[i]), 16) + `]`
|
||||||
|
ret += u
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ret += string(rs[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
66
tools/file.go
Normal file
66
tools/file.go
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
package tools
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"public/mylog"
|
||||||
|
)
|
||||||
|
|
||||||
|
//检查目录是否存在
|
||||||
|
func CheckFileIsExist(filename string) bool {
|
||||||
|
var exist = true
|
||||||
|
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||||
|
mylog.Debug(filename + " not exist")
|
||||||
|
exist = false
|
||||||
|
}
|
||||||
|
return exist
|
||||||
|
}
|
||||||
|
|
||||||
|
//创建目录
|
||||||
|
func BuildDir(abs_dir string) error {
|
||||||
|
return os.MkdirAll(abs_dir, os.ModePerm) //生成多级目录
|
||||||
|
}
|
||||||
|
|
||||||
|
//删除文件或文件夹
|
||||||
|
func DeleteFile(abs_dir string) error {
|
||||||
|
return os.RemoveAll(abs_dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取目录所有文件夹
|
||||||
|
func GetPathDirs(abs_dir string) (re []string) {
|
||||||
|
if CheckFileIsExist(abs_dir) {
|
||||||
|
files, _ := ioutil.ReadDir(abs_dir)
|
||||||
|
for _, f := range files {
|
||||||
|
if f.IsDir() {
|
||||||
|
re = append(re, f.Name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取目录所有文件夹
|
||||||
|
func GetPathFiles(abs_dir string) (re []string) {
|
||||||
|
if CheckFileIsExist(abs_dir) {
|
||||||
|
files, _ := ioutil.ReadDir(abs_dir)
|
||||||
|
for _, f := range files {
|
||||||
|
if !f.IsDir() {
|
||||||
|
re = append(re, f.Name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取目录地址
|
||||||
|
func GetModelPath() string {
|
||||||
|
file, _ := exec.LookPath(os.Args[0])
|
||||||
|
path, _ := filepath.Abs(file)
|
||||||
|
// if len(path) > 0 {
|
||||||
|
// path += "/"
|
||||||
|
// }
|
||||||
|
path = filepath.Dir(path)
|
||||||
|
return path
|
||||||
|
}
|
75
tools/ip.go
Normal file
75
tools/ip.go
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
package tools
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io/ioutil"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"public/mylog"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
///*
|
||||||
|
// 获取外网ip
|
||||||
|
//*/
|
||||||
|
//func GetWwwIP() (ip string) {
|
||||||
|
// ip = ""
|
||||||
|
// resp, err := http.Get("http://myexternalip.com/raw")
|
||||||
|
// if err != nil {
|
||||||
|
// mylog.Error(err)
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
|
||||||
|
// defer resp.Body.Close()
|
||||||
|
// body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
// if err != nil {
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
|
||||||
|
// ip = string(body)
|
||||||
|
// ip = strings.Split(ip, "\n")[0]
|
||||||
|
// return
|
||||||
|
//}
|
||||||
|
|
||||||
|
//获取公网IP地址
|
||||||
|
func GetWwwIP() (exip string) {
|
||||||
|
resp, err := http.Get("http://myexternalip.com/raw")
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
b, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return string(bytes.TrimSpace(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
获取内网ip
|
||||||
|
*/
|
||||||
|
func GetLocalIP() (ip string) {
|
||||||
|
addrs, err := net.InterfaceAddrs()
|
||||||
|
if err != nil {
|
||||||
|
mylog.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, a := range addrs {
|
||||||
|
if ipnet, ok := a.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
|
||||||
|
if ipnet.IP.To4() != nil {
|
||||||
|
ip = ipnet.IP.String()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取用户ip
|
||||||
|
func GetClientIp(r *http.Request) (ip string) {
|
||||||
|
ip = r.Header.Get("X-Real-Ip")
|
||||||
|
if ip == "" {
|
||||||
|
ip = strings.Split(r.RemoteAddr, ":")[0]
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
68
tools/json.go
Normal file
68
tools/json.go
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
package tools
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/ant0ine/go-json-rest/rest"
|
||||||
|
)
|
||||||
|
|
||||||
|
func JsonToForm(r *http.Request) {
|
||||||
|
//添加支持json 操作
|
||||||
|
r.ParseForm()
|
||||||
|
if len(r.Form) == 1 { //可能是json 支持json
|
||||||
|
for key, value := range r.Form {
|
||||||
|
if len(value[0]) == 0 {
|
||||||
|
delete(r.Form, key)
|
||||||
|
var m map[string]string
|
||||||
|
if err := json.Unmarshal([]byte(key), &m); err == nil {
|
||||||
|
for k, v := range m {
|
||||||
|
r.Form[k] = []string{v}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body, _ := ioutil.ReadAll(r.Body)
|
||||||
|
body_str := string(body)
|
||||||
|
if len(body_str) > 0 {
|
||||||
|
var m map[string]string
|
||||||
|
if err := json.Unmarshal(body, &m); err == nil {
|
||||||
|
for k, v := range m {
|
||||||
|
r.Form[k] = []string{v}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//-----------------------------end
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetRequestJsonObj(r *rest.Request, v interface{}) error {
|
||||||
|
|
||||||
|
//添加支持json 操作
|
||||||
|
body, err := ioutil.ReadAll(r.Body)
|
||||||
|
r.Body.Close()
|
||||||
|
json.Unmarshal(body, &v)
|
||||||
|
//-----------------------------end
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetJsonStr(obj interface{}) string {
|
||||||
|
b, _ := json.Marshal(obj)
|
||||||
|
return string(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func JsonDecode(obj interface{}) string {
|
||||||
|
return GetJsonStr(obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetJsonObj(str string, out interface{}) {
|
||||||
|
json.Unmarshal([]byte(str), out)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func JsonEncode(str string, out interface{}) {
|
||||||
|
GetJsonObj(str, out)
|
||||||
|
}
|
13
tools/mybase64.go
Normal file
13
tools/mybase64.go
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package tools
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Base64Encode(src []byte) string {
|
||||||
|
return base64.StdEncoding.EncodeToString(src)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Base64Decode(src []byte) ([]byte, error) {
|
||||||
|
return base64.StdEncoding.DecodeString(string(src))
|
||||||
|
}
|
47
tools/rand.go
Normal file
47
tools/rand.go
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
package tools
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
//生成随机字符串
|
||||||
|
var _bytes []byte = []byte("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
||||||
|
var r *rand.Rand
|
||||||
|
|
||||||
|
func GetRandomString(n int) string {
|
||||||
|
result := []byte{}
|
||||||
|
if r == nil {
|
||||||
|
r = rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
result = append(result, _bytes[r.Intn(len(_bytes))])
|
||||||
|
}
|
||||||
|
return string(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
//生成随机整数 digit:位数
|
||||||
|
func GenerateRangeNum(digit int) int {
|
||||||
|
var max, min int = 1, 1
|
||||||
|
if digit > 0 {
|
||||||
|
for i := 0; i < digit; i++ {
|
||||||
|
max = max * 10
|
||||||
|
}
|
||||||
|
for i := 0; i < digit-1; i++ {
|
||||||
|
min = min * 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rand.Seed(time.Now().Unix())
|
||||||
|
return rand.Intn(max-min) + min
|
||||||
|
}
|
||||||
|
|
||||||
|
//生成随机整数 digit:位数
|
||||||
|
func GetGetRandInt(min int, max int) int {
|
||||||
|
if min > max {
|
||||||
|
min = 0
|
||||||
|
max = 0
|
||||||
|
}
|
||||||
|
rand.Seed(time.Now().Unix())
|
||||||
|
return rand.Intn(max-min) + min
|
||||||
|
}
|
97
tools/str.go
Normal file
97
tools/str.go
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
package tools
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/axgle/mahonia"
|
||||||
|
)
|
||||||
|
|
||||||
|
//int数组转字符串
|
||||||
|
func FormatInt(list []int, seg string) string {
|
||||||
|
s := make([]string, len(list))
|
||||||
|
for i := range list {
|
||||||
|
s[i] = strconv.Itoa(list[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Join(s, seg)
|
||||||
|
}
|
||||||
|
|
||||||
|
//字符串去除特殊字符
|
||||||
|
//func DealStr(str, replace string) string {
|
||||||
|
// var s string = strings.TrimSpace(str) //去除尾部空格
|
||||||
|
// strings.Replace(s, replace, "", -1)
|
||||||
|
// return s
|
||||||
|
//}
|
||||||
|
|
||||||
|
//截取字符串 不包括str
|
||||||
|
func Substr(str string, start, length int) string {
|
||||||
|
rs := []rune(str)
|
||||||
|
rl := len(rs)
|
||||||
|
end := 0
|
||||||
|
|
||||||
|
if start < 0 {
|
||||||
|
start = rl - 1 + start
|
||||||
|
}
|
||||||
|
end = start + length
|
||||||
|
|
||||||
|
if start > end {
|
||||||
|
start, end = end, start
|
||||||
|
}
|
||||||
|
|
||||||
|
if start < 0 {
|
||||||
|
start = 0
|
||||||
|
}
|
||||||
|
if start > rl {
|
||||||
|
start = rl
|
||||||
|
}
|
||||||
|
if end < 0 {
|
||||||
|
end = 0
|
||||||
|
}
|
||||||
|
if end > rl {
|
||||||
|
end = rl
|
||||||
|
}
|
||||||
|
return string(rs[start:end])
|
||||||
|
}
|
||||||
|
|
||||||
|
//查找字符串最小值
|
||||||
|
func MinimumString(rest []string) string {
|
||||||
|
minimum := rest[0]
|
||||||
|
for _, v := range rest {
|
||||||
|
|
||||||
|
if v := v; v < minimum {
|
||||||
|
minimum = v
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return minimum
|
||||||
|
}
|
||||||
|
|
||||||
|
//字符集转换
|
||||||
|
func ConvertToString(src string, srcCode string, tagCode string) string {
|
||||||
|
srcCoder := mahonia.NewDecoder(srcCode)
|
||||||
|
srcResult := srcCoder.ConvertString(src)
|
||||||
|
tagCoder := mahonia.NewDecoder(tagCode)
|
||||||
|
_, cdata, _ := tagCoder.Translate([]byte(srcResult), true)
|
||||||
|
return string(cdata)
|
||||||
|
}
|
||||||
|
|
||||||
|
//系统转其他
|
||||||
|
func ConvertString(src string, tagCode string) string {
|
||||||
|
enc := mahonia.NewEncoder(tagCode)
|
||||||
|
return enc.ConvertString(src)
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
func GetGBK(src string) string {
|
||||||
|
return string(ConvertString(src, "gbK"))
|
||||||
|
}
|
||||||
|
|
||||||
|
//反转字符串
|
||||||
|
func Reverse(s string) string {
|
||||||
|
r := []rune(s)
|
||||||
|
for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
|
||||||
|
r[i], r[j] = r[j], r[i]
|
||||||
|
}
|
||||||
|
return string(r)
|
||||||
|
}
|
186
tools/timeTools.go
Normal file
186
tools/timeTools.go
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
package tools
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
//获取本地时间戳
|
||||||
|
func GetUtcTime(tm time.Time) int64 {
|
||||||
|
return tm.Unix() //- 8*60*60
|
||||||
|
}
|
||||||
|
|
||||||
|
//当前时间向上取整点
|
||||||
|
func GetHour(timestamp int64) int {
|
||||||
|
// formaTime := time.Format("2006-01-02 15:04:05")
|
||||||
|
tm := time.Unix(timestamp, 0)
|
||||||
|
return tm.Hour()
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取offset天的现在时间:注意时区
|
||||||
|
func GetLastDayCurrentTime(timestamp int64, offset int) time.Time {
|
||||||
|
tm := time.Unix(timestamp, 0)
|
||||||
|
yesDay := tm.AddDate(0, 0, 1*offset)
|
||||||
|
return yesDay
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取给定时间的星期
|
||||||
|
func GetTimeWeek(timestamp int64) int {
|
||||||
|
tm := time.Unix(timestamp, 0)
|
||||||
|
weekDay := tm.Weekday().String()
|
||||||
|
var week int = 0
|
||||||
|
switch weekDay {
|
||||||
|
case "Monday":
|
||||||
|
week = 1
|
||||||
|
case "Tuesday":
|
||||||
|
week = 2
|
||||||
|
case "Wednesday":
|
||||||
|
week = 3
|
||||||
|
case "Thursday":
|
||||||
|
week = 4
|
||||||
|
case "Friday":
|
||||||
|
week = 5
|
||||||
|
case "Saturday":
|
||||||
|
week = 6
|
||||||
|
default:
|
||||||
|
week = 0
|
||||||
|
}
|
||||||
|
return week
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取向上整时时间
|
||||||
|
func GetHour0(timestamp int64, timeZone *time.Location) time.Time {
|
||||||
|
tm := time.Unix(timestamp, 0)
|
||||||
|
tStr := tm.Format("2006-01-02 15") + ":00:00"
|
||||||
|
return StrToTime(tStr, "2006-01-02 15:04:05", timeZone)
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取给定日期的零点时间
|
||||||
|
func GetDay0(timestamp int64, timeZone *time.Location) time.Time {
|
||||||
|
tm := time.Unix(timestamp, 0)
|
||||||
|
tStr := tm.Format("2006-01-02") + " 00:00:00"
|
||||||
|
|
||||||
|
return StrToTime(tStr, "2006-01-02 15:04:05", timeZone)
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取offset 0点时间
|
||||||
|
func GetUtcDay0(now time.Time, timeZone *time.Location) int64 {
|
||||||
|
tm := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
|
||||||
|
return tm.Unix()
|
||||||
|
}
|
||||||
|
|
||||||
|
//字符串转时间
|
||||||
|
func StrToTime(tStr, format string, timeZone *time.Location) time.Time {
|
||||||
|
if len(format) == 0 {
|
||||||
|
format = "2006-01-02 15:04:05"
|
||||||
|
}
|
||||||
|
if timeZone == nil {
|
||||||
|
//chinaLocal, _ := time.LoadLocation("Local")
|
||||||
|
timeZone = time.Local
|
||||||
|
}
|
||||||
|
|
||||||
|
ti, _ := time.ParseInLocation(format, tStr, timeZone)
|
||||||
|
return ti
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
给定字符串时间转换成本地时间戳
|
||||||
|
*/
|
||||||
|
func StringTimetoUnix(timestr string) int64 {
|
||||||
|
return StrToTime(timestr, "2006-01-02 15:04:05", time.Local).Unix()
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取最近上个星期天的零点日期
|
||||||
|
func GetTimeWeek0(timestamp int64) int64 {
|
||||||
|
weekday := GetTimeWeek(timestamp)
|
||||||
|
tm0 := GetDay0(timestamp, nil)
|
||||||
|
tm0 = tm0.AddDate(0, 0, -1*weekday)
|
||||||
|
|
||||||
|
return tm0.Unix()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
获取给定时间的当月1号零点时间
|
||||||
|
*/
|
||||||
|
func GetMonth0(timestamp int64) time.Time {
|
||||||
|
|
||||||
|
tm0 := GetDay0(timestamp, nil)
|
||||||
|
month0 := tm0.Day() - 1
|
||||||
|
tm0 = tm0.AddDate(0, 0, -1*month0) //这个月1号
|
||||||
|
return tm0
|
||||||
|
}
|
||||||
|
|
||||||
|
//整点执行操作
|
||||||
|
func TimerByHour(f func()) {
|
||||||
|
for {
|
||||||
|
now := time.Now()
|
||||||
|
// 计算下一个整点
|
||||||
|
next := now.Add(time.Hour * 1)
|
||||||
|
next = time.Date(next.Year(), next.Month(), next.Day(), next.Hour(), 0, 0, 0, next.Location())
|
||||||
|
t := time.NewTimer(next.Sub(now))
|
||||||
|
<-t.C
|
||||||
|
//以下为定时执行的操作
|
||||||
|
f()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//时间戳转换为time
|
||||||
|
func UnixToTime(timestamp int64) time.Time {
|
||||||
|
return time.Unix(timestamp, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取本地时间
|
||||||
|
func GetLocalTime(tm time.Time) time.Time {
|
||||||
|
local, _ := time.LoadLocation("Local")
|
||||||
|
return tm.In(local)
|
||||||
|
//return tm.Add(8 * 60 * 60 * time.Second)
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取系统时间的格式
|
||||||
|
func GetSysTimeLayout() string {
|
||||||
|
t := time.Date(2006, 1, 2, 15, 4, 5, 0, time.UTC)
|
||||||
|
strLayout := strings.Replace(t.String(), "+0000 UTC", "", -1)
|
||||||
|
return strings.TrimSpace(strLayout)
|
||||||
|
}
|
||||||
|
|
||||||
|
func FormatTime(tm time.Time, for_str string) string {
|
||||||
|
return tm.Format(for_str)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetTimeStr(tm time.Time) string {
|
||||||
|
return FormatTime(tm, "2006-01-02 15:04:05")
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetDayStr(tm time.Time) string {
|
||||||
|
return FormatTime(tm, "2006-01-02")
|
||||||
|
}
|
||||||
|
|
||||||
|
//json marsh 重写
|
||||||
|
type Time struct {
|
||||||
|
time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Time) UnmarshalJSON(data []byte) (err error) {
|
||||||
|
tmp := string(data)
|
||||||
|
str := `"2006-01-02 15:04:05"`
|
||||||
|
if len(tmp) <= 20 {
|
||||||
|
str = `"2006-01-02"`
|
||||||
|
}
|
||||||
|
if tmp != `""` {
|
||||||
|
now, err1 := time.ParseInLocation(str, tmp, time.Local)
|
||||||
|
err = err1
|
||||||
|
*t = Time{now}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t Time) MarshalJSON() ([]byte, error) {
|
||||||
|
var stamp = fmt.Sprintf(`"%s"`, t.Format("2006-01-02 15:04:05"))
|
||||||
|
return []byte(stamp), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t Time) String() string {
|
||||||
|
return t.Format("2006-01-02 15:04:05")
|
||||||
|
}
|
154
tools/tools.go
Normal file
154
tools/tools.go
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
package tools
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/md5"
|
||||||
|
crand "crypto/rand"
|
||||||
|
"crypto/sha1"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/hex"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"html/template"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"public/mylog"
|
||||||
|
"reflect"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"data/config"
|
||||||
|
|
||||||
|
"github.com/ant0ine/go-json-rest/rest"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
获取程序运行路径
|
||||||
|
*/
|
||||||
|
func GetCurrentDirectory() string {
|
||||||
|
dir, _ := filepath.Abs(filepath.Dir(os.Args[0]))
|
||||||
|
return strings.Replace(dir, "\\", "/", -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Md5Encoder(src string) string {
|
||||||
|
h := md5.New()
|
||||||
|
h.Write([]byte(src)) // 需要加密的字符串
|
||||||
|
// fmt.Printf("%x\n", h.Sum(nil)) // 输出加密结
|
||||||
|
ret := fmt.Sprintf("%x", h.Sum(nil))
|
||||||
|
return strings.ToUpper(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
//合并数组
|
||||||
|
func Copy(dest []interface{}, src []interface{}) (result []interface{}) {
|
||||||
|
result = make([]interface{}, len(dest)+len(src))
|
||||||
|
copy(result, dest)
|
||||||
|
copy(result[len(dest):], src)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//删除数组
|
||||||
|
func DeleteArray(src []interface{}, index int) (result []interface{}) {
|
||||||
|
result = append(src[:index], src[(index+1):]...)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//生成32位md5字串
|
||||||
|
func GetMd5String(s string) string {
|
||||||
|
h := md5.New()
|
||||||
|
h.Write([]byte(s))
|
||||||
|
return hex.EncodeToString(h.Sum(nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取总页数
|
||||||
|
func GetTotalPageNum(pageSize, totalCount int) int {
|
||||||
|
return (totalCount + pageSize - 1) / pageSize
|
||||||
|
}
|
||||||
|
|
||||||
|
//生成32位guid
|
||||||
|
func UniqueId() string {
|
||||||
|
b := make([]byte, 48)
|
||||||
|
if _, err := io.ReadFull(crand.Reader, b); err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return GetMd5String(base64.URLEncoding.EncodeToString(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
//删除切片index
|
||||||
|
func DeleteSlice(slice interface{}, index int) (interface{}, error) {
|
||||||
|
sliceValue := reflect.ValueOf(slice)
|
||||||
|
length := sliceValue.Len()
|
||||||
|
if slice == nil || length == 0 || (length-1) < index {
|
||||||
|
return nil, errors.New("error")
|
||||||
|
}
|
||||||
|
if length-1 == index {
|
||||||
|
return sliceValue.Slice(0, index).Interface(), nil
|
||||||
|
} else {
|
||||||
|
return reflect.AppendSlice(sliceValue.Slice(0, index), sliceValue.Slice(index+1, length)).Interface(), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//查找int最小值
|
||||||
|
func MinimumInt(rest []int) int {
|
||||||
|
minimum := rest[0]
|
||||||
|
for _, v := range rest {
|
||||||
|
if v < minimum {
|
||||||
|
minimum = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return minimum
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadTemplate(list ...string) *template.Template {
|
||||||
|
var tmp []string
|
||||||
|
for _, v := range list {
|
||||||
|
if CheckFileIsExist(GetModelPath() + config.Static_host[0] + v) {
|
||||||
|
tmp = append(tmp, GetModelPath()+config.Static_host[0]+v)
|
||||||
|
} else {
|
||||||
|
mylog.Debug("file does not exist:" + GetModelPath() + config.Static_host[0] + v)
|
||||||
|
panic(GetModelPath() + config.Static_host[0] + v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return template.Must(template.ParseFiles(tmp...))
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
执行模版渲染,
|
||||||
|
name:模版名字,""则无名字
|
||||||
|
data:传参列表
|
||||||
|
list:模版列表
|
||||||
|
*/
|
||||||
|
func ExecuteTemplate(w rest.ResponseWriter, name string, data interface{}, list ...string) error {
|
||||||
|
t := LoadTemplate(list...)
|
||||||
|
w.(http.ResponseWriter).Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||||
|
|
||||||
|
if len(name) == 0 {
|
||||||
|
return t.Execute(w.(http.ResponseWriter), data)
|
||||||
|
} else {
|
||||||
|
return t.ExecuteTemplate(w.(http.ResponseWriter), name, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//按字典顺序排序
|
||||||
|
func DictSort(res []string) (str string) {
|
||||||
|
sort.Strings(res)
|
||||||
|
if len(res) > 0 {
|
||||||
|
for _, v := range res {
|
||||||
|
str += v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//SHA1加密
|
||||||
|
func Sha1Encrypt(str string) string {
|
||||||
|
h := sha1.New()
|
||||||
|
h.Write([]byte(str))
|
||||||
|
bs := h.Sum(nil)
|
||||||
|
return fmt.Sprintf("%x", bs)
|
||||||
|
}
|
||||||
|
|
||||||
|
//中文字符切割时有问题。采用此方式不会有问题
|
||||||
|
func GetUtf8Str(str string) []rune {
|
||||||
|
return []rune(str)
|
||||||
|
}
|
139
tools/zip.go
Normal file
139
tools/zip.go
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
package tools
|
||||||
|
|
||||||
|
import (
|
||||||
|
"archive/zip"
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
func IsZip(zipPath string) bool {
|
||||||
|
f, err := os.Open(zipPath)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
buf := make([]byte, 4)
|
||||||
|
if n, err := f.Read(buf); err != nil || n < 4 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes.Equal(buf, []byte("PK\x03\x04"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Unzip(archive, target string) error {
|
||||||
|
reader, err := zip.OpenReader(archive)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.MkdirAll(target, 0755); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, file := range reader.File {
|
||||||
|
path := filepath.Join(target, file.Name)
|
||||||
|
if file.FileInfo().IsDir() {
|
||||||
|
os.MkdirAll(path, file.Mode())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
//------------注入
|
||||||
|
|
||||||
|
dir := filepath.Dir(path)
|
||||||
|
if len(dir) > 0 {
|
||||||
|
if _, err = os.Stat(dir); os.IsNotExist(err) {
|
||||||
|
err = os.MkdirAll(dir, 0755)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------end
|
||||||
|
|
||||||
|
fileReader, err := file.Open()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer fileReader.Close()
|
||||||
|
|
||||||
|
targetFile, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer targetFile.Close()
|
||||||
|
|
||||||
|
if _, err := io.Copy(targetFile, fileReader); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//压缩文件
|
||||||
|
//files 文件数组,可以是不同dir下的文件或者文件夹
|
||||||
|
//dest 压缩文件存放地址
|
||||||
|
func Compress(files []*os.File, dest string) error {
|
||||||
|
d, _ := os.Create(dest)
|
||||||
|
defer d.Close()
|
||||||
|
w := zip.NewWriter(d)
|
||||||
|
defer w.Close()
|
||||||
|
for _, file := range files {
|
||||||
|
err := compress(file, "", w)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func compress(file *os.File, prefix string, zw *zip.Writer) error {
|
||||||
|
info, err := file.Stat()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if info.IsDir() {
|
||||||
|
if len(prefix) == 0 {
|
||||||
|
prefix = info.Name()
|
||||||
|
} else {
|
||||||
|
prefix = prefix + "/" + info.Name()
|
||||||
|
}
|
||||||
|
fileInfos, err := file.Readdir(-1)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, fi := range fileInfos {
|
||||||
|
f, err := os.Open(file.Name() + "/" + fi.Name())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = compress(f, prefix, zw)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
header, err := zip.FileInfoHeader(info)
|
||||||
|
if len(prefix) == 0 {
|
||||||
|
header.Name = header.Name
|
||||||
|
} else {
|
||||||
|
header.Name = prefix + "/" + header.Name
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
writer, err := zw.CreateHeader(header)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = io.Copy(writer, file)
|
||||||
|
file.Close()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
112
weixin/base.go
Normal file
112
weixin/base.go
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
package weixin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"public/mycache"
|
||||||
|
"public/mylog"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/silenceper/wechat"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
GETTICKETURL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=wx_card&access_token="
|
||||||
|
GETJSURL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token="
|
||||||
|
)
|
||||||
|
|
||||||
|
//获取微信accesstoken
|
||||||
|
func GetAccessToken() (access_token string, err error) {
|
||||||
|
//先从缓存中获取
|
||||||
|
cache := mycache.OnGetCache("weixin_token")
|
||||||
|
var tp interface{}
|
||||||
|
tp, b := cache.Value("base")
|
||||||
|
if b {
|
||||||
|
access_token = tp.(string)
|
||||||
|
} else {
|
||||||
|
wc := wechat.NewWechat(&cfg)
|
||||||
|
access_token, err = wc.GetAccessToken()
|
||||||
|
//保存缓存
|
||||||
|
cache.Add("base", access_token, 7000*time.Second)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取微信卡券ticket
|
||||||
|
func GetApiTicket() (ticket string, err error) {
|
||||||
|
//先从缓存中获取
|
||||||
|
cache := mycache.OnGetCache("weixin_card_ticket")
|
||||||
|
var tp interface{}
|
||||||
|
tp, b := cache.Value("base")
|
||||||
|
if b {
|
||||||
|
ticket = tp.(string)
|
||||||
|
} else {
|
||||||
|
access_token, e := GetAccessToken()
|
||||||
|
if e != nil {
|
||||||
|
mylog.Error(e)
|
||||||
|
err = e
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var url = GETTICKETURL + access_token
|
||||||
|
|
||||||
|
resp, e1 := http.Get(url)
|
||||||
|
if e1 != nil {
|
||||||
|
mylog.Error(e1)
|
||||||
|
err = e1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
body, e2 := ioutil.ReadAll(resp.Body)
|
||||||
|
if e2 != nil {
|
||||||
|
mylog.Error(e2)
|
||||||
|
err = e2
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var result ApiTicket
|
||||||
|
json.Unmarshal(body, &result)
|
||||||
|
ticket = result.Ticket
|
||||||
|
//保存缓存
|
||||||
|
cache.Add("base", ticket, 7000*time.Second)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取微信js ticket
|
||||||
|
func GetJsTicket() (ticket string, err error) {
|
||||||
|
//先从缓存中获取
|
||||||
|
cache := mycache.OnGetCache("weixin_js_ticket")
|
||||||
|
var tp interface{}
|
||||||
|
tp, b := cache.Value("base")
|
||||||
|
if b {
|
||||||
|
ticket = tp.(string)
|
||||||
|
} else {
|
||||||
|
access_token, e := GetAccessToken()
|
||||||
|
if e != nil {
|
||||||
|
mylog.Error(e)
|
||||||
|
err = e
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var url = GETJSURL + access_token
|
||||||
|
|
||||||
|
resp, e1 := http.Get(url)
|
||||||
|
if e1 != nil {
|
||||||
|
mylog.Error(e1)
|
||||||
|
err = e1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
body, e2 := ioutil.ReadAll(resp.Body)
|
||||||
|
if e2 != nil {
|
||||||
|
mylog.Error(e2)
|
||||||
|
err = e2
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var result ApiTicket
|
||||||
|
json.Unmarshal(body, &result)
|
||||||
|
ticket = result.Ticket
|
||||||
|
//保存缓存
|
||||||
|
cache.Add("base", ticket, 7000*time.Second)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
39
weixin/cache.go
Normal file
39
weixin/cache.go
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
package weixin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"public/mycache"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
//Memcache struct contains *memcache.Client
|
||||||
|
type Gocache struct {
|
||||||
|
mc *mycache.MyCache
|
||||||
|
}
|
||||||
|
|
||||||
|
//NewGocache create new cache2go
|
||||||
|
func NewGocache(server string) *Gocache {
|
||||||
|
mc := mycache.OnGetCache(server)
|
||||||
|
return &Gocache{&mc}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get return cached value
|
||||||
|
func (mem *Gocache) Get(key string) interface{} {
|
||||||
|
v, _ := mem.mc.Value(key)
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsExist check value exists in memcache.
|
||||||
|
func (mem *Gocache) IsExist(key string) bool {
|
||||||
|
return mem.mc.IsExist(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set cached value with key and expire time.
|
||||||
|
func (mem *Gocache) Set(key string, val interface{}, timeout time.Duration) (err error) {
|
||||||
|
mem.mc.Add(key, val, timeout)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//Delete value in memcache.
|
||||||
|
func (mem *Gocache) Delete(key string) error {
|
||||||
|
return mem.mc.Delete(key)
|
||||||
|
}
|
19
weixin/def.go
Normal file
19
weixin/def.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package weixin
|
||||||
|
|
||||||
|
type UserInfo struct {
|
||||||
|
OpenID string `json:"openid"`
|
||||||
|
Nickname string `json:"nickname"`
|
||||||
|
Sex int32 `json:"sex"`
|
||||||
|
Province string `json:"province"`
|
||||||
|
City string `json:"city"`
|
||||||
|
Country string `json:"country"`
|
||||||
|
HeadImgURL string `json:"headimgurl"`
|
||||||
|
Privilege []string `json:"privilege"`
|
||||||
|
Unionid string `json:"unionid"`
|
||||||
|
}
|
||||||
|
type ApiTicket struct {
|
||||||
|
Errcode int `json:"errcode"`
|
||||||
|
Errmsg string `json:"errmsg"`
|
||||||
|
Ticket string `json:"ticket"`
|
||||||
|
Expires_in int `json:"expires_in"`
|
||||||
|
}
|
58
weixin/enterprisePay.go
Normal file
58
weixin/enterprisePay.go
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
package weixin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"public/tools"
|
||||||
|
|
||||||
|
wxpay "gopkg.in/go-with/wxpay.v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
enterprisePayUrl = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers" // 查询企业付款接口请求URL
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
企业付款
|
||||||
|
open_id:用户唯一标识
|
||||||
|
trade_no : 商户订单号
|
||||||
|
desc : 操作说明
|
||||||
|
amount:付款金额 分
|
||||||
|
*/
|
||||||
|
func WxEnterprisePay(open_id, trade_no, desc, ipAddr string, amount int) bool {
|
||||||
|
c := wxpay.NewClient(pay_appId, mchId, apiKey)
|
||||||
|
|
||||||
|
// 附着商户证书
|
||||||
|
err := c.WithCert(certFile, keyFile, rootcaFile)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
params := make(wxpay.Params)
|
||||||
|
nonce_str := tools.GetRandomString(16)
|
||||||
|
// 查询企业付款接口请求参数
|
||||||
|
params.SetString("mch_appid", c.AppId) //商户账号appid
|
||||||
|
params.SetString("mchid", c.MchId) //商户号
|
||||||
|
params.SetString("nonce_str", nonce_str) // 随机字符串
|
||||||
|
params.SetString("partner_trade_no", trade_no) // 商户订单号
|
||||||
|
params.SetString("openid", open_id) //用户openid
|
||||||
|
params.SetString("check_name", "NO_CHECK") //校验用户姓名选项
|
||||||
|
params.SetInt64("amount", int64(amount)) //企业付款金额,单位为分
|
||||||
|
params.SetString("desc", desc) //企业付款操作说明信息。必填。
|
||||||
|
params.SetString("spbill_create_ip", ipAddr)
|
||||||
|
|
||||||
|
params.SetString("sign", c.Sign(params)) // 签名
|
||||||
|
|
||||||
|
// 发送查询企业付款请求
|
||||||
|
ret, err := c.Post(enterprisePayUrl, params, true)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
log.Print(ret)
|
||||||
|
returnCode := ret.GetString("return_code")
|
||||||
|
resultCode := ret.GetString("result_code")
|
||||||
|
if returnCode == "SUCCESS" && resultCode == "SUCCESS" {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
60
weixin/init.go
Normal file
60
weixin/init.go
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
package weixin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"data/config"
|
||||||
|
"public/tools"
|
||||||
|
|
||||||
|
"github.com/silenceper/wechat"
|
||||||
|
wxpay "gopkg.in/go-with/wxpay.v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// 微信支付商户平台证书路径
|
||||||
|
certFileLoc = "/cert/apiclient_cert.pem"
|
||||||
|
keyFileLoc = "/cert/apiclient_key.pem"
|
||||||
|
rootcaFileLoc = "/cert/rootca.pem"
|
||||||
|
)
|
||||||
|
|
||||||
|
var cfg wechat.Config
|
||||||
|
var client *wxpay.Client
|
||||||
|
|
||||||
|
var pay_appId string // 微信公众平台应用ID
|
||||||
|
var mchId string // 微信支付商户平台商户号
|
||||||
|
var apiKey string // 微信支付商户平台API密钥
|
||||||
|
var secret string
|
||||||
|
var notify_url string
|
||||||
|
var token string
|
||||||
|
var encodingAESKey string
|
||||||
|
|
||||||
|
var certFile string // 微信支付商户平台证书路径
|
||||||
|
var keyFile string
|
||||||
|
var rootcaFile string
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
wx_info := config.GetWxInfo()
|
||||||
|
//配置微信支付参数
|
||||||
|
pay_appId = wx_info.AppID
|
||||||
|
mchId = wx_info.MchId
|
||||||
|
apiKey = wx_info.Key
|
||||||
|
secret = wx_info.AppSecret
|
||||||
|
notify_url = wx_info.NotifyUrl
|
||||||
|
token = wx_info.Token
|
||||||
|
encodingAESKey = wx_info.EncodingAESKey
|
||||||
|
|
||||||
|
certFile = tools.GetModelPath() + certFileLoc
|
||||||
|
keyFile = tools.GetModelPath() + keyFileLoc
|
||||||
|
rootcaFile = tools.GetModelPath() + rootcaFileLoc
|
||||||
|
|
||||||
|
//使用memcache保存access_token,也可选择redis或自定义cache
|
||||||
|
memCache := NewGocache("_winxin_access")
|
||||||
|
//配置微信参数
|
||||||
|
cfg = wechat.Config{
|
||||||
|
AppID: pay_appId,
|
||||||
|
AppSecret: secret,
|
||||||
|
Token: token,
|
||||||
|
EncodingAESKey: encodingAESKey,
|
||||||
|
Cache: memCache,
|
||||||
|
}
|
||||||
|
client = wxpay.NewClient(pay_appId, mchId, apiKey)
|
||||||
|
client.WithCert(certFile, keyFile, rootcaFile)
|
||||||
|
}
|
29
weixin/oauth.go
Normal file
29
weixin/oauth.go
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package weixin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"public/mylog"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
小程序授权
|
||||||
|
*/
|
||||||
|
func SmallAppOauth(jscode string) string {
|
||||||
|
var url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + pay_appId + "&secret=" +
|
||||||
|
secret + "&js_code=" + jscode + "&grant_type=authorization_code&trade_type=JSAPI"
|
||||||
|
|
||||||
|
resp, e := http.Get(url)
|
||||||
|
if e != nil {
|
||||||
|
mylog.Error(e)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
mylog.Error(e)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return string(body)
|
||||||
|
}
|
210
weixin/pay.go
Normal file
210
weixin/pay.go
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
package weixin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/md5"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"public/message"
|
||||||
|
"public/mylog"
|
||||||
|
"public/tools"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
wxpay "gopkg.in/go-with/wxpay.v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
unifiedOrderUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder" // 统一下单请求URL
|
||||||
|
queryOrderUrl = "https://api.mch.weixin.qq.com/pay/orderquery" // 统一查询请求URL
|
||||||
|
refundUrl = "https://api.mch.weixin.qq.com/secapi/pay/refund" //退款请求URL
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
PAY_SUCCESS = 1 //支付成功
|
||||||
|
PAY_REFUND = 2 //转入退款
|
||||||
|
PAY_CLOSED = 3 //已关闭
|
||||||
|
PAY_NOTPAY = 4 //未支付
|
||||||
|
PAY_REVOKED = 5 //已撤销
|
||||||
|
PAY_USERPAYING = 6 //支付中
|
||||||
|
PAY_ERROR = -1 //支付失败
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
小程序统一下单接口
|
||||||
|
open_id:用户唯一标识
|
||||||
|
price : 预支付价钱
|
||||||
|
price_body : 支付描述
|
||||||
|
order_id : 商户订单号
|
||||||
|
*/
|
||||||
|
func SmallAppUnifiedorder(open_id string, price int, price_body, order_id, client_ip string) message.MessageBody {
|
||||||
|
if !tools.CheckParam(open_id, order_id) || price <= 0 { //参数检测
|
||||||
|
return message.GetErrorMsg(message.ParameterInvalid)
|
||||||
|
}
|
||||||
|
|
||||||
|
params := make(wxpay.Params)
|
||||||
|
// 查询企业付款接口请求参数
|
||||||
|
params.SetString("appid", client.AppId)
|
||||||
|
params.SetString("mch_id", client.MchId)
|
||||||
|
params.SetString("body", price_body)
|
||||||
|
params.SetInt64("total_fee", int64(price*10))
|
||||||
|
params.SetString("spbill_create_ip", client_ip)
|
||||||
|
params.SetString("notify_url", notify_url)
|
||||||
|
params.SetString("trade_type", "JSAPI")
|
||||||
|
params.SetString("openid", open_id)
|
||||||
|
params.SetString("nonce_str", tools.GetRandomString(32)) // 随机字符串
|
||||||
|
params.SetString("out_trade_no", order_id) // 商户订单号
|
||||||
|
params.SetString("sign", client.Sign(params)) // 签名 c.Sign(params)
|
||||||
|
|
||||||
|
log.Println("paramsparams", params)
|
||||||
|
// 发送查询企业付款请求
|
||||||
|
ret, err := client.Post(unifiedOrderUrl, params, true)
|
||||||
|
if err != nil {
|
||||||
|
mylog.Error(err)
|
||||||
|
msg := message.GetErrorMsg(message.UnknownError)
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
//-----------------------end
|
||||||
|
|
||||||
|
//ret["order_id"] = order_tbl.Order_id
|
||||||
|
fmt.Println(ret)
|
||||||
|
|
||||||
|
if ret["result_code"] == "SUCCESS" { //再次签名
|
||||||
|
dd := make(map[string]string)
|
||||||
|
dd["timeStamp"] = strconv.FormatInt(tools.GetUtcTime(time.Now()), 10)
|
||||||
|
dd["nonceStr"] = tools.GetRandomString(32)
|
||||||
|
dd["package"] = "prepay_id=" + ret["prepay_id"]
|
||||||
|
dd["signType"] = "MD5"
|
||||||
|
dd["paySign"] = "MD5"
|
||||||
|
//appId=wxd678efh567hg6787&nonceStr=5K8264ILTKCH16CQ2502SI8ZNMTM67VS&package=prepay_id=&signType=MD5&timeStamp=1490840662&key=qazwsxedcrfvtgbyhnujmikolp111111
|
||||||
|
str := "appId=" + pay_appId + "&nonceStr=" + dd["nonceStr"] + "&package=" + dd["package"] + "&signType=MD5&timeStamp=" + dd["timeStamp"] + "&key=" + apiKey
|
||||||
|
by := md5.Sum([]byte(str))
|
||||||
|
dd["paySign"] = strings.ToUpper(fmt.Sprintf("%x", by))
|
||||||
|
dd["order_id"] = order_id
|
||||||
|
|
||||||
|
msg := message.GetSuccessMsg()
|
||||||
|
msg.Data = dd
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := message.GetErrorMsg(message.InValidOp)
|
||||||
|
msg.Data = ret
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
统一查询接口
|
||||||
|
open_id:用户唯一标识
|
||||||
|
order_id : 商户订单号
|
||||||
|
*/
|
||||||
|
func OnSelectData(open_id, order_id string) (int, message.MessageBody) {
|
||||||
|
if !tools.CheckParam(open_id, order_id) { //参数检测
|
||||||
|
return 0, message.GetErrorMsg(message.ParameterInvalid)
|
||||||
|
}
|
||||||
|
|
||||||
|
code := 0
|
||||||
|
|
||||||
|
params := make(wxpay.Params)
|
||||||
|
// 查询企业付款接口请求参数
|
||||||
|
params.SetString("appid", client.AppId)
|
||||||
|
params.SetString("mch_id", client.MchId)
|
||||||
|
params.SetString("out_trade_no", order_id) //商户订单号
|
||||||
|
params.SetString("nonce_str", tools.GetRandomString(32)) // 随机字符串
|
||||||
|
params.SetString("sign", client.Sign(params)) // 签名 c.Sign(params)
|
||||||
|
|
||||||
|
// 发送查询企业付款请求
|
||||||
|
ret := make(wxpay.Params)
|
||||||
|
var err error
|
||||||
|
ret, err = client.Post(queryOrderUrl, params, true)
|
||||||
|
if err != nil { //做再次确认
|
||||||
|
time.Sleep(time.Second * 1)
|
||||||
|
ret, err = client.Post(queryOrderUrl, params, true)
|
||||||
|
if err != nil {
|
||||||
|
mylog.Error(err)
|
||||||
|
msg := message.GetSuccessMsg()
|
||||||
|
return code, msg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//-----------------------end
|
||||||
|
|
||||||
|
msg := message.GetSuccessMsg(message.NormalMessageId)
|
||||||
|
|
||||||
|
/*
|
||||||
|
SUCCESS—支付成功
|
||||||
|
REFUND—转入退款
|
||||||
|
NOTPAY—未支付
|
||||||
|
CLOSED—已关闭
|
||||||
|
REVOKED—已撤销(刷卡支付)
|
||||||
|
USERPAYING--用户支付中
|
||||||
|
PAYERROR--支付失败(其他原因,如银行返回失败)
|
||||||
|
*/
|
||||||
|
if ret["trade_state"] == "SUCCESS" {
|
||||||
|
code = PAY_SUCCESS
|
||||||
|
} else if ret["trade_state"] == "REFUND" {
|
||||||
|
code = PAY_REFUND
|
||||||
|
} else if ret["trade_state"] == "CLOSED" {
|
||||||
|
code = PAY_CLOSED
|
||||||
|
} else if ret["trade_state"] == "NOTPAY" {
|
||||||
|
code = PAY_NOTPAY
|
||||||
|
} else if ret["trade_state"] == "REVOKED" {
|
||||||
|
code = PAY_REVOKED
|
||||||
|
} else if ret["trade_state"] == "USERPAYING" {
|
||||||
|
code = PAY_USERPAYING
|
||||||
|
} else {
|
||||||
|
code = PAY_ERROR
|
||||||
|
}
|
||||||
|
|
||||||
|
if ret["trade_state"] == "SUCCESS" { //支付成功
|
||||||
|
msg.State = true
|
||||||
|
} else {
|
||||||
|
msg.State = false
|
||||||
|
}
|
||||||
|
|
||||||
|
msg.Data = ret
|
||||||
|
return code, msg
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
申请退款
|
||||||
|
open_id:用户唯一标识
|
||||||
|
order_id : 商户订单号
|
||||||
|
refund_no:商户退款单号
|
||||||
|
total_fee: 订单总金额 分
|
||||||
|
refund_fee: 退款总金额 分
|
||||||
|
*/
|
||||||
|
func RefundPay(open_id, order_id, refund_no string, total_fee, refund_fee int) (bool, message.MessageBody) {
|
||||||
|
if !tools.CheckParam(open_id, order_id) { //参数检测
|
||||||
|
return false, message.GetErrorMsg(message.ParameterInvalid)
|
||||||
|
}
|
||||||
|
code := false
|
||||||
|
params := make(wxpay.Params)
|
||||||
|
// 退款请求参数
|
||||||
|
params.SetString("appid", client.AppId)
|
||||||
|
params.SetString("mch_id", client.MchId)
|
||||||
|
params.SetString("out_trade_no", order_id) //商户订单号
|
||||||
|
params.SetString("out_refund_no", refund_no) //商户退款单号
|
||||||
|
params.SetInt64("total_fee", int64(total_fee)) // 订单总金额(分)
|
||||||
|
params.SetInt64("refund_fee", int64(refund_fee)) // 退款金额(分)
|
||||||
|
params.SetString("nonce_str", tools.GetRandomString(32)) // 随机字符串
|
||||||
|
params.SetString("sign", client.Sign(params)) // 签名 c.Sign(params)
|
||||||
|
|
||||||
|
// 发送申请退款请求
|
||||||
|
ret, err := client.Post(refundUrl, params, true)
|
||||||
|
if err != nil {
|
||||||
|
mylog.Error(err)
|
||||||
|
msg := message.GetErrorMsg(message.UnknownError)
|
||||||
|
return code, msg
|
||||||
|
}
|
||||||
|
//-----------------------end
|
||||||
|
|
||||||
|
msg := message.GetSuccessMsg(message.NormalMessageId)
|
||||||
|
|
||||||
|
if ret["result_code"] == "SUCCESS" { //申请成功
|
||||||
|
msg.State = true
|
||||||
|
code = true
|
||||||
|
} else {
|
||||||
|
msg.State = false
|
||||||
|
}
|
||||||
|
msg.Data = ret
|
||||||
|
return code, msg
|
||||||
|
}
|
Reference in New Issue
Block a user