作一個項目往移動端延伸,有原商家支付寶支付信息,此前是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
}