From 7074e7f8c524d566e4289bd4a35069882773bf28 Mon Sep 17 00:00:00 2001 From: blusewang Date: Tue, 7 Sep 2021 13:50:40 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81API=20Hook=EF=BC=8C=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E9=80=80=E6=AC=BE=E9=80=9A=E7=9F=A5=E5=8F=8A=E8=A7=A3?= =?UTF-8?q?=E5=AF=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- http_client_test.go | 14 ++++++++------ mch.go | 21 +++++++++++++++++++++ mch_api/structs.go | 33 +++++++++++++++++++++++++++++---- mch_req.go | 11 ++++++----- 4 files changed, 64 insertions(+), 15 deletions(-) diff --git a/http_client_test.go b/http_client_test.go index 8fbab8c..1456f9d 100644 --- a/http_client_test.go +++ b/http_client_test.go @@ -9,6 +9,7 @@ package wx import ( "bytes" "encoding/json" + "github.com/blusewang/wx/mch_api" "io/ioutil" "log" "net/http" @@ -38,11 +39,12 @@ func TestMt_RoundTrip(t *testing.T) { log.Println(string(raw), err) }) - var buf = new(bytes.Buffer) - var coder = json.NewEncoder(buf) - coder.SetEscapeHTML(false) - if err := coder.Encode(map[string]string{"a": "b"}); err != nil { - return + var mch = MchAccount{ + MchId: "", + MchKey: "", + MchSSLCert: nil, + MchSSLKey: nil, + MchRSAPublicKey: nil, } - log.Println(client().Post("https://www.baidu.com", "text/json", buf)) + mch.NewMchReq(mch_api.PayOrderQuery) } diff --git a/mch.go b/mch.go index 91b047c..b064f37 100644 --- a/mch.go +++ b/mch.go @@ -7,6 +7,7 @@ package wx import ( + "crypto/aes" "crypto/hmac" "crypto/md5" rand2 "crypto/rand" @@ -17,6 +18,7 @@ import ( "crypto/x509" "encoding/base64" "encoding/pem" + "encoding/xml" "errors" "fmt" "github.com/blusewang/wx/mch_api" @@ -93,6 +95,25 @@ func (ma MchAccount) PayNotify(pn mch_api.PayNotify) bool { return false } +// DecryptRefundNotify 验证支付成功通知 +func (ma MchAccount) DecryptRefundNotify(rn mch_api.RefundNotify) (body mch_api.RefundNotifyBody, err error) { + raw, err := base64.StdEncoding.DecodeString(rn.ReqInfo) + if err != nil { + return + } + block, err := aes.NewCipher([]byte(fmt.Sprintf("%x", md5.Sum([]byte(ma.MchKey))))) + length := len(raw) + size := block.BlockSize() + decrypted := make([]byte, len(raw)) + for bs, be := 0, size; bs < len(raw); bs, be = bs+size, be+size { + block.Decrypt(decrypted[bs:be], raw[bs:be]) + } + up := int(decrypted[length-1]) + decrypted = decrypted[:length-up] + err = xml.Unmarshal(decrypted, &body) + return +} + // RsaEncrypt 银行卡机要信息加密 func (ma MchAccount) RsaEncrypt(plain string) (out string) { block, _ := pem.Decode(ma.MchRSAPublicKey) diff --git a/mch_api/structs.go b/mch_api/structs.go index 1a93d0d..3a3f3dc 100644 --- a/mch_api/structs.go +++ b/mch_api/structs.go @@ -120,13 +120,13 @@ type PayOrderQueryRes PayNotify type PayRefundData struct { MchBase - TransactionId string `xml:"transaction_id"` - OutTradeNo string `xml:"out_trade_no"` + TransactionId string `xml:"transaction_id,omitempty"` + OutTradeNo string `xml:"out_trade_no,omitempty"` OutRefundNo string `xml:"out_refund_no"` TotalFee int64 `xml:"total_fee"` RefundFee int64 `xml:"refund_fee"` - RefundDesc string `xml:"refund_desc"` - NotifyUrl string `xml:"notify_url"` + RefundDesc string `xml:"refund_desc,omitempty"` + NotifyUrl string `xml:"notify_url,omitempty"` } type PayRefundRes struct { @@ -304,3 +304,28 @@ type PublicKeyRes struct { MchBaseResponse PubKey string `xml:"pub_key"` } + +// RefundNotify 退款状态通知消息 +type RefundNotify struct { + MchBaseResponse + MchBase + ReqInfo string `xml:"req_info"` +} + +// RefundNotifyBody 退款状态通知内容 +type RefundNotifyBody struct { + XMLName xml.Name `xml:"root"` + TransactionId string `xml:"transaction_id"` + OutTradeNo string `xml:"out_trade_no"` + RefundId string `xml:"refund_id"` + OutRefundNo string `xml:"out_refund_no"` + TotalFee int64 `xml:"total_fee"` + SettlementTotalFee int64 `xml:"settlement_total_fee,omitempty"` + RefundFee int64 `xml:"refund_fee"` + SettlementRefundFee int64 `xml:"settlement_refund_fee"` + RefundStatus string `xml:"refund_status"` + SuccessTime string `xml:"success_time,omitempty"` + RefundRecvAccount string `xml:"refund_recv_account"` + RefundAccount string `xml:"refund_account"` + RefundRequestSource string `xml:"refund_request_source"` +} diff --git a/mch_req.go b/mch_req.go index 100c6dd..3f59016 100644 --- a/mch_req.go +++ b/mch_req.go @@ -59,16 +59,17 @@ func (mr *mchReq) Bind(data interface{}) *mchReq { // Do 执行 func (mr *mchReq) Do() (err error) { - var cli http.Client + var cli = client() if mr.isPrivateClient { if privateClientCache[mr.account.MchId] != nil { - cli = *privateClientCache[mr.account.MchId] + cli = privateClientCache[mr.account.MchId] } else { - cli, err = mr.account.newPrivateClient() + _cli, err := mr.account.newPrivateClient() if err != nil { - return + return err } - privateClientCache[mr.account.MchId] = &cli + cli = &_cli + privateClientCache[mr.account.MchId] = cli } } if err = mr.sign(); err != nil {