支付宝签名验证

支付宝服务器向商家服务器发送音讯签名验证

官网文档

  • 在对接支付宝领取时无论何种领取,领取实现后支付宝都会有一个异步的回调告诉,此时咱们就须要解决其中的音讯来更新订单状态。
  • 因为接口是对外开放的谁都能申请,所以须要留神接口平安,支付宝给咱们发送的音讯会带有签名,避免音讯被篡改

    1. 当咱们收到音讯是首先就须要对内容进行签名验证

支付宝官网并没有提供Go的sdk
// CheckSign 校验签名//  @Description: 校验异步告诉签名//  @param req_body 申请body a=1&b=2//  @param public_key 支付宝公钥//  @return bool 后果//  @return errorfunc CheckSign(req_body string, public_key string) (bool, error) {    var sign string    input := map[string]string{}    //解析查问字符串    val, _ := url.ParseQuery(req_body)    for k, v := range val {        if k == "sign" || k == "sign_type" {            if k == "sign" {                sign = v[0]            }            continue        }        //URL解码        value, _ := url.QueryUnescape(v[0])        input[k] = value    }    return checkSign(input, sign, utils.GetPublicKey(public_key))}// 自定义排序type kv struct {    Key   string    Value string}type SortKv []kvfunc (s SortKv) Len() int {    return len(s)}func (s SortKv) Less(i, j int) bool {    return s[i].Key < s[j].Key}func (s SortKv) Swap(i, j int) {    s[i], s[j] = s[j], s[i]}// 解决数据验证签名func checkSign(input map[string]string, sign string, public_key string) (bool, error) {    var ListKv SortKv    for key, val := range input {        ListKv = append(ListKv, kv{            key, val,        })    }    sort.Sort(ListKv)    var sign_str string    for _, v := range ListKv {        sign_str += v.Key + "=" + v.Value + "&"    }    sign_str = strings.TrimRight(sign_str, "&")    fmt.Println("---------------------------------")    fmt.Println(fmt.Sprintf("签名字符串:%s", sign_str))    fmt.Println(fmt.Sprintf("sign:%s", sign))    fmt.Println(fmt.Sprintf("public_key:%s", public_key))    return utils.Rsa2PubCheckSign(sign_str, sign, public_key, crypto.SHA256)}// rsa2公钥签名验证func Rsa2PubCheckSign(signContent, sign, publicKey string, hash crypto.Hash) (res bool, err error) {    hashed := sha256.Sum256([]byte(signContent))    pubKey, err := ParsePublicKey(publicKey)    if err != nil {        return false, err    }    sig, _ := base64.StdEncoding.DecodeString(sign)    err = rsa.VerifyPKCS1v15(pubKey, hash, hashed[:], sig)    if err != nil {        return false, err    }    return true, nil}// 组装公钥func GetPublicKey(pubkey string) string {    PREFIX := "-----BEGIN PUBLIC KEY-----"    SUFFIX := "-----END PUBLIC KEY-----"    return PREFIX + "\n" + pubkey + "\n" + SUFFIX}// ParsePublicKey 解析公钥func ParsePublicKey(publicKey string) (*rsa.PublicKey, error) {    block, _ := pem.Decode([]byte(publicKey))    if block == nil {        return nil, errors.New("公钥信息谬误!")    }    pubKey, err := x509.ParsePKIXPublicKey(block.Bytes)    if err != nil {        return nil, err    }    return pubKey.(*rsa.PublicKey), nil}

2. 签名能够避免音讯被篡改然而不是阻止重放攻打,所以咱们还须要验证内容的合法性

以下是官网文档原文

1. 商家须要验证该告诉数据中的 out_trade_no 是否为商家零碎中创立的订单号。2. 判断 total_amount 是否的确为该订单的理论金额(即商家订单创立时的金额)。3. 校验告诉中的 seller_id(或者 seller_email ) 是否为 out_trade_no 这笔单据的对应的操作方(有的时候,一个商家可能有多个seller_id/seller_email)。4. 验证 app_id 是否为该商家自身。