package localjx import ( "errors" "fmt" "git.rosy.net.cn/baseapi/platformapi/kuaishou_mini" beego "github.com/astaxie/beego/server/web" "strings" "time" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/auth2/authprovider/kuaishou" "git.rosy.net.cn/jx-callback/business/jxutils" "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/model/dao" "git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals/api" ) func getOrderBriefKs(order *model.GoodsOrder) string { sku := make([]string, len(order.Skus)) for _, v := range order.Skus { sku = append(sku, fmt.Sprintf("%s x %d件商品", v.SkuName, v.Count)) } return strings.Join(sku, ",") } func pay4OrderByKs(ctx *jxcontext.Context, order *model.GoodsOrder, vendorPayType, subAppID string) (orderPay *model.OrderPay, err error) { // 获取用户快手OpenId var ( db = dao.GetDB() ) authBindList, err := dao.GetUserBindAuthInfo(db, ctx.GetUserID(), model.AuthBindTypeAuth, []string{kuaishou.AuthTypeKuaiShouMini}, "", "", nil) if err != nil { return nil, err } if len(authBindList) == model.NO { return nil, errors.New("用户未绑定快手,无法快手支付") } param := &kuaishou_mini.PreCreateOrderReq{ OutOrderNo: utils.Int64ToStr(GenPayOrderID(order)), OpenId: authBindList[0].AuthID, TotalAmount: order.ActualPayPrice, Subject: "蔬菜水果日用品", Detail: getOrderBriefKs(order), TypeDetail: 1832, // 蔬菜:费率2%,水果:1833%2 ExpireTime: 60 * 10, Sign: "", //Attach: "", //GoodsId: "", //GoodsDetailUrl: "", //MultiCopiesGoodsInfo: "", CancelOrder: 0, } if beego.BConfig.RunMode == "jxgy" { param.NotifyUrl = "https://callback-jxgy.jxc4.com/kuaishou/kuaiShouCallback" } else { param.NotifyUrl = "https://callback.jxc4.com/kuaishou/kuaiShouCallback" } // 预下单 prePayInfo, err := api.KuaiShouApi.PreCreateOrder(param) if err == nil { orderPay = &model.OrderPay{ PayOrderID: order.VendorOrderID, // 抖音订单id PayType: model.PayTypeKuaiShou, VendorPayType: vendorPayType, VendorOrderID: order.VendorOrderID, VendorID: order.VendorID, Status: 0, PayCreatedAt: time.Now(), PrepayID: prePayInfo.OrderNo, CodeURL: prePayInfo.OrderInfoToken, // 抖音支付token TotalFee: int(order.ActualPayPrice), } } return orderPay, err } func OnKSPayCallback(msg *kuaishou_mini.CallBackDetail, refund *kuaishou_mini.RefundCallBack, payType string) (err error) { switch payType { case kuaishou_mini.CallbackTypePay: // 支付回调 err = onKSPayFinished(msg) case kuaishou_mini.CallbackTypeRefund: // 退款回调 err = onKSPayRefund(refund) } return err } func onKSPayFinished(msg *kuaishou_mini.CallBackDetail) (err error) { orderPay := &model.OrderPay{ PayOrderID: msg.OutOrderNo, PayType: model.PayTypeKuaiShou, } orderPay.DeletedAt = utils.DefaultTimeValue db := dao.GetDB() if err = dao.GetEntity(db, orderPay, "PayOrderID", "PayType", "DeletedAt"); err == nil { orderPay.PayFinishedAt = utils.Time2Pointer(time.Now()) orderPay.TransactionID = msg.TradeNo orderPay.OriginalData = utils.Format4Output(msg, true) switch msg.Status { case kuaishou_mini.OrderPayStatusHandleing: orderPay.Status = model.PayStatusNo case kuaishou_mini.OrderPayStatusSuccess: orderPay.Status = model.PayStatusYes case kuaishou_mini.OrderPayStatusFailed: orderPay.Status = model.PayStatusFailed } dao.UpdateEntity(db, orderPay) if msg.Status == kuaishou_mini.OrderPayStatusSuccess { err = OnPayFinished(orderPay) } } else { globals.SugarLogger.Debugf("onKSPayFinished msg:%s, err:%v", utils.Format4Output(msg, true), err) } return err } func onKSPayRefund(msg *kuaishou_mini.RefundCallBack) (err error) { orderPayRefund := &model.OrderPayRefund{ RefundID: msg.OutRefundNo, } db := dao.GetDB() if err = dao.GetEntity(db, orderPayRefund, "RefundID"); err == nil { switch msg.Status { case kuaishou_mini.OrderPayStatusHandleing: orderPayRefund.Status = model.PayStatusNo case kuaishou_mini.OrderPayStatusSuccess: orderPayRefund.Status = model.PayStatusYes case kuaishou_mini.OrderPayStatusFailed: orderPayRefund.Status = model.PayStatusFailed } orderPayRefund.OriginalData = utils.Format4Output(msg, true) dao.UpdateEntity(db, orderPayRefund) } else if dao.IsNoRowsError(err) { globals.SugarLogger.Warnf("收到异常的退款事件, msg:%s", utils.Format4Output(msg, true)) } orderPay := &model.OrderPay{ VendorOrderID: orderPayRefund.VendorOrderID, VendorID: jxutils.GetPossibleVendorIDFromVendorOrderID(orderPayRefund.VendorOrderID), PayType: model.PayTypeKuaiShou, Status: model.PayStatusYes, } orderPay.DeletedAt = utils.DefaultTimeValue if err = dao.GetEntity(db, orderPay, "VendorOrderID", "VendorID", "PayType", "Status", "DeletedAt"); err == nil { orderPay.Status = model.PayStatusRefund dao.UpdateEntity(db, orderPay) } return err } // RefundOrderByKS 申请退款 func RefundOrderByKS(ctx *jxcontext.Context, orderPay *model.OrderPay, refundID string, refundFee int, refundDesc string) (orderPayRefund *model.OrderPayRefund, err error) { param := kuaishou_mini.RefundParam{ OutOrderNo: orderPay.VendorOrderID, OutRefundNo: refundID, Reason: refundDesc, Attach: "", NotifyUrl: "https://callback.jxc4.com/kuaishou/kuaiShouCallback", RefundAmount: int64(orderPay.TotalFee), Sign: "", MultiCopiesGoodsInfo: "", } result, err := api.KuaiShouApi.RefundOrder(¶m) if err == nil { orderPayRefund = &model.OrderPayRefund{ RefundID: refundID, VendorRefundID: result, VendorOrderID: orderPay.VendorOrderID, VendorID: orderPay.VendorID, Status: model.RefundStatusNo, TransactionID: orderPay.TransactionID, RefundFee: refundFee, RefundCreatedAt: time.Now(), } dao.WrapAddIDCULDEntity(orderPayRefund, ctx.GetUserName()) db := dao.GetDB() if result != "" { orderPayRefund.Status = model.RefundStatusYes } else { orderPayRefund.Status = model.RefundStatusFailed } orderPayRefund.OriginalData = utils.Format4Output(result, true) dao.CreateEntity(db, orderPayRefund) orderPay.Status = model.PayStatusRefund dao.UpdateEntity(db, orderPay) } return orderPayRefund, err }