Skip to content
14 changes: 14 additions & 0 deletions src/Contracts/CreditCardContract.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,18 @@ interface CreditCardContract
* @throws GatewayException|GatewayNotAvailableException
*/
public function createCreditCard(CreditCard $creditCard): CreditCard;

/**
* Get a credit card by its ID
*
* @throws GatewayException|GatewayNotAvailableException
*/
public function getCreditCard(CreditCard $creditCard): CreditCard;

/**
* Delete a credit card
*
* @throws GatewayException|GatewayNotAvailableException
*/
public function deleteCreditCard(CreditCard $creditCard): void;
}
17 changes: 13 additions & 4 deletions src/Contracts/CustomerContract.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ public function createCustomer(Customer $customer): Customer;
/**
* Return one customer based on the customer ID
*
* @param string $id
*
* @param \Potelo\MultiPayment\Models\Customer $customer
* @return Customer
* @throws GatewayException|GatewayNotAvailableException
* @throws \Potelo\MultiPayment\Exceptions\GatewayException
* @throws \Potelo\MultiPayment\Exceptions\GatewayNotAvailableException
*/
public function getCustomer(string $id): Customer;
public function getCustomer(Customer $customer): Customer;

/**
* Update an existing customer
Expand All @@ -40,4 +40,13 @@ public function getCustomer(string $id): Customer;
* @throws GatewayException|GatewayNotAvailableException
*/
public function updateCustomer(Customer $customer): Customer;

/**
* Set the customer's default card
*
* @param \Potelo\MultiPayment\Models\Customer $customer
* @param string $cardId
* @return \Potelo\MultiPayment\Models\Customer
*/
public function setCustomerDefaultCard(Customer $customer, string $cardId): Customer;
}
10 changes: 5 additions & 5 deletions src/Contracts/InvoiceContract.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ public function createInvoice(Invoice $invoice): Invoice;

/**
* Return one invoice based on the invoice ID
*
* @param string $id
*
*
* @param \Potelo\MultiPayment\Models\Invoice $invoice
* @return Invoice
* @throws GatewayException|GatewayNotAvailableException
* @throws \Potelo\MultiPayment\Exceptions\GatewayException
* @throws \Potelo\MultiPayment\Exceptions\GatewayNotAvailableException
*/
public function getInvoice(string $id): Invoice;
public function getInvoice(Invoice $invoice): Invoice;

/**
* Refund an invoice
Expand Down
8 changes: 7 additions & 1 deletion src/Exceptions/GatewayException.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,13 @@ class GatewayException extends MultiPaymentException
public function __construct(string $message = "", $errors = null)
{
$this->errors = $errors;
parent::__construct($message . ' - ' . $this->parseErrorsToString($errors));
$appends = $this->parseErrorsToString($errors);

if (!empty($appends)) {
$message .= ' - ' . $appends;
}

parent::__construct($message);
}

/**
Expand Down
4 changes: 4 additions & 0 deletions src/Facades/MultiPayment.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Potelo\MultiPayment\Facades;

use Illuminate\Support\Facades\Facade;
use Potelo\MultiPayment\Models\CreditCard;
use Potelo\MultiPayment\Models\Invoice;
use Potelo\MultiPayment\Builders\InvoiceBuilder;
use Potelo\MultiPayment\Builders\CustomerBuilder;
Expand All @@ -14,8 +15,11 @@
* @method static InvoiceBuilder newInvoice()
* @method static CustomerBuilder newCustomer()
* @method static CreditCardBuilder newCreditCard()
* @method static CreditCard getCard(string $customerId, string $creditCardId)
* @method static void deleteCard(string $customerId, string $creditCardId)
* @method static \Potelo\MultiPayment\MultiPayment setGateway($gateway)
* @method static Invoice chargeInvoiceWithCreditCard($invoice, ?string $creditCardToken = null, ?string $creditCardId = null)
* @method static \Potelo\MultiPayment\Models\Customer setDefaultCard(string $customerId, string $creditCardId)
*/
class MultiPayment extends Facade
{
Expand Down
124 changes: 104 additions & 20 deletions src/Gateways/IuguGateway.php
Original file line number Diff line number Diff line change
Expand Up @@ -278,29 +278,16 @@ public function createCreditCard(CreditCard $creditCard): CreditCard
throw new GatewayException('Error creating creditCard: ', $iuguCreditCard->errors);
}

