package paymentapiimp import ( "encoding/json" "net/http" "strings" "github.com/tech/sendico/pkg/api/http/response" "github.com/tech/sendico/pkg/merrors" "github.com/tech/sendico/pkg/model" "github.com/tech/sendico/pkg/mutil/mzap" orchestrationv2 "github.com/tech/sendico/pkg/proto/payments/orchestration/v2" "github.com/tech/sendico/server/interface/api/srequest" "github.com/tech/sendico/server/interface/api/sresponse" mutil "github.com/tech/sendico/server/internal/mutil/param" "go.mongodb.org/mongo-driver/v2/bson" "go.uber.org/zap" ) func (a *PaymentAPI) initiatePaymentsByQuote(r *http.Request, account *model.Account, token *sresponse.TokenData) http.HandlerFunc { orgRef, err := a.oph.GetRef(r) if err != nil { a.logger.Warn("Failed to parse organization reference for batch payment initiation", zap.Error(err), zap.String(a.oph.Name(), a.oph.GetID(r))) return response.BadReference(a.logger, a.Name(), a.oph.Name(), a.oph.GetID(r), err) } ctx := r.Context() allowed, err := a.enf.Enforce(ctx, a.permissionRef, account.ID, orgRef, bson.NilObjectID, model.ActionCreate) if err != nil { a.logger.Warn("Failed to check payments access permissions", zap.Error(err), mutil.PLog(a.oph, r)) return response.Auto(a.logger, a.Name(), err) } if !allowed { a.logger.Debug("Access denied when initiating batch payments", mutil.PLog(a.oph, r)) return response.AccessDenied(a.logger, a.Name(), "payments write permission denied") } payload, err := decodeInitiatePaymentsPayload(r) if err != nil { return response.BadPayload(a.logger, a.Name(), err) } clientPaymentRef := strings.TrimSpace(payload.ClientPaymentRef) idempotencyKey := strings.TrimSpace(payload.IdempotencyKey) quotationRef := strings.TrimSpace(payload.QuoteRef) req := &orchestrationv2.ExecuteBatchPaymentRequest{ Meta: requestMeta(orgRef.Hex(), idempotencyKey), QuotationRef: quotationRef, ClientPaymentRef: clientPaymentRef, } resp, err := a.execution.ExecuteBatchPayment(ctx, req) if err != nil { a.logger.Warn("Failed to initiate batch payments", zap.Error(err), mzap.ObjRef("organization_ref", orgRef)) return grpcErrorResponse(a.logger, a.Name(), err) } payments := make([]*orchestrationv2.Payment, 0) if resp != nil { payments = append(payments, resp.GetPayments()...) } return sresponse.PaymentsResponse(a.logger, payments, token) } func decodeInitiatePaymentsPayload(r *http.Request) (*srequest.InitiatePayments, error) { defer r.Body.Close() payload := &srequest.InitiatePayments{} decoder := json.NewDecoder(r.Body) decoder.DisallowUnknownFields() if err := decoder.Decode(payload); err != nil { return nil, merrors.InvalidArgument("invalid payload: " + err.Error()) } payload.IdempotencyKey = strings.TrimSpace(payload.IdempotencyKey) payload.QuoteRef = strings.TrimSpace(payload.QuoteRef) payload.ClientPaymentRef = strings.TrimSpace(payload.ClientPaymentRef) if err := payload.Validate(); err != nil { return nil, err } return payload, nil }