package wechat import ( "bytes" "encoding/xml" "errors" "fmt" "git.chuangxin1.com/cx/util" ) /* 退款示例: wx2421b1c4370ec43b 10000100 6cefdb308e1e2e8aabd48cf79e546a02 1415701182 1415757673 1 1 4006252001201705123297353072 FE56DD4AA85C0EECA82C35595A69E153 //*/ // WePayRefund https://api.mch.weixin.qq.com/secapi/pay/refund type WePayRefund struct { XMLName xml.Name `xml:"xml"` AppID string `xml:"appid"` // 公众账号 ID string(32) MchID string `xml:"mch_id"` // 商户号 string(32) NonceStr string `xml:"nonce_str"` // 随机字符串 string(32) Sign string `xml:"sign"` // 签名 string(32) //SignType string `xml:"sign_type"` // 签名类型, 默认 MD5 string(32), HMAC-SHA256 和 MD5 OutTradeNo string `xml:"out_trade_no"` // 商户订单号 OutRefundNo string `xml:"out_refund_no"` // 商户退款单号 TotalFee int `xml:"total_fee"` // 订单金额 RefundFee int `xml:"refund_fee"` // 退款金额 //RefundFeeType string `xml:"refund_fee_type"` // 退款货币种类, 款货币类型,需与支付一致,或者不填。符合ISO 4217标准的三位字母代码,默认人民币:CNY NotifyURL string `xml:"notify_url"` // 退款结果通知 url, 异步接收微信支付退款结果通知的回调地址,通知URL必须为外网可访问的url,不允许带参数。如果参数中传了notify_url,则商户平台上配置的回调地址将不会生效 } // WePayRefundReply pay refund reply type WePayRefundReply struct { XMLName xml.Name `xml:"xml" json:"_,omitempty"` ReturnCode string `xml:"return_code"` ReturnMsg string `xml:"return_msg"` ResultCode string `xml:"result_code"` ErrCode string `xml:"err_code"` ErrCodeDes string `xml:"err_code_des"` AppID string `xml:"appid"` MchID string `xml:"mch_id"` NonceStr string `xml:"nonce_str"` Sign string `xml:"sign"` TransactionID string `xml:"transaction_id"` OutTradeNo string `xml:"out_trade_no"` OutRefundNo string `xml:"out_refund_no"` RefundFee int `xml:"refund_fee"` // 退款金额 TotalFee int `xml:"total_fee"` // 标价金额, 订单总金额,单位为分,只能为整数 FeeType int `xml:"fee_type"` // 退款货币种类, 款货币类型,需与支付一致,或者不填。符合ISO 4217标准的三位字母代码,默认人民币:CNY CashFee int `xml:"cash_fee"` // 现金支付金额 } // PayRefundCheck check refund reply func PayRefundCheck(reply WePayRefundReply) (ok bool, err error) { // 通信是否正确 if reply.ReturnCode == "FAIL" { err = errors.New(reply.ReturnMsg) return } // 交易是否成功 if reply.ResultCode == "FAIL" { err = errors.New(reply.ErrCodeDes) return } ok = true return } // PayRefund 退款 func PayRefund(config WePayConfig, order WePayRefund) (reply WePayRefundReply, err error) { var data []byte m := make(map[string]interface{}) m["appid"] = order.AppID m["mch_id"] = order.MchID m["nonce_str"] = order.NonceStr m["total_fee"] = order.TotalFee m["out_trade_no"] = order.OutTradeNo m["out_refund_no"] = order.OutRefundNo m["total_fee"] = order.TotalFee m["refund_fee"] = order.RefundFee m["notify_url"] = order.NotifyURL //order.SignType = `MD5` order.Sign = Sign(m, config.Key) if data, err = xml.Marshal(order); err != nil { return } fmt.Println(string(data)) url := WePayHost + WePayURLPayRefund reply, err = postRefund(url, config.SSLCert, config.SSLKey, data) bs, _ := xml.Marshal(reply) fmt.Println(string(bs)) return } func postRefund(url, cert, key string, data []byte) (reply WePayRefundReply, err error) { var ( msg util.Message headers = make(map[string]string) ) headers["Accept"] = "application/xml" headers["Content-Type"] = "application/xml; charset=utf-8" msg, err = util.Post(url, cert, key, headers, bytes.NewReader(data)) if err != nil { fmt.Println("util.Post", err) return } fmt.Println(string(msg.Body)) err = xml.Unmarshal(msg.Body, &reply) return }