添加网站文件
This commit is contained in:
90
vendor/alipaysdk/easysdk/go/README.md
vendored
Normal file
90
vendor/alipaysdk/easysdk/go/README.md
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
[](https://packagist.org/packages/alipaysdk/easysdk)
|
||||
[](https://app.fossa.com/projects/git%2Bgithub.com%2Falipay%2Falipay-easysdk?ref=badge_shield)
|
||||
|
||||
欢迎使用 Alipay **Easy** SDK for Go 。
|
||||
|
||||
Alipay Esay SDK for Go让您不用复杂编程即可访支付宝开放平台开放的各项常用能力,SDK可以自动帮您满足能力调用过程中所需的证书校验、加签、验签、发送HTTP请求等非功能性要求。
|
||||
|
||||
下面向您介绍Alipay Easy SDK for Go 的基本设计理念和使用方法。
|
||||
|
||||
## 设计理念
|
||||
|
||||
Alipay Easy SDK主要目标是提升开发者在**服务端**集成支付宝开放平台开放的各类核心能力的效率。
|
||||
|
||||
## 环境要求
|
||||
1. Alipay Easy SDK for Go 需要配合`Go 1.12`或其以上版本。
|
||||
|
||||
2. 使用 Alipay Easy SDK for Go 之前 ,您需要先前往[支付宝开发平台-开发者中心](https://openhome.alipay.com/platform/developerIndex.htm)完成开发者接入的一些准备工作,包括创建应用、为应用添加功能包、设置应用的接口加签方式等。
|
||||
|
||||
3. 准备工作完成后,注意保存如下信息,后续将作为使用SDK的输入。
|
||||
|
||||
* 加签模式为公钥证书模式时(推荐)
|
||||
|
||||
`AppId`、`应用的私钥`、`应用公钥证书文件`、`支付宝公钥证书文件`、`支付宝根证书文件`
|
||||
|
||||
* 加签模式为公钥模式时
|
||||
|
||||
`AppId`、`应用的私钥`、`支付宝公钥`
|
||||
|
||||
## 安装
|
||||
手动下载go目录下源码集成即可
|
||||
|
||||
## 快速使用
|
||||
以下这段代码示例向您展示了使用Alipay Easy SDK for Go调用一个API的3个主要步骤:
|
||||
|
||||
1. 设置参数(全局只需设置一次)。
|
||||
2. 发起API调用。
|
||||
3. 处理响应或异常。
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"kernel"
|
||||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
account:= kernel.Client{}
|
||||
account.Protocol = "https"
|
||||
account.GatewayHost = "openapi.alipay.com"
|
||||
account.AppId = "<-- 请填写您的AppId,例如:2019022663440152 -->"
|
||||
account.SignType = "RSA2"
|
||||
account.AlipayPublicKey = "<-- 请填写您的支付宝公钥,例如:MIIBIjANBg... -->"
|
||||
account.MerchantPrivateKey = "<-- 请填写您的应用私钥,例如:MIIEvQIBADANB ... ... -->"
|
||||
|
||||
kernel.InitClient(account)
|
||||
}
|
||||
|
||||
|
||||
func main() {
|
||||
result, _ := kernel.Execute("alipay.trade.create", nil, getBizParams(time.Now().Format("2006-01-02 15:04:05")))
|
||||
fmt.Println(result)
|
||||
}
|
||||
|
||||
func getBizParams(outTradeNo string) map[string]string {
|
||||
bizParams := map[string]string{
|
||||
"subject": "phone6 16G",
|
||||
"out_trade_no": outTradeNo,
|
||||
"total_amount": "0.10",
|
||||
"buyer_id": "2088002656718920",
|
||||
"extend_params": getHuabeiParams(),
|
||||
}
|
||||
return bizParams
|
||||
}
|
||||
|
||||
func getHuabeiParams() string {
|
||||
extendParams := map[string]string{
|
||||
"hb_fq_num": "3",
|
||||
"hb_fq_seller_percent": "3",
|
||||
}
|
||||
byt, _ := json.Marshal(extendParams)
|
||||
return string(byt)
|
||||
}
|
||||
```
|
||||
|
||||
## 文档
|
||||
|
||||
[Alipay Easy SDK](./../README.md)
|
||||
14
vendor/alipaysdk/easysdk/go/src/kernel/AlipayConstants.go
vendored
Normal file
14
vendor/alipaysdk/easysdk/go/src/kernel/AlipayConstants.go
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
package kernel
|
||||
|
||||
/**
|
||||
* 与网关HTTP交互中涉及到的字段值
|
||||
*/
|
||||
const bizContent = "biz_content"
|
||||
const alipayCertSN = "alipay_cert_sn"
|
||||
const signField = "sign"
|
||||
const bodyField = "http_body"
|
||||
const notifyUrl = "notify_url"
|
||||
const methodField = "method"
|
||||
const response = "_response"
|
||||
const errorResponse = "error_response"
|
||||
const sdkVersion = "alipay-easysdk-go-1.0.0"
|
||||
246
vendor/alipaysdk/easysdk/go/src/kernel/BaseClient.go
vendored
Normal file
246
vendor/alipaysdk/easysdk/go/src/kernel/BaseClient.go
vendored
Normal file
@@ -0,0 +1,246 @@
|
||||
package kernel
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
Sort "sort"
|
||||
"strings"
|
||||
"tea"
|
||||
"time"
|
||||
)
|
||||
|
||||
var this Client
|
||||
|
||||
func GetConfig(key string) string {
|
||||
if key == "protocol" {
|
||||
return this.Protocol
|
||||
} else if key == "gatewayHost" {
|
||||
return this.GatewayHost
|
||||
} else if key == "appId" {
|
||||
return this.AppId
|
||||
} else if key == "signType" {
|
||||
return this.SignType
|
||||
} else if key == "alipayPublicKey" {
|
||||
return this.AlipayPublicKey
|
||||
} else if key == "merchantPrivateKey" {
|
||||
return this.MerchantPrivateKey
|
||||
} else if key == "merchantCertPath" {
|
||||
return this.MerchantCertPath
|
||||
} else if key == "alipayCertPath" {
|
||||
return this.AlipayCertPath
|
||||
} else if key == "alipayRootCertPath" {
|
||||
return this.AlipayRootCertPath
|
||||
} else if key == "notifyUrl" {
|
||||
return this.NotifyUrl
|
||||
} else if key == "encryptKey" {
|
||||
return this.EncryptKey
|
||||
} else {
|
||||
panic(key + " is illegal")
|
||||
}
|
||||
}
|
||||
|
||||
func InitClient(config Client) {
|
||||
this = config
|
||||
}
|
||||
|
||||
/**
|
||||
获取时间戳,格式yyyy-MM-dd HH:mm:ss
|
||||
*/
|
||||
func GetTimestamp() string {
|
||||
return time.Now().Format("2006-01-02 15:04:05")
|
||||
}
|
||||
|
||||
func GetSdkVersion() string {
|
||||
return sdkVersion
|
||||
}
|
||||
|
||||
func GetMerchantCertSN() string {
|
||||
return this.MerchantCertSN
|
||||
}
|
||||
|
||||
func GetAlipayCertSN(alipayCertSN map[string]string) string {
|
||||
return this.AlipayCertSN
|
||||
}
|
||||
|
||||
func GetAlipayRootCertSN() string {
|
||||
return this.AlipayRootCertSN
|
||||
}
|
||||
|
||||
func ExtractAlipayPublicKey(alipayPublicKey string) string {
|
||||
return this.AlipayCertSN
|
||||
}
|
||||
|
||||
func IsCertMode() bool {
|
||||
if len(this.AlipayCertSN) != 0 {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
将业务参数和其他额外文本参数按www-form-urlencoded格式转换成HTTP Body中的字节数组,注意要做URL Encode
|
||||
*/
|
||||
func ToUrlEncodedRequestBody(bizParams map[string]string) string {
|
||||
sortedMap := getSortedMap(nil, bizParams, nil)
|
||||
if sortedMap == nil {
|
||||
return ""
|
||||
}
|
||||
return buildQueryString(bizParams)
|
||||
}
|
||||
|
||||
func buildQueryString(sortedMap map[string]string) string {
|
||||
requestUrl := ""
|
||||
keys := make([]string, 0)
|
||||
for k, _ := range sortedMap {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
Sort.Strings(keys)
|
||||
var pList = make([]string, 0, 0)
|
||||
for _, key := range keys {
|
||||
pList = append(pList, key+"="+sortedMap[key])
|
||||
}
|
||||
requestUrl = strings.Join(pList, "&")
|
||||
return requestUrl
|
||||
}
|
||||
|
||||
func getSortedMap(systemParams map[string]string, bizParams map[string]string, textParams map[string]string) map[string]string {
|
||||
sortedMap := tea.Merge(systemParams, bizParams, textParams)
|
||||
sortedMap = SortMap(sortedMap)
|
||||
return sortedMap
|
||||
}
|
||||
|
||||
func SortMap(romanNumeralDict map[string]string) map[string]string {
|
||||
keys := make([]string, 0)
|
||||
for k, _ := range romanNumeralDict {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
Sort.Strings(keys)
|
||||
return romanNumeralDict
|
||||
}
|
||||
|
||||
/**
|
||||
计算签名
|
||||
*/
|
||||
func Sign(systemParams map[string]string, bizParams map[string]string, textParams map[string]string, privateKey string) string {
|
||||
if bizParams != nil {
|
||||
byt, _ := json.Marshal(bizParams)
|
||||
bizParams[bizContent] = string(byt)
|
||||
}
|
||||
sortedMap := getSortedMap(systemParams, bizParams, textParams)
|
||||
data := buildQueryString(sortedMap)
|
||||
var prvKey = formatKey(privateKey, `-----BEGIN RSA PRIVATE KEY-----`, `-----END RSA PRIVATE KEY-----`, 64)
|
||||
signData := RsaSignWithSha256([]byte(data), prvKey)
|
||||
return base64.StdEncoding.EncodeToString(signData)
|
||||
}
|
||||
|
||||
func Verify(respMap map[string]string, alipayPublicKey string) bool {
|
||||
resp := respMap[bodyField]
|
||||
method := respMap[methodField]
|
||||
content, sign := getSignSourceData(resp, method)
|
||||
signBytes, err := base64.StdEncoding.DecodeString(sign)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
pubKey := formatKey(alipayPublicKey, `-----BEGIN PUBLIC KEY-----`, `-----END PUBLIC KEY-----`, 64)
|
||||
result := RsaVerySignWithSha256([]byte(content), signBytes, pubKey)
|
||||
return result
|
||||
}
|
||||
|
||||
func getSignSourceData(body string, method string) (content string, sign string) {
|
||||
var rootNodeName = strings.Replace(method, ".", "_", -1) + response
|
||||
var rootIndex = strings.LastIndex(body, rootNodeName)
|
||||
var errorIndex = strings.LastIndex(body, errorResponse)
|
||||
if rootIndex > 0 {
|
||||
return parserJSONSource(body, rootNodeName, rootIndex)
|
||||
} else if errorIndex > 0 {
|
||||
return parserJSONSource(body, errorResponse, errorIndex)
|
||||
} else {
|
||||
return "", ""
|
||||
}
|
||||
}
|
||||
|
||||
func parserJSONSource(responseContent string, nodeName string, nodeIndex int) (content string, sign string) {
|
||||
signDataStartIndex := nodeIndex + len(nodeName) + 2
|
||||
signIndex := 0
|
||||
if strings.LastIndex(responseContent, alipayCertSN) > 0 {
|
||||
signIndex = strings.LastIndex(responseContent, "\""+alipayCertSN+"\"")
|
||||
} else {
|
||||
signIndex = strings.LastIndex(responseContent, "\""+signField+"\"")
|
||||
}
|
||||
signDataEndIndex := signIndex - 1
|
||||
indexLen := signDataEndIndex - signDataStartIndex
|
||||
if indexLen < 0 {
|
||||
return "", ""
|
||||
}
|
||||
content = responseContent[signDataStartIndex:signDataEndIndex]
|
||||
sign = responseContent[signIndex+8 : len(responseContent)-2]
|
||||
return content, sign
|
||||
}
|
||||
|
||||
func ToRespModel(resp map[string]string) map[string]interface{} {
|
||||
body := resp[bodyField]
|
||||
method := resp[methodField]
|
||||
content, _ := getSignSourceData(body, method)
|
||||
result := map[string]interface{}{
|
||||
bodyField: body,
|
||||
}
|
||||
arg := make(map[string]interface{})
|
||||
err := json.Unmarshal([]byte(content), &arg)
|
||||
tmp := make(map[string]string)
|
||||
err = json.Unmarshal([]byte(content), &tmp)
|
||||
if err == nil {
|
||||
for key, value := range arg {
|
||||
if value != "" {
|
||||
result[key] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
解析网关响应内容,同时将API的接口名称和响应原文插入到响应数组的method和body字段中
|
||||
*/
|
||||
func ReadAsJson(response io.Reader, method string) (map[string]string, error) {
|
||||
byt, err := ioutil.ReadAll(response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = json.Unmarshal(byt, response)
|
||||
result := map[string]string{
|
||||
bodyField: string(byt),
|
||||
methodField: method,
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
|
||||
func AesDecrypt(cipherText string, encryptKey string) {
|
||||
de:=AESDecrypt([]byte(cipherText), []byte(encryptKey))
|
||||
fmt.Println(de)
|
||||
}
|
||||
|
||||
func AesEncrypt(plainText string, encryptKey string) {
|
||||
en := AESEncrypt([]byte(plainText), []byte(encryptKey))
|
||||
fmt.Println(en)
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
Protocol string
|
||||
GatewayHost string
|
||||
AppId string
|
||||
SignType string
|
||||
AlipayPublicKey string
|
||||
MerchantPrivateKey string
|
||||
MerchantCertPath string
|
||||
AlipayCertPath string
|
||||
AlipayRootCertPath string
|
||||
NotifyUrl string
|
||||
EncryptKey string
|
||||
MerchantCertSN string
|
||||
AlipayCertSN string
|
||||
AlipayRootCertSN string
|
||||
}
|
||||
142
vendor/alipaysdk/easysdk/go/src/kernel/client.go
vendored
Normal file
142
vendor/alipaysdk/easysdk/go/src/kernel/client.go
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
package kernel
|
||||
|
||||
|
||||
import (
|
||||
"tea"
|
||||
)
|
||||
|
||||
type AlipayOpenApiGenericResponse struct {
|
||||
HttpBody *string `json:"http_body" xml:"http_body" require:"true"`
|
||||
Code *string `json:"code" xml:"code" require:"true"`
|
||||
Msg *string `json:"msg" xml:"msg" require:"true"`
|
||||
SubCode *string `json:"sub_code" xml:"sub_code" require:"true"`
|
||||
SubMsg *string `json:"sub_msg" xml:"sub_msg" require:"true"`
|
||||
}
|
||||
|
||||
func (s AlipayOpenApiGenericResponse) String() string {
|
||||
return tea.Prettify(s)
|
||||
}
|
||||
|
||||
func (s AlipayOpenApiGenericResponse) GoString() string {
|
||||
return s.String()
|
||||
}
|
||||
|
||||
func (s *AlipayOpenApiGenericResponse) SetHttpBody(v string) *AlipayOpenApiGenericResponse {
|
||||
s.HttpBody = &v
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *AlipayOpenApiGenericResponse) SetCode(v string) *AlipayOpenApiGenericResponse {
|
||||
s.Code = &v
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *AlipayOpenApiGenericResponse) SetMsg(v string) *AlipayOpenApiGenericResponse {
|
||||
s.Msg = &v
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *AlipayOpenApiGenericResponse) SetSubCode(v string) *AlipayOpenApiGenericResponse {
|
||||
s.SubCode = &v
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *AlipayOpenApiGenericResponse) SetSubMsg(v string) *AlipayOpenApiGenericResponse {
|
||||
s.SubMsg = &v
|
||||
return s
|
||||
}
|
||||
|
||||
func NewClient()(*Client, error) {
|
||||
client := new(Client)
|
||||
err := client.Init()
|
||||
return client, err
|
||||
}
|
||||
|
||||
func (client *Client)Init()(_err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
func Execute(method string, textParams map[string]string, bizParams map[string]string) (_result *AlipayOpenApiGenericResponse, _err error) {
|
||||
_runtime := map[string]interface{}{
|
||||
"connectTimeout": 15000,
|
||||
"readTimeout": 15000,
|
||||
"retry": map[string]int{
|
||||
"maxAttempts": 0,
|
||||
},
|
||||
}
|
||||
|
||||
_resp := &AlipayOpenApiGenericResponse{}
|
||||
for _retryTimes := 0; tea.AllowRetry(_runtime["retry"], _retryTimes); _retryTimes++ {
|
||||
if _retryTimes > 0 {
|
||||
_backoffTime := tea.GetBackoffTime(_runtime["backoff"], _retryTimes)
|
||||
if _backoffTime > 0 {
|
||||
tea.Sleep(_backoffTime)
|
||||
}
|
||||
}
|
||||
|
||||
_resp, _err = func()(*AlipayOpenApiGenericResponse, error){
|
||||
request_ := tea.NewRequest()
|
||||
systemParams := map[string]string{
|
||||
"method": method,
|
||||
"app_id": GetConfig("appId"),
|
||||
"timestamp": GetTimestamp(),
|
||||
"format": "json",
|
||||
"version": "1.0",
|
||||
"alipay_sdk": GetSdkVersion(),
|
||||
"charset": "UTF-8",
|
||||
"sign_type": GetConfig("signType"),
|
||||
"app_cert_sn": GetMerchantCertSN(),
|
||||
"alipay_root_cert_sn": GetAlipayRootCertSN(),
|
||||
}
|
||||
request_.Protocol = GetConfig("protocol")
|
||||
request_.Method = "POST"
|
||||
request_.Pathname = "/gateway.do"
|
||||
request_.Headers = map[string]string{
|
||||
"host": GetConfig("gatewayHost"),
|
||||
"content-type": "application/x-www-form-urlencoded;charset=utf-8",
|
||||
}
|
||||
request_.Query = SortMap(tea.Merge(map[string]string{
|
||||
"sign": Sign(systemParams, bizParams, textParams, GetConfig("merchantPrivateKey")),
|
||||
},systemParams,
|
||||
textParams))
|
||||
request_.Body = tea.ToReader(ToUrlEncodedRequestBody(bizParams))
|
||||
response_, _err := tea.DoRequest(request_, _runtime)
|
||||
if _err != nil {
|
||||
return nil, _err
|
||||
}
|
||||
respMap, _err := ReadAsJson(response_.Body, method)
|
||||
if _err != nil {
|
||||
return nil, _err
|
||||
}
|
||||
|
||||
if IsCertMode() {
|
||||
if Verify(respMap, ExtractAlipayPublicKey(GetAlipayCertSN(respMap))) {
|
||||
_result = &AlipayOpenApiGenericResponse{}
|
||||
_body := ToRespModel(respMap)
|
||||
_err = tea.Convert(_body, &_result)
|
||||
return _result, _err
|
||||
}
|
||||
|
||||
} else {
|
||||
if Verify(respMap, GetConfig("alipayPublicKey")) {
|
||||
_result = &AlipayOpenApiGenericResponse{}
|
||||
_body := ToRespModel(respMap)
|
||||
_err = tea.Convert(_body, &_result)
|
||||
return _result, _err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_err = tea.NewSDKError(map[string]interface{}{
|
||||
"message": "验签失败,请检查支付宝公钥设置是否正确。",
|
||||
})
|
||||
return nil, _err
|
||||
}()
|
||||
if !tea.Retryable(_err) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return _resp, _err
|
||||
}
|
||||
133
vendor/alipaysdk/easysdk/go/src/kernel/signer.go
vendored
Normal file
133
vendor/alipaysdk/easysdk/go/src/kernel/signer.go
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
package kernel
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha256"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
//签名
|
||||
func RsaSignWithSha256(data []byte, keyBytes []byte) []byte {
|
||||
h := sha256.New()
|
||||
h.Write(data)
|
||||
hashed := h.Sum(nil)
|
||||
block, _ := pem.Decode(keyBytes)
|
||||
if block == nil {
|
||||
panic(errors.New("private key error"))
|
||||
}
|
||||
privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
|
||||
if err != nil {
|
||||
fmt.Println("ParsePKCS8PrivateKey err", err)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
signature, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hashed)
|
||||
if err != nil {
|
||||
fmt.Printf("Error from signing: %s\n", err)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return signature
|
||||
}
|
||||
|
||||
//验证
|
||||
func RsaVerySignWithSha256(data, signData, keyBytes []byte) bool {
|
||||
block, _ := pem.Decode(keyBytes)
|
||||
if block == nil {
|
||||
panic(errors.New("public key error"))
|
||||
}
|
||||
pubKey, err := x509.ParsePKIXPublicKey(block.Bytes)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
hashed := sha256.Sum256(data)
|
||||
err = rsa.VerifyPKCS1v15(pubKey.(*rsa.PublicKey), crypto.SHA256, hashed[:], signData)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func formatKey(raw, prefix, suffix string, lineCount int) []byte {
|
||||
if raw == "" {
|
||||
return nil
|
||||
}
|
||||
raw = strings.Replace(raw, prefix, "", 1)
|
||||
raw = strings.Replace(raw, suffix, "", 1)
|
||||
raw = strings.Replace(raw, " ", "", -1)
|
||||
raw = strings.Replace(raw, "\n", "", -1)
|
||||
raw = strings.Replace(raw, "\r", "", -1)
|
||||
raw = strings.Replace(raw, "\t", "", -1)
|
||||
var sl = len(raw)
|
||||
var c = sl / lineCount
|
||||
if sl%lineCount > 0 {
|
||||
c = c + 1
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
buf.WriteString(prefix + "\n")
|
||||
for i := 0; i < c; i++ {
|
||||
var b = i * lineCount
|
||||
var e = b + lineCount
|
||||
if e > sl {
|
||||
buf.WriteString(raw[b:])
|
||||
} else {
|
||||
buf.WriteString(raw[b:e])
|
||||
}
|
||||
buf.WriteString("\n")
|
||||
}
|
||||
buf.WriteString(suffix)
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
//解密
|
||||
func AESDecrypt(crypted, key []byte) []byte {
|
||||
block, _ := aes.NewCipher(key)
|
||||
blockSize := block.BlockSize()
|
||||
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
|
||||
origData := make([]byte, len(crypted))
|
||||
blockMode.CryptBlocks(origData, crypted)
|
||||
origData = PKCS7UnPadding(origData)
|
||||
return origData
|
||||
}
|
||||
|
||||
//去补码
|
||||
func PKCS7UnPadding(origData []byte) []byte {
|
||||
length := len(origData)
|
||||
unpadding := int(origData[length-1])
|
||||
return origData[:length-unpadding]
|
||||
}
|
||||
|
||||
//加密
|
||||
func AESEncrypt(origData, key []byte) []byte {
|
||||
//获取block块
|
||||
block, _ := aes.NewCipher(key)
|
||||
//补码
|
||||
origData = PKCS7Padding(origData, block.BlockSize())
|
||||
//加密模式,
|
||||
blockMode := cipher.NewCBCEncrypter(block, key[:block.BlockSize()])
|
||||
//创建明文长度的数组
|
||||
crypted := make([]byte, len(origData))
|
||||
//加密明文
|
||||
blockMode.CryptBlocks(crypted, origData)
|
||||
return crypted
|
||||
}
|
||||
|
||||
//补码
|
||||
func PKCS7Padding(origData []byte, blockSize int) []byte {
|
||||
//计算需要补几位数
|
||||
padding := blockSize - len(origData)%blockSize
|
||||
//在切片后面追加char数量的byte(char)
|
||||
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
|
||||
return append(origData, padtext...)
|
||||
}
|
||||
37
vendor/alipaysdk/easysdk/go/src/tea/debug.go
vendored
Normal file
37
vendor/alipaysdk/easysdk/go/src/tea/debug.go
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
package tea
|
||||
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Debug func(format string, v ...interface{})
|
||||
|
||||
var hookGetEnv = func() string {
|
||||
return os.Getenv("DEBUG")
|
||||
}
|
||||
|
||||
var hookPrint = func(input string) {
|
||||
fmt.Println(input)
|
||||
}
|
||||
|
||||
func Init(flag string) Debug {
|
||||
enable := false
|
||||
|
||||
env := hookGetEnv()
|
||||
parts := strings.Split(env, ",")
|
||||
for _, part := range parts {
|
||||
if part == flag {
|
||||
enable = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return func(format string, v ...interface{}) {
|
||||
if enable {
|
||||
hookPrint(fmt.Sprintf(format, v...))
|
||||
}
|
||||
}
|
||||
}
|
||||
110
vendor/alipaysdk/easysdk/go/src/tea/logger.go
vendored
Normal file
110
vendor/alipaysdk/easysdk/go/src/tea/logger.go
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
package tea
|
||||
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Logger struct {
|
||||
*log.Logger
|
||||
formatTemplate string
|
||||
isOpen bool
|
||||
lastLogMsg string
|
||||
}
|
||||
|
||||
var defaultLoggerTemplate = `{time} {channel}: "{method} {uri} HTTP/{version}" {code} {cost} {hostname}`
|
||||
var loggerParam = []string{"{time}", "{start_time}", "{ts}", "{channel}", "{pid}", "{host}", "{method}", "{uri}", "{version}", "{target}", "{hostname}", "{code}", "{error}", "{req_headers}", "{res_body}", "{res_headers}", "{cost}"}
|
||||
var logChannel string
|
||||
|
||||
func InitLogMsg(fieldMap map[string]string) {
|
||||
for _, value := range loggerParam {
|
||||
fieldMap[value] = ""
|
||||
}
|
||||
}
|
||||
|
||||
func (logger *Logger) SetFormatTemplate(template string) {
|
||||
logger.formatTemplate = template
|
||||
|
||||
}
|
||||
|
||||
func (logger *Logger) GetFormatTemplate() string {
|
||||
return logger.formatTemplate
|
||||
|
||||
}
|
||||
|
||||
func NewLogger(level string, channel string, out io.Writer, template string) *Logger {
|
||||
if level == "" {
|
||||
level = "info"
|
||||
}
|
||||
|
||||
logChannel = "AlibabaCloud"
|
||||
if channel != "" {
|
||||
logChannel = channel
|
||||
}
|
||||
log := log.New(out, "["+strings.ToUpper(level)+"]", log.Lshortfile)
|
||||
if template == "" {
|
||||
template = defaultLoggerTemplate
|
||||
}
|
||||
|
||||
return &Logger{
|
||||
Logger: log,
|
||||
formatTemplate: template,
|
||||
isOpen: true,
|
||||
}
|
||||
}
|
||||
|
||||
func (logger *Logger) OpenLogger() {
|
||||
logger.isOpen = true
|
||||
}
|
||||
|
||||
func (logger *Logger) CloseLogger() {
|
||||
logger.isOpen = false
|
||||
}
|
||||
|
||||
func (logger *Logger) SetIsopen(isopen bool) {
|
||||
logger.isOpen = isopen
|
||||
}
|
||||
|
||||
func (logger *Logger) GetIsopen() bool {
|
||||
return logger.isOpen
|
||||
}
|
||||
|
||||
func (logger *Logger) SetLastLogMsg(lastLogMsg string) {
|
||||
logger.lastLogMsg = lastLogMsg
|
||||
}
|
||||
|
||||
func (logger *Logger) GetLastLogMsg() string {
|
||||
return logger.lastLogMsg
|
||||
}
|
||||
|
||||
func SetLogChannel(channel string) {
|
||||
logChannel = channel
|
||||
}
|
||||
|
||||
func (logger *Logger) PrintLog(fieldMap map[string]string, err error) {
|
||||
if err != nil {
|
||||
fieldMap["{error}"] = err.Error()
|
||||
}
|
||||
fieldMap["{time}"] = time.Now().Format("2006-01-02 15:04:05")
|
||||
fieldMap["{ts}"] = getTimeInFormatISO8601()
|
||||
fieldMap["{channel}"] = logChannel
|
||||
if logger != nil {
|
||||
logMsg := logger.formatTemplate
|
||||
for key, value := range fieldMap {
|
||||
logMsg = strings.Replace(logMsg, key, value, -1)
|
||||
}
|
||||
logger.lastLogMsg = logMsg
|
||||
if logger.isOpen == true {
|
||||
logger.Output(2, logMsg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getTimeInFormatISO8601() (timeStr string) {
|
||||
gmt := time.FixedZone("GMT", 0)
|
||||
|
||||
return time.Now().In(gmt).Format("2006-01-02T15:04:05Z")
|
||||
}
|
||||
60
vendor/alipaysdk/easysdk/go/src/tea/progress.go
vendored
Normal file
60
vendor/alipaysdk/easysdk/go/src/tea/progress.go
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
package tea
|
||||
|
||||
// ProgressEventType defines transfer progress event type
|
||||
type ProgressEventType int
|
||||
|
||||
const (
|
||||
// TransferStartedEvent transfer started, set TotalBytes
|
||||
TransferStartedEvent ProgressEventType = 1 + iota
|
||||
// TransferDataEvent transfer data, set ConsumedBytes anmd TotalBytes
|
||||
TransferDataEvent
|
||||
// TransferCompletedEvent transfer completed
|
||||
TransferCompletedEvent
|
||||
// TransferFailedEvent transfer encounters an error
|
||||
TransferFailedEvent
|
||||
)
|
||||
|
||||
// ProgressEvent defines progress event
|
||||
type ProgressEvent struct {
|
||||
ConsumedBytes int64
|
||||
TotalBytes int64
|
||||
RwBytes int64
|
||||
EventType ProgressEventType
|
||||
}
|
||||
|
||||
// ProgressListener listens progress change
|
||||
type ProgressListener interface {
|
||||
ProgressChanged(event *ProgressEvent)
|
||||
}
|
||||
|
||||
// -------------------- Private --------------------
|
||||
|
||||
func NewProgressEvent(eventType ProgressEventType, consumed, total int64, rwBytes int64) *ProgressEvent {
|
||||
return &ProgressEvent{
|
||||
ConsumedBytes: consumed,
|
||||
TotalBytes: total,
|
||||
RwBytes: rwBytes,
|
||||
EventType: eventType}
|
||||
}
|
||||
|
||||
// publishProgress
|
||||
func PublishProgress(listener ProgressListener, event *ProgressEvent) {
|
||||
if listener != nil && event != nil {
|
||||
listener.ProgressChanged(event)
|
||||
}
|
||||
}
|
||||
|
||||
func GetProgressListener(obj interface{}) ProgressListener {
|
||||
if obj == nil {
|
||||
return nil
|
||||
}
|
||||
listener, ok := obj.(ProgressListener)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return listener
|
||||
}
|
||||
|
||||
type ReaderTracker struct {
|
||||
CompletedBytes int64
|
||||
}
|
||||
919
vendor/alipaysdk/easysdk/go/src/tea/tea.go
vendored
Normal file
919
vendor/alipaysdk/easysdk/go/src/tea/tea.go
vendored
Normal file
@@ -0,0 +1,919 @@
|
||||
package tea
|
||||
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/proxy"
|
||||
)
|
||||
|
||||
var debugLog = Init("tea")
|
||||
|
||||
var hookDo = func(fn func(req *http.Request) (*http.Response, error)) func(req *http.Request) (*http.Response, error) {
|
||||
return fn
|
||||
}
|
||||
|
||||
var basicTypes = []string{
|
||||
"int", "int64", "float32", "float64", "string", "bool", "uint64",
|
||||
}
|
||||
|
||||
// Verify whether the parameters meet the requirements
|
||||
var validateParams = []string{"require", "pattern", "maxLength"}
|
||||
|
||||
// CastError is used for cast type fails
|
||||
type CastError struct {
|
||||
Message string
|
||||
}
|
||||
|
||||
// Request is used wrap http request
|
||||
type Request struct {
|
||||
Protocol string
|
||||
Port int
|
||||
Method string
|
||||
Pathname string
|
||||
Domain string
|
||||
Headers map[string]string
|
||||
Query map[string]string
|
||||
Body io.Reader
|
||||
}
|
||||
|
||||
// Response is use d wrap http response
|
||||
type Response struct {
|
||||
Body io.ReadCloser
|
||||
StatusCode int
|
||||
StatusMessage string
|
||||
Headers map[string]string
|
||||
}
|
||||
|
||||
// SDKError struct is used save error code and message
|
||||
type SDKError struct {
|
||||
Code string
|
||||
Message string
|
||||
Data string
|
||||
}
|
||||
|
||||
// RuntimeObject is used for converting http configuration
|
||||
type RuntimeObject struct {
|
||||
IgnoreSSL bool `json:"ignoreSSL" xml:"ignoreSSL"`
|
||||
ReadTimeout int `json:"readTimeout" xml:"readTimeout"`
|
||||
ConnectTimeout int `json:"connectTimeout" xml:"connectTimeout"`
|
||||
LocalAddr string `json:"localAddr" xml:"localAddr"`
|
||||
HttpProxy string `json:"httpProxy" xml:"httpProxy"`
|
||||
HttpsProxy string `json:"httpsProxy" xml:"httpsProxy"`
|
||||
NoProxy string `json:"noProxy" xml:"noProxy"`
|
||||
MaxIdleConns int `json:"maxIdleConns" xml:"maxIdleConns"`
|
||||
Socks5Proxy string `json:"socks5Proxy" xml:"socks5Proxy"`
|
||||
Socks5NetWork string `json:"socks5NetWork" xml:"socks5NetWork"`
|
||||
Listener ProgressListener `json:"listener" xml:"listener"`
|
||||
Tracker *ReaderTracker `json:"tracker" xml:"tracker"`
|
||||
Logger *Logger `json:"logger" xml:"logger"`
|
||||
}
|
||||
|
||||
type teaClient struct {
|
||||
sync.Mutex
|
||||
httpClient *http.Client
|
||||
ifInit bool
|
||||
}
|
||||
|
||||
var clientPool = &sync.Map{}
|
||||
|
||||
func (r *RuntimeObject) getClientTag(domain string) string {
|
||||
return strconv.FormatBool(r.IgnoreSSL) + strconv.Itoa(r.ReadTimeout) +
|
||||
strconv.Itoa(r.ConnectTimeout) + r.LocalAddr + r.HttpProxy +
|
||||
r.HttpsProxy + r.NoProxy + r.Socks5Proxy + r.Socks5NetWork + domain
|
||||
}
|
||||
|
||||
// NewRuntimeObject is used for shortly create runtime object
|
||||
func NewRuntimeObject(runtime map[string]interface{}) *RuntimeObject {
|
||||
if runtime == nil {
|
||||
return &RuntimeObject{}
|
||||
}
|
||||
|
||||
runtimeObject := &RuntimeObject{
|
||||
IgnoreSSL: TransInterfaceToBool(runtime["ignoreSSL"]),
|
||||
ReadTimeout: TransInterfaceToInt(runtime["readTimeout"]),
|
||||
ConnectTimeout: TransInterfaceToInt(runtime["connectTimeout"]),
|
||||
LocalAddr: TransInterfaceToString(runtime["localAddr"]),
|
||||
HttpProxy: TransInterfaceToString(runtime["httpProxy"]),
|
||||
HttpsProxy: TransInterfaceToString(runtime["httpsProxy"]),
|
||||
NoProxy: TransInterfaceToString(runtime["noProxy"]),
|
||||
MaxIdleConns: TransInterfaceToInt(runtime["maxIdleConns"]),
|
||||
Socks5Proxy: TransInterfaceToString(runtime["socks5Proxy"]),
|
||||
Socks5NetWork: TransInterfaceToString(runtime["socks5NetWork"]),
|
||||
}
|
||||
if runtime["listener"] != nil {
|
||||
runtimeObject.Listener = runtime["listener"].(ProgressListener)
|
||||
}
|
||||
if runtime["tracker"] != nil {
|
||||
runtimeObject.Tracker = runtime["tracker"].(*ReaderTracker)
|
||||
}
|
||||
if runtime["logger"] != nil {
|
||||
runtimeObject.Logger = runtime["logger"].(*Logger)
|
||||
}
|
||||
return runtimeObject
|
||||
}
|
||||
|
||||
// NewCastError is used for cast type fails
|
||||
func NewCastError(message string) (err error) {
|
||||
return &CastError{
|
||||
Message: message,
|
||||
}
|
||||
}
|
||||
|
||||
// NewRequest is used shortly create Request
|
||||
func NewRequest() (req *Request) {
|
||||
return &Request{
|
||||
Headers: map[string]string{},
|
||||
Query: map[string]string{},
|
||||
}
|
||||
}
|
||||
|
||||
// NewResponse is create response with http response
|
||||
func NewResponse(httpResponse *http.Response) (res *Response) {
|
||||
res = &Response{}
|
||||
res.Body = httpResponse.Body
|
||||
res.Headers = make(map[string]string)
|
||||
res.StatusCode = httpResponse.StatusCode
|
||||
res.StatusMessage = httpResponse.Status
|
||||
return
|
||||
}
|
||||
|
||||
// NewSDKError is used for shortly create SDKError object
|
||||
func NewSDKError(obj map[string]interface{}) *SDKError {
|
||||
err := &SDKError{}
|
||||
if val, ok := obj["code"].(int); ok {
|
||||
err.Code = strconv.Itoa(val)
|
||||
} else if val, ok := obj["code"].(string); ok {
|
||||
err.Code = val
|
||||
}
|
||||
|
||||
if obj["message"] != nil {
|
||||
err.Message = obj["message"].(string)
|
||||
}
|
||||
if data := obj["data"]; data != nil {
|
||||
byt, _ := json.Marshal(data)
|
||||
err.Data = string(byt)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Return message of CastError
|
||||
func (err *CastError) Error() string {
|
||||
return err.Message
|
||||
}
|
||||
|
||||
// Convert is use convert map[string]interface object to struct
|
||||
func Convert(in interface{}, out interface{}) error {
|
||||
byt, _ := json.Marshal(in)
|
||||
err := json.Unmarshal(byt, out)
|
||||
return err
|
||||
}
|
||||
|
||||
// ReadBody is used read response body
|
||||
func (response *Response) ReadBody() (body []byte, err error) {
|
||||
defer response.Body.Close()
|
||||
var buffer [512]byte
|
||||
result := bytes.NewBuffer(nil)
|
||||
|
||||
for {
|
||||
n, err := response.Body.Read(buffer[0:])
|
||||
result.Write(buffer[0:n])
|
||||
if err != nil && err == io.EOF {
|
||||
break
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return result.Bytes(), nil
|
||||
}
|
||||
|
||||
func getTeaClient(tag string) *teaClient {
|
||||
client, ok := clientPool.Load(tag)
|
||||
if client == nil && !ok {
|
||||
client = &teaClient{
|
||||
httpClient: &http.Client{},
|
||||
ifInit: false,
|
||||
}
|
||||
clientPool.Store(tag, client)
|
||||
}
|
||||
return client.(*teaClient)
|
||||
}
|
||||
|
||||
// DoRequest is used send request to server
|
||||
func DoRequest(request *Request, requestRuntime map[string]interface{}) (response *Response, err error) {
|
||||
runtimeObject := NewRuntimeObject(requestRuntime)
|
||||
fieldMap := make(map[string]string)
|
||||
InitLogMsg(fieldMap)
|
||||
defer func() {
|
||||
if runtimeObject.Logger != nil {
|
||||
runtimeObject.Logger.PrintLog(fieldMap, err)
|
||||
}
|
||||
}()
|
||||
if request.Method == "" {
|
||||
request.Method = "GET"
|
||||
}
|
||||
|
||||
if request.Protocol == "" {
|
||||
request.Protocol = "http"
|
||||
} else {
|
||||
request.Protocol = strings.ToLower(request.Protocol)
|
||||
}
|
||||
|
||||
if request.Protocol == "http" {
|
||||
request.Port = 80
|
||||
} else if request.Protocol == "https" {
|
||||
request.Port = 443
|
||||
}
|
||||
|
||||
requestURL := ""
|
||||
request.Domain = request.Headers["host"]
|
||||
matched, _ := regexp.MatchString(":", request.Domain)
|
||||
if matched {
|
||||
requestURL = fmt.Sprintf("%s://%s%s", request.Protocol, request.Domain, request.Pathname)
|
||||
} else {
|
||||
requestURL = fmt.Sprintf("%s://%s:%d%s", request.Protocol, request.Domain, request.Port, request.Pathname)
|
||||
}
|
||||
queryParams := request.Query
|
||||
// sort QueryParams by key
|
||||
q := url.Values{}
|
||||
for key, value := range queryParams {
|
||||
q.Add(key, value)
|
||||
}
|
||||
querystring := q.Encode()
|
||||
if len(querystring) > 0 {
|
||||
if strings.Contains(requestURL, "?") {
|
||||
requestURL = fmt.Sprintf("%s&%s", requestURL, querystring)
|
||||
} else {
|
||||
requestURL = fmt.Sprintf("%s?%s", requestURL, querystring)
|
||||
}
|
||||
}
|
||||
debugLog("> %s %s", request.Method, requestURL)
|
||||
|
||||
httpRequest, err := http.NewRequest(request.Method, requestURL, request.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
httpRequest.Host = request.Domain
|
||||
|
||||
client := getTeaClient(runtimeObject.getClientTag(request.Domain))
|
||||
client.Lock()
|
||||
if !client.ifInit {
|
||||
trans, err := getHttpTransport(request, runtimeObject)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client.httpClient.Timeout = time.Duration(runtimeObject.ConnectTimeout) * time.Second
|
||||
client.httpClient.Transport = trans
|
||||
client.ifInit = true
|
||||
}
|
||||
client.Unlock()
|
||||
for key, value := range request.Headers {
|
||||
if value == "" || key == "content-length" {
|
||||
continue
|
||||
} else if key == "host" {
|
||||
httpRequest.Header["Host"] = []string{value}
|
||||
} else {
|
||||
httpRequest.Header[key] = []string{value}
|
||||
}
|
||||
debugLog("> %s: %s", key, value)
|
||||
}
|
||||
contentlength, _ := strconv.Atoi(request.Headers["content-length"])
|
||||
event := NewProgressEvent(TransferStartedEvent, 0, int64(contentlength), 0)
|
||||
PublishProgress(runtimeObject.Listener, event)
|
||||
|
||||
putMsgToMap(fieldMap, httpRequest)
|
||||
startTime := time.Now()
|
||||
fieldMap["{start_time}"] = startTime.Format("2006-01-02 15:04:05")
|
||||
res, err := hookDo(client.httpClient.Do)(httpRequest)
|
||||
fieldMap["{cost}"] = time.Since(startTime).String()
|
||||
completedBytes := int64(0)
|
||||
if runtimeObject.Tracker != nil {
|
||||
completedBytes = runtimeObject.Tracker.CompletedBytes
|
||||
}
|
||||
if err != nil {
|
||||
event = NewProgressEvent(TransferFailedEvent, completedBytes, int64(contentlength), 0)
|
||||
PublishProgress(runtimeObject.Listener, event)
|
||||
return
|
||||
}
|
||||
|
||||
event = NewProgressEvent(TransferCompletedEvent, completedBytes, int64(contentlength), 0)
|
||||
PublishProgress(runtimeObject.Listener, event)
|
||||
|
||||
response = NewResponse(res)
|
||||
fieldMap["{code}"] = strconv.Itoa(res.StatusCode)
|
||||
fieldMap["{res_headers}"] = TransToString(res.Header)
|
||||
debugLog("< HTTP/1.1 %s", res.Status)
|
||||
for key, value := range res.Header {
|
||||
debugLog("< %s: %s", key, strings.Join(value, ""))
|
||||
if len(value) != 0 {
|
||||
response.Headers[strings.ToLower(key)] = value[0]
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getHttpTransport(req *Request, runtime *RuntimeObject) (*http.Transport, error) {
|
||||
trans := new(http.Transport)
|
||||
httpProxy, err := getHttpProxy(req.Protocol, req.Domain, runtime)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
trans.TLSClientConfig = &tls.Config{
|
||||
InsecureSkipVerify: runtime.IgnoreSSL,
|
||||
}
|
||||
if httpProxy != nil {
|
||||
trans.Proxy = http.ProxyURL(httpProxy)
|
||||
if httpProxy.User != nil {
|
||||
password, _ := httpProxy.User.Password()
|
||||
auth := httpProxy.User.Username() + ":" + password
|
||||
basic := "Basic " + base64.StdEncoding.EncodeToString([]byte(auth))
|
||||
req.Headers["Proxy-Authorization"] = basic
|
||||
}
|
||||
}
|
||||
if runtime.Socks5Proxy != "" {
|
||||
socks5Proxy, err := getSocks5Proxy(runtime)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if socks5Proxy != nil {
|
||||
var auth *proxy.Auth
|
||||
if socks5Proxy.User != nil {
|
||||
password, _ := socks5Proxy.User.Password()
|
||||
auth = &proxy.Auth{
|
||||
User: socks5Proxy.User.Username(),
|
||||
Password: password,
|
||||
}
|
||||
}
|
||||
dialer, err := proxy.SOCKS5(strings.ToLower(runtime.Socks5NetWork), socks5Proxy.String(), auth,
|
||||
&net.Dialer{
|
||||
Timeout: time.Duration(runtime.ConnectTimeout) * time.Second,
|
||||
DualStack: true,
|
||||
LocalAddr: getLocalAddr(runtime.LocalAddr, req.Port),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
trans.Dial = dialer.Dial
|
||||
}
|
||||
} else {
|
||||
trans.DialContext = setDialContext(runtime, req.Port)
|
||||
}
|
||||
return trans, nil
|
||||
}
|
||||
|
||||
func TransToString(object interface{}) string {
|
||||
byt, _ := json.Marshal(object)
|
||||
return string(byt)
|
||||
}
|
||||
|
||||
func putMsgToMap(fieldMap map[string]string, request *http.Request) {
|
||||
fieldMap["{host}"] = request.Host
|
||||
fieldMap["{method}"] = request.Method
|
||||
fieldMap["{uri}"] = request.URL.RequestURI()
|
||||
fieldMap["{pid}"] = strconv.Itoa(os.Getpid())
|
||||
fieldMap["{version}"] = strings.Split(request.Proto, "/")[1]
|
||||
hostname, _ := os.Hostname()
|
||||
fieldMap["{hostname}"] = hostname
|
||||
fieldMap["{req_headers}"] = TransToString(request.Header)
|
||||
fieldMap["{target}"] = request.URL.Path + request.URL.RawQuery
|
||||
}
|
||||
|
||||
func getNoProxy(protocol string, runtime *RuntimeObject) []string {
|
||||
var urls []string
|
||||
if runtime.NoProxy != "" {
|
||||
urls = strings.Split(runtime.NoProxy, ",")
|
||||
} else if rawurl := os.Getenv("NO_PROXY"); rawurl != "" {
|
||||
urls = strings.Split(rawurl, ",")
|
||||
} else if rawurl := os.Getenv("no_proxy"); rawurl != "" {
|
||||
urls = strings.Split(rawurl, ",")
|
||||
}
|
||||
|
||||
return urls
|
||||
}
|
||||
|
||||
func ToReader(obj interface{}) io.Reader {
|
||||
switch obj.(type) {
|
||||
case string:
|
||||
return strings.NewReader(obj.(string))
|
||||
case []byte:
|
||||
return strings.NewReader(string(obj.([]byte)))
|
||||
case io.Reader:
|
||||
return obj.(io.Reader)
|
||||
default:
|
||||
panic("Invalid Body. Please set a valid Body.")
|
||||
}
|
||||
}
|
||||
|
||||
func ToString(val interface{}) string {
|
||||
return fmt.Sprintf("%v", val)
|
||||
}
|
||||
|
||||
func getHttpProxy(protocol, host string, runtime *RuntimeObject) (proxy *url.URL, err error) {
|
||||
urls := getNoProxy(protocol, runtime)
|
||||
for _, url := range urls {
|
||||
if url == host {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
if protocol == "https" {
|
||||
if runtime.HttpsProxy != "" {
|
||||
proxy, err = url.Parse(runtime.HttpsProxy)
|
||||
} else if rawurl := os.Getenv("HTTPS_PROXY"); rawurl != "" {
|
||||
proxy, err = url.Parse(rawurl)
|
||||
} else if rawurl := os.Getenv("https_proxy"); rawurl != "" {
|
||||
proxy, err = url.Parse(rawurl)
|
||||
}
|
||||
} else {
|
||||
if runtime.HttpProxy != "" {
|
||||
proxy, err = url.Parse(runtime.HttpProxy)
|
||||
} else if rawurl := os.Getenv("HTTP_PROXY"); rawurl != "" {
|
||||
proxy, err = url.Parse(rawurl)
|
||||
} else if rawurl := os.Getenv("http_proxy"); rawurl != "" {
|
||||
proxy, err = url.Parse(rawurl)
|
||||
}
|
||||
}
|
||||
|
||||
return proxy, err
|
||||
}
|
||||
|
||||
func getSocks5Proxy(runtime *RuntimeObject) (proxy *url.URL, err error) {
|
||||
if runtime.Socks5Proxy != "" {
|
||||
proxy, err = url.Parse(runtime.Socks5Proxy)
|
||||
}
|
||||
return proxy, err
|
||||
}
|
||||
|
||||
func getLocalAddr(localAddr string, port int) (addr *net.TCPAddr) {
|
||||
if localAddr != "" {
|
||||
addr = &net.TCPAddr{
|
||||
Port: port,
|
||||
IP: []byte(localAddr),
|
||||
}
|
||||
}
|
||||
return addr
|
||||
}
|
||||
|
||||
func setDialContext(runtime *RuntimeObject, port int) func(cxt context.Context, net, addr string) (c net.Conn, err error) {
|
||||
return func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
if runtime.LocalAddr != "" {
|
||||
netAddr := &net.TCPAddr{
|
||||
Port: port,
|
||||
IP: []byte(runtime.LocalAddr),
|
||||
}
|
||||
return (&net.Dialer{
|
||||
Timeout: time.Duration(runtime.ConnectTimeout) * time.Second,
|
||||
DualStack: true,
|
||||
LocalAddr: netAddr,
|
||||
}).DialContext(ctx, network, address)
|
||||
}
|
||||
return (&net.Dialer{
|
||||
Timeout: time.Duration(runtime.ConnectTimeout) * time.Second,
|
||||
DualStack: true,
|
||||
}).DialContext(ctx, network, address)
|
||||
}
|
||||
}
|
||||
|
||||
func (err *SDKError) Error() string {
|
||||
return fmt.Sprintf("SDKError: %s %s %s", err.Code, err.Message, err.Data)
|
||||
}
|
||||
|
||||
func ToObject(obj interface{}) map[string]interface{} {
|
||||
result := make(map[string]interface{})
|
||||
byt, _ := json.Marshal(obj)
|
||||
err := json.Unmarshal(byt, &result)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func AllowRetry(retry interface{}, retryTimes int) bool {
|
||||
if retryTimes == 0 {
|
||||
return true
|
||||
}
|
||||
retryMap, ok := retry.(map[string]interface{})
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
retryable, ok := retryMap["retryable"].(bool)
|
||||
if !ok || !retryable {
|
||||
return false
|
||||
}
|
||||
|
||||
maxAttempts, ok := retryMap["maxAttempts"].(int)
|
||||
if !ok || maxAttempts < retryTimes {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func Merge(args ...interface{}) map[string]string {
|
||||
finalArg := make(map[string]string)
|
||||
for _, obj := range args {
|
||||
switch obj.(type) {
|
||||
case map[string]string:
|
||||
arg := obj.(map[string]string)
|
||||
for key, value := range arg {
|
||||
if value != "" {
|
||||
finalArg[key] = value
|
||||
}
|
||||
}
|
||||
default:
|
||||
byt, _ := json.Marshal(obj)
|
||||
arg := make(map[string]string)
|
||||
err := json.Unmarshal(byt, &arg)
|
||||
if err != nil {
|
||||
return finalArg
|
||||
}
|
||||
for key, value := range arg {
|
||||
if value != "" {
|
||||
finalArg[key] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return finalArg
|
||||
}
|
||||
|
||||
func isNil(a interface{}) bool {
|
||||
defer func() {
|
||||
recover()
|
||||
}()
|
||||
vi := reflect.ValueOf(a)
|
||||
return vi.IsNil()
|
||||
}
|
||||
|
||||
func ToMap(args ...interface{}) map[string]interface{} {
|
||||
isNotNil := false
|
||||
finalArg := make(map[string]interface{})
|
||||
for _, obj := range args {
|
||||
if obj == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if isNil(obj) {
|
||||
continue
|
||||
}
|
||||
isNotNil = true
|
||||
|
||||
switch obj.(type) {
|
||||
case map[string]string:
|
||||
arg := obj.(map[string]string)
|
||||
for key, value := range arg {
|
||||
if value != "" {
|
||||
finalArg[key] = value
|
||||
}
|
||||
}
|
||||
case map[string]interface{}:
|
||||
arg := obj.(map[string]interface{})
|
||||
for key, value := range arg {
|
||||
if value != nil {
|
||||
finalArg[key] = value
|
||||
}
|
||||
}
|
||||
case string:
|
||||
str := obj.(string)
|
||||
arg := make(map[string]interface{})
|
||||
err := json.Unmarshal([]byte(str), &arg)
|
||||
if err == nil {
|
||||
for key, value := range arg {
|
||||
if value != nil {
|
||||
finalArg[key] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
tmp := make(map[string]string)
|
||||
err = json.Unmarshal([]byte(str), &tmp)
|
||||
if err == nil {
|
||||
for key, value := range arg {
|
||||
if value != "" {
|
||||
finalArg[key] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
case []byte:
|
||||
byt := obj.([]byte)
|
||||
arg := make(map[string]interface{})
|
||||
err := json.Unmarshal(byt, &arg)
|
||||
if err == nil {
|
||||
for key, value := range arg {
|
||||
if value != nil {
|
||||
finalArg[key] = value
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
default:
|
||||
val := reflect.ValueOf(obj)
|
||||
res := structToMap(val)
|
||||
for key, value := range res {
|
||||
if value != nil {
|
||||
finalArg[key] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !isNotNil {
|
||||
return nil
|
||||
}
|
||||
return finalArg
|
||||
}
|
||||
|
||||
func structToMap(dataValue reflect.Value) map[string]interface{} {
|
||||
out := make(map[string]interface{})
|
||||
if !dataValue.IsValid() {
|
||||
return out
|
||||
}
|
||||
if dataValue.Kind().String() == "ptr" {
|
||||
dataValue = dataValue.Elem()
|
||||
}
|
||||
if !dataValue.IsValid() {
|
||||
return out
|
||||
}
|
||||
dataType := dataValue.Type()
|
||||
if dataType.Kind().String() != "struct" {
|
||||
return out
|
||||
}
|
||||
for i := 0; i < dataType.NumField(); i++ {
|
||||
field := dataType.Field(i)
|
||||
name, containsNameTag := field.Tag.Lookup("json")
|
||||
if !containsNameTag {
|
||||
name = field.Name
|
||||
}
|
||||
fieldValue := dataValue.FieldByName(field.Name)
|
||||
if !fieldValue.IsValid() {
|
||||
continue
|
||||
}
|
||||
if field.Type.Kind().String() == "struct" {
|
||||
out[name] = structToMap(fieldValue)
|
||||
} else if field.Type.Kind().String() == "ptr" &&
|
||||
field.Type.Elem().Kind().String() == "struct" {
|
||||
if fieldValue.Elem().IsValid() {
|
||||
out[name] = structToMap(fieldValue)
|
||||
}
|
||||
} else if field.Type.Kind().String() == "ptr" {
|
||||
if fieldValue.IsValid() && !fieldValue.IsNil() {
|
||||
out[name] = fieldValue.Elem().Interface()
|
||||
}
|
||||
} else if field.Type.Kind().String() == "slice" {
|
||||
tmp := make([]interface{}, 0)
|
||||
num := fieldValue.Len()
|
||||
for i := 0; i < num; i++ {
|
||||
value := fieldValue.Index(i)
|
||||
if !value.IsValid() {
|
||||
continue
|
||||
}
|
||||
if value.Type().Kind().String() == "ptr" &&
|
||||
value.Type().Elem().Kind().String() == "struct" {
|
||||
if value.IsValid() && !value.IsNil() {
|
||||
tmp = append(tmp, structToMap(value))
|
||||
}
|
||||
} else if value.Type().Kind().String() == "struct" {
|
||||
tmp = append(tmp, structToMap(value))
|
||||
} else if value.Type().Kind().String() == "ptr" {
|
||||
if value.IsValid() && !value.IsNil() {
|
||||
tmp = append(tmp, value.Elem().Interface())
|
||||
}
|
||||
} else {
|
||||
tmp = append(tmp, value.Interface())
|
||||
}
|
||||
}
|
||||
if len(tmp) > 0 {
|
||||
out[name] = tmp
|
||||
}
|
||||
} else {
|
||||
out[name] = fieldValue.Interface()
|
||||
}
|
||||
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func Retryable(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
if realErr, ok := err.(*SDKError); ok {
|
||||
code, err := strconv.Atoi(realErr.Code)
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
return code >= http.StatusInternalServerError
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func GetBackoffTime(backoff interface{}, retrytimes int) int {
|
||||
backoffMap, ok := backoff.(map[string]interface{})
|
||||
if !ok {
|
||||
return 0
|
||||
}
|
||||
policy, ok := backoffMap["policy"].(string)
|
||||
if !ok || policy == "no" {
|
||||
return 0
|
||||
}
|
||||
|
||||
period, ok := backoffMap["period"].(int)
|
||||
if !ok || period == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
maxTime := math.Pow(2.0, float64(retrytimes))
|
||||
return rand.Intn(int(maxTime-1)) * period
|
||||
}
|
||||
|
||||
func Sleep(backoffTime int) {
|
||||
sleeptime := time.Duration(backoffTime) * time.Second
|
||||
time.Sleep(sleeptime)
|
||||
}
|
||||
|
||||
func Validate(params interface{}) error {
|
||||
requestValue := reflect.ValueOf(params).Elem()
|
||||
err := validate(requestValue)
|
||||
return err
|
||||
}
|
||||
|
||||
// Verify whether the parameters meet the requirements
|
||||
func validate(dataValue reflect.Value) error {
|
||||
if strings.HasPrefix(dataValue.Type().String(), "*") { // Determines whether the input is a structure object or a pointer object
|
||||
if dataValue.IsNil() {
|
||||
return nil
|
||||
}
|
||||
dataValue = dataValue.Elem()
|
||||
}
|
||||
dataType := dataValue.Type()
|
||||
for i := 0; i < dataType.NumField(); i++ {
|
||||
field := dataType.Field(i)
|
||||
valueField := dataValue.Field(i)
|
||||
for _, value := range validateParams {
|
||||
err := validateParam(field, valueField, value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateParam(field reflect.StructField, valueField reflect.Value, tagName string) error {
|
||||
tag, containsTag := field.Tag.Lookup(tagName) // Take out the checked regular expression
|
||||
if containsTag && tagName == "require" {
|
||||
err := checkRequire(field, valueField)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if strings.HasPrefix(field.Type.String(), "[]") { // Verify the parameters of the array type
|
||||
err := validateSlice(valueField, containsTag, tag, tagName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if valueField.Kind() == reflect.Ptr { // Determines whether it is a pointer object
|
||||
err := validatePtr(valueField, containsTag, tag, tagName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateSlice(valueField reflect.Value, containsregexpTag bool, tag, tagName string) error {
|
||||
if valueField.IsValid() && !valueField.IsNil() { // Determines whether the parameter has a value
|
||||
for m := 0; m < valueField.Len(); m++ {
|
||||
elementValue := valueField.Index(m)
|
||||
if elementValue.Type().Kind() == reflect.Ptr { // Determines whether the child elements of an array are of a basic type
|
||||
err := validatePtr(elementValue, containsregexpTag, tag, tagName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validatePtr(elementValue reflect.Value, containsregexpTag bool, tag, tagName string) error {
|
||||
if elementValue.IsNil() {
|
||||
return nil
|
||||
}
|
||||
|
||||
if isFilterType(elementValue.Elem().Type().String(), basicTypes) {
|
||||
if containsregexpTag {
|
||||
if tagName == "pattern" {
|
||||
err := checkPattern(elementValue.Elem(), tag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if tagName == "maxLength" {
|
||||
err := checkMaxLength(elementValue.Elem(), tag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err := validate(elementValue)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkRequire(field reflect.StructField, valueField reflect.Value) error {
|
||||
name, _ := field.Tag.Lookup("json")
|
||||
if !valueField.IsNil() && valueField.IsValid() {
|
||||
return nil
|
||||
}
|
||||
return errors.New(name + " should be setted")
|
||||
}
|
||||
|
||||
func checkPattern(valueField reflect.Value, tag string) error {
|
||||
if valueField.IsValid() && valueField.String() != "" {
|
||||
value := valueField.String()
|
||||
if match, _ := regexp.MatchString(tag, value); !match { // Determines whether the parameter value satisfies the regular expression or not, and throws an error
|
||||
return errors.New(value + " is not matched " + tag)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkMaxLength(valueField reflect.Value, tag string) error {
|
||||
if valueField.IsValid() && valueField.String() != "" {
|
||||
maxLength, err := strconv.Atoi(tag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
length := valueField.Len()
|
||||
if valueField.Kind().String() == "string" {
|
||||
length = strings.Count(valueField.String(), "") - 1
|
||||
}
|
||||
if maxLength < length {
|
||||
errMsg := fmt.Sprintf("Length of %s is more than %d", valueField.String(), maxLength)
|
||||
return errors.New(errMsg)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Determines whether realType is in filterTypes
|
||||
func isFilterType(realType string, filterTypes []string) bool {
|
||||
for _, value := range filterTypes {
|
||||
if value == realType {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func TransInterfaceToBool(val interface{}) bool {
|
||||
if val == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return val.(bool)
|
||||
}
|
||||
|
||||
func TransInterfaceToInt(val interface{}) int {
|
||||
if val == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return val.(int)
|
||||
}
|
||||
|
||||
func TransInterfaceToString(val interface{}) string {
|
||||
if val == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return val.(string)
|
||||
}
|
||||
|
||||
func Prettify(i interface{}) string {
|
||||
resp, _ := json.MarshalIndent(i, "", " ")
|
||||
return string(resp)
|
||||
}
|
||||
44
vendor/alipaysdk/easysdk/go/src/tea/utils.go
vendored
Normal file
44
vendor/alipaysdk/easysdk/go/src/tea/utils.go
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
package tea
|
||||
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func containsKind(kinds []reflect.Kind, kind reflect.Kind) bool {
|
||||
for i := 0; i < len(kinds); i++ {
|
||||
if kind == kinds[i] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func AssertEqual(t *testing.T, a, b interface{}) {
|
||||
if !reflect.DeepEqual(a, b) {
|
||||
t.Errorf("%v != %v", a, b)
|
||||
}
|
||||
}
|
||||
|
||||
func AssertNil(t *testing.T, object interface{}) {
|
||||
if !isNil(object) {
|
||||
t.Errorf("%v is not nil", object)
|
||||
}
|
||||
}
|
||||
|
||||
func AssertNotNil(t *testing.T, object interface{}) {
|
||||
if isNil(object) {
|
||||
t.Errorf("%v is nil", object)
|
||||
}
|
||||
}
|
||||
|
||||
func AssertContains(t *testing.T, contains string, msgAndArgs ...string) {
|
||||
for _, value := range msgAndArgs {
|
||||
if ok := strings.Contains(contains, value); !ok {
|
||||
t.Errorf("%s does not contain %s", contains, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
46
vendor/alipaysdk/easysdk/go/src/test/main.go
vendored
Normal file
46
vendor/alipaysdk/easysdk/go/src/test/main.go
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"kernel"
|
||||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
account:= kernel.Client{}
|
||||
account.Protocol = "https"
|
||||
account.GatewayHost = "openapi.alipay.com"
|
||||
account.AppId = "<-- 请填写您的AppId,例如:2019022663440152 -->"
|
||||
account.SignType = "RSA2"
|
||||
account.AlipayPublicKey = "<-- 请填写您的支付宝公钥,例如:MIIBIjANBg... -->"
|
||||
account.MerchantPrivateKey = "<-- 请填写您的应用私钥,例如:MIIEvQIBADANB ... ... -->"
|
||||
|
||||
kernel.InitClient(account)
|
||||
}
|
||||
|
||||
|
||||
func main() {
|
||||
result, _ := kernel.Execute("alipay.trade.create", nil, getBizParams(time.Now().Format("2006-01-02 15:04:05")))
|
||||
fmt.Println(result)
|
||||
}
|
||||
|
||||
func getBizParams(outTradeNo string) map[string]string {
|
||||
bizParams := map[string]string{
|
||||
"subject": "phone6 16G",
|
||||
"out_trade_no": outTradeNo,
|
||||
"total_amount": "0.10",
|
||||
"buyer_id": "2088002656718920",
|
||||
"extend_params": getHuabeiParams(),
|
||||
}
|
||||
return bizParams
|
||||
}
|
||||
|
||||
func getHuabeiParams() string {
|
||||
extendParams := map[string]string{
|
||||
"hb_fq_num": "3",
|
||||
"hb_fq_seller_percent": "3",
|
||||
}
|
||||
byt, _ := json.Marshal(extendParams)
|
||||
return string(byt)
|
||||
}
|
||||
Reference in New Issue
Block a user