提交 b8f93064 authored 作者: lihaixin's avatar lihaixin

初始

上级 878a9a4c
module gitlab.jxhh.com/stbz/wechat.git
go 1.15
require github.com/gogf/gf v1.16.6
package wechat
import (
"bytes"
"encoding/json"
"io/ioutil"
"net/http"
)
type WeChatClient struct {
AppId string
Token string
EncodingAESKey string
Appsecret string
ApiUrl string
}
func NewWeChatClient() *WeChatClient {
return &WeChatClient{
AppId: "you AppId",
Token: "you Token",
EncodingAESKey: "you EncodingAESKey",
Appsecret: "you Appsecret",
ApiUrl: "you ApiUrl",
}
}
//获取预授权码
func (client *WeChatClient) GetPreAuthCode(access_token string) (pre_auth_code string, err error) {
url := "https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode?component_access_token=" + access_token
params := map[string]interface{}{
"component_appid": client.AppId,
}
res, err := client.PostJson(url, params)
if err != nil {
return
}
var getPreAuthCode *GetPreAuthCode
err = json.Unmarshal([]byte(res), &getPreAuthCode)
if err != nil {
return
}
pre_auth_code = getPreAuthCode.PreAuthCode
return
}
//获取令牌
func (client *WeChatClient) GetComponentAccessToken(component_verify_ticket string) (res *ApiComponentToken, err error) {
url := "https://api.weixin.qq.com/cgi-bin/component/api_component_token"
params := map[string]interface{}{
"component_appid": client.AppId,
"component_appsecret": client.Appsecret,
"component_verify_ticket": component_verify_ticket,
}
str, err := client.PostJson(url, params)
if err != nil {
return
}
err = json.Unmarshal([]byte(str), &res)
if err != nil {
return
}
return
}
func (client *WeChatClient) PostJson(urlMethod string, params map[string]interface{}) (str string, err error) {
postbyte, _ := json.Marshal(params)
req, err := http.NewRequest("POST", urlMethod, bytes.NewReader(postbyte))
postString := string(postbyte)
if checkErr(err, "wechat NewRequest request"+urlMethod+"myParam:【"+postString+"】") {
return
}
req.Header.Set("Content-Type", "application/json;charset=UTF-8")
resp, err := (&http.Client{}).Do(req)
if checkErr(err, "wechat NewRequest do request"+urlMethod+"myParam:【"+postString+"】") {
return
}
body, _ := ioutil.ReadAll(resp.Body)
resp.Body.Close()
str = string(body)
// glog.Path("./logs/wechatRequire").File("info-{Ymd}.log").Printf(urlMethod + "myParam:【" + postString + "】 thirdParam:【" + str + "】")
return
}
////错误处理函数
func checkErr(err error, extra string) bool {
if err != nil {
formatStr := " Err : %s\n"
if extra != "" {
formatStr = extra + formatStr
}
// glog.Path("./logs/wechatRequire").File("error-{Ymd}.log").Printf("formatStr %s error %v", formatStr, err)
return true
}
return false
}
//绑定公众号
func (client *WeChatClient) Binding(authorizer_appid string, authorizer_access_token string) (res *BindingDate, err error) {
url := "https://api.weixin.qq.com/cgi-bin/open/create?access_token=" + authorizer_access_token
if err != nil {
return
}
params := map[string]interface{}{
"appid": authorizer_appid,
}
str, err := client.PostJson(url, params)
if err != nil {
return
}
err = json.Unmarshal([]byte(str), &res)
return
}
//获取授权信息
func (client *WeChatClient) AuthorizationData(auth_code, access_token string) (res *AuthorizationDataRes, err error) {
url := "https://api.weixin.qq.com/cgi-bin/component/api_query_auth?component_access_token=" + access_token
if err != nil {
return
}
params := map[string]interface{}{
"component_appid": client.AppId,
"authorization_code": auth_code,
}
str, err := client.PostJson(url, params)
if err != nil {
return
}
err = json.Unmarshal([]byte(str), &res)
return
}
//刷新token
func (client *WeChatClient) AuthorizerToken(authorizer_appid, access_token, redisResult string) (res *AuthorizerTokenRes, err error) {
url := "https://api.weixin.qq.com/cgi-bin/component/api_authorizer_token?component_access_token=" + access_token
params := map[string]interface{}{
"authorizer_appid": authorizer_appid,
"component_appid": client.AppId,
"authorizer_refresh_token": redisResult,
}
str, err := client.PostJson(url, params)
if err != nil {
return
}
err = json.Unmarshal([]byte(str), &res)
return
}
package wechat
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"crypto/sha1"
"encoding/base64"
"encoding/binary"
"encoding/xml"
"errors"
"fmt"
"io"
"io/ioutil"
"log"
//"net/http"
http "github.com/gogf/gf/net/ghttp"
"sort"
"strconv"
"strings"
"time"
)
//微信消息加解密工具包
var AesKey []byte
func EncodingAESKey2AESKey(encodingKey string) []byte {
data, _ := base64.StdEncoding.DecodeString(encodingKey + "=")
return data
}
func (client *WeChatClient) MakeSignature(timestamp, nonce string) string {
sl := []string{client.Token, timestamp, nonce}
sort.Strings(sl)
s := sha1.New()
io.WriteString(s, strings.Join(sl, ""))
return fmt.Sprintf("%x", s.Sum(nil))
}
func (client *WeChatClient) MakeMsgSignature(timestamp, nonce, msg_encrypt string) string {
sl := []string{client.Token, timestamp, nonce, msg_encrypt}
sort.Strings(sl)
s := sha1.New()
io.WriteString(s, strings.Join(sl, ""))
return fmt.Sprintf("%x", s.Sum(nil))
}
func (client *WeChatClient) ValidateUrl(timestamp, nonce, signatureIn string) bool {
signatureGen := client.MakeSignature(timestamp, nonce)
fmt.Println(signatureGen, "------------", signatureIn)
if signatureGen != signatureIn {
return false
}
return true
}
func (client *WeChatClient) ValidateMsg(timestamp, nonce, msgEncrypt, msgSignatureIn string) bool {
msgSignatureGen := client.MakeMsgSignature(timestamp, nonce, msgEncrypt)
if msgSignatureGen != msgSignatureIn {
return false
}
return true
}
func (client *WeChatClient) ParseEncryptRequestBody(r *http.Request) *EncryptRequestBody {
body, err := ioutil.ReadAll(r.Body)
if err != nil {
return nil
}
// //mlog.AppendObj(nil, "Wechat Message Service: RequestBody--", body)
requestBody := &EncryptRequestBody{}
xml.Unmarshal(body, requestBody)
return requestBody
}
func (client *WeChatClient) ParseTextRequestBody(r *http.Request) *TextRequestBody {
body, err := ioutil.ReadAll(r.Body)
r.Body.Close()
if err != nil {
log.Fatal(err)
return nil
}
requestBody := &TextRequestBody{}
xml.Unmarshal(body, requestBody)
return requestBody
}
func (client *WeChatClient) Value2CDATA(v string) CDATAText {
//return CDATAText{[]byte("<![CDATA[" + v + "]]>")}
return CDATAText{"<![CDATA[" + v + "]]>"}
}
func (client *WeChatClient) MakeTextResponseBody(fromUserName, toUserName, content string) ([]byte, error) {
textResponseBody := &TextResponseBody{}
textResponseBody.FromUserName = client.Value2CDATA(fromUserName)
textResponseBody.ToUserName = client.Value2CDATA(toUserName)
textResponseBody.MsgType = client.Value2CDATA("text")
textResponseBody.Content = client.Value2CDATA(content)
textResponseBody.CreateTime = strconv.Itoa(int(time.Duration(time.Now().Unix())))
return xml.MarshalIndent(textResponseBody, " ", " ")
}
func (client *WeChatClient) MakeEncryptResponseBody(fromUserName, toUserName, content, nonce, timestamp string) ([]byte, error) {
encryptBody := &EncryptResponseBody{}
encryptXmlData, _ := client.MakeEncryptXmlData(fromUserName, toUserName, timestamp, content)
encryptBody.Encrypt = client.Value2CDATA(encryptXmlData)
encryptBody.MsgSignature = client.Value2CDATA(client.MakeMsgSignature(timestamp, nonce, encryptXmlData))
encryptBody.TimeStamp = timestamp
encryptBody.Nonce = client.Value2CDATA(nonce)
return xml.MarshalIndent(encryptBody, " ", " ")
}
func (client *WeChatClient) MakeEncryptXmlData(fromUserName, toUserName, timestamp, content string) (string, error) {
textResponseBody := &TextResponseBody{}
textResponseBody.FromUserName = client.Value2CDATA(fromUserName)
textResponseBody.ToUserName = client.Value2CDATA(toUserName)
textResponseBody.MsgType = client.Value2CDATA("text")
textResponseBody.Content = client.Value2CDATA(content)
textResponseBody.CreateTime = timestamp
body, err := xml.MarshalIndent(textResponseBody, " ", " ")
if err != nil {
return "", errors.New("xml marshal error")
}
buf := new(bytes.Buffer)
err = binary.Write(buf, binary.BigEndian, int32(len(body)))
if err != nil {
//mlog.AppendObj(err, "Binary write err:", err)
}
bodyLength := buf.Bytes()
randomBytes := []byte("abcdefghijklmnop")
plainData := bytes.Join([][]byte{randomBytes, bodyLength, body, []byte(client.AppId)}, nil)
cipherData, err := client.AesEncrypt(plainData, EncodingAESKey2AESKey(client.EncodingAESKey))
if err != nil {
return "", errors.New("AesEncrypt error")
}
return base64.StdEncoding.EncodeToString(cipherData), nil
}
// PadLength calculates padding length, from github.com/vgorin/cryptogo
func (client *WeChatClient) PadLength(slice_length, blocksize int) (padlen int) {
padlen = blocksize - slice_length%blocksize
if padlen == 0 {
padlen = blocksize
}
return padlen
}
//from github.com/vgorin/cryptogo
func (client *WeChatClient) PKCS7Pad(message []byte, blocksize int) (padded []byte) {
// block size must be bigger or equal 2
if blocksize < 1<<1 {
panic("block size is too small (minimum is 2 bytes)")
}
// block size up to 255 requires 1 byte padding
if blocksize < 1<<8 {
// calculate padding length
padlen := client.PadLength(len(message), blocksize)
// define PKCS7 padding block
padding := bytes.Repeat([]byte{byte(padlen)}, padlen)
// apply padding
padded = append(message, padding...)
return padded
}
// block size bigger or equal 256 is not currently supported
panic("unsupported block size")
}
func (client *WeChatClient) AesEncrypt(plainData []byte, aesKey []byte) ([]byte, error) {
k := len(aesKey)
if len(plainData)%k != 0 {
plainData = client.PKCS7Pad(plainData, k)
}
block, err := aes.NewCipher(aesKey)
if err != nil {
return nil, err
}
iv := make([]byte, aes.BlockSize)
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
return nil, err
}
cipherData := make([]byte, len(plainData))
blockMode := cipher.NewCBCEncrypter(block, iv)
blockMode.CryptBlocks(cipherData, plainData)
return cipherData, nil
}
func (client *WeChatClient) AesDecrypt(cipherData []byte, aesKey []byte) ([]byte, error) {
k := len(aesKey) //PKCS#7
if len(cipherData)%k != 0 {
return nil, errors.New("crypto/cipher: ciphertext size is not multiple of aes key length")
}
block, err := aes.NewCipher(aesKey)
if err != nil {
return nil, err
}
iv := make([]byte, aes.BlockSize)
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
return nil, err
}
blockMode := cipher.NewCBCDecrypter(block, iv)
plainData := make([]byte, len(cipherData))
blockMode.CryptBlocks(plainData, cipherData)
return plainData, nil
}
func (client *WeChatClient) ValidateAppId(id []byte) bool {
if string(id) == client.AppId {
return true
}
return false
}
func (client *WeChatClient) ParseEncryptTextRequestBody(plainText []byte) (*TextRequestBody, error) {
// Read length
buf := bytes.NewBuffer(plainText[16:20])
var length int32
binary.Read(buf, binary.BigEndian, &length)
// appID validation
appIDstart := 20 + length
id := plainText[appIDstart : int(appIDstart)+len(client.AppId)]
if !client.ValidateAppId(id) {
//mlog.AppendObj(nil, "Wechat Message Service: appid is invalid!")
return nil, errors.New("Appid is invalid")
}
//mlog.AppendObj(nil, "Wechat Message Service: appid validation is ok!")
textRequestBody := &TextRequestBody{}
xml.Unmarshal(plainText[20:20+length], textRequestBody)
return textRequestBody, nil
}
func (client *WeChatClient) ParseEncryptResponse(responseEncryptTextBody []byte) {
textResponseBody := &EncryptResponseBody1{}
xml.Unmarshal(responseEncryptTextBody, textResponseBody)
if !client.ValidateMsg(textResponseBody.TimeStamp, textResponseBody.Nonce, textResponseBody.Encrypt, textResponseBody.MsgSignature) {
//mlog.AppendInfo("msg signature is invalid")
return
}
cipherData, err := base64.StdEncoding.DecodeString(textResponseBody.Encrypt)
if err != nil {
//mlog.AppendObj(err, "Wechat Message Service: Decode base64 error")
return
}
plainText, err := client.AesDecrypt(cipherData, EncodingAESKey2AESKey(client.EncodingAESKey))
if err != nil {
//mlog.AppendInfo(err)
return
}
fmt.Println(plainText)
//mlog.AppendInfo(string(plainText))
}
func (client *WeChatClient) DecryptWechatAppletUser(encryptedData string, session_key string, iv string) ([]byte, error) {
ciphertext, _ := base64.StdEncoding.DecodeString(encryptedData)
key, _ := base64.StdEncoding.DecodeString(session_key)
keyBytes := []byte(key)
block, err := aes.NewCipher(keyBytes) //选择加密算法
if err != nil {
return nil, err
}
iv_b, _ := base64.StdEncoding.DecodeString(iv)
blockModel := cipher.NewCBCDecrypter(block, iv_b)
plantText := make([]byte, len(ciphertext))
blockModel.CryptBlocks(plantText, ciphertext)
plantText = client.PKCS7UnPadding(plantText, block.BlockSize())
return plantText, nil
}
func (client *WeChatClient) PKCS7UnPadding(plantText []byte, blockSize int) []byte {
length := len(plantText)
unpadding := int(plantText[length-1])
return plantText[:(length - unpadding)]
}
差异被折叠。
package wechat
import "encoding/json"
//推送微信消息
func (client *WeChatClient) PushWxMsg(tokenStr string, body map[string]interface{}) (res *PushWxMsgRes, err error) {
url := "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + tokenStr
list, err := client.PostJson(url, body)
if err != nil {
return
}
err = json.Unmarshal([]byte(list), &res)
return
}
package wechat
import (
"encoding/json"
)
//创建二维码
func (client *WeChatClient) GetTicket(access_token, SceneStr string) (ticket *GetTicketRes, err error) {
url := "https://api.weixin.qq.com/cgi-bin/qrcode/create"
body := map[string]interface{}{
"expire_seconds": 86400, //二维码有效期一天(86400秒)
"action_name": "QR_STR_SCENE", //临时
"action_info": map[string]interface{}{
"scene": map[string]interface{}{
"scene_str": SceneStr,
},
},
}
list, err := client.PostJson(url+"?access_token="+access_token, body)
if err != nil {
return
}
err = json.Unmarshal([]byte(list), &ticket)
return
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论