Skip to content

Add networkBusinessProfile to seller payment methods#6326

Open
floriansuess-stripe wants to merge 2 commits intomasterfrom
fsue/add-network-business-profile
Open

Add networkBusinessProfile to seller payment methods#6326
floriansuess-stripe wants to merge 2 commits intomasterfrom
fsue/add-network-business-profile

Conversation

@floriansuess-stripe
Copy link
Copy Markdown

Summary and motivation

APIREVIEW-4954.

iOS SDK counterpart to the Stripe.js change in mint#2041413.

Exposes the API surface for agents to pass a seller's Business Network profile to Payment Element on iOS, enabling PE to display the seller's configured payment methods. Beta header payment_element_seller_payment_methods_beta_1 is automatically included when networkBusinessProfile is provided.

The /v1/elements/sessions request already supports:

GET /v1/elements/sessions

<<< REQUEST <<<
{
   seller_details?: {
      network_id?: string,                // was required
      external_id?: string,               // was required
      business_name?: string,             // was required (local-only, now also sent to API)
      network_business_profile?: string,  // new
   },
}

In the iOS SDK:

@_spi(SharedPaymentToken) public struct SellerDetails {
    public let networkId: String?              // was required
    public let externalId: String?             // was required
    public let businessName: String?           // was required
    public let networkBusinessProfile: String? // new
}

For backwards compatibility, the existing 3-arg initializer SellerDetails(networkId:externalId:businessName:) with non-optional String types is preserved. A new initializer with all-optional parameters enables flexible usage including the new networkBusinessProfile field.

The new network_business_profile field allows agents to specify a BizNet profile ID, from which Stripe resolves the seller's default PMC (provided payment_element_seller_payment_methods_beta_1 is present).

All fields made optional. networkBusinessProfile added. paymentMethodConfigurationId and sellerDetails are now validated as mutually exclusive, passing both returns a PaymentSheetError client-side.

All this together looks like:

// 1. Agent creates intent configuration with seller's BizNet profile
@_spi(SharedPaymentToken) import StripePaymentSheet

let intentConfig = PaymentSheet.IntentConfiguration(
    sharedPaymentTokenSessionWithMode: .payment(amount: 1000, currency: "usd"),
    sellerDetails: .init(
        networkBusinessProfile: "bnp_abc123"  // the seller's profile
    ),
    preparePaymentMethodHandler: { paymentMethod, shippingAddress in
        // handle payment
    }
)

// 2. Payment Element renders the SELLER's payment methods
// The SDK automatically includes the beta header in the elements/sessions request

Note: what we do not do in this PR is act on it, i.e., take that network_business_profile value, resolve it to a seller's PMC, and return the right payment methods in the session response. That will come later.

- Make SellerDetails fields (networkId, externalId, businessName) optional
- Add networkBusinessProfile field to SellerDetails
- Send business_name and network_business_profile in elements/sessions params
- Add beta header when networkBusinessProfile is provided
- Add mutual exclusion validation for sellerDetails vs paymentMethodConfigurationId
- Add tests for new fields, beta header, and mutual exclusion

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Committed-By-Agent: claude
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 10, 2026

⚠️ Public API changes detected:

StripePaymentSheet

Public API

+  case paymentMethodConfigurationAndSellerDetailsMutuallyExclusive

SPI API

-      @_spi(SharedPaymentToken) public init(networkId: Swift.String, externalId: Swift.String, businessName: Swift.String)
-      @_spi(SharedPaymentToken) public let businessName: Swift.String
-      @_spi(SharedPaymentToken) public let externalId: Swift.String
-      @_spi(SharedPaymentToken) public let networkId: Swift.String
+      @_spi(SharedPaymentToken) public init(networkId: Swift.String? = nil, externalId: Swift.String? = nil, businessName: Swift.String? = nil, networkBusinessProfile: Swift.String? = nil)
+      @_spi(SharedPaymentToken) public let businessName: Swift.String?
+      @_spi(SharedPaymentToken) public let externalId: Swift.String?
+      @_spi(SharedPaymentToken) public let networkBusinessProfile: Swift.String?
+      @_spi(SharedPaymentToken) public let networkId: Swift.String?

If you are adding a new public API consider the following:

  • Do these APIs need to be public or can they be protected with @_spi(STP)?
  • If these APIs need to be public, assess whether they require an API review.

If you are modifying or removing a public API:

  • Does this require a breaking version change?
  • Do these changes require API review?

If you confirm these APIs need to be added/updated and have undergone necessary review, add the label modifies public API to this PR to acknowledge the interface change.
Additionally, if you modified or removed an existing API, ensure you update the changelog to reflect the necessary version bump for your changes. Regular public API changes require a MAJOR version bump, and SPI API changes (other than @_spi(STP)-only declarations) require a MINOR or MAJOR version bump.

ℹ️ If this comment appears to be left in error, make sure your branch is up-to-date with master.

Copy link
Copy Markdown

@paulcarey-stripe paulcarey-stripe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good from LPMs.

Comment on lines +66 to +72
/// Backwards-compatible initializer with required fields
public init(networkId: String, externalId: String, businessName: String) {
self.networkId = networkId
self.externalId = externalId
self.businessName = businessName
self.networkBusinessProfile = nil
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can delete this because the new constructor has a default value for networkBusinessProfile

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @tulio-stripe, have addressed.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for updating it 🤣

The all-optional initializer already handles the 3-arg case since
networkBusinessProfile defaults to nil.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Committed-By-Agent: claude
Copy link
Copy Markdown
Contributor

@toluo-stripe toluo-stripe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, but I'm not an iOS codeowner. There's also an api change that may be a blocker. @wooj-stripe @yuki-stripe can you take a look?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants