go-pay / gopay

微信、支付宝、通联支付、拉卡拉、PayPal、Apple 的Go版本SDK。【极简、易用的聚合支付SDK】
https://github.com/go-pay/gopay
Apache License 2.0
4.26k stars 734 forks source link

支付宝异步验签失败 #113

Closed stong1994 closed 3 years ago

stong1994 commented 3 years ago

最近开始对接支付宝,但是调用异步验签失败。 测试代码如下

func TestVerify(t *testing.T) {
    body := `gmt_create=2021-03-10+15%3A03%3A12&charset=utf-8&seller_email=pay%40eebochina.com&subject=%E5%B0%8F%E7%B1%B3%E5%8A%A0%E6%AD%A5%E6%9E%AA-%E5%8A%A0%E5%BC%BA%E7%89%88&sign=JxeM0q56G3PrfGp6yWkgQAhQeZDbE2QWvwDULB9Xp%2BNjYC2nTDVc6JTElYz%2BBF6FIAYbHcZQiMErt8c4dHaFIy9oFttPlvxLn8%2BTQewgFKEzZxEITvKKJ9WHWL8BluW7epdF8qMG8i3GbNiBniUzSuBkeWp4Po7Q86H9QSdSQmS48RXG%2BgkXPQwv6XFYAO%2FgBBilCZO3BrM7zNUR0dBsbzFUMKanNd3NIlj2RBoYriz7WLlUc0WdMHGHHKaTqZxT61PGObDbJ0F1yE5zQE5ABE9jAp94nzPI42Z6u3dlRR1V2iIe022GHIkohZiEZJr1eTk53GdCHCuoRshfSU2%2Fcw%3D%3D&buyer_id=2088112271226255&invoice_amount=0.01&notify_id=2021031000222150318026251411867346&fund_bill_list=%5B%7B%22amount%22%3A%220.01%22%2C%22fundChannel%22%3A%22PCREDIT%22%7D%5D&notify_type=trade_status_sync&trade_status=TRADE_SUCCESS&receipt_amount=0.01&app_id=2016070601587476&buyer_pay_amount=0.01&sign_type=RSA2&seller_id=2088421320773124&gmt_payment=2021-03-10+15%3A03%3A17&notify_time=2021-03-10+15%3A03%3A18&version=1.0&out_trade_no=7674c960ff0544b2af72ffc79fa7498e&total_amount=0.01&trade_no=2021031022001426251450957042&auth_app_id=2016070601587476&buyer_logon_id=177****4392&point_amount=0.00`

    esBody, err := url.QueryUnescape(body)
    if err != nil {
        t.Fatal(err)
    }
    m := make(map[string]interface{})
    sps := strings.Split(esBody, "&")
    for _, v := range sps {
        s2 := strings.Split(v, "=")
        m[s2[0]] = s2[1]
    }
    ok, err := alipay.VerifySignWithCert("C:\\alipay\\cert\\alipayCertPublicKey_RSA2.crt", m)
    if err != nil {
        t.Fatal(err)
    }
    fmt.Println(ok)
}

报错内容如下 crypto/rsa: verification error 这个问题排查半天也没解决。。。希望您能帮忙看下,谢谢~

iGoogle-ink commented 3 years ago

此处必须用 gopay.BodyMap 吧,你换成 bodymap 试试吧 image

stong1994 commented 3 years ago

换成bodyMap后还是不行,

func TestVerify(t *testing.T) {
    body := `gmt_create=2021-03-10+15%3A03%3A12&charset=utf-8&seller_email=pay%40eebochina.com&subject=%E5%B0%8F%E7%B1%B3%E5%8A%A0%E6%AD%A5%E6%9E%AA-%E5%8A%A0%E5%BC%BA%E7%89%88&sign=JxeM0q56G3PrfGp6yWkgQAhQeZDbE2QWvwDULB9Xp%2BNjYC2nTDVc6JTElYz%2BBF6FIAYbHcZQiMErt8c4dHaFIy9oFttPlvxLn8%2BTQewgFKEzZxEITvKKJ9WHWL8BluW7epdF8qMG8i3GbNiBniUzSuBkeWp4Po7Q86H9QSdSQmS48RXG%2BgkXPQwv6XFYAO%2FgBBilCZO3BrM7zNUR0dBsbzFUMKanNd3NIlj2RBoYriz7WLlUc0WdMHGHHKaTqZxT61PGObDbJ0F1yE5zQE5ABE9jAp94nzPI42Z6u3dlRR1V2iIe022GHIkohZiEZJr1eTk53GdCHCuoRshfSU2%2Fcw%3D%3D&buyer_id=2088112271226255&invoice_amount=0.01&notify_id=2021031000222150318026251411867346&fund_bill_list=%5B%7B%22amount%22%3A%220.01%22%2C%22fundChannel%22%3A%22PCREDIT%22%7D%5D&notify_type=trade_status_sync&trade_status=TRADE_SUCCESS&receipt_amount=0.01&app_id=2016070601587476&buyer_pay_amount=0.01&sign_type=RSA2&seller_id=2088421320773124&gmt_payment=2021-03-10+15%3A03%3A17&notify_time=2021-03-10+15%3A03%3A18&version=1.0&out_trade_no=7674c960ff0544b2af72ffc79fa7498e&total_amount=0.01&trade_no=2021031022001426251450957042&auth_app_id=2016070601587476&buyer_logon_id=177****4392&point_amount=0.00`

    esBody, err := url.QueryUnescape(body)
    if err != nil {
        t.Fatal(err)
    }
    m := make(map[string]interface{})
    sps := strings.Split(esBody, "&")
    for _, v := range sps {
        s2 := strings.Split(v, "=")
        m[s2[0]] = s2[1]
    }
    bodyMap := gopay.BodyMap(m)
    ok, err := alipay.VerifySignWithCert("C:\\internal\\alipay\\cert\\alipayCertPublicKey_RSA2.crt", bodyMap)
    if err != nil {
        t.Fatal(err)
    }
    fmt.Println(ok)
}

我以前没有对接过支付宝,不知道在验签的时候需要注意什么?我这里根据支付宝回调的数据组装的bodyMap有问题吗?谢谢~

iGoogle-ink commented 3 years ago

推荐你用封装好的方法测试,通过接口直接解析出请求数据,然后通过方法直接验签 image

stong1994 commented 3 years ago

问题解决了。 原因是上边获取到的内容是用ngx.req.get_body_data()获取的,但是这个数据是不对的(sign值后边缺失等号)。 改成ngx.req.get_post_args()后通过了校验。

dreamlu commented 3 years ago

用gin框架的,不要用alipay.ParseNotifyToBodyMap()的方式 用原始方案:

_ = u.Request.ParseForm()
values := u.Request.Form
notifyReq, err := alipay.ParseNotifyByURLValues(values)