Просмотр исходного кода

create qr api call tested.

master
Patrick Peng Sun 8 лет назад
Родитель
Сommit
8d9e22df6e
4 измененных файлов: 110 добавлений и 9 удалений
  1. +46
    -2
      main.go
  2. +30
    -7
      qrcode.go
  3. +2
    -0
      serveEvents.go
  4. +32
    -0
      server_test.go

+ 46
- 2
main.go Просмотреть файл

"log" "log"
"net/http" "net/http"
"net/http/httputil" "net/http/httputil"
"net/url"
"strconv"
"time" "time"
) )


http.HandleFunc("/MP_verify_6JqVkftKr39GMakA.txt", mpDomainAuthSecret) http.HandleFunc("/MP_verify_6JqVkftKr39GMakA.txt", mpDomainAuthSecret)
http.HandleFunc("/profile_newly_register", initialRegistrationHandler) http.HandleFunc("/profile_newly_register", initialRegistrationHandler)
http.HandleFunc("/iapi/getAccessToken", supplyAccessToken) http.HandleFunc("/iapi/getAccessToken", supplyAccessToken)
http.HandleFunc("/iapi/createQr", iapiCreateQrCode)
http.HandleFunc("/iapi/createWechatQr", iapiCreateWechatQrCode)
http.ListenAndServe(":65500", nil) http.ListenAndServe(":65500", nil)
} }


} }
} }


func iapiCreateQrCode(w http.ResponseWriter, r *http.Request) {
func iapiCreateWechatQrCode(w http.ResponseWriter, r *http.Request) {
if !checkSignatureByToken(r, IntraAPIConfig.CRMSecrete) { if !checkSignatureByToken(r, IntraAPIConfig.CRMSecrete) {
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprint(w, "unauthorized") fmt.Fprint(w, "unauthorized")
return
}
rq := r.URL.RawQuery
m, _ := url.ParseQuery(rq)

qrValue, qok := m["qrValue"]
expire, eok := m["expire"]

if !qok || !eok {
w.WriteHeader(http.StatusUnprocessableEntity)
fmt.Fprintf(w, "parameter not correct, bad api call %s", time.Now().Format(getCrmTimeLayout()))
return
}

if isStrInt(qrValue[0]) && isStrInt(expire[0]) {
intVal, _ := strconv.Atoi(qrValue[0])
intExpire, _ := strconv.Atoi(expire[0])
jsonB, err := iapiCreateTempQr(int32(intVal), int32(intExpire))
if err == nil {
w.Write(jsonB)
} else {
fmt.Fprintf(w, "%s", err)
}
return
} }


if !isStrInt(qrValue[0]) && expire[0] == "0" {
jsonB, err := isapiCreatePermQr(qrValue[0])
if err == nil {
w.Write(jsonB)
} else {
fmt.Fprintf(w, "%s", err)
}
return

}
}

func isStrInt(v string) bool {
if _, err := strconv.Atoi(v); err == nil {
return true
}
return false
} }


// 用户在网页授权页同意授权给公众号后,微信会将授权数据传给一个回调页面,回调页面需在此域名下,以确保安全可靠。 // 用户在网页授权页同意授权给公众号后,微信会将授权数据传给一个回调页面,回调页面需在此域名下,以确保安全可靠。

+ 30
- 7
qrcode.go Просмотреть файл

"log" "log"
) )


