瀏覽代碼

create qr api call tested.

master
Patrick Peng Sun 8 年之前
父節點
當前提交
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 查看文件

@@ -5,6 +5,8 @@ import (
"log"
"net/http"
"net/http/httputil"
"net/url"
"strconv"
"time"
)

@@ -60,7 +62,7 @@ func setupHTTPHandler() {
http.HandleFunc("/MP_verify_6JqVkftKr39GMakA.txt", mpDomainAuthSecret)
http.HandleFunc("/profile_newly_register", initialRegistrationHandler)
http.HandleFunc("/iapi/getAccessToken", supplyAccessToken)
http.HandleFunc("/iapi/createQr", iapiCreateQrCode)
http.HandleFunc("/iapi/createWechatQr", iapiCreateWechatQrCode)
http.ListenAndServe(":65500", nil)
}

@@ -114,11 +116,53 @@ func supplyAccessToken(w http.ResponseWriter, r *http.Request) {
}
}

func iapiCreateQrCode(w http.ResponseWriter, r *http.Request) {
func iapiCreateWechatQrCode(w http.ResponseWriter, r *http.Request) {
if !checkSignatureByToken(r, IntraAPIConfig.CRMSecrete) {
w.WriteHeader(http.StatusUnauthorized)
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 查看文件

@@ -6,13 +6,13 @@ import (
"log"
)

//QRLimitScene 生成永久二维码的信息
type QRLimitScene struct {
//QRPermanentScene 生成永久二维码的信息
type QRPermanentScene struct {
Name string `json:"action_name"`
Info 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:"action_info"`
}
@@ -38,16 +38,20 @@ type QRSrcInfo struct {
//CreateProfileEditQR give user a temp password to login
//for editing one's own profile
func CreateProfileEditQR() (result QRSrcInfo, err error) {
return createPermanentQR("edit_profile")
}

func createPermanentQR(value string) (result QRSrcInfo, err error) {
// http请求方式: POST
// 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_STR_SCENE", "action_info": {"scene": {"scene_str": "123"}}}
u := getURL4CreateQR()
s := QRLimitScene{}
s := QRPermanentScene{}
//s.Name = "QR_LIMIT_SCENE" //use integer
s.Name = "QR_LIMIT_STR_SCENE" //use string
s.Info.Scene.IDstr = "edit_profile"
s.Info.Scene.IDstr = value
j, _ := json.Marshal(s)
log.Println(string(j))
resp, err := postJSON(j, u)
@@ -58,8 +62,8 @@ func CreateProfileEditQR() (result QRSrcInfo, err error) {
//image: https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=gQEm8DwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyS19UblE5Z3VjU2gxMDAwME0wM04AAgRMYh1ZAwQAAAAA
err = json.Unmarshal([]byte(resp), &result)
return
}

}
func getURL4CreateQR() (URL string) {
atk, _ := GetAccessToken()
u := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=%s", atk)
@@ -98,3 +102,22 @@ func CreateTempQr(sceneID int32, expire int32) (result QRSrcInfo, err error) {
func qrImgByTicket(ticket string) (url string) {
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 查看文件

@@ -12,6 +12,8 @@ func (ss *openIDSessionData) serveEvents(in InWechatMsg) (processed bool) {
in.replyText("")
onUnSubscribe(in)
return
case "scancode_waitmsg":
in.replyText("scancode_waitmsg/" + e.EventKey)
case "SCAN":
in.replyText("SCAN/" + e.EventKey)
case "LOCATION":

+ 32
- 0
server_test.go 查看文件

@@ -2,6 +2,7 @@ package main

import (
"bytes"
"encoding/json"
"fmt"
"log"
"net/http"
@@ -91,6 +92,20 @@ func TestGetAccesstokenUnAuthorized(t *testing.T) {

}

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) {

// Our handlers satisfy http.Handler, so we can call their ServeHTTP method
@@ -191,6 +206,23 @@ func buildReqGetAccessTokenUnAuthorized() *http.Request {
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) {
timestamp = fmt.Sprintf("%d", int32(time.Now().Unix()))
nonce = "1461107899" //a randome string cut from previous wechat request

Loading…
取消
儲存