+alipayapi
This commit is contained in:
162
platformapi/alipayapi/alipayapi.go
Normal file
162
platformapi/alipayapi/alipayapi.go
Normal file
@@ -0,0 +1,162 @@
|
||||
package alipayapi
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha256"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"git.rosy.net.cn/baseapi"
|
||||
"git.rosy.net.cn/baseapi/platformapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
prodURL = "https://openapi.alipay.com/gateway.do"
|
||||
|
||||
signKey = "sign"
|
||||
)
|
||||
|
||||
const (
|
||||
CommonErrSuccess = "10000"
|
||||
CommonErrServiceNotAvailable = "20000"
|
||||
)
|
||||
|
||||
type API struct {
|
||||
appID string
|
||||
privateKey *rsa.PrivateKey
|
||||
client *http.Client
|
||||
config *platformapi.APIConfig
|
||||
}
|
||||
|
||||
var (
|
||||
commonCanRetryErrMap = map[string]bool{
|
||||
CommonErrServiceNotAvailable: true,
|
||||
}
|
||||
)
|
||||
|
||||
func New(appID string, privateKey interface{}, config ...*platformapi.APIConfig) (a *API) {
|
||||
curConfig := platformapi.DefAPIConfig
|
||||
if len(config) > 0 {
|
||||
curConfig = *config[0]
|
||||
}
|
||||
var keyBytes []byte
|
||||
if keyBytes2, ok := privateKey.([]byte); ok {
|
||||
keyBytes = keyBytes2
|
||||
} else {
|
||||
keyBytes, _ = ioutil.ReadFile(privateKey.(string))
|
||||
}
|
||||
pubPem, _ := pem.Decode(keyBytes)
|
||||
if pubPem == nil {
|
||||
keyBytes, _ = base64.StdEncoding.DecodeString(string(keyBytes))
|
||||
} else {
|
||||
keyBytes = pubPem.Bytes
|
||||
}
|
||||
a = &API{
|
||||
appID: appID,
|
||||
client: &http.Client{Timeout: curConfig.ClientTimeout},
|
||||
config: &curConfig,
|
||||
}
|
||||
if privateKey, err := x509.ParsePKCS1PrivateKey(keyBytes); err == nil {
|
||||
a.privateKey = privateKey
|
||||
} else {
|
||||
baseapi.SugarLogger.Errorf("alpayapi.New failed with err:%v", err)
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
func (a *API) GetAppID() string {
|
||||
return a.appID
|
||||
}
|
||||
|
||||
func (a *API) signParams(params map[string]interface{}) (sign string) {
|
||||
keys := make([]string, 0)
|
||||
for k := range params {
|
||||
if k != signKey {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
strList := make([]string, len(keys))
|
||||
for index, k := range keys {
|
||||
strList[index] = fmt.Sprintf("%s=%v", k, params[k])
|
||||
}
|
||||
|
||||
finalStr := strings.Join(strList, "&")
|
||||
// baseapi.SugarLogger.Debugf("finalStr:%s", finalStr)
|
||||
d := sha256.Sum256([]byte(finalStr))
|
||||
signature, _ := rsa.SignPKCS1v15(rand.Reader, a.privateKey, crypto.SHA256, d[:])
|
||||
sign = base64.StdEncoding.EncodeToString(signature)
|
||||
return sign
|
||||
}
|
||||
|
||||
func method2ResponseKey(method string) (responseKey string) {
|
||||
responseKey = strings.Join(append(strings.Split(method, "."), "response"), "_")
|
||||
return responseKey
|
||||
}
|
||||
|
||||
func (a *API) AccessAPI(method string, params, bizContent map[string]interface{}) (retVal map[string]interface{}, err error) {
|
||||
params = utils.MergeMaps(map[string]interface{}{
|
||||
"app_id": a.GetAppID(),
|
||||
"method": method,
|
||||
"format": "JSON",
|
||||
// "return_url"
|
||||
"charset": "utf-8",
|
||||
"sign_type": "RSA2",
|
||||
"version": "1.0",
|
||||
}, params)
|
||||
if len(bizContent) > 0 {
|
||||
params["biz_content"] = string(utils.MustMarshal(bizContent))
|
||||
}
|
||||
|
||||
err = platformapi.AccessPlatformAPIWithRetry(a.client,
|
||||
func() *http.Request {
|
||||
params["timestamp"] = utils.GetCurTimeStr()
|
||||
params[signKey] = a.signParams(params)
|
||||
fullURL := utils.GenerateGetURL(prodURL, "", params)
|
||||
request, _ := http.NewRequest(http.MethodGet, fullURL, nil)
|
||||
// request, _ := http.NewRequest(http.MethodPost, prodURL, bytes.NewReader(utils.MustMarshal(params)))
|
||||
return request
|
||||
},
|
||||
a.config,
|
||||
func(response *http.Response, bodyStr string, jsonResult1 map[string]interface{}) (errLevel string, err error) {
|
||||
if jsonResult1 == nil {
|
||||
return platformapi.ErrLevelRecoverableErr, fmt.Errorf("mapData is nil")
|
||||
}
|
||||
if errorResponse, ok := jsonResult1["error_response"].(map[string]interface{}); ok {
|
||||
retVal = errorResponse
|
||||
} else {
|
||||
retVal, _ = jsonResult1[method2ResponseKey(method)].(map[string]interface{})
|
||||
if retVal == nil {
|
||||
return platformapi.ErrLevelGeneralFail, fmt.Errorf("结果格式异常")
|
||||
}
|
||||
}
|
||||
|
||||
errCode := utils.Interface2String(retVal["code"])
|
||||
if errCode != CommonErrSuccess && errCode != "" {
|
||||
err = utils.NewErrorCode(utils.Interface2String(retVal["msg"]), errCode)
|
||||
if commonCanRetryErrMap[errCode] {
|
||||
return platformapi.ErrLevelRecoverableErr, err
|
||||
}
|
||||
errLevel = platformapi.ErrLevelGeneralFail
|
||||
}
|
||||
subErrCode := utils.Interface2String(retVal["sub_code"])
|
||||
if subErrCode != "" {
|
||||
return platformapi.ErrLevelCodeIsNotOK, utils.NewErrorCode(utils.Interface2String(retVal["sub_msg"]), subErrCode)
|
||||
} else if err != nil {
|
||||
return errLevel, err
|
||||
}
|
||||
|
||||
return platformapi.ErrLevelSuccess, nil
|
||||
})
|
||||
return retVal, err
|
||||
}
|
||||
Reference in New Issue
Block a user