diff --git a/app/db/db_order.go b/app/db/db_order.go index b7401ce..515197b 100644 --- a/app/db/db_order.go +++ b/app/db/db_order.go @@ -23,6 +23,22 @@ func GetOrderEg(eg *xorm.Engine, oid string) *model.CommunityTeamOrder { } return &data } +func GetOrderPayEg(eg *xorm.Engine, oid string) *model.CommunityTeamPayOrder { + var data model.CommunityTeamPayOrder + get, err := eg.Where("oid=?", oid).Get(&data) + if get == false || err != nil { + return nil + } + return &data +} +func GetOrderPay(sess *xorm.Session, oid string) *model.CommunityTeamPayOrder { + var data model.CommunityTeamPayOrder + get, err := sess.Where("oid=?", oid).Get(&data) + if get == false || err != nil { + return nil + } + return &data +} func GetOrder(sess *xorm.Session, oid string) *model.CommunityTeamOrder { var data model.CommunityTeamOrder get, err := sess.Where("oid=?", oid).Get(&data) diff --git a/app/db/model/community_team_pay_order.go b/app/db/model/community_team_pay_order.go new file mode 100644 index 0000000..99d86c0 --- /dev/null +++ b/app/db/model/community_team_pay_order.go @@ -0,0 +1,29 @@ +package model + +import ( + "time" +) + +type CommunityTeamPayOrder struct { + Id int `json:"id" xorm:"not null pk autoincr INT(11)"` + Uid int `json:"uid" xorm:"default 0 INT(11)"` + StoreType int `json:"store_type" xorm:"default 0 comment('0官方自营店 1加盟店 2连锁店') INT(11)"` + StoreUid int `json:"store_uid" xorm:"default 0 comment('门店用户id') INT(11)"` + ParentUid int `json:"parent_uid" xorm:"default 0 comment('上级代理') INT(11)"` + Commission string `json:"commission" xorm:"comment('分佣(元)') DECIMAL(20,2)"` + CreateAt time.Time `json:"create_at" xorm:"DATETIME"` + UpdateAt time.Time `json:"update_at" xorm:"DATETIME"` + State int `json:"state" xorm:"default 0 comment('0待付款 1已支付 2已提货') INT(11)"` + PayAt time.Time `json:"pay_at" xorm:"comment('付款时间') DATETIME"` + Oid int64 `json:"oid" xorm:"default 0 comment('主单号') BIGINT(20)"` + PayMethod int `json:"pay_method" xorm:"default 0 comment('1余额 2支付宝 3微信') INT(11)"` + PayId string `json:"pay_id" xorm:"comment('第三方的支付id') VARCHAR(255)"` + Amount string `json:"amount" xorm:"default 0.00 comment('总金额') DECIMAL(20,2)"` + Memo string `json:"memo" xorm:"comment('备注') VARCHAR(255)"` + StoreSettleAt int `json:"store_settle_at" xorm:"default 0 INT(11)"` + CommissionAt int `json:"commission_at" xorm:"default 0 INT(11)"` + SettleAt int `json:"settle_at" xorm:"default 0 INT(11)"` + UserCommission string `json:"user_commission" xorm:"default 0.00 DECIMAL(20,2)"` + AgentCommission string `json:"agent_commission" xorm:"default 0.00 DECIMAL(20,2)"` + PlatformCommission string `json:"platform_commission" xorm:"default 0.00 DECIMAL(20,2)"` +} diff --git a/app/hdl/hdl_order.go b/app/hdl/hdl_order.go index 2742f38..dcade7f 100644 --- a/app/hdl/hdl_order.go +++ b/app/hdl/hdl_order.go @@ -11,6 +11,9 @@ func OrderTotal(c *gin.Context) { func OrderCreate(c *gin.Context) { svc.OrderCreate(c) } +func PayOrderCreate(c *gin.Context) { + svc.PayOrderCreate(c) +} func OrderCoupon(c *gin.Context) { svc.OrderCoupon(c) } diff --git a/app/hdl/hdl_store.go b/app/hdl/hdl_store.go index 8947b98..ea27c51 100644 --- a/app/hdl/hdl_store.go +++ b/app/hdl/hdl_store.go @@ -39,6 +39,9 @@ func StoreScan(c *gin.Context) { func StorePayScan(c *gin.Context) { svc.StorePayScan(c) } +func StorePayInfo(c *gin.Context) { + svc.StorePayInfo(c) +} func City(c *gin.Context) { var arg = make(map[string]string) c.ShouldBindJSON(&arg) diff --git a/app/md/pay.go b/app/md/pay.go index 4994c8f..3857010 100644 --- a/app/md/pay.go +++ b/app/md/pay.go @@ -39,6 +39,7 @@ var PayMethodIDs = map[string]int{ const ( CommunityTeam = "community_team" + CommunityTeamPay = "community_team_pay" PrivilegeCard = "privilege_card" LianlianPay = "lianlian_pay" BusinessCollege = "business_college" diff --git a/app/router/router.go b/app/router/router.go index bd4dc36..7acffe5 100644 --- a/app/router/router.go +++ b/app/router/router.go @@ -139,8 +139,9 @@ func routeCommunityTeam(r *gin.RouterGroup) { r.Use(mw.CheckSign) //签名校验 r.Use(mw.Checker) r.GET("/style/store/scan", hdl.StyleStoreScan) - r.POST("/store/scan", hdl.StoreScan) - r.POST("/store/pay/scan", hdl.StorePayScan) + r.GET("/store/scan", hdl.StoreScan) + r.GET("/store/pay/scan", hdl.StorePayScan) + r.POST("/store/pay/info", hdl.StorePayInfo) r.POST("/city", hdl.City) r.GET("/bank/store/cate", hdl.BankStoreCate) r.POST("/bank/store/list", hdl.BankStore) @@ -168,7 +169,7 @@ func routeCommunityTeam(r *gin.RouterGroup) { r.POST("/order/detail", hdl.OrderDetail) r.GET("/order/cate", hdl.OrderCate) r.POST("/pay/:payMethod/:orderType", hdl.Pay) - + r.POST("/pay/order/create", hdl.PayOrderCreate) r.POST("/store/order/list", hdl.StoreOrderList) r.POST("/store/order/detail", hdl.StoreOrderDetail) r.POST("/store/order/confirm", hdl.StoreOrderConfirm) diff --git a/app/store/svc/svc_qrcode.go b/app/store/svc/svc_qrcode.go index 9de3e05..380107c 100644 --- a/app/store/svc/svc_qrcode.go +++ b/app/store/svc/svc_qrcode.go @@ -40,11 +40,30 @@ func SysModDataBySkipIdentifier(c *gin.Context, name string) (*model.SysModule, return mod, nil } func QrcodeBase(c *gin.Context) { - h5Domain := svc.GetWebSiteDomainInfo(c, "wap") - content := h5Domain + "/#/zy-landing-page/pages/o2o-scan/o2o-scan?qrcode_id=1" - res := map[string]string{ - "pay_url": content, - "pay_qrcode": strings.ReplaceAll(qrcode.GetPNGBase64(content), "\u0000", ""), + user := svc.GetUser(c) + qrcodeData := db.GetStorePayQrcodeByUid(svc.MasterDb(c), user.Info.Uid) + eg := svc.MasterDb(c) + m, _ := SysModDataBySkipIdentifier(c, "pub.flutter.community_store_qrcode_style") + bytes := utils.MarshalJSONCamelCase2JsonSnakeCase(m.Data) + m.Data = string(bytes) + fmt.Println(m.Data) + store := db.GetStoreIdEg(eg, utils.IntToStr(user.Info.Uid)) + if store != nil { + m.Data = strings.ReplaceAll(m.Data, "{店铺名}", store.Name) + m.Data = strings.ReplaceAll(m.Data, "{店铺编号}", utils.IntToStr(store.Uid)) + } + css := make(map[string]interface{}) + json.Unmarshal([]byte(m.Data), &css) + res := map[string]interface{}{ + "pay_url": "", + "pay_qrcode": "", + "css": css, + } + if qrcodeData != nil { + h5Domain := svc.GetWebSiteDomainInfo(c, "wap") + content := h5Domain + "/#/zy-landing-page/pages/o2o-scan/o2o-scan?qrcode_id=" + utils.IntToStr(qrcodeData.Id) + res["pay_url"] = content + res["pay_qrcode"] = strings.ReplaceAll(qrcode.GetPNGBase64(content), "\u0000", "") } e.OutSuc(c, res, nil) return diff --git a/app/svc/svc_order.go b/app/svc/svc_order.go index dca6f34..253e306 100644 --- a/app/svc/svc_order.go +++ b/app/svc/svc_order.go @@ -471,6 +471,75 @@ func OrderConfirm(c *gin.Context) { e.OutSuc(c, "success", nil) return } +func PayOrderCreate(c *gin.Context) { + var arg map[string]string + if err := c.ShouldBindJSON(&arg); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + user := GetUser(c) + if utils.StrToFloat64(arg["amount"]) <= 0 { + e.OutErr(c, e.ERR, e.NewErr(400000, "金额不正确")) + return + } + // 加锁 防止并发提取 + mutexKey := fmt.Sprintf("%s:team.OrderCreate:%s", c.GetString("mid"), utils.IntToStr(user.Info.Uid)) + withdrawAvailable, err := cache.Do("SET", mutexKey, 1, "EX", 5, "NX") + if err != nil { + e.OutErr(c, e.ERR, err) + return + } + if withdrawAvailable != "OK" { + e.OutErr(c, e.ERR, e.NewErr(400000, "请求过于频繁,请稍后再试")) + return + } + sess := MasterDb(c).NewSession() + defer sess.Close() + err = sess.Begin() + if err != nil { + e.OutErr(c, 400, err.Error()) + return + } + ordId := utils.OrderUUID(user.Info.Uid) + // 获取店铺信息 + store := db.GetStoreId(sess, arg["store_id"]) + totalPrice := arg["amount"] + var order = &model.CommunityTeamPayOrder{ + Uid: user.Info.Uid, + StoreUid: utils.StrToInt(arg["store_id"]), + Commission: utils.Float64ToStr(utils.FloatFormat(utils.AnyToFloat64(totalPrice)*(utils.AnyToFloat64(store.Commission)/100), 2)), + CreateAt: time.Now(), + UpdateAt: time.Now(), + Oid: utils.StrToInt64(ordId), + Amount: totalPrice, + } + if store.ParentUid > 0 { //代理下门店 + order.StoreType = 2 + order.Commission = "0" + order.ParentUid = store.ParentUid + order.AgentCommission = utils.Float64ToStr(utils.FloatFormat(utils.AnyToFloat64(totalPrice)*(utils.AnyToFloat64(store.AgentCommission)/100), 2)) + } + if store.StoreType == 1 { + order.StoreType = 1 + order.Commission = "0" + order.PlatformCommission = utils.Float64ToStr(utils.FloatFormat(utils.AnyToFloat64(totalPrice)*(utils.AnyToFloat64(store.PlatformCommission)/100), 2)) + } + insert, err := sess.Insert(order) + if insert == 0 || err != nil { + sess.Rollback() + e.OutErr(c, 400, e.NewErr(400, "下单失败")) + return + } + err = sess.Commit() + if err != nil { + sess.Rollback() + e.OutErr(c, 400, err.Error()) + return + } + sess.Commit() + e.OutSuc(c, map[string]string{"oid": ordId}, nil) + return +} func OrderCreate(c *gin.Context) { var arg md.OrderTotal if err := c.ShouldBindJSON(&arg); err != nil { diff --git a/app/svc/svc_pay.go b/app/svc/svc_pay.go index a888629..0c53c83 100644 --- a/app/svc/svc_pay.go +++ b/app/svc/svc_pay.go @@ -11,6 +11,11 @@ var PayFuncList = map[string]map[string]func(*gin.Context) (interface{}, error){ md.ALIPAY: AlipayCommunityTeam, md.WX_PAY: WxPayCommunityTeam, }, + md.CommunityTeamPay: { + md.BALANCE_PAY: BalanceCommunityTeamPay, + md.ALIPAY: AlipayCommunityTeamPay, + md.WX_PAY: WxPayCommunityTeamPay, + }, } var PayCallbackFuncList = map[string]map[string]func(*gin.Context){ md.CommunityTeam: { @@ -18,4 +23,9 @@ var PayCallbackFuncList = map[string]map[string]func(*gin.Context){ md.ALIPAY: AlipayCallbackCommunityTeam, md.WX_PAY: WxPayCallbackCommunityTeam, }, + md.CommunityTeamPay: { + md.BALANCE_PAY: nil, + md.ALIPAY: AlipayCallbackCommunityTeamPay, + md.WX_PAY: WxPayCallbackCommunityTeamPay, + }, } diff --git a/app/svc/svc_pay_community_team.go b/app/svc/svc_pay_community_team.go index 50f4425..139a604 100644 --- a/app/svc/svc_pay_community_team.go +++ b/app/svc/svc_pay_community_team.go @@ -57,7 +57,7 @@ func WxPayCommunityTeam(c *gin.Context) (interface{}, error) { return nil, err } params := map[string]string{ - "subject": md.NeedPayPart[md.AggregationRecharge], + "subject": "小店下单", "amount": wxMoneyMulHundred(ord.Amount), "order_type": md.AggregationRecharge, "ord_id": utils.AnyToString(ord.Oid), diff --git a/app/svc/svc_pay_community_team_pay.go b/app/svc/svc_pay_community_team_pay.go new file mode 100644 index 0000000..ef87341 --- /dev/null +++ b/app/svc/svc_pay_community_team_pay.go @@ -0,0 +1,146 @@ +package svc + +import ( + "applet/app/db" + "applet/app/db/model" + "applet/app/e" + "applet/app/md" + "applet/app/utils" + "errors" + "fmt" + "github.com/gin-gonic/gin" + "github.com/tidwall/gjson" + "time" +) + +func BalanceCommunityTeamPay(c *gin.Context) (interface{}, error) { + + ord, err := CheckCommunityTeamPay(c) + if err != nil || ord == nil { + return nil, err + } + err = BalancePay(c, ord.Amount, utils.Int64ToStr(ord.Oid), md.CommunityTeam) + if err != nil { + return nil, err + } + // 回调 + CommonCallbackCommunityTeamPay(c, utils.AnyToString(ord.Oid), md.BALANCE_PAY) + return nil, nil +} +func AlipayCommunityTeamPay(c *gin.Context) (interface{}, error) { + ord, err := CheckCommunityTeamPay(c) + if err != nil { + return nil, err + } + payParams := &md.AliPayPayParams{ + Subject: "收款码收款", + Amount: ord.Amount, + OrdId: utils.AnyToString(ord.Oid), + OrderType: md.CommunityTeamPay, + Uid: utils.IntToStr(ord.Uid), + AgentId: ord.ParentUid, + } + r, err := PrepareAlipayCode(c, payParams) + if err != nil { + return nil, err + } + return r, nil +} +func WxPayCommunityTeamPay(c *gin.Context) (interface{}, error) { + var r interface{} + var err error + ord, err := CheckCommunityTeamPay(c) + if err != nil { + return nil, err + } + params := map[string]string{ + "subject": "收款码收款", + "amount": wxMoneyMulHundred(ord.Amount), + "order_type": md.AggregationRecharge, + "ord_id": utils.AnyToString(ord.Oid), + "pay_wx_mch_id": SysCfgGet(c, "pay_wx_mch_id"), + "pay_wx_api_key": SysCfgGet(c, "pay_wx_api_key"), + "uid": utils.IntToStr(ord.Uid), + } + if ord.ParentUid > 0 { + user, _ := db.UserThirdPartyFindByID(MasterDb(c), ord.ParentUid) + if user.WechatPayInfo == "" { + return nil, errors.New("支付失败") + } + params["pay_wx_mch_id"] = gjson.Get(user.WechatPayInfo, "pay_wx_mch_id").String() + params["pay_wx_api_key"] = gjson.Get(user.WechatPayInfo, "pay_wx_api_key").String() + } + params["notify_url"] = fmt.Sprintf(md.CALLBACK_URL, c.Request.Host, c.GetString("mid"), params["order_type"], md.WX_PAY) + r, err = CommPayData(c, params) + if err != nil { + return nil, err + } + + return r, nil +} +func AlipayCallbackCommunityTeamPay(c *gin.Context) { + orderId, err := AlipayCallback(c) + if err != nil || orderId == "" { + return + } + CommonCallbackCommunityTeamPay(c, orderId, md.ALIPAY) +} +func WxPayCallbackCommunityTeamPay(c *gin.Context) { + orderId, err := wxPayCallback(c) + if err != nil || orderId == "" { + return + } + CommonCallbackCommunityTeamPay(c, orderId, md.WX_PAY) +} + +func CommonCallbackCommunityTeamPay(c *gin.Context, orderId string, payMethod string) { + sess := MasterDb(c).NewSession() + defer sess.Close() + sess.Begin() + ord := db.GetOrderPay(sess, orderId) + if ord == nil { + sess.Rollback() + return + } + // 判断是否失效 + if ord.State != 0 { + return + } + ord.State = 1 + ord.UpdateAt = time.Now() + ord.PayAt = time.Now() + ord.PayMethod = md.PayMethodIDs[payMethod] + sess.Where("id=?", ord.Id).Cols("state,update_at,pay_at,pay_method").Update(ord) + money := utils.StrToFloat64(ord.Commission) + if ord.ParentUid > 0 { + money = utils.StrToFloat64(ord.Amount) - utils.StrToFloat64(ord.AgentCommission) + } + if ord.StoreType == 1 { + money = utils.StrToFloat64(ord.Amount) - utils.StrToFloat64(ord.PlatformCommission) + } + bools := MoneyCheck(c, sess, ord.StoreUid, ord.ParentUid, ord.StoreType, 0, 1, money, "收款码收款", ord.Oid) + if bools == false { + sess.Rollback() + return + } + sess.Commit() + return +} +func CheckCommunityTeamPay(c *gin.Context) (*model.CommunityTeamPayOrder, error) { + var args struct { + MainOrdId string `json:"main_ord_id"` + } + if err := c.ShouldBindJSON(&args); err != nil || args.MainOrdId == "" { + return nil, e.NewErrCode(e.ERR_INVALID_ARGS) + } + // 查询订单 + ord := db.GetOrderPayEg(db.DBs[c.GetString("mid")], args.MainOrdId) + if ord == nil { + return nil, e.NewErr(403000, "不存在该订单") + } + // 判断是否失效 + if ord.State != 0 { + return nil, e.NewErr(403000, "订单已处理") + } + return ord, nil +} diff --git a/app/svc/svc_store.go b/app/svc/svc_store.go index 985e03c..84fafbe 100644 --- a/app/svc/svc_store.go +++ b/app/svc/svc_store.go @@ -9,6 +9,24 @@ import ( "time" ) +func StorePayInfo(c *gin.Context) { + var arg map[string]string + if err := c.ShouldBindJSON(&arg); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + engine := MasterDb(c) + store := db.GetStoreIdEg(engine, arg["store_id"]) + if store == nil { + e.OutErr(c, 400, e.NewErr(400, "门店不存在")) + return + } + res := map[string]string{ + "name": store.Name, "logo": store.Logo, + } + e.OutSuc(c, res, nil) + return +} func StorePayScan(c *gin.Context) { kind := c.DefaultQuery("type", "alipay") //1:支付宝 2:微信 id, _ := c.GetQuery("id") @@ -30,6 +48,7 @@ func StorePayScan(c *gin.Context) { StoreId string `json:"store_id" ` StoreType string `json:"store_type" ` AppId string `json:"app_id" ` + AppLogo string `json:"app_logo"` InviteCode string `json:"invite_code"` } store := db.GetStoreIdEg(engine, utils.IntToStr(data.Uid)) @@ -39,12 +58,14 @@ func StorePayScan(c *gin.Context) { } user, _ := db.UserProfileFindByID(engine, store.Uid) var appId = "" + var appLogo = "" var inviteCode = user.InviteCode if kind != "alipay" { communityTeamStoreWxAppletId := db.SysCfgGet(c, "community_team_store_wx_applet_id") var wxApplet model.WxAppletList MasterDb(c).Where("id=?", communityTeamStoreWxAppletId).Get(&wxApplet) appId = wxApplet.OriginalAppId + appLogo = wxApplet.AppletLogo } var result = RefundReq{ @@ -52,6 +73,7 @@ func StorePayScan(c *gin.Context) { AppId: appId, StoreType: utils.IntToStr(store.StoreType), InviteCode: inviteCode, + AppLogo: appLogo, } e.OutSuc(c, result, nil) return @@ -78,6 +100,7 @@ func StoreScan(c *gin.Context) { StoreType string `json:"store_type" ` TableNumber string `json:"table_number" ` AppId string `json:"app_id" ` + AppLogo string `json:"app_logo"` InviteCode string `json:"invite_code"` } store := db.GetStoreIdEg(engine, utils.IntToStr(data.Uid)) @@ -87,12 +110,14 @@ func StoreScan(c *gin.Context) { } user, _ := db.UserProfileFindByID(engine, store.Uid) var appId = "" + var appLogo = "" var inviteCode = user.InviteCode if kind != "alipay" { communityTeamStoreWxAppletId := db.SysCfgGet(c, "community_team_store_wx_applet_id") var wxApplet model.WxAppletList MasterDb(c).Where("id=?", communityTeamStoreWxAppletId).Get(&wxApplet) appId = wxApplet.OriginalAppId + appLogo = wxApplet.AppletLogo } var result = RefundReq{ @@ -101,6 +126,7 @@ func StoreScan(c *gin.Context) { AppId: appId, StoreType: utils.IntToStr(store.StoreType), InviteCode: inviteCode, + AppLogo: appLogo, } e.OutSuc(c, result, nil) return