package thirdpay import ( "PaymentCenter/app/constants/common" "PaymentCenter/app/constants/errorcode" "PaymentCenter/app/http/entities/backend" "PaymentCenter/app/http/entities/front" "PaymentCenter/app/models/orderrequestlogmodel" "PaymentCenter/app/models/ordersmodel" "PaymentCenter/app/models/paychannelmodel" "PaymentCenter/app/services" "PaymentCenter/app/services/thirdpay/do" "PaymentCenter/app/third/paymentService" "PaymentCenter/app/third/paymentService/payCommon" "PaymentCenter/app/utils" "PaymentCenter/config" "context" "encoding/json" "fmt" "strconv" "time" "xorm.io/builder" ) // 收银台获取付款链接 func GetPayLinkService(req front.GetPayLinkRequest) (result, message string, code int) { defer func() { if err := recover(); err != nil { utils.Log(nil, "", "GetPayLinkService,获取支付链接失败", fmt.Sprintf("错误原因:%s", err)) code = errorcode.SystemError } }() var ( payChannel = &paychannelmodel.PayChannel{} order = &ordersmodel.Orders{} orderPayRequest front.PayReqsV2 ) // 支付方式校验 payChannel, code = services.PayChannelFindOne(payChannel, builder.Eq{"id": req.PayChannelId}) if code != errorcode.Success { return } if !payChannel.ExpireTime.IsZero() && payChannel.ExpireTime.Unix() < time.Now().Unix() { code = errorcode.PayChannelExpired return } // 订单校验 order, code = services.OrderFindOne(order, builder.Eq{"id": req.OrderId}) if code != errorcode.Success { return } // 订单状态校验 code = services.OrderStatusCheck(*order) if code != errorcode.Success { return } // 订单的支付方式是否一致, 不一致则更新 if order.PayChannelId != payChannel.Id { order.PayChannelId = payChannel.Id code = services.OrderUpdate(order) if code != errorcode.Success { return } } // 获取订单的请求参数 orderRequestLog := orderrequestlogmodel.OrderRequestLog{ OutTradeNo: order.OutTradeNo, AppId: order.AppId, } has, err := services.OrderRequestLogs(&orderRequestLog) if err != nil { code = handErr(err) return } if !has { code = errorcode.OrderPayRequestLogNotExist return } err = json.Unmarshal([]byte(orderRequestLog.MerchantRequest), &orderPayRequest) if err != nil { code = handErr(err) return } // 支付方式需要用户授权 if payChannel.ChannelType == common.PAY_CHANNEL_WECHAT_JSAPI && orderPayRequest.OpenId == "" { result, code = do.GetWxAuthUrl(payChannel.AppId, order.Id) return } // 请求第三方支付获取付款链接 payParam := paymentService.PayOrderRequest{ PayChannelId: payChannel.Id, OrderId: order.Id, ChannelType: payChannel.ChannelType, Description: orderPayRequest.Desc, Amount: orderPayRequest.Amount, PayerClientIp: req.ClientIp, ReturnUrl: orderPayRequest.ReturnUrl, OpenId: orderPayRequest.OpenId, } // 判断是否是支持的支付渠道,找到对应的配置 var payFunc func(commonPayInfo *paymentService.PayOrderRequest, channel *paychannelmodel.PayChannel) error var ok bool if payFunc, ok = do.PayWayList[payChannel.ChannelType]; !ok { code = errorcode.PayChannelNotBuild return } err = payFunc(&payParam, payChannel) if err != nil { code = errorcode.PayChannelExtJsonError return } res := paymentService.PaymentService(context.Background(), payParam) // 下单失败 if res.Code != payCommon.PAY_SUCCESS_CODE { code = errorcode.PrePayFail message = res.ErrorMsg return } // 更新订单状态 order.Status = common.ORDER_STATUS_PAYING code = services.OrderUpdate(order, "status") if code != errorcode.Success { utils.Log(nil, "成功下单,更新订单状态失败", order) } result = res.Result code = res.Code return } // 预支付 type payUrl struct { ClientIp string param front.PayReqsV2 app *services.AppCheck result front.PayReqsV2Response } func NewPayUrl(param front.PayReqsV2) *payUrl { return &payUrl{ param: param, } } func (this *payUrl) WithApp(app *services.AppCheck) *payUrl { this.app = app return this } func (this *payUrl) WithClientIp(ip string) *payUrl { this.ClientIp = ip return this } func (this *payUrl) saveOrder() { order := &ordersmodel.Orders{ MerchantId: this.app.App.MerchantId, //PayChannelId: w.PayParam.Channel.Id, AppId: this.app.App.Id, OutTradeNo: this.param.OutTradeNo, OrderType: common.ORDER_TYPE_PAY, Amount: this.param.Amount, ExtJson: this.param.ExtJson, Desc: this.param.Desc, Status: common.ORDER_STATUS_WAITPAY, } this.result.Order, this.result.PayCode = services.OrderCreate(order) } func (this *payUrl) PayUrlV2Service() (result front.PayReqsV2Response, code int) { var ( channelList []paychannelmodel.PayChannel order = new(ordersmodel.Orders) ) // redis 分布式锁 订单号幂等 key := utils.GetRealKey("payUrl:" + this.param.OutTradeNo) lockValue := fmt.Sprintf("%d", time.Now().UnixNano()) ok, err := utils.AcquireLock(key, lockValue, time.Second*time.Duration(3)) if ok { defer utils.ReleaseLock(key, lockValue) } else { if err != nil { utils.Log(nil, "", "PayUrlV2Service,获取分布式锁失败", fmt.Sprintf("错误原因:%s", err.Error())) } return } // 商户是否有配置支付渠道 channelList, _, code = services.PayChannelList(backend.PayChannelListRequest{MerchantId: this.app.App.MerchantId}) if code != errorcode.Success { return } if len(channelList) == 0 { code = errorcode.PayChannelNotFound return } // 订单是否存在 conn := builder.NewCond() conn = conn.And(builder.Eq{"out_trade_no": this.param.OutTradeNo}) conn = conn.And(builder.Eq{"app_id": this.param.AppId}) order, code = services.OrderFindOne(order, conn) if code == errorcode.Success { // 订单存在 this.result.Order = order this.result.PayCode = services.OrderStatusCheck(*order) } else if code == errorcode.OrdersNotFound { // 订单不存在 this.saveOrder() } else { return } code = this.result.PayCode if code == errorcode.Success { this.result.Url = config.GetConf().PayService.Host + common.PayPageAddress + "?no=" + strconv.FormatInt(this.result.Order.Id, 10) } return this.result, code } func PayPageCheckOrder(orderId string) (order ordersmodel.Orders, code int) { orderInfo := &ordersmodel.Orders{} orderInfo, code = services.OrderFindOne(&ordersmodel.Orders{}, builder.Eq{"id": orderId}) if code != errorcode.Success { return } code = services.OrderStatusCheck(*orderInfo) return *orderInfo, code }