//QRLimitScene 生成永久二维码的信息
type QRLimitScene struct {
//QRPermanentScene 生成永久二维码的信息
type QRPermanentScene struct {
Name string `json:"action_name"` Name string `json:"action_name"`
Info struct { Info struct {
Scene struct { Scene struct {
ID int32 `json:"scene_id"`
IDstr string `json:"scene_str"` //对于永久二维码,我们使用 字符串, 用来区分 数字为主的 临时二维码
ID int32 `json:"scene_id,omitempty"`
IDstr string `json:"scene_str,omitempty"` //对于永久二维码,我们使用 字符串, 用来区分 数字为主的 临时二维码
} `json:"scene"` } `json:"scene"`
} `json:"action_info"` } `json:"action_info"`
} }
//CreateProfileEditQR give user a temp password to login //CreateProfileEditQR give user a temp password to login
//for editing one's own profile //for editing one's own profile
func CreateProfileEditQR() (result QRSrcInfo, err error) { func CreateProfileEditQR() (result QRSrcInfo, err error) {
return createPermanentQR("edit_profile")
}

func createPermanentQR(value string) (result QRSrcInfo, err error) {
// http请求方式: POST // http请求方式: POST
// URL: https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKENPOST数据格式:json // URL: https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKENPOST数据格式:json
// POST数据例子:{"action_name": "QR_LIMIT_SCENE", "action_info": {"scene": {"scene_id": 123}}} // POST数据例子:{"action_name": "QR_LIMIT_SCENE", "action_info": {"scene": {"scene_id": 123}}}
// 或者也可以使用以下POST数据创建字符串形式的二维码参数: // 或者也可以使用以下POST数据创建字符串形式的二维码参数:
// {"action_name": "QR_LIMIT_STR_SCENE", "action_info": {"scene": {"scene_str": "123"}}} // {"action_name": "QR_LIMIT_STR_SCENE", "action_info": {"scene": {"scene_str": "123"}}}
u := getURL4CreateQR() u := getURL4CreateQR()
s := QRLimitScene{}
s := QRPermanentScene{}
//s.Name = "QR_LIMIT_SCENE" //use integer //s.Name = "QR_LIMIT_SCENE" //use integer
s.Name = "QR_LIMIT_STR_SCENE" //use string s.Name = "QR_LIMIT_STR_SCENE" //use string
s.Info.Scene.IDstr = "edit_profile"
s.Info.Scene.IDstr = value
j, _ := json.Marshal(s) j, _ := json.Marshal(s)
log.Println(string(j)) log.Println(string(j))
resp, err := postJSON(j, u) resp, err := postJSON(j, u)
//image: https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=gQEm8DwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyS19UblE5Z3VjU2gxMDAwME0wM04AAgRMYh1ZAwQAAAAA //image: https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=gQEm8DwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyS19UblE5Z3VjU2gxMDAwME0wM04AAgRMYh1ZAwQAAAAA
err = json.Unmarshal([]byte(resp), &result) err = json.Unmarshal([]byte(resp), &result)
return return
}


}
func getURL4CreateQR() (URL string) { func getURL4CreateQR() (URL string) {
atk, _ := GetAccessToken() atk, _ := GetAccessToken()
u := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=%s", atk) u := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=%s", atk)
func qrImgByTicket(ticket string) (url string) { func qrImgByTicket(ticket string) (url string) {
return "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=" + ticket return "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=" + ticket
} }

func iapiCreateTempQr(qr, expire int32) (jsonB []byte, err error) {
if expire <= 0 {
expire = 30 //30 temp seconds only for 0 value
}
info, err := CreateTempQr(qr, expire)
if err == nil {
jsonB, err = json.Marshal(info)
}
return
}

func isapiCreatePermQr(qr string) (jsonB []byte, err error) {
info, err := createPermanentQR(qr)
if err == nil {
jsonB, err = json.Marshal(info)
}
return
}

+ 2
- 0
serveEvents.go Просмотреть файл

in.replyText("") in.replyText("")
onUnSubscribe(in) onUnSubscribe(in)
return return
case "scancode_waitmsg":
in.replyText("scancode_waitmsg/" + e.EventKey)
case "SCAN": case "SCAN":
in.replyText("SCAN/" + e.EventKey) in.replyText("SCAN/" + e.EventKey)
case "LOCATION": case "LOCATION":

+ 32
- 0
server_test.go Просмотреть файл



import ( import (
"bytes" "bytes"
"encoding/json"
"fmt" "fmt"
"log" "log"
"net/http" "net/http"


} }


func TestCreatePermenentWechatQr(t *testing.T) {
scene := "edit_profile" //do not create rubbish, create something that we can use later on
expected := "gQEm8DwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyS19UblE5Z3VjU2gxMDAwME0wM04AAgRMYh1ZAwQAAAAA"
req := buildReqPermQr(scene)
rr, _ := getHTTPResponse(req, iapiCreateWechatQrCode)
m := rr.Body.String()
info := QRSrcInfo{}
err := json.Unmarshal([]byte(m), &info)
AssertEqual(t, err, nil, "decode json should be correct")
log.Println(info)
log.Println(expected)
AssertEqual(t, info.Ticket, expected, "expected ticket not match")
}

func getHTTPResponse(req *http.Request, handler http.HandlerFunc) (rr *httptest.ResponseRecorder, err error) { func getHTTPResponse(req *http.Request, handler http.HandlerFunc) (rr *httptest.ResponseRecorder, err error) {


// Our handlers satisfy http.Handler, so we can call their ServeHTTP method // Our handlers satisfy http.Handler, so we can call their ServeHTTP method
return req return req
} }


func buildReqPermQr(scene string) *http.Request {
req, err := http.NewRequest("GET", "/iapi/createWechatQr", nil)
if err != nil {
log.Fatal(err)
}
q := req.URL.Query()
q.Add("qrValue", scene)
q.Add("expire", "0")
req.URL.RawQuery = q.Encode()

buildReqCommonSignature(req, IntraAPIConfig.CRMSecrete)
buildReqCommonHeader(req)

return req

}

func buildSignature(token string) (signature, timestamp, nonce string) { func buildSignature(token string) (signature, timestamp, nonce string) {
timestamp = fmt.Sprintf("%d", int32(time.Now().Unix())) timestamp = fmt.Sprintf("%d", int32(time.Now().Unix()))
nonce = "1461107899" //a randome string cut from previous wechat request nonce = "1461107899" //a randome string cut from previous wechat request

Загрузка…
Отмена
Сохранить