-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
求助:SDK签名验证算法Bug #2
Comments
这部分工作还没有完成吗? 我这边实现过支付宝api接口的response的签名验证。 |
@xluohome 大部分接口签名验证是可以的,但是碰到多维结构的,就无法验证了。就像上面的结构, JsApiResponse 包含一个 JsApi ,然后就验证失败了。 |
可否贴出 response 的 json 字符串 ? |
提供 “通信密钥"、 "PayJS的商户号”之类必要的东东我来帮你调吧,保证能解! |
@xluohome |
生成这个 sign 的key 多少。
------------------
PHPOSS Team!
…------------------ 原始邮件 ------------------
发件人: "卿务国"<notifications@github.com>;
发送时间: 2019年6月26日(星期三) 上午10:40
收件人: "qingwg/payjs"<payjs@noreply.github.com>;
抄送: ""<phposs@qq.com>; "Mention"<mention@noreply.github.com>;
主题: Re: [qingwg/payjs] 求助:SDK签名验证算法Bug (#2)
@xluohome
{"return_code":1,"return_msg":"SUCCESS","user":{"subscribe":1,"openid":"o7LFAwXrAJip_0GEhcHWKqM2LPxw","nickname":"卿务国","sex":1,"city":"长沙","country":"中国","province":"湖南","language":"zh_CN","headimgurl":"http://thirdwx.qlogo .cn/mmopen/Z7gAdqBjbbFMvGpwQvsVSVdpxjalBfg6V9cm2svg7yUtFgQjSVOsnYFSBG7401bZJPNoc9ZNfNEC0LgtBtQO8DaCtcu1icOnL/132","subscribe_time":1544522310,"remark":"","groupid":0,"tagid_list":[],"subscribe_scene":"ADD_SCENE_SEARCH","qr_scene":0, "qr_scene_str":""},"sign":"3C0427D9D501D856F29274B9EF11F995"}
不好意思,这么晚回复。
上面就是用户获取详情接口的 response 的 json 字符串
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
|
@xluohome 我发你这个邮箱了:phposs@qq.com |
校验响应得到的bytes数据可以试着调用动态语言吗, 我发现golang很难完成这个工作 |
你可以用go调用python, 我刚才实现了一下, 应该能用 import json
import hashlib
import importlib
import sys
json_str = '{"name":"markity","tags":["golang","python"],"detail":{"age":16,"phone":"11011011011", "birthday":"88888888"},"sign":"3123123"}'
mchKey = "demoMchKey"
try:
json_obj = json.loads(json_str)
except:
sys.exit(1)
keys = list(json_obj.keys())
# 对于某些特殊情况, 如重复退款, 即使return_code为1也无sign
if "sign" not in keys:
print("true")
sys.exit(0)
origin_sign = json_obj["sign"]
keys.remove("sign")
keys.sort()
def walk(perfix, l, keys, struct):
# walk 迭代遍历, 将key=val字符串追加入l列表中
for k in keys:
v = struct[k]
if v == None:
continue
if type(v) == dict:
_keys = list(v.keys())
_keys.sort()
walk(k, kvList, _keys, v)
continue
if type(v) == list:
walk(k, kvList, range(len(v)), v)
continue
if perfix == "":
kvList.append("{}={}".format(k, v))
if perfix != "":
kvList.append("{}[{}]={}".format(perfix, k, v))
kvList = []
walk("", kvList, keys, json_obj)
kvChain = '&'.join(kvList)
print(kvChain)
realSign = hashlib.md5(kvChain.encode("utf-8")).hexdigest().upper()
print(realSign) 输出
|
刚才用go重写了一遍, 你看看 package main
import (
"crypto/md5"
"encoding/json"
"fmt"
"sort"
"strings"
)
var jsonStr = `
{
"name":"Markity",
"age":16,
"interests":["python","golang"],
"friends":[
{"name":"Jack","age":17,"interests":["lua"]},
{"name":"Mary","age":15,"interests":["java"]}
],
"compary":
{
"name":"Microsoft",
"workders":[
{"name":"Peter","age":22},
{"name":"Eric","age":23}
]
},
"sign":"XXX"
}
`
var mchKey = "xxxxx"
func main() {
jsonObj := make(map[string]interface{})
json.Unmarshal([]byte(jsonStr), &jsonObj)
_, ok := jsonObj["sign"]
// 某些特殊情况如重复退款, 即使return_code为1, 也没有sign, 这时直接return true
if !ok {
fmt.Println("true")
return
}
originSign := jsonObj["sign"].(string)
delete(jsonObj, "sign")
// 将key=val追加入kvList中
kvList := make([]string, 0)
var walkMap func(string, interface{}, interface{}) = nil
walkMap = func(perfix string, obj interface{}, ks interface{}) {
// obj为[]interface{}或者map[string]interface{}类型, ks为[]string或者[]int类型
switch keys := ks.(type) {
case []string:
// 当ks为[]string类型时, obj为map[string]interface{}类型
object := obj.(map[string]interface{})
for _, key := range keys {
v := object[key]
// 根据签名算法, 值为null的不计入
if v == nil {
continue
}
switch value := v.(type) {
// 若v为复合类型, 进入继续遍历
case []interface{}:
_perfix := ""
if perfix == "" {
_perfix = key
} else {
_perfix = fmt.Sprintf("%v[%v]", perfix, key)
}
_keys := make([]int, len(value))
for i := 0; i < len(value); i++ {
_keys = append(_keys, i)
}
walkMap(_perfix, value, _keys)
continue
case map[string]interface{}:
_perfix := ""
if perfix == "" {
_perfix = key
} else {
_perfix = fmt.Sprintf("%v[%v]", perfix, key)
}
_keys := make([]string, 0)
for __key, _ := range value {
_keys = append(_keys, __key)
}
sort.Strings(_keys)
walkMap(_perfix, value, _keys)
continue
}
if perfix == "" {
kvList = append(kvList, fmt.Sprintf("%v=%v", key, v))
} else {
kvList = append(kvList, fmt.Sprintf("%v[%v]=%v", perfix, key, v))
}
}
case []int:
// 当ks为[]int, obj为[]interface{}
object := obj.([]interface{})
for key := 0; key < len(object); key++ {
v := object[key]
if v == nil {
continue
}
switch value := v.(type) {
// 若v为复合类型, 进入继续遍历
case []interface{}:
_perfix := fmt.Sprintf("%v[%v]", perfix, key)
_keys := make([]int, len(value))
for i := 0; i < len(value); i++ {
_keys = append(_keys, i)
}
walkMap(_perfix, value, _keys)
continue
case map[string]interface{}:
_perfix := fmt.Sprintf("%v[%v]", perfix, key)
_keys := make([]string, 0)
for __key, _ := range value {
_keys = append(_keys, __key)
}
walkMap(_perfix, value, _keys)
continue
}
}
}
}
keys := make([]string, 0)
for key, _ := range jsonObj {
keys = append(keys, key)
}
sort.Strings(keys)
walkMap("", jsonObj, keys)
kvList = append(kvList, "key="+mchKey)
kvChain := strings.Join(kvList, "&")
fmt.Println(kvChain)
realSign := fmt.Sprintf("%x", md5.Sum([]byte(kvChain)))
if realSign == originSign {
fmt.Println("true")
} else {
fmt.Println("false")
}
} 输出
|
求助:此SDK签名验证算法与微信相同。但是如果碰到[]string等,或多维结构体,例如JSAPI支付接口的Response,则无法正确签名验证。该如何处理呢?
目前有存在多为结构签名验证的地方都取消了验证判断
分别是:
JSAPI支付接口
获取用户详情
异步通知
签名验证代码则如下:
签名验证代码
代码有点乱,一直在调试。这段代码无法正确验证多维结构,例如无法验证下面结构:
官方给出的回复为:
The text was updated successfully, but these errors were encountered: