支付宝支付RSA签名,PKCS8转RSA pem格式

 

做一个项目往移动端延伸,有原商家支付宝支付信息,此前是PC端的系统,使用JAVA,所以RSA的密钥信息给到的是PKCS8格式的。我用的是golang语言,调用的函数不能直接使用PKCS8格式,想使用RSA格式,网上找了一下转换的资料。结果找到如下命令:

openssl rsa -in pri-pkcs8.pem -out pri-rsa-r.pem

我直接把PKCS8那段只有一行的密钥拷进文件中去执行,结果报错。后来头尾加入-----BEGIN PRIVATE KEY-----和-----END PRIVATE KEY-----。发现也不行。后来看到有前后转换的一些例子,应该是需要换行的,看了下,发现65个字符换一行。将原来只有一行的密钥按65分一行试,头尾-----BEGIN PRIVATE KEY-----和-----END PRIVATE KEY-----分别一行,再试那个命令,果然可以了。

 

以下是一些支付宝签名的代码:

 

import (
    "bytes"
    "crypto"
    "crypto/rsa"
    "crypto/sha1"
    "crypto/x509"
    "encoding/base64"
    "encoding/hex"
    "encoding/pem"
    "errors"
    "fmt"
    "io"
    "net/http"
    "net/url"
    //"math/rand"
    //"net/http"
    "sort"
    //"strings"
    //"time"

    "github.com/alecthomas/log4go"
)
type ChargeInfo struct {
    Service     string `json:"service"`        // 接口名称
    Partner     string `json:"partner"`        // 合作者身份ID
    Charset     string `json:"_input_charset"` // 商户网站使用的编码格式,仅支持UTF-8
    SignType    string `json:"sign_type"`      // 签名方式 DSA、RSA、MD5三个值可选,必须大写。
    Sign        string `json:"sign"`           // 签名
    NotifyUrl   string `json:"notify_url"`     // 服务器异步通知页面路径
    ReturnUrl   string `json:"return_url"`     // 页面跳转同步通知页面路径(客户端)
    OrderNo     string `json:"out_trade_no"`   // 商户网站唯一订单号
    Subject     string `json:"subject"`        // 商品名称
    TotalFee    string `json:"total_fee"`      // 交易金额
    SellerId    string `json:"seller_id"`      // 卖家支付宝用户号
    PaymentType string `json:"payment_type"`   // 支付类型。仅支持:1(商品购买)
    ShowUrl     string `json:"show_url"`       // 商品展示网址 用户付款中途退出返回商户网站的地址
}

func (o *APIHandler) ChargeOrderAliPay(userId int64, orderNo string) (*ChargeInfo, error) {

    log4go.Debug("ChargeOrderAliPay()... userId:%d, orderNo:%s", userId, orderNo)

    bookOrder, err := o.GetOrderByOrderNoDb(orderNo)
    if err != nil {
        log4go.Error("ChargeOrderAliPay(): GetOrderByOrderNoDb error.")
        return nil, err
    }

    mapParaValue := make(map[string]string)

    mapParaValue["service"] = ALIPAY_SERVICE
    mapParaValue["partner"] = ALIPAY_PARTNER
    mapParaValue["_input_charset"] = ALIPAY_CHARSET
    mapParaValue["notify_url"] = ALIPAY_NOTIFY_URL
    mapParaValue["return_url"] = o.sc.AlipayReturnUrl
    mapParaValue["out_trade_no"] = orderNo
    mapParaValue["subject"] = bookOrder.LineName
    mapParaValue["total_fee"] = fmt.Sprintf("%f", bookOrder.TotalPrice)
    mapParaValue["seller_id"] = ALIPAY_PARTNER
    mapParaValue["payment_type"] = ALIPAY_PAYMENT_TYPE
    mapParaValue["show_url"] = o.sc.AlipayShowUrl

    signedStr, err := o.AlipaySignParam(mapParaValue)
    if err != nil {
        log4go.Error("ChargeOrderAliPay(): AlipaySignParam error.")
        return nil, err
    }

    charge := ChargeInfo{
        Service:     mapParaValue["service"],
        Partner:     mapParaValue["partner"],
        Charset:     mapParaValue["_input_charset"],
        SignType:    ALIPAY_SIGN_TYPE,
        Sign:        signedStr,
        NotifyUrl:   mapParaValue["notify_url"],
        ReturnUrl:   mapParaValue["return_url"],
        OrderNo:     orderNo,
        Subject:     bookOrder.LineName,
        TotalFee:    mapParaValue["total_fee"],
        SellerId:    mapParaValue["seller_id"],
        PaymentType: mapParaValue["payment_type"],
        ShowUrl:     mapParaValue["show_url"],
    }
    return &charge, nil
}

func (o *APIHandler) AlipaySignParam(mapParam map[string]string) (string, error) {

    log4go.Debug("AlipaySignParam()...len(mapParam):%d", len(mapParam))

    mapDest := make(map[string]interface{})
    for k, v := range mapParam {
        mapDest[k] = interface{}(v)
    }

    // 参数排序
    signStr := o.GenAlipaySignString(mapDest)
    log4go.Debug("AlipaySignParam()...signStr:%s", signStr)

    // rsa加密
    block, _ := pem.Decode([]byte(ALIPAY_PRIVATE_KEY))
    if block == nil {
        log4go.Error("AlipaySignParam private_key error")
        return "", errors.New("pem.Decode error")
    }

    privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
    if err != nil {
        log4go.Error("x509.ParsePKCS1PrivateKey-------privateKey----- error : %v", err)
        return "", err
    } else {
        log4go.Debug("x509.ParsePKCS1PrivateKey-------privateKey-----:%s", privateKey)
    }

    result, err := AlipayRsaSign(signStr, privateKey)
    if err != nil {
        log4go.Error("AlipayRsaSign error")
        return "", err
    }
    log4go.Debug("AlipayRsaSign result:%s", result)
    return result, nil
}

func (o *APIHandler) GenAlipaySignString(mapBody map[string]interface{}) (sign string) {

    log4go.Debug("GenAlipaySignString()...")
    sorted_keys := make([]string, 0)
    for k, _ := range mapBody {
        sorted_keys = append(sorted_keys, k)
    }
    sort.Strings(sorted_keys)
    var signStrings string

    index := 0
    for _, k := range sorted_keys {
        log4go.Debug("GenAlipaySignString() k=%s, v=%v", k, mapBody[k])
        value := fmt.Sprintf("%v", mapBody[k])
        if value != "" {
            signStrings = signStrings + k + "=" + value
        }
        // 最后一项后面不要&
        if index < len(sorted_keys)-1 {
            signStrings = signStrings + "&"
        }
        index++
    }

    return signStrings
}

/**
 * RSA签名
 * @param $data 待签名数据
 * @param $private_key_path 商户私钥文件路径
 * return 签名结果
 */
func AlipayRsaSign(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 {
        log4go.Error("RsaSign() err=%s", err)
        return "", err
    }
    data := base64.StdEncoding.EncodeToString(s)
    return string(data), nil
}

posted @ 2017-06-20 18:11  kaka7518  阅读(1312)  评论(0编辑  收藏  举报