diff --git a/codegen/pkg/generator/collect.go b/codegen/pkg/generator/collect.go index c5a59de..be48f87 100644 --- a/codegen/pkg/generator/collect.go +++ b/codegen/pkg/generator/collect.go @@ -10,6 +10,7 @@ import ( ) type schemaUsage struct { + name string schema *base.SchemaProxy tags map[string]struct{} } @@ -23,79 +24,28 @@ func (g *Generator) collectSchemaUsage() map[string]*schemaUsage { for path, pathItem := range g.spec.Paths.PathItems.FromOldest() { for method, op := range pathItem.GetOperations().FromOldest() { - c := make(schemaProxyCollection, 0, 16) - c.collectSchemasInResponse(op) - c.collectSchemasInParams(op) - c.collectSchemasInRequest(op) - - for _, schema := range c { - if schema == nil { - continue - } - - if schema.GetReference() == "" { - continue - } - - name := schemaClassName(schema) - entry, ok := usage[name] - if !ok { - entry = &schemaUsage{ - schema: schema, - tags: make(map[string]struct{}), - } - usage[name] = entry - } - - if len(op.Tags) == 0 { - slog.Warn("operation without tags; skipping schema assignment", - slog.String("path", path), - slog.String("method", method), - slog.String("schema", name), - ) - continue - } - - for _, tag := range op.Tags { - entry.tags[normalizeTagKey(tag)] = struct{}{} - } + opTags := make([]string, 0, len(op.Tags)) + for _, tag := range op.Tags { + opTags = append(opTags, normalizeTagKey(tag)) } - } - } - - return usage -} - -func (g *Generator) assignSchemasToTags(usage map[string]*schemaUsage) (map[string][]*base.SchemaProxy, map[string]string) { - result := make(map[string][]*base.SchemaProxy) - namespaceBySchema := make(map[string]string) - - for schemaName, info := range usage { - targetTag := typesTagKey - // Skip schemas that are additionalProperties-only (they'll be treated as arrays) - if schemaIsAdditionalPropertiesOnly(info.schema) { - continue - } + g.collectSchemaUsageInResponse(op, opTags, usage) + g.collectSchemaUsageInParams(op, opTags, usage) + g.collectSchemaUsageInRequest(op, opTags, usage) - if schemaIsObject(info.schema) { - result[targetTag] = append(result[targetTag], info.schema) - namespaceBySchema[schemaName] = g.namespaceForTag(targetTag) + if len(op.Tags) == 0 { + slog.Warn("operation without tags; skipping schema assignment", + slog.String("path", path), + slog.String("method", method), + ) + } } } - for tag := range result { - slices.SortFunc(result[tag], func(a, b *base.SchemaProxy) int { - return strings.Compare(schemaClassName(a), schemaClassName(b)) - }) - } - - return result, namespaceBySchema + return usage } -type schemaProxyCollection []*base.SchemaProxy - -func (c *schemaProxyCollection) collectSchemasInResponse(op *v3.Operation) { +func (g *Generator) collectSchemaUsageInResponse(op *v3.Operation, tags []string, usage map[string]*schemaUsage) { if op == nil || op.Responses == nil || op.Responses.Codes.Len() == 0 { return } @@ -106,64 +56,178 @@ func (c *schemaProxyCollection) collectSchemasInResponse(op *v3.Operation) { } for _, mediaType := range response.Content.FromOldest() { - c.collectReferencedSchemas(mediaType.Schema) + g.collectSchemaUsageFromSchema(mediaType.Schema, tags, usage, make(map[*base.SchemaProxy]struct{}), "") } } } -func (c *schemaProxyCollection) collectSchemasInParams(op *v3.Operation) { +func (g *Generator) collectSchemaUsageInParams(op *v3.Operation, tags []string, usage map[string]*schemaUsage) { if op == nil { return } for _, param := range op.Parameters { - c.collectReferencedSchemas(param.Schema) + g.collectSchemaUsageFromSchema(param.Schema, tags, usage, make(map[*base.SchemaProxy]struct{}), "") } } -func (c *schemaProxyCollection) collectSchemasInRequest(op *v3.Operation) { +func (g *Generator) collectSchemaUsageInRequest(op *v3.Operation, tags []string, usage map[string]*schemaUsage) { if op == nil || op.RequestBody == nil { return } for _, mediaType := range op.RequestBody.Content.FromOldest() { - c.collectReferencedSchemas(mediaType.Schema) + g.collectSchemaUsageFromSchema(mediaType.Schema, tags, usage, make(map[*base.SchemaProxy]struct{}), "") } } -func (c *schemaProxyCollection) collectReferencedSchemas(schema *base.SchemaProxy) { +func (g *Generator) collectSchemaUsageFromSchema(schema *base.SchemaProxy, tags []string, usage map[string]*schemaUsage, stack map[*base.SchemaProxy]struct{}, suggestedName string) { if schema == nil { return } + if _, ok := stack[schema]; ok { + return + } + stack[schema] = struct{}{} + defer delete(stack, schema) + spec := schema.Schema() if spec == nil { return } - if slices.Contains(spec.Type, "object") { - for _, prop := range spec.Properties.FromOldest() { - c.collectReferencedSchemas(prop) + name := g.registerSchemaUsage(schema, suggestedName, tags, usage) + parentName := name + if parentName == "" { + parentName = suggestedName + } + + if spec.Properties != nil { + for propName, propSchema := range spec.Properties.FromOldest() { + childName := g.inlinePropertyClassName(parentName, propName, propSchema) + g.collectSchemaUsageFromSchema(propSchema, tags, usage, stack, childName) } } - if slices.Contains(spec.Type, "array") && spec.Items != nil { - c.collectReferencedSchemas(spec.Items.A) + if hasSchemaType(spec, "array") && spec.Items != nil && spec.Items.A != nil { + itemName := g.inlineArrayItemClassName(parentName, spec.Items.A) + g.collectSchemaUsageFromSchema(spec.Items.A, tags, usage, stack, itemName) } - for _, one := range spec.AnyOf { - c.collectReferencedSchemas(one) + for _, composite := range spec.AllOf { + g.collectSchemaUsageFromSchema(composite, tags, usage, stack, parentName) } + for _, composite := range spec.AnyOf { + g.collectSchemaUsageFromSchema(composite, tags, usage, stack, parentName) + } + for _, composite := range spec.OneOf { + g.collectSchemaUsageFromSchema(composite, tags, usage, stack, parentName) + } +} - for _, one := range spec.AllOf { - c.collectReferencedSchemas(one) +func (g *Generator) registerSchemaUsage(schema *base.SchemaProxy, suggestedName string, tags []string, usage map[string]*schemaUsage) string { + if schema == nil { + return "" + } + + name := g.classNameForSchema(schema) + if name == "" { + if suggestedName == "" || !schemaIsObject(schema) || schemaIsAdditionalPropertiesOnly(schema) { + return "" + } + name = suggestedName + g.inlineSchemaNames[schema] = name } - for _, one := range spec.OneOf { - c.collectReferencedSchemas(one) + entry, ok := usage[name] + if !ok { + entry = &schemaUsage{ + name: name, + schema: schema, + tags: make(map[string]struct{}), + } + usage[name] = entry } - if !slices.Contains(*c, schema) { - *c = append(*c, schema) + for _, tag := range tags { + entry.tags[tag] = struct{}{} } + + return name +} + +func (g *Generator) assignSchemasToTags(usage map[string]*schemaUsage) (map[string][]*base.SchemaProxy, map[string]string) { + result := make(map[string][]*base.SchemaProxy) + namespaceBySchema := make(map[string]string) + + for schemaName, info := range usage { + targetTag := typesTagKey + + // Skip schemas that are additionalProperties-only (they'll be treated as arrays) + if schemaIsAdditionalPropertiesOnly(info.schema) { + continue + } + + if schemaIsObject(info.schema) { + result[targetTag] = append(result[targetTag], info.schema) + namespaceBySchema[schemaName] = g.namespaceForTag(targetTag) + } + } + + for tag := range result { + slices.SortFunc(result[tag], func(a, b *base.SchemaProxy) int { + return strings.Compare(g.classNameForSchema(a), g.classNameForSchema(b)) + }) + } + + return result, namespaceBySchema +} + +func (g *Generator) classNameForSchema(schema *base.SchemaProxy) string { + if schema == nil { + return "" + } + + if ref := schema.GetReference(); ref != "" { + return schemaClassName(schema) + } + + if name, ok := g.inlineSchemaNames[schema]; ok { + return name + } + + return "" +} + +func (g *Generator) inlinePropertyClassName(parentName string, propertyName string, schema *base.SchemaProxy) string { + if parentName == "" || schema == nil { + return "" + } + + if schema.GetReference() != "" { + return "" + } + + if !schemaIsObject(schema) || schemaIsAdditionalPropertiesOnly(schema) { + return "" + } + + return phpInlineObjectName(parentName, propertyName) +} + +func (g *Generator) inlineArrayItemClassName(parentName string, schema *base.SchemaProxy) string { + if parentName == "" || schema == nil { + return "" + } + + if schema.GetReference() != "" { + return "" + } + + if !schemaIsObject(schema) || schemaIsAdditionalPropertiesOnly(schema) { + return "" + } + + return parentName + "Item" } diff --git a/codegen/pkg/generator/generator.go b/codegen/pkg/generator/generator.go index 10dbc31..4122fbb 100644 --- a/codegen/pkg/generator/generator.go +++ b/codegen/pkg/generator/generator.go @@ -37,6 +37,9 @@ type Generator struct { tagLookup map[string]*base.Tag + // inlineSchemaNames tracks deterministic generated names for inline object schemas. + inlineSchemaNames map[*base.SchemaProxy]string + // schemasByTag maps normalized tag names to schemas they own. schemasByTag map[string][]*base.SchemaProxy @@ -62,7 +65,8 @@ type enumDefinition struct { // New creates a new Generator instance. func New(cfg Config) *Generator { return &Generator{ - cfg: cfg, + cfg: cfg, + inlineSchemaNames: make(map[*base.SchemaProxy]string), } } @@ -265,7 +269,7 @@ func (g *Generator) buildPHPClass(name string, schema *base.SchemaProxy, current fmt.Fprintf(&buf, "class %s\n{\n", name) - properties := g.schemaProperties(schema, currentNamespace) + properties := g.schemaProperties(schema, currentNamespace, name) if len(properties) == 0 { buf.WriteString("}\n") return buf.String() @@ -430,7 +434,11 @@ func (g *Generator) collectEnumsFromSchema(schema *base.SchemaProxy, tagKey stri } if len(propSpec.Enum) > 0 { - enumName := phpEnumName(schemaClassName(schema), propName) + schemaName := g.classNameForSchema(schema) + if schemaName == "" { + continue + } + enumName := phpEnumName(schemaName, propName) if _, seen := enumsSeen[enumName]; seen { continue } diff --git a/codegen/pkg/generator/names.go b/codegen/pkg/generator/names.go index 1e7899e..c81fb06 100644 --- a/codegen/pkg/generator/names.go +++ b/codegen/pkg/generator/names.go @@ -53,6 +53,15 @@ func phpEnumName(schemaName, propertyName string) string { return schemaName + baseName } +func phpInlineObjectName(schemaName, propertyName string) string { + propertyName = strings.TrimSpace(propertyName) + propertyName = strings.ReplaceAll(propertyName, "-", "_") + propertyName = strings.ReplaceAll(propertyName, ".", "_") + + baseName := strcase.ToCamel(propertyName) + return schemaName + baseName +} + func phpEnumCaseName(value string) string { value = strings.TrimSpace(value) diff --git a/codegen/pkg/generator/properties.go b/codegen/pkg/generator/properties.go index a23c41b..78b971e 100644 --- a/codegen/pkg/generator/properties.go +++ b/codegen/pkg/generator/properties.go @@ -18,13 +18,12 @@ type phpProperty struct { Description string } -func (g *Generator) schemaProperties(schema *base.SchemaProxy, currentNamespace string) []phpProperty { +func (g *Generator) schemaProperties(schema *base.SchemaProxy, currentNamespace string, currentClassName string) []phpProperty { propertySpecs := g.collectSchemaPropertyEntries(schema) if len(propertySpecs) == 0 { return nil } - schemaName := schemaClassName(schema) props := make([]phpProperty, 0, len(propertySpecs)) for _, spec := range propertySpecs { prop := phpProperty{ @@ -37,7 +36,7 @@ func (g *Generator) schemaProperties(schema *base.SchemaProxy, currentNamespace prop.Description = spec.Schema.Schema().Description } - prop.Type, prop.DocType = g.resolvePHPType(spec.Schema, currentNamespace, schemaName, spec.Name) + prop.Type, prop.DocType = g.resolvePHPType(spec.Schema, currentNamespace, currentClassName, spec.Name) props = append(props, prop) } @@ -203,7 +202,7 @@ func (g *Generator) resolvePHPType(schema *base.SchemaProxy, currentNamespace st if ref := schema.GetReference(); ref != "" { if !schemaIsObject(schema) { - return g.resolvePHPTypeFromSpec(schema.Schema(), currentNamespace, parentSchemaName, propertyName) + return g.resolvePHPTypeFromSpec(schema, schema.Schema(), currentNamespace, parentSchemaName, propertyName) } // Check if this is an additionalProperties-only schema - treat as array @@ -211,7 +210,7 @@ func (g *Generator) resolvePHPType(schema *base.SchemaProxy, currentNamespace st return "array", "array" } - name := schemaClassName(schema) + name := g.classNameForSchema(schema) namespace := g.schemaNamespaces[name] if namespace == "" { return name, name @@ -225,10 +224,10 @@ func (g *Generator) resolvePHPType(schema *base.SchemaProxy, currentNamespace st return typeName, typeName } - return g.resolvePHPTypeFromSpec(schema.Schema(), currentNamespace, parentSchemaName, propertyName) + return g.resolvePHPTypeFromSpec(schema, schema.Schema(), currentNamespace, parentSchemaName, propertyName) } -func (g *Generator) resolvePHPTypeFromSpec(spec *base.Schema, currentNamespace string, parentSchemaName string, propertyName string) (string, string) { +func (g *Generator) resolvePHPTypeFromSpec(schema *base.SchemaProxy, spec *base.Schema, currentNamespace string, parentSchemaName string, propertyName string) (string, string) { if spec == nil { return "mixed", "mixed" } @@ -268,6 +267,19 @@ func (g *Generator) resolvePHPTypeFromSpec(spec *base.Schema, currentNamespace s } return "array", itemDoc + "[]" case hasSchemaType(spec, "object"): + if schema != nil && !schemaIsAdditionalPropertiesOnly(schema) { + typeName := g.classNameForSchema(schema) + if typeName == "" && parentSchemaName != "" && propertyName != "" { + typeName = phpInlineObjectName(parentSchemaName, propertyName) + } + if typeName != "" { + namespace := g.schemaNamespaces[typeName] + if namespace != "" && namespace != currentNamespace { + typeName = fmt.Sprintf("\\%s\\%s", namespace, typeName) + } + return typeName, typeName + } + } return "array", "array" default: } diff --git a/codegen/pkg/generator/services.go b/codegen/pkg/generator/services.go index 5879d84..2123f80 100644 --- a/codegen/pkg/generator/services.go +++ b/codegen/pkg/generator/services.go @@ -28,16 +28,10 @@ func (g *Generator) buildServiceBlock(tagKey string, operations []*operation) st buf.WriteString("use SumUp\\SdkInfo;\n\n") inlineResponseSchemas := collectInlineResponseSchemas(operations) - if len(inlineResponseSchemas) > 0 { - inlineNames := make([]string, 0, len(inlineResponseSchemas)) - for name := range inlineResponseSchemas { - inlineNames = append(inlineNames, name) - } - slices.Sort(inlineNames) - for _, name := range inlineNames { - buf.WriteString(g.buildPHPClass(name, inlineResponseSchemas[name], "SumUp\\Services")) - buf.WriteString("\n") - } + serviceInlineSchemas := make(map[string]*base.SchemaProxy) + for name, schema := range inlineResponseSchemas { + serviceInlineSchemas[name] = schema + g.collectNestedInlineServiceSchemas(name, schema, serviceInlineSchemas, make(map[*base.SchemaProxy]struct{})) } seenRequestBodies := make(map[string]struct{}) @@ -56,6 +50,10 @@ func (g *Generator) buildServiceBlock(tagKey string, operations []*operation) st op.BodyType = requestClass op.BodyDocType = requestClass + if op.BodySchema != nil { + g.collectNestedInlineServiceSchemas(requestClass, op.BodySchema, serviceInlineSchemas, make(map[*base.SchemaProxy]struct{})) + } + if op.BodySchema != nil { buf.WriteString(g.buildPHPClass(requestClass, op.BodySchema, "SumUp\\Services")) } else { @@ -64,6 +62,18 @@ func (g *Generator) buildServiceBlock(tagKey string, operations []*operation) st buf.WriteString("\n") } + if len(serviceInlineSchemas) > 0 { + inlineNames := make([]string, 0, len(serviceInlineSchemas)) + for name := range serviceInlineSchemas { + inlineNames = append(inlineNames, name) + } + slices.Sort(inlineNames) + for _, name := range inlineNames { + buf.WriteString(g.buildPHPClass(name, serviceInlineSchemas[name], "SumUp\\Services")) + buf.WriteString("\n") + } + } + seenParams := make(map[string]struct{}) for _, op := range operations { if op == nil || !op.HasQuery { @@ -466,6 +476,61 @@ func collectInlineResponseSchema(rt *responseType, acc map[string]*base.SchemaPr } } +func (g *Generator) collectNestedInlineServiceSchemas(parentName string, schema *base.SchemaProxy, acc map[string]*base.SchemaProxy, stack map[*base.SchemaProxy]struct{}) { + if parentName == "" || schema == nil { + return + } + + if _, ok := stack[schema]; ok { + return + } + stack[schema] = struct{}{} + defer delete(stack, schema) + + spec := schema.Schema() + if spec == nil { + return + } + + if spec.Properties != nil { + for propName, propSchema := range spec.Properties.FromOldest() { + name := g.inlinePropertyClassName(parentName, propName, propSchema) + if name != "" { + if _, ok := acc[name]; !ok { + acc[name] = propSchema + } + g.inlineSchemaNames[propSchema] = name + g.collectNestedInlineServiceSchemas(name, propSchema, acc, stack) + } else { + g.collectNestedInlineServiceSchemas(parentName, propSchema, acc, stack) + } + } + } + + if hasSchemaType(spec, "array") && spec.Items != nil && spec.Items.A != nil { + itemName := g.inlineArrayItemClassName(parentName, spec.Items.A) + if itemName != "" { + if _, ok := acc[itemName]; !ok { + acc[itemName] = spec.Items.A + } + g.inlineSchemaNames[spec.Items.A] = itemName + g.collectNestedInlineServiceSchemas(itemName, spec.Items.A, acc, stack) + } else { + g.collectNestedInlineServiceSchemas(parentName, spec.Items.A, acc, stack) + } + } + + for _, composite := range spec.AllOf { + g.collectNestedInlineServiceSchemas(parentName, composite, acc, stack) + } + for _, composite := range spec.AnyOf { + g.collectNestedInlineServiceSchemas(parentName, composite, acc, stack) + } + for _, composite := range spec.OneOf { + g.collectNestedInlineServiceSchemas(parentName, composite, acc, stack) + } +} + func renderResponseTypeDescriptor(rt *responseType) string { if rt == nil { return "['type' => 'mixed']" diff --git a/codegen/pkg/generator/types.go b/codegen/pkg/generator/types.go index 63568c1..0c0d91f 100644 --- a/codegen/pkg/generator/types.go +++ b/codegen/pkg/generator/types.go @@ -46,7 +46,7 @@ func (g *Generator) writeTypeModels(schemas []*base.SchemaProxy) error { } for _, schema := range schemas { - className := schemaClassName(schema) + className := g.classNameForSchema(schema) filename := filepath.Join(dir, fmt.Sprintf("%s.php", className)) f, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0o644) if err != nil { diff --git a/src/Checkouts/Checkouts.php b/src/Checkouts/Checkouts.php index 98bc9df..f3a9486 100644 --- a/src/Checkouts/Checkouts.php +++ b/src/Checkouts/Checkouts.php @@ -16,12 +16,23 @@ class CheckoutsListAvailablePaymentMethodsResponse { /** * - * @var array[]|null + * @var CheckoutsListAvailablePaymentMethodsResponseItem[]|null */ public ?array $availablePaymentMethods = null; } +class CheckoutsListAvailablePaymentMethodsResponseItem +{ + /** + * The ID of the payment method. + * + * @var string + */ + public string $id; + +} + /** * Query parameters for CheckoutsListParams. * diff --git a/src/Members/Members.php b/src/Members/Members.php index 896a288..377759e 100644 --- a/src/Members/Members.php +++ b/src/Members/Members.php @@ -12,22 +12,6 @@ use SumUp\ResponseDecoder; use SumUp\SdkInfo; -class MembersListResponse -{ - /** - * - * @var \SumUp\Types\Member[] - */ - public array $items; - - /** - * - * @var int|null - */ - public ?int $totalCount = null; - -} - class MembersCreateRequest { /** @@ -118,9 +102,9 @@ class MembersUpdateRequest /** * Allows you to update user data of managed users. * - * @var array|null + * @var MembersUpdateRequestUser|null */ - public ?array $user = null; + public ?MembersUpdateRequestUser $user = null; /** * Create request DTO from an associative array. @@ -136,6 +120,43 @@ public function __construct(array $data = []) } +class MembersListResponse +{ + /** + * + * @var \SumUp\Types\Member[] + */ + public array $items; + + /** + * + * @var int|null + */ + public ?int $totalCount = null; + +} + +/** + * Allows you to update user data of managed users. + */ +class MembersUpdateRequestUser +{ + /** + * User's preferred name. Used for display purposes only. + * + * @var string|null + */ + public ?string $nickname = null; + + /** + * Password of the member to add. Only used if `is_managed_user` is true. + * + * @var string|null + */ + public ?string $password = null; + +} + /** * Query parameters for MembersListParams. * diff --git a/src/Readers/Readers.php b/src/Readers/Readers.php index d9c8f86..8817cf7 100644 --- a/src/Readers/Readers.php +++ b/src/Readers/Readers.php @@ -12,16 +12,6 @@ use SumUp\ResponseDecoder; use SumUp\SdkInfo; -class ReadersListResponse -{ - /** - * - * @var \SumUp\Types\Reader[] - */ - public array $items; - -} - class ReadersCreateRequest { /** @@ -98,6 +88,16 @@ public function __construct(array $data = []) } +class ReadersListResponse +{ + /** + * + * @var \SumUp\Types\Reader[] + */ + public array $items; + +} + /** * Class Readers * diff --git a/src/Roles/Roles.php b/src/Roles/Roles.php index 83d460f..d5279b4 100644 --- a/src/Roles/Roles.php +++ b/src/Roles/Roles.php @@ -12,16 +12,6 @@ use SumUp\ResponseDecoder; use SumUp\SdkInfo; -class RolesListResponse -{ - /** - * - * @var \SumUp\Types\Role[] - */ - public array $items; - -} - class RolesCreateRequest { /** @@ -103,6 +93,16 @@ public function __construct(array $data = []) } +class RolesListResponse +{ + /** + * + * @var \SumUp\Types\Role[] + */ + public array $items; + +} + /** * Class Roles * diff --git a/src/Subaccounts/Subaccounts.php b/src/Subaccounts/Subaccounts.php index d0ba328..83da5c5 100644 --- a/src/Subaccounts/Subaccounts.php +++ b/src/Subaccounts/Subaccounts.php @@ -34,9 +34,9 @@ class SubaccountsCreateSubAccountRequest /** * - * @var array|null + * @var SubaccountsCreateSubAccountRequestPermissions|null */ - public ?array $permissions = null; + public ?SubaccountsCreateSubAccountRequestPermissions $permissions = null; /** * Create request DTO from an associative array. @@ -80,9 +80,9 @@ class SubaccountsUpdateSubAccountRequest /** * - * @var array|null + * @var SubaccountsUpdateSubAccountRequestPermissions|null */ - public ?array $permissions = null; + public ?SubaccountsUpdateSubAccountRequestPermissions $permissions = null; /** * Create request DTO from an associative array. @@ -98,6 +98,62 @@ public function __construct(array $data = []) } +class SubaccountsCreateSubAccountRequestPermissions +{ + /** + * + * @var bool|null + */ + public ?bool $createMotoPayments = null; + + /** + * + * @var bool|null + */ + public ?bool $createReferral = null; + + /** + * + * @var bool|null + */ + public ?bool $fullTransactionHistoryView = null; + + /** + * + * @var bool|null + */ + public ?bool $refundTransactions = null; + +} + +class SubaccountsUpdateSubAccountRequestPermissions +{ + /** + * + * @var bool|null + */ + public ?bool $createMotoPayments = null; + + /** + * + * @var bool|null + */ + public ?bool $createReferral = null; + + /** + * + * @var bool|null + */ + public ?bool $fullTransactionHistoryView = null; + + /** + * + * @var bool|null + */ + public ?bool $refundTransactions = null; + +} + /** * Query parameters for SubaccountsListSubAccountsParams. * diff --git a/src/Transactions/Transactions.php b/src/Transactions/Transactions.php index fdcc785..8ac547e 100644 --- a/src/Transactions/Transactions.php +++ b/src/Transactions/Transactions.php @@ -12,23 +12,33 @@ use SumUp\ResponseDecoder; use SumUp\SdkInfo; -class TransactionsListDeprecatedResponse +/** + * Optional amount for partial refunds of transactions. + */ +class TransactionsRefundRequest { /** + * Amount to be refunded. Eligible amount can't exceed the amount of the transaction and varies based on country and currency. If you do not specify a value, the system performs a full refund of the transaction. * - * @var \SumUp\Types\TransactionHistory[]|null + * @var float|null */ - public ?array $items = null; + public ?float $amount = null; /** + * Create request DTO from an associative array. * - * @var \SumUp\Types\TransactionsHistoryLink[]|null + * @param array $data */ - public ?array $links = null; + public function __construct(array $data = []) + { + if ($data !== []) { + \SumUp\Hydrator::hydrate($data, self::class, $this); + } + } } -class TransactionsListResponse +class TransactionsListDeprecatedResponse { /** * @@ -44,29 +54,19 @@ class TransactionsListResponse } -/** - * Optional amount for partial refunds of transactions. - */ -class TransactionsRefundRequest +class TransactionsListResponse { /** - * Amount to be refunded. Eligible amount can't exceed the amount of the transaction and varies based on country and currency. If you do not specify a value, the system performs a full refund of the transaction. * - * @var float|null + * @var \SumUp\Types\TransactionHistory[]|null */ - public ?float $amount = null; + public ?array $items = null; /** - * Create request DTO from an associative array. * - * @param array $data + * @var \SumUp\Types\TransactionsHistoryLink[]|null */ - public function __construct(array $data = []) - { - if ($data !== []) { - \SumUp\Hydrator::hydrate($data, self::class, $this); - } - } + public ?array $links = null; } diff --git a/src/Types/BadRequest.php b/src/Types/BadRequest.php index 4095310..448a2c5 100644 --- a/src/Types/BadRequest.php +++ b/src/Types/BadRequest.php @@ -11,8 +11,8 @@ class BadRequest { /** * - * @var array + * @var BadRequestErrors */ - public array $errors; + public BadRequestErrors $errors; } diff --git a/src/Types/BadRequestErrors.php b/src/Types/BadRequestErrors.php new file mode 100644 index 0000000..24321d5 --- /dev/null +++ b/src/Types/BadRequestErrors.php @@ -0,0 +1,23 @@ +|null + * @var CheckoutAcceptedNextStep|null */ - public ?array $nextStep = null; + public ?CheckoutAcceptedNextStep $nextStep = null; } diff --git a/src/Types/CheckoutAcceptedNextStep.php b/src/Types/CheckoutAcceptedNextStep.php new file mode 100644 index 0000000..335187b --- /dev/null +++ b/src/Types/CheckoutAcceptedNextStep.php @@ -0,0 +1,47 @@ +|null + * @var CheckoutSuccessPaymentInstrument|null */ - public ?array $paymentInstrument = null; + public ?CheckoutSuccessPaymentInstrument $paymentInstrument = null; } diff --git a/src/Types/CheckoutSuccessPaymentInstrument.php b/src/Types/CheckoutSuccessPaymentInstrument.php new file mode 100644 index 0000000..51a43f9 --- /dev/null +++ b/src/Types/CheckoutSuccessPaymentInstrument.php @@ -0,0 +1,19 @@ + + * @var CreateReaderCheckoutErrorErrors */ - public array $errors; + public CreateReaderCheckoutErrorErrors $errors; } diff --git a/src/Types/CreateReaderCheckoutErrorErrors.php b/src/Types/CreateReaderCheckoutErrorErrors.php new file mode 100644 index 0000000..3ba10f4 --- /dev/null +++ b/src/Types/CreateReaderCheckoutErrorErrors.php @@ -0,0 +1,23 @@ +|null + * @var CreateReaderCheckoutRequestAade|null */ - public ?array $aade = null; + public ?CreateReaderCheckoutRequestAade $aade = null; /** * Affiliate metadata for the transaction. * It is a field that allow for integrators to track the source of the transaction. * - * @var array|null + * @var CreateReaderCheckoutRequestAffiliate|null */ - public ?array $affiliate = null; + public ?CreateReaderCheckoutRequestAffiliate $affiliate = null; /** * The card type of the card used for the transaction. @@ -83,9 +83,9 @@ class CreateReaderCheckoutRequest * The amount is represented as an integer value altogether with the currency and the minor unit. * For example, EUR 1.00 is represented as value 100 with minor unit of 2. * - * @var array + * @var CreateReaderCheckoutRequestTotalAmount */ - public array $totalAmount; + public CreateReaderCheckoutRequestTotalAmount $totalAmount; /** * Create request DTO from an associative array. diff --git a/src/Types/CreateReaderCheckoutRequestAade.php b/src/Types/CreateReaderCheckoutRequestAade.php new file mode 100644 index 0000000..929e5a0 --- /dev/null +++ b/src/Types/CreateReaderCheckoutRequestAade.php @@ -0,0 +1,35 @@ +|null + */ + public ?array $tags = null; + +} diff --git a/src/Types/CreateReaderCheckoutRequestTotalAmount.php b/src/Types/CreateReaderCheckoutRequestTotalAmount.php new file mode 100644 index 0000000..ae2fd13 --- /dev/null +++ b/src/Types/CreateReaderCheckoutRequestTotalAmount.php @@ -0,0 +1,39 @@ + + * @var CreateReaderCheckoutResponseData */ - public array $data; + public CreateReaderCheckoutResponseData $data; } diff --git a/src/Types/CreateReaderCheckoutResponseData.php b/src/Types/CreateReaderCheckoutResponseData.php new file mode 100644 index 0000000..2158152 --- /dev/null +++ b/src/Types/CreateReaderCheckoutResponseData.php @@ -0,0 +1,17 @@ + + * @var CreateReaderTerminateErrorErrors */ - public array $errors; + public CreateReaderTerminateErrorErrors $errors; } diff --git a/src/Types/CreateReaderTerminateErrorErrors.php b/src/Types/CreateReaderTerminateErrorErrors.php new file mode 100644 index 0000000..f5092d1 --- /dev/null +++ b/src/Types/CreateReaderTerminateErrorErrors.php @@ -0,0 +1,23 @@ + + * @var NotFoundErrors */ - public array $errors; + public NotFoundErrors $errors; } diff --git a/src/Types/NotFoundErrors.php b/src/Types/NotFoundErrors.php new file mode 100644 index 0000000..80ef380 --- /dev/null +++ b/src/Types/NotFoundErrors.php @@ -0,0 +1,16 @@ +|null + * @var PaymentInstrumentResponseCard|null */ - public ?array $card = null; + public ?PaymentInstrumentResponseCard $card = null; /** * Created mandate diff --git a/src/Types/PaymentInstrumentResponseCard.php b/src/Types/PaymentInstrumentResponseCard.php new file mode 100644 index 0000000..1faa856 --- /dev/null +++ b/src/Types/PaymentInstrumentResponseCard.php @@ -0,0 +1,26 @@ +|null + * @var ProcessCheckoutGooglePay|null */ - public ?array $googlePay = null; + public ?ProcessCheckoutGooglePay $googlePay = null; /** * Raw payment token object received from Apple Pay. Send the Apple Pay response payload as-is. * - * @var array|null + * @var ProcessCheckoutApplePay|null */ - public ?array $applePay = null; + public ?ProcessCheckoutApplePay $applePay = null; /** * __Required when using a tokenized card to process a checkout.__ Unique token identifying the saved payment card for a customer. diff --git a/src/Types/ProcessCheckoutApplePay.php b/src/Types/ProcessCheckoutApplePay.php new file mode 100644 index 0000000..6288f10 --- /dev/null +++ b/src/Types/ProcessCheckoutApplePay.php @@ -0,0 +1,12 @@ +|null + * @var ReceiptEmvData|null */ - public ?array $emvData = null; + public ?ReceiptEmvData $emvData = null; /** * Acquirer-specific metadata related to the card authorization. * - * @var array|null + * @var ReceiptAcquirerData|null */ - public ?array $acquirerData = null; + public ?ReceiptAcquirerData $acquirerData = null; } diff --git a/src/Types/ReceiptAcquirerData.php b/src/Types/ReceiptAcquirerData.php new file mode 100644 index 0000000..de84a42 --- /dev/null +++ b/src/Types/ReceiptAcquirerData.php @@ -0,0 +1,36 @@ +|null + * @var ReceiptMerchantDataMerchantProfile|null */ - public ?array $merchantProfile = null; + public ?ReceiptMerchantDataMerchantProfile $merchantProfile = null; /** * Locale used for rendering localized receipt fields. diff --git a/src/Types/ReceiptMerchantDataMerchantProfile.php b/src/Types/ReceiptMerchantDataMerchantProfile.php new file mode 100644 index 0000000..58e17cd --- /dev/null +++ b/src/Types/ReceiptMerchantDataMerchantProfile.php @@ -0,0 +1,60 @@ + + * @var StatusResponseData */ - public array $data; + public StatusResponseData $data; } diff --git a/src/Types/StatusResponseData.php b/src/Types/StatusResponseData.php new file mode 100644 index 0000000..67e1e4a --- /dev/null +++ b/src/Types/StatusResponseData.php @@ -0,0 +1,58 @@ +|null + * @var TransactionFullLocation|null */ - public ?array $location = null; + public ?TransactionFullLocation $location = null; /** * Indicates whether tax deduction is enabled for the transaction. diff --git a/src/Types/TransactionFullLocation.php b/src/Types/TransactionFullLocation.php new file mode 100644 index 0000000..619063d --- /dev/null +++ b/src/Types/TransactionFullLocation.php @@ -0,0 +1,33 @@ + + * @var UnauthorizedErrors */ - public array $errors; + public UnauthorizedErrors $errors; } diff --git a/src/Types/UnauthorizedErrors.php b/src/Types/UnauthorizedErrors.php new file mode 100644 index 0000000..ccbbe15 --- /dev/null +++ b/src/Types/UnauthorizedErrors.php @@ -0,0 +1,23 @@ +assertSame('ref-123', $request->checkoutReference); } + + public function testCreateReaderCheckoutRequestHydratesInlineObjectProperties(): void + { + $request = new CreateReaderCheckoutRequest([ + 'aade' => [ + 'provider_id' => 'provider-123', + 'signature' => 'base64-signature', + 'signature_data' => 'signed-data', + ], + 'affiliate' => [ + 'app_id' => 'com.example.app', + 'foreign_transaction_id' => 'txn-123', + 'key' => 'key-123', + 'tags' => [ + 'source' => 'sdk-test', + ], + ], + 'total_amount' => [ + 'currency' => 'EUR', + 'minor_unit' => 2, + 'value' => 100, + ], + ]); + + $this->assertInstanceOf(CreateReaderCheckoutRequestAade::class, $request->aade); + $this->assertSame('provider-123', $request->aade->providerId); + $this->assertSame('signed-data', $request->aade->signatureData); + + $this->assertInstanceOf(CreateReaderCheckoutRequestAffiliate::class, $request->affiliate); + $this->assertSame('com.example.app', $request->affiliate->appId); + $this->assertSame(['source' => 'sdk-test'], $request->affiliate->tags); + + $this->assertInstanceOf(CreateReaderCheckoutRequestTotalAmount::class, $request->totalAmount); + $this->assertSame('EUR', $request->totalAmount->currency); + $this->assertSame(2, $request->totalAmount->minorUnit); + $this->assertSame(100, $request->totalAmount->value); + } }