28 Commits

Author SHA1 Message Date
  lijianbin e845674f4b update 2 years ago
  lijianbin c0ce0771ac 增加site_id参数 2 years ago
  guzeng 560548b22c 微信支付退款client 3 years ago
  guzeng 10f3760acb 增加data处理方法 3 years ago
  guzeng 7aadadbae3 增加支付退款 3 years ago
  listen bd48d1cc30 加入图片和文字检测 3 years ago
  guzeng f94ec81d83 更新pb.go 3 years ago
  listen 131fea8347 加入检测方法 3 years ago
  listen 30e4e1d689 更改小程序码参数 3 years ago
  listen eb61287f73 修复bug 3 years ago
  listen 716c994c1f 添加app获取openid方法 3 years ago
  guzeng 772d930427 更新pb.go 3 years ago
  listen 1235e63a18 新增app获取openid方法 3 years ago
  listen 1d365c1ee6 新增获取小程序码方法 3 years ago
  listen c800f05775 删除文件 3 years ago
  listen ffa8f898a8 测试rpc 3 years ago
  guzeng 5810bc14fe 更新pb.go 3 years ago
  listen 9f96115ccd 提交 3 years ago
  guzeng 3691ba30ea 更新pb.go 3 years ago
  listen 385eecdb31 新增方法 3 years ago
  listen ea8de4ed43 修复错误 3 years ago
  listen e68c361408 更新结构 3 years ago
  listen 7ecafe3fea 添加获取公众号用户信息的方法 3 years ago
  listen e2def3228e 加入公众号获取openid方法 3 years ago
  guzeng 92944dc02d 增加获取公众号OPENID与获取公众号用户信息方法 3 years ago
  listen 6e5ee948fe 新增方法 3 years ago
  listen 0d399213c3 更新获取openid方法的结构体 3 years ago
  guzeng 3310a1fff7 增加调试解析openid 3 years ago
16 changed files with 802 additions and 20 deletions
Unified View
  1. +71
    -0
      app_openid.client.go
  2. +48
    -4
      common.go
  3. +106
    -0
      data.go
  4. +5
    -2
      go.mod
  5. +8
    -4
      go.sum
  6. +62
    -0
      miniapp_qrcode.client.go
  7. +33
    -0
      miniapp_qrcode.client_test.go
  8. +80
    -0
      mp_open_id.client.go
  9. +77
    -0
      mp_userinfo.client.go
  10. +63
    -0
      pay.client.go
  11. +76
    -0
      pay.client_test.go
  12. +97
    -0
      security_check.go
  13. +31
    -0
      security_check_test.go
  14. +10
    -10
      send_uniform_message.client_test.go
  15. +28
    -0
      weixin.pb.go
  16. +7
    -0
      weixin.proto

+ 71
- 0
app_openid.client.go View File

@ -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
}

+ 48
- 4
common.go View File

