-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathmain.go
159 lines (139 loc) · 4.16 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
package main
import (
"crypto/sha1"
"encoding/json"
"fmt"
"html/template"
"log"
"math/rand"
"net/http"
"net/url"
"strconv"
"time"
"github.com/asdine/storm"
"github.com/parnurzeal/gorequest"
)
// Ticket 类型
type Ticket struct {
Errcode int `json:"errcode,omitempty"`
Errmsg string `json:"errmsg,omitempty"`
Ticket string `json:"ticket,omitempty"`
ExpiresIn int `json:"expires_in,omitempty"`
}
// Token 类型
type Token struct {
AccessToken string `json:"access_token,omitempty"`
ExpiresIn int `json:"expires_in,omitempty"`
}
// Sign 签名类型
type Sign struct {
AppID string `json:"app_id,omitempty"`
Timestamp string `json:"timestamp,omitempty"`
NonceStr string `json:"nonce_str,omitempty"`
Signature string `json:"signature,omitempty"`
}
//IndexTemplate 页面模板
type IndexTemplate struct {
Title template.HTML
}
var (
//微信公众号
wxAppID = ""
wxSecret = ""
port = ":8383"
letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
)
func init() {
rand.Seed(time.Now().UnixNano())
}
func main() {
go func() {
for {
GetWeixin(wxAppID, wxSecret)
time.Sleep(time.Duration(7200) * time.Second)
}
}()
http.Handle("/img/", http.FileServer(http.Dir("html")))
http.Handle("/css/", http.FileServer(http.Dir("html")))
http.Handle("/js/", http.FileServer(http.Dir("html")))
http.Handle("/", http.FileServer(http.Dir("html/www"))) //存放微信JS接口安全域名验证文件
http.HandleFunc("/sign", signHandler)
http.ListenAndServe(port, nil)
log.Println("Server start at", port)
}
//signHandler 异步处理微信签名
func signHandler(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
if r.Method == "POST" {
wxNoncestr := RandStringRunes(32)
wxURL, _ := url.QueryUnescape(r.FormValue("url"))
timestamp, signature := GetCanshu(wxNoncestr, wxURL)
var u = Sign{
AppID: wxAppID,
Timestamp: timestamp,
NonceStr: wxNoncestr,
Signature: signature,
}
w.Header().Add("Access-Control-Allow-Headers", "Content-Type") //header的类型
w.Header().Set("Content-type", "application/json") //返回数据格式是json
b, err := json.Marshal(u)
if err != nil {
log.Println(err.Error())
}
w.Write(b)
} else if r.Method == "GET" {
t, _ := template.ParseFiles("html/index.tpl", "html/foot.tpl")
t.Execute(w, &IndexTemplate{Title: template.HTML("生成微信分享签名")})
}
}
//GetCanshu 微信签名算法
func GetCanshu(noncestr, url string) (timestamp, signature string) {
db, err := storm.Open("db/weixin.db")
if err != nil {
log.Println("Database open err:", err.Error())
}
defer db.Close()
defer func() { //异常处理
if err := recover(); err != nil {
time.Sleep(time.Duration(3) * time.Second)
}
}()
var tc Ticket
if e := db.Get("sessions", "ticket", &tc); e != nil {
panic(e.Error())
}
timestamp = strconv.FormatInt(time.Now().Unix(), 10)
longstr := "jsapi_ticket=" + tc.Ticket + "&noncestr=" + noncestr + "×tamp=" + timestamp + "&url=" + url
h := sha1.New()
if _, e := h.Write([]byte(longstr)); e != nil {
log.Println(e.Error())
}
signature = fmt.Sprintf("%x", h.Sum(nil))
return
}
//GetWeixin 得到微信AccessToken和JSTicket
func GetWeixin(appid, secret string) {
var tk Token
var tc Ticket
db, err := storm.Open("db/weixin.db")
if err != nil {
log.Println("Database open err:", err.Error())
}
defer db.Close()
gorequest.New().Get("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + secret).EndStruct(&tk)
gorequest.New().Get("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + tk.AccessToken + "&type=jsapi").EndStruct(&tc)
if e := db.Set("sessions", "token", &tk); e != nil {
log.Println(e.Error())
}
if e := db.Set("sessions", "ticket", &tc); e != nil {
log.Println(e.Error())
}
}
//RandStringRunes 生成随机字符串
func RandStringRunes(n int) string {
b := make([]rune, n)
for i := range b {
b[i] = letterRunes[rand.Intn(len(letterRunes))]
}
return string(b)
}