| @ -0,0 +1,11 @@ | |||
| package weixinrpc | |||
| import ( | |||
| "testing" | |||
| ) | |||
| func Test_GetAccessToken(t *testing.T) { | |||
| ret, err := GetAccessToken("test", "100005", "wx303b0cec4a8d1bc1", "90ddb8da4bc4e96e600532dd24be8c7b") | |||
| t.Log(ret, err) | |||
| } | |||
| @ -0,0 +1,71 @@ | |||
| package weixinrpc | |||
| import ( | |||
| "encoding/json" | |||
| "log" | |||
| "strconv" | |||
| "time" | |||
| "git.tetele.net/tgo/crypter" | |||
| "github.com/golang/protobuf/proto" | |||
| ) | |||
| func GetAppOpenid(appid, secret, js_code string, url ...string) (map[string]string, error) { | |||
| conn, err := rpc_server_conn(url...) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| defer conn.Close() | |||
| data := MiniAppOpenidReq{} | |||
| data.Appid = appid | |||
| data.Secret = secret | |||
| data.JsCode = js_code | |||
| data_json, err := json.Marshal(data) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| encryData := crypter.DesEn(string(data_json), DES_KEY) | |||
| now_int64 := time.Now().Unix() | |||
| now := strconv.FormatInt(now_int64, 10) | |||
| sign := Sign(encryData, now) | |||
| req := &Request{ | |||
| proto.String(encryData), | |||
| proto.String(now), | |||
| proto.String(sign), | |||
| nil} | |||
| res := &Response{} | |||
| err = conn.GetAppOpenid(req, res) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| //解密 | |||
| res_data_de, err := GetOrgData(res) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| var res_arr map[string]string | |||
| err = json.Unmarshal([]byte(res_data_de), &res_arr) | |||
| if err != nil { | |||
| log.Println(err, res_data_de) | |||
| return nil, err | |||
| } | |||
| return res_arr, nil | |||
| } | |||
| @ -0,0 +1,106 @@ | |||
| package weixinrpc | |||
| import ( | |||
| "encoding/json" | |||
| "errors" | |||
| "strconv" | |||
| "time" | |||
| "git.tetele.net/tgo/crypter" | |||
| "github.com/golang/protobuf/proto" | |||
| ) | |||
| func SetResData(data interface{}, res *Response) { | |||
| res_data_json, err := json.Marshal(data) | |||
| if err == nil { | |||
| encryData := crypter.DesEn(string(res_data_json), DES_KEY) | |||
| now_str := strconv.FormatInt(time.Now().Unix(), 10) | |||
| res_sign := Sign(encryData, now_str) | |||
| res.Data = proto.String(encryData) | |||
| res.Time = proto.String(now_str) | |||
| res.Sign = proto.String(res_sign) | |||
| } | |||
| } | |||
| func SetReqData(arg interface{}) (*Request, error) { | |||
| data_json, err := json.Marshal(arg) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| now_int64 := time.Now().Unix() | |||
| encryData := crypter.DesEn(string(data_json), DES_KEY) | |||
| now := strconv.FormatInt(now_int64, 10) | |||
| sign := Sign(encryData, now) | |||
| return &Request{proto.String(encryData), proto.String(now), proto.String(sign), nil}, nil | |||
| } | |||
| func GetReqData(req *Request) (string, error) { | |||
| res_data := req.GetData() | |||
| if res_data != "" { | |||
| time_int64, err := strconv.ParseInt(req.GetTime(), 10, 64) | |||
| if err != nil { | |||
| return "", err | |||
| } | |||
| now_int64 := time.Now().Unix() | |||
| if now_int64-time_int64 > 10 || time_int64-now_int64 > 10 { | |||
| //时间误差前后10秒,返回 | |||
| return "", errors.New("返回时间错误") | |||
| } | |||
| check_sign := CheckSign(req.GetSign(), res_data, req.GetTime()) | |||
| if !check_sign { | |||
| return "", errors.New("返回数据签名错误") | |||
| } | |||
| //解密 | |||
| return crypter.DesDe(res_data, DES_KEY), nil | |||
| } | |||
| return "", nil | |||
| } | |||
| func GetResData(res *Response) (string, error) { | |||
| res_data := res.GetData() | |||
| if res_data != "" { | |||
| time_int64, err := strconv.ParseInt(res.GetTime(), 10, 64) | |||
| if err != nil { | |||
| return "", err | |||
| } | |||
| now_int64 := time.Now().Unix() | |||
| if now_int64-time_int64 > 10 || time_int64-now_int64 > 10 { | |||
| //时间误差前后10秒,返回 | |||
| return "", errors.New("返回时间错误") | |||
| } | |||
| check_sign := CheckSign(res.GetSign(), res_data, res.GetTime()) | |||
| if !check_sign { | |||
| return "", errors.New("返回数据签名错误") | |||
| } | |||
| //解密 | |||
| return crypter.DesDe(res_data, DES_KEY), nil | |||
| } | |||
| return "", nil | |||
| } | |||
| @ -0,0 +1,13 @@ | |||
| module git.tetele.net/tgo/weixinrpc | |||
| go 1.14 | |||
| require ( | |||
| git.tetele.net/tgo/crypter v0.2.2 | |||
| git.tetele.net/tgo/helper v0.2.6 | |||
| git.tetele.net/yueheng/conf v1.2.4 | |||
| github.com/chai2010/protorpc v1.1.3 | |||
| github.com/golang/protobuf v1.0.0 | |||
| golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 // indirect | |||
| golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect | |||
| ) | |||
| @ -0,0 +1,21 @@ | |||
| git.tetele.net/tgo/crypter v0.2.2 h1:YMQJh2Gj5Po4ZfelJUmXBKi01UbmtiSy3bmqRfnYQMo= | |||
| git.tetele.net/tgo/crypter v0.2.2/go.mod h1:vfvRLZA8+lHNgNXneOcgvVhDyuv25ZRb+C6xHOmXNx0= | |||
| git.tetele.net/tgo/helper v0.2.6 h1:JC+N+If/bGvcwuUSklva17YDNtKBV2Qpvl5RQpMySOY= | |||
| git.tetele.net/tgo/helper v0.2.6/go.mod h1:89mQwyfqZ+t8YXiVwzSxA70gLlUNqoZGDEUxvV46jXk= | |||
| git.tetele.net/yueheng/conf v1.2.4 h1:QQr6yflZa9PjISTyNDBL25qOmkRYR06BCJJWWagETQI= | |||
| git.tetele.net/yueheng/conf v1.2.4/go.mod h1:qRujMTqjMByvdC05qdfscZMFRKM5XA1qbtz4rnFyStY= | |||
| github.com/chai2010/protorpc v1.1.3 h1:VJK5hIoZn0XCGol0GmbxZkUG6FbTI5LP2Lam6RVd15w= | |||
| github.com/chai2010/protorpc v1.1.3/go.mod h1:/wO0kiyVdu7ug8dCMrA2yDr2vLfyhsLEuzLa9J2HJ+I= | |||
| github.com/golang/protobuf v1.0.0 h1:lsek0oXi8iFE9L+EXARyHIjU5rlWIhhTkjDz3vHhWWQ= | |||
| github.com/golang/protobuf v1.0.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | |||
| github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= | |||
| github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= | |||
| golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w= | |||
| golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= | |||
| golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= | |||
| golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= | |||
| golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||
| golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
| golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | |||
| golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | |||
| golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | |||
| @ -0,0 +1,80 @@ | |||
| package weixinrpc | |||
| import ( | |||
| "encoding/json" | |||
| "log" | |||
| "strconv" | |||
| "time" | |||
| "git.tetele.net/tgo/crypter" | |||
| "github.com/golang/protobuf/proto" | |||
| ) | |||
| func GetMiniAppOpenid(appid, secret, js_code string, url ...string) (*MiniAppOpenidRes, error) { | |||
| conn, err := rpc_server_conn(url...) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| defer conn.Close() | |||
| data := MiniAppOpenidReq{} | |||
| data.Appid = appid | |||
| data.Secret = secret | |||
| data.JsCode = js_code | |||
| data_json, err := json.Marshal(data) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| encryData := crypter.DesEn(string(data_json), DES_KEY) | |||
| now_int64 := time.Now().Unix() | |||
| now := strconv.FormatInt(now_int64, 10) | |||
| sign := Sign(encryData, now) | |||
| req := &Request{ | |||
| proto.String(encryData), | |||
| proto.String(now), | |||
| proto.String(sign), | |||
| nil} | |||
| res := &Response{} | |||
| err = conn.GetMiniAppOpenid(req, res) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| return HandleMiniAppOpenid(res) | |||
| } | |||
| /** | |||
| * 处理返回结果 | |||
| */ | |||
| func HandleMiniAppOpenid(res *Response) (*MiniAppOpenidRes, error) { | |||
| //解密 | |||
| res_data_de, err := GetOrgData(res) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| var res_arr MiniAppOpenidRes | |||
| err = json.Unmarshal([]byte(res_data_de), &res_arr) | |||
| if err != nil { | |||
| log.Println(err, res_data_de) | |||
| return nil, err | |||
| } | |||
| return &res_arr, nil | |||
| } | |||
| @ -0,0 +1,62 @@ | |||
| package weixinrpc | |||
| import ( | |||
| "encoding/json" | |||
| "strconv" | |||
| "time" | |||
| "git.tetele.net/tgo/crypter" | |||
| "github.com/golang/protobuf/proto" | |||
| ) | |||
| func GetMiniAppQrcode(siteId, appId, appSecret string, qrcodeParams map[string]interface{}, url ...string) (string, error) { | |||
| conn, err := rpc_server_conn(url...) | |||
| if err != nil { | |||
| return "", err | |||
| } | |||
| defer conn.Close() | |||
| data := map[string]interface{}{} | |||
| data["site_id"] = siteId | |||
| data["app_id"] = appId | |||
| data["app_secret"] = appSecret | |||
| data["qrcode"] = qrcodeParams | |||
| data_json, err := json.Marshal(data) | |||
| if err != nil { | |||
| return "", err | |||
| } | |||
| encryData := crypter.DesEn(string(data_json), DES_KEY) | |||
| now_int64 := time.Now().Unix() | |||
| now := strconv.FormatInt(now_int64, 10) | |||
| sign := Sign(encryData, now) | |||
| req := &Request{ | |||
| proto.String(encryData), | |||
| proto.String(now), | |||
| proto.String(sign), | |||
| nil} | |||
| res := &Response{} | |||
| err = conn.GetMiniappQrcode(req, res) | |||
| if err != nil { | |||
| return "", err | |||
| } | |||
| // 解密 | |||
| res_data_de, err := GetOrgData(res) | |||
| if err != nil { | |||
| return "", err | |||
| } | |||
| return res_data_de, nil | |||
| } | |||
| @ -0,0 +1,33 @@ | |||
| package weixinrpc | |||
| import ( | |||
| "testing" | |||
| ) | |||
| func Test_GetMiniappCode(t *testing.T){ | |||
| site_id := "1198881" | |||
| appid := "wx3d53ccbaf69f7995" | |||
| appSecret := "165983626235636be54a16404e3e70a7" | |||
| page := "" | |||
| scene := "user_id=19" | |||
| qrcodeParams := map[string]interface{}{ | |||
| "page":page, | |||
| "scene":scene, | |||
| // "is_hyaline":true, | |||
| } | |||
| qrcode,err := GetMiniAppQrcode(site_id,appid,appSecret,qrcodeParams) | |||
| t.Log(qrcode) | |||
| t.Log(err) | |||
| } | |||
| func Test_GetMiniappOpenid(t *testing.T){ | |||
| appid := "wx3d53ccbaf69f7995" | |||
| appSecret := "165983626235636be54a16404e3e70a7" | |||
| js_code := "063iBAll27ez884FT6nl254pW02iBAlw" | |||
| res,err := GetMiniAppOpenid(appid,appSecret,js_code) | |||
| t.Log(res) | |||
| t.Log(err) | |||
| } | |||
| @ -0,0 +1,80 @@ | |||
| package weixinrpc | |||
| import ( | |||
| "encoding/json" | |||
| "log" | |||
| "strconv" | |||
| "time" | |||
| "git.tetele.net/tgo/crypter" | |||
| "github.com/golang/protobuf/proto" | |||
| ) | |||
| func GetMpOpenId(appid, secret, js_code string, url ...string) (*MpOpenidRes, error) { | |||
| conn, err := rpc_server_conn(url...) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| defer conn.Close() | |||
| data := MiniAppOpenidReq{} | |||
| data.Appid = appid | |||
| data.Secret = secret | |||
| data.JsCode = js_code | |||
| data_json, err := json.Marshal(data) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| encryData := crypter.DesEn(string(data_json), DES_KEY) | |||
| now_int64 := time.Now().Unix() | |||
| now := strconv.FormatInt(now_int64, 10) | |||
| sign := Sign(encryData, now) | |||
| req := &Request{ | |||
| proto.String(encryData), | |||
| proto.String(now), | |||
| proto.String(sign), | |||
| nil} | |||
| res := &Response{} | |||
| err = conn.GetMpOpenid(req, res) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| return HandleMpOpenid(res) | |||
| } | |||
| /** | |||
| * 处理返回结果 | |||
| */ | |||
| func HandleMpOpenid(res *Response) (*MpOpenidRes, error) { | |||
| //解密 | |||
| res_data_de, err := GetOrgData(res) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| var res_arr MpOpenidRes | |||
| err = json.Unmarshal([]byte(res_data_de), &res_arr) | |||
| if err != nil { | |||
| log.Println(err, res_data_de) | |||
| return nil, err | |||
| } | |||
| return &res_arr, nil | |||
| } | |||
| @ -0,0 +1,77 @@ | |||
| package weixinrpc | |||
| import ( | |||
| "encoding/json" | |||
| "log" | |||
| "strconv" | |||
| "time" | |||
| "git.tetele.net/tgo/crypter" | |||
| "github.com/golang/protobuf/proto" | |||
| ) | |||
| func GetMpUserInfo(accessToken,openId string,url ...string) (*MpUserInfoRes, error) { | |||
| conn, err := rpc_server_conn(url...) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| defer conn.Close() | |||
| data := MpUserInfoReq{} | |||
| data.AccessToken = accessToken | |||
| data.Openid = openId | |||
| data_json, err := json.Marshal(data) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| encryData := crypter.DesEn(string(data_json), DES_KEY) | |||
| now_int64 := time.Now().Unix() | |||
| now := strconv.FormatInt(now_int64, 10) | |||
| sign := Sign(encryData, now) | |||
| req := &Request{ | |||
| proto.String(encryData), | |||
| proto.String(now), | |||
| proto.String(sign), | |||
| nil} | |||
| res := &Response{} | |||
| err = conn.GetMpUserInfo(req, res) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| return HandleMpUserInfo(res) | |||
| } | |||
| /** | |||
| * 处理返回结果 | |||
| */ | |||
| func HandleMpUserInfo(res *Response) (*MpUserInfoRes, error) { | |||
| //解密 | |||
| res_data_de, err := GetOrgData(res) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| var res_arr MpUserInfoRes | |||
| err = json.Unmarshal([]byte(res_data_de), &res_arr) | |||
| if err != nil { | |||
| log.Println(err, res_data_de) | |||
| return nil, err | |||
| } | |||
| return &res_arr, nil | |||
| } | |||
| @ -0,0 +1,63 @@ | |||
| package weixinrpc | |||
| import ( | |||
| "encoding/json" | |||
| ) | |||
| /** | |||
| * 订单号,子单号,总金额,退款金额,微信商户id,微信商户平台API私钥,平台证书,商户平台证书序列号,商品名,退款原因,商品id,回调地址 | |||
| */ | |||
| func PayRefund(order_sn, sn, total, refund, wx_mp_mch_id, wx_mch_apiclient_key, | |||
| wx_pay_cert, mch_serial_no, title, uuid, reason, notify_url string, | |||
| url ...string) (map[string]string, error) { | |||
| conn, err := rpc_server_conn(url...) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| defer conn.Close() | |||
| data := map[string]string{ | |||
| "order_sn": order_sn, | |||
| "sn": sn, | |||
| "total": total, | |||
| "refund": refund, | |||
| "wx_mp_mch_id": wx_mp_mch_id, | |||
| "wx_mch_apiclient_key": wx_mch_apiclient_key, | |||
| "wx_pay_cert": wx_pay_cert, | |||
| "mch_serial_no": mch_serial_no, | |||
| "reason": reason, | |||
| "uuid": uuid, | |||
| "title": title, | |||
| "notify_url": notify_url, | |||
| } | |||
| req, err := SetReqData(data) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| res := &Response{} | |||
| err = conn.PayRefund(req, res) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| res_data_de, err := GetResData(res) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| if res_data_de == "" { | |||
| return nil, nil | |||
| } | |||
| var res_arr map[string]string | |||
| err = json.Unmarshal([]byte(res_data_de), &res_arr) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| return res_arr, nil | |||
| } | |||
| @ -0,0 +1,76 @@ | |||
| package weixinrpc | |||
| import ( | |||
| "testing" | |||
| ) | |||
| func Test_PayRefund(t *testing.T) { | |||
| order_sn := "1638614195578314926" //订单号 | |||
| sn := "1638614195546464238" //子单号 | |||
| total := "0.04" //总金额 | |||
| refund := "0.04" //退款金额 | |||
| wx_mp_mch_id := "1612824503" //微信商户id | |||
| wx_mch_apiclient_key := `-----BEGIN PRIVATE KEY----- | |||
| MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDS6pGtfloagNoX | |||
| NPc27PFaw+K/H4n8Z7sdHyXSD6hlLzvTq7Fx4/MZYgmmXrhAjtdW/+KeKrHnYyAq | |||
| jNlkIamCVhteNZd9XQ3SCWpmqLVtT6sMV5Xtx31A8WqRi0ABReiNlTjnlqOntpkr | |||
| bP/9NTwQJLsAVKCbkOtaL3fFm5aTd6Jsu4BTq/4GWQOhY4UfsBcwBRTOJ9LsowX3 | |||
| CZA4npha8nVftKT/ut7eqKgD11l6VrCgsksJ+swEmz4Je7WhEplDp+4nNdpEXwE0 | |||
| u5/CWqu/kZCf2LFHmikHMstVy/FMZ66l5sHXpEA8e5dfr92/mfK7R2nvER/M6VPg | |||
| vkFWmL19AgMBAAECggEAOAH4G0URMjaDM2RqPVigIsUfojcC0lbNVkdeKLDlu7DW | |||
| Rzgxj5fDhzsEavx+Gw6TWlPq3qthwJsPAJ2UYMWbmLO64sKCbtTWBa9gZNBqFRPx | |||
| zP45HwI5XZR+AxYiMfRZc7dre/wBi1iuxdxVAe0v/O10BvtyBr1t8e3m9T+Ctbe0 | |||
| m6DLABIkrnwULBuHuWr1aFq2anmDrEiVzE09792qSPOspP/gbBnhkispu3DyqcaK | |||
| 0lI8s/asGfa0OI7XPVR0L+9pXmbPIE75JcHp2YOxXIL/PWcGxy6G6M7Riw4CSb4N | |||
| zHrK1hoz8bynGrRGM5UzUfKgcZHYpLfEV5mOuybvYQKBgQDwdMqyhDvIx61Xw+cg | |||
| HfCuk6pddZoIlq4cdA8by2WWtM2+KVO5RIOnRWkMrVHQ02piYyzXLEbFk+jWi0U9 | |||
| 3f6Ph0aiX9Zg5tr8/EMArYySOyL6CNFxPe1rkK3edcbwZRphJ2RZi0nIhAzbwqKU | |||
| MOYqdM2KgAHSkofCA4nFYFc9NQKBgQDgjO70uHWB3Er8orkxo9BIoFqOyZKZMTjE | |||
| yDuhu3EyY6O+TrdWJQGeTcoeXeGh2sIqxri7T2CeLip669TiSkTHm7M6EhF5LB4g | |||
| qMCl2zjDtdLAxc1zlDXHMjWh9VdQ9adsb7eQqhIm7vRCQ7oABhGiXXvDvxugJ8RN | |||
| mpHYK04wKQKBgAld81t67T1IEgeeOQ22PN8AH53ea+6zt/qhxsjlZoK1bmJfB8Tq | |||
| 11oXyRzWT56b7cQBawjCz8r4lRRufncHg9ghg+3lX9uMgrFiPlXzbMtxhE5LM6V+ | |||
| rRYIn81Ptz08Iwfv2efnFiu6gSm6bkzpjr3OqQchL3D9hk5XhvFqbFuVAoGBAIKX | |||
| M/k6tYwac7nNYOrPnDhAmank7M8O4zb+RD/g5QorDHWHDfSZfQF1uBBFBQ2+TaHX | |||
| BGRa25PiwW3PbXVVP/7ePDOPgn33/GV9/tv2TGL1gWX/I2cOUOBSAQL5zhgVZZMY | |||
| vabyYbAm1AMdpDSTUvocZ/gFUqmntvBy7lLLjKNRAoGAaj3O6BP/djkE9zsm7Ao0 | |||
| tqgwec15iaGz/5rRYXyVrWo0UqF0lNvXK2m5D0EiQeGSv3LR9EuilysVego4MvQk | |||
| Dn8ITNRti+YCeRgPBGd38+o4wWXsS50WtlQMWx2DmYrORPYadHEuA9lo1rt5uDoR | |||
| IOLIPinMkOLYWAdLHqPzL7E= | |||
| -----END PRIVATE KEY-----` //微信商户平台API私钥 | |||
| wx_pay_cert := `-----BEGIN CERTIFICATE----- | |||
| MIID3DCCAsSgAwIBAgIUSdPFwujSihpwlK7m057+WdAXRnAwDQYJKoZIhvcNAQEL | |||
| BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT | |||
| FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg | |||
| Q0EwHhcNMjEwODExMDcwMzExWhcNMjYwODEwMDcwMzExWjBuMRgwFgYDVQQDDA9U | |||
| ZW5wYXkuY29tIHNpZ24xEzARBgNVBAoMClRlbnBheS5jb20xHTAbBgNVBAsMFFRl | |||
| bnBheS5jb20gQ0EgQ2VudGVyMQswCQYDVQQGDAJDTjERMA8GA1UEBwwIU2hlblpo | |||
| ZW4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDSzutwzsCf03UmqtP5 | |||
| z+oMAyoPK78uNH9+inpMZlkLJslruerVhRVgz+U/Yz7t25GXha4Ui0EQ/HoaIUea | |||
| wbOghYA7GAk21lOU0WLaX8a9U2t96nme9PJ5yqnqi8P7FpX+HsJG+3WRhL0D3hm4 | |||
| iLBEhMbHXvzri2NIbYDiac62Ekx6xtk3XjmfyTgabYRzTIJ8cw8RWW2+X0GYlyi9 | |||
| biXy9diVd/rohl5++6ATcRmk51skJaPI4qaQDBjpedaS/pSd83ujhs51M/CvqgQ6 | |||
| Woczk/ha5w9PVFJTIwIMzmr3HSXjYtKxgMucrfpNOlrb2uVD4xmulDA6XAhk9Hx/ | |||
| bj8fAgMBAAGjgYEwfzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIE8DBlBgNVHR8EXjBc | |||
| MFqgWKBWhlRodHRwOi8vZXZjYS5pdHJ1cy5jb20uY24vcHVibGljL2l0cnVzY3Js | |||
| P0NBPTFCRDQyMjBFNTBEQkMwNEIwNkFEMzk3NTQ5ODQ2QzAxQzNFOEVCRDIwDQYJ | |||
| KoZIhvcNAQELBQADggEBAA69QPm7w9LcXU5lmyQ0HQdQFp9Rdq3IYmpEPDytRL0M | |||
| L40PKRc4VdS9ttZN4PUxh0Gat4EoYD7YR3nfB7Lx1xu00G3Rondx7g7ryTVN3y5E | |||
| SioX94JsZ8QD3NDHuCPwgMT5SS1FIyO9ls8x82vtagZc1M9YjP1x8kfledJxC4NI | |||
| JhpX1cuKgCbRLhi0qrerRoQlbbb7oP6NsBnXuVCPCHzxDg+YgLuPrz82w7Z5+UxZ | |||
| G0KYKvGdupW5Sc8n+yJczCsmhhhmJy8N17qf60UGi9vQdHXVy2nwHRMTnjTpP56x | |||
| 52hbci3SxbjNY9IC+J+jaYDM6ChMPVIsdEniJKpof5E= | |||
| -----END CERTIFICATE-----` //平台证书 | |||
| mch_serial_no := "735B1DE549DB6BF12796BA0EF87BABA7D3853080" //商户平台证书序列号 | |||
| reason := "缺货取消" //退款原因 | |||
| uuid := "28303" //退款原因 | |||
| title := "抽巾纹~~" //回调地址 | |||
| notify_url := "https://manager.youpincat.com/api/wxrefunds/refund_notify" //回调地址 | |||
| ret, err := PayRefund(order_sn, sn, total, refund, wx_mp_mch_id, wx_mch_apiclient_key, | |||
| wx_pay_cert, mch_serial_no, title, uuid, reason, notify_url) | |||
| t.Log(ret) | |||
| t.Log(err) | |||
| } | |||
| @ -0,0 +1,97 @@ | |||
| package weixinrpc | |||
| import ( | |||
| "encoding/json" | |||
| "git.tetele.net/tgo/crypter" | |||
| "github.com/golang/protobuf/proto" | |||
| "strconv" | |||
| "time" | |||
| ) | |||
| //检测图片是否合法 | |||
| func ImgSecCheck(appId, appSecret,imgUrl string, url ...string) (error) { | |||
| conn, err := rpc_server_conn(url...) | |||
| if err != nil { | |||
| return err | |||
| } | |||
| defer conn.Close() | |||
| data := map[string]interface{}{} | |||
| data["app_id"] = appId | |||
| data["app_secret"] = appSecret | |||
| data["img_url"] = imgUrl | |||
| data_json, err := json.Marshal(data) | |||
| if err != nil { | |||
| return err | |||
| } | |||
| encryData := crypter.DesEn(string(data_json), DES_KEY) | |||
| now_int64 := time.Now().Unix() | |||
| now := strconv.FormatInt(now_int64, 10) | |||
| sign := Sign(encryData, now) | |||
| req := &Request{ | |||
| proto.String(encryData), | |||
| proto.String(now), | |||
| proto.String(sign), | |||
| nil} | |||
| res := &Response{} | |||
| err = conn.ImgSecCheck(req, res) | |||
| if err != nil { | |||
| return err | |||
| } | |||
| return nil | |||
| } | |||
| //检测文本是否合法 | |||
| func MsgSecCheck(appId, appSecret string,checkData map[string]interface{}, url ...string)error{ | |||
| conn, err := rpc_server_conn(url...) | |||
| if err != nil { | |||
| return err | |||
| } | |||
| defer conn.Close() | |||
| data := map[string]interface{}{} | |||
| data["app_id"] = appId | |||
| data["app_secret"] = appSecret | |||
| data["check_data"] = checkData | |||
| data_json, err := json.Marshal(data) | |||
| if err != nil { | |||
| return err | |||
| } | |||
| encryData := crypter.DesEn(string(data_json), DES_KEY) | |||
| now_int64 := time.Now().Unix() | |||
| now := strconv.FormatInt(now_int64, 10) | |||
| sign := Sign(encryData, now) | |||
| req := &Request{ | |||
| proto.String(encryData), | |||
| proto.String(now), | |||
| proto.String(sign), | |||
| nil} | |||
| res := &Response{} | |||
| err = conn.MsgSecCheck(req, res) | |||
| if err != nil { | |||
| return err | |||
| } | |||
| return nil | |||
| } | |||
| @ -0,0 +1,31 @@ | |||
| package weixinrpc | |||
| import ( | |||
| "git.tetele.net/tgo/helper" | |||
| "testing" | |||
| ) | |||
| func Test_CheckImg(t *testing.T){ | |||
| appid := "wx3d53ccbaf69f7995" | |||
| appSecret := "165983626235636be54a16404e3e70a7" | |||
| imgUrl := helper.TencentCloudImageCompress("https://images-1306193253.cos.ap-guangzhou.myqcloud.com/uploads/20211026/1635213788c5713f49816c74a0e130694ed6544e71.jpg","450") | |||
| //imgUrl := "https://images-1306193253.cos.ap-guangzhou.myqcloud.com/uploads/20211026/1635213788c5713f49816c74a0e130694ed6544e71.jpg" | |||
| err := ImgSecCheck(appid,appSecret,imgUrl) | |||
| t.Log(err) | |||
| } | |||
| func Test_CheckMsg(t *testing.T){ | |||
| appid := "wx3d53ccbaf69f7995" | |||
| appSecret := "165983626235636be54a16404e3e70a7" | |||
| checkData := map[string]interface{}{ | |||
| "openid":"oLBHE4kRuj8ywGKuXMgLbmFKrdkM", | |||
| "scene":3, | |||
| "content":"", | |||
| } | |||
| err := MsgSecCheck(appid,appSecret,checkData) | |||
| t.Log(err) | |||
| } | |||
| @ -0,0 +1,70 @@ | |||
| package weixinrpc | |||
| import ( | |||
| "encoding/json" | |||
| "strconv" | |||
| "time" | |||
| "git.tetele.net/tgo/crypter" | |||
| "github.com/golang/protobuf/proto" | |||
| ) | |||
| /** | |||
| * 发送小程序订阅服务消息 | |||
| * appid,secret 小程序ID 密钥 | |||
| * touser 小程序openid | |||
| * mp_appid 关联公众号appid,要求与小程序有绑定且同主体 | |||
| * temp_id 模板id | |||
| * page 跳转的url | |||
| * lang 进入小程序查看”的语言类型,支持zh_CN(简体中文)、en_US(英文)、zh_HK(繁体中文)、zh_TW(繁体中文),默认为zh_CN | |||
| * miniprogram_state 跳转小程序类型:developer为开发版;trial为体验版;formal为正式版;默认为正式版 | |||
| * data 公众号模板消息的数据 | |||
| */ | |||
| func SendMiniSubscribeMessage(dbname, site_id string, appid, secret, touser, temp_id, page string, miniprogram_state, lang string, data interface{}, url ...string) (*WxApiRes, error) { | |||
| conn, err := rpc_server_conn(url...) | |||
| message_data := SubscribeMessageReq{} | |||
| message_data.SiteId = site_id | |||
| message_data.Dbname = dbname | |||
| message_data.Appid = appid | |||
| message_data.Secret = secret | |||
| message_data.Touser = touser | |||
| message_data.TemplateId = temp_id | |||
| message_data.Page = page | |||
| message_data.MiniprogramState = miniprogram_state | |||
| message_data.Lang = lang | |||
| message_data.Data = data | |||
| data_json, err := json.Marshal(message_data) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| encryData := crypter.DesEn(string(data_json), DES_KEY) | |||
| now_int64 := time.Now().Unix() | |||
| now := strconv.FormatInt(now_int64, 10) | |||
| sign := Sign(encryData, now) | |||
| req := &Request{ | |||
| proto.String(encryData), | |||
| proto.String(now), | |||
| proto.String(sign), | |||
| nil} | |||
| res := &Response{} | |||
| err = conn.SendMiniappSubscribeMessage(req, res) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| return HandleRes(res) | |||
| } | |||
| @ -0,0 +1,30 @@ | |||
| package weixinrpc | |||
| import ( | |||
| "testing" | |||
| ) | |||
| func Test_SendMiniSubscribeMessage(t *testing.T) { | |||
| db := "gkxy_tetele_net" | |||
| site_id := "1101832" | |||
| appid := "wx7b72dc719ad1f6d3" | |||
| secret := "b8ae6d64605a963056ff067cceffefd2" | |||
| touser := "osxVD5S0PAh82gyIXSiXCJzM_k6s" | |||
| temp_id := "0Qbw6nuzj3X4kvOqGbGgD-dlu06NF6u9_ZYIiw0TY4Y" | |||
| page := "pages/order/order" | |||
| miniprogram_state := "" | |||
| lang := "" | |||
| data := map[string]map[string]string{ | |||
| "character_string1": map[string]string{"value": "961617783456"}, | |||
| "phrase2": map[string]string{"value": "配送中"}, | |||
| "thing3": map[string]string{"value": "小火锅"}, | |||
| "thing4": map[string]string{"value": "香洲区测试用"}, | |||
| "thing5": map[string]string{"value": "下单备注"}, | |||
| } | |||
| // data_json, _ := json.Marshal(data) | |||
| ret, err := SendMiniSubscribeMessage(db, site_id, appid, secret, touser, temp_id, page, miniprogram_state, lang, data, "49.232.85.91:17969") | |||
| t.Log(ret, err) | |||
| } | |||
| @ -0,0 +1,35 @@ | |||
| package weixinrpc | |||
| import ( | |||
| "testing" | |||
| ) | |||
| func Test_SendUniformMessage(t *testing.T) { | |||
| db := "gkxy_tetele_net" | |||
| site_id := "1111" | |||
| appid := "wx5ef4ad840cb3d269" | |||
| secret := "a937a3f5ac918ebba171deefe2c2ab60" | |||
| touser := "ox7nK5OQNuAfNAeIWVE8CsVL6D94" //"oDTib5KC5uX5rVivTnbK-sFkrC2Q" // | |||
| mp_appid := "wx5ef4ad840cb3d269" | |||
| temp_id := "VDpSj4VVJTH8-wVDp2t3izAuXXl79JYb0l6lezN4kig" | |||
| url := "" | |||
| mini_program := map[string]string{ | |||
| "appid": "wx5ef4ad840cb3d269", | |||
| "pagepath": "pages/order/index", | |||
| } | |||
| data := map[string]map[string]string{ | |||
| "first": map[string]string{"value": "商城小程序"}, | |||
| "keyword1": map[string]string{"value": "961617783456"}, | |||
| "keyword2": map[string]string{"value": "测试商家"}, | |||
| "keyword3": map[string]string{"value": "顾曾"}, | |||
| "keyword4": map[string]string{"value": "18607565510"}, | |||
| "keyword5": map[string]string{"value": "香洲区测试用"}, | |||
| "remark": map[string]string{"value": "下单备注"}, | |||
| } | |||
| // data_json, _ := json.Marshal(data) | |||
| //, "49.232.85.91:17969" | |||
| ret, err := SendUniformMessage(db, site_id, appid, secret, touser, mp_appid, temp_id, url, mini_program, data) | |||
| t.Log(ret, err) | |||
| } | |||