@ -1,5 +1,9 @@
package weixinrpc package weixinrpc
import (
"git.tetele.net/yueheng/conf"
)
const DES_KEY = "wxserrpc" const DES_KEY = "wxserrpc"
type WxApiRes struct { type WxApiRes struct {
@ -59,18 +63,58 @@ type MiniAppOpenidReq struct {
* 获取小程序openid返回参数 * 获取小程序openid返回参数
*/ */
type MiniAppOpenidRes struct { type MiniAppOpenidRes struct {
Openid string
SessionKey string
Unionid int
Openid string `json:"openid"`
SessionKey interface{} `json:"session_key"`
Unionid interface{} `json:"unionid"`
NickName string `json:"nick_name"`
AvatarUrl string `json:"avatar_url"`
WxApiRes WxApiRes
} }
/**
* 获取公众号openid返回参数
*/
type MpOpenidRes struct {
AccessToken string `json:"access_token"`
ExpiresIn string `json:"expires_in"`
RefreshToken string `json:"refresh_token"`
Openid string `json:"openid"`
Scope string `json:"scope"`
}
/**
* 获取公众号用户信息请求参数
*/
type MpUserInfoReq struct {
AccessToken string
Openid string
}
/**
* 根据用户access_token换取用户信息返回参数
*/
type MpUserInfoRes struct {
Openid string
Nickname string
Sex string
Province string
City string
Country string
Headimgurl string
Privilege string
Unionid string
}
func rpc_server_conn(url ...string) (*WeixinRpcServiceClient, error) { func rpc_server_conn(url ...string) (*WeixinRpcServiceClient, error) {
var wx_rpc_url string = "127.0.0.1:7969"
var wx_rpc_url string
if len(url) > 0 && url[0] != "" { if len(url) > 0 && url[0] != "" {
wx_rpc_url = url[0] wx_rpc_url = url[0]
} else {
wx_rpc_url = "127.0.0.1:" + conf.WEIXIN_RPC_PORT
} }
conn, _, err := DialWeixinRpcService("tcp", wx_rpc_url) conn, _, err := DialWeixinRpcService("tcp", wx_rpc_url)
if err != nil { if err != nil {
return nil, err return nil, err


+ 106
- 0
data.go View File

@ -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
}

+ 5
- 2
go.mod View File

@ -3,8 +3,11 @@ module git.tetele.net/tgo/weixinrpc
go 1.14 go 1.14
require ( require (
git.tetele.net/tgo/crypter v0.2.2 // indirect
github.com/chai2010/protorpc v1.0.0 // indirect
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/crypto v0.0.0-20210322153248-0c34fe9e7dc2 // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
) )

+ 8
- 4
go.sum View File

@ -1,11 +1,15 @@
git.tetele.net/tgo/crypter v0.2.2 h1:YMQJh2Gj5Po4ZfelJUmXBKi01UbmtiSy3bmqRfnYQMo= 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/crypter v0.2.2/go.mod h1:vfvRLZA8+lHNgNXneOcgvVhDyuv25ZRb+C6xHOmXNx0=
github.com/chai2010/protorpc v1.0.0 h1:aJ45G9sl1utSKo35EqnBSTs5jqTpdJDJAuZMMYPAtFo=
github.com/chai2010/protorpc v1.0.0/go.mod h1:woR3WwjaQDqFjlzdVsFEKiK5Ur12QL8mYxVPjfr5z54=
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 h1:lsek0oXi8iFE9L+EXARyHIjU5rlWIhhTkjDz3vHhWWQ=
github.com/golang/protobuf v1.0.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.0.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/snappy v0.0.0-20170215233205-553a64147049 h1:K9KHZbXKpGydfDN0aZrsoHpLJlZsBrGMFWbgLDGnPZk=
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
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 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= 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/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=


+ 62
- 0
miniapp_qrcode.client.go View File

@ -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
}

+ 33
- 0
miniapp_qrcode.client_test.go View File

@ -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)
}

+ 80
- 0
mp_open_id.client.go View File

@ -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
}

+ 77
- 0
mp_userinfo.client.go View File

@ -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
}

+ 63
- 0
pay.client.go View File

@ -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
}

+ 76
- 0
pay.client_test.go View File

@ -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)
}

+ 97
- 0
security_check.go View File

@ -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
}

+ 31
- 0
security_check_test.go View File

@ -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)
}

+ 10
- 10
send_uniform_message.client_test.go View File

