if ( ! $this->response instanceof ApiResponse ) {
$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() ];
* Retrieve last API call response and display error messages.
* @param string $type Type of error message.
private function add_response_errors_message( string $type = 'API' ) {
$errors = $this->get_response_errors();
if ( empty( $errors ) ) {
$key = ( $type === 'Exception' ) ? 'message' : 'detail';
foreach ( $errors as $error ) {
$message = $error[ $key ] ?? '';
if ( empty( $error['code'] ) || empty( $message ) ) {
$this->errors[] = esc_html( $type ) . ': (' . esc_html( $error['code'] ) . ') ' . esc_html( $message );
* Perform a subscription transaction.
* @param array $args Payment arguments.
private function perform_subscription_transaction( array $args ) {
$customer_request = $this->prepare_create_customer_request( $args );
$customer = $this->send_create_customer_request( $customer_request );
if ( ! $customer instanceof Customer ) {
// 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 ) {
// Get a subscription plan.
$plan = $this->get_plan( $args );
if ( ! $plan instanceof CatalogObject ) {
// Get a subscription plan variation.
$plan_variation = $this->get_plan_variation( $args, $plan );
if ( ! $plan_variation instanceof CatalogObject ) {
// 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.
* @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.
* @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 );
* Prepare a create customer card request object for sending to API.
* @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'] );
* Prepare a create subscription request object for sending to API.
* @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 );
* Retrieve a create customer request object.
* @return CreateCustomerRequest
private function get_create_customer_request_object(): CreateCustomerRequest {
$request = new CreateCustomerRequest();
$request->setIdempotencyKey( $this->get_idempotency_key() );
* Retrieve a search catalog request object.
* @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->setQuery( new CatalogQuery() );
$request->getQuery()->setExactQuery( new CatalogQueryExact( 'name', $name ) );
* Retrieve a create plan request object.
* @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 );
* Get subscription plan variation.
* @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 ) {
$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 ) {
* Retrieve a create plan variation request object.
* @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() );
* Retrieve a create subscription request object.
* @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 );
* Send a create customer request to API.
* @param CreateCustomerRequest $request Create customer request object.
private function send_create_customer_request( $request ) {
$this->response = $this->client->getCustomersApi()->createCustomer( $request );
if ( ! $this->response->isSuccess() ) {
$this->errors[] = esc_html__( 'Square fail: customer was not created.', 'wpforms-lite' );
return $this->response->getResult()->getCustomer();
} catch ( ApiException $e ) {
$this->errors[] = esc_html__( 'Square fail: customer was not created.', 'wpforms-lite' );
* Send a retrieve card request to API.
* @param string $id The ID of the customer to retrieve.
private function send_retrieve_card_request( string $id ) {
$response = $this->client->getCardsApi()->retrieveCard( $id );
if ( ! $response->isSuccess() ) {
return $response->getResult()->getCard();
} catch ( ApiException $e ) {
* Send a create customer card request to API.
* @param CreateCardRequest $request Create card request object.
private function send_create_customer_card_request( $request ) {
$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 $this->response->getResult()->getCard();
} catch ( ApiException $e ) {
$this->errors[] = esc_html__( 'Square fail: customer card was not created.', 'wpforms-lite' );
* Send a search catalog request to API.
* @param SearchCatalogObjectsRequest $request Search subscription plan request object.
* @return CatalogObject|null
private function send_search_catalog_request( $request ) {
$this->response = $this->client->getCatalogApi()->searchCatalogObjects( $request );
if ( ! $this->response->isSuccess() ) {
$objects = $this->response->getResult()->getObjects();
if ( ! is_array( $objects ) || empty( $objects[0] ) ) {
} catch ( ApiException $e ) {
* @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.
$create_plan_request = $this->get_create_plan_request_object( $args );
$plan = $this->send_create_plan_request( $create_plan_request );
if ( ! $plan instanceof CatalogObject ) {
* Send a create subscription plan request to API.