# This file was auto-generated by Fern from our API Definition.

import typing
from ..core.client_wrapper import SyncClientWrapper
from ..requests.money import MoneyParams
from ..requests.address import AddressParams
from ..requests.cash_payment_details import CashPaymentDetailsParams
from ..requests.external_payment_details import ExternalPaymentDetailsParams
from ..requests.customer_details import CustomerDetailsParams
from ..requests.offline_payment_details import OfflinePaymentDetailsParams
from ..core.request_options import RequestOptions
from ..core.http_response import HttpResponse
from ..types.create_payment_response import CreatePaymentResponse
from ..core.serialization import convert_and_respect_annotation_metadata
from ..core.unchecked_base_model import construct_type
from json.decoder import JSONDecodeError
from ..core.api_error import ApiError
from ..types.cancel_payment_by_idempotency_key_response import CancelPaymentByIdempotencyKeyResponse
from ..types.get_payment_response import GetPaymentResponse
from ..core.jsonable_encoder import jsonable_encoder
from ..requests.payment import PaymentParams
from ..types.update_payment_response import UpdatePaymentResponse
from ..types.cancel_payment_response import CancelPaymentResponse
from ..types.complete_payment_response import CompletePaymentResponse
from ..core.client_wrapper import AsyncClientWrapper
from ..core.http_response import AsyncHttpResponse

# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)