@ -7,19 +7,19 @@ import (
func Test_SendUniformMessage(t *testing.T) { func Test_SendUniformMessage(t *testing.T) {
db := "gkxy_tetele_net" db := "gkxy_tetele_net"
site_id := "1101832"
appid := "wx7b72dc719ad1f6d3"
secret := "b8ae6d64605a963056ff067cceffefd2"
touser := "oDTib5GULMfLSGZcMz7vB2xToxG4" //"oDTib5KC5uX5rVivTnbK-sFkrC2Q" //
mp_appid := "wx056995d61ca222f5"
temp_id := "6xgj_65KivigMvwdJgiveR4wLXJLDpzsT2-hShczLmU"
site_id := "1111"
appid := "wx5ef4ad840cb3d269"
secret := "a937a3f5ac918ebba171deefe2c2ab60"
touser := "ox7nK5OQNuAfNAeIWVE8CsVL6D94" //"oDTib5KC5uX5rVivTnbK-sFkrC2Q" //
mp_appid := "wx5ef4ad840cb3d269"
temp_id := "VDpSj4VVJTH8-wVDp2t3izAuXXl79JYb0l6lezN4kig"
url := "" url := ""
mini_program := map[string]string{ mini_program := map[string]string{
"appid": "wx7b72dc719ad1f6d3",
"appid": "wx5ef4ad840cb3d269",
"pagepath": "pages/order/index", "pagepath": "pages/order/index",
} }
data := map[string]map[string]string{ data := map[string]map[string]string{
"first": map[string]string{"value": "AI广科商城小程序"},
"first": map[string]string{"value": "商城小程序"},
"keyword1": map[string]string{"value": "961617783456"}, "keyword1": map[string]string{"value": "961617783456"},
"keyword2": map[string]string{"value": "测试商家"}, "keyword2": map[string]string{"value": "测试商家"},
"keyword3": map[string]string{"value": "顾曾"}, "keyword3": map[string]string{"value": "顾曾"},
@ -29,7 +29,7 @@ func Test_SendUniformMessage(t *testing.T) {
} }
// data_json, _ := json.Marshal(data) // data_json, _ := json.Marshal(data)
ret, err := SendUniformMessage(db, site_id, appid, secret, touser, mp_appid, temp_id, url, mini_program, data, "49.232.85.91:17969")
//, "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) t.Log(ret, err)
} }

+ 28
- 0
weixin.pb.go View File

@ -102,6 +102,13 @@ type WeixinRpcService interface {
SendMiniappSubscribeMessage(in *Request, out *Response) error SendMiniappSubscribeMessage(in *Request, out *Response) error
SendUniformMessage(in *Request, out *Response) error SendUniformMessage(in *Request, out *Response) error
GetMiniAppOpenid(in *Request, out *Response) error GetMiniAppOpenid(in *Request, out *Response) error
GetMpOpenid(in *Request, out *Response) error
GetAppOpenid(in *Request, out *Response) error
GetMpUserInfo(in *Request, out *Response) error
GetMiniappQrcode(in *Request, out *Response) error
ImgSecCheck(in *Request, out *Response) error
MsgSecCheck(in *Request, out *Response) error
PayRefund(in *Request, out *Response) error
} }
// AcceptWeixinRpcServiceClient accepts connections on the listener and serves requests // AcceptWeixinRpcServiceClient accepts connections on the listener and serves requests
@ -185,6 +192,27 @@ func (c *WeixinRpcServiceClient) SendUniformMessage(in *Request, out *Response)
func (c *WeixinRpcServiceClient) GetMiniAppOpenid(in *Request, out *Response) error { func (c *WeixinRpcServiceClient) GetMiniAppOpenid(in *Request, out *Response) error {
return c.Call("WeixinRpcService.GetMiniAppOpenid", in, out) return c.Call("WeixinRpcService.GetMiniAppOpenid", in, out)
} }
func (c *WeixinRpcServiceClient) GetMpOpenid(in *Request, out *Response) error {
return c.Call("WeixinRpcService.GetMpOpenid", in, out)
}
func (c *WeixinRpcServiceClient) GetAppOpenid(in *Request, out *Response) error {
return c.Call("WeixinRpcService.GetAppOpenid", in, out)
}
func (c *WeixinRpcServiceClient) GetMpUserInfo(in *Request, out *Response) error {
return c.Call("WeixinRpcService.GetMpUserInfo", in, out)
}
func (c *WeixinRpcServiceClient) GetMiniappQrcode(in *Request, out *Response) error {
return c.Call("WeixinRpcService.GetMiniappQrcode", in, out)
}
func (c *WeixinRpcServiceClient) ImgSecCheck(in *Request, out *Response) error {
return c.Call("WeixinRpcService.ImgSecCheck", in, out)
}
func (c *WeixinRpcServiceClient) MsgSecCheck(in *Request, out *Response) error {
return c.Call("WeixinRpcService.MsgSecCheck", in, out)
}
func (c *WeixinRpcServiceClient) PayRefund(in *Request, out *Response) error {
return c.Call("WeixinRpcService.PayRefund", in, out)
}
// DialWeixinRpcService connects to an WeixinRpcService at the specified network address. // DialWeixinRpcService connects to an WeixinRpcService at the specified network address.
func DialWeixinRpcService(network, addr string) (*WeixinRpcServiceClient, *rpc.Client, error) { func DialWeixinRpcService(network, addr string) (*WeixinRpcServiceClient, *rpc.Client, error) {


+ 7
- 0
weixin.proto View File

@ -22,4 +22,11 @@ service WeixinRpcService {
rpc sendMiniappSubscribeMessage (Request) returns (Response); // rpc sendMiniappSubscribeMessage (Request) returns (Response); //
rpc sendUniformMessage(Request) returns (Response); // rpc sendUniformMessage(Request) returns (Response); //
rpc getMiniAppOpenid(Request) returns (Response); // openid rpc getMiniAppOpenid(Request) returns (Response); // openid
rpc getMpOpenid(Request) returns (Response); // openid
rpc getAppOpenid(Request) returns (Response); // app的openid
rpc getMpUserInfo(Request) returns (Response); //
rpc getMiniappQrcode(Request) returns (Response); //
rpc imgSecCheck(Request) returns (Response); //
rpc msgSecCheck(Request) returns (Response); //
rpc payRefund(Request) returns (Response); //v3支付退款
} }

Loading…
Cancel
Save