$creditCard->id = $iuguCreditCard->id ?? null;
$creditCard->brand = $iuguCreditCard->data->brand ?? null;
$creditCard->year = $iuguCreditCard->data->year ?? null;
$creditCard->month = $iuguCreditCard->data->month ?? null;
if (!empty($iuguCreditCard->data->holder_name)) {
$names = explode(' ', $iuguCreditCard->data->holder_name);
$creditCard->firstName = $names[0] ?? null;
$creditCard->lastName = $names[array_key_last($names)] ?? null;
}
$creditCard->lastDigits = $iuguCreditCard->data->last_digits ?? substr($iuguCreditCard->data->display_number, -4);
$creditCard->gateway = 'iugu';
$creditCard->original = $iuguCreditCard;
$creditCard->createdAt = new Carbon($iuguCreditCard->created_at_iso) ?? null;
return $creditCard;
return $this->parseIuguCard($iuguCreditCard, $creditCard);
}

/**
* @inheritDoc
*/
public function getInvoice(string $id): Invoice
public function getInvoice(Invoice $invoice): Invoice
{
try {
$iuguInvoice = \Iugu_Invoice::fetch($id);
$iuguInvoice = \Iugu_Invoice::fetch($invoice->id);
} catch (\IuguRequestException | IuguObjectNotFound $e) {
if (str_contains($e->getMessage(), '502 Bad Gateway')) {
throw new GatewayNotAvailableException($e->getMessage());
Expand All @@ -314,7 +301,7 @@ public function getInvoice(string $id): Invoice
throw new GatewayException('Error getting invoice', $iuguInvoice->errors);
}

return $this->parseInvoice($iuguInvoice);
return $this->parseInvoice($iuguInvoice, $invoice);
}

/**
Expand Down Expand Up @@ -587,10 +574,13 @@ private function chargeIuguInvoice(array $iuguInvoiceData)
return $iuguCharge->invoice();
}

public function getCustomer(string $id): Customer
/**
* @inheritDoc
*/
public function getCustomer(Customer $customer): Customer
{
try {
$iuguCustomer = Iugu_Customer::fetch($id);
$iuguCustomer = Iugu_Customer::fetch($customer->id);
} catch (\IuguRequestException | IuguObjectNotFound $e) {
if (str_contains($e->getMessage(), '502 Bad Gateway')) {
throw new GatewayNotAvailableException($e->getMessage());
Expand All @@ -605,7 +595,7 @@ public function getCustomer(string $id): Customer
throw new GatewayException('Error getting customer', $iuguCustomer->errors);
}

return $this->parseCustomer($iuguCustomer);
return $this->parseCustomer($iuguCustomer, $customer);
}

public function updateCustomer(Customer $customer): Customer
Expand Down Expand Up @@ -747,6 +737,100 @@ private function customerToIuguData(Customer $customer): array
}
}

if (!empty($customer->defaultCard) && !empty($customer->defaultCard->id)) {
$iuguCustomerData['default_payment_method_id'] = $customer->defaultCard->id;
}

return $iuguCustomerData;
}

/**
* @inheritDoc
*/
public function setCustomerDefaultCard(Customer $customer, string $cardId): Customer
{
$customer->defaultCard = new CreditCard();
$customer->defaultCard->id = $cardId;

return $this->updateCustomer($customer);
}

/**
* @inheritDoc
*/
public function deleteCreditCard(CreditCard $creditCard): void
{
try {
$iuguCreditCard = new Iugu_PaymentMethod([
'id' => $creditCard->id,
'customer_id' => $creditCard->customer->id
]);
$iuguCreditCard->delete();
} 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($e->getMessage());
}
}

/**
* @inheritDoc
*/
public function getCreditCard(CreditCard $creditCard): CreditCard
{
try {
$iuguCustomer = new Iugu_Customer(['id' => $creditCard->customer->id]);
$iuguCreditCard = $iuguCustomer->payment_methods()->fetch($creditCard->id);
} 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($e->getMessage());
}
if ($iuguCreditCard->errors) {
throw new GatewayException('Error getting creditCard: ', $iuguCreditCard->errors);
}

return $this->parseIuguCard($iuguCreditCard, $creditCard);
}

