From 59d1bf0e7924a74ae0e45b36a55487de14533bca Mon Sep 17 00:00:00 2001 From: leexsoft-mac Date: Thu, 26 Sep 2019 17:53:40 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=88=A4=E6=96=AD?= =?UTF-8?q?=E6=94=AF=E4=BB=98=E7=A0=81=E6=98=AF=E5=90=A6=E7=AC=A6=E5=90=88?= =?UTF-8?q?=E8=A7=84=E5=88=99=E7=9A=84=E6=96=B9=E6=B3=95=EF=BC=8C=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0http=E8=BF=9E=E6=8E=A5=E6=B1=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client.go | 19 ++++++++++++------- client_certificate.go | 25 +++++++++++++++++++------ client_request.go | 15 +++++++++------ network.go | 28 +++++++++++++++++++++++----- util.go | 25 +++++++++++++++++++++++++ wx_micropay_test.go | 6 ++++++ 6 files changed, 94 insertions(+), 24 deletions(-) diff --git a/client.go b/client.go index 70f2a01..0e988e3 100644 --- a/client.go +++ b/client.go @@ -1,13 +1,18 @@ package wechat +import ( + "net/http" +) + type Client struct { - config Config // 配置信息 - serviceType int // 服务模式 - apiKey string // API Key - certFilepath string // 证书目录 - certData []byte // 证书内容 - isProd bool // 是否是生产环境 - isMch bool // 是否是特殊的商户接口(微信找零) + config Config // 配置信息 + serviceType int // 服务模式 + apiKey string // API Key + certFilepath string // 证书目录 + certData []byte // 证书内容 + certClient *http.Client // 带证书的http连接池 + isProd bool // 是否是生产环境 + isMch bool // 是否是特殊的商户接口(微信找零) } // 是否是服务商模式 diff --git a/client_certificate.go b/client_certificate.go index 8596f9d..c2fa7eb 100644 --- a/client_certificate.go +++ b/client_certificate.go @@ -4,24 +4,26 @@ import ( "crypto/tls" "encoding/pem" "io/ioutil" + "net" "net/http" + "time" "golang.org/x/crypto/pkcs12" ) -func (c *Client) setCertData(certPath string) (transport *http.Transport) { +func (c *Client) setCertData(certPath string) { if c.certData != nil && len(c.certData) > 0 { return } certData, err := ioutil.ReadFile(certPath) if err == nil { c.certData = certData - transport = c.buildTransport() + c.certClient = c.buildClient() } return } -func (c *Client) buildTransport() (transport *http.Transport) { +func (c *Client) buildClient() (client *http.Client) { // 将pkcs12证书转成pem cert, err := c.pkc12ToPerm() if err != nil { @@ -29,9 +31,20 @@ func (c *Client) buildTransport() (transport *http.Transport) { } // tls配置 config := &tls.Config{Certificates: []tls.Certificate{cert}} - transport = &http.Transport{ - TLSClientConfig: config, - DisableCompression: true, + // 带证书的客户端 + client = &http.Client{ + Timeout: 30 * time.Second, + Transport: &http.Transport{ + IdleConnTimeout: 3 * time.Minute, + TLSHandshakeTimeout: 10 * time.Second, + DialContext: (&net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 10 * time.Minute, + DualStack: true, + }).DialContext, + TLSClientConfig: config, + DisableCompression: true, + }, } return } diff --git a/client_request.go b/client_request.go index 15c7022..fe792f0 100644 --- a/client_request.go +++ b/client_request.go @@ -2,6 +2,7 @@ package wechat import ( "encoding/json" + "errors" ) func (c *Client) buildBody(bodyObj interface{}) (body map[string]interface{}, err error) { @@ -59,12 +60,14 @@ func (c *Client) doWeChatWithCert(relativeUrl string, bodyObj interface{}) (byte if err != nil { return } - // 设置证书 - transport := c.setCertData(c.certFilepath) - if transport == nil { - return - } + // 设置证书和连接池 + c.setCertData(c.certFilepath) + // 发起请求 - bytes, err = httpPostWithCert(c.url(relativeUrl), GenerateXml(body), transport) + if c.certClient == nil { + err = errors.New("带证书的http连接池生成失败") + } else { + bytes, err = httpPostWithCert(c.url(relativeUrl), GenerateXml(body), c.certClient) + } return } diff --git a/network.go b/network.go index e11361d..d654e76 100644 --- a/network.go +++ b/network.go @@ -2,13 +2,32 @@ package wechat import ( "io/ioutil" + "net" "net/http" "strings" + "time" ) +var client *http.Client + +func init() { + client = &http.Client{ + Timeout: 30 * time.Second, + Transport: &http.Transport{ + IdleConnTimeout: 3 * time.Minute, + TLSHandshakeTimeout: 10 * time.Second, + DialContext: (&net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 10 * time.Minute, + DualStack: true, + }).DialContext, + }, + } +} + // 发送Get请求 func httpGet(url string) (body []byte, err error) { - resp, err := http.Get(url) + resp, err := client.Get(url) if err != nil { return } @@ -19,7 +38,7 @@ func httpGet(url string) (body []byte, err error) { // 发送Post请求,参数是XML格式的字符串 func httpPost(url string, xmlBody string) (body []byte, err error) { - resp, err := http.Post(url, "application/xml", strings.NewReader(xmlBody)) + resp, err := client.Post(url, "application/xml", strings.NewReader(xmlBody)) if err != nil { return } @@ -29,9 +48,8 @@ func httpPost(url string, xmlBody string) (body []byte, err error) { } // 发送带证书的Post请求,参数是XML格式的字符串 -func httpPostWithCert(url string, xmlBody string, transport *http.Transport) (body []byte, err error) { - h := &http.Client{Transport: transport} - resp, err := h.Post(url, "application/xml", strings.NewReader(xmlBody)) +func httpPostWithCert(url string, xmlBody string, client *http.Client) (body []byte, err error) { + resp, err := client.Post(url, "application/xml", strings.NewReader(xmlBody)) if err != nil { return } diff --git a/util.go b/util.go index ac0531b..b0be916 100644 --- a/util.go +++ b/util.go @@ -6,6 +6,8 @@ import ( "fmt" "math/rand" "net/url" + "strconv" + "strings" "time" ) @@ -60,3 +62,26 @@ func PKCS7UnPadding(plainText []byte) []byte { unpadding := int(plainText[length-1]) // 找到Byte数组最后的填充byte return plainText[:(length - unpadding)] // 只截取返回有效数字内的byte数组 } + +// 18位纯数字,以10、11、12、13、14、15开头 +func IsValidAuthCode(authcode string) (ok bool) { + ok = false + + if len(authcode) != 18 { + return + } + + if _, err := strconv.ParseUint(authcode, 10, 64); err != nil { + return + } + + if strings.HasPrefix(authcode, "10") || + strings.HasPrefix(authcode, "11") || + strings.HasPrefix(authcode, "12") || + strings.HasPrefix(authcode, "13") || + strings.HasPrefix(authcode, "14") || + strings.HasPrefix(authcode, "15") { + ok = true + } + return +} diff --git a/wx_micropay_test.go b/wx_micropay_test.go index 8658741..2e23481 100644 --- a/wx_micropay_test.go +++ b/wx_micropay_test.go @@ -5,6 +5,12 @@ import ( "testing" ) +func TestAuthcode(t *testing.T) { + code := "135007001630843681" + ok := IsValidAuthCode(code) + t.Logf("%s is : %v", code, ok) +} + func TestMicropay(t *testing.T) { testMicropay(t) } -- Gitee From 0d288a38fe59600cf1b9e3e4602fdd6b091ebd63 Mon Sep 17 00:00:00 2001 From: leexsoft-mac Date: Thu, 26 Sep 2019 18:30:41 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E6=A0=A1=E9=AA=8C=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E6=AD=A3=E5=88=99=E8=A1=A8=E8=BE=BE=E5=BC=8F=EF=BC=8C=E6=94=B9?= =?UTF-8?q?=E8=BF=9B=E8=AF=81=E4=B9=A6=E8=BF=9E=E6=8E=A5=E6=B1=A0=E7=9A=84?= =?UTF-8?q?=E5=86=99=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client.go | 1 - client_certificate.go | 22 +++++++++++++--------- client_request.go | 12 ++++-------- util.go | 23 +++-------------------- wx_micropay_test.go | 2 +- 5 files changed, 21 insertions(+), 39 deletions(-) diff --git a/client.go b/client.go index 0e988e3..61ea29a 100644 --- a/client.go +++ b/client.go @@ -9,7 +9,6 @@ type Client struct { serviceType int // 服务模式 apiKey string // API Key certFilepath string // 证书目录 - certData []byte // 证书内容 certClient *http.Client // 带证书的http连接池 isProd bool // 是否是生产环境 isMch bool // 是否是特殊的商户接口(微信找零) diff --git a/client_certificate.go b/client_certificate.go index c2fa7eb..e18ef3b 100644 --- a/client_certificate.go +++ b/client_certificate.go @@ -11,21 +11,25 @@ import ( "golang.org/x/crypto/pkcs12" ) -func (c *Client) setCertData(certPath string) { - if c.certData != nil && len(c.certData) > 0 { +func (c *Client) setCertData(certPath string) (err error) { + if c.certClient != nil { return } certData, err := ioutil.ReadFile(certPath) - if err == nil { - c.certData = certData - c.certClient = c.buildClient() + if err != nil { + return + } + client, err = c.buildClient(certData) + if err != nil { + return } + c.certClient = client return } -func (c *Client) buildClient() (client *http.Client) { +func (c *Client) buildClient(data []byte) (client *http.Client, err error) { // 将pkcs12证书转成pem - cert, err := c.pkc12ToPerm() + cert, err := c.pkc12ToPerm(data) if err != nil { return } @@ -49,8 +53,8 @@ func (c *Client) buildClient() (client *http.Client) { return } -func (c *Client) pkc12ToPerm() (cert tls.Certificate, err error) { - blocks, err := pkcs12.ToPEM(c.certData, c.config.MchId) +func (c *Client) pkc12ToPerm(data []byte) (cert tls.Certificate, err error) { + blocks, err := pkcs12.ToPEM(data, c.config.MchId) if err != nil { return } diff --git a/client_request.go b/client_request.go index fe792f0..c01f826 100644 --- a/client_request.go +++ b/client_request.go @@ -2,7 +2,6 @@ package wechat import ( "encoding/json" - "errors" ) func (c *Client) buildBody(bodyObj interface{}) (body map[string]interface{}, err error) { @@ -61,13 +60,10 @@ func (c *Client) doWeChatWithCert(relativeUrl string, bodyObj interface{}) (byte return } // 设置证书和连接池 - c.setCertData(c.certFilepath) - - // 发起请求 - if c.certClient == nil { - err = errors.New("带证书的http连接池生成失败") - } else { - bytes, err = httpPostWithCert(c.url(relativeUrl), GenerateXml(body), c.certClient) + if err = c.setCertData(c.certFilepath); err != nil { + return } + // 发起请求 + bytes, err = httpPostWithCert(c.url(relativeUrl), GenerateXml(body), c.certClient) return } diff --git a/util.go b/util.go index b0be916..bb67a4e 100644 --- a/util.go +++ b/util.go @@ -6,8 +6,7 @@ import ( "fmt" "math/rand" "net/url" - "strconv" - "strings" + "regexp" "time" ) @@ -65,23 +64,7 @@ func PKCS7UnPadding(plainText []byte) []byte { // 18位纯数字,以10、11、12、13、14、15开头 func IsValidAuthCode(authcode string) (ok bool) { - ok = false - - if len(authcode) != 18 { - return - } - - if _, err := strconv.ParseUint(authcode, 10, 64); err != nil { - return - } - - if strings.HasPrefix(authcode, "10") || - strings.HasPrefix(authcode, "11") || - strings.HasPrefix(authcode, "12") || - strings.HasPrefix(authcode, "13") || - strings.HasPrefix(authcode, "14") || - strings.HasPrefix(authcode, "15") { - ok = true - } + pattern := "^1[0-5][0-9]{16}$" + ok, _ = regexp.MatchString(pattern, authcode) return } diff --git a/wx_micropay_test.go b/wx_micropay_test.go index 2e23481..46a5702 100644 --- a/wx_micropay_test.go +++ b/wx_micropay_test.go @@ -6,7 +6,7 @@ import ( ) func TestAuthcode(t *testing.T) { - code := "135007001630843681" + code := "165007001630843683" ok := IsValidAuthCode(code) t.Logf("%s is : %v", code, ok) } -- Gitee