| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
e845674f4b | update | 4 years ago |
|
|
c0ce0771ac | 增加site_id参数 | 4 years ago |
|
|
560548b22c | 微信支付退款client | 4 years ago |
|
|
10f3760acb | 增加data处理方法 | 4 years ago |
|
|
7aadadbae3 | 增加支付退款 | 4 years ago |
|
|
bd48d1cc30 | 加入图片和文字检测 | 4 years ago |
|
|
f94ec81d83 | 更新pb.go | 4 years ago |
|
|
131fea8347 | 加入检测方法 | 4 years ago |
|
|
30e4e1d689 | 更改小程序码参数 | 4 years ago |
|
|
eb61287f73 | 修复bug | 4 years ago |
|
|
716c994c1f | 添加app获取openid方法 | 4 years ago |
|
|
772d930427 | 更新pb.go | 4 years ago |
|
|
1235e63a18 | 新增app获取openid方法 | 4 years ago |
|
|
1d365c1ee6 | 新增获取小程序码方法 | 4 years ago |
| @ -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,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,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) | |||||
| } | |||||