/**
* @param mixed $iuguCreditCard
* @param \Potelo\MultiPayment\Models\CreditCard|null $creditCard
* @return \Potelo\MultiPayment\Models\CreditCard
*/
private function parseIuguCard(mixed $iuguCreditCard, ?CreditCard $creditCard = null): CreditCard
{
if (is_null($creditCard)) {
$creditCard = new CreditCard();
}

$creditCard->id = $iuguCreditCard->id ?? null;
$creditCard->brand = $iuguCreditCard->data->brand ?? null;
$creditCard->year = $iuguCreditCard->data->year ?? null;
$creditCard->month = $iuguCreditCard->data->month ?? null;
$creditCard->description = $iuguCreditCard->description ?? null;

if (!empty($iuguCreditCard->data->holder_name)) {
$names = explode(' ', $iuguCreditCard->data->holder_name);
$creditCard->firstName = $names[0] ?? null;
$creditCard->lastName = $names[array_key_last($names)] ?? null;
}
$creditCard->lastDigits = $iuguCreditCard->data->last_digits ?? substr($iuguCreditCard->data->display_number, -4);
$creditCard->gateway = 'iugu';
$creditCard->original = $iuguCreditCard;
$creditCard->createdAt = new Carbon($iuguCreditCard->created_at_iso) ?? null;
return $creditCard;
}
}
49 changes: 49 additions & 0 deletions src/Models/Customer.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
namespace Potelo\MultiPayment\Models;

use Carbon\Carbon;
use Potelo\MultiPayment\Contracts\GatewayContract;
use Potelo\MultiPayment\Exceptions\ModelAttributeValidationException;
use Potelo\MultiPayment\Helpers\ConfigurationHelper;

/**
* Class Customer
Expand Down Expand Up @@ -167,4 +169,51 @@ public function toArray(): array
}
return $array;
}

public function setDefaultCard(string $cardId): Customer
{
$gateway = ConfigurationHelper::resolveGateway($this->gateway);
return $gateway->setCustomerDefaultCard($this, $cardId);
}

/**
* Get a customer credit card by id from the gateway.
*
* @param string $creditCardId
* @param string|GatewayContract|null $gateway
*
* @return static
* @throws \Potelo\MultiPayment\Exceptions\ConfigurationException
* @throws \Potelo\MultiPayment\Exceptions\GatewayException
* @throws \Potelo\MultiPayment\Exceptions\GatewayNotAvailableException
*/
public function getCreditCard(string $creditCardId, GatewayContract|string $gateway = null): CreditCard
{
$gateway = ConfigurationHelper::resolveGateway($gateway);
$creditCard = new CreditCard();
$creditCard->customer = $this;
$creditCard->id = $creditCardId;

return $gateway->getCreditCard($creditCard);
}

/**
* Delete a customer credit card by id from the gateway.
*
* @param string $creditCardId
* @param \Potelo\MultiPayment\Contracts\GatewayContract|string|null $gateway
* @return void
* @throws \Potelo\MultiPayment\Exceptions\ConfigurationException
* @throws \Potelo\MultiPayment\Exceptions\GatewayException
* @throws \Potelo\MultiPayment\Exceptions\GatewayNotAvailableException
*/
public function deleteCreditCard(string $creditCardId, GatewayContract|string $gateway = null): void
{
$gateway = ConfigurationHelper::resolveGateway($gateway);
$creditCard = new CreditCard();
$creditCard->customer = $this;
$creditCard->id = $creditCardId;

$gateway->deleteCreditCard($creditCard);
}
}
31 changes: 29 additions & 2 deletions src/Models/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -161,13 +161,40 @@ protected static function getClassName(): string
* @throws \Potelo\MultiPayment\Exceptions\ConfigurationException
* @throws \Potelo\MultiPayment\Exceptions\GatewayException
*/
public static function get(string $id, GatewayContract|string $gateway = null): static
public function get(GatewayContract|string $gateway = null): static
{
$method = 'get' . static::getClassName();
$gateway = ConfigurationHelper::resolveGateway($gateway);
if (!method_exists($gateway, $method)) {
throw GatewayException::methodNotFound(get_class($gateway), $method);
}
return $gateway->$method($id);
return $gateway->$method($this);
}

/**
* Delete the model instance by id in the gateway.
*
* @param \Potelo\MultiPayment\Contracts\GatewayContract|string|null $gateway
* @return void
* @throws \Potelo\MultiPayment\Exceptions\ConfigurationException
* @throws \Potelo\MultiPayment\Exceptions\GatewayException
*/
public function delete(GatewayContract|string $gateway = null): void
{
$method = 'delete' . static::getClassName();
$gateway = ConfigurationHelper::resolveGateway($gateway);
if (!method_exists($gateway, $method)) {
throw GatewayException::methodNotFound(get_class($gateway), $method);
}
$gateway->$method($this);
}

/**
* Refresh the model instance with the latest data from the gateway.
*/
public function refresh(GatewayContract|string $gateway = null): static
{
$gateway = ConfigurationHelper::resolveGateway($gateway);
return $this->get($gateway);
}
}
Loading