golang 支付宝SHA1withRSA加密

u012210379 · · 7648 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

SHA1大家用的挺多,RSA不多但用的也有,但像支付宝这样要求 SHA1 + RSA的恐怕就没几个了,写起来实在痛苦。而且一搜一片,却没几个能跑起来的。

刚才有个人在QQ上加我,问之前在支付宝集成的帖子里的SHA1withRSA是咋解决的。说实话,不是专门研究加密的,鬼知道报的错是什么玩意,比如这个:

signature, err := rsa.SignPKCS1v15(rand.Reader, this.privateKey,
crypto.SHA1, hashed) //ParsePKCS8PrivateKey err asn1: structure error: tags don't match (16 vs {class:0 tag:2 length:129 isCompound:false}) {optional:false explicit:false application:false defaultValue:<nil> tag:<nil> stringType:0 timeType:0 set:false omitEmpty:false} AlgorithmIdentifier

反正我是真心看的莫名其妙,不过不妨碍我们解决它,由于调用的是系统加密,所以基本可以肯定是套路问题。以下是在beego中集成支付宝的代码,大家可以参考下:

package controllers

import (
    "github.com/astaxie/beego"
    "fmt"
    "net/url"
    "time"
    "sort"
    "encoding/pem"
    "crypto/x509"
    "mlshop/shopUtils/AliSignUtil"
    "net/http"
    "io/ioutil"
    "mlshop/shopUtils/RandomStrUtil"
    "strings"
)

/**
    ali第三方授权或用户信息授权后回调地址。授权链接中配置的redirect_uri的值必须与此值保持一致
*/

type AliAnswerController struct {
    beego.Controller
}

func (c *AliAnswerController) Get() {

    c.EnableRender = false
    fmt.Println("AliAnswerController=============get")

    //接收manager登录支付宝付款授权页面后 支付宝传递过来的回调信息
    auth_code, state := c.GetString("auth_code", "-1"), c.GetString("state")
    if state == zfbRandomState {

        //根据 auth_code 获取 token
        getAliTokenByAuthCode(auth_code)

        fmt.Println("============== 开始批量付款 =============")

        service := "batch_trans_notify"
        partner := "20880000000000"
        _input_charset := "UTF-8"
        sign_type := "RSA"

        notify_url := "http://www.xxxx.com/xxx"
        account_name := "130000000"//todo 付款方的支付宝账户名
        detail_data := "111110^xxxx^name^0.01^beizhu0"//todo 付款的详细数据 格式为:流水号1^收款方账号1^收款账号姓名1^付款金额1^备注说明1|流水号2^收款方账号2^收款账号姓名2^付款金额2^备注说明2。
        batch_no := RandomStrUtil.GetRandomString(32)
        batch_num := "1"//付款总笔数
        batch_fee := "0.01"//付款总金额
        email := "xxxx@sina.com"//付款方的支付宝账号,支持邮箱和手机号2种格式
        pay_date := time.Now().Format(TIMELAYOUT3)//YYYYMMDD

        m := make(map[string]interface{})
        m["service"] = service
        m["partner"] = partner
        m["_input_charset"] = _input_charset
        m["sign_type"] = sign_type
        m["notify_url"] = notify_url
        m["account_name"] = account_name
        m["detail_data"] = detail_data
        m["batch_no"] = batch_no
        m["batch_num"] = batch_num
        m["batch_fee"] = batch_fee
        m["email"] = email
        m["pay_date"] = pay_date

        sign := aliPaySign(m)//签名

        requestLine := strings.Join([]string{"https://mapi.alipay.com/gateway.do",
            "?service=" + service,
            "&partner=" + partner,
            "&_input_charset=" + _input_charset,
            "&notify_url=" + url.QueryEscape(notify_url),
            "&sign_type=" + sign_type,
            "&sign=" + sign,
            "&email=" + email,
            "&pay_date=" + pay_date,
            "&batch_no=" + batch_no,
            "&batch_num=" + batch_num,
            "&account_name=" + url.QueryEscape(account_name),
            "&batch_fee=" + batch_fee,
            "&detail_data=",
            url.QueryEscape(detail_data)}, "")

        c.Redirect(requestLine, 302)
        //data := make(url.Values)
        //data["service"] = []string{service}
        //data["partner"] = []string{partner}
        //data["_input_charset"] = []string{_input_charset}
        //data["sign_type"] = []string{sign_type}
        //data["notify_url"] = []string{notify_url}
        //data["account_name"] = []string{account_name}
        //data["detail_data"] = []string{detail_data}
        //data["batch_no"] = []string{batch_no}
        //data["batch_num"] = []string{batch_num}
        //data["batch_fee"] = []string{batch_fee}
        //data["email"] = []string{email}
        //data["pay_date"] = []string{pay_date}
        //data["sign"] = []string{sign}
        //
        //
        ////把批量付款发送给目标服务器
        //_, err := http.PostForm("https://openapi.alipay.com/gateway.do", data)
        //if err != nil {
        //  fmt.Println("批量付款出现错误",err.Error())
        //  return
        //}else {
        //  fmt.Println("批量付款完毕")
        //}

        fmt.Println("============== 结束批量付款 =============")

    } else {
        fmt.Println("接收到的支付宝回调发现state不一致 ", state, " ", zfbRandomState)
    }

}

