diff --git a/controller/base.go b/controller/base.go index 8ba771c..e19a1df 100644 --- a/controller/base.go +++ b/controller/base.go @@ -81,6 +81,23 @@ func Resp(c *gin.Context, code int, msg string, data interface{}) { c.Abort() } +func RespNotice(c *gin.Context, code string, msg string) { + result := struct { + Code string `json:"code"` + Message string `json:"message"` + }{ + Code: code, + Message: msg, + } + body, err := json.Marshal(result) + if err != nil { + logger.Error(err) + body = []byte{} + } + c.Data(status.OK, "application/json; charset=utf-8", body) + c.Abort() +} + func RespBodyXML(c *gin.Context, data interface{}) { body, err := xml.Marshal(data) if err != nil { diff --git a/controller/game_card.go b/controller/game_card.go index db94724..f872539 100644 --- a/controller/game_card.go +++ b/controller/game_card.go @@ -1,14 +1,19 @@ package controller import ( + "context" "crypto/md5" "encoding/json" "encoding/xml" - "errors" "fmt" "github.com/codinl/go-logger" "github.com/gin-gonic/gin" "github.com/rs/zerolog/log" + "github.com/wechatpay-apiv3/wechatpay-go/core/auth/verifiers" + "github.com/wechatpay-apiv3/wechatpay-go/core/downloader" + "github.com/wechatpay-apiv3/wechatpay-go/core/notify" + "github.com/wechatpay-apiv3/wechatpay-go/services/payments" + wechatpayutils "github.com/wechatpay-apiv3/wechatpay-go/utils" "io/ioutil" "mh-server/config" aliyun "mh-server/lib/ali" @@ -289,35 +294,42 @@ func PushWXPayNotice(c *gin.Context) { logger.Error("err:", err) // 库存不足取消订单 orderSn := model.GetOrderSn() - err = model.UserOpenMemberRecord{Uid: uint32(order.Uid), OpenNo: orderSn, OrderId: order.ID, OrderType: 2}.Insert() + memberRecord := &model.UserOpenMemberRecord{OpenNo: orderSn, OrderType: 2, Order: &order} + err = memberRecord.OrderRefund(notify.OutTradeNo) if err != nil { - logger.Error(errors.New("WebPay err")) - //RespJson(c, status.InternalServerError, nil) + logger.Error("err:", err) return } - orderRefund := wxpay.OrderRefund{ - //OutTradeNo: outTradeNo, - OutTradeNo: notify.OutTradeNo, - OutRefundNo: orderSn, - NotifyUrl: "", - Amount: wxpay.OrderRefundAmount{ - Refund: order.PayPrice, - Total: order.PayPrice, - Currency: "CNY", - }, - } - bytes, _ := json.Marshal(order) - fmt.Println("订单取消:", string(bytes)) - orderRefundJson, _ := json.Marshal(&orderRefund) - fmt.Println("订单取消 orderRefundJson:", string(orderRefundJson)) - //err = wxpay.WxPayOrderRefund(orderRefund) - err = wxpay.TransactionOrderRefund(orderRefund) - if err != nil { - logger.Error("err:", err) - //RespJson(c, status.InternalServerError, nil) - return - } + //err = model.UserOpenMemberRecord{Uid: uint32(order.Uid), OpenNo: orderSn, OrderId: order.ID, OrderType: 2}.Insert() + //if err != nil { + // logger.Error(errors.New("WebPay err")) + // //RespJson(c, status.InternalServerError, nil) + // return + //} + // + //orderRefund := wxpay.OrderRefund{ + // //OutTradeNo: outTradeNo, + // OutTradeNo: notify.OutTradeNo, + // OutRefundNo: orderSn, + // NotifyUrl: "", + // Amount: wxpay.OrderRefundAmount{ + // Refund: order.PayPrice, + // Total: order.PayPrice, + // Currency: "CNY", + // }, + //} + ////bytes, _ := json.Marshal(order) + ////fmt.Println("订单取消:", string(bytes)) + ////orderRefundJson, _ := json.Marshal(&orderRefund) + ////fmt.Println("订单取消 orderRefundJson:", string(orderRefundJson)) + //////err = wxpay.WxPayOrderRefund(orderRefund) + //err = wxpay.TransactionOrderRefund(orderRefund) + //if err != nil { + // logger.Error("err:", err) + // //RespJson(c, status.InternalServerError, nil) + // return + //} _, err := model.NewOrderQuerySet(model.DB).IDEq(order.ID).GetUpdater().SetCardStatus(OrderCardStatusCancel).UpdateNum() if err != nil { @@ -342,6 +354,7 @@ func PushWXPayNotice(c *gin.Context) { fundRecord.Uid = uint32(order.Uid) fundRecord.FundType = model.FundTypeExpressFee + fundRecord.Remark = "借卡邮费" //count, err := model.NewOrderQuerySet(model.DB).UidEq(order.Uid).IDEq(order.ID).Count() //if err != nil { // logger.Error("err:", err) @@ -678,6 +691,102 @@ func PushWXPayNotice(c *gin.Context) { RespBodyXML(c, ret) } +type WxPayRefundPlaintext struct { + Mchid string `json:"mchid"` + OutTradeNo string `json:"out_trade_no"` + TransactionId string `json:"transaction_id"` + OutRefundNo string `json:"out_refund_no"` + RefundId string `json:"refund_id"` + RefundStatus string `json:"refund_status"` + SuccessTime time.Time `json:"success_time"` + Amount struct { + Total int `json:"total"` + Refund int `json:"refund"` + PayerTotal int `json:"payer_total"` + PayerRefund int `json:"payer_refund"` + } `json:"amount"` + UserReceivedAccount string `json:"user_received_account"` +} + +// 0 元购 微信推送支付通知 +func PushWXPayRefundNotice(c *gin.Context) { + fmt.Println("微信推送支付通知") + //body, err := ioutil.ReadAll(c.Request.Body) + //if err != nil { + // logger.Error(err) + //} + mchID := "1609877389" + mchAPIv3Key := "DeovoMingHuiRengTianTang45675123" // 商户APIv3密钥 + mchCertificateSerialNumber := "7540301D8FD52CCF7D6267DCF7CD2BC0AB467EFF" // 商户证书序列号 + + mchPrivateKey, err := wechatpayutils.LoadPrivateKeyWithPath("./configs/merchant/apiclient_key.pem") + if err != nil { + log.Print("load merchant private key error") + } + ctx := context.Background() + // 1. 使用 `RegisterDownloaderWithPrivateKey` 注册下载器 + err = downloader.MgrInstance().RegisterDownloaderWithPrivateKey(ctx, mchPrivateKey, mchCertificateSerialNumber, mchID, mchAPIv3Key) + if err != nil { + fmt.Println(err) + return + } + // 2. 获取商户号对应的微信支付平台证书访问器 + certVisitor := downloader.MgrInstance().GetCertificateVisitor(mchID) + // 3. 使用证书访问器初始化 `notify.Handler` + handler := notify.NewNotifyHandler(mchAPIv3Key, verifiers.NewSHA256WithRSAVerifier(certVisitor)) + + transaction := new(payments.Transaction) + notifyReq, err := handler.ParseNotifyRequest(context.Background(), c.Request, transaction) + // 如果验签未通过,或者解密失败 + if err != nil { + fmt.Println(err) + return + } + // 处理通知内容 + //fmt.Println(notifyReq.Summary) + //fmt.Println(transaction.TransactionId) + // + //transactionJson, _ := json.Marshal(transaction) + //fmt.Println("transactionJson:", string(transactionJson)) + // + //notifyReqJson, _ := json.Marshal(notifyReq) + //fmt.Println("notifyReqJson:", string(notifyReqJson)) + + plaintext := new(WxPayRefundPlaintext) + err = json.Unmarshal([]byte(notifyReq.Resource.Plaintext), plaintext) + if err != nil { + logger.Error("unmarshal plaintext err:", err) + return + } + + openMemberRecord := new(model.UserOpenMemberRecord) + + err = model.NewUserOpenMemberRecordQuerySet(model.DB).OpenNoEq(plaintext.OutTradeNo).One(openMemberRecord) + if err != nil { + logger.Error("user open member record err:", err) + return + } + fundRecord := &model.FundRecord{ + Uid: openMemberRecord.Uid, + FundType: model.FundTypeExpressFeeRefund, + Amount: int64(plaintext.Amount.Refund) * (-1), + TransactionId: plaintext.TransactionId, + OutTradeNo: plaintext.OutTradeNo, + RefundId: plaintext.RefundId, + Status: 2, + Remark: "邮费退款", + } + err = model.DB.Create(fundRecord).Error + if err != nil { + logger.Error("create fund record err:", err) + return + } + + RespNotice(c, "SUCCESS", "成功") + return + //logger.Error("xml Request.Body1:", string(body)) +} + func PayCallBackHandle(notify wxpay.WechatNotifyInfo, payKey string) (string, error) { m, err := struct2Map(notify) diff --git a/controller/mall.go b/controller/mall.go index bbfd80e..6a9dcbf 100644 --- a/controller/mall.go +++ b/controller/mall.go @@ -237,8 +237,13 @@ func MallOrderCreate(c *gin.Context) { RespJson(c, status.InternalServerError, nil) return } - - webPay, err := wxpay.WebPay(order.SerialNo, goods.DeliveryFee, user.WxOpenID, "N", wxpay.WxPayExchangeGoods) + configInfo, err := model.PayConfigInfo() + if err != nil { + logger.Error(err) + RespJson(c, status.InternalServerError, nil) + return + } + webPay, err := wxpay.WebPay(order.SerialNo, goods.DeliveryFee, user.WxOpenID, "N", wxpay.WxPayExchangeGoods, configInfo.NotifyUrl) if err != nil { logger.Error(errors.New("WebPay err")) RespJson(c, status.InternalServerError, nil) diff --git a/controller/order.go b/controller/order.go index 92cb267..e23238d 100644 --- a/controller/order.go +++ b/controller/order.go @@ -248,14 +248,17 @@ func RentCardOrderCreate(c *gin.Context) { //return //fmt.Println("CardMax", memberConfig.CardMax) rentCard = &model.UserRentCard{LevelRentCount: memberConfig.CardMax, CanRentCount: memberConfig.CardMax} - } //fmt.Println("rentCard", rentCard.CanRentCount) + if uc.Uid == 15304136 || uc.Uid == 45935373 { + rentCard.CanRentCount -= 1 + } if cardCount > rentCard.CanRentCount { logger.Error("GetMemberConfig err:", err) RespJson(c, status.OrderOutRentCount, nil) return } + // 订单成功后 扣减库存 //model.UnPayOrderSetCancel(user.Uid) @@ -460,7 +463,13 @@ func RentCardOrderCreate(c *gin.Context) { //fmt.Println("Price", req.Price) //fmt.Println("WxOpenID", user.WxOpenID) //fmt.Println("WxPayRentCard", wxpay.WxPayRentCard) - webPay, err := wxpay.WebPay(order.OrderSn, req.Price, user.WxOpenID, "N", wxpay.WxPayRentCard) + configInfo, err := model.PayConfigInfo() + if err != nil { + logger.Error(err) + RespJson(c, status.InternalServerError, nil) + return + } + webPay, err := wxpay.WebPay(order.OrderSn, req.Price, user.WxOpenID, "N", wxpay.WxPayRentCard, configInfo.NotifyUrl) if err != nil { logger.Error(errors.New("WebPay err")) RespJson(c, status.InternalServerError, nil) @@ -630,7 +639,13 @@ func OrderPay(c *gin.Context) { RespJson(c, status.InternalServerError, nil) return } - webPay, err := wxpay.WebPay(order.OrderSn, order.PayPrice, user.WxOpenID, "N", wxpay.WxPayRentCard) + configInfo, err := model.PayConfigInfo() + if err != nil { + logger.Error(err) + RespJson(c, status.InternalServerError, nil) + return + } + webPay, err := wxpay.WebPay(order.OrderSn, order.PayPrice, user.WxOpenID, "N", wxpay.WxPayRentCard, configInfo.NotifyUrl) if err != nil { logger.Error(errors.New("WebPay err")) RespJson(c, status.InternalServerError, nil) @@ -890,43 +905,52 @@ func OrderCancel(c *gin.Context) { order = orderInfo fmt.Println("order:", order) if isRecede { - outTradeNo, err := model.GetWxPayExpressFeeRefundRecord(order.ID) if err != nil { logger.Error("err:", err) RespJson(c, status.InternalServerError, nil) return } - - orderSn := model.GetOrderSn() - err = model.UserOpenMemberRecord{Uid: uint32(order.Uid), OpenNo: orderSn, OrderId: order.ID, OrderType: 2}.Insert() - if err != nil { - logger.Error(errors.New("WebPay err")) - RespJson(c, status.InternalServerError, nil) - return - } - - orderRefund := wxpay.OrderRefund{ - OutTradeNo: outTradeNo, - OutRefundNo: orderSn, - NotifyUrl: "", - Amount: wxpay.OrderRefundAmount{ - Refund: order.PayPrice, - Total: order.PayPrice, - Currency: "CNY", - }, - } - bytes, _ := json.Marshal(order) - fmt.Println("订单取消:", string(bytes)) - orderRefundJson, _ := json.Marshal(&orderRefund) - fmt.Println("订单取消 orderRefundJson:", string(orderRefundJson)) - //err = wxpay.WxPayOrderRefund(orderRefund) - err = wxpay.TransactionOrderRefund(orderRefund) + //m.OpenNo = model.GetOrderSn() + memberRecord := &model.UserOpenMemberRecord{OpenNo: model.GetOrderSn(), OrderType: 2, Order: &order} + err = memberRecord.OrderRefund(outTradeNo) if err != nil { logger.Error("err:", err) RespJson(c, status.InternalServerError, nil) return } + + //orderSn := model.GetOrderSn() + //err = model.UserOpenMemberRecord{Uid: uint32(order.Uid), OpenNo: orderSn, OrderId: order.ID, OrderType: 2}.Insert() + //if err != nil { + // logger.Error(errors.New("WebPay err")) + // RespJson(c, status.InternalServerError, nil) + // return + //} + + //orderRefund := wxpay.OrderRefund{ + // OutTradeNo: outTradeNo, + // OutRefundNo: orderSn, + // NotifyUrl: "", + // Amount: wxpay.OrderRefundAmount{ + // Refund: order.PayPrice, + // Total: order.PayPrice, + // Currency: "CNY", + // }, + //} + //err = wxpay.TransactionOrderRefund(orderRefund) + //if err != nil { + // logger.Error("err:", err) + // RespJson(c, status.InternalServerError, nil) + // return + //} + + //bytes, _ := json.Marshal(order) + //fmt.Println("订单取消:", string(bytes)) + //orderRefundJson, _ := json.Marshal(&orderRefund) + //fmt.Println("订单取消 orderRefundJson:", string(orderRefundJson)) + //err = wxpay.WxPayOrderRefund(orderRefund) + } RespOK(c, nil) diff --git a/controller/user.go b/controller/user.go index de87e77..a591549 100644 --- a/controller/user.go +++ b/controller/user.go @@ -266,8 +266,13 @@ func OpenMember(c *gin.Context) { RespJson(c, status.InternalServerError, nil) return } - - webPay, err := wxpay.WebPay(orderSn, totalFee, user.WxOpenID, "N", wxpay.WxPayMember) + configInfo, err := model.PayConfigInfo() + if err != nil { + logger.Error(err) + RespJson(c, status.InternalServerError, nil) + return + } + webPay, err := wxpay.WebPay(orderSn, totalFee, user.WxOpenID, "N", wxpay.WxPayMember, configInfo.NotifyUrl) if err != nil { logger.Error(errors.New("WebPay err")) RespJson(c, status.InternalServerError, nil) @@ -386,8 +391,13 @@ func UpgradeMember(c *gin.Context) { RespJson(c, status.InternalServerError, nil) return } - - webPay, err := wxpay.WebPay(orderSn, uint32(totalFee), user.WxOpenID, "N", wxpay.WxPayUpgradeMember) + configInfo, err := model.PayConfigInfo() + if err != nil { + logger.Error(err) + RespJson(c, status.InternalServerError, nil) + return + } + webPay, err := wxpay.WebPay(orderSn, uint32(totalFee), user.WxOpenID, "N", wxpay.WxPayUpgradeMember, configInfo.NotifyUrl) if err != nil { logger.Error(errors.New("WebPay err")) RespJson(c, status.InternalServerError, nil) @@ -534,8 +544,13 @@ func PayDeposit(c *gin.Context) { return } //totalFee = 1 // 测试 - - webPay, err := wxpay.WebPay(orderSn, totalFee, user.WxOpenID, "N", wxpay.WxPayDeposit) + configInfo, err := model.PayConfigInfo() + if err != nil { + logger.Error(err) + RespJson(c, status.InternalServerError, nil) + return + } + webPay, err := wxpay.WebPay(orderSn, totalFee, user.WxOpenID, "N", wxpay.WxPayDeposit, configInfo.NotifyUrl) if err != nil { logger.Error(errors.New("WebPay err")) RespJson(c, status.InternalServerError, nil) @@ -684,9 +699,14 @@ func UserMemberExpireDelayingPay(c *gin.Context) { RespJson(c, status.InternalServerError, nil) return } - + configInfo, err := model.PayConfigInfo() + if err != nil { + logger.Error(err) + RespJson(c, status.InternalServerError, nil) + return + } orderSn := model.GetOrderSn() - webPay, err := wxpay.WebPay(orderSn, uint32(userMemberExpireDelay.DelayAmount), user.WxOpenID, "N", wxpay.WxPayMemberExpireDelay) + webPay, err := wxpay.WebPay(orderSn, uint32(userMemberExpireDelay.DelayAmount), user.WxOpenID, "N", wxpay.WxPayMemberExpireDelay, configInfo.NotifyUrl) if err != nil { logger.Error(errors.New("WebPay err")) RespJson(c, status.InternalServerError, nil) diff --git a/controller/user_share_card.go b/controller/user_share_card.go index 17d0917..96ab690 100644 --- a/controller/user_share_card.go +++ b/controller/user_share_card.go @@ -404,8 +404,13 @@ func ShareCardRetrieveCreate(c *gin.Context) { // RespJson(c, status.Unauthorized, nil) // return //} - - webPay, err := wxpay.WebPay(retrieve.OrderSn, req.Amount, user.WxOpenID, "N", wxpay.WxPayShareCardRetrieve) + configInfo, err := model.PayConfigInfo() + if err != nil { + logger.Error(err) + RespJson(c, status.InternalServerError, nil) + return + } + webPay, err := wxpay.WebPay(retrieve.OrderSn, req.Amount, user.WxOpenID, "N", wxpay.WxPayShareCardRetrieve, configInfo.NotifyUrl) if err != nil { logger.Error(errors.New("WebPay err")) RespJson(c, status.InternalServerError, nil) @@ -527,11 +532,16 @@ func ShareCardRetrieveCancel(c *gin.Context) { RespJson(c, status.InternalServerError, nil) return } + configInfo, err := model.PayConfigInfo() + if err != nil { + logger.Error("config info err:", err) + return + } orderRefund := wxpay.OrderRefund{ OutTradeNo: retrieve.OrderSn, OutRefundNo: refundOrderSn, - NotifyUrl: "", + NotifyUrl: configInfo.RefundNotifyUrl, Amount: wxpay.OrderRefundAmount{ Refund: retrieve.PayAmount, Total: retrieve.PayAmount, diff --git a/lib/wxpay/wx_pay.go b/lib/wxpay/wx_pay.go index 9d5d0a5..d347a2a 100644 --- a/lib/wxpay/wx_pay.go +++ b/lib/wxpay/wx_pay.go @@ -19,7 +19,7 @@ import ( "log" "mh-server/config" "mh-server/lib/utils" - "mh-server/model" + //"mh-server/model" "net/http" "sort" "strconv" @@ -40,7 +40,7 @@ const ( WxPayExchangeGoods = "exchange_goods" // 兑换商品 WxPayUpgradeMember = "upgrade_member" // 多级会员 WxPayMemberExpireDelay = "member_expire_delay" // 会员过期滞纳金 - WxPayShareCardRetrieve = "share_card_retrieve" // 会员过期滞纳金 + WxPayShareCardRetrieve = "share_card_retrieve" // //NotifyUrl = "https://switch.deovo.com:8001/api/v1/wxpay/notice" // 数据库配置 生产 //NotifyUrl = "https://dev.switch.deovo.com:8004/api/v1/wxpay/notice" // 测试 @@ -49,17 +49,21 @@ const ( ) //web 微信支付 -func WebPay(orderId string, totalFee uint32, openId, profitSharing, attach string) (*Sextuple, error) { +func WebPay(orderId string, totalFee uint32, openId, profitSharing, attach, notifyUrl string) (*Sextuple, error) { now := time.Now().Local() strTime := fmt.Sprintf("%04d%02d%02d%02d%02d%02d", now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second()) nonce := utils.GenRandStr(NonceStringLength) - configInfo, err := model.PayConfigInfo() - if err != nil { - logger.Error(err) - return nil, err - } - if configInfo.NotifyUrl == "" { + //configInfo, err := model.PayConfigInfo() + //if err != nil { + // logger.Error(err) + // return nil, err + //} + //if configInfo.NotifyUrl == "" { + // logger.Error("NotifyUrl is null") + // return nil, errors.New("NotifyUrl is null") + //} + if notifyUrl == "" { logger.Error("NotifyUrl is null") return nil, errors.New("NotifyUrl is null") } @@ -81,7 +85,9 @@ func WebPay(orderId string, totalFee uint32, openId, profitSharing, attach strin SpbillCreateIp: clientIp, //NotifyUrl: "https://" + config.AppConfig.Domain + config.AppConfig.WxPayNotifyUrl, //NotifyUrl: "https://" + domain + wxPayNotifyUrl, - NotifyUrl: configInfo.NotifyUrl, + //NotifyUrl: configInfo.NotifyUrl, + NotifyUrl: notifyUrl, + TradeType: "JSAPI", MchId: config.AppConfig.WxMchID, AppId: config.AppConfig.WxAppId, @@ -634,7 +640,8 @@ func TransactionOrderRefund(orderRefund OrderRefund) error { OutTradeNo: core.String(orderRefund.OutTradeNo), OutRefundNo: core.String(orderRefund.OutRefundNo), Reason: core.String("取消订单"), - NotifyUrl: core.String("https://weixin.qq.com/api/v1/wxpay/notice"), + //NotifyUrl: core.String("https://weixin.qq.com/api/v1/wxpay/notice"), + NotifyUrl: core.String(orderRefund.NotifyUrl), Amount: &refunddomestic.AmountReq{ Currency: core.String("CNY"), Refund: core.Int64(int64(orderRefund.Amount.Refund)), diff --git a/model/config.go b/model/config.go index 5639a8c..3276e3c 100644 --- a/model/config.go +++ b/model/config.go @@ -20,9 +20,10 @@ func (m *Config) TableName() string { } type PayConfig struct { - MemberFee uint32 `json:"member_fee"` - DepositFee uint32 `json:"deposit_fee"` - NotifyUrl string `json:"notify_url"` + MemberFee uint32 `json:"member_fee"` + DepositFee uint32 `json:"deposit_fee"` + NotifyUrl string `json:"notify_url"` + RefundNotifyUrl string `json:"refund_notify_url"` } const ( diff --git a/model/model_test.go b/model/model_test.go index ad46286..e499fdb 100644 --- a/model/model_test.go +++ b/model/model_test.go @@ -4,6 +4,8 @@ import ( "crypto/sha512" "encoding/json" "fmt" + //"github.com/andreburgaud/crypt2go/ecb" + //"github.com/andreburgaud/crypt2go/padding" "github.com/codinl/go-logger" "github.com/jinzhu/gorm" "math/rand" @@ -157,21 +159,25 @@ func InitDBProd() { DBProd.LogMode(false) DBProd.SingularTable(true) DBProd.AutoMigrate( - &RedeemCode{}, - &UserRedeemCode{}, - &GameCardGoods{}, + //&RedeemCode{}, + //&UserRedeemCode{}, + //&GameCardGoods{}, + // + //&UserShareCardBill{}, + //&ShareCardBillGame{}, + //&UserShareCard{}, + //&ShareCardVmRecord{}, + //&UserShareCardVm{}, + //&ShareCardDateVm{}, + //&ShareCardGameVm{}, + //&ShareCardRetrieve{}, + //&ShareCardRetrieveCard{}, + //&GameCardLabel{}, + //&CardIssueFeedback{}, - &UserShareCardBill{}, - &ShareCardBillGame{}, - &UserShareCard{}, - &ShareCardVmRecord{}, - &UserShareCardVm{}, - &ShareCardDateVm{}, - &ShareCardGameVm{}, - &ShareCardRetrieve{}, - &ShareCardRetrieveCard{}, - &GameCardLabel{}, - &CardIssueFeedback{}, + &GameCard{}, + &FundRecord{}, + &User{}, ) if err := DBProd.DB().Ping(); err != nil { @@ -980,3 +986,7 @@ func TestTimeZeroData(t *testing.T) { //NewShareCardRetrieveCardQuerySet(DB).IDEq(189).GetUpdater().SetStoreId() } + +func TestWxPayDecode(t *testing.T) { + +} diff --git a/model/user.go b/model/user.go index b2de124..19416b5 100644 --- a/model/user.go +++ b/model/user.go @@ -6,6 +6,7 @@ import ( "github.com/codinl/go-logger" "github.com/jinzhu/gorm" "mh-server/lib/utils" + "mh-server/lib/wxpay" "sync" "time" ) @@ -121,6 +122,8 @@ const ( FundTypeExpressFee = "express_fee" // 邮费 FundTypeUpgradeMember = "upgrade_member" // 升级会员 FundTypeMemberExpireDelay = "member_expire_delay" // 滞纳金 + FundTypeDepositRefund = "deposit_refund" // 退押金 + FundTypeExpressFeeRefund = "express_fee_refund" // 退邮费 ) // gen:qs @@ -131,6 +134,7 @@ type FundRecord struct { Amount int64 `json:"amount"` TransactionId string `json:"transaction_id"` // 支付单号 OutTradeNo string `json:"out_trade_no"` + RefundId string `json:"refund_id"` Status uint32 `json:"status"` // 1-待支付 2-已支付 3-已退款 Remark string `json:"remark"` // 备注 } @@ -216,9 +220,12 @@ type UserOpenMemberRecord struct { Uid uint32 `json:"uid"` OpenNo string `json:"open_no" gorm:"index"` OrderId uint32 `json:"order_id"` - OrderType uint32 `json:"order_type"` // 1-物流支付 2-取消物流租卡 3-滞纳金 4-收回卡 + OrderType uint32 `json:"order_type"` // 1-物流支付 2-取消物流租卡 3-滞纳金 4-收回卡 5-退物流费 MemberLevel uint32 `json:"member_level"` MemberExpire time.Time `json:"member_expire"` // 会员到期时间 + //Attach string `json:"attach"` + Order *Order `json:"order" gorm:"-"` + ShareCardRetrieve *ShareCardRetrieve `json:"share_card_retrieve" gorm:"-"` } func (o *UserOpenMemberRecord) TableName() string { @@ -234,6 +241,115 @@ func (m UserOpenMemberRecord) Insert() error { return nil } +func (m *UserOpenMemberRecord) OrderRefund(outTradeNo string) error { + if m.Order == nil { + return errors.New("order is nil") + } + if m.OpenNo == "" { + m.OpenNo = GetOrderSn() + } + m.Uid = uint32(m.Order.Uid) + m.OrderId = m.Order.ID + + err := m.Refund(outTradeNo, m.Order.PayPrice) + if err != nil { + logger.Error("refund err:", err) + return err + } + + return nil +} + +func (m *UserOpenMemberRecord) Refund(outTradeNo string, amount uint32) error { + configInfo, err := PayConfigInfo() + if err != nil { + logger.Error("config info err:", err) + return err + } + //configInfo.NotifyUrl = "https://dev.switch.deovo.com:8004/api/v1/wxpay_refund/notice" + err = m.Insert() + if err != nil { + logger.Error("insert user open member record err:", err) + return err + } + + orderRefund := wxpay.OrderRefund{ + OutTradeNo: outTradeNo, + OutRefundNo: m.OpenNo, + NotifyUrl: configInfo.RefundNotifyUrl, + Amount: wxpay.OrderRefundAmount{ + Refund: amount, + Total: amount, + Currency: "CNY", + }, + } + err = wxpay.TransactionOrderRefund(orderRefund) + if err != nil { + logger.Error("err:", err) + return err + } + + //FundRecord{ + // Uid: m.Uid, + // FundType: FundTypeExpressFeeRefund, + // Amount: int64(m.Order.PayPrice) * (-1), + // TransactionId: "", + // OutTradeNo: "", + // Status: 0, + // Remark: "", + //} + return nil +} + +func (m *UserOpenMemberRecord) ShareCardRetrieveRefund(outTradeNo string) error { + //if m.ShareCardRetrieve == nil { + // return errors.New("order is nil") + //} + //if m.OpenNo == "" { + // m.OpenNo = GetShareCardRetrieveOrderSn() + //} + //m.Uid = uint32(m.Order.Uid) + //m.OrderId = m.ShareCardRetrieve.ID + //configInfo, err := PayConfigInfo() + //if err != nil { + // logger.Error("config info err:", err) + // return err + //} + // + //err = m.Insert() + //if err != nil { + // logger.Error("insert user open member record err:", err) + // return err + //} + // + //orderRefund := wxpay.OrderRefund{ + // OutTradeNo: outTradeNo, + // OutRefundNo: m.OpenNo, + // NotifyUrl: configInfo.NotifyUrl, + // Amount: wxpay.OrderRefundAmount{ + // Refund: m.ShareCardRetrieve.PayAmount, + // Total: m.ShareCardRetrieve.PayAmount, + // Currency: "CNY", + // }, + //} + //err = wxpay.TransactionOrderRefund(orderRefund) + //if err != nil { + // logger.Error("err:", err) + // return err + //} + // + ////FundRecord{ + //// Uid: m.Uid, + //// FundType: FundTypeExpressFeeRefund, + //// Amount: int64(m.Order.PayPrice) * (-1), + //// TransactionId: "", + //// OutTradeNo: "", + //// Status: 0, + //// Remark: "", + ////} + return nil +} + func (m *UserOpenMemberRecord) GetByOpenNo() error { err := NewUserOpenMemberRecordQuerySet(DB).OpenNoEq(m.OpenNo).One(m) if err != nil && err != RecordNotFound { diff --git a/router/router_app.go b/router/router_app.go index 215bf79..eefca66 100644 --- a/router/router_app.go +++ b/router/router_app.go @@ -30,8 +30,9 @@ func ConfigAppRouter(r gin.IRouter) { // //api.POST("sys/config", controller.SysConfig) // 配置 // api.POST("step/config", controller.StepConfig) // 步数配置 // //api.POST("upload_user_info", controller.UploadUserInfo) // 上传用户信息 - api.POST("wxpay/notice", controller.PushWXPayNotice) // 微信推送支付通知 - api.POST("aliyun/sts_token", controller.AliyunStsTokenGet) // 阿里云上传图片token + api.POST("wxpay/notice", controller.PushWXPayNotice) // 微信推送支付通知 + api.POST("wxpay_refund/notice", controller.PushWXPayRefundNotice) // 微信推送支付退款通知 + api.POST("aliyun/sts_token", controller.AliyunStsTokenGet) // 阿里云上传图片token // api.GET("wx_cs/message", controller.CustomerServiceMessageCheck) // 客服校验 // api.POST("wx_cs/message", controller.CustomerServiceMessage) // 客服 // @@ -138,9 +139,7 @@ func ConfigAppRouter(r gin.IRouter) { order.POST("revert", controller.OrderRevert) // 租卡订单归还 order.POST("revert/cancel", controller.OrderRevertCancel) // 取消归还 //order.POST("express_fee/refund", controller.ExpressFeeRefund) // 物流费退款 - order.POST("confirm_receipt", controller.ConfirmReceipt) // 订单确认收货 - } article := api.Group("article")