|
|
- package wechat
-
- import (
- "encoding/xml"
- "errors"
- "fmt"
- "log"
- "reflect"
- "strings"
-
- "git.tetele.net/tgo/network"
-
- "git.tetele.net/tgo/helper"
- )
-
- //请求支付
- type PayXml struct {
- XMLName xml.Name `xml:"xml"`
- Appid string `xml:"appid"`
- MchId string `xml:"mch_id"`
- DeviceInfo string `xml:"device_info"`
- NonceStr string `xml:"nonce_str"`
- Sign string `xml:"sign"`
- Body string `xml:"body"`
- OutTradeNo string `xml:"out_trade_no"`
- TotalFee int `xml:"total_fee"`
- SpbillCreateIp string `xml:"spbill_create_ip"`
- AuthCode string `xml:"auth_code"`
- }
-
- //支付结果
- type PayReturnXml struct {
- ReturnCode string `xml:"return_code"`
- ReturnMsg string `xml:"return_msg"`
- Appid string `xml:"appid"`
- MchId string `xml:"mch_id"`
- DeviceInfo string `xml:"device_info"`
- NonceStr string `xml:"nonce_str"`
- Sign string `xml:"sign"`
- ResultCode string `xml:"result_code"`
- ErrCode string `xml:"err_code"`
- ErrCodeDes string `xml:"err_code_des"`
- Openid string `xml:"openid"`
- IsSubscribe string `xml:"is_subscribe"`
- TradeType string `xml:"trade_type"`
- BankType string `xml:"bank_type"`
- FeeType string `xml:"fee_type"`
- TotalFee string `xml:"total_fee"`
- SettlementTotalFee string `xml:"settlement_total_fee"`
- CouponFee string `xml:"coupon_fee"`
- CashFeeType string `xml:"cash_fee_type"`
- CashFee string `xml:"cash_fee"`
- TransactionId string `xml:"transaction_id"`
- OutTradeNo string `xml:"out_trade_no"`
- Attach string `xml:"attach"`
- TimeEnd string `xml:"time_end"`
- PromotionDetail string `xml:"promotion_detail"`
- }
-
- //查询支付
- type QueryXml struct {
- XMLName xml.Name `xml:"xml"`
- Appid string `xml:"appid"`
- MchId string `xml:"mch_id"`
- OutTradeNo string `xml:"out_trade_no"`
- NonceStr string `xml:"nonce_str"`
- Sign string `xml:"sign"`
- }
-
- //查询结果
- type QueryReturnXml struct {
- 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"`
- ErrCode string `xml:"err_code"`
- ErrCodeDes string `xml:"err_code_des"`
- DeviceInfo string `xml:"device_info"`
- Openid string `xml:"openid"`
- IsSubscribe string `xml:"is_subscribe"`
- TradeType string `xml:"trade_type"`
- TradeState string `xml:"trade_state"`
- BankType string `xml:"bank_type"`
- TotalFee string `xml:"total_fee"`
- SettlementTotalFee string `xml:"settlement_total_fee"`
- FeeType string `xml:"fee_type"`
- CashFee string `xml:"cash_fee"`
- CashFeeType string `xml:"cash_fee_type"`
- CouponFee string `xml:"coupon_fee"`
- CouponCount string `xml:"coupon_count"`
- TransactionId string `xml:"transaction_id"`
- OutTradeNo string `xml:"out_trade_no"`
- Attach string `xml:"attach"`
- TimeEnd string `xml:"time_end"`
- TradeStateDesc string `xml:"trade_state_desc"`
- }
-
- // 撤消
- type ReverseXml struct {
- XMLName xml.Name `xml:"xml"`
- Appid string `xml:"appid"`
- MchId string `xml:"mch_id"`
- OutTradeNo string `xml:"out_trade_no"`
- NonceStr string `xml:"nonce_str"`
- Sign string `xml:"sign"`
- }
-
- //撤消结果
- type ReverseReturnXml struct {
- 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"`
- ErrCode string `xml:"err_code"`
- ErrCodeDes string `xml:"err_code_des"`
- Recall string `xml:"recall"`
- }
-
- /**
- * 微信二维码支付
- * 2022/02/07
- * @param device_info 设备号
- * @param body 商品描述
- * @param out_trade_no 商户订单号
- * @param total_fee 订单金额
- * @param auth_code 付款码
- */
-
- func MicroPay(appid, mchid, mch_key, device_info, body, out_trade_no, auth_code, total_fee string) (PayReturnXml, error) {
-
- log.Println("wechat micropay")
-
- var requestxml PayXml
-
- var retXml PayReturnXml
-
- requestxml.Appid = appid
- requestxml.MchId = mchid
- requestxml.DeviceInfo = device_info
- requestxml.NonceStr = helper.GetRandomString(30)
- requestxml.Body = body
- requestxml.OutTradeNo = out_trade_no
- requestxml.TotalFee = helper.ToInt(helper.FloatMul(total_fee, 100))
- requestxml.SpbillCreateIp = network.GetLocalIp()
- requestxml.AuthCode = auth_code
-
- signStr := helper.StringJoin("appid=", requestxml.Appid, "&auth_code=", requestxml.AuthCode,
- "&body=", requestxml.Body, "&device_info=", requestxml.DeviceInfo,
- "&mch_id=", requestxml.MchId, "&nonce_str=", requestxml.NonceStr,
- "&out_trade_no=", requestxml.OutTradeNo, "&spbill_create_ip=", requestxml.SpbillCreateIp,
- "&total_fee=", helper.ToString(requestxml.TotalFee), "&key=", mch_key)
-
- signMd5 := Md5Str(signStr)
-
- requestxml.Sign = strings.ToUpper(signMd5)
-
- reqXmlJson, err := xml.Marshal(requestxml)
-
- log.Println(requestxml, string(reqXmlJson), err)
-
- url := "https://api.mch.weixin.qq.com/pay/micropay"
- ret, err := network.SendXml("POST", url, requestxml)
-
- log.Println("wechat micropay pay result:", string(ret), err)
-
- if err != nil {
- log.Println("Err:", err)
- return retXml, errors.New("微信支付失败,请检查网络")
- }
-
- err = xml.Unmarshal(ret, &retXml)
- if err != nil {
- log.Println("xml Unmarshal Err:", retXml, err)
- return retXml, errors.New("未知的支付结果")
- }
-
- if retXml.ResultCode == "SUCCESS" {
-
- retMap := XmlStructToMap(retXml)
-
- //验证sign
- signStr = helper.HttpBuildQuery(retMap) + "&key=" + mch_key
-
- sign := strings.ToUpper(Md5Str(signStr))
-
- if sign != retXml.Sign {
- log.Println("Err:签名错误", string(ret), sign)
- return retXml, errors.New("支付结果签名错误")
- }
- } else {
- return retXml, errors.New(retXml.ReturnMsg)
- }
-
- return retXml, nil
- }
-
- func MicroPayQuery(appid, mchid, out_trade_no, mch_key string) (QueryReturnXml, error) {
-
- log.Println("wechat micropay query", out_trade_no)
-
- var requestxml QueryXml
-
- var retXml QueryReturnXml
-
- requestxml.Appid = appid
- requestxml.MchId = mchid
- requestxml.NonceStr = helper.GetRandomString(30)
- requestxml.OutTradeNo = out_trade_no
-
- signStr := helper.StringJoin("appid=", requestxml.Appid,
- "&mch_id=", requestxml.MchId, "&nonce_str=", requestxml.NonceStr,
- "&out_trade_no=", requestxml.OutTradeNo, "&key=", mch_key)
-
- signMd5 := Md5Str(signStr)
-
- requestxml.Sign = strings.ToUpper(signMd5)
-
- url := "https://api.mch.weixin.qq.com/pay/orderquery"
- ret, err := network.SendXml("POST", url, requestxml)
-
- if err != nil {
- log.Println("Err:", err)
- return retXml, errors.New("微信支付失败,请检查网络")
- }
-
- err = xml.Unmarshal(ret, &retXml)
- if err != nil {
- log.Println("xml Unmarshal Err:", retXml, err)
- return retXml, errors.New("未知的支付结果")
- }
-
- if retXml.ReturnCode == "SUCCESS" {
-
- retMap := XmlStructToMap(retXml)
-
- //验证sign
- signStr = helper.HttpBuildQuery(retMap) + "&key=" + mch_key
-
- sign := strings.ToUpper(Md5Str(signStr))
-
- if sign != retXml.Sign {
- log.Println("Err:签名错误", string(ret), sign)
- return retXml, errors.New("查询支付结果签名错误")
- }
- } else {
- return retXml, errors.New(retXml.ReturnMsg)
- }
- return retXml, nil
- }
-
- /**
- * 撤消订单
- * 2023/06/13
- */
- func MicroPayReverse(appid, mchid, out_trade_no, mch_key string) (ReverseReturnXml, error) {
-
- log.Println("wechat micropay reverse", out_trade_no)
-
- var requestxml ReverseXml
-
- var retXml ReverseReturnXml
-
- requestxml.Appid = appid
- requestxml.MchId = mchid
- requestxml.NonceStr = helper.GetRandomString(30)
- requestxml.OutTradeNo = out_trade_no
-
- signStr := helper.StringJoin("appid=", requestxml.Appid,
- "&mch_id=", requestxml.MchId, "&nonce_str=", requestxml.NonceStr,
- "&out_trade_no=", requestxml.OutTradeNo, "&key=", mch_key)
-
- signMd5 := Md5Str(signStr)
-
- requestxml.Sign = strings.ToUpper(signMd5)
-
- url := "https://api.mch.weixin.qq.com/secapi/pay/reverse"
- ret, err := network.SendXml("POST", url, requestxml)
-
- if err != nil {
- log.Println("Err:", err)
- return retXml, errors.New("撤消微信支付失败,请检查网络")
- }
-
- err = xml.Unmarshal(ret, &retXml)
- if err != nil {
- log.Println("xml Unmarshal Err:", retXml, err)
- return retXml, errors.New("未知的撤消结果")
- }
-
- if retXml.ReturnCode == "SUCCESS" {
-
- retMap := XmlStructToMap(retXml)
-
- //验证sign
- signStr = helper.HttpBuildQuery(retMap) + "&key=" + mch_key
-
- sign := strings.ToUpper(Md5Str(signStr))
-
- if sign != retXml.Sign {
- log.Println("Err:签名错误", string(ret), sign)
- return retXml, errors.New("查询支付结果签名错误")
- }
-
- } else {
- return retXml, errors.New(retXml.ReturnMsg)
- }
- return retXml, nil
- }
-
- func XmlStructToMap(retXml interface{}) map[string]string {
-
- t := reflect.TypeOf(retXml)
- v := reflect.ValueOf(retXml)
-
- //转为map,验签
- retMap := make(map[string]string)
- var retValue string
- var tag string
- for k := 0; k < t.NumField(); k++ {
- if t.Field(k).Name != "Sign" {
- retValue = helper.ToString(v.Field(k).Interface())
- tag = fmt.Sprintf("%s", t.Field(k).Tag)
- tag = strings.ReplaceAll(tag, "xml:", "")
- tag = strings.ReplaceAll(tag, "\"", "")
- retMap[tag] = retValue
- }
- }
-
- return retMap
- }
|