func getAliTokenByAuthCode(auth_code string) {

    fmt.Println("接收到的auth_code = ", auth_code)

    app_id := beego.AppConfig.String("ali_appId")
    method := "alipay.system.oauth.token"
    charset := "GBK"
    timestamp := time.Now().Format(TIMELAYOUT)
    version := "1.0"
    grant_type := "authorization_code"
    sign_type := "RSA"
    code := auth_code

    m := make(map[string]interface{})
    m["app_id"] = app_id
    m["method"] = method
    m["charset"] = charset
    m["timestamp"] = timestamp
    m["version"] = version
    m["grant_type"] = grant_type
    m["code"] = code
    m["sign_type"] = sign_type

    //换取 token
    data := make(url.Values)
    data["app_id"] = []string{app_id}
    data["method"] = []string{method}
    data["charset"] = []string{charset}
    data["sign_type"] = []string{sign_type}
    data["timestamp"] = []string{timestamp}
    data["sign"] = []string{aliPaySign(m)}//使用RSA进行签名
    data["version"] = []string{version}
    data["grant_type"] = []string{grant_type}
    data["code"] = []string{code}

    //把post表单发送给目标服务器 获取token
    res, err := http.PostForm("https://openapi.alipay.com/gateway.do", data)
    if err != nil {
        fmt.Println(err.Error())
        return
    }
    defer res.Body.Close()

    bodyBytes, err := ioutil.ReadAll(res.Body)//其中含有 token
    fmt.Println("把post表单发送给目标服务器 获取token 返回的数据---", string(bodyBytes), err)

}

func aliPaySign(mReq map[string]interface{}) string {

    //STEP 1, 对key进行升序排序.
    sorted_keys := make([]string, 0)
    for k, _ := range mReq {
        sorted_keys = append(sorted_keys, k)
    }
    sort.Strings(sorted_keys)

    //STEP2, 对key=value的键值对用&连接起来,略过空值
    var signStrings string
    for i, k := range sorted_keys {
        //fmt.Printf("k=%v, v=%v\n", k, mReq[k])
        value := fmt.Sprintf("%v", mReq[k])
        if value != "" {
            if i != (len(sorted_keys) - 1) {
                signStrings = signStrings + k + "=" + value + "&"
            } else {
                signStrings = signStrings + k + "=" + value//最后一个不加此符号
            }
        }
    }
    fmt.Println("生成的待签名---->", signStrings)

    //============================= 开始签名 ==================================
    block, _ := pem.Decode([]byte(`-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQCsAocILoBYZqhMYDg40AFZTUiFjcSxwrUXOF0rgw8hh98tP+Ox
4awokuF+FJn8qN/9k9gFz9j7zM694vNv976W60k2ye6uiQdQy/gOJh+ciFME3kAH
QoyvuItKRec+3cEhwblpuY7Gchk0mk22WXWyAHuNGXcCMGSJo9ugGnPDUwIDAQAB
AoGARDgcZdpLfMP6K5Bdu+qDHm/QO2emgvm96J+qE/++mIXStZeJLptaNB1M4Tw6
dkJj06Y3Htb4L6ViuVyxP875/yqKocNur4KeoTLC/t+9L7f6jey7GCvWlCcpp97A
NiVCPILG+7Py2+xGyv0tQT+98yJqTb0yA0nIsmq1XpmjkQECQQDUmVH8L6mJvyzj
xDA32jLKoQLWyJTvzkBxeTnsuTL6GqXEcj9HN0Q1qEyTl/DcN5YfACL4XevV1NNV
s6CrKEojAkEAzx/5d3aAI3dg9VHfAcWdiUZ5uTbx+qpDfZ4CtoyhEfolRGTiy2SC
y9GDrtpY3NO1mm+D5lIM3HPbTgAxtvm9EQJADmI5K8jFva4TiW1ynbTDjvYJzSJR
AVCBB6xeAOgezNEUug/IvDa/BKpYU/wJrbyNCZfmxnqE87ise7Xlfu8A5QJBAJTP
Bx9SLvvMMAfwm0UdonJXBOsR08Zg/35HwPFAlhRhYNcDmIHCo8olq/M7Am8dV7Mt
/VjDiGP2hRBESXOJd9ECPxeHMhK4prFTN1N/+fHcnbB61P89mIsH5ff38D9uEwa/
sLqen0K1ibjhgbcs0LjoVklK9fxJ5AK7SwU0Oxaq0w==
-----END RSA PRIVATE KEY-----
`))
    if block == nil {
        fmt.Println("rsaSign private_key error")
        return ""
    }

    privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
    if err != nil {
        fmt.Printf("x509.ParsePKCS1PrivateKey-------privateKey----- error : %v\n", err)
        return ""
    } else {
        //fmt.Println("x509.ParsePKCS1PrivateKey-------privateKey-----", privateKey)
    }

    result, err := alipay.RsaSign(signStrings, privateKey)
    fmt.Println("alipay.RsaSign=========", result, err)
    return result
}


func (c *AliAnswerController) Post() {
    c.Ctx.WriteString("success")
}
/**
 * RSA签名
 * @param $data 待签名数据
 * @param $private_key_path 商户私钥文件路径
 * return 签名结果
 */
func RsaSign(origData string, privateKey *rsa.PrivateKey) (string, error) {

    h := sha1.New()
    h.Write([]byte(origData))
    digest := h.Sum(nil)

    s, err := rsa.SignPKCS1v15(nil, privateKey, crypto.SHA1, digest)
    if err != nil {
        fmt.Errorf("rsaSign SignPKCS1v15 error")
        return "", err
    }
    data := base64.StdEncoding.EncodeToString(s)
    return string(data), nil
}

如果,当然希望没有这个如果,按照上面的法子依然存在问题,大家可以去github搜下go alipay,再试试看吧。


有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:u012210379

查看原文:golang 支付宝SHA1withRSA加密

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

7648 次点击  ∙  1 赞  
加入收藏 微博
1 回复  |  直到 2017-12-14 14:17:41
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传