芝麻web文件管理V1.00
编辑当前文件:/home/disqkgca/aqanet.org/wp-content/plugins/wpforms-lite/src/Integrations/Square/Api/Api.php
client = new SquareClient( [ 'accessToken' => $connection->get_access_token(), 'environment' => $connection->get_mode(), ] ); } /** * Set tokens from a submitted form data. * * @since 1.9.5 * * @param array $entry Copy of original $_POST. */ public function set_payment_tokens( array $entry ) { if ( ! empty( $entry['square']['source_id'] ) ) { $this->source_id = $entry['square']['source_id']; } } /** * Check if OAuth connection is present and ready to use. * * @since 1.9.5 */ private function check_connection() { $connection = Connection::get(); if ( ! $connection || ! $connection->is_configured() ) { $this->errors[] = esc_html__( 'Square account connection is missing.', 'wpforms-lite' ); return; } if ( ! $connection->is_valid() ) { $this->errors[] = esc_html__( 'Square account connection is invalid.', 'wpforms-lite' ); return; } if ( ! $connection->is_currency_matched() ) { $this->errors[] = esc_html__( 'The currency associated with the payment is not valid for the provided business location.', 'wpforms-lite' ); } } /** * Check if single payment tokens are present. * * @since 1.9.5 */ private function check_payment_tokens() { if ( empty( $this->source_id ) ) { $this->errors[] = esc_html__( 'Square payment stopped, missing card tokens.', 'wpforms-lite' ); } } /** * Check if all required general arguments are present. * * @since 1.9.5 * * @param array $args Arguments to check. */ private function check_required_args_general( array $args ) { if ( empty( $args['location_id'] ) ) { $this->errors[] = esc_html__( 'Missing location ID.', 'wpforms-lite' ); } if ( empty( $args['currency'] ) ) { $this->errors[] = esc_html__( 'Missing currency.', 'wpforms-lite' ); } if ( empty( $args['amount'] ) && ! is_numeric( $args['amount'] ) ) { $this->errors[] = esc_html__( 'Missing amount.', 'wpforms-lite' ); } } /** * Check if all required single payment arguments are present. * * @since 1.9.5 * * @param array $args Arguments to check. */ private function check_required_args_single( array $args ) { if ( empty( $args['order_items'] ) ) { $this->errors[] = esc_html__( 'Missing order/payment items.', 'wpforms-lite' ); } } /** * Process single transaction. * * @since 1.9.5 * * @param array $args Payment arguments. */ public function process_single_transaction( array $args ) { $this->check_connection(); $this->check_payment_tokens(); $this->check_required_args_general( $args ); $this->check_required_args_single( $args ); if ( $this->errors ) { return; } $result = $this->perform_single_transaction( $args ); /** * Fire when a single transaction is performed. * * @since 1.9.5 * * @param array $result Single transaction result. * @param array $args Payment arguments. * @param Api $api Api class instance. */ do_action( 'wpforms_square_api_process_single_transaction_after', $result, $args, $this ); // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName } /** * Process subscription transaction. * * @since 1.9.5 * * @param array $args Payment arguments. */ public function process_subscription_transaction( array $args ) { $this->check_connection(); $this->check_payment_tokens(); $this->check_required_args_general( $args ); $this->check_required_args_subscription( $args ); if ( $this->errors ) { return; } $this->perform_subscription_transaction( $args ); } /** * Refund payment. * * @since 1.9.5 * * @param string $payment_id Payment ID. * @param array $args Payment data. */ public function refund_payment( string $payment_id, array $args ): bool { try { $request = new RefundPaymentRequest( $this->get_idempotency_key(), new Money() ); $request->setPaymentId( $payment_id ); $request->setReason( $args['reason'] ); $request->getAmountMoney()->setAmount( $args['amount'] ); $request->getAmountMoney()->setCurrency( $args['currency'] ); $this->response = $this->client->getRefundsApi()->refundPayment( $request ); if ( ! $this->response->isSuccess() ) { return false; } } catch ( ApiException $e ) { $this->exception = $e; return false; } return true; } /** * Update subscription. * * @since 1.9.5 * * @param array $args Subscription arguments. */ public function update_subscription( array $args ) { $subscription = $this->retrieve_subscription( $args['id'] ); if ( ! $subscription instanceof Subscription ) { return; } $request = $this->get_update_subscription_request_object( $subscription, $args ); $this->send_update_subscription_request( $args['id'], $request ); } /** * Cancel subscription. * * @since 1.9.5 * * @param string $subscription_id Subscription id. * * @return bool */ public function cancel_subscription( string $subscription_id ): bool { try { $this->response = $this->client->getSubscriptionsApi()->cancelSubscription( $subscription_id ); if ( ! $this->response->isSuccess() ) { return false; } } catch ( ApiException $e ) { $this->exception = $e; return false; } return true; } /** * Retrieve a Card object. * * @since 1.9.5 * * @param Subscription $subscription Subscription object. * * @return Card|null */ public function get_subscription_card( $subscription ) { if ( ! $subscription instanceof Subscription ) { return null; } $card_id = $subscription->getCardId(); if ( empty( $card_id ) ) { return null; } // Get a customer. $card = $this->send_retrieve_card_request( $card_id ); if ( ! $card instanceof Card ) { return null; } return $card; } /** * Send a retrieve subscription request to API. * * @since 1.9.5 * * @param string $id The ID of the subscription to retrieve. * * @return Subscription|null */ public function retrieve_subscription( string $id ) { try { $response = $this->client->getSubscriptionsApi()->retrieveSubscription( $id ); if ( ! $response->isSuccess() ) { return null; } return $response->getResult()->getSubscription(); } catch ( ApiException $e ) { return null; } } /** * Retrieve a Card object. * * @since 1.9.5 * * @param Subscription $subscription Subscription object. * * @return Invoice|null */ public function get_latest_subscription_invoice( $subscription ) { if ( ! $subscription instanceof Subscription ) { return null; } try { $invoices = $subscription->getInvoiceIds(); if ( empty( $invoices ) ) { return null; } // Get a customer. $response = $this->client->getInvoicesApi()->getInvoice( reset( $invoices ) ); // Get the latest invoice by using the first ID in the array as the subscription's invoice IDs are sorted by date in ascending order. if ( ! $response->isSuccess() ) { return null; } return $response->getResult()->getInvoice(); } catch ( ApiException $e ) { return null; } } /** * Perform a single transaction. * * @since 1.9.5 * * @param array $args Payment arguments. * * @return array */ private function perform_single_transaction( array $args ): array { $result = []; // Create an order. $order_request = $this->prepare_create_order_request( $args ); $order = $this->send_create_order_request( $order_request ); if ( ! $order instanceof Order ) { return $result; } $result['order'] = $order; // Create a payment. $payment_request = $this->prepare_create_payment_request( $order, $args ); $payment = $this->send_create_payment_request( $payment_request ); // In this case we should cancel an order. if ( ! $payment instanceof Payment ) { $update_order_request = $this->prepare_update_order_request( $order ); $updated_order = $this->send_update_order_request( $order->getId(), $update_order_request ); return $updated_order instanceof Order ? [ 'order' => $updated_order ] : $result; } $result['payment'] = $payment; return $result; } /** * Prepare a create order request object for sending to API. * * @since 1.9.5 * * @param array $args Single payment arguments. * * @return CreateOrderRequest */ private function prepare_create_order_request( array $args ): CreateOrderRequest { $request = $this->get_create_order_request_object( $args ); $request = $this->create_order_request_set_line_items( $request, $args ); $request = $this->create_order_request_set_discounts( $request, $args ); /** * Filter a create order request object. * * @since 1.9.5 * * @param CreateOrderRequest $request Create order request object. * @param array $args Payment arguments. * @param Api $api Api class instance. */ return apply_filters( 'wpforms_square_api_prepare_create_order_request', $request, $args, $this ); // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName } /** * Prepare an update order request object for sending to API. * * @since 1.9.5 * * @param Order $order Order object. * * @return UpdateOrderRequest */ private function prepare_update_order_request( $order ): UpdateOrderRequest { $request = $this->get_update_order_request_object( $order ); /** * Filter an update order request object. * * @since 1.9.5 * * @param UpdateOrderRequest $request Update order request object. * @param Order $order Order object. * @param Api $api Api class instance. */ return apply_filters( 'wpforms_square_api_prepare_update_order_request', $request, $order, $this ); // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName } /** * Prepare a create payment request object for sending to API. * * @since 1.9.5 * * @param Order $order Order object. * @param array $args Payment arguments. * * @return CreatePaymentRequest */ private function prepare_create_payment_request( $order, array $args ): CreatePaymentRequest { $request = $this->get_create_payment_request_object(); $request = $this->create_payment_request_set_order( $request, $order ); if ( ! empty( $args['billing'] ) ) { $address = $this->get_address_object( $args['billing'] ); $request->setBillingAddress( $address ); } if ( ! empty( $args['buyer_email'] ) ) { $request->setBuyerEmailAddress( $args['buyer_email'] ); } if ( ! empty( $args['note'] ) ) { $request->setNote( $args['note'] ); } /** * Filter a create payment request object. * * @since 1.9.5 * * @param CreateOrderRequest $request Create payment request object. * @param array $args Payment arguments. * @param Api $api Api class instance. */ return apply_filters( 'wpforms_square_api_prepare_create_payment_request', $request, $args, $this ); // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName } /** * Retrieve a create order request object. * * @since 1.9.5 * * @param array $args Payment arguments. * * @return CreateOrderRequest */ private function get_create_order_request_object( array $args ): CreateOrderRequest { $request = new CreateOrderRequest(); $request->setIdempotencyKey( $this->get_idempotency_key() ); $request->setOrder( new Order( $args['location_id'] ) ); $request->getOrder()->setSource( new OrderSource() ); $request->getOrder()->getSource()->setName( Square::APP_NAME ); return $request; } /** * Retrieve an update order request object. * * @since 1.9.5 * * @param Order $order Order object. * * @return UpdateOrderRequest */ private function get_update_order_request_object( $order ): UpdateOrderRequest { $request = new UpdateOrderRequest(); $request->setIdempotencyKey( $this->get_idempotency_key() ); $request->setOrder( $order ); $request->getOrder()->setState( OrderState::CANCELED ); return $request; } /** * Retrieve a create payment request object. * * @since 1.9.5 * * @return CreatePaymentRequest */ private function get_create_payment_request_object(): CreatePaymentRequest { $request = new CreatePaymentRequest( $this->source_id, $this->get_idempotency_key() ); $request->setAmountMoney( new Money() ); return $request; } /** * Send a create order request object to API. * * @since 1.9.5 * * @param CreateOrderRequest $request Create order request object. * * @return Order|null */ private function send_create_order_request( $request ) { try { $this->response = $this->client->getOrdersApi()->createOrder( $request ); if ( ! $this->response->isSuccess() ) { $this->errors[] = esc_html__( 'Square fail: order was not created.', 'wpforms-lite' ); return null; } return $this->response->getResult()->getOrder(); } catch ( ApiException $e ) { $this->exception = $e; $this->errors[] = esc_html__( 'Square fail: order was not created.', 'wpforms-lite' ); return null; } } /** * Send an update order request object to API. * * @since 1.9.5 * * @param string $order_id The ID of the order to update. * @param UpdateOrderRequest $request Update order request object. * * @return Order|null */ private function send_update_order_request( string $order_id, $request ) { try { $response = $this->client->getOrdersApi()->updateOrder( $order_id, $request ); if ( ! $response->isSuccess() ) { return null; } return $response->getResult()->getOrder(); } catch ( ApiException $e ) { return null; } } /** * Send a create payment request to API. * * @since 1.9.5 * * @param CreatePaymentRequest $request Create payment request object. * * @return Payment|null */ private function send_create_payment_request( $request ) { try { $this->response = $this->client->getPaymentsApi()->createPayment( $request ); if ( ! $this->response->isSuccess() ) { $this->errors[] = esc_html__( 'Square fail: payment was not processed.', 'wpforms-lite' ); $this->add_response_errors_message(); return null; } return $this->response->getResult()->getPayment(); } catch ( ApiException $e ) { $this->exception = $e; $this->errors[] = esc_html__( 'Square fail: payment was not processed.', 'wpforms-lite' ); $this->add_response_errors_message( 'Exception' ); return null; } } /** * Set line items to a create order request object. * * @since 1.9.5 * * @param CreateOrderRequest $request Request to create an order. * @param array $args Payment arguments. * * @return CreateOrderRequest */ private function create_order_request_set_line_items( $request, array $args ): CreateOrderRequest { $line_items = []; foreach ( (array) $args['order_items'] as $item ) { // Order item without variations. if ( empty( $item['variations'] ) ) { $line_items[] = $this->get_order_line_item_object( $item, $args ); continue; } // Order item with variations (e.g. Small, Medium and Large). foreach ( (array) $item['variations'] as $variation ) { $order_line_item = $this->get_order_line_item_object( $variation, $args ); $order_line_item->setVariationName( $variation['variation_name'] ); $line_items[] = $order_line_item; } } $request->getOrder()->setLineItems( $line_items ); return $request; } /** * Set discounts to a create order request object. * * @since 1.9.5 * * @param CreateOrderRequest $request Request to create an order. * @param array $args Payment arguments. * * @return CreateOrderRequest */ private function create_order_request_set_discounts( $request, array $args ): CreateOrderRequest { $discounts = []; if ( empty( $args['discounts'] ) ) { return $request; } foreach ( (array) $args['discounts'] as $discount ) { $discounts[] = $this->get_order_discount_object( $discount, $args ); } if ( ! empty( $discounts ) ) { $request->getOrder()->setDiscounts( $discounts ); } return $request; } /** * Set order to a create payment request object. * * @since 1.9.5 * * @param CreatePaymentRequest $request Create payment request object. * @param Order $order Order object. * * @return CreatePaymentRequest */ private function create_payment_request_set_order( $request, $order ): CreatePaymentRequest { $request->setOrderId( $order->getId() ); $request->setLocationId( $order->getLocationId() ); $amount = $order->getTotalMoney()->getAmount(); $currency = $order->getTotalMoney()->getCurrency(); $request->getAmountMoney()->setAmount( $amount ); $request->getAmountMoney()->setCurrency( $currency ); if ( ! Helpers::is_license_ok() && Helpers::is_application_fee_supported( $currency ) ) { $request->setAppFeeMoney( new Money() ); $request->getAppFeeMoney()->setAmount( (int) ( round( $amount * 0.03 ) ) ); $request->getAppFeeMoney()->setCurrency( $currency ); } return $request; } /** * Retrieve a single order line item object. * * @since 1.9.5 * * @param array $item Order item data. * @param array $args Payment arguments. * * @return OrderLineItem */ private function get_order_line_item_object( array $item, array $args ): OrderLineItem { $order_line_items = new OrderLineItem( $item['quantity'] ); $order_line_items->setName( $item['name'] ); $order_line_items->setBasePriceMoney( new Money() ); // Round to the nearest whole number because $item['amount'] can contain a number close to, // but slightly under it, due to how it is stored in the memory. $order_line_items->getBasePriceMoney()->setAmount( round( $item['amount'] ) ); $order_line_items->getBasePriceMoney()->setCurrency( $args['currency'] ); return $order_line_items; } /** * Retrieve a single order discount object. * * @since 1.9.5 * * @param array $discount Discount data. * @param array $args Payment arguments. * * @return OrderLineItemDiscount */ private function get_order_discount_object( array $discount, array $args ): OrderLineItemDiscount { $order_discounts = new OrderLineItemDiscount(); $order_discounts->setName( $discount['name'] ); $order_discounts->setAmountMoney( new Money() ); $order_discounts->getAmountMoney()->setAmount( $discount['amount'] ); $order_discounts->getAmountMoney()->setCurrency( $args['currency'] ); return $order_discounts; } /** * Prepare and retrieve an address object. * * @since 1.9.5 * * @param array $data Address data. * * @return Address */ private function get_address_object( array $data ): Address { $address = new Address(); // The empty country value may occur API errors. if ( ! empty( $data['address']['country'] ) ) { $address->setAddressLine1( $data['address']['address1'] ); $address->setAddressLine2( $data['address']['address2'] ); $address->setLocality( $data['address']['city'] ); $address->setAdministrativeDistrictLevel1( $data['address']['state'] ); $address->setPostalCode( $data['address']['postal'] ); $address->setCountry( $data['address']['country'] ); } if ( ! empty( $data['first_name'] ) ) { $address->setFirstName( $data['first_name'] ); } if ( ! empty( $data['last_name'] ) ) { $address->setLastName( $data['last_name'] ); } return $address; } /** * Retrieve information of all locations of a business. * * @since 1.9.5 * * @return array|Location|null */ public function get_locations() { try { $this->response = $this->client->getLocationsApi()->listLocations(); if ( ! $this->response->isSuccess() ) { return null; } return $this->response->getResult()->getLocations(); } catch ( ApiException $e ) { $this->exception = $e; return null; } } /** * Retrieve a Merchant object with details. * * @since 1.9.5 * * @param string $id The Merchant ID. * * @return Merchant|null */ public function get_merchant( string $id ) { try { $this->response = $this->client->getMerchantsApi()->retrieveMerchant( $id ); if ( ! $this->response->isSuccess() ) { return null; } return $this->response->getResult()->getMerchant(); } catch ( ApiException $e ) { $this->exception = $e; return null; } } /** * Retrieve an idempotency key. * * @since 1.9.5 * * @link https://developer.squareup.com/docs/working-with-apis/idempotency * * @return string */ private function get_idempotency_key(): string { return uniqid( '', false ); } /** * Retrieve API errors. * * @since 1.9.5 * * @return array|null */ public function get_errors() { return $this->errors; } /** * Retrieve last API call errors if are exist. * * @since 1.9.5 * * @return array */ public function get_response_errors(): array { if ( $this->response instanceof ApiResponse && ! $this->response->isSuccess() ) { $errors = []; foreach ( (array) $this->response->getErrors() as $error ) { $errors[] = $error->jsonSerialize(); } return $errors; } if ( $this->exception instanceof ApiException ) { return [ 'code' => $this->exception->getCode(), 'message' => $this->exception->getMessage(), ]; } return []; } /** * Retrieve last API call response resource. * * @since 1.9.5 * * @return array */ public function get_response_resource(): array { if ( ! $this->response instanceof ApiResponse ) { return []; } $result = $this->response->getResult(); if ( $result instanceof CreatePaymentResponse ) { return [ 'payment' => $this->response->getResult()->getPayment() ]; } if ( $result instanceof CreateSubscriptionResponse || $result instanceof UpdateSubscriptionResponse ) { return [ 'subscription' => $this->response->getResult()->getSubscription() ]; } return []; } /** * Retrieve last API call response and display error messages. * * @since 1.14.0 * * @param string $type Type of error message. */ private function add_response_errors_message( string $type = 'API' ) { $errors = $this->get_response_errors(); if ( empty( $errors ) ) { return; } $key = ( $type === 'Exception' ) ? 'message' : 'detail'; foreach ( $errors as $error ) { $message = $error[ $key ] ?? ''; if ( empty( $error['code'] ) || empty( $message ) ) { return; } $this->errors[] = esc_html( $type ) . ': (' . esc_html( $error['code'] ) . ') ' . esc_html( $message ); } } /** * Perform a subscription transaction. * * @since 1.9.5 * * @param array $args Payment arguments. */ private function perform_subscription_transaction( array $args ) { // Create a customer. $customer_request = $this->prepare_create_customer_request( $args ); $customer = $this->send_create_customer_request( $customer_request ); if ( ! $customer instanceof Customer ) { return; } // Create a customer card. $card_request = $this->prepare_create_customer_card_request( $customer->getId(), $args ); $card = $this->send_create_customer_card_request( $card_request ); if ( ! $card instanceof Card ) { return; } // Get a subscription plan. $plan = $this->get_plan( $args ); if ( ! $plan instanceof CatalogObject ) { return; } // Get a subscription plan variation. $plan_variation = $this->get_plan_variation( $args, $plan ); if ( ! $plan_variation instanceof CatalogObject ) { return; } // Create a subscription. $subscription_request = $this->prepare_create_subscription_request( $plan_variation->getId(), $customer->getId(), $card->getId(), $args ); $this->send_create_subscription_request( $subscription_request ); } /** * Check if all required subscription arguments are present. * * @since 1.9.5 * * @param array $args Arguments to check. */ private function check_required_args_subscription( array $args ) { if ( empty( $args['subscription']['plan_name'] ) ) { $this->errors[] = esc_html__( 'Missing subscription plan name.', 'wpforms-lite' ); } if ( empty( $args['subscription']['plan_variation_name'] ) ) { $this->errors[] = esc_html__( 'Missing subscription plan variation name.', 'wpforms-lite' ); } if ( empty( $args['subscription']['phase_cadence'] ) ) { $this->errors[] = esc_html__( 'Missing subscription cadence.', 'wpforms-lite' ); } if ( empty( $args['subscription']['customer']['first_name'] ) && empty( $args['subscription']['customer']['last_name'] ) ) { $this->errors[] = esc_html__( 'Missing customer name.', 'wpforms-lite' ); } if ( empty( $args['subscription']['customer']['email'] ) ) { $this->errors[] = esc_html__( 'Missing customer email.', 'wpforms-lite' ); } } /** * Prepare a create customer request object for sending to API. * * @since 1.9.5 * * @param array $args Payment arguments. * * @return CreateCustomerRequest */ private function prepare_create_customer_request( array $args ): CreateCustomerRequest { $request = $this->get_create_customer_request_object(); $request->setEmailAddress( $args['subscription']['customer']['email'] ); if ( ! empty( $args['subscription']['customer']['first_name'] ) ) { $request->setGivenName( $args['subscription']['customer']['first_name'] ); } if ( ! empty( $args['subscription']['customer']['last_name'] ) ) { $request->setFamilyName( $args['subscription']['customer']['last_name'] ); } if ( ! empty( $args['subscription']['customer']['address'] ) ) { $address = $this->get_address_object( $args['subscription']['customer'] ); $request->setAddress( $address ); } return $request; } /** * Prepare a create customer card request object for sending to API. * * @since 1.9.5 * * @param string $customer_id Customer ID. * @param array $args Payment arguments. * * @return CreateCardRequest */ private function prepare_create_customer_card_request( string $customer_id, array $args ): CreateCardRequest { $request = new CreateCardRequest( $this->get_idempotency_key(), $this->source_id, new Card() ); $request->getCard()->setCustomerId( $customer_id ); if ( ! empty( $args['subscription']['customer']['address'] ) ) { $address = $this->get_address_object( $args['subscription']['customer'] ); // For subscriptions: make sure that a postal code is not empty. // Otherwise, API error "The postal code doesn't match the one used for card nonce creation" is occur here. if ( ! empty( $address->getPostalCode() ) ) { $request->getCard()->setBillingAddress( $address ); } } if ( ! empty( $args['subscription']['card_name'] ) ) { $request->getCard()->setCardholderName( $args['subscription']['card_name'] ); } return $request; } /** * Prepare a create subscription request object for sending to API. * * @since 1.9.5 * * @param string $plan_id Plan ID. * @param string $customer_id Customer ID. * @param string $card_id Customer ID. * @param array $args Payment arguments. * * @return CreateSubscriptionRequest */ private function prepare_create_subscription_request( string $plan_id, string $customer_id, string $card_id, array $args ): CreateSubscriptionRequest { $request = $this->get_create_subscription_request_object( $plan_id, $customer_id, $args ); $request->setCardId( $card_id ); $request->setSource( new SubscriptionSource() ); $request->getSource()->setName( Square::APP_NAME ); return $request; } /** * Retrieve a create customer request object. * * @since 1.9.5 * * @return CreateCustomerRequest */ private function get_create_customer_request_object(): CreateCustomerRequest { $request = new CreateCustomerRequest(); $request->setIdempotencyKey( $this->get_idempotency_key() ); return $request; } /** * Retrieve a search catalog request object. * * @since 1.9.5 * * @param string $type Object type. * @param string $name Object name. * * @return SearchCatalogObjectsRequest */ private function get_search_catalog_request_object( string $type, string $name ): SearchCatalogObjectsRequest { $request = new SearchCatalogObjectsRequest(); $request->setObjectTypes( [ $type ] ); $request->setLimit( 1 ); $request->setQuery( new CatalogQuery() ); $request->getQuery()->setExactQuery( new CatalogQueryExact( 'name', $name ) ); return $request; } /** * Retrieve a create plan request object. * * @since 1.9.5 * * @param array $args Payment arguments. * * @return UpsertCatalogObjectRequest */ private function get_create_plan_request_object( array $args ): UpsertCatalogObjectRequest { $request = new UpsertCatalogObjectRequest( $this->get_idempotency_key(), new CatalogObject( CatalogObjectType::SUBSCRIPTION_PLAN, '#plan' ) ); $plan_data = new CatalogSubscriptionPlan( $args['subscription']['plan_name'] ); $plan_data->setAllItems( true ); $request->getObject()->setSubscriptionPlanData( $plan_data ); return $request; } /** * Get subscription plan variation. * * @since 1.9.5 * * @param array $args Payment arguments. * @param CatalogObject $plan Plan object. * * @return CatalogObject|null */ private function get_plan_variation( array $args, $plan ) { // Search a subscription plan. $search_plan_request = $this->get_search_catalog_request_object( CatalogObjectType::SUBSCRIPTION_PLAN_VARIATION, $args['subscription']['plan_name'] ); $plan_variation = $this->send_search_catalog_request( $search_plan_request ); // Create a subscription plan if it's not exists. if ( $plan_variation !== null ) { return $plan_variation; } $plan_variations_request = $this->get_create_plan_variations_request_object( $args, $plan ); $plan_variation = $this->send_create_plan_variations_request( $plan_variations_request ); if ( ! $plan_variation instanceof CatalogObject ) { return null; } return $plan_variation; } /** * Retrieve a create plan variation request object. * * @since 1.9.5 * * @param array $args Payment arguments. * @param CatalogObject $plan Plan object. * * @return UpsertCatalogObjectRequest */ private function get_create_plan_variations_request_object( array $args, $plan ): UpsertCatalogObjectRequest { $request = new UpsertCatalogObjectRequest( $this->get_idempotency_key(), new CatalogObject( CatalogObjectType::SUBSCRIPTION_PLAN_VARIATION, '#plan_variation' ) ); $phase = new SubscriptionPhase( $args['subscription']['phase_cadence']['value'] ); $phase->setPricing( new SubscriptionPricing() ); $phase->getPricing()->setType( 'STATIC' ); $phase->getPricing()->setPriceMoney( new Money() ); $phase->getPricing()->getPriceMoney()->setAmount( $args['amount'] ); $phase->getPricing()->getPriceMoney()->setCurrency( $args['currency'] ); $request->getObject()->setSubscriptionPlanVariationData( new CatalogSubscriptionPlanVariation( $args['subscription']['plan_variation_name'], [ $phase ] ) ); $request->getObject()->getSubscriptionPlanVariationData()->setSubscriptionPlanId( $plan->getId() ); return $request; } /** * Retrieve a create subscription request object. * * @since 1.9.5 * * @param string $plan_id Plan ID. * @param string $customer_id Customer ID. * @param array $args Payment arguments. * * @return CreateSubscriptionRequest */ private function get_create_subscription_request_object( string $plan_id, string $customer_id, array $args ): CreateSubscriptionRequest { $request = new CreateSubscriptionRequest( $args['location_id'], $customer_id ); $request->setIdempotencyKey( $this->get_idempotency_key() ); $request->setPlanVariationId( $plan_id ); return $request; } /** * Send a create customer request to API. * * @since 1.9.5 * * @param CreateCustomerRequest $request Create customer request object. * * @return Customer|null */ private function send_create_customer_request( $request ) { try { $this->response = $this->client->getCustomersApi()->createCustomer( $request ); if ( ! $this->response->isSuccess() ) { $this->errors[] = esc_html__( 'Square fail: customer was not created.', 'wpforms-lite' ); return null; } return $this->response->getResult()->getCustomer(); } catch ( ApiException $e ) { $this->exception = $e; $this->errors[] = esc_html__( 'Square fail: customer was not created.', 'wpforms-lite' ); return null; } } /** * Send a retrieve card request to API. * * @since 1.9.5 * * @param string $id The ID of the customer to retrieve. * * @return Card|null */ private function send_retrieve_card_request( string $id ) { try { $response = $this->client->getCardsApi()->retrieveCard( $id ); if ( ! $response->isSuccess() ) { return null; } return $response->getResult()->getCard(); } catch ( ApiException $e ) { return null; } } /** * Send a create customer card request to API. * * @since 1.9.5 * * @param CreateCardRequest $request Create card request object. * * @return Card|null */ private function send_create_customer_card_request( $request ) { try { $this->response = $this->client->getCardsApi()->createCard( $request ); if ( ! $this->response->isSuccess() ) { $this->errors[] = esc_html__( 'Square fail: customer card was not created.', 'wpforms-lite' ); return null; } return $this->response->getResult()->getCard(); } catch ( ApiException $e ) { $this->exception = $e; $this->errors[] = esc_html__( 'Square fail: customer card was not created.', 'wpforms-lite' ); return null; } } /** * Send a search catalog request to API. * * @since 1.9.5 * * @param SearchCatalogObjectsRequest $request Search subscription plan request object. * * @return CatalogObject|null */ private function send_search_catalog_request( $request ) { try { $this->response = $this->client->getCatalogApi()->searchCatalogObjects( $request ); if ( ! $this->response->isSuccess() ) { return null; } $objects = $this->response->getResult()->getObjects(); if ( ! is_array( $objects ) || empty( $objects[0] ) ) { return null; } return $objects[0]; } catch ( ApiException $e ) { $this->exception = $e; return null; } } /** * Get subscription plan. * * @since 1.9.5 * * @param array $args Payment arguments. * * @return CatalogObject|null */ private function get_plan( array $args ) { // Search a subscription plan. $search_plan_request = $this->get_search_catalog_request_object( CatalogObjectType::SUBSCRIPTION_PLAN, $args['subscription']['plan_variation_name'] ); $plan = $this->send_search_catalog_request( $search_plan_request ); // Create a subscription plan if it's not exists. if ( $plan === null ) { $create_plan_request = $this->get_create_plan_request_object( $args ); $plan = $this->send_create_plan_request( $create_plan_request ); } if ( ! $plan instanceof CatalogObject ) { return null; } return $plan; } /** * Send a create subscription plan request to API. * * @since 1.9.5 * * @param UpsertCatalogObjectRequest $request Create subscription plan request object. * * @return CatalogObject|null */ private function send_create_plan_request( $request ) { try { $this->response = $this->client->getCatalogApi()->upsertCatalogObject( $request ); if ( ! $this->response->isSuccess() ) { $this->errors[] = esc_html__( 'Square fail: subscription plan was not created.', 'wpforms-lite' ); return null; } return $this->response->getResult()->getCatalogObject(); } catch ( ApiException $e ) { $this->exception = $e; $this->errors[] = esc_html__( 'Square fail: subscription plan was not created.', 'wpforms-lite' ); return null; } } /** * Send a create subscription plan variations request to API. * * @since 1.9.5 * * @param UpsertCatalogObjectRequest $request Create subscription plan request object. * * @return CatalogObject|null */ private function send_create_plan_variations_request( $request ) { try { $this->response = $this->client->getCatalogApi()->upsertCatalogObject( $request ); if ( ! $this->response->isSuccess() ) { $this->errors[] = esc_html__( 'Square fail: subscription plan variation was not created.', 'wpforms-lite' ); return null; } return $this->response->getResult()->getCatalogObject(); } catch ( ApiException $e ) { $this->exception = $e; $this->errors[] = esc_html__( 'Square fail: subscription plan variation was not created.', 'wpforms-lite' ); return null; } } /** * Send a create subscription request to API. * * @since 1.9.5 * * @param CreateSubscriptionRequest $request Create subscription request object. * * @return Subscription|null */ private function send_create_subscription_request( $request ) { try { $this->response = $this->client->getSubscriptionsApi()->createSubscription( $request ); if ( ! $this->response->isSuccess() ) { $this->errors[] = esc_html__( 'Square fail: something went wrong during subscription process.', 'wpforms-lite' ); return null; } return $this->response->getResult()->getSubscription(); } catch ( ApiException $e ) { $this->exception = $e; $this->errors[] = esc_html__( 'Square fail: something went wrong during subscription process.', 'wpforms-lite' ); return null; } } /** * Retrieve a update subscription request object. * * @since 1.9.5 * * @param Subscription $subscription Subscription object. * @param array $args Subscription arguments. * * @return UpdateSubscriptionRequest|null */ private function get_update_subscription_request_object( $subscription, array $args ) { if ( ! $subscription instanceof Subscription ) { return null; } $subscription->setSource( new SubscriptionSource() ); $subscription->getSource()->setName( Square::APP_NAME . ' Payment #' . $args['payment_id'] ); $request = new UpdateSubscriptionRequest(); $request->setSubscription( $subscription ); return $request; } /** * Send a create subscription request to API. * * @since 1.9.5 * * @param string $subscription_id Subscription id. * @param UpdateSubscriptionRequest $request Update subscription request object. * * @return Subscription|null */ private function send_update_subscription_request( string $subscription_id, $request ) { try { $this->response = $this->client->getSubscriptionsApi()->updateSubscription( $subscription_id, $request ); if ( ! $this->response->isSuccess() ) { $this->errors[] = esc_html__( 'Square fail: something went wrong during subscription update.', 'wpforms-lite' ); return null; } return $this->response->getResult()->getSubscription(); } catch ( ApiException $e ) { $this->exception = $e; $this->errors[] = esc_html__( 'Square fail: something went wrong during subscription update.', 'wpforms-lite' ); return null; } } /** * Retrieve card details from specific transaction in object format. * * @since 1.9.5 * * @param string $transaction_id The ID of the order to retrieve card details from. * * @return stdClass|void */ public function get_card_details_from_transaction_id( string $transaction_id ) { $response = $this->client->getPaymentsApi()->getPayment( $transaction_id ); if ( ! $response->isSuccess() ) { return; } $payment = $response->getResult()->getPayment(); $card_details = $payment->getCardDetails(); if ( ! $card_details ) { return; } $card = $card_details->getCard(); if ( ! $card ) { return; } // Create a temporary object to mimic Square's payment_method_details structure. $details = new stdClass(); $details->source_type = 'card'; $details->card_details = new stdClass(); $details->card_details->card = new stdClass(); $details->card_details->card->last_4 = $card->getLast4(); $details->card_details->card->card_brand = $card->getCardBrand(); $details->card_details->card->exp_month = $card->getExpMonth(); $details->card_details->card->exp_year = $card->getExpYear(); return $details; } /** * Retrieve the latest invoice transaction_id. * * @since 1.9.5 * * @param Invoice $invoice Invoice object. * * @return string */ public function get_latest_invoice_transaction_id( $invoice ): string { $order_id = $invoice->getOrderId(); if ( ! $order_id ) { return ''; } $order_response = $this->client->getOrdersApi()->retrieveOrder( $order_id ); if ( ! $order_response->isSuccess() ) { return ''; } $order = $order_response->getResult()->getOrder(); $tenders = $order->getTenders(); if ( empty( $tenders ) ) { return ''; } // Assuming the last tender represents the final transaction. return end( $tenders )->getPaymentId(); } /** * Retrieve the invoice by order ID. * * @since 1.9.5 * * @param string $order_id Order ID. * * @return Invoice|null */ public function get_invoice_by_order_id( string $order_id ) { $invoices_api = $this->client->getInvoicesApi(); try { $response = $invoices_api->listInvoices( Helpers::get_location_id() ); if ( ! $response->isSuccess() ) { return null; } $invoices = $response->getResult()->getInvoices(); if ( empty( $invoices ) ) { return null; } foreach ( $invoices as $invoice ) { if ( $invoice->getOrderId() === $order_id ) { return $invoice; } } } catch ( ApiException $e ) { return null; } return null; } }