94 lines
3.0 KiB
Go
94 lines
3.0 KiB
Go
package rechargeser
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"unicode/utf8"
|
|
|
|
"91porn-server/models/commod"
|
|
"91porn-server/models/v/vipcardexperimentmod"
|
|
|
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
|
)
|
|
|
|
const maxAttributionValueLength = 128
|
|
|
|
func (r *RechargeRequest) normalizeAttribution() {
|
|
r.SourcePage = NormalizeOrderSourcePage(r.SourcePage)
|
|
r.SourceRef = strings.TrimSpace(r.SourceRef)
|
|
r.VideoID = strings.TrimSpace(r.VideoID)
|
|
r.ActivityID = strings.TrimSpace(r.ActivityID)
|
|
r.ExperimentID = strings.TrimSpace(r.ExperimentID)
|
|
r.ExperimentVariant = strings.ToUpper(strings.TrimSpace(r.ExperimentVariant))
|
|
r.SessionID = strings.TrimSpace(r.SessionID)
|
|
r.CheckoutContextID = strings.TrimSpace(r.CheckoutContextID)
|
|
}
|
|
|
|
func (r *RechargeRequest) validateAttribution(uid uint64) error {
|
|
r.normalizeAttribution()
|
|
if utf8.RuneCountInString(r.SourcePage) > maxAttributionValueLength {
|
|
return fmt.Errorf("sourcePage must not exceed %d characters", maxAttributionValueLength)
|
|
}
|
|
if r.SourcePage == OrderSourcePageDramaPaywall {
|
|
if r.BuyType != commod.BuyGold && r.BuyType != commod.BuyProduct {
|
|
return fmt.Errorf("buyType must be 1 or 4 for DRAMA_PAYWALL")
|
|
}
|
|
// sourceRef is the generic order attribution field. For drama paywall
|
|
// orders, derive it from the backend-issued checkout context instead of
|
|
// requiring clients to submit the same identifier twice. The remaining
|
|
// drama fields are attribution-only and must not block a real payment.
|
|
if len(r.CheckoutContextID) > maxAttributionValueLength {
|
|
r.CheckoutContextID = ""
|
|
}
|
|
r.SourceRef = r.CheckoutContextID
|
|
}
|
|
values := map[string]string{
|
|
"sourceRef": r.SourceRef,
|
|
"videoId": r.VideoID,
|
|
"activityId": r.ActivityID,
|
|
"experimentId": r.ExperimentID,
|
|
"experimentVariant": r.ExperimentVariant,
|
|
"sessionId": r.SessionID,
|
|
"checkoutContextId": r.CheckoutContextID,
|
|
}
|
|
for name, value := range values {
|
|
if len(value) > maxAttributionValueLength {
|
|
return fmt.Errorf("%s must not exceed %d characters", name, maxAttributionValueLength)
|
|
}
|
|
}
|
|
if r.ExperimentID == "" {
|
|
r.ExperimentVariant = ""
|
|
return nil
|
|
}
|
|
if r.ExperimentVariant == "" || r.SessionID == "" {
|
|
return fmt.Errorf("experimentVariant and sessionId are required with experimentId")
|
|
}
|
|
experiment, err := vipcardexperimentmod.FindByExperimentID(r.ExperimentID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if experiment == nil {
|
|
return fmt.Errorf("experiment does not exist")
|
|
}
|
|
config, ok := experiment.ConfigFor(r.ExperimentVariant)
|
|
if !ok {
|
|
return fmt.Errorf("experimentVariant must be A or B")
|
|
}
|
|
if assigned := experiment.Assign(uid); assigned != r.ExperimentVariant {
|
|
return fmt.Errorf("experimentVariant does not match user assignment")
|
|
}
|
|
if !containsObjectID(config.ProductIDs, r.ProductID) {
|
|
return fmt.Errorf("productID does not belong to experiment variant")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func containsObjectID(ids []primitive.ObjectID, target primitive.ObjectID) bool {
|
|
for _, id := range ids {
|
|
if id == target {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|