From 191c5b2a5e1cf1f68f293ad33013d196f7904f51 Mon Sep 17 00:00:00 2001 From: "fern-api[bot]" <115122769+fern-api[bot]@users.noreply.github.com> Date: Sat, 10 Oct 2026 13:33:14 +0000 Subject: [PATCH 1/2] [fern-generated] Update SDK Generated by Fern CLI Version: unknown Generators: - fernapi/fern-go-sdk: 1.65.1 --- .fern/metadata.json | 2 +- payment_quotes.go | 37 ++++++++---- payment_quotes_test.go | 46 +++++++++++++++ paymentquotes/doc.go | 4 +- payments.go | 2 +- payments/direct.go | 2 +- reference.md | 48 ++++++++++++--- variants.go | 36 +++++++++--- variants/client.go | 6 ++ variants/variants_test/variants_test.go | 10 +++- variants_test.go | 78 +++++++++++++++++++++++++ wiremock/wiremock-mappings.json | 6 ++ 12 files changed, 241 insertions(+), 36 deletions(-) diff --git a/.fern/metadata.json b/.fern/metadata.json index 8400d97d..2737255e 100644 --- a/.fern/metadata.json +++ b/.fern/metadata.json @@ -10,7 +10,7 @@ "packageName": "whopsdk", "clientName": "Whop" }, - "originGitCommit": "5e4b7064e04d687363cf69ed2044c705570ebbb7", + "originGitCommit": "d9754d1712cd4d25c94baec00749b0109dbe9b7a", "originGitCommitIsDirty": false, "invokedBy": "ci", "requestedVersion": "2.3.0", diff --git a/payment_quotes.go b/payment_quotes.go index a05f4959..81710c2f 100644 --- a/payment_quotes.go +++ b/payment_quotes.go @@ -12,9 +12,10 @@ import ( var ( createPaymentQuotesRequestFieldAddress = big.NewInt(1 << 0) createPaymentQuotesRequestFieldIPAddress = big.NewInt(1 << 1) - createPaymentQuotesRequestFieldPresentmentCurrency = big.NewInt(1 << 2) - createPaymentQuotesRequestFieldShippingAddress = big.NewInt(1 << 3) - createPaymentQuotesRequestFieldTaxIDs = big.NewInt(1 << 4) + createPaymentQuotesRequestFieldPresentmentCountry = big.NewInt(1 << 2) + createPaymentQuotesRequestFieldPresentmentCurrency = big.NewInt(1 << 3) + createPaymentQuotesRequestFieldShippingAddress = big.NewInt(1 << 4) + createPaymentQuotesRequestFieldTaxIDs = big.NewInt(1 << 5) ) type CreatePaymentQuotesRequest struct { @@ -30,11 +31,13 @@ type CreatePaymentQuotesRequest struct { PromoCode *string `json:"promo_code,omitempty" url:"-"` // An active promo code to apply, prefixed `promo_`. It must belong to the account and be valid for the variant. Send it or `promo_code`, not both. A code this purchase cannot use is refused with the error code `promo_invalid`, and the error's message says why. PromoCodeID *string `json:"promo_code_id,omitempty" url:"-"` - // The buyer's billing address. Where tax is calculated when no shipping address is given, and the address a tax registration belongs to. A seller that collects tax on this purchase needs the buyer located by a `country` here, on `shipping_address`, or an `ip_address`; without one the quote is refused with `quote_location_required`. Only the keys you supply are kept. The payment that consumes the quote must put the buyer in the same place, by country, state and postal code, through its own `shipping_address` or its confirmation token's billing address, or it is refused with `quote_mismatch`. + // The buyer's billing address. Where tax is calculated when no shipping address is given, and the address a tax registration belongs to. A seller that collects tax on this purchase needs the buyer located by a `country` here, on `shipping_address`, a `presentment_country`, or an `ip_address`; without one the quote is refused with `quote_location_required`. Only the keys you supply are kept. The payment that consumes the quote must put the buyer in the same place, by country, state and postal code, through its own `shipping_address` or its confirmation token's billing address, or it is refused with `quote_mismatch`. Address *CreatePaymentQuotesRequestAddress `json:"address,omitempty" url:"-"` - // The buyer's IP address, when your server makes the call on their behalf. Locates the buyer when neither address carries a country. A quote located this way (`located_by` is `ip_address`) is a preview: a payment refuses it with `quote_preview_only`, so quote again with the buyer's address before paying. Also where `presentment_currency` `auto` and `recommended_currencies` find the buyer's local currency. + // The buyer's IP address, when your server makes the call on their behalf. Locates the buyer when neither address carries a country and no `presentment_country` is sent. A quote located this way (`located_by` is `ip_address`) is a preview: a payment refuses it with `quote_preview_only`, so quote again with the buyer's address before paying. Also where `presentment_currency` `auto` and `recommended_currencies` find the buyer's local currency, and where a payment method must be able to collect it. IPAddress *string `json:"ip_address,omitempty" url:"-"` - // The currency to price and charge the purchase in. Omit it, or send null, to price in the variants' own currency. `auto` prices in the currency of the country Whop places the buyer's `ip_address` in when the purchase can be converted into it and a payment method can collect it, and in the variants' own currency otherwise, including when no `ip_address` is sent or Whop cannot place it in a country. A three-letter ISO 4217 code, such as `eur`, prices in that currency or is refused: with `presentment_currency_unsupported` when the purchase cannot be converted into it (adaptive pricing is off for the variant, the variant is not a one-time purchase, or `plan` describes a variant that does not exist yet), and with `presentment_currency_not_payable` when no payment method can collect it. A converted quote states every amount in this currency at an `exchange_rate` fixed until `expires_at`, and the payment that consumes it is charged in this currency at that rate. + // The country to price the purchase for, as an ISO 3166-1 alpha-2 code such as `JP`, when the buyer chose one: a store's country picker. Prices in the currency `auto` would pick for a buyer in that country, so send it instead of `presentment_currency`, never with it. Whether a payment method can collect that currency is still judged where the buyer is: by `ip_address`, and by this country only without one. With no address that carries a country, tax is estimated for this country (`located_by` is `presentment_country`) at the country level, and a quote located this way is a preview a payment refuses with `quote_preview_only`. Send it only once the buyer has chosen a country: without it, an `ip_address` estimates more precisely, such as for a US state. For a country Whop has no currency for, the quote is priced as `auto` for the buyer's `ip_address`, and tax is still estimated for the country. + PresentmentCountry *string `json:"presentment_country,omitempty" url:"-"` + // The currency to price and charge the purchase in. Omit it, or send null, to price in the variants' own currency. `auto` prices in the currency of the country Whop places the buyer's `ip_address` in when the purchase can be converted into it and a payment method can collect it, and in the variants' own currency otherwise, including when no `ip_address` is sent or Whop cannot place it in a country. To choose that country instead, send `presentment_country` in place of this. A three-letter ISO 4217 code, such as `eur`, prices in that currency or is refused: with `presentment_currency_unsupported` when the purchase cannot be converted into it (adaptive pricing is off for the variant, the variant is not a one-time purchase, or `plan` describes a variant that does not exist yet), and with `presentment_currency_not_payable` when no payment method can collect it. A converted quote states every amount in this currency at an `exchange_rate` fixed until `expires_at`, and the payment that consumes it is charged in this currency at that rate. PresentmentCurrency *string `json:"presentment_currency,omitempty" url:"-"` // Where physical goods ship. When present it is where tax is calculated; omit it for digital goods. Only the keys you supply are kept. The payment that consumes the quote must ship to the same place, by country, state and postal code, or it is refused with `quote_mismatch`. ShippingAddress *CreatePaymentQuotesRequestShippingAddress `json:"shipping_address,omitempty" url:"-"` @@ -68,6 +71,13 @@ func (c *CreatePaymentQuotesRequest) SetIPAddress(ipAddress *string) { c.require(createPaymentQuotesRequestFieldIPAddress) } +// SetPresentmentCountry sets the PresentmentCountry field and marks it as non-optional; +// this prevents an empty or null value for this field from being omitted during serialization. +func (c *CreatePaymentQuotesRequest) SetPresentmentCountry(presentmentCountry *string) { + c.PresentmentCountry = presentmentCountry + c.require(createPaymentQuotesRequestFieldPresentmentCountry) +} + // SetPresentmentCurrency sets the PresentmentCurrency field and marks it as non-optional; // this prevents an empty or null value for this field from being omitted during serialization. func (c *CreatePaymentQuotesRequest) SetPresentmentCurrency(presentmentCurrency *string) { @@ -196,7 +206,7 @@ type PaymentQuote struct { // Payment quote ID, prefixed `pq_`. ID string `json:"id" url:"id"` LineItems []*PaymentQuoteLineItem `json:"line_items" url:"line_items"` - // Which location tax was calculated for: `shipping_address` when it carries a country, else the billing `address` when it does, else the buyer's `ip_address`. A quote located by `ip_address` is a preview: a payment cannot use it, so quote again with the buyer's address to pay. Null when nothing in the request located the buyer, which only a seller that collects no tax on this purchase is quoted without; `tax_status` is then `not_applicable`. + // Which location tax was calculated for: `shipping_address` when it carries a country, else the billing `address` when it does, else the `presentment_country` sent, else the buyer's `ip_address`. A quote located by `presentment_country` or `ip_address` is a preview that estimates tax: a payment cannot use it, so quote again with the buyer's address to pay. Null when nothing in the request located the buyer, which only a seller that collects no tax on this purchase is quoted without; `tax_status` is then `not_applicable`. LocatedBy *PaymentQuoteLocatedBy `json:"located_by,omitempty" url:"located_by,omitempty"` // The payment holding this quote, prefixed `pay_`, or null while it is unspent. A declined payment keeps its quote and can be retried; check that payment's `status`. PaymentID *string `json:"payment_id,omitempty" url:"payment_id,omitempty"` @@ -781,13 +791,14 @@ func (p *PaymentQuoteLineItem) String() string { return fmt.Sprintf("%#v", p) } -// Which location tax was calculated for: `shipping_address` when it carries a country, else the billing `address` when it does, else the buyer's `ip_address`. A quote located by `ip_address` is a preview: a payment cannot use it, so quote again with the buyer's address to pay. Null when nothing in the request located the buyer, which only a seller that collects no tax on this purchase is quoted without; `tax_status` is then `not_applicable`. +// Which location tax was calculated for: `shipping_address` when it carries a country, else the billing `address` when it does, else the `presentment_country` sent, else the buyer's `ip_address`. A quote located by `presentment_country` or `ip_address` is a preview that estimates tax: a payment cannot use it, so quote again with the buyer's address to pay. Null when nothing in the request located the buyer, which only a seller that collects no tax on this purchase is quoted without; `tax_status` is then `not_applicable`. type PaymentQuoteLocatedBy string const ( - PaymentQuoteLocatedByShippingAddress PaymentQuoteLocatedBy = "shipping_address" - PaymentQuoteLocatedByAddress PaymentQuoteLocatedBy = "address" - PaymentQuoteLocatedByIPAddress PaymentQuoteLocatedBy = "ip_address" + PaymentQuoteLocatedByShippingAddress PaymentQuoteLocatedBy = "shipping_address" + PaymentQuoteLocatedByAddress PaymentQuoteLocatedBy = "address" + PaymentQuoteLocatedByPresentmentCountry PaymentQuoteLocatedBy = "presentment_country" + PaymentQuoteLocatedByIPAddress PaymentQuoteLocatedBy = "ip_address" ) func NewPaymentQuoteLocatedByFromString(s string) (PaymentQuoteLocatedBy, error) { @@ -796,6 +807,8 @@ func NewPaymentQuoteLocatedByFromString(s string) (PaymentQuoteLocatedBy, error) return PaymentQuoteLocatedByShippingAddress, nil case "address": return PaymentQuoteLocatedByAddress, nil + case "presentment_country": + return PaymentQuoteLocatedByPresentmentCountry, nil case "ip_address": return PaymentQuoteLocatedByIPAddress, nil } @@ -1337,7 +1350,7 @@ var createPaymentQuotesRequestAddressNullableFields = map[string]*big.Int{ "state": createPaymentQuotesRequestAddressFieldState, } -// The buyer's billing address. Where tax is calculated when no shipping address is given, and the address a tax registration belongs to. A seller that collects tax on this purchase needs the buyer located by a `country` here, on `shipping_address`, or an `ip_address`; without one the quote is refused with `quote_location_required`. Only the keys you supply are kept. The payment that consumes the quote must put the buyer in the same place, by country, state and postal code, through its own `shipping_address` or its confirmation token's billing address, or it is refused with `quote_mismatch`. +// The buyer's billing address. Where tax is calculated when no shipping address is given, and the address a tax registration belongs to. A seller that collects tax on this purchase needs the buyer located by a `country` here, on `shipping_address`, a `presentment_country`, or an `ip_address`; without one the quote is refused with `quote_location_required`. Only the keys you supply are kept. The payment that consumes the quote must put the buyer in the same place, by country, state and postal code, through its own `shipping_address` or its confirmation token's billing address, or it is refused with `quote_mismatch`. type CreatePaymentQuotesRequestAddress struct { // City name. City *string `json:"city,omitempty" url:"city,omitempty"` diff --git a/payment_quotes_test.go b/payment_quotes_test.go index 709d7934..ee96c725 100644 --- a/payment_quotes_test.go +++ b/payment_quotes_test.go @@ -26,6 +26,14 @@ func TestSettersCreatePaymentQuotesRequest(t *testing.T) { assert.NotNil(t, obj.explicitFields) }) + t.Run("SetPresentmentCountry", func(t *testing.T) { + obj := &CreatePaymentQuotesRequest{} + var fernTestValuePresentmentCountry *string + obj.SetPresentmentCountry(fernTestValuePresentmentCountry) + assert.Equal(t, fernTestValuePresentmentCountry, obj.PresentmentCountry) + assert.NotNil(t, obj.explicitFields) + }) + t.Run("SetPresentmentCurrency", func(t *testing.T) { obj := &CreatePaymentQuotesRequest{} var fernTestValuePresentmentCurrency *string @@ -115,6 +123,37 @@ func TestSettersMarkExplicitCreatePaymentQuotesRequest(t *testing.T) { // It verifies that setting a field via setter allows successful JSON round-trip }) + t.Run("SetPresentmentCountry_MarksExplicit", func(t *testing.T) { + t.Parallel() + // Arrange + obj := &CreatePaymentQuotesRequest{} + var fernTestValuePresentmentCountry *string + + // Act + obj.SetPresentmentCountry(fernTestValuePresentmentCountry) + + // Assert - object with explicitly set field can be marshaled/unmarshaled + bytes, err := json.Marshal(obj) + require.NoError(t, err, "marshaling should succeed for test setup") + + // This test ensures JSON marshaling and unmarshaling succeed when the field has a zero/nil value + // Detect if marshaled JSON is an object or primitive to use correct unmarshal target + if len(bytes) > 0 && bytes[0] == '{' { + // JSON object - unmarshal into map + var unmarshaled map[string]interface{} + err = json.Unmarshal(bytes, &unmarshaled) + require.NoError(t, err, "unmarshaling should succeed for test verification") + } else { + // JSON primitive (string, number, boolean, null) - unmarshal into interface{} + var unmarshaled interface{} + err = json.Unmarshal(bytes, &unmarshaled) + require.NoError(t, err, "unmarshaling should succeed for test verification") + } + + // Note: This does not explicitly assert the presence of a specific JSON field + // It verifies that setting a field via setter allows successful JSON round-trip + }) + t.Run("SetPresentmentCurrency_MarksExplicit", func(t *testing.T) { t.Parallel() // Arrange @@ -4806,6 +4845,13 @@ func TestEnumPaymentQuoteLocatedBy(t *testing.T) { assert.Equal(t, PaymentQuoteLocatedBy("address"), val, "enum value should match expected wire value") }) + t.Run("NewFromString_presentment_country", func(t *testing.T) { + t.Parallel() + val, err := NewPaymentQuoteLocatedByFromString("presentment_country") + assert.NoError(t, err, "valid enum value should not return error") + assert.Equal(t, PaymentQuoteLocatedBy("presentment_country"), val, "enum value should match expected wire value") + }) + t.Run("NewFromString_ip_address", func(t *testing.T) { t.Parallel() val, err := NewPaymentQuoteLocatedByFromString("ip_address") diff --git a/paymentquotes/doc.go b/paymentquotes/doc.go index ed0d6540..aa8105a4 100644 --- a/paymentquotes/doc.go +++ b/paymentquotes/doc.go @@ -1,6 +1,6 @@ // Code generated by Fern. DO NOT EDIT. -// A Payment Quote prices a purchase exactly as a payment for it will be charged: the same line pricing, the same promo code, the same per-line tax calculation. The body is the `PaymentInput` a payment takes (the account, the variants or an inline plan, the promo code) plus where the buyer is: `address`, `shipping_address`, `tax_ids` and `ip_address`. Tax is calculated for the shipping address, else the billing address, else the IP address, and `located_by` says which one priced it. A seller who collects no tax on the purchase needs no location at all. +// A Payment Quote prices a purchase exactly as a payment for it will be charged: the same line pricing, the same promo code, the same per-line tax calculation. The body is the `PaymentInput` a payment takes (the account, the variants or an inline plan, the promo code) plus where the buyer is: `address`, `shipping_address`, `tax_ids`, `ip_address` and `presentment_country`. Tax is calculated for the shipping address, else the billing address, else the country the buyer chose, else the IP address, and `located_by` says which one priced it. A seller who collects no tax on the purchase needs no location at all. // -// Pass the quote's `id` as `quote_id` when you create the payment and the buyer is charged exactly this quote: its purchase (which the payment may then omit), its promo code and its `tax_amount`, with no figure recomputed at charge time. A quote is priced once, may be consumed by one payment, and expires at `expires_at`; quote again whenever the cart, the promo code or the address changes. It is priced in the variants' own currency unless you send `presentment_currency` (`auto` for the currency of the country Whop places the buyer's `ip_address` in, or a currency code): every amount is then converted at an `exchange_rate` fixed until `expires_at`, the payment is charged in that currency at that rate, and `recommended_currencies` lists the currencies to offer the buyer. A quote located by `ip_address` is a preview: show it, then quote again with the buyer's address to pay. `tax_status` says whether every line was priced (`calculated`), whether the seller collects no tax on this purchase (`not_applicable`), or whether tax could not be priced (`unavailable`, which a payment refuses: quote again, or charge without `quote_id` to have tax calculated at charge time). +// Pass the quote's `id` as `quote_id` when you create the payment and the buyer is charged exactly this quote: its purchase (which the payment may then omit), its promo code and its `tax_amount`, with no figure recomputed at charge time. A quote is priced once, may be consumed by one payment, and expires at `expires_at`; quote again whenever the cart, the promo code or the address changes. It is priced in the variants' own currency unless you send `presentment_currency` (`auto` for the currency of the country Whop places the buyer's `ip_address` in, or a currency code) or `presentment_country` (the currency `auto` would pick for a buyer in a country they chose): every amount is then converted at an `exchange_rate` fixed until `expires_at`, the payment is charged in that currency at that rate, and `recommended_currencies` lists the currencies to offer the buyer. A quote located by `presentment_country` or `ip_address` is a preview: show it, then quote again with the buyer's address to pay. `tax_status` says whether every line was priced (`calculated`), whether the seller collects no tax on this purchase (`not_applicable`), or whether tax could not be priced (`unavailable`, which a payment refuses: quote again, or charge without `quote_id` to have tax calculated at charge time). package paymentquotes diff --git a/payments.go b/payments.go index c8223668..44cb7f5c 100644 --- a/payments.go +++ b/payments.go @@ -91,7 +91,7 @@ type CreatePaymentsRequest struct { PaymentMethod *CreatePaymentsRequestPaymentMethod `json:"payment_method,omitempty" url:"-"` // The stored payment method to charge, prefixed `payt_`. It must belong to the member. Required unless `confirmation_token` is provided. PaymentMethodID *string `json:"payment_method_id,omitempty" url:"-"` - // A payment quote from `POST /payment_quotes`, prefixed `pq_`. The payment charges exactly the quote: its purchase (its variants and quantities, or the `plan` it priced), which this body may then omit, its promo code, and its tax, the quote's `tax_amount` rather than a figure calculated now. Omit it, or send null, to have tax calculated when the payment is charged. The quote must belong to `account_id`. A purchase field you omit or send as null takes the quote's value; the buyer's email, the addresses and the payment method are this request's own, never the quote's. Whatever you do send must describe the quoted purchase: the same variants, quantities and promo code. A quote that priced `plan` takes only the same `plan` you sent to `POST /payment_quotes` (or omit the purchase to take the quoted one), never `plan_id` or `line_items`, and a quote that priced variants by id never takes `plan`. Unless the quote located no buyer (`located_by` is null), the address the payment carries (its shipping address, else its billing address) must put the buyer where the quote priced tax, by country, state and postal code; otherwise the payment is refused with 400 before the payment method is used. A quote located by IP address (`located_by` is `ip_address`) is a preview and cannot be paid. A quote is consumed by one payment: a declined payment keeps it and can be retried; a new payment needs a new quote. A quote cannot be charged through PayPal; such a payment is refused before the payment method is used. A quote priced in a `presentment_currency` is charged in that currency at the quote's `exchange_rate`. A payment refused over its quote carries an error `code`. `quote_expired`: the quote has expired; quote again. `quote_tax_unavailable`: the quote could not price tax; quote again, or omit `quote_id`. `quote_preview_only`: the quote was located by IP address; quote again with the buyer's address. `quote_in_use` (409): another payment holds the quote. `quote_mismatch`: the purchase or the buyer's address is not the one quoted. `quote_rate_expired`: the exchange rate the quote was priced at has moved too far to charge; quote again. `payment_method_currency_unsupported`: the payment method cannot pay in the quote's currency; use another method, or quote again in another currency. `quote_processor_unsupported`: the payment method cannot pay a quote, as with PayPal; use another method, or omit `quote_id` to have tax calculated when the payment is charged. + // A payment quote from `POST /payment_quotes`, prefixed `pq_`. The payment charges exactly the quote: its purchase (its variants and quantities, or the `plan` it priced), which this body may then omit, its promo code, and its tax, the quote's `tax_amount` rather than a figure calculated now. Omit it, or send null, to have tax calculated when the payment is charged. The quote must belong to `account_id`. A purchase field you omit or send as null takes the quote's value; the buyer's email, the addresses and the payment method are this request's own, never the quote's. Whatever you do send must describe the quoted purchase: the same variants, quantities and promo code. A quote that priced `plan` takes only the same `plan` you sent to `POST /payment_quotes` (or omit the purchase to take the quoted one), never `plan_id` or `line_items`, and a quote that priced variants by id never takes `plan`. Unless the quote located no buyer (`located_by` is null), the address the payment carries (its shipping address, else its billing address) must put the buyer where the quote priced tax, by country, state and postal code; otherwise the payment is refused with 400 before the payment method is used. A quote located by IP address or by the country the buyer chose (`located_by` is `ip_address` or `presentment_country`) is a preview and cannot be paid. A quote is consumed by one payment: a declined payment keeps it and can be retried; a new payment needs a new quote. A quote cannot be charged through PayPal; such a payment is refused before the payment method is used. A quote priced in a `presentment_currency` is charged in that currency at the quote's `exchange_rate`. A payment refused over its quote carries an error `code`. `quote_expired`: the quote has expired; quote again. `quote_tax_unavailable`: the quote could not price tax; quote again, or omit `quote_id`. `quote_preview_only`: the quote was located by IP address or by the country the buyer chose; quote again with the buyer's address. `quote_in_use` (409): another payment holds the quote. `quote_mismatch`: the purchase or the buyer's address is not the one quoted. `quote_rate_expired`: the exchange rate the quote was priced at has moved too far to charge; quote again. `payment_method_currency_unsupported`: the payment method cannot pay in the quote's currency; use another method, or quote again in another currency. `quote_processor_unsupported`: the payment method cannot pay a quote, as with PayPal; use another method, or omit `quote_id` to have tax calculated when the payment is charged. QuoteID *string `json:"quote_id,omitempty" url:"-"` // Where the buyer continues after completing an off-site step such as 3D Secure. An absolute https URL without credentials, at most 2,048 characters. Required when a saved payment method is charged with `off_session` false; otherwise ignored unless `confirmation_token` is provided. ReturnURL *string `json:"return_url,omitempty" url:"-"` diff --git a/payments/direct.go b/payments/direct.go index b22f03ec..562f03c4 100644 --- a/payments/direct.go +++ b/payments/direct.go @@ -54,7 +54,7 @@ type CreateDirectRequest struct { OffSession *bool `json:"off_session,omitempty" url:"-"` // The payment method to charge, as the raw details the caller holds. Raw details are accepted only on the vault host, where Whop's vault tokenizes them in transit; the official SDKs route this operation there. Whop's own clients, which tokenize with the Basis Theory SDK, send the resulting token intent id to the regular host. PaymentMethod *CreateDirectRequestPaymentMethod `json:"payment_method" url:"-"` - // A payment quote from `POST /payment_quotes`, prefixed `pq_`. The payment charges exactly the quote: its purchase (its variants and quantities, or the `plan` it priced), which this body may then omit, its promo code, and its tax, the quote's `tax_amount` rather than a figure calculated now. Omit it, or send null, to have tax calculated when the payment is charged. The quote must belong to `account_id`. A purchase field you omit or send as null takes the quote's value; the buyer's email, the addresses and the payment method are this request's own, never the quote's. Whatever you do send must describe the quoted purchase: the same variants, quantities and promo code. A quote that priced `plan` takes only the same `plan` you sent to `POST /payment_quotes` (or omit the purchase to take the quoted one), never `plan_id` or `line_items`, and a quote that priced variants by id never takes `plan`. Unless the quote located no buyer (`located_by` is null), the address the payment carries (its shipping address, else its billing address) must put the buyer where the quote priced tax, by country, state and postal code; otherwise the payment is refused with 400 before the payment method is used. A quote located by IP address (`located_by` is `ip_address`) is a preview and cannot be paid. A quote is consumed by one payment: a declined payment keeps it and can be retried; a new payment needs a new quote. A quote cannot be charged through PayPal; such a payment is refused before the payment method is used. A quote priced in a `presentment_currency` is charged in that currency at the quote's `exchange_rate`. A payment refused over its quote carries an error `code`. `quote_expired`: the quote has expired; quote again. `quote_tax_unavailable`: the quote could not price tax; quote again, or omit `quote_id`. `quote_preview_only`: the quote was located by IP address; quote again with the buyer's address. `quote_in_use` (409): another payment holds the quote. `quote_mismatch`: the purchase or the buyer's address is not the one quoted. `quote_rate_expired`: the exchange rate the quote was priced at has moved too far to charge; quote again. `payment_method_currency_unsupported`: the payment method cannot pay in the quote's currency; use another method, or quote again in another currency. `quote_processor_unsupported`: the payment method cannot pay a quote, as with PayPal; use another method, or omit `quote_id` to have tax calculated when the payment is charged. + // A payment quote from `POST /payment_quotes`, prefixed `pq_`. The payment charges exactly the quote: its purchase (its variants and quantities, or the `plan` it priced), which this body may then omit, its promo code, and its tax, the quote's `tax_amount` rather than a figure calculated now. Omit it, or send null, to have tax calculated when the payment is charged. The quote must belong to `account_id`. A purchase field you omit or send as null takes the quote's value; the buyer's email, the addresses and the payment method are this request's own, never the quote's. Whatever you do send must describe the quoted purchase: the same variants, quantities and promo code. A quote that priced `plan` takes only the same `plan` you sent to `POST /payment_quotes` (or omit the purchase to take the quoted one), never `plan_id` or `line_items`, and a quote that priced variants by id never takes `plan`. Unless the quote located no buyer (`located_by` is null), the address the payment carries (its shipping address, else its billing address) must put the buyer where the quote priced tax, by country, state and postal code; otherwise the payment is refused with 400 before the payment method is used. A quote located by IP address or by the country the buyer chose (`located_by` is `ip_address` or `presentment_country`) is a preview and cannot be paid. A quote is consumed by one payment: a declined payment keeps it and can be retried; a new payment needs a new quote. A quote cannot be charged through PayPal; such a payment is refused before the payment method is used. A quote priced in a `presentment_currency` is charged in that currency at the quote's `exchange_rate`. A payment refused over its quote carries an error `code`. `quote_expired`: the quote has expired; quote again. `quote_tax_unavailable`: the quote could not price tax; quote again, or omit `quote_id`. `quote_preview_only`: the quote was located by IP address or by the country the buyer chose; quote again with the buyer's address. `quote_in_use` (409): another payment holds the quote. `quote_mismatch`: the purchase or the buyer's address is not the one quoted. `quote_rate_expired`: the exchange rate the quote was priced at has moved too far to charge; quote again. `payment_method_currency_unsupported`: the payment method cannot pay in the quote's currency; use another method, or quote again in another currency. `quote_processor_unsupported`: the payment method cannot pay a quote, as with PayPal; use another method, or omit `quote_id` to have tax calculated when the payment is charged. QuoteID *string `json:"quote_id,omitempty" url:"-"` // Where the buyer continues after completing an off-site step such as 3D Secure. An absolute https URL without credentials, at most 2,048 characters. ReturnURL *string `json:"return_url,omitempty" url:"-"` diff --git a/reference.md b/reference.md index 8210805c..9d67a6d0 100644 --- a/reference.md +++ b/reference.md @@ -26740,7 +26740,7 @@ client.PaymentQuotes.Create(
-**address:** `*whopsdk.CreatePaymentQuotesRequestAddress` — The buyer's billing address. Where tax is calculated when no shipping address is given, and the address a tax registration belongs to. A seller that collects tax on this purchase needs the buyer located by a `country` here, on `shipping_address`, or an `ip_address`; without one the quote is refused with `quote_location_required`. Only the keys you supply are kept. The payment that consumes the quote must put the buyer in the same place, by country, state and postal code, through its own `shipping_address` or its confirmation token's billing address, or it is refused with `quote_mismatch`. +**address:** `*whopsdk.CreatePaymentQuotesRequestAddress` — The buyer's billing address. Where tax is calculated when no shipping address is given, and the address a tax registration belongs to. A seller that collects tax on this purchase needs the buyer located by a `country` here, on `shipping_address`, a `presentment_country`, or an `ip_address`; without one the quote is refused with `quote_location_required`. Only the keys you supply are kept. The payment that consumes the quote must put the buyer in the same place, by country, state and postal code, through its own `shipping_address` or its confirmation token's billing address, or it is refused with `quote_mismatch`.
@@ -26748,7 +26748,7 @@ client.PaymentQuotes.Create(
-**ipAddress:** `*string` — The buyer's IP address, when your server makes the call on their behalf. Locates the buyer when neither address carries a country. A quote located this way (`located_by` is `ip_address`) is a preview: a payment refuses it with `quote_preview_only`, so quote again with the buyer's address before paying. Also where `presentment_currency` `auto` and `recommended_currencies` find the buyer's local currency. +**ipAddress:** `*string` — The buyer's IP address, when your server makes the call on their behalf. Locates the buyer when neither address carries a country and no `presentment_country` is sent. A quote located this way (`located_by` is `ip_address`) is a preview: a payment refuses it with `quote_preview_only`, so quote again with the buyer's address before paying. Also where `presentment_currency` `auto` and `recommended_currencies` find the buyer's local currency, and where a payment method must be able to collect it.
@@ -26756,7 +26756,15 @@ client.PaymentQuotes.Create(
-**presentmentCurrency:** `*string` — The currency to price and charge the purchase in. Omit it, or send null, to price in the variants' own currency. `auto` prices in the currency of the country Whop places the buyer's `ip_address` in when the purchase can be converted into it and a payment method can collect it, and in the variants' own currency otherwise, including when no `ip_address` is sent or Whop cannot place it in a country. A three-letter ISO 4217 code, such as `eur`, prices in that currency or is refused: with `presentment_currency_unsupported` when the purchase cannot be converted into it (adaptive pricing is off for the variant, the variant is not a one-time purchase, or `plan` describes a variant that does not exist yet), and with `presentment_currency_not_payable` when no payment method can collect it. A converted quote states every amount in this currency at an `exchange_rate` fixed until `expires_at`, and the payment that consumes it is charged in this currency at that rate. +**presentmentCountry:** `*string` — The country to price the purchase for, as an ISO 3166-1 alpha-2 code such as `JP`, when the buyer chose one: a store's country picker. Prices in the currency `auto` would pick for a buyer in that country, so send it instead of `presentment_currency`, never with it. Whether a payment method can collect that currency is still judged where the buyer is: by `ip_address`, and by this country only without one. With no address that carries a country, tax is estimated for this country (`located_by` is `presentment_country`) at the country level, and a quote located this way is a preview a payment refuses with `quote_preview_only`. Send it only once the buyer has chosen a country: without it, an `ip_address` estimates more precisely, such as for a US state. For a country Whop has no currency for, the quote is priced as `auto` for the buyer's `ip_address`, and tax is still estimated for the country. + +
+
+ +
+
+ +**presentmentCurrency:** `*string` — The currency to price and charge the purchase in. Omit it, or send null, to price in the variants' own currency. `auto` prices in the currency of the country Whop places the buyer's `ip_address` in when the purchase can be converted into it and a payment method can collect it, and in the variants' own currency otherwise, including when no `ip_address` is sent or Whop cannot place it in a country. To choose that country instead, send `presentment_country` in place of this. A three-letter ISO 4217 code, such as `eur`, prices in that currency or is refused: with `presentment_currency_unsupported` when the purchase cannot be converted into it (adaptive pricing is off for the variant, the variant is not a one-time purchase, or `plan` describes a variant that does not exist yet), and with `presentment_currency_not_payable` when no payment method can collect it. A converted quote states every amount in this currency at an `exchange_rate` fixed until `expires_at`, and the payment that consumes it is charged in this currency at that rate.
@@ -27799,7 +27807,7 @@ client.Payments.Create(
-**quoteID:** `*string` — A payment quote from `POST /payment_quotes`, prefixed `pq_`. The payment charges exactly the quote: its purchase (its variants and quantities, or the `plan` it priced), which this body may then omit, its promo code, and its tax, the quote's `tax_amount` rather than a figure calculated now. Omit it, or send null, to have tax calculated when the payment is charged. The quote must belong to `account_id`. A purchase field you omit or send as null takes the quote's value; the buyer's email, the addresses and the payment method are this request's own, never the quote's. Whatever you do send must describe the quoted purchase: the same variants, quantities and promo code. A quote that priced `plan` takes only the same `plan` you sent to `POST /payment_quotes` (or omit the purchase to take the quoted one), never `plan_id` or `line_items`, and a quote that priced variants by id never takes `plan`. Unless the quote located no buyer (`located_by` is null), the address the payment carries (its shipping address, else its billing address) must put the buyer where the quote priced tax, by country, state and postal code; otherwise the payment is refused with 400 before the payment method is used. A quote located by IP address (`located_by` is `ip_address`) is a preview and cannot be paid. A quote is consumed by one payment: a declined payment keeps it and can be retried; a new payment needs a new quote. A quote cannot be charged through PayPal; such a payment is refused before the payment method is used. A quote priced in a `presentment_currency` is charged in that currency at the quote's `exchange_rate`. A payment refused over its quote carries an error `code`. `quote_expired`: the quote has expired; quote again. `quote_tax_unavailable`: the quote could not price tax; quote again, or omit `quote_id`. `quote_preview_only`: the quote was located by IP address; quote again with the buyer's address. `quote_in_use` (409): another payment holds the quote. `quote_mismatch`: the purchase or the buyer's address is not the one quoted. `quote_rate_expired`: the exchange rate the quote was priced at has moved too far to charge; quote again. `payment_method_currency_unsupported`: the payment method cannot pay in the quote's currency; use another method, or quote again in another currency. `quote_processor_unsupported`: the payment method cannot pay a quote, as with PayPal; use another method, or omit `quote_id` to have tax calculated when the payment is charged. +**quoteID:** `*string` — A payment quote from `POST /payment_quotes`, prefixed `pq_`. The payment charges exactly the quote: its purchase (its variants and quantities, or the `plan` it priced), which this body may then omit, its promo code, and its tax, the quote's `tax_amount` rather than a figure calculated now. Omit it, or send null, to have tax calculated when the payment is charged. The quote must belong to `account_id`. A purchase field you omit or send as null takes the quote's value; the buyer's email, the addresses and the payment method are this request's own, never the quote's. Whatever you do send must describe the quoted purchase: the same variants, quantities and promo code. A quote that priced `plan` takes only the same `plan` you sent to `POST /payment_quotes` (or omit the purchase to take the quoted one), never `plan_id` or `line_items`, and a quote that priced variants by id never takes `plan`. Unless the quote located no buyer (`located_by` is null), the address the payment carries (its shipping address, else its billing address) must put the buyer where the quote priced tax, by country, state and postal code; otherwise the payment is refused with 400 before the payment method is used. A quote located by IP address or by the country the buyer chose (`located_by` is `ip_address` or `presentment_country`) is a preview and cannot be paid. A quote is consumed by one payment: a declined payment keeps it and can be retried; a new payment needs a new quote. A quote cannot be charged through PayPal; such a payment is refused before the payment method is used. A quote priced in a `presentment_currency` is charged in that currency at the quote's `exchange_rate`. A payment refused over its quote carries an error `code`. `quote_expired`: the quote has expired; quote again. `quote_tax_unavailable`: the quote could not price tax; quote again, or omit `quote_id`. `quote_preview_only`: the quote was located by IP address or by the country the buyer chose; quote again with the buyer's address. `quote_in_use` (409): another payment holds the quote. `quote_mismatch`: the purchase or the buyer's address is not the one quoted. `quote_rate_expired`: the exchange rate the quote was priced at has moved too far to charge; quote again. `payment_method_currency_unsupported`: the payment method cannot pay in the quote's currency; use another method, or quote again in another currency. `quote_processor_unsupported`: the payment method cannot pay a quote, as with PayPal; use another method, or omit `quote_id` to have tax calculated when the payment is charged.
@@ -38822,6 +38830,9 @@ request := &whopsdk.ListVariantsRequest{ IPAddress: whopsdk.String( "203.0.113.7", ), + PresentmentCountry: whopsdk.String( + "JP", + ), } client.Variants.List( context.TODO(), @@ -38913,7 +38924,7 @@ client.Variants.List(
-**presentmentCurrency:** `*string` — The currency to state each variant's prices in. Omit it, or send null, for each variant's own currency. `auto` states them in the currency of the country Whop places the buyer in: by `ip_address` when your server sends one, and by the request's own IP address otherwise. A three-letter ISO 4217 code, such as `eur`, states them in that currency. A variant converts only where a payment quote for it would be priced in that currency, and stays in its own currency otherwise: a renewing variant, one with adaptive pricing off, a currency no payment method can collect, or `auto` for a buyer Whop cannot place in a country. Converted prices are an estimate at the current exchange rate. Nothing is held: the payment quote the buyer pays from fixes the rate. +**presentmentCurrency:** `*string` — The currency to state each variant's prices in. Omit it, or send null, for each variant's own currency. `auto` states them in the currency of the country Whop places the buyer in: by `ip_address` when your server sends one, and by the request's own IP address otherwise. To choose that country instead, send `presentment_country` in place of this. A three-letter ISO 4217 code, such as `eur`, states them in that currency. A variant converts only where a payment quote for it would be priced in that currency, and stays in its own currency otherwise: a renewing variant, one with adaptive pricing off, a currency no payment method can collect, or `auto` for a buyer Whop cannot place in a country. Converted prices are an estimate at the current exchange rate. Nothing is held: the payment quote the buyer pays from fixes the rate.
@@ -38921,7 +38932,15 @@ client.Variants.List(
-**ipAddress:** `*string` — The buyer's IP address, when your server reads on their behalf. Needs an API key; any other caller is placed by its own request. Where `presentment_currency` `auto` finds the buyer's local currency. +**ipAddress:** `*string` — The buyer's IP address, when your server reads on their behalf. Needs an API key; any other caller is placed by its own request. Where `presentment_currency` `auto` finds the buyer's local currency, and where a payment method must be able to collect it. + +
+
+ +
+
+ +**presentmentCountry:** `*string` — The country to state each variant's prices for, as an ISO 3166-1 alpha-2 code such as `JP`, when the buyer chose one: a store's country picker. States them in the currency `auto` would for a buyer in that country, so send it instead of `presentment_currency`, never with it. Whether a payment method can collect that currency is still judged where the buyer is: by `ip_address`, else by the request's own IP address. A country Whop has no currency for is ignored, and the prices are stated as `auto` would state them.
@@ -39266,6 +39285,9 @@ request := &whopsdk.RetrieveVariantsRequest{ IPAddress: whopsdk.String( "203.0.113.7", ), + PresentmentCountry: whopsdk.String( + "JP", + ), } client.Variants.Retrieve( context.TODO(), @@ -39293,7 +39315,15 @@ client.Variants.Retrieve(
-**presentmentCurrency:** `*string` — The currency to state each variant's prices in. Omit it, or send null, for each variant's own currency. `auto` states them in the currency of the country Whop places the buyer in: by `ip_address` when your server sends one, and by the request's own IP address otherwise. A three-letter ISO 4217 code, such as `eur`, states them in that currency. A variant converts only where a payment quote for it would be priced in that currency, and stays in its own currency otherwise: a renewing variant, one with adaptive pricing off, a currency no payment method can collect, or `auto` for a buyer Whop cannot place in a country. Converted prices are an estimate at the current exchange rate. Nothing is held: the payment quote the buyer pays from fixes the rate. +**presentmentCurrency:** `*string` — The currency to state each variant's prices in. Omit it, or send null, for each variant's own currency. `auto` states them in the currency of the country Whop places the buyer in: by `ip_address` when your server sends one, and by the request's own IP address otherwise. To choose that country instead, send `presentment_country` in place of this. A three-letter ISO 4217 code, such as `eur`, states them in that currency. A variant converts only where a payment quote for it would be priced in that currency, and stays in its own currency otherwise: a renewing variant, one with adaptive pricing off, a currency no payment method can collect, or `auto` for a buyer Whop cannot place in a country. Converted prices are an estimate at the current exchange rate. Nothing is held: the payment quote the buyer pays from fixes the rate. + +
+
+ +
+
+ +**ipAddress:** `*string` — The buyer's IP address, when your server reads on their behalf. Needs an API key; any other caller is placed by its own request. Where `presentment_currency` `auto` finds the buyer's local currency, and where a payment method must be able to collect it.
@@ -39301,7 +39331,7 @@ client.Variants.Retrieve(
-**ipAddress:** `*string` — The buyer's IP address, when your server reads on their behalf. Needs an API key; any other caller is placed by its own request. Where `presentment_currency` `auto` finds the buyer's local currency. +**presentmentCountry:** `*string` — The country to state each variant's prices for, as an ISO 3166-1 alpha-2 code such as `JP`, when the buyer chose one: a store's country picker. States them in the currency `auto` would for a buyer in that country, so send it instead of `presentment_currency`, never with it. Whether a payment method can collect that currency is still judged where the buyer is: by `ip_address`, else by the request's own IP address. A country Whop has no currency for is ignored, and the prices are stated as `auto` would state them.
@@ -44234,7 +44264,7 @@ client.Payments.Direct.Create(
-**quoteID:** `*string` — A payment quote from `POST /payment_quotes`, prefixed `pq_`. The payment charges exactly the quote: its purchase (its variants and quantities, or the `plan` it priced), which this body may then omit, its promo code, and its tax, the quote's `tax_amount` rather than a figure calculated now. Omit it, or send null, to have tax calculated when the payment is charged. The quote must belong to `account_id`. A purchase field you omit or send as null takes the quote's value; the buyer's email, the addresses and the payment method are this request's own, never the quote's. Whatever you do send must describe the quoted purchase: the same variants, quantities and promo code. A quote that priced `plan` takes only the same `plan` you sent to `POST /payment_quotes` (or omit the purchase to take the quoted one), never `plan_id` or `line_items`, and a quote that priced variants by id never takes `plan`. Unless the quote located no buyer (`located_by` is null), the address the payment carries (its shipping address, else its billing address) must put the buyer where the quote priced tax, by country, state and postal code; otherwise the payment is refused with 400 before the payment method is used. A quote located by IP address (`located_by` is `ip_address`) is a preview and cannot be paid. A quote is consumed by one payment: a declined payment keeps it and can be retried; a new payment needs a new quote. A quote cannot be charged through PayPal; such a payment is refused before the payment method is used. A quote priced in a `presentment_currency` is charged in that currency at the quote's `exchange_rate`. A payment refused over its quote carries an error `code`. `quote_expired`: the quote has expired; quote again. `quote_tax_unavailable`: the quote could not price tax; quote again, or omit `quote_id`. `quote_preview_only`: the quote was located by IP address; quote again with the buyer's address. `quote_in_use` (409): another payment holds the quote. `quote_mismatch`: the purchase or the buyer's address is not the one quoted. `quote_rate_expired`: the exchange rate the quote was priced at has moved too far to charge; quote again. `payment_method_currency_unsupported`: the payment method cannot pay in the quote's currency; use another method, or quote again in another currency. `quote_processor_unsupported`: the payment method cannot pay a quote, as with PayPal; use another method, or omit `quote_id` to have tax calculated when the payment is charged. +**quoteID:** `*string` — A payment quote from `POST /payment_quotes`, prefixed `pq_`. The payment charges exactly the quote: its purchase (its variants and quantities, or the `plan` it priced), which this body may then omit, its promo code, and its tax, the quote's `tax_amount` rather than a figure calculated now. Omit it, or send null, to have tax calculated when the payment is charged. The quote must belong to `account_id`. A purchase field you omit or send as null takes the quote's value; the buyer's email, the addresses and the payment method are this request's own, never the quote's. Whatever you do send must describe the quoted purchase: the same variants, quantities and promo code. A quote that priced `plan` takes only the same `plan` you sent to `POST /payment_quotes` (or omit the purchase to take the quoted one), never `plan_id` or `line_items`, and a quote that priced variants by id never takes `plan`. Unless the quote located no buyer (`located_by` is null), the address the payment carries (its shipping address, else its billing address) must put the buyer where the quote priced tax, by country, state and postal code; otherwise the payment is refused with 400 before the payment method is used. A quote located by IP address or by the country the buyer chose (`located_by` is `ip_address` or `presentment_country`) is a preview and cannot be paid. A quote is consumed by one payment: a declined payment keeps it and can be retried; a new payment needs a new quote. A quote cannot be charged through PayPal; such a payment is refused before the payment method is used. A quote priced in a `presentment_currency` is charged in that currency at the quote's `exchange_rate`. A payment refused over its quote carries an error `code`. `quote_expired`: the quote has expired; quote again. `quote_tax_unavailable`: the quote could not price tax; quote again, or omit `quote_id`. `quote_preview_only`: the quote was located by IP address or by the country the buyer chose; quote again with the buyer's address. `quote_in_use` (409): another payment holds the quote. `quote_mismatch`: the purchase or the buyer's address is not the one quoted. `quote_rate_expired`: the exchange rate the quote was priced at has moved too far to charge; quote again. `payment_method_currency_unsupported`: the payment method cannot pay in the quote's currency; use another method, or quote again in another currency. `quote_processor_unsupported`: the payment method cannot pay a quote, as with PayPal; use another method, or omit `quote_id` to have tax calculated when the payment is charged.
diff --git a/variants.go b/variants.go index 35d76f25..b6ce981e 100644 --- a/variants.go +++ b/variants.go @@ -438,10 +438,11 @@ var ( listVariantsRequestFieldCreatedAfter = big.NewInt(1 << 8) listVariantsRequestFieldPresentmentCurrency = big.NewInt(1 << 9) listVariantsRequestFieldIPAddress = big.NewInt(1 << 10) - listVariantsRequestFieldFirst = big.NewInt(1 << 11) - listVariantsRequestFieldAfter = big.NewInt(1 << 12) - listVariantsRequestFieldLast = big.NewInt(1 << 13) - listVariantsRequestFieldBefore = big.NewInt(1 << 14) + listVariantsRequestFieldPresentmentCountry = big.NewInt(1 << 11) + listVariantsRequestFieldFirst = big.NewInt(1 << 12) + listVariantsRequestFieldAfter = big.NewInt(1 << 13) + listVariantsRequestFieldLast = big.NewInt(1 << 14) + listVariantsRequestFieldBefore = big.NewInt(1 << 15) ) type ListVariantsRequest struct { @@ -463,10 +464,12 @@ type ListVariantsRequest struct { CreatedBefore *string `json:"-" url:"created_before,omitempty"` // Only return variants created after this timestamp. CreatedAfter *string `json:"-" url:"created_after,omitempty"` - // The currency to state each variant's prices in. Omit it, or send null, for each variant's own currency. `auto` states them in the currency of the country Whop places the buyer in: by `ip_address` when your server sends one, and by the request's own IP address otherwise. A three-letter ISO 4217 code, such as `eur`, states them in that currency. A variant converts only where a payment quote for it would be priced in that currency, and stays in its own currency otherwise: a renewing variant, one with adaptive pricing off, a currency no payment method can collect, or `auto` for a buyer Whop cannot place in a country. Converted prices are an estimate at the current exchange rate. Nothing is held: the payment quote the buyer pays from fixes the rate. + // The currency to state each variant's prices in. Omit it, or send null, for each variant's own currency. `auto` states them in the currency of the country Whop places the buyer in: by `ip_address` when your server sends one, and by the request's own IP address otherwise. To choose that country instead, send `presentment_country` in place of this. A three-letter ISO 4217 code, such as `eur`, states them in that currency. A variant converts only where a payment quote for it would be priced in that currency, and stays in its own currency otherwise: a renewing variant, one with adaptive pricing off, a currency no payment method can collect, or `auto` for a buyer Whop cannot place in a country. Converted prices are an estimate at the current exchange rate. Nothing is held: the payment quote the buyer pays from fixes the rate. PresentmentCurrency *string `json:"-" url:"presentment_currency,omitempty"` - // The buyer's IP address, when your server reads on their behalf. Needs an API key; any other caller is placed by its own request. Where `presentment_currency` `auto` finds the buyer's local currency. + // The buyer's IP address, when your server reads on their behalf. Needs an API key; any other caller is placed by its own request. Where `presentment_currency` `auto` finds the buyer's local currency, and where a payment method must be able to collect it. IPAddress *string `json:"-" url:"ip_address,omitempty"` + // The country to state each variant's prices for, as an ISO 3166-1 alpha-2 code such as `JP`, when the buyer chose one: a store's country picker. States them in the currency `auto` would for a buyer in that country, so send it instead of `presentment_currency`, never with it. Whether a payment method can collect that currency is still judged where the buyer is: by `ip_address`, else by the request's own IP address. A country Whop has no currency for is ignored, and the prices are stated as `auto` would state them. + PresentmentCountry *string `json:"-" url:"presentment_country,omitempty"` // Number of results to return from the start of the range. First *int `json:"-" url:"first,omitempty"` // Return results after this cursor. Use `page_info.end_cursor` from the previous response to fetch the next page. @@ -566,6 +569,13 @@ func (l *ListVariantsRequest) SetIPAddress(ipAddress *string) { l.require(listVariantsRequestFieldIPAddress) } +// SetPresentmentCountry sets the PresentmentCountry field and marks it as non-optional; +// this prevents an empty or null value for this field from being omitted during serialization. +func (l *ListVariantsRequest) SetPresentmentCountry(presentmentCountry *string) { + l.PresentmentCountry = presentmentCountry + l.require(listVariantsRequestFieldPresentmentCountry) +} + // SetFirst sets the First field and marks it as non-optional; // this prevents an empty or null value for this field from being omitted during serialization. func (l *ListVariantsRequest) SetFirst(first *int) { @@ -598,15 +608,18 @@ var ( retrieveVariantsRequestFieldID = big.NewInt(1 << 0) retrieveVariantsRequestFieldPresentmentCurrency = big.NewInt(1 << 1) retrieveVariantsRequestFieldIPAddress = big.NewInt(1 << 2) + retrieveVariantsRequestFieldPresentmentCountry = big.NewInt(1 << 3) ) type RetrieveVariantsRequest struct { // Variant ID, prefixed `plan_`. ID string `json:"-" url:"-"` - // The currency to state each variant's prices in. Omit it, or send null, for each variant's own currency. `auto` states them in the currency of the country Whop places the buyer in: by `ip_address` when your server sends one, and by the request's own IP address otherwise. A three-letter ISO 4217 code, such as `eur`, states them in that currency. A variant converts only where a payment quote for it would be priced in that currency, and stays in its own currency otherwise: a renewing variant, one with adaptive pricing off, a currency no payment method can collect, or `auto` for a buyer Whop cannot place in a country. Converted prices are an estimate at the current exchange rate. Nothing is held: the payment quote the buyer pays from fixes the rate. + // The currency to state each variant's prices in. Omit it, or send null, for each variant's own currency. `auto` states them in the currency of the country Whop places the buyer in: by `ip_address` when your server sends one, and by the request's own IP address otherwise. To choose that country instead, send `presentment_country` in place of this. A three-letter ISO 4217 code, such as `eur`, states them in that currency. A variant converts only where a payment quote for it would be priced in that currency, and stays in its own currency otherwise: a renewing variant, one with adaptive pricing off, a currency no payment method can collect, or `auto` for a buyer Whop cannot place in a country. Converted prices are an estimate at the current exchange rate. Nothing is held: the payment quote the buyer pays from fixes the rate. PresentmentCurrency *string `json:"-" url:"presentment_currency,omitempty"` - // The buyer's IP address, when your server reads on their behalf. Needs an API key; any other caller is placed by its own request. Where `presentment_currency` `auto` finds the buyer's local currency. + // The buyer's IP address, when your server reads on their behalf. Needs an API key; any other caller is placed by its own request. Where `presentment_currency` `auto` finds the buyer's local currency, and where a payment method must be able to collect it. IPAddress *string `json:"-" url:"ip_address,omitempty"` + // The country to state each variant's prices for, as an ISO 3166-1 alpha-2 code such as `JP`, when the buyer chose one: a store's country picker. States them in the currency `auto` would for a buyer in that country, so send it instead of `presentment_currency`, never with it. Whether a payment method can collect that currency is still judged where the buyer is: by `ip_address`, else by the request's own IP address. A country Whop has no currency for is ignored, and the prices are stated as `auto` would state them. + PresentmentCountry *string `json:"-" url:"presentment_country,omitempty"` // Private bitmask of fields set to an explicit value and therefore not to be omitted explicitFields *big.Int `json:"-" url:"-"` @@ -642,6 +655,13 @@ func (r *RetrieveVariantsRequest) SetIPAddress(ipAddress *string) { r.require(retrieveVariantsRequestFieldIPAddress) } +// SetPresentmentCountry sets the PresentmentCountry field and marks it as non-optional; +// this prevents an empty or null value for this field from being omitted during serialization. +func (r *RetrieveVariantsRequest) SetPresentmentCountry(presentmentCountry *string) { + r.PresentmentCountry = presentmentCountry + r.require(retrieveVariantsRequestFieldPresentmentCountry) +} + var ( variantFieldAccount = big.NewInt(1 << 0) variantFieldAdaptivePricingEnabled = big.NewInt(1 << 1) diff --git a/variants/client.go b/variants/client.go index f375f5db..ebd15a6e 100644 --- a/variants/client.go +++ b/variants/client.go @@ -70,6 +70,9 @@ func NewClient(options *core.RequestOptions) *Client { // IPAddress: whopsdk.String( // "203.0.113.7", // ), +// PresentmentCountry: whopsdk.String( +// "JP", +// ), // } // client.Variants.List( // context.TODO(), @@ -183,6 +186,9 @@ func (c *Client) Create( // IPAddress: whopsdk.String( // "203.0.113.7", // ), +// PresentmentCountry: whopsdk.String( +// "JP", +// ), // } // client.Variants.Retrieve( // context.TODO(), diff --git a/variants/variants_test/variants_test.go b/variants/variants_test/variants_test.go index 9a37252f..0d96c050 100644 --- a/variants/variants_test/variants_test.go +++ b/variants/variants_test/variants_test.go @@ -115,6 +115,9 @@ func TestVariantsListWithWireMock( IPAddress: whopsdk.String( "203.0.113.7", ), + PresentmentCountry: whopsdk.String( + "JP", + ), } _, invocationErr := client.Variants.List( context.TODO(), @@ -125,7 +128,7 @@ func TestVariantsListWithWireMock( ) require.NoError(t, invocationErr, "Client method call should succeed") - VerifyRequestCount(t, "TestVariantsListWithWireMock", "GET", "/variants", map[string]interface{}{"release_methods": "buy_now", "visibilities": "visible", "plan_types": "renewal", "product_ids": "prod_xxxxxxxxxxxxxx", "presentment_currency": "auto", "ip_address": "203.0.113.7"}, 1) + VerifyRequestCount(t, "TestVariantsListWithWireMock", "GET", "/variants", map[string]interface{}{"release_methods": "buy_now", "visibilities": "visible", "plan_types": "renewal", "product_ids": "prod_xxxxxxxxxxxxxx", "presentment_currency": "auto", "ip_address": "203.0.113.7", "presentment_country": "JP"}, 1) } func TestVariantsCreateWithWireMock( @@ -171,6 +174,9 @@ func TestVariantsRetrieveWithWireMock( IPAddress: whopsdk.String( "203.0.113.7", ), + PresentmentCountry: whopsdk.String( + "JP", + ), } _, invocationErr := client.Variants.Retrieve( context.TODO(), @@ -181,7 +187,7 @@ func TestVariantsRetrieveWithWireMock( ) require.NoError(t, invocationErr, "Client method call should succeed") - VerifyRequestCount(t, "TestVariantsRetrieveWithWireMock", "GET", "/variants/id", map[string]interface{}{"presentment_currency": "auto", "ip_address": "203.0.113.7"}, 1) + VerifyRequestCount(t, "TestVariantsRetrieveWithWireMock", "GET", "/variants/id", map[string]interface{}{"presentment_currency": "auto", "ip_address": "203.0.113.7", "presentment_country": "JP"}, 1) } func TestVariantsDeleteWithWireMock( diff --git a/variants_test.go b/variants_test.go index 0d7da6a2..0f4a1b1c 100644 --- a/variants_test.go +++ b/variants_test.go @@ -1365,6 +1365,14 @@ func TestSettersListVariantsRequest(t *testing.T) { assert.NotNil(t, obj.explicitFields) }) + t.Run("SetPresentmentCountry", func(t *testing.T) { + obj := &ListVariantsRequest{} + var fernTestValuePresentmentCountry *string + obj.SetPresentmentCountry(fernTestValuePresentmentCountry) + assert.Equal(t, fernTestValuePresentmentCountry, obj.PresentmentCountry) + assert.NotNil(t, obj.explicitFields) + }) + t.Run("SetFirst", func(t *testing.T) { obj := &ListVariantsRequest{} var fernTestValueFirst *int @@ -1741,6 +1749,37 @@ func TestSettersMarkExplicitListVariantsRequest(t *testing.T) { // It verifies that setting a field via setter allows successful JSON round-trip }) + t.Run("SetPresentmentCountry_MarksExplicit", func(t *testing.T) { + t.Parallel() + // Arrange + obj := &ListVariantsRequest{} + var fernTestValuePresentmentCountry *string + + // Act + obj.SetPresentmentCountry(fernTestValuePresentmentCountry) + + // Assert - object with explicitly set field can be marshaled/unmarshaled + bytes, err := json.Marshal(obj) + require.NoError(t, err, "marshaling should succeed for test setup") + + // This test ensures JSON marshaling and unmarshaling succeed when the field has a zero/nil value + // Detect if marshaled JSON is an object or primitive to use correct unmarshal target + if len(bytes) > 0 && bytes[0] == '{' { + // JSON object - unmarshal into map + var unmarshaled map[string]interface{} + err = json.Unmarshal(bytes, &unmarshaled) + require.NoError(t, err, "unmarshaling should succeed for test verification") + } else { + // JSON primitive (string, number, boolean, null) - unmarshal into interface{} + var unmarshaled interface{} + err = json.Unmarshal(bytes, &unmarshaled) + require.NoError(t, err, "unmarshaling should succeed for test verification") + } + + // Note: This does not explicitly assert the presence of a specific JSON field + // It verifies that setting a field via setter allows successful JSON round-trip + }) + t.Run("SetFirst_MarksExplicit", func(t *testing.T) { t.Parallel() // Arrange @@ -1892,6 +1931,14 @@ func TestSettersRetrieveVariantsRequest(t *testing.T) { assert.NotNil(t, obj.explicitFields) }) + t.Run("SetPresentmentCountry", func(t *testing.T) { + obj := &RetrieveVariantsRequest{} + var fernTestValuePresentmentCountry *string + obj.SetPresentmentCountry(fernTestValuePresentmentCountry) + assert.Equal(t, fernTestValuePresentmentCountry, obj.PresentmentCountry) + assert.NotNil(t, obj.explicitFields) + }) + } func TestSettersMarkExplicitRetrieveVariantsRequest(t *testing.T) { @@ -1988,6 +2035,37 @@ func TestSettersMarkExplicitRetrieveVariantsRequest(t *testing.T) { // It verifies that setting a field via setter allows successful JSON round-trip }) + t.Run("SetPresentmentCountry_MarksExplicit", func(t *testing.T) { + t.Parallel() + // Arrange + obj := &RetrieveVariantsRequest{} + var fernTestValuePresentmentCountry *string + + // Act + obj.SetPresentmentCountry(fernTestValuePresentmentCountry) + + // Assert - object with explicitly set field can be marshaled/unmarshaled + bytes, err := json.Marshal(obj) + require.NoError(t, err, "marshaling should succeed for test setup") + + // This test ensures JSON marshaling and unmarshaling succeed when the field has a zero/nil value + // Detect if marshaled JSON is an object or primitive to use correct unmarshal target + if len(bytes) > 0 && bytes[0] == '{' { + // JSON object - unmarshal into map + var unmarshaled map[string]interface{} + err = json.Unmarshal(bytes, &unmarshaled) + require.NoError(t, err, "unmarshaling should succeed for test verification") + } else { + // JSON primitive (string, number, boolean, null) - unmarshal into interface{} + var unmarshaled interface{} + err = json.Unmarshal(bytes, &unmarshaled) + require.NoError(t, err, "unmarshaling should succeed for test verification") + } + + // Note: This does not explicitly assert the presence of a specific JSON field + // It verifies that setting a field via setter allows successful JSON round-trip + }) + } func TestSettersVariant(t *testing.T) { diff --git a/wiremock/wiremock-mappings.json b/wiremock/wiremock-mappings.json index 702404b5..0022fe64 100644 --- a/wiremock/wiremock-mappings.json +++ b/wiremock/wiremock-mappings.json @@ -14375,6 +14375,9 @@ }, "ip_address": { "equalTo": "203.0.113.7" + }, + "presentment_country": { + "equalTo": "JP" } } }, @@ -14451,6 +14454,9 @@ }, "ip_address": { "equalTo": "203.0.113.7" + }, + "presentment_country": { + "equalTo": "JP" } } }, From 30a354b5ba78bc3a36fd7f81447c1bef7fa4526e Mon Sep 17 00:00:00 2001 From: "fern-api[bot]" <115122769+fern-api[bot]@users.noreply.github.com> Date: Sat, 10 Oct 2026 13:33:14 +0000 Subject: [PATCH 2/2] [fern-replay] advance lockfile --- .fern/replay.lock | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.fern/replay.lock b/.fern/replay.lock index 224b5143..792d14ca 100644 --- a/.fern/replay.lock +++ b/.fern/replay.lock @@ -2238,5 +2238,11 @@ generations: cli_version: unknown generator_versions: fernapi/fern-go-sdk: 1.65.1 -current_generation: 9f45a17aa8662ff22dc5259d0f6fbb5238ba75aa + - commit_sha: 2e457a75d5abf52d383529515e7dde73c8276069 + tree_hash: 4744c46f4d8f27a83cdd390708052485ce199fc9 + timestamp: 2026-10-10T13:33:12.363Z + cli_version: unknown + generator_versions: + fernapi/fern-go-sdk: 1.65.1 +current_generation: 2e457a75d5abf52d383529515e7dde73c8276069 patches: []