From 3ae504fa3ca94271aee6f61dd490dd95111efc87 Mon Sep 17 00:00:00 2001 From: Gabriel Peixoto Date: Sat, 20 Jun 2026 00:25:25 -0300 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20Rota=20para=20cancelar=20o=20pix=20?= =?UTF-8?q?autom=C3=A1tico.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Contracts/AutomaticPixContract.php | 24 ++++++++++++++++++ src/Facades/MultiPayment.php | 1 + src/Gateways/IuguGateway.php | 34 +++++++++++++++++++++++++- src/MultiPayment.php | 19 ++++++++++++++ 4 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 src/Contracts/AutomaticPixContract.php diff --git a/src/Contracts/AutomaticPixContract.php b/src/Contracts/AutomaticPixContract.php new file mode 100644 index 0000000..9ea36b3 --- /dev/null +++ b/src/Contracts/AutomaticPixContract.php @@ -0,0 +1,24 @@ +parseInvoice($iuguInvoice); } + /** + * @inheritDoc + * + * Endpoint: PUT /automatic_pix/receiver_recurrences/{id}/cancel + */ + public function cancelAutomaticPixRecurrence(string $recurrenceId): object + { + $url = Iugu::getBaseURI() . '/automatic_pix/receiver_recurrences/' . $recurrenceId . '/cancel'; + + try { + $response = (new Iugu_APIRequest())->request('PUT', $url); + } catch (\IuguRequestException | IuguObjectNotFound $e) { + if (str_contains($e->getMessage(), '502 Bad Gateway')) { + throw new GatewayNotAvailableException($e->getMessage()); + } else { + throw new GatewayException($e->getMessage()); + } + } catch (\IuguAuthenticationException $e) { + throw new GatewayNotAvailableException($e->getMessage()); + } catch (\Exception $e) { + throw new GatewayException("Error cancelling automatic pix recurrence: {$e->getMessage()}"); + } + + if (!empty($response->errors)) { + throw new GatewayException('Error cancelling automatic pix recurrence', (array) $response->errors); + } + + return $response; + } + /** * @inheritDoc */ diff --git a/src/MultiPayment.php b/src/MultiPayment.php index 6ee3686..b6b7caa 100644 --- a/src/MultiPayment.php +++ b/src/MultiPayment.php @@ -12,6 +12,7 @@ use Potelo\MultiPayment\Builders\CustomerBuilder; use Potelo\MultiPayment\Builders\CreditCardBuilder; use Potelo\MultiPayment\Exceptions\GatewayException; +use Potelo\MultiPayment\Contracts\AutomaticPixContract; use Potelo\MultiPayment\Helpers\ConfigurationHelper; use Potelo\MultiPayment\Exceptions\GatewayNotAvailableException; use Potelo\MultiPayment\Exceptions\ModelAttributeValidationException; @@ -267,4 +268,22 @@ public function setDefaultCard(string $customerId, string $creditCardId): Custom return $customer->setDefaultCard($creditCardId); } + /** + * Cancela uma recorrência de Pix Automático no gateway. + * + * @param string $recurrenceId UUID da recorrência (receiver_recurrence_id). + * @return object + * @throws MultiPaymentException + * @throws GatewayException + * @throws GatewayNotAvailableException + */ + public function cancelAutomaticPixRecurrence(string $recurrenceId): object + { + if (!$this->gateway instanceof AutomaticPixContract) { + throw new MultiPaymentException('The selected gateway does not support automatic pix.'); + } + + return $this->gateway->cancelAutomaticPixRecurrence($recurrenceId); + } + } From 227662bada817a2068261a57de67bbb2685f71ce Mon Sep 17 00:00:00 2001 From: Gabriel Peixoto Date: Sat, 20 Jun 2026 13:17:25 -0300 Subject: [PATCH 2/2] feat: Normaliza objetos --- src/Exceptions/GatewayException.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Exceptions/GatewayException.php b/src/Exceptions/GatewayException.php index f8455c7..7934a98 100644 --- a/src/Exceptions/GatewayException.php +++ b/src/Exceptions/GatewayException.php @@ -86,6 +86,13 @@ private function flattenErrors(array $array, array &$messages, string $prefix = // Constrói a chave completa para o item atual $newKey = $prefix ? "{$prefix}.{$key}" : $key; + // Normaliza objetos (ex.: stdClass aninhado vindo da Iugu) para array + // antes de prosseguir, evitando "Object of class stdClass could not be + // converted to string" ao tentar interpolar o valor. + if (is_object($value)) { + $value = (array) $value; + } + if (is_array($value) && !empty($value)) { // Se o valor for um array não vazio, continua a recursão $this->flattenErrors($value, $messages, $newKey);