作一个项目往移动端延伸,有原商家支付宝支付信息,此前是PC端的系统,使用JAVA,因此RSA的密钥信息给到的是PKCS8格式的。我用的是golang语言,调用的函数不能直接使用PKCS8格式,想使用RSA格式,网上找了一下转换的资料。结果找到以下命令:git
openssl rsa -in pri-pkcs8.pem -out pri-rsa-r.pemgithub
我直接把PKCS8那段只有一行的密钥拷进文件中去执行,结果报错。后来头尾加入-----BEGIN PRIVATE KEY-----和-----END PRIVATE KEY-----。发现也不行。后来看到有先后转换的一些例子,应该是须要换行的,看了下,发现65个字符换一行。将原来只有一行的密钥按65分一行试,头尾-----BEGIN PRIVATE KEY-----和-----END PRIVATE KEY-----分别一行,再试那个命令,果真能够了。golang
如下是一些支付宝签名的代码:json
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
}