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
}
fmt.Println(string(data))
fmt.Println("***********************************************")
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
}