package wechat import ( "bytes" "encoding/xml" "errors" "fmt" "git.chuangxin1.com/cx/util" ) const ( // WePayHost base host WePayHost = `https://api.mch.weixin.qq.com` // WePayURLUnifiedOrder pay 付款 WePayURLUnifiedOrder = `/pay/unifiedorder` // WePayURLUnifiedQuery order query 订单查询 WePayURLUnifiedQuery = `/pay/orderquery` // WePayURLPayRefund pay refund 退款 WePayURLPayRefund = `/secapi/pay/refund` // WePayURLPapPay 委托代扣申请扣款 WePayURLPapPay = `/pay/pappayapply` // WePayURLPapayEntrust H5 纯签约 WePayURLPapayEntrust = `/papay/h5entrustweb` // WePayTradeTypeJS JSAPI 公众号支付 WePayTradeTypeJS = `JSAPI` // WePayTradeTypeNative NATIVE 扫码支付 WePayTradeTypeNative = `NATIVE` // WePayTradeTypeAPP APP APP支付 WePayTradeTypeAPP = `APP` // WeOrderPaySuccess pay ok WeOrderPaySuccess = 0 ) // WePayConfig WeChat pay configure type WePayConfig struct { AppID string `json:"appid"` MchID string `json:"mchid"` Key string `json:"key"` AppSecret string `json:"appsecret"` SSLCert string `json:"sslcert"` SSLKey string `json:"sslkey"` ContractID string `json:"contractid"` NotifyURL string `json:"notify_url"` } // UnifiedOrder https://api.mch.weixin.qq.com/pay/unifiedorder type UnifiedOrder struct { XMLName xml.Name `xml:"xml"` AppID string `xml:"appid"` MchID string `xml:"mch_id"` Body string `xml:"body"` NonceStr string `xml:"nonce_str"` NotifyURL string `xml:"notify_url"` TradeType string `xml:"trade_type"` OpenID string `xml:"openid"` SpbillCreateIP string `xml:"spbill_create_ip"` TimeStart string `xml:"time_start"` TotalFee int `xml:"total_fee"` OutTradeNo string `xml:"out_trade_no"` Attach string `xml:"attach"` Sign string `xml:"sign"` } // OrderQuery https://api.mch.weixin.qq.com/pay/orderquery type OrderQuery struct { XMLName xml.Name `xml:"xml"` AppID string `xml:"appid"` MchID string `xml:"mch_id"` NonceStr string `xml:"nonce_str"` TransactionID string `xml:"transaction_id,omitempty"` OutTradeNo string `xml:"out_trade_no,omitempty"` Sign string `xml:"sign"` } /* 349000 SUCCESS wx84998d72abc5970a 1511843111 1534475690 27577C258DD809DCE0F8A515233494D1 SUCCESS JSAPI opCl81S2TyHPx7IJRZxc2yGrom5E {"PlaceNo":"603009","VNO":"","Start":"2018-08-17 11:14:50" Y CFT 2 CNY 1534475690957535612 20180817111506 2 4200000159201808174345835044 // */ // FormWePayNotify notify type FormWePayNotify struct { XMLName xml.Name `xml:"xml" json:"_,omitempty"` AppID string `form:"appid" xml:"appid"` Attach string `form:"attach" xml:"attach"` BankType string `form:"bank_type" xml:"bank_type"` CashFee int `form:"cash_fee" xml:"cash_fee"` FeeType string `form:"fee_type" xml:"fee_type"` MchID string `form:"mch_id" xml:"mch_id"` IsSubscribe string `form:"is_subscribe" xml:"is_subscribe"` NonceStr string `form:"nonce_str" xml:"nonce_str"` OpenID string `form:"openid" xml:"openid"` OutTradeNo string `form:"out_trade_no" xml:"out_trade_no"` ResultCode string `form:"result_code" xml:"result_code"` ReturnMsg string `form:"return_msg" xml:"return_msg"` ReturnCode string `form:"return_code" xml:"return_code"` ErrCodeDes string `form:"err_code_des" xml:"err_code_des"` ErrCode string `form:"err_code" xml:"err_code"` Sign string `form:"sign" xml:"sign"` TimeEnd string `form:"time_end" xml:"time_end"` TotalFee int `form:"total_fee" xml:"total_fee"` TradeType string `form:"trade_type" xml:"trade_type"` TransactionID string `form:"transaction_id" xml:"transaction_id"` ContractID string `form:"contract_id" xml:"contract_id"` } // WePayReply pay reply type WePayReply struct { XMLName xml.Name `xml:"xml" json:"_,omitempty"` ReturnCode string `xml:"return_code"` ReturnMsg string `xml:"return_msg"` AppID string `xml:"appid"` MchID string `xml:"mch_id"` NonceStr string `xml:"nonce_str"` Sign string `xml:"sign"` ResultCode string `xml:"result_code"` PrePayID string `xml:"prepay_id"` TradeType string `xml:"trade_type"` URL string `xml:"code_url"` ErrCode string `xml:"err_code"` ErrCodeDes string `xml:"err_code_des"` OpenID string `xml:"openid"` Attach string `xml:"attach"` IsSubscribe string `xml:"is_subscribe"` BankType string `xml:"bank_type"` CashFee string `xml:"cash_fee"` FeeType string `xml:"fee_type"` OutTradeNo string `xml:"out_trade_no"` TimeEnd string `xml:"time_end"` TotalFee string `xml:"total_fee"` TradeState string `xml:"trade_state"` TradeStateDesc string `xml:"trade_state_desc"` TransactionID string `xml:"transaction_id"` ContractID string `form:"contract_id" xml:"contract_id"` } var ( // WePayTradeState 交易状态 WePayTradeState = map[string]int{"SUCCESS": 0, "REFUND": 2, "NOTPAY": 3, "CLOSED": 4, "REVOKED": 5, "USERPAYING": 6, "PAYERROR": 7} ) // PayCheck check reply func PayCheck(reply WePayReply) (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 } // PayNotifyCheck check reply func PayNotifyCheck(reply FormWePayNotify) (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 } // PayQuery order query func PayQuery(cpyid int, config WePayConfig, order OrderQuery) (reply WePayReply, err error) { m := make(map[string]interface{}) m["appid"] = order.AppID m["mch_id"] = order.MchID m["out_trade_no"] = order.OutTradeNo m["nonce_str"] = order.NonceStr //m["transaction_id"] = order.TransactionID var ( data []byte ) order.Sign = Sign(m, config.Key) data, err = xml.Marshal(order) if err != nil { return } reply, err = post(WePayHost+WePayURLUnifiedQuery, data) return } // Pay pay func Pay(config WePayConfig, order UnifiedOrder) (reply WePayReply, err error) { m := make(map[string]interface{}) m["appid"] = order.AppID m["mch_id"] = order.MchID m["body"] = order.Body m["notify_url"] = order.NotifyURL m["trade_type"] = order.TradeType m["spbill_create_ip"] = order.SpbillCreateIP m["total_fee"] = order.TotalFee m["out_trade_no"] = order.OutTradeNo m["nonce_str"] = order.NonceStr m["attach"] = order.Attach m["time_start"] = order.TimeStart m["openid"] = order.OpenID var data []byte order.Sign = Sign(m, config.Key) if data, err = xml.Marshal(order); err != nil { return } reply, err = post(WePayHost+WePayURLUnifiedOrder, data) return } func post(url string, data []byte) (reply WePayReply, 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, "", "", headers, bytes.NewReader(data)) if err != nil { return } fmt.Println("************Response************") fmt.Println(string(msg.Body)) fmt.Println("************ResponseEnd************") err = xml.Unmarshal(msg.Body, &reply) return }