// Copyright 2019 getensh.com. All rights reserved. // Use of this source code is governed by getensh.com. package charge import ( "context" "encoding/json" "fmt" "property-garden/errors" "property-garden/impl/v1/charge_utils" dbmodel "property-garden/model" "property-garden/pb" pb_v1 "property-garden/pb/v1" "property-garden/utils" "strings" "time" "git.getensh.com/common/gopkgs/database" "git.getensh.com/common/gopkgs/logger" "go.uber.org/zap" "google.golang.org/grpc/status" ) func checkChargeBillPayByHouseholdParam(req *pb_v1.ChargeBillPayByHouseholdRequest) error { switch { case req.GardenId == 0: return status.Error(10003, "小区不能为空") case req.PayType == 0: return status.Error(10003, "缴费方式不能为空") case req.ShouldPayAmount == 0: return status.Error(10003, "应缴金额不能为空") case req.PayAmount == 0: return status.Error(10003, "实缴金额不能为空") case len(req.BillIds) == 0 && len(req.BindIds) == 0: return status.Error(10003, "缴费对象不能为空") case req.HouseholdUid == 0 && !req.Native: return status.Error(10003, "住户id不能为空") } return nil } func ThirdpartyPay(openId string, inputIp string, amount int64, orderId string, product string, mchid string, native bool) (string, string, string, error) { mreq := pb_v1.WxAppletPrepayRequest{ Order: orderId, Product: product, OpenId: openId, Amount: amount, InputIp: inputIp, MchId: mchid, Native: native, } mreply, err := pb.Thirdparty.WxAppletPrepay(context.Background(), &mreq) if err != nil { return "", "", "", err } return mreply.PrepayId, mreply.Prepay, mreply.CodeUrl, nil } func householdChargeBillPayByBindIds(req *pb_v1.ChargeBillPayByHouseholdRequest, dbname string, mchId string) (reply *pb_v1.ChargeBillPayByHouseholdReply, err error) { reply = &pb_v1.ChargeBillPayByHouseholdReply{} bill := dbmodel.NewChargeBill(dbname) where := map[string]interface{}{ "charge_bind_id in": req.BindIds, } chargeInfoM, err := charge_utils.GetAllChargeInfos(dbname) if err != nil { return nil, err } db := database.DB().Begin() defer func() { if err != nil { db.Rollback() } }() list, err := bill.List(db, where, nil, -1, -1, "") if err != nil { return nil, errors.DataBaseError } amount := int64(0) billIds := []string{} billIdsInt := []int64{} objName := "" productM := map[string]bool{} lateFeeBool := false orders := []string{} for i, v := range list { billIds = append(billIds, fmt.Sprintf("%v", v.ID)) productM[charge_utils.ChargeTypeM[v.ChargeType]] = true objName = v.ObjName chargeInfo := chargeInfoM[v.ChargeId] billIdsInt = append(billIdsInt, v.ID) amount += v.Amount list[i].LateFee, _ = charge_utils.GetLateFee(v.Amount, v.ChargeEnd, &chargeInfo) amount += list[i].LateFee if list[i].LateFee > 0 { lateFeeBool = true } if v.OrderId != "" { orders = append(orders, v.OrderId) } } isPaying := false isPaying, err = charge_utils.IsOrderPaying(orders, dbname, db) if err != nil { return nil, err } if isPaying { return nil, status.Error(10003, "无法支付,有订单正在支付中") } product := "" for k, _ := range productM { product = product + k + ";" } if amount != req.ShouldPayAmount { return nil, status.Error(10003, "应缴错误") } if req.ShouldPayAmount != req.PayAmount && req.Comment == "" { return nil, status.Error(10003, "应缴金额与实缴金额不一致,需添加备注") } //生成订单 orderId, err := GenerateOrderId(req.GardenId, OrderTypeLife) if err != nil { return nil, err } //调用三方预支付 thirdPrepayId, thirdPrepayInfo, codeUrl, err := ThirdpartyPay(req.OpenId, req.InputIp, req.ShouldPayAmount, orderId, product, mchId, req.Native) if err != nil { return nil, err } // 更新订单状态 now := time.Now() values := map[string]interface{}{ "comment": req.Comment, "pay_time": now.Unix(), "pay_mode": 1, "uid": req.HouseholdUid, "order_id": orderId, "pay_type": req.PayType, "status": charge_utils.PayStatusUnPay, } // 没有滞纳金批量更新 if !lateFeeBool { bill.SetTable(dbname) err = bill.Update(db, where, values) if err != nil { return nil, errors.DataBaseError } } else { // 有滞纳金逐个更新 for _, v := range list { values["late_fee"] = v.LateFee where = map[string]interface{}{ "id": v.ID, } bill.SetTable(dbname) err = bill.Update(db, where, values) if err != nil { return nil, errors.DataBaseError } } } // 插入订单 order := dbmodel.TChargeOrder{ OrderId: orderId, Comment: req.Comment, Amount: req.ShouldPayAmount, PayAmount: req.PayAmount, PayType: req.PayType, CreatedAt: now, Uid: req.HouseholdUid, PackageId: 0, PrepayId: thirdPrepayId, TransactionId: "", Status: charge_utils.PayStatusUnPay, PayingDesc: "生活缴费", PayTime: now.Unix(), BillIds: strings.Join(billIds, ","), ObjName: objName, } order.SetTable(dbname) err = order.Insert(db) if err != nil { return nil, errors.DataBaseError } db.Commit() reply.OrderId = orderId reply.PrepayInfo = thirdPrepayInfo reply.CodeUrl = codeUrl return reply, nil } func householdChargeBillPayByBillIds(req *pb_v1.ChargeBillPayByHouseholdRequest, dbname string, mchId string) (reply *pb_v1.ChargeBillPayByHouseholdReply, err error) { reply = &pb_v1.ChargeBillPayByHouseholdReply{} chargeInfoM, err := charge_utils.GetAllChargeInfos(dbname) if err != nil { return nil, err } bill := dbmodel.NewChargeBill(dbname) where := map[string]interface{}{ "id in": req.BillIds, } db := database.DB().Begin() defer func() { if err != nil { db.Rollback() } }() list, err := bill.List(db, where, nil, -1, -1, "") if err != nil { return nil, errors.DataBaseError } if len(list) == 0 { return nil, status.Error(10003, "没有账单") } amount := int64(0) billIds := []string{} productM := map[string]bool{} lateFeeBool := false orders := []string{} for i, v := range list { billIds = append(billIds, fmt.Sprintf("%v", v.ID)) productM[charge_utils.ChargeTypeM[v.ChargeType]] = true chargeInfo := chargeInfoM[v.ChargeId] amount += v.Amount list[i].LateFee, _ = charge_utils.GetLateFee(v.Amount, v.ChargeEnd, &chargeInfo) amount += list[i].LateFee if list[i].LateFee > 0 { lateFeeBool = true } if v.OrderId != "" { orders = append(orders, v.OrderId) } } isPaying := false isPaying, err = charge_utils.IsOrderPaying(orders, dbname, db) if err != nil { return nil, err } if isPaying { return nil, status.Error(10003, "无法支付,有订单正在支付中") } if amount != req.ShouldPayAmount { return nil, status.Error(10003, "应缴错误") } if req.ShouldPayAmount != req.PayAmount && req.Comment == "" { return nil, status.Error(10003, "应缴金额与实缴金额不一致,需添加备注") } product := "" for k, _ := range productM { product = product + k + ";" } // 生成订单 orderId, err := GenerateOrderId(req.GardenId, OrderTypeLife) if err != nil { return nil, err } //调用三方预支付 thirdPrepayId, thirdPrepayInfo, codeUrl, err := ThirdpartyPay(req.OpenId, req.InputIp, req.ShouldPayAmount, orderId, product, mchId, req.Native) if err != nil { return nil, err } // 更新订单状态 now := time.Now() values := map[string]interface{}{ "comment": req.Comment, "pay_time": now.Unix(), "pay_mode": 1, "uid": req.HouseholdUid, "order_id": orderId, "pay_type": req.PayType, "status": charge_utils.PayStatusUnPay, } // 没有滞纳金批量更新 if !lateFeeBool { bill.SetTable(dbname) err = bill.Update(db, where, values) if err != nil { return nil, errors.DataBaseError } } else { // 有滞纳金逐个更新 for _, v := range list { values["late_fee"] = v.LateFee where = map[string]interface{}{ "id": v.ID, } bill.SetTable(dbname) err = bill.Update(db, where, values) if err != nil { return nil, errors.DataBaseError } } } order := dbmodel.TChargeOrder{ OrderId: orderId, Comment: req.Comment, Amount: req.ShouldPayAmount, PayAmount: req.PayAmount, PayType: req.PayType, CreatedAt: now, Uid: req.HouseholdUid, PackageId: 0, PrepayId: thirdPrepayId, TransactionId: "", Status: charge_utils.PayStatusUnPay, PayingDesc: "生活缴费", PayTime: now.Unix(), BillIds: strings.Join(billIds, ","), ObjName: list[0].ObjName, } order.SetTable(dbname) err = order.Insert(db) if err != nil { return nil, errors.DataBaseError } db.Commit() reply.OrderId = orderId reply.PrepayInfo = thirdPrepayInfo reply.CodeUrl = codeUrl return reply, nil } func ChargeBillPayByHousehold(ctx context.Context, req *pb_v1.ChargeBillPayByHouseholdRequest) (reply *pb_v1.ChargeBillPayByHouseholdReply, err error) { reply = &pb_v1.ChargeBillPayByHouseholdReply{} // 捕获各个task中的异常并返回给调用者 defer func() { if r := recover(); r != nil { err = fmt.Errorf("%+v", r) e := &status.Status{} if er := json.Unmarshal([]byte(err.Error()), e); er != nil { logger.Error("err", zap.String("system_err", err.Error()), zap.Stack("stacktrace")) } } }() // 参数检查 err = checkChargeBillPayByHouseholdParam(req) if err != nil { return nil, err } mchId, err := charge_utils.CheckMchPayMode(req.GardenId) if err != nil { return nil, err } dbname := utils.GetGardenDbName(req.GardenId) if len(req.BillIds) > 0 { return householdChargeBillPayByBillIds(req, dbname, mchId) } return householdChargeBillPayByBindIds(req, dbname, mchId) }