|
|
@@ -0,0 +1,98 @@
|
|
|
+package order
|
|
|
+
|
|
|
+import (
|
|
|
+ "encoding/xml"
|
|
|
+ "errors"
|
|
|
+
|
|
|
+ "github.com/silenceper/wechat/v2/util"
|
|
|
+)
|
|
|
+
|
|
|
+// https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_3
|
|
|
+var closeGateway = "https://api.mch.weixin.qq.com/pay/closeorder"
|
|
|
+
|
|
|
+// CloseParams 传入的参数
|
|
|
+type CloseParams struct {
|
|
|
+ OutTradeNo string // 商户订单号
|
|
|
+ SignType string // 签名类型
|
|
|
+}
|
|
|
+
|
|
|
+// closeRequest 接口请求参数
|
|
|
+type closeRequest struct {
|
|
|
+ AppID string `xml:"appid"` // 公众账号ID
|
|
|
+ MchID string `xml:"mch_id"` // 商户号
|
|
|
+ NonceStr string `xml:"nonce_str"` // 随机字符串
|
|
|
+ Sign string `xml:"sign"` // 签名
|
|
|
+ SignType string `xml:"sign_type,omitempty"` // 签名类型
|
|
|
+ OutTradeNo string `xml:"out_trade_no"` // 商户订单号
|
|
|
+}
|
|
|
+
|
|
|
+// CloseResult 关闭订单返回结果
|
|
|
+type CloseResult struct {
|
|
|
+ ReturnCode *string `xml:"return_code"`
|
|
|
+ ReturnMsg *string `xml:"return_msg"`
|
|
|
+
|
|
|
+ AppID *string `xml:"appid" json:"appid"`
|
|
|
+ MchID *string `xml:"mch_id"`
|
|
|
+ NonceStr *string `xml:"nonce_str"`
|
|
|
+ Sign *string `xml:"sign"`
|
|
|
+ ResultCode *string `xml:"result_code"`
|
|
|
+ ResultMsg *string `xml:"result_msg"`
|
|
|
+ ErrCode *string `xml:"err_code"`
|
|
|
+ ErrCodeDes *string `xml:"err_code_des"`
|
|
|
+}
|
|
|
+
|
|
|
+// CloseOrder 关闭订单
|
|
|
+func (o *Order) CloseOrder(p *CloseParams) (closeResult CloseResult, err error) {
|
|
|
+ nonceStr := util.RandomStr(32)
|
|
|
+ // 签名类型
|
|
|
+ if p.SignType == "" {
|
|
|
+ p.SignType = "MD5"
|
|
|
+ }
|
|
|
+
|
|
|
+ params := make(map[string]string)
|
|
|
+ params["appid"] = o.AppID
|
|
|
+ params["mch_id"] = o.MchID
|
|
|
+ params["nonce_str"] = nonceStr
|
|
|
+ params["out_trade_no"] = p.OutTradeNo
|
|
|
+ params["sign_type"] = p.SignType
|
|
|
+
|
|
|
+ var (
|
|
|
+ sign string
|
|
|
+ rawRet []byte
|
|
|
+ )
|
|
|
+
|
|
|
+ sign, err = util.ParamSign(params, o.Key)
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ request := closeRequest{
|
|
|
+ AppID: o.AppID,
|
|
|
+ MchID: o.MchID,
|
|
|
+ NonceStr: nonceStr,
|
|
|
+ Sign: sign,
|
|
|
+ OutTradeNo: p.OutTradeNo,
|
|
|
+ SignType: p.SignType,
|
|
|
+ }
|
|
|
+
|
|
|
+ rawRet, err = util.PostXML(closeGateway, request)
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ err = xml.Unmarshal(rawRet, &closeResult)
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if *closeResult.ReturnCode == SUCCESS {
|
|
|
+ // close success
|
|
|
+ if *closeResult.ResultCode == SUCCESS {
|
|
|
+ err = nil
|
|
|
+ return
|
|
|
+ }
|
|
|
+ err = errors.New(*closeResult.ErrCode + *closeResult.ErrCodeDes)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ err = errors.New("[msg : xmlUnmarshalError] [rawReturn : " + string(rawRet) + "] [sign : " + sign + "]")
|
|
|
+ return
|
|
|
+}
|