package svc import ( "applet/app/customer/enum" "applet/app/customer/md" "applet/app/db" "applet/app/db/model" enum2 "applet/app/enum" svc3 "applet/app/svc" "applet/app/utils" "applet/app/utils/logx" "encoding/json" "errors" "fmt" "github.com/gin-gonic/gin" "github.com/wechatpay-apiv3/wechatpay-go/core" "github.com/wechatpay-apiv3/wechatpay-go/services/partnerpayments/jsapi" jsapi2 "github.com/wechatpay-apiv3/wechatpay-go/services/payments/jsapi" utils2 "github.com/wechatpay-apiv3/wechatpay-go/utils" "io/ioutil" "net/url" "strconv" "time" ) func BuyPackageForAli(c *gin.Context, req md.BuyPackageReq) (outTradeNo, tradeNo, total string, err error) { user := GetUser(c) session := db.Db.NewSession() defer session.Close() session.Begin() if err != nil { _ = session.Rollback() return } //1、判断是否为教师 isTeacher := false userIdentityDb := db.UserIdentityDb{} userIdentityDb.Set(0) userIdentity, err := userIdentityDb.GetUserIdentity(req.UserIdentityId) if err != nil { return } if userIdentity == nil { err = errors.New("未查询到对应身份记录") return } if userIdentity.Identity == enum2.UserIdentityForCentralKitchenForTeacher { isTeacher = true } //2、计算数据(1:按学期购买 2:按月购买 3:按天购买 4:补餐) var totalPrice float64 var data []*model.CentralKitchenForSchoolUserWithDay if req.Kind == 1 { totalPrice, data, err = CalcBySchoolTerm(user.Id, isTeacher, req) if err != nil { return } } if req.Kind == 2 { totalPrice, data, err = CalcByMonth(user.Id, isTeacher, req) if err != nil { return } } if req.Kind == 3 { totalPrice, data, err = CalcByDay(user.Id, isTeacher, req) if err != nil { return } } if req.Kind == 4 { totalPrice, data, err = CalcSupplementaryByDay(user.Id, isTeacher, req) if err != nil { return } } total = utils.Float64ToStr(totalPrice) //3、生成订单号 outTradeNo = utils.OrderUUID(user.Id) //4、请求 alipay.trade.create(统一收单交易创建接口) sysCfgDb := db.SysCfgDb{} sysCfgDb.Set() sysCfg := sysCfgDb.SysCfgFindWithDb(enum2.OpenAppletAppid, enum2.OpenAlipayAppid, enum2.OpenAlipayAppPrivateKey, enum2.OpenAlipayPublicKey, enum2.JsapiPayAppAutToken, enum2.JsapiPayNotifyUrl) err, resp := CurlAlipayTradeCreate(md.CurlAlipayTradeCreateReq{ Config: struct { PayAliAppId string `json:"pay_ali_app_id" label:"支付宝开放平台-第三方应用-appid"` PayAliPrivateKey string `json:"pay_ali_private_key" label:"支付宝开放平台-第三方应用-接口加签-应用私钥"` PayAliPublicKey string `json:"pay_ali_public_key" label:"支付宝开放平台-第三方应用-接口加签-支付宝公钥"` }{ PayAliAppId: sysCfg[enum2.OpenAlipayAppid], PayAliPrivateKey: sysCfg[enum2.OpenAlipayAppPrivateKey], PayAliPublicKey: sysCfg[enum2.OpenAlipayPublicKey], }, OpAppId: sysCfg[enum2.OpenAppletAppid], BuyerId: user.UserId, TotalAmount: total, OutTradeNo: outTradeNo, Subject: "购买食堂套餐", AppAuthToken: sysCfg[enum2.JsapiPayAppAutToken], NotifyUrl: sysCfg[enum2.JsapiPayNotifyUrl], }) if err != nil { return } //5、插入订单记录 now := time.Now() centralKitchenForSchoolPackageOrd := db.CentralKitchenForSchoolPackageOrd{} centralKitchenForSchoolPackageOrd.Set(outTradeNo) _, err = centralKitchenForSchoolPackageOrd.CentralKitchenForSchoolPackageOrdInsertBySession(session, &model.CentralKitchenForSchoolPackageOrd{ EnterpriseId: req.EnterpriseId, Uid: user.Id, UserIdentityId: req.UserIdentityId, UserIdentityName: userIdentity.Name, TotalPrice: total, Kind: req.Kind, OutTradeNo: outTradeNo, TradeNo: resp.TradeNo, State: enum2.CentralKitchenForSchoolPackageOrdStateForWait, OrdState: enum2.CentralKitchenForSchoolPackageOrdOrdStateForWait, ReqContent: string(utils.Serialize(req)), WithDayData: string(utils.Serialize(data)), PayWay: enum.PayWayForAli, CreateAt: now.Format("2006-01-02 15:04:05"), UpdateAt: now.Format("2006-01-02 15:04:05"), }) if err != nil { _ = session.Rollback() return } session.Commit() tradeNo = resp.TradeNo return } func BuyPackageForWx(c *gin.Context, req md.BuyPackageReq) (outTradeNo, total string, resp *jsapi2.PrepayWithRequestPaymentResponse, err error) { user := GetUser(c) session := db.Db.NewSession() defer session.Close() session.Begin() if err != nil { _ = session.Rollback() return } //1、判断是否为教师 isTeacher := false userIdentityDb := db.UserIdentityDb{} userIdentityDb.Set(0) userIdentity, err := userIdentityDb.GetUserIdentity(req.UserIdentityId) if err != nil { return } if userIdentity == nil { err = errors.New("未查询到对应身份记录") return } if userIdentity.Identity == enum2.UserIdentityForCentralKitchenForTeacher { isTeacher = true } //2、计算数据(1:按学期购买 2:按月购买 3:按天购买 4:补餐) var totalPrice float64 var data []*model.CentralKitchenForSchoolUserWithDay if req.Kind == 1 { totalPrice, data, err = CalcBySchoolTerm(user.Id, isTeacher, req) if err != nil { return } } if req.Kind == 2 { totalPrice, data, err = CalcByMonth(user.Id, isTeacher, req) if err != nil { return } } if req.Kind == 3 { totalPrice, data, err = CalcByDay(user.Id, isTeacher, req) if err != nil { return } } if req.Kind == 4 { totalPrice, data, err = CalcSupplementaryByDay(user.Id, isTeacher, req) if err != nil { return } } total = utils.Float64ToStr(totalPrice) //3、生成订单号 outTradeNo = utils.OrderUUID(user.Id) //4、请求 /v3/pay/partner/transactions/jsapi (生成预支付交易单) sysCfgDb := db.SysCfgDb{} sysCfgDb.Set() client, err := svc3.NewWxPayClient(c) if err != nil { return } wxSvc := jsapi.JsapiApiService{Client: client} sysCfg := sysCfgDb.SysCfgFindWithDb(enum2.WxSpAppId, enum2.WxSpMchId, enum2.WxAppletAppId, enum2.WxMchId, enum2.WxJsapiPayNotifyUrl) result, _, err := wxSvc.Prepay(c, jsapi.PrepayRequest{ SpAppid: core.String(sysCfg[enum2.WxSpAppId]), SpMchid: core.String(sysCfg[enum2.WxSpMchId]), SubAppid: core.String(sysCfg[enum2.WxAppletAppId]), SubMchid: core.String(sysCfg[enum2.WxMchId]), Description: core.String("购买食堂套餐"), OutTradeNo: core.String(outTradeNo), TimeExpire: core.Time(time.Now().Add(30 * time.Minute)), //Attach: core.String("自定义数据说明"), NotifyUrl: core.String(sysCfg[enum2.WxJsapiPayNotifyUrl]), Amount: &jsapi.Amount{ Currency: core.String("CNY"), Total: core.Int64(int64(totalPrice * 100)), }, Payer: &jsapi.Payer{ //SpOpenid: core.String("oUpF8uMuAJO_M2pxb1Q9zNjWeS6o"), SubOpenid: core.String(user.OpenId), }, }, ) fmt.Println(">>>>>>>>>>>", core.Int64(utils.StrToInt64(total)*100)) if err != nil { _ = session.Rollback() return } //5、插入订单记录 now := time.Now() centralKitchenForSchoolPackageOrd := db.CentralKitchenForSchoolPackageOrd{} centralKitchenForSchoolPackageOrd.Set(outTradeNo) _, err = centralKitchenForSchoolPackageOrd.CentralKitchenForSchoolPackageOrdInsertBySession(session, &model.CentralKitchenForSchoolPackageOrd{ EnterpriseId: req.EnterpriseId, Uid: user.Id, UserIdentityId: req.UserIdentityId, UserIdentityName: userIdentity.Name, TotalPrice: total, Kind: req.Kind, OutTradeNo: outTradeNo, TradeNo: "", State: enum2.CentralKitchenForSchoolPackageOrdStateForWait, OrdState: enum2.CentralKitchenForSchoolPackageOrdOrdStateForWait, ReqContent: string(utils.Serialize(req)), WithDayData: string(utils.Serialize(data)), PayWay: enum.PayWayForWx, CreateAt: now.Format("2006-01-02 15:04:05"), UpdateAt: now.Format("2006-01-02 15:04:05"), }) if err != nil { _ = session.Rollback() return } session.Commit() //prepayId = *resp.PrepayId resp = new(jsapi2.PrepayWithRequestPaymentResponse) resp.PrepayId = result.PrepayId resp.SignType = core.String("RSA") appid := sysCfg[enum2.WxSpAppId] resp.Appid = &appid resp.TimeStamp = core.String(strconv.FormatInt(time.Now().Unix(), 10)) nonce, err := utils2.GenerateNonce() if err != nil { _ = session.Rollback() return } resp.NonceStr = core.String(nonce) resp.Package = core.String("prepay_id=" + *result.PrepayId) message := fmt.Sprintf("%s\n%s\n%s\n%s\n", *resp.Appid, *resp.TimeStamp, *resp.NonceStr, *resp.Package) signatureResult, err := wxSvc.Client.Sign(c, message) if err != nil { _ = session.Rollback() return } resp.PaySign = core.String(signatureResult.Signature) return } func NursingHomeBuyPackageReq(c *gin.Context, req md.NursingHomeBuyPackageReq) (outTradeNo, tradeNo, total string, err error) { user := GetUser(c) session := db.Db.NewSession() defer session.Close() session.Begin() if err != nil { _ = session.Rollback() return } userIdentityDb := db.UserIdentityDb{} userIdentityDb.Set(0) userIdentity, err := userIdentityDb.GetUserIdentity(req.UserIdentityId) if err != nil { return } if userIdentity == nil { err = errors.New("未查询到对应身份记录") return } //1、计算数据(1:按年购买 2:按月购买 3:按天购买 4:补餐) var totalPrice float64 var data []*model.NursingHomeUserWithDay if req.Kind == 1 { totalPrice, data, err = CalcByYearForNursingHome(user.Id, req) if err != nil { return } } if req.Kind == 2 { totalPrice, data, err = CalcByMonthForNursingHome(user.Id, req) if err != nil { return } } if req.Kind == 3 { totalPrice, data, err = CalcByDayForNursingHome(user.Id, req) if err != nil { return } } if req.Kind == 4 { totalPrice, data, err = CalcByDayForNursingHome(user.Id, req) if err != nil { return } } total = utils.Float64ToStr(totalPrice) //3、生成订单号 outTradeNo = utils.OrderUUID(user.Id) //4、请求 alipay.trade.create(统一收单交易创建接口) sysCfgDb := db.SysCfgDb{} sysCfgDb.Set() sysCfg := sysCfgDb.SysCfgFindWithDb(enum2.OpenAppletAppid, enum2.OpenAlipayAppid, enum2.OpenAlipayAppPrivateKey, enum2.OpenAlipayPublicKey, enum2.JsapiPayAppAutToken) err, resp := CurlAlipayTradeCreate(md.CurlAlipayTradeCreateReq{ Config: struct { PayAliAppId string `json:"pay_ali_app_id" label:"支付宝开放平台-第三方应用-appid"` PayAliPrivateKey string `json:"pay_ali_private_key" label:"支付宝开放平台-第三方应用-接口加签-应用私钥"` PayAliPublicKey string `json:"pay_ali_public_key" label:"支付宝开放平台-第三方应用-接口加签-支付宝公钥"` }{ PayAliAppId: sysCfg[enum2.OpenAlipayAppid], PayAliPrivateKey: sysCfg[enum2.OpenAlipayAppPrivateKey], PayAliPublicKey: sysCfg[enum2.OpenAlipayPublicKey], }, OpAppId: sysCfg[enum2.OpenAppletAppid], BuyerId: user.UserId, TotalAmount: total, OutTradeNo: outTradeNo, Subject: "购买食堂套餐", AppAuthToken: sysCfg[enum2.JsapiPayAppAutToken], }) if err != nil { return } //5、插入订单记录 now := time.Now() NursingHomePackageOrd := db.NursingHomePackageOrd{} NursingHomePackageOrd.Set(outTradeNo) _, err = NursingHomePackageOrd.NursingHomePackageOrdInsertBySession(session, &model.NursingHomePackageOrd{ EnterpriseId: req.EnterpriseId, Uid: user.Id, UserIdentityId: req.UserIdentityId, UserIdentityName: userIdentity.Name, TotalPrice: total, Kind: req.Kind, OutTradeNo: outTradeNo, TradeNo: resp.TradeNo, State: enum2.NursingHomePackageOrdStateForWait, OrdState: enum2.NursingHomePackageOrdOrdStateForWait, ReqContent: string(utils.Serialize(req)), WithDayData: string(utils.Serialize(data)), CreateAt: now.Format("2006-01-02 15:04:05"), UpdateAt: now.Format("2006-01-02 15:04:05"), }) if err != nil { _ = session.Rollback() return } session.Commit() tradeNo = resp.TradeNo return } func DealCentralKitchenForSchoolOrderCallBack(outTradeNo, tradeStatus string) (state int, err error) { centralKitchenForSchoolPackageOrd := db.CentralKitchenForSchoolPackageOrd{} centralKitchenForSchoolPackageOrd.Set(outTradeNo) ord, err := centralKitchenForSchoolPackageOrd.GetCentralKitchenForSchoolPackageOrd() if err != nil { return } if ord == nil { err = errors.New("未查询到对应订单记录") return } if ord.State == enum2.CentralKitchenForSchoolPackageOrdStateForWait { if tradeStatus == "TRADE_CLOSED" { ord.State = enum2.CentralKitchenForSchoolPackageOrdStateForFail } if tradeStatus == "TRADE_SUCCESS" { ord.State = enum2.CentralKitchenForSchoolPackageOrdStateForSuccess ord.OrdState = enum2.CentralKitchenForSchoolPackageOrdOrdStateForSuccess //TODO::将预留数据插入到 `central_kitchen_for_school_user_with_day` var data []*model.CentralKitchenForSchoolUserWithDay err = json.Unmarshal([]byte(ord.WithDayData), &data) if err != nil { return } var hasMonths = map[string]map[string]interface{}{} var hasKinds = map[string]map[string]string{} var hasTotalPrice = map[string]map[string]float64{} for _, v := range data { date, _ := time.ParseInLocation("2006-01-02", v.Date, time.Local) if hasMonths[utils.TimeParseStd(v.Date).Month().String()] == nil { hasMonths[utils.TimeParseStd(v.Date).Month().String()] = make(map[string]interface{}) hasMonths[utils.TimeParseStd(v.Date).Month().String()]["meal_time_start"] = date.Format("2006-01-02") hasMonths[utils.TimeParseStd(v.Date).Month().String()]["meal_time_end"] = date.Format("2006-01-02") } else { startTime, _ := time.ParseInLocation("2006-01-02", utils.AnyToString(hasMonths[utils.TimeParseStd(v.Date).Month().String()]["meal_time_start"]), time.Local) if startTime.After(date) { hasMonths[utils.TimeParseStd(v.Date).Month().String()]["meal_time_start"] = date.Format("2006-01-02") } endTime, _ := time.ParseInLocation("2006-01-02", utils.AnyToString(hasMonths[utils.TimeParseStd(v.Date).Month().String()]["meal_time_end"]), time.Local) if endTime.Before(date) { hasMonths[utils.TimeParseStd(v.Date).Month().String()]["meal_time_end"] = date.Format("2006-01-02") } } if hasTotalPrice[utils.TimeParseStd(v.Date).Month().String()] == nil { hasTotalPrice[utils.TimeParseStd(v.Date).Month().String()] = make(map[string]float64) } if hasKinds[utils.TimeParseStd(v.Date).Month().String()] == nil { hasKinds[utils.TimeParseStd(v.Date).Month().String()] = make(map[string]string) } hasMonths[utils.TimeParseStd(v.Date).Month().String()]["month"] = int(utils.TimeParseStd(v.Date).Month()) hasKinds[utils.TimeParseStd(v.Date).Month().String()][utils.IntToStr(v.Kind)] = utils.IntToStr(v.Kind) hasTotalPrice[utils.TimeParseStd(v.Date).Month().String()][utils.IntToStr(v.Kind)] += utils.StrToFloat64(v.Amount) v.OrdNo = outTradeNo } centralKitchenForSchoolUserWithDayDb := db.CentralKitchenForSchoolUserWithDayDb{} centralKitchenForSchoolUserWithDayDb.Set(0) _, err = centralKitchenForSchoolUserWithDayDb.BatchAddCentralKitchenForSchoolUserWithDays(data) if err != nil { return } //TODO::插入数据至 `central_kitchen_for_school_package_ord_for_reserve` centralKitchenForSchoolPackageOrdForReserve := db.CentralKitchenForSchoolPackageOrdForReserve{} centralKitchenForSchoolPackageOrdForReserve.Set(outTradeNo) for k, v := range hasMonths { for _, v1 := range hasKinds[k] { _, err = centralKitchenForSchoolPackageOrdForReserve.CentralKitchenForSchoolPackageOrdForReserveInsert(&model.CentralKitchenForSchoolPackageOrdForReserve{ EnterpriseId: ord.EnterpriseId, Uid: ord.Uid, UserIdentityName: ord.UserIdentityName, UserIdentityId: ord.UserIdentityId, Kind: utils.StrToInt(v1), OutTradeNo: ord.OutTradeNo, ReserveMonth: utils.AnyToString(v["month"]), MealTimeStart: utils.AnyToString(v["meal_time_start"]), MealTimeEnd: utils.AnyToString(v["meal_time_end"]), TotalPrice: utils.Float64ToStr(hasTotalPrice[k][v1]), CreateAt: time.Now().Format("2006-01-02 15:04:05"), UpdateAt: time.Now().Format("2006-01-02 15:04:05"), }) if err != nil { return } } } } _, err = centralKitchenForSchoolPackageOrd.CentralKitchenForSchoolPackageOrdUpdate(ord, "state", "ord_state") if err != nil { return } } state = ord.State return } func CheckAllCallbackParams(c *gin.Context) interface{} { body, _ := ioutil.ReadAll(c.Request.Body) utils.FilePutContents("CheckAllCallbackParams", utils.SerializeStr(string(body))) dataAlipay, _ := GetAlipayCallbackParams(body) if dataAlipay != nil { return dataAlipay } return nil } // GetAlipayCallbackParams 支付宝参数解析 func GetAlipayCallbackParams(body []byte) (*md.AliPayCallback, error) { decodeArgs, err := url.QueryUnescape(string(body)) if err != nil { _ = logx.Warn(err) return nil, logx.Warn("回调参数解码错误") } data, err := url.ParseQuery(decodeArgs) if err != nil { return nil, err } dataMap := make(map[string]interface{}) for k := range data { dataMap[k] = data.Get(k) } callbackStr := utils.Serialize(dataMap) fmt.Println("支付宝回调数据", string(callbackStr)) var args md.AliPayCallback if err := json.Unmarshal(callbackStr, &args); err != nil { return nil, logx.Warn(err) } return &args, nil }