class RawPaymentsClient:
    def __init__(self, *, client_wrapper: SyncClientWrapper):
        self._client_wrapper = client_wrapper

    def create(
        self,
        *,
        source_id: str,
        idempotency_key: str,
        amount_money: typing.Optional[MoneyParams] = OMIT,
        tip_money: typing.Optional[MoneyParams] = OMIT,
        app_fee_money: typing.Optional[MoneyParams] = OMIT,
        delay_duration: typing.Optional[str] = OMIT,
        delay_action: typing.Optional[str] = OMIT,
        autocomplete: typing.Optional[bool] = OMIT,
        order_id: typing.Optional[str] = OMIT,
        customer_id: typing.Optional[str] = OMIT,
        location_id: typing.Optional[str] = OMIT,
        team_member_id: typing.Optional[str] = OMIT,
        reference_id: typing.Optional[str] = OMIT,
        verification_token: typing.Optional[str] = OMIT,
        accept_partial_authorization: typing.Optional[bool] = OMIT,
        buyer_email_address: typing.Optional[str] = OMIT,
        buyer_phone_number: typing.Optional[str] = OMIT,
        billing_address: typing.Optional[AddressParams] = OMIT,
        shipping_address: typing.Optional[AddressParams] = OMIT,
        note: typing.Optional[str] = OMIT,
        statement_description_identifier: typing.Optional[str] = OMIT,
        cash_details: typing.Optional[CashPaymentDetailsParams] = OMIT,
        external_details: typing.Optional[ExternalPaymentDetailsParams] = OMIT,
        customer_details: typing.Optional[CustomerDetailsParams] = OMIT,
        offline_payment_details: typing.Optional[OfflinePaymentDetailsParams] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[CreatePaymentResponse]:
        """
        Creates a payment using the provided source. You can use this endpoint
        to charge a card (credit/debit card or
        Square gift card) or record a payment that the seller received outside of Square
        (cash payment from a buyer or a payment that an external entity
        processed on behalf of the seller).

        The endpoint creates a
        `Payment` object and returns it in the response.

        Parameters
        ----------
        source_id : str
            The ID for the source of funds for this payment.
            This could be a payment token generated by the Web Payments SDK for any of its
            [supported methods](https://developer.squareup.com/docs/web-payments/overview#explore-payment-methods),
            including cards, bank transfers, Afterpay or Cash App Pay. If recording a payment
            that the seller received outside of Square, specify either "CASH" or "EXTERNAL".
            For more information, see
            [Take Payments](https://developer.squareup.com/docs/payments-api/take-payments).

        idempotency_key : str
            A unique string that identifies this `CreatePayment` request. Keys can be any valid string
            but must be unique for every `CreatePayment` request.

            Note: The number of allowed characters might be less than the stated maximum, if multi-byte
            characters are used.

            For more information, see [Idempotency](https://developer.squareup.com/docs/working-with-apis/idempotency).

        amount_money : typing.Optional[MoneyParams]
            The amount of money to accept for this payment, not including `tip_money`.

            The amount must be specified in the smallest denomination of the applicable currency
            (for example, US dollar amounts are specified in cents). For more information, see
            [Working with Monetary Amounts](https://developer.squareup.com/docs/build-basics/working-with-monetary-amounts).

            The currency code must match the currency associated with the business
            that is accepting the payment.

        tip_money : typing.Optional[MoneyParams]
            The amount designated as a tip, in addition to `amount_money`.

            The amount must be specified in the smallest denomination of the applicable currency
            (for example, US dollar amounts are specified in cents). For more information, see
            [Working with Monetary Amounts](https://developer.squareup.com/docs/build-basics/working-with-monetary-amounts).

            The currency code must match the currency associated with the business
            that is accepting the payment.

        app_fee_money : typing.Optional[MoneyParams]
            The amount of money that the developer is taking as a fee
            for facilitating the payment on behalf of the seller.

            The amount cannot be more than 90% of the total amount of the payment.

            The amount must be specified in the smallest denomination of the applicable currency
            (for example, US dollar amounts are specified in cents). For more information, see
            [Working with Monetary Amounts](https://developer.squareup.com/docs/build-basics/working-with-monetary-amounts).

            The fee currency code must match the currency associated with the seller
            that is accepting the payment. The application must be from a developer
            account in the same country and using the same currency code as the seller.

            For more information about the application fee scenario, see
            [Take Payments and Collect Fees](https://developer.squareup.com/docs/payments-api/take-payments-and-collect-fees).

            To set this field, `PAYMENTS_WRITE_ADDITIONAL_RECIPIENTS` OAuth permission is required.
            For more information, see [Permissions](https://developer.squareup.com/docs/payments-api/take-payments-and-collect-fees#permissions).

        delay_duration : typing.Optional[str]
            The duration of time after the payment's creation when Square automatically
            either completes or cancels the payment depending on the `delay_action` field value.
            For more information, see
            [Time threshold](https://developer.squareup.com/docs/payments-api/take-payments/card-payments/delayed-capture#time-threshold).

            This parameter should be specified as a time duration, in RFC 3339 format.

            Note: This feature is only supported for card payments. This parameter can only be set for a delayed
            capture payment (`autocomplete=false`).

            Default:

            - Card-present payments: "PT36H" (36 hours) from the creation time.
            - Card-not-present payments: "P7D" (7 days) from the creation time.

        delay_action : typing.Optional[str]
            The action to be applied to the payment when the `delay_duration` has elapsed. The action must be
            CANCEL or COMPLETE. For more information, see
            [Time Threshold](https://developer.squareup.com/docs/payments-api/take-payments/card-payments/delayed-capture#time-threshold).

            Default: CANCEL

        autocomplete : typing.Optional[bool]
            If set to `true`, this payment will be completed when possible. If
            set to `false`, this payment is held in an approved state until either
            explicitly completed (captured) or canceled (voided). For more information, see
            [Delayed capture](https://developer.squareup.com/docs/payments-api/take-payments/card-payments#delayed-capture-of-a-card-payment).

            Default: true

        order_id : typing.Optional[str]
            Associates a previously created order with this payment.

        customer_id : typing.Optional[str]
            The [Customer](entity:Customer) ID of the customer associated with the payment.

            This is required if the `source_id` refers to a card on file created using the Cards API.

        location_id : typing.Optional[str]
            The location ID to associate with the payment. If not specified, the [main location](https://developer.squareup.com/docs/locations-api#about-the-main-location) is
            used.

        team_member_id : typing.Optional[str]
            An optional [TeamMember](entity:TeamMember) ID to associate with
            this payment.

        reference_id : typing.Optional[str]
            A user-defined ID to associate with the payment.

            You can use this field to associate the payment to an entity in an external system
            (for example, you might specify an order ID that is generated by a third-party shopping cart).

        verification_token : typing.Optional[str]
            An identifying token generated by [payments.verifyBuyer()](https://developer.squareup.com/reference/sdks/web/payments/objects/Payments#Payments.verifyBuyer).
            Verification tokens encapsulate customer device information and 3-D Secure
            challenge results to indicate that Square has verified the buyer identity.

            For more information, see [SCA Overview](https://developer.squareup.com/docs/sca-overview).

        accept_partial_authorization : typing.Optional[bool]
            If set to `true` and charging a Square Gift Card, a payment might be returned with
            `amount_money` equal to less than what was requested. For example, a request for $20 when charging
            a Square Gift Card with a balance of $5 results in an APPROVED payment of $5. You might choose
            to prompt the buyer for an additional payment to cover the remainder or cancel the Gift Card
            payment. This field cannot be `true` when `autocomplete = true`.

            For more information, see
            [Partial amount with Square Gift Cards](https://developer.squareup.com/docs/payments-api/take-payments#partial-payment-gift-card).

            Default: false

        buyer_email_address : typing.Optional[str]
            The buyer's email address.

        buyer_phone_number : typing.Optional[str]
            The buyer's phone number.
            Must follow the following format:
            1. A leading + symbol (followed by a country code)
            2. The phone number can contain spaces and the special characters `(` , `)` , `-` , and `.`.
            Alphabetical characters aren't allowed.
            3. The phone number must contain between 9 and 16 digits.

        billing_address : typing.Optional[AddressParams]
            The buyer's billing address.

        shipping_address : typing.Optional[AddressParams]
            The buyer's shipping address.

        note : typing.Optional[str]
            An optional note to be entered by the developer when creating a payment.

        statement_description_identifier : typing.Optional[str]
            Optional additional payment information to include on the customer's card statement
            as part of the statement description. This can be, for example, an invoice number, ticket number,
            or short description that uniquely identifies the purchase.

            Note that the `statement_description_identifier` might get truncated on the statement description
            to fit the required information including the Square identifier (SQ *) and name of the
            seller taking the payment.

        cash_details : typing.Optional[CashPaymentDetailsParams]
            Additional details required when recording a cash payment (`source_id` is CASH).

        external_details : typing.Optional[ExternalPaymentDetailsParams]
            Additional details required when recording an external payment (`source_id` is EXTERNAL).

        customer_details : typing.Optional[CustomerDetailsParams]
            Details about the customer making the payment.

        offline_payment_details : typing.Optional[OfflinePaymentDetailsParams]
            An optional field for specifying the offline payment details. This is intended for
            internal 1st-party callers only.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[CreatePaymentResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            "v2/payments",
            method="POST",
            json={
                "source_id": source_id,
                "idempotency_key": idempotency_key,
                "amount_money": convert_and_respect_annotation_metadata(
                    object_=amount_money, annotation=MoneyParams, direction="write"
                ),
                "tip_money": convert_and_respect_annotation_metadata(
                    object_=tip_money, annotation=MoneyParams, direction="write"
                ),
                "app_fee_money": convert_and_respect_annotation_metadata(
                    object_=app_fee_money, annotation=MoneyParams, direction="write"
                ),
                "delay_duration": delay_duration,
                "delay_action": delay_action,
                "autocomplete": autocomplete,
                "order_id": order_id,
                "customer_id": customer_id,
                "location_id": location_id,
                "team_member_id": team_member_id,
                "reference_id": reference_id,
                "verification_token": verification_token,
                "accept_partial_authorization": accept_partial_authorization,
                "buyer_email_address": buyer_email_address,
                "buyer_phone_number": buyer_phone_number,
                "billing_address": convert_and_respect_annotation_metadata(
                    object_=billing_address, annotation=AddressParams, direction="write"
                ),
                "shipping_address": convert_and_respect_annotation_metadata(
                    object_=shipping_address, annotation=AddressParams, direction="write"
                ),
                "note": note,
                "statement_description_identifier": statement_description_identifier,
                "cash_details": convert_and_respect_annotation_metadata(
                    object_=cash_details, annotation=CashPaymentDetailsParams, direction="write"
                ),
                "external_details": convert_and_respect_annotation_metadata(
                    object_=external_details, annotation=ExternalPaymentDetailsParams, direction="write"
                ),
                "customer_details": convert_and_respect_annotation_metadata(
                    object_=customer_details, annotation=CustomerDetailsParams, direction="write"
                ),
                "offline_payment_details": convert_and_respect_annotation_metadata(
                    object_=offline_payment_details, annotation=OfflinePaymentDetailsParams, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CreatePaymentResponse,
                    construct_type(
                        type_=CreatePaymentResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def cancel_by_idempotency_key(
        self, *, idempotency_key: str, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[CancelPaymentByIdempotencyKeyResponse]:
        """
        Cancels (voids) a payment identified by the idempotency key that is specified in the
        request.

        Use this method when the status of a `CreatePayment` request is unknown (for example, after you send a
        `CreatePayment` request, a network error occurs and you do not get a response). In this case, you can
        direct Square to cancel the payment using this endpoint. In the request, you provide the same
        idempotency key that you provided in your `CreatePayment` request that you want to cancel. After
        canceling the payment, you can submit your `CreatePayment` request again.

        Note that if no payment with the specified idempotency key is found, no action is taken and the endpoint
        returns successfully.

        Parameters
        ----------
        idempotency_key : str
            The `idempotency_key` identifying the payment to be canceled.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[CancelPaymentByIdempotencyKeyResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            "v2/payments/cancel",
            method="POST",
            json={
                "idempotency_key": idempotency_key,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CancelPaymentByIdempotencyKeyResponse,
                    construct_type(
                        type_=CancelPaymentByIdempotencyKeyResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def get(
        self, payment_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[GetPaymentResponse]:
        """
        Retrieves details for a specific payment.

        Parameters
        ----------
        payment_id : str
            A unique ID for the desired payment.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[GetPaymentResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/payments/{jsonable_encoder(payment_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    GetPaymentResponse,
                    construct_type(
                        type_=GetPaymentResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def update(
        self,
        payment_id: str,
        *,
        idempotency_key: str,
        payment: typing.Optional[PaymentParams] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[UpdatePaymentResponse]:
        """
        Updates a payment with the APPROVED status.
        You can update the `amount_money` and `tip_money` using this endpoint.

        Parameters
        ----------
        payment_id : str
            The ID of the payment to update.

        idempotency_key : str
            A unique string that identifies this `UpdatePayment` request. Keys can be any valid string
            but must be unique for every `UpdatePayment` request.

            For more information, see [Idempotency](https://developer.squareup.com/docs/build-basics/common-api-patterns/idempotency).

        payment : typing.Optional[PaymentParams]
            The updated `Payment` object.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[UpdatePaymentResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/payments/{jsonable_encoder(payment_id)}",
            method="PUT",
            json={
                "payment": convert_and_respect_annotation_metadata(
                    object_=payment, annotation=PaymentParams, direction="write"
                ),
                "idempotency_key": idempotency_key,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    UpdatePaymentResponse,
                    construct_type(
                        type_=UpdatePaymentResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def cancel(
        self, payment_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[CancelPaymentResponse]:
        """
        Cancels (voids) a payment. You can use this endpoint to cancel a payment with
        the APPROVED `status`.

        Parameters
        ----------
        payment_id : str
            The ID of the payment to cancel.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[CancelPaymentResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/payments/{jsonable_encoder(payment_id)}/cancel",
            method="POST",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CancelPaymentResponse,
                    construct_type(
                        type_=CancelPaymentResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def complete(
        self,
        payment_id: str,
        *,
        version_token: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[CompletePaymentResponse]:
        """
        Completes (captures) a payment.
        By default, payments are set to complete immediately after they are created.

        You can use this endpoint to complete a payment with the APPROVED `status`.

        Parameters
        ----------
        payment_id : str
            The unique ID identifying the payment to be completed.

        version_token : typing.Optional[str]
            Used for optimistic concurrency. This opaque token identifies the current `Payment`
            version that the caller expects. If the server has a different version of the Payment,
            the update fails and a response with a VERSION_MISMATCH error is returned.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[CompletePaymentResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/payments/{jsonable_encoder(payment_id)}/complete",
            method="POST",
            json={
                "version_token": version_token,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CompletePaymentResponse,
                    construct_type(
                        type_=CompletePaymentResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)


class AsyncRawPaymentsClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._client_wrapper = client_wrapper

    async def create(
        self,
        *,
        source_id: str,
        idempotency_key: str,
        amount_money: typing.Optional[MoneyParams] = OMIT,
        tip_money: typing.Optional[MoneyParams] = OMIT,
        app_fee_money: typing.Optional[MoneyParams] = OMIT,
        delay_duration: typing.Optional[str] = OMIT,
        delay_action: typing.Optional[str] = OMIT,
        autocomplete: typing.Optional[bool] = OMIT,
        order_id: typing.Optional[str] = OMIT,
        customer_id: typing.Optional[str] = OMIT,
        location_id: typing.Optional[str] = OMIT,
        team_member_id: typing.Optional[str] = OMIT,
        reference_id: typing.Optional[str] = OMIT,
        verification_token: typing.Optional[str] = OMIT,
        accept_partial_authorization: typing.Optional[bool] = OMIT,
        buyer_email_address: typing.Optional[str] = OMIT,
        buyer_phone_number: typing.Optional[str] = OMIT,
        billing_address: typing.Optional[AddressParams] = OMIT,
        shipping_address: typing.Optional[AddressParams] = OMIT,
        note: typing.Optional[str] = OMIT,
        statement_description_identifier: typing.Optional[str] = OMIT,
        cash_details: typing.Optional[CashPaymentDetailsParams] = OMIT,
        external_details: typing.Optional[ExternalPaymentDetailsParams] = OMIT,
        customer_details: typing.Optional[CustomerDetailsParams] = OMIT,
        offline_payment_details: typing.Optional[OfflinePaymentDetailsParams] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[CreatePaymentResponse]:
        """
        Creates a payment using the provided source. You can use this endpoint
        to charge a card (credit/debit card or
        Square gift card) or record a payment that the seller received outside of Square
        (cash payment from a buyer or a payment that an external entity
        processed on behalf of the seller).

        The endpoint creates a
        `Payment` object and returns it in the response.

        Parameters
        ----------
        source_id : str
            The ID for the source of funds for this payment.
            This could be a payment token generated by the Web Payments SDK for any of its
            [supported methods](https://developer.squareup.com/docs/web-payments/overview#explore-payment-methods),
            including cards, bank transfers, Afterpay or Cash App Pay. If recording a payment
            that the seller received outside of Square, specify either "CASH" or "EXTERNAL".
            For more information, see
            [Take Payments](https://developer.squareup.com/docs/payments-api/take-payments).

        idempotency_key : str
            A unique string that identifies this `CreatePayment` request. Keys can be any valid string
            but must be unique for every `CreatePayment` request.

            Note: The number of allowed characters might be less than the stated maximum, if multi-byte
            characters are used.

            For more information, see [Idempotency](https://developer.squareup.com/docs/working-with-apis/idempotency).

        amount_money : typing.Optional[MoneyParams]
            The amount of money to accept for this payment, not including `tip_money`.

            The amount must be specified in the smallest denomination of the applicable currency
            (for example, US dollar amounts are specified in cents). For more information, see
            [Working with Monetary Amounts](https://developer.squareup.com/docs/build-basics/working-with-monetary-amounts).

            The currency code must match the currency associated with the business
            that is accepting the payment.

        tip_money : typing.Optional[MoneyParams]
            The amount designated as a tip, in addition to `amount_money`.

            The amount must be specified in the smallest denomination of the applicable currency
            (for example, US dollar amounts are specified in cents). For more information, see
            [Working with Monetary Amounts](https://developer.squareup.com/docs/build-basics/working-with-monetary-amounts).

            The currency code must match the currency associated with the business
            that is accepting the payment.

        app_fee_money : typing.Optional[MoneyParams]
            The amount of money that the developer is taking as a fee
            for facilitating the payment on behalf of the seller.

            The amount cannot be more than 90% of the total amount of the payment.

            The amount must be specified in the smallest denomination of the applicable currency
            (for example, US dollar amounts are specified in cents). For more information, see
            [Working with Monetary Amounts](https://developer.squareup.com/docs/build-basics/working-with-monetary-amounts).

            The fee currency code must match the currency associated with the seller
            that is accepting the payment. The application must be from a developer
            account in the same country and using the same currency code as the seller.

            For more information about the application fee scenario, see
            [Take Payments and Collect Fees](https://developer.squareup.com/docs/payments-api/take-payments-and-collect-fees).

            To set this field, `PAYMENTS_WRITE_ADDITIONAL_RECIPIENTS` OAuth permission is required.
            For more information, see [Permissions](https://developer.squareup.com/docs/payments-api/take-payments-and-collect-fees#permissions).

        delay_duration : typing.Optional[str]
            The duration of time after the payment's creation when Square automatically
            either completes or cancels the payment depending on the `delay_action` field value.
            For more information, see
            [Time threshold](https://developer.squareup.com/docs/payments-api/take-payments/card-payments/delayed-capture#time-threshold).

            This parameter should be specified as a time duration, in RFC 3339 format.

            Note: This feature is only supported for card payments. This parameter can only be set for a delayed
            capture payment (`autocomplete=false`).

            Default:

            - Card-present payments: "PT36H" (36 hours) from the creation time.
            - Card-not-present payments: "P7D" (7 days) from the creation time.

        delay_action : typing.Optional[str]
            The action to be applied to the payment when the `delay_duration` has elapsed. The action must be
            CANCEL or COMPLETE. For more information, see
            [Time Threshold](https://developer.squareup.com/docs/payments-api/take-payments/card-payments/delayed-capture#time-threshold).

            Default: CANCEL

        autocomplete : typing.Optional[bool]
            If set to `true`, this payment will be completed when possible. If
            set to `false`, this payment is held in an approved state until either
            explicitly completed (captured) or canceled (voided). For more information, see
            [Delayed capture](https://developer.squareup.com/docs/payments-api/take-payments/card-payments#delayed-capture-of-a-card-payment).

            Default: true

        order_id : typing.Optional[str]
            Associates a previously created order with this payment.

        customer_id : typing.Optional[str]
            The [Customer](entity:Customer) ID of the customer associated with the payment.

            This is required if the `source_id` refers to a card on file created using the Cards API.

        location_id : typing.Optional[str]
            The location ID to associate with the payment. If not specified, the [main location](https://developer.squareup.com/docs/locations-api#about-the-main-location) is
            used.

        team_member_id : typing.Optional[str]
            An optional [TeamMember](entity:TeamMember) ID to associate with
            this payment.

        reference_id : typing.Optional[str]
            A user-defined ID to associate with the payment.

            You can use this field to associate the payment to an entity in an external system
            (for example, you might specify an order ID that is generated by a third-party shopping cart).

        verification_token : typing.Optional[str]
            An identifying token generated by [payments.verifyBuyer()](https://developer.squareup.com/reference/sdks/web/payments/objects/Payments#Payments.verifyBuyer).
            Verification tokens encapsulate customer device information and 3-D Secure
            challenge results to indicate that Square has verified the buyer identity.

            For more information, see [SCA Overview](https://developer.squareup.com/docs/sca-overview).

        accept_partial_authorization : typing.Optional[bool]
            If set to `true` and charging a Square Gift Card, a payment might be returned with
            `amount_money` equal to less than what was requested. For example, a request for $20 when charging
            a Square Gift Card with a balance of $5 results in an APPROVED payment of $5. You might choose
            to prompt the buyer for an additional payment to cover the remainder or cancel the Gift Card
            payment. This field cannot be `true` when `autocomplete = true`.

            For more information, see
            [Partial amount with Square Gift Cards](https://developer.squareup.com/docs/payments-api/take-payments#partial-payment-gift-card).

            Default: false

        buyer_email_address : typing.Optional[str]
            The buyer's email address.

        buyer_phone_number : typing.Optional[str]
            The buyer's phone number.
            Must follow the following format:
            1. A leading + symbol (followed by a country code)
            2. The phone number can contain spaces and the special characters `(` , `)` , `-` , and `.`.
            Alphabetical characters aren't allowed.
            3. The phone number must contain between 9 and 16 digits.

        billing_address : typing.Optional[AddressParams]
            The buyer's billing address.

        shipping_address : typing.Optional[AddressParams]
            The buyer's shipping address.

        note : typing.Optional[str]
            An optional note to be entered by the developer when creating a payment.

        statement_description_identifier : typing.Optional[str]
            Optional additional payment information to include on the customer's card statement
            as part of the statement description. This can be, for example, an invoice number, ticket number,
            or short description that uniquely identifies the purchase.

            Note that the `statement_description_identifier` might get truncated on the statement description
            to fit the required information including the Square identifier (SQ *) and name of the
            seller taking the payment.

        cash_details : typing.Optional[CashPaymentDetailsParams]
            Additional details required when recording a cash payment (`source_id` is CASH).

        external_details : typing.Optional[ExternalPaymentDetailsParams]
            Additional details required when recording an external payment (`source_id` is EXTERNAL).

        customer_details : typing.Optional[CustomerDetailsParams]
            Details about the customer making the payment.

        offline_payment_details : typing.Optional[OfflinePaymentDetailsParams]
            An optional field for specifying the offline payment details. This is intended for
            internal 1st-party callers only.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[CreatePaymentResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v2/payments",
            method="POST",
            json={
                "source_id": source_id,
                "idempotency_key": idempotency_key,
                "amount_money": convert_and_respect_annotation_metadata(
                    object_=amount_money, annotation=MoneyParams, direction="write"
                ),
                "tip_money": convert_and_respect_annotation_metadata(
                    object_=tip_money, annotation=MoneyParams, direction="write"
                ),
                "app_fee_money": convert_and_respect_annotation_metadata(
                    object_=app_fee_money, annotation=MoneyParams, direction="write"
                ),
                "delay_duration": delay_duration,
                "delay_action": delay_action,
                "autocomplete": autocomplete,
                "order_id": order_id,
                "customer_id": customer_id,
                "location_id": location_id,
                "team_member_id": team_member_id,
                "reference_id": reference_id,
                "verification_token": verification_token,
                "accept_partial_authorization": accept_partial_authorization,
                "buyer_email_address": buyer_email_address,
                "buyer_phone_number": buyer_phone_number,
                "billing_address": convert_and_respect_annotation_metadata(
                    object_=billing_address, annotation=AddressParams, direction="write"
                ),
                "shipping_address": convert_and_respect_annotation_metadata(
                    object_=shipping_address, annotation=AddressParams, direction="write"
                ),
                "note": note,
                "statement_description_identifier": statement_description_identifier,
                "cash_details": convert_and_respect_annotation_metadata(
                    object_=cash_details, annotation=CashPaymentDetailsParams, direction="write"
                ),
                "external_details": convert_and_respect_annotation_metadata(
                    object_=external_details, annotation=ExternalPaymentDetailsParams, direction="write"
                ),
                "customer_details": convert_and_respect_annotation_metadata(
                    object_=customer_details, annotation=CustomerDetailsParams, direction="write"
                ),
                "offline_payment_details": convert_and_respect_annotation_metadata(
                    object_=offline_payment_details, annotation=OfflinePaymentDetailsParams, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CreatePaymentResponse,
                    construct_type(
                        type_=CreatePaymentResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def cancel_by_idempotency_key(
        self, *, idempotency_key: str, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[CancelPaymentByIdempotencyKeyResponse]:
        """
        Cancels (voids) a payment identified by the idempotency key that is specified in the
        request.

        Use this method when the status of a `CreatePayment` request is unknown (for example, after you send a
        `CreatePayment` request, a network error occurs and you do not get a response). In this case, you can
        direct Square to cancel the payment using this endpoint. In the request, you provide the same
        idempotency key that you provided in your `CreatePayment` request that you want to cancel. After
        canceling the payment, you can submit your `CreatePayment` request again.

        Note that if no payment with the specified idempotency key is found, no action is taken and the endpoint
        returns successfully.

        Parameters
        ----------
        idempotency_key : str
            The `idempotency_key` identifying the payment to be canceled.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[CancelPaymentByIdempotencyKeyResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v2/payments/cancel",
            method="POST",
            json={
                "idempotency_key": idempotency_key,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CancelPaymentByIdempotencyKeyResponse,
                    construct_type(
                        type_=CancelPaymentByIdempotencyKeyResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def get(
        self, payment_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[GetPaymentResponse]:
        """
        Retrieves details for a specific payment.

        Parameters
        ----------
        payment_id : str
            A unique ID for the desired payment.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[GetPaymentResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/payments/{jsonable_encoder(payment_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    GetPaymentResponse,
                    construct_type(
                        type_=GetPaymentResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def update(
        self,
        payment_id: str,
        *,
        idempotency_key: str,
        payment: typing.Optional[PaymentParams] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[UpdatePaymentResponse]:
        """
        Updates a payment with the APPROVED status.
        You can update the `amount_money` and `tip_money` using this endpoint.

        Parameters
        ----------
        payment_id : str
            The ID of the payment to update.

        idempotency_key : str
            A unique string that identifies this `UpdatePayment` request. Keys can be any valid string
            but must be unique for every `UpdatePayment` request.

            For more information, see [Idempotency](https://developer.squareup.com/docs/build-basics/common-api-patterns/idempotency).

        payment : typing.Optional[PaymentParams]
            The updated `Payment` object.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[UpdatePaymentResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/payments/{jsonable_encoder(payment_id)}",
            method="PUT",
            json={
                "payment": convert_and_respect_annotation_metadata(
                    object_=payment, annotation=PaymentParams, direction="write"
                ),
                "idempotency_key": idempotency_key,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    UpdatePaymentResponse,
                    construct_type(
                        type_=UpdatePaymentResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def cancel(
        self, payment_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[CancelPaymentResponse]:
        """
        Cancels (voids) a payment. You can use this endpoint to cancel a payment with
        the APPROVED `status`.

        Parameters
        ----------
        payment_id : str
            The ID of the payment to cancel.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[CancelPaymentResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/payments/{jsonable_encoder(payment_id)}/cancel",
            method="POST",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CancelPaymentResponse,
                    construct_type(
                        type_=CancelPaymentResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def complete(
        self,
        payment_id: str,
        *,
        version_token: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[CompletePaymentResponse]:
        """
        Completes (captures) a payment.
        By default, payments are set to complete immediately after they are created.

        You can use this endpoint to complete a payment with the APPROVED `status`.

        Parameters
        ----------
        payment_id : str
            The unique ID identifying the payment to be completed.

        version_token : typing.Optional[str]
            Used for optimistic concurrency. This opaque token identifies the current `Payment`
            version that the caller expects. If the server has a different version of the Payment,
            the update fails and a response with a VERSION_MISMATCH error is returned.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[CompletePaymentResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/payments/{jsonable_encoder(payment_id)}/complete",
            method="POST",
            json={
                "version_token": version_token,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CompletePaymentResponse,
                    construct_type(
                        type_=CompletePaymentResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)
