├── .docker └── php │ └── Dockerfile ├── .github ├── CODE_OF_CONDUCT.md ├── FUNDING.yml ├── SECURITY.md └── SUPPORT.md ├── .gitignore ├── .husky ├── commit-msg ├── pre-commit └── pre-push ├── .vscode └── settings.json ├── CONTRIBUTING.md ├── LICENSE.md ├── Makefile ├── README.md ├── composer.json ├── composer.lock ├── docker-compose.yml ├── examples ├── asaas │ ├── charges.php │ ├── credentials.example.php │ ├── customers.php │ ├── pix.php │ ├── subscriptions.php │ └── webhook.php ├── efi │ ├── charges.php │ └── credentials.example.php └── helper │ ├── termwind-cli.php │ └── termwind.php ├── package-lock.json ├── package.json ├── phpstan.neon ├── phpunit.xml ├── pint.json ├── src ├── Contracts │ └── GatewayInterface.php ├── Exceptions │ └── AsaasExceptions.php ├── Gateways │ ├── Asaas │ │ ├── AsaasGateway.php │ │ ├── Enums │ │ │ ├── BillingTypeEnum.php │ │ │ ├── InvoiceFiltersEnum.php │ │ │ ├── InvoiceStatusEnum.php │ │ │ └── InvoiceStatusFiscalDocumentEnum.php │ │ ├── Interface │ │ │ └── AsaasGatewayInterface.php │ │ ├── Requests │ │ │ ├── AsaasChargeRequest.php │ │ │ ├── AsaasCustomerRequest.php │ │ │ └── AsaasPixRequest.php │ │ ├── Resources │ │ │ ├── Charge │ │ │ │ ├── Charge.php │ │ │ │ ├── Enum │ │ │ │ │ └── WebhookEventsEnum.php │ │ │ │ └── Interface │ │ │ │ │ └── ChargeInterface.php │ │ │ ├── Customer │ │ │ │ ├── Customer.php │ │ │ │ └── Interface │ │ │ │ │ └── CustomerInterface.php │ │ │ ├── Pix │ │ │ │ ├── Interface │ │ │ │ │ └── PixInterface.php │ │ │ │ └── Pix.php │ │ │ ├── Subscription │ │ │ │ ├── Interface │ │ │ │ │ └── SubscriptionInterface.php │ │ │ │ ├── Requests │ │ │ │ │ └── StoreSubscriptionAsaasRequest.php │ │ │ │ └── Subscription.php │ │ │ └── Webhook │ │ │ │ ├── Interface │ │ │ │ └── WebhookInterface.php │ │ │ │ └── Webhook.php │ │ └── Traits │ │ │ └── HasAsaasClient.php │ └── Efi │ │ ├── EfiGateway.php │ │ ├── Interface │ │ └── EfiGatewayInterface.php │ │ ├── Resources │ │ ├── Authorization │ │ │ ├── Authorization.php │ │ │ └── Interface │ │ │ │ └── AuthorizationInterface.php │ │ └── Charge │ │ │ ├── Charge.php │ │ │ └── Interface │ │ │ └── ChargeInterface.php │ │ └── Traits │ │ └── HasEfiClient.php └── PHPay.php └── tests ├── AsaasGatewayTest.php ├── EfiGatewayTest.php ├── PHPayTest.php ├── Pest.php └── TestCase.php /.docker/php/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:8.2-cli-alpine 2 | 3 | RUN apk add --no-cache \ 4 | curl \ 5 | bash \ 6 | nodejs \ 7 | npm 8 | 9 | COPY --from=composer /usr/bin/composer /usr/bin/composer 10 | RUN composer self-update 11 | 12 | 13 | WORKDIR /usr/src/app 14 | COPY . . 15 | 16 | RUN composer install --prefer-dist -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Código de Conduta 2 | 3 | ## Nossa Promessa 4 | 5 | Como membros, colaboradores e líderes deste projeto, nos comprometemos a criar uma comunidade aberta, acolhedora e respeitosa para todos, independentemente de idade, tamanho corporal, deficiência, etnia, características sexuais, identidade e expressão de gênero, nível de experiência, educação, status socioeconômico, nacionalidade, aparência pessoal, raça, religião ou identidade e orientação sexual. 6 | 7 | Prometemos agir e interagir de maneiras que contribuam para um ambiente aberto, acolhedor, diversificado, inclusivo e saudável. 8 | 9 | ## Nossos Padrões 10 | 11 | Exemplos de comportamento que contribuem para um ambiente positivo incluem: 12 | 13 | - Demonstrar empatia e bondade com os outros. 14 | - Respeitar opiniões, pontos de vista e experiências diferentes. 15 | - Aceitar críticas construtivas de maneira educada. 16 | - Assumir responsabilidade e pedir desculpas aos afetados por nossos erros. 17 | - Focar no que é melhor não apenas para nós individualmente, mas para toda a comunidade. 18 | 19 | Comportamentos inaceitáveis incluem: 20 | 21 | - Uso de linguagem ou imagens sexualizadas e atenção ou avanços indesejados. 22 | - Comentários insultuosos, depreciativos ou ataques pessoais ou políticos. 23 | - Assédio público ou privado. 24 | - Outras condutas que possam razoavelmente ser consideradas inapropriadas em um ambiente profissional. 25 | 26 | ## Aplicação do Código de Conduta 27 | 28 | Casos de comportamento abusivo, assediador ou inaceitável podem ser relatados à equipe responsável em fale@phpay.io. Todas as queixas serão analisadas e investigadas com imparcialidade e respeito pela privacidade. 29 | 30 | Os mantenedores do projeto que não seguirem ou aplicarem o Código de Conduta podem enfrentar repercussões temporárias ou permanentes conforme determinado pelos outros membros da liderança do projeto. 31 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [mariolucasdev] 4 | -------------------------------------------------------------------------------- /.github/SECURITY.md: -------------------------------------------------------------------------------- 1 | # Política de Segurança 2 | 3 | Agradecemos seu interesse em manter este projeto seguro para todos! Esta página fornece informações sobre como relatar vulnerabilidades de segurança. 4 | 5 | ## Relatando Vulnerabilidades 6 | 7 | Se você encontrar uma vulnerabilidade de segurança, siga estas etapas: 8 | 9 | 1. **Não abra uma issue pública**: 10 | 11 | - Para proteger os usuários, não relate vulnerabilidades em issues públicas ou em discussões abertas do repositório. 12 | 13 | 2. **Envie um relatório privado**: 14 | 15 | - Entre em contato diretamente pelo e-mail: [sec@phpay.io](mailto:sec@phpay.io). 16 | - Inclua detalhes suficientes para que possamos entender e reproduzir o problema, como: 17 | - Descrição da vulnerabilidade. 18 | - Passos para reproduzi-la (se aplicável). 19 | - Impacto potencial. 20 | 21 | 3. **Nossa resposta**: 22 | - Confirmaremos o recebimento do relatório em até **48 horas úteis**. 23 | - Investigaremos e forneceremos uma atualização inicial sobre o progresso da resolução em até **5 dias úteis**. 24 | - Trabalhamos para corrigir todas as vulnerabilidades confirmadas o mais rápido possível. 25 | 26 | ## Política de Divulgação 27 | 28 | Após resolvermos a vulnerabilidade, poderemos divulgar as informações publicamente em um prazo combinado com o responsável pelo relatório, para garantir que os usuários possam atualizar e proteger seus sistemas. 29 | 30 | ## Agradecimentos 31 | 32 | Valorizamos a contribuição da comunidade para manter este projeto seguro. Se você relatar uma vulnerabilidade válida, ficaremos felizes em reconhecer sua ajuda (se desejar) na seção de agradecimentos do projeto. 33 | -------------------------------------------------------------------------------- /.github/SUPPORT.md: -------------------------------------------------------------------------------- 1 | # Suporte 2 | 3 | Obrigado por usar nosso projeto! Estamos aqui para ajudá-lo(a). 4 | 5 | ## Como Obter Suporte 6 | 7 | Se você encontrar problemas, dúvidas ou precisa de ajuda, siga estas etapas: 8 | 9 | 1. **Consulte a documentação**: 10 | 11 | - Leia o [README.md](./README.md) do repositório para instruções de uso e soluções comuns. 12 | 13 | 2. **Pesquise nas issues**: 14 | 15 | - Verifique se sua dúvida já foi respondida em issues abertas ou fechadas. 16 | 17 | 3. **Abra uma nova issue**: 18 | 19 | - Se não encontrar resposta, crie uma nova issue descrevendo o problema de forma clara e detalhada. 20 | 21 | 4. **Entre em contato diretamente** (para questões críticas ou vulnerabilidades de segurança): 22 | - Email: fale@phpay.io 23 | 24 | ## Política de Resposta 25 | 26 | Tentamos responder às issues dentro de **48 horas úteis** e fornecemos atualizações contínuas até que o problema seja resolvido. 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | node_modules/ 3 | examples/asaas/credentials.php 4 | examples/efi/credentials.php 5 | .idea/ -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | KN='\033[0m' 4 | BBlue='\033[1;34m' 5 | BRed='\033[1;31m' 6 | 7 | REGEX_ISSUE_ID="[0-9]+" 8 | 9 | BRANCH_NAME=$(git symbolic-ref --short HEAD) 10 | ISSUE_ID=$(echo "$BRANCH_NAME" | grep -o -E "$REGEX_ISSUE_ID") 11 | COMMIT_MESSAGE=$(cat "$1") 12 | 13 | if [ -z "$ISSUE_ID" ]; then 14 | php examples/helper/termwind-cli.php error "${BRed} Branch name does not follow the expected pattern...${KN}" 15 | 16 | exit 1 17 | fi 18 | 19 | case "$COMMIT_MESSAGE" in 20 | "$ISSUE_ID"*) 21 | exit 0 22 | ;; 23 | esac 24 | 25 | php examples/helper/termwind-cli.php success "PHPAY-$ISSUE_ID: $COMMIT_MESSAGE" 26 | 27 | echo "PHPAY-$ISSUE_ID: $COMMIT_MESSAGE" > "$1" 28 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | pint_output=$(vendor/bin/pint --test -v 2>&1) 2 | 3 | if [ $? -ne 0 ]; then 4 | php examples/helper/termwind-cli.php error "Pint tests failed." "$pint_output" 5 | 6 | exit 1 7 | fi 8 | 9 | php examples/helper/termwind-cli.php success "Pint Ok!" 10 | 11 | phpstan=$(vendor/bin/phpstan analyse --level=7 2>&1) 12 | 13 | if [ $? -ne 0 ]; then 14 | php examples/helper/termwind-cli.php error "PHPStan tests failed." "$phpstan" 15 | exit 1 16 | fi 17 | 18 | php examples/helper/termwind-cli.php success "PHPStan Ok!" 19 | 20 | exit 0 -------------------------------------------------------------------------------- /.husky/pre-push: -------------------------------------------------------------------------------- 1 | pest_output=$(./vendor/bin/pest --colors=always --stop-on-failure 2>&1) 2 | 3 | if [ $? -ne 0 ]; then 4 | php examples/helper/termwind-cli.php error "Pest tests failed." "$pest_output" 5 | 6 | exit 1 7 | fi 8 | 9 | php examples/helper/termwind-cli.php success "Pest Ok!" 10 | 11 | exit 0 -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.enabled": false, 3 | "editor.lineHeight": 2.4, 4 | // "editor.fontFamily": "JetBrains Mono", 5 | // "editor.fontFamily": "Dank Mono", 6 | // "editor.codeLensFontFamily": "Operator Mono", 7 | "editor.fontLigatures": true, 8 | "editor.formatOnSave": true, 9 | "php-cs-fixer.onsave": true, 10 | "php-cs-fixer.executablePath": "${extensionPath}/php-cs-fixer.phar", 11 | "cSpell.userWords": [ 12 | "Assertable", 13 | "autoload", 14 | "Bootstrapper", 15 | "bootstrappers", 16 | "Codeigniter", 17 | "Dispatchable", 18 | "flashdata", 19 | "intelephense", 20 | "junstyle", 21 | "Laravel", 22 | "Livewire", 23 | "onsave", 24 | "phar", 25 | "phpstan", 26 | "Queueable", 27 | "Stancl", 28 | "timesheet", 29 | "userdata" 30 | ], 31 | "php-cs-fixer.lastDownload": 1693233566761, 32 | "terminal.integrated.cursorStyle": "underline", 33 | "terminal.integrated.defaultProfile.windows": "Git Bash", 34 | "terminal.integrated.fontFamily": "Hack Nerd Font Mono", 35 | "terminal.integrated.lineHeight": 1.2, 36 | "editor.accessibilitySupport": "off", 37 | "terminal.integrated.copyOnSelection": true, 38 | "terminal.integrated.sendKeybindingsToShell": true, 39 | "redhat.telemetry.enabled": true, 40 | "editor.minimap.enabled": false, 41 | "editor.tabSize": 4, 42 | "editor.insertSpaces": true, 43 | "editor.detectIndentation": false, 44 | "github.copilot.enable": { 45 | "*": true, 46 | "plaintext": true, 47 | "markdown": false, 48 | "scminput": false 49 | }, 50 | "editor.inlineSuggest.enabled": true, 51 | "explorer.confirmDragAndDrop": false, 52 | "[javascript]": { 53 | "editor.defaultFormatter": "esbenp.prettier-vscode" 54 | }, 55 | "files.associations": { 56 | "*.js": "javascriptreact" 57 | }, 58 | "window.zoomLevel": 1, 59 | "editor.fontVariations": false, 60 | "phpunit.phpunit": "vendor/bin/pest", 61 | "jira-plugin.workingProject": "" 62 | } 63 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # PHPay - Manual de Contribuição 2 | 3 | Seja bem-vindo(a) à nossa área de contribuição para o projeto PHPay! Estamos felizes por você estar interessado(a) em colaborar com nosso projeto open source. Suas contribuições são extremamente importantes para o crescimento e evolução do PHPay. 4 | 5 | ## ❓ Como contribuir? 6 | 7 | 1. Antes de começar 8 | Leia a documentação: Familiarize-se com o código e os objetivos do projeto. 9 | Respeite o Código de Conduta: Certifique-se de seguir as diretrizes de comportamento, promovendo um ambiente colaborativo e inclusivo. 10 | Verifique as Issues: Dê uma olhada nas issues abertas para encontrar algo que você possa resolver ou melhorar. 11 | 2. Passo a passo para contribuir 12 | 🍴 Faça um fork do repositório 13 | 14 | No repositório do PHPay, clique no botão Fork no canto superior direito. 15 | 🎋 Clone o repositório para sua máquina local 16 | 17 | ```bash 18 | git clone https://github.com/seu-usuario/phppay.git 19 | cd phpay 20 | ``` 21 | 22 | 🎋 Crie uma branch para sua contribuição 23 | 24 | Use um nome descritivo para a branch que reflete a feature ou correção que você está implementando: 25 | 26 | ```bash 27 | git checkout -b feature/nome-da-feature 28 | ``` 29 | 30 | 🗒️ Implemente sua contribuição 31 | 32 | Mantenha o código limpo e organizado. 33 | Siga as convenções de código do projeto. 34 | Escreva testes para validar suas alterações sempre que possível. 35 | 36 | 🗒️ Faça commit das suas alterações 37 | 38 | Escreva mensagens de commit claras e descritivas: 39 | 40 | ```bash 41 | git commit -m "feat: [descrição da feature]" 42 | ``` 43 | 44 | ✏️ Envie suas alterações para o repositório do fork 45 | 46 | ```bash 47 | git push origin feature/nome-da-feature 48 | ``` 49 | 50 | ✈️ Abra um Pull Request 51 | 52 | No repositório original do PHPay, clique em Pull Requests e, em seguida, clique em New Pull Request. 53 | Escolha a branch que você criou no seu fork e compare-a com a branch principal do repositório original. 54 | Adicione uma descrição detalhada do que sua contribuição resolve ou melhora. 55 | 56 | ## 3. Revisão e Feedback 57 | 58 | Sua contribuição será revisada por um dos mantenedores do projeto. 59 | Caso necessário, serão solicitadas alterações ou melhorias antes da aprovação. 60 | Após a aprovação, sua contribuição será integrada ao projeto principal. 61 | 62 | 🎉Diretrizes de Contribuição 63 | 64 | - Certifique-se de que seu código seja compatível com as versões do PHP suportadas pelo projeto. 65 | 66 | - Escreva testes unitários para novas funcionalidades ou correções de bugs. 67 | 68 | - Mantenha uma boa documentação do código, incluindo comentários e exemplos de uso. 69 | 70 | - Evite commits grandes e difíceis de revisar. 71 | 72 | - Divida suas alterações em partes menores e mais específicas. 73 | 74 | ## 💻 Ambiente de Desenvolvimento 75 | 76 | Certifique-se de configurar corretamente o ambiente de desenvolvimento local: 77 | 78 | Requisitos básicos: 79 | 80 | - PHP ^8.1 81 | - Composer. 82 | 83 | ## 🏗️ Instalando as dependências: 84 | 85 | ```bash 86 | composer install 87 | ``` 88 | 89 | ## 🖥️ Configuração do ambiente: 90 | 91 | Renomeie o arquivo credentials.example.php para credentials.php e configure suas chaves de do seu gateways. 92 | 93 | ## Rodando os testes: 94 | 95 | ```bash 96 | composer tests 97 | ``` 98 | 99 | ## ✉️ Entre em contato 100 | 101 | Caso tenha dúvidas ou precise de ajuda, sinta-se à vontade para abrir uma issue ou entrar em contato com a equipe de mantenedores. 102 | 103 | Agradecemos desde já por suas contribuições. 💙 104 | Juntos podemos tornar o PHPay ainda melhor! 105 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # Licença MIT 2 | 3 | Copyright (c) 2024 PHPay | Mário Lucas 4 | 5 | A permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma cópia deste software e dos arquivos de documentação associados (o "Software"), para lidar com o Software sem restrição, incluindo, sem limitação, os direitos de usar, copiar, modificar, mesclar, publicar, distribuir, sublicenciar e/ou vender cópias do Software, e permitir que as pessoas a quem o Software é fornecido o façam, sujeito às seguintes condições: 6 | 7 | O aviso de copyright acima e este aviso de permissão devem ser incluídos em todas as cópias ou partes substanciais do Software. 8 | 9 | O SOFTWARE É FORNECIDO "COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO ÀS GARANTIAS DE COMERCIALIZAÇÃO, ADEQUAÇÃO A UM PROPÓSITO ESPECÍFICO E NÃO INFRAÇÃO. EM NENHUM CASO OS AUTORES OU DETENTORES DE DIREITOS AUTORAIS SERÃO RESPONSÁVEIS POR QUALQUER RECLAMAÇÃO, DANO OU OUTRA RESPONSABILIDADE, SEJA EM UMA AÇÃO DE CONTRATO, DELITO OU DE OUTRA FORMA, DECORRENTE DE OU EM CONEXÃO COM O SOFTWARE OU O USO OU OUTRAS NEGOCIAÇÕES NO SOFTWARE. 10 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | DEFAULT_GOAL := help 2 | help: 3 | @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z0-9_-]+:.*?##/ { printf " \033[36m%-40s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) 4 | 5 | ##@ [Docker] 6 | start: ## Spin up the container 7 | docker compose up -d 8 | 9 | stop: ## Shutdown the containers 10 | docker compose down 11 | 12 | build: ## Build all docker images 13 | docker compose build 14 | 15 | ##@ [Application] 16 | composer: ## Run composer commands. Specify the command e.g. via "make composer ARGS="install|update|require " 17 | docker compose run --rm app composer $(ARGS) 18 | 19 | install: 20 | docker compose run --rm app composer install 21 | 22 | lint: ## Run the Linter 23 | docker compose run --rm app composer lint 24 | 25 | test-lint: ## Run the Linter Test 26 | docker compose run --rm app composer test:lint 27 | 28 | test-types: ## Run the PHPStan analysis 29 | docker compose run --rm app composer test:types 30 | 31 | test-unit: ## Run the Pest Test Suite 32 | docker compose run --rm app composer test:unit 33 | 34 | test: ## Run the tests. Apply arguments via make test ARGS="--init" 35 | docker compose run --rm app composer test 36 | 37 | ##@ [Gateway Asaas] 38 | asaas: ## Run resource asaas. Apply arguments via make asaas ARGS="charge|customer|pix|webhook" 39 | @docker compose exec -it app php examples/asaas/$(resource).php -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![capa-redes](https://github.com/user-attachments/assets/20051d3a-ecbf-4d01-8c29-50c43b8d3af4) 2 | 3 |

4 | Stable Version 5 | Php Version 6 | Total Downloads 7 |

8 | 9 | O PHPay é uma biblioteca PHP que tem o objetivo tornar o trabalho de integrações com gateways de pagamento mais simples e descomplicadas, facilitando a conexão entre tecnologia e negócios em produtos de software. 10 | 11 | ## 💸 Gateways 12 | 13 | - Asaas (cobranças, gestão de clientes e webhooks) 14 | - Efí (cobranças) 15 | 16 | ## 📦 Instalação 17 | 18 | Instale via Composer: 19 | 20 | ```php 21 | composer require phpay-io/phpay 22 | ``` 23 | 24 | ## ⚙️ Como usar o PHPay? 25 | 26 | ```php 27 | /** 28 | * instance with gateway inject 29 | * @var AsaasGateway $phpay 30 | */ 31 | $phpay = (new PHPay(new AsaasGateway(TOKEN_ASAAS_SANDBOX))); 32 | ``` 33 | 34 | ### Cobranças 35 | 36 | ```php 37 | /** 38 | * instance with gateway inject and resource call 39 | * 40 | * @var Charge $phpay 41 | */ 42 | $phpay = (new PHPay(new AsaasGateway(TOKEN_ASAAS_SANDBOX)))->charge(); 43 | 44 | /** 45 | * create charge 46 | */ 47 | $phpay 48 | ->setCharge($charge) 49 | ->setCustomer($customer) 50 | ->create(); 51 | 52 | /** 53 | * find charge 54 | */ 55 | $phpay->find($chargeId); 56 | 57 | /** 58 | * get all charges 59 | */ 60 | $phpay->getAll(); 61 | 62 | /** 63 | * get all charges with filters 64 | */ 65 | $phpay 66 | ->setQueryParams(['limit' => 2]) 67 | ->getAll(); 68 | 69 | /** 70 | * update charge 71 | */ 72 | $phpay->update($chargeId, $data); 73 | 74 | /** 75 | * destroy charge 76 | */ 77 | $phpay->destroy($chargeId); 78 | 79 | /** 80 | * restore charge 81 | */ 82 | $phpay->restore($chargeId); 83 | 84 | /** 85 | * get status charge 86 | */ 87 | $phpay->getStatus($chargeId); 88 | 89 | /** 90 | * get digitable line charge 91 | */ 92 | $phpay->getDigitableLine($chargeId); 93 | 94 | /** 95 | * get qrcode charge 96 | */ 97 | $phpay->getQrCodePix($chargeId); 98 | 99 | /** 100 | * confirm receipt charge 101 | */ 102 | $phpay->confirmReceipt($chargeId, [ 103 | 'paymentDate' => date('Y-m-d'), 104 | 'value' => 100.00, 105 | 'notifyCustomer' => true, 106 | ]); 107 | 108 | /** 109 | * undo confirm receipt 110 | */ 111 | $phpay->undoConfirmReceipt($chargeId); 112 | 113 | ``` 114 | 115 | ### Assinaturas 116 | 117 | ```php 118 | /** 119 | * @var Subscription $phpay 120 | */ 121 | $phpay = PHPay::gateway(new AsaasGateway(TOKEN_ASAAS_SANDBOX))->subscription(); 122 | 123 | /** 124 | * create a new subscription 125 | */ 126 | $phpay->setCustomer($customer)->create([ 127 | 'billingType' => 'BOLETO', 128 | 'value' => 100, 129 | 'nextDueDate' => '2025-04-09', 130 | ]); 131 | ``` 132 | 133 | ## 📝 Roadmap 134 | 135 | - Definições de Arquitetura ✅ 136 | - Domínios ✅ 137 | - Documentação ✍️ 138 | - Site 🕛 139 | - Gateways ✍️ 140 | 141 | - Asaas. 142 | 143 | - Cobranças ✅ 144 | - Clientes ✅ 145 | - Webhook ✅ 146 | - Assinaturas ✍️ 147 | - Pix 🕥 148 | 149 | - Efí. 150 | 151 | - Autorização ✅ 152 | - Cobranças ✅ 153 | - Clientes 🕥 154 | - Webhook 🕥 155 | - Assinaturas ✍️ 156 | - Pix 🕥 157 | 158 | - Lançamento v1.0.0 🚀 159 | 160 | ## 🌟 Contribuindo 161 | 162 | Para contribuir com o PHPay, implementando melhorias e novos gateways de pagamento, 163 | leia nosso manual de contribuição. [MANUAL DE CONTRIBUIÇÃO PHPAY](./CONTRIBUTING.md) 164 | 165 | ## 📄 Licença 166 | 167 | Este projeto está licenciado sob a MIT License. Consulte o arquivo [LICENSE](./LICENSE.md) para mais detalhes. 168 | 169 | ## 🤝 Contato 170 | 171 | 💻 GitHub: [Mário Lucas](https://github.com/mariolucasdev) 172 | 173 | 📧 Email: fale@phpay.io 174 | 175 | 🎉 Comece a usar o PHPay e simplifique suas integrações com gateways de pagamento! 176 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "phpay-io/phpay", 3 | "type": "library", 4 | "funding": [ 5 | { 6 | "url": "https://github.com/sponsors/mariolucasdev", 7 | "type": "github" 8 | } 9 | ], 10 | "keywords": [ 11 | "efi", 12 | "asaas", 13 | "gateways de pagamento", 14 | "gateways", 15 | "sdk asaas", 16 | "sdk efi", 17 | "phpay" 18 | ], 19 | "license": "MIT", 20 | "autoload": { 21 | "psr-4": { 22 | "PHPay\\": "src/", 23 | "PHPay\\Asaas\\": "src/Gateways/Asaas/", 24 | "PHPay\\Efi\\": "src/Gateways/Efi/", 25 | "Efi\\": "src/Gateways/Efi/", 26 | "AsaasCustomer\\": "src/Gateways/Asaas/Resources/Customer/" 27 | } 28 | }, 29 | "authors": [ 30 | { 31 | "name": "Mário Lucas", 32 | "email": "mariolucasdev@gmail.com" 33 | } 34 | ], 35 | "config": { 36 | "allow-plugins": { 37 | "pestphp/pest-plugin": true 38 | } 39 | }, 40 | "require": { 41 | "php": "^8.1", 42 | "ext-curl": "*", 43 | "guzzlehttp/guzzle": "^7.0" 44 | }, 45 | "require-dev": { 46 | "pestphp/pest": "3.5", 47 | "laravel/pint": "^1.18", 48 | "phpstan/phpstan": "^2.0", 49 | "nunomaduro/termwind": "^2.3" 50 | }, 51 | "scripts": { 52 | "lint": "pint -v", 53 | "test:lint": "pint --test -v", 54 | "test:unit": "pest --colors=always", 55 | "test:types": "phpstan analyse --level=9", 56 | "test": [ 57 | "@test:lint", 58 | "@test:unit", 59 | "@test:types" 60 | ] 61 | } 62 | } -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | app: 3 | image: phpay-docker 4 | container_name: phpay-docker 5 | stdin_open: true 6 | tty: true 7 | build: 8 | context: . 9 | dockerfile: .docker/php/Dockerfile 10 | volumes: 11 | - .:/usr/src/app 12 | -------------------------------------------------------------------------------- /examples/asaas/charges.php: -------------------------------------------------------------------------------- 1 | charge(); 15 | 16 | /** 17 | * create charge 18 | */ 19 | $phpay 20 | ->setCharge($charge) 21 | ->setCustomer($customer) 22 | ->create(); 23 | 24 | /** 25 | * find charge 26 | */ 27 | $phpay->find($chargeId); 28 | 29 | /** 30 | * get all charges 31 | */ 32 | $phpay->getAll(); 33 | 34 | /** 35 | * get all charges with filters 36 | */ 37 | $phpay 38 | ->setQueryParams(['limit' => 2]) 39 | ->getAll(); 40 | 41 | /** 42 | * update charge 43 | */ 44 | $phpay->update($chargeId, $data); 45 | 46 | /** 47 | * destroy charge 48 | */ 49 | $phpay->destroy($chargeId); 50 | 51 | /** 52 | * restore charge 53 | */ 54 | $phpay->restore($chargeId); 55 | 56 | /** 57 | * get status charge 58 | */ 59 | $phpay->getStatus($chargeId); 60 | 61 | /** 62 | * get digitable line charge 63 | */ 64 | $phpay->getDigitableLine($chargeId); 65 | 66 | /** 67 | * get qrcode charge 68 | */ 69 | $phpay->getQrCodePix($chargeId); 70 | 71 | /** 72 | * confirm receipt charge 73 | */ 74 | $phpay->confirmReceipt($chargeId, [ 75 | 'paymentDate' => date('Y-m-d'), 76 | 'value' => 100.00, 77 | 'notifyCustomer' => true, 78 | ]); 79 | 80 | /** 81 | * undo confirm receipt 82 | */ 83 | $phpay->undoConfirmReceipt($chargeId); 84 | -------------------------------------------------------------------------------- /examples/asaas/credentials.example.php: -------------------------------------------------------------------------------- 1 | NAME, 12 | 'cpfCnpj' => CPF_CNPJ, 13 | ]; 14 | 15 | /** 16 | * initialize phpay 17 | * 18 | * @var AsaasGateway $phpay 19 | */ 20 | $phpay = PHPay::gateway(new AsaasGateway(TOKEN_ASAAS_SANDBOX)); 21 | 22 | /** 23 | * store asaas customer 24 | * 25 | * @param array $customer 26 | * @return array 27 | * @see available fields in https://docs.asaas.com/reference/criar-novo-cliente 28 | */ 29 | $customerCreated = $phpay 30 | ->customer($customer) 31 | ->create(); 32 | 33 | /** 34 | * list all clients without filters 35 | * 36 | * @return array customers 37 | */ 38 | $customers = $phpay 39 | ->customer() 40 | ->getAll(); 41 | 42 | /** 43 | * get customer with filter 44 | * 45 | * @see available fields in https://docs.asaas.com/reference/criar-novo-cliente 46 | * @return array customers 47 | */ 48 | $customersFiltred = $phpay 49 | ->customer() 50 | ->setFilter([ 51 | 'cpfCnpj' => $customerCreated['cpfCnpj'], 52 | ]) 53 | ->getAll(); 54 | 55 | /** 56 | * get customer by id 57 | * 58 | * @return array customer 59 | */ 60 | $customerById = $phpay 61 | ->customer() 62 | ->find($customerCreated['id']); 63 | 64 | /** 65 | * update customer 66 | * 67 | * @return array customer 68 | */ 69 | $customerUpdate = $phpay 70 | ->customer([ 71 | 'name' => 'Mário Lucas Updated', 72 | ]) 73 | ->update($customerCreated['id']); 74 | 75 | /** 76 | * delete cliente no asaas 77 | * 78 | * @return bool 79 | */ 80 | $customerDeleted = $phpay 81 | ->customer() 82 | ->destroy($customerCreated['id']); 83 | 84 | /** 85 | * restore customer deleted 86 | * 87 | * @return bool 88 | */ 89 | $customerIdRestored = $phpay 90 | ->customer() 91 | ->restore($customerCreated['id']); 92 | 93 | /** 94 | * customer notifications 95 | * 96 | * @return array notifications 97 | */ 98 | $notifications = $phpay 99 | ->customer() 100 | ->getNotifications($customerCreated['id']); 101 | -------------------------------------------------------------------------------- /examples/asaas/pix.php: -------------------------------------------------------------------------------- 1 | pix() 17 | ->createKey(); 18 | 19 | $phpay 20 | ->pix() 21 | ->find(ID_PIX_KEY); 22 | 23 | $phpay 24 | ->pix() 25 | ->getAll(); 26 | 27 | $phpay 28 | ->pix() 29 | ->destroy(ID_PIX_KEY); 30 | 31 | $phpay 32 | ->pix() 33 | ->staticQrCode($staticQrCodeParams); 34 | 35 | $phpay 36 | ->pix() 37 | ->destroyStaticQrCode($statiQrCodeId); 38 | -------------------------------------------------------------------------------- /examples/asaas/subscriptions.php: -------------------------------------------------------------------------------- 1 | NAME, 13 | 'cpfCnpj' => CPF_CNPJ, 14 | ]; 15 | 16 | $subscriptionId = 'sub_e3knxyfo6ffgb6kg'; 17 | 18 | /** 19 | * @var Subscription $phpay 20 | */ 21 | $phpay = PHPay::gateway(new AsaasGateway(TOKEN_ASAAS_SANDBOX))->subscription(); 22 | 23 | /* subscription store */ 24 | $phpay->setCustomer($customer) 25 | ->create([ 26 | 'billingType' => 'BOLETO', 27 | 'value' => 100, 28 | 'nextDueDate' => '2025-04-09', 29 | 'discount' => [ 30 | 'value' => 10, 31 | 'dueDateLimitDays' => 5, 32 | 'type' => 'FIXED', /* PERCENTAGE */ 33 | ], 34 | 'interest' => [ 35 | 'value' => 2, 36 | ], 37 | 'fine' => [ 38 | 'value' => 1, 39 | 'type' => 'FIXED', /* PERCENTAGE */ 40 | ], 41 | 'cycle' => 'MONTHLY', 42 | 'description' => 'Teste de assinatura', 43 | 'maxPayments' => 12, 44 | 'externalReference' => '123456', 45 | // 'split' => [ 46 | // [ 47 | // 'walletId' => 'rec_123456', 48 | // 'fixedValue' => 50, 49 | // 'percentageValue' => 50, 50 | // 'externalReference' => '123456', 51 | // 'description' => 'Teste de divisão', 52 | // ], 53 | // ], 54 | // 'callback' => [ 55 | // 'successUrl' => 'https://example.com/success', 56 | // 'autoRedirect' => true, 57 | // ] 58 | ]); 59 | 60 | print_r($subscriptionCreated); 61 | -------------------------------------------------------------------------------- /examples/asaas/webhook.php: -------------------------------------------------------------------------------- 1 | NAME, 12 | 'cpfCnpj' => CPF_CNPJ, 13 | ]; 14 | 15 | /** 16 | * initialize phpay 17 | * 18 | * @var AsaasGateway $phpay 19 | */ 20 | $phpay = new PHPay(new AsaasGateway(TOKEN_ASAAS_SANDBOX)); 21 | 22 | /** 23 | * store a new webhook 24 | * 25 | * @return array 26 | * @see available fields in https://docs.asaas.com/reference/criar-novo-webhook 27 | */ 28 | $phpay 29 | ->webhook(WEBHOOK) 30 | ->create(); 31 | 32 | /** 33 | * get all webhooks 34 | * 35 | * @return array 36 | */ 37 | $phpay 38 | ->webhook() 39 | ->getAll(); 40 | 41 | /** 42 | * find a webhook 43 | * 44 | * @return array 45 | */ 46 | $phpay 47 | ->webhook() 48 | ->find($webhookId); 49 | 50 | /** 51 | * update a webhook 52 | * 53 | * @return array 54 | * @see available fields in https://docs.asaas.com/reference/atualizar-webhook-existente 55 | */ 56 | $phpay 57 | ->webhook() 58 | ->update($webhookId, [ 59 | 'name' => 'Update webhook with PHPay is awesome', 60 | 'url' => 'https://sixtec.com.br/webhook/atualizado', 61 | ]); 62 | 63 | /** 64 | * delete a webhook 65 | * 66 | * @return bool 67 | */ 68 | $phpay 69 | ->webhook() 70 | ->destroy($webhookId); 71 | -------------------------------------------------------------------------------- /examples/efi/charges.php: -------------------------------------------------------------------------------- 1 | NAME, 12 | 'cpf_cnpj' => CPF_CNPJ, 13 | ]; 14 | 15 | $charge = [ 16 | 'value' => 100.00, 17 | 'description' => 'Teste de fatura', 18 | 'expire_at' => date('Y-m-d', strtotime('+1 day')), 19 | 'message' => 'Teste de mensagem', 20 | ]; 21 | 22 | /** 23 | * @var EfiGateway $phpay 24 | */ 25 | $phpay = new PHPay(new EfiGateway(CLIENT_ID, CLIENT_SECRET)); 26 | 27 | $phpay 28 | ->charge($charge) 29 | ->setCustomer($customer) 30 | ->create(); 31 | 32 | /** 33 | * get all charges 34 | * 35 | * @return array charges 36 | */ 37 | $charges = $phpay 38 | ->charge() 39 | ->getAll(); 40 | 41 | /** 42 | * find charge by id 43 | * 44 | * @return array charge 45 | */ 46 | $phpay 47 | ->charge() 48 | ->find($chargeId); 49 | 50 | /** 51 | * confirm receipt 52 | * 53 | * @return array charge 54 | */ 55 | $phpay 56 | ->charge() 57 | ->confirmReceipt($chargeId); 58 | 59 | /** 60 | * cancel charge 61 | */ 62 | $phpay 63 | ->charge() 64 | ->cancel($chargeId); 65 | 66 | /** 67 | * update due date 68 | */ 69 | $phpay 70 | ->charge() 71 | ->updateDueDate($chargeId, $dueDate); 72 | 73 | /** 74 | * update billet metadata 75 | * notification_url and custom_id 76 | */ 77 | $phpay 78 | ->charge() 79 | ->updateMetadata($chargeId, [ 80 | 'notification_url' => $notificationUrl, 81 | 'custom_id' => $customId, 82 | ]); 83 | -------------------------------------------------------------------------------- /examples/efi/credentials.example.php: -------------------------------------------------------------------------------- 1 | 1) { 10 | $type = $argv[1]; 11 | $message = $argv[2]; 12 | $error = $argv[3] ?? null; 13 | 14 | renderCLI($message, $type, $error); 15 | } 16 | 17 | /** 18 | * render success message 19 | */ 20 | function renderCLI( 21 | string $message, 22 | string $type, 23 | ?string $error 24 | ): void { 25 | switch ($type) { 26 | case 'success': 27 | $icon = '✔️'; 28 | 29 | break; 30 | case 'error': 31 | $icon = '❌'; 32 | 33 | break; 34 | default: 35 | $icon = '⚠️'; 36 | 37 | break; 38 | } 39 | 40 | $contentError = $error ? "{$error}" : ''; 41 | 42 | render(<< 44 | $icon 45 | {$message} 46 | {$contentError} 47 | 48 | HTML); 49 | } 50 | -------------------------------------------------------------------------------- /examples/helper/termwind.php: -------------------------------------------------------------------------------- 1 | {$content}" : ''; 13 | 14 | render(<< 16 | {$gateway} 17 | {$message} 18 | {$aditionalContent} 19 | 20 | HTML); 21 | } 22 | 23 | /** 24 | * render error message 25 | */ 26 | function renderError(string $message, string $gateway, ?string $content): void 27 | { 28 | $aditionalContent = $content ? "
{$content}" : ''; 29 | 30 | render(<< 32 | {$gateway} 33 | {$message} 34 | {$aditionalContent} 35 | 36 | HTML); 37 | } 38 | 39 | /** 40 | * render info message 41 | */ 42 | function renderMessage(string $message, string $gateway, ?string $content): void 43 | { 44 | $aditionalContent = $content ? "
{$content}" : ''; 45 | 46 | render(<< 48 | {$gateway} 49 | {$message} 50 | {$aditionalContent} 51 | 52 | HTML); 53 | } 54 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "phpay", 3 | "lockfileVersion": 3, 4 | "requires": true, 5 | "packages": { 6 | "": { 7 | "hasInstallScript": true, 8 | "devDependencies": { 9 | "husky": "^9.1.7" 10 | } 11 | }, 12 | "node_modules/husky": { 13 | "version": "9.1.7", 14 | "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", 15 | "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", 16 | "dev": true, 17 | "license": "MIT", 18 | "bin": { 19 | "husky": "bin.js" 20 | }, 21 | "engines": { 22 | "node": ">=18" 23 | }, 24 | "funding": { 25 | "url": "https://github.com/sponsors/typicode" 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "husky": "^9.1.7" 4 | }, 5 | "scripts": { 6 | "prepare": "husky", 7 | "postinstall": "husky install" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /phpstan.neon: -------------------------------------------------------------------------------- 1 | parameters: 2 | paths: 3 | - src -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | ./tests 10 | 11 | 12 | 13 | 14 | ./src 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /pint.json: -------------------------------------------------------------------------------- 1 | { 2 | "preset": "psr12", 3 | "rules": { 4 | "group_import": true, 5 | "single_import_per_statement": false, 6 | "no_unused_imports": true, 7 | "array_indentation": true, 8 | "array_syntax": { 9 | "syntax": "short" 10 | }, 11 | "binary_operator_spaces": { 12 | "default": "single_space", 13 | "operators": { 14 | "=": "align_single_space_minimal", 15 | "=>": "align_single_space_minimal" 16 | } 17 | }, 18 | "blank_line_after_namespace": true, 19 | "blank_line_after_opening_tag": false, 20 | "class_attributes_separation": { 21 | "elements": { 22 | "property": "one" 23 | } 24 | }, 25 | "concat_space": { 26 | "spacing": "one" 27 | }, 28 | "declare_equal_normalize": { 29 | "space": "single" 30 | }, 31 | "elseif": false, 32 | "encoding": true, 33 | "indentation_type": true, 34 | "no_useless_else": false, 35 | "no_useless_return": true, 36 | "ordered_imports": true, 37 | "ternary_operator_spaces": true, 38 | "no_extra_blank_lines": true, 39 | "no_multiline_whitespace_around_double_arrow": true, 40 | "multiline_whitespace_before_semicolons": true, 41 | "no_singleline_whitespace_before_semicolons": true, 42 | "no_spaces_around_offset": true, 43 | "ternary_to_null_coalescing": true, 44 | "whitespace_after_comma_in_array": true, 45 | "trim_array_spaces": true, 46 | "trailing_comma_in_multiline": true, 47 | "unary_operator_spaces": true, 48 | "blank_line_before_statement": { 49 | "statements": [ 50 | "break", 51 | "continue", 52 | "declare", 53 | "return", 54 | "throw", 55 | "try", 56 | "continue", 57 | "do", 58 | "exit", 59 | "for", 60 | "foreach", 61 | "if", 62 | "include", 63 | "include_once", 64 | "require", 65 | "require_once" 66 | ] 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /src/Contracts/GatewayInterface.php: -------------------------------------------------------------------------------- 1 | $customer 11 | * @return object 12 | */ 13 | public function customer(array $customer = []): object; 14 | 15 | /** 16 | * get resource charge from gateway. 17 | * 18 | * @return object 19 | */ 20 | public function charge(): object; 21 | 22 | /** 23 | * get resource webhook from gateway. 24 | * 25 | * @param array $webhook 26 | * @return object 27 | */ 28 | public function webhook(array $webhook = []): object; 29 | 30 | /** 31 | * get resource pix from gateway. 32 | * 33 | * @param array $pix 34 | * @return object 35 | */ 36 | public function pix(array $pix = []): object; 37 | 38 | /** 39 | * get resource subscription from gateway. 40 | * 41 | * @return object 42 | */ 43 | public function subscription(): object; 44 | } 45 | -------------------------------------------------------------------------------- /src/Exceptions/AsaasExceptions.php: -------------------------------------------------------------------------------- 1 | $customer 43 | * @return Customer 44 | */ 45 | public function customer(array $customer = []): Customer 46 | { 47 | $this->customer = new Customer($this->token, $customer, $this->sandbox); 48 | 49 | return $this->customer; 50 | } 51 | 52 | /** 53 | * charge 54 | * 55 | * @return Charge 56 | */ 57 | public function charge(): Charge 58 | { 59 | return new Charge($this->token, $this->sandbox); 60 | } 61 | 62 | /** 63 | * webhook 64 | * 65 | * @param array $webhook 66 | * @return Webhook 67 | */ 68 | public function webhook(array $webhook = []): Webhook 69 | { 70 | return new Webhook($this->token, $webhook, $this->sandbox); 71 | } 72 | 73 | /** 74 | * pix 75 | * 76 | * @param array $pix 77 | * @return Pix 78 | */ 79 | public function pix(array $pix = []): Pix 80 | { 81 | return new Pix($this->token, $this->sandbox); 82 | } 83 | 84 | public function subscription(): Subscription 85 | { 86 | return new Subscription($this->token, $this->sandbox); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/Gateways/Asaas/Enums/BillingTypeEnum.php: -------------------------------------------------------------------------------- 1 | $customer 18 | * @return Customer 19 | */ 20 | public function customer(array $customer = []): Customer; 21 | 22 | /** 23 | * get resource charge from gateway. 24 | * 25 | * @return Charge 26 | */ 27 | public function charge(): Charge; 28 | 29 | /** 30 | * get resource subscription from gateway. 31 | * 32 | * @return Subscription 33 | */ 34 | public function subscription(): Subscription; 35 | 36 | /** 37 | * get resource webhook from gateway. 38 | * 39 | * @param array $webhook 40 | * @return Webhook 41 | */ 42 | public function webhook(array $webhook = []): Webhook; 43 | 44 | /** 45 | * get resource pix from gateway. 46 | * 47 | * @param array $pix 48 | * @return Pix 49 | */ 50 | public function pix(array $pix = []): Pix; 51 | } 52 | -------------------------------------------------------------------------------- /src/Gateways/Asaas/Requests/AsaasChargeRequest.php: -------------------------------------------------------------------------------- 1 | $charge 13 | * @return void 14 | */ 15 | public static function validate(array $charge): void 16 | { 17 | if (!isset($charge['customer']) && !is_string($charge['customer'])) { 18 | /** @phpstan-ignore property.notFound */ 19 | throw new \InvalidArgumentException(self::messages()->charge->customer, 400); 20 | } 21 | 22 | if (!isset($charge['billingType'])) { 23 | /** @phpstan-ignore property.notFound */ 24 | throw new \InvalidArgumentException(self::messages()->charge->billingType, 400); 25 | } 26 | 27 | if (!BillingTypeEnum::tryFrom($charge['billingType'])) { 28 | /** @phpstan-ignore property.notFound */ 29 | throw new \InvalidArgumentException(self::messages()->charge->billingType, 400); 30 | } 31 | 32 | if (!isset($charge['value']) && !is_numeric($charge['value'])) { 33 | /** @phpstan-ignore property.notFound */ 34 | throw new \InvalidArgumentException(self::messages()->charge->value, 400); 35 | } 36 | 37 | if (!isset($charge['dueDate']) && !is_string($charge['dueDate'])) { 38 | /** @phpstan-ignore property.notFound */ 39 | throw new \InvalidArgumentException(self::messages()->charge->dueDate, 400); 40 | } 41 | } 42 | 43 | /** 44 | * messages for validation 45 | * 46 | * @return object 47 | */ 48 | public static function messages(): object 49 | { 50 | return (object) [ 51 | 'customer' => (object) [ 52 | 'id' => 'Asaas: Para gerar uma cobrança é necessário um id de customere do Asaas.', 53 | ], 54 | 'charge' => (object) [ 55 | 'customer' => 'Asaas: O campo customer é obrigatório e deve ser do tipo string.', 56 | 'billingType' => 'Asaas: O campo billingType é obrigatório, e tem como disponível as seguintes opções: UNDEFINED, BOLETO, CREDIT_CARD, PIX', 57 | 'value' => 'Asaas: O campo value é obrigatório e deve ser do tipo numérico.', 58 | 'dueDate' => 'Asaas: O campo dueDate é obrigatório e deve ser do tipo string.', 59 | ], 60 | ]; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/Gateways/Asaas/Requests/AsaasCustomerRequest.php: -------------------------------------------------------------------------------- 1 | $customer 11 | * @property-read string $name 12 | * @property-read string $cpfCnpj 13 | * @return void 14 | */ 15 | public static function validate(array $customer): void 16 | { 17 | if (!isset($customer['name'])) { 18 | /** @phpstan-ignore property.notFound */ 19 | throw new \InvalidArgumentException(self::messages()->name, 400); 20 | } 21 | 22 | if (!isset($customer['cpfCnpj'])) { 23 | /** @phpstan-ignore property.notFound */ 24 | throw new \InvalidArgumentException(self::messages()->cpfCnpj, 400); 25 | } 26 | } 27 | 28 | /** 29 | * messages for validation 30 | * 31 | * @return object 32 | */ 33 | public static function messages(): object 34 | { 35 | return (object) [ 36 | 'name' => 'Asaas: Nome do cliente é obrigatório para o Asaas', 37 | 'cpfCnpj' => 'Asaas: CPF/CNPJ do cliente é obrigatório para o Asaas', 38 | ]; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Gateways/Asaas/Requests/AsaasPixRequest.php: -------------------------------------------------------------------------------- 1 | $pix 11 | * @return void 12 | */ 13 | public static function validate(array $pix): void 14 | { 15 | if (!isset($pix['description'])) { 16 | /** @phpstan-ignore property.notFound */ 17 | throw new \InvalidArgumentException(self::messages()->description); 18 | } 19 | 20 | if (!isset($pix['amount'])) { 21 | /** @phpstan-ignore property.notFound */ 22 | throw new \InvalidArgumentException(self::messages()->amount); 23 | } 24 | 25 | if (!isset($pix['due_date'])) { 26 | /** @phpstan-ignore property.notFound */ 27 | throw new \InvalidArgumentException(self::messages()->due_date->required); 28 | } 29 | 30 | if ($pix['due_date'] < date('Y-m-d')) { 31 | /** @phpstan-ignore property.notFound */ 32 | throw new \InvalidArgumentException(self::messages()->due_date->date); 33 | } 34 | } 35 | 36 | public static function messages(): object 37 | { 38 | return (object) [ 39 | 'description' => 'Asaas: Descrição do pagamento é obrigatório para o Asaas', 40 | 'amount' => 'Asaas: Valor do pagamento é obrigatório para o Asaas', 41 | 'due_date' => (object) [ 42 | 'required' => 'Asaas: Data de vencimento do pagamento é obrigatório para o Asaas', 43 | 'date' => 'Asaas: Data de vencimento do pagamento não pode ser menor que a data atual', 44 | ], 45 | ]; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Gateways/Asaas/Resources/Charge/Charge.php: -------------------------------------------------------------------------------- 1 | 25 | */ 26 | private array $queryParams = []; 27 | 28 | /** 29 | * @var array 30 | */ 31 | private array $charge = []; 32 | 33 | /** 34 | * construct 35 | */ 36 | public function __construct( 37 | private string $token, 38 | private bool $sandbox = true, 39 | ) { 40 | $this->client = $this->clientAsaasBoot(); 41 | } 42 | 43 | /** 44 | * set charge 45 | * 46 | * @param array $charge 47 | * @return ChargeInterface 48 | */ 49 | public function setCharge(array $charge): ChargeInterface 50 | { 51 | $this->charge = $charge; 52 | 53 | return $this; 54 | } 55 | 56 | /** 57 | * set query params 58 | * 59 | * @param array $queryParams 60 | * @return ChargeInterface 61 | */ 62 | public function setQueryParams(array $queryParams): ChargeInterface 63 | { 64 | $this->queryParams = $queryParams; 65 | 66 | return $this; 67 | } 68 | 69 | /** 70 | * set customer 71 | * 72 | * @param array $customer 73 | * @return ChargeInterface 74 | */ 75 | public function setCustomer(array $customer): ChargeInterface 76 | { 77 | $customer = (new Customer( 78 | $this->token, 79 | $customer, 80 | $this->sandbox 81 | ))->create(); 82 | 83 | $this->charge['customer'] = $customer['id']; 84 | 85 | return $this; 86 | } 87 | 88 | /** 89 | * find charges by id 90 | * 91 | * @return array 92 | */ 93 | public function find(string $id): array 94 | { 95 | return $this->get("payments/{$id}"); 96 | } 97 | 98 | /** 99 | * get all charges 100 | * 101 | * @return array 102 | */ 103 | public function getAll(): array 104 | { 105 | return $this->get('payments', $this->queryParams); 106 | } 107 | 108 | /** 109 | * create charge 110 | * 111 | * @return string 112 | * @return array 113 | * @see fields available in https://docs.asaas.com/reference/criar-nova-cobranca 114 | */ 115 | public function create(): array 116 | { 117 | AsaasChargeRequest::validate($this->charge); 118 | 119 | return $this->post('payments', $this->charge); 120 | } 121 | 122 | /** 123 | * update charge 124 | * 125 | * @param string $id 126 | * @param array $data 127 | * @return array 128 | */ 129 | public function update(string $id, array $data): array 130 | { 131 | return $this->put("payments/{$id}", $data); 132 | } 133 | 134 | /** 135 | * destroy charge 136 | * 137 | * @param string $id 138 | * @return bool 139 | */ 140 | public function destroy(string $id): bool 141 | { 142 | return $this->delete("payments/{$id}"); 143 | } 144 | 145 | /** 146 | * restore charge 147 | * 148 | * @param string $id 149 | * @return array 150 | */ 151 | public function restore(string $id): array 152 | { 153 | return $this->post("payments/{$id}/restore"); 154 | } 155 | 156 | /** 157 | * get status charge 158 | * 159 | * @param string $id 160 | * @return array 161 | */ 162 | public function getStatus(string $id): array 163 | { 164 | return $this->get("payments/{$id}/status"); 165 | } 166 | 167 | /** 168 | * get digitable line 169 | * 170 | * @param string $id 171 | * @return mixed 172 | */ 173 | public function getDigitableLine(string $id): mixed 174 | { 175 | $charge = $this->get("payments/{$id}/identificationField"); 176 | 177 | if (isset($charge['identificationField'])) { 178 | return $charge['identificationField']; 179 | } 180 | 181 | return null; 182 | } 183 | 184 | /** 185 | * get qrcode pix 186 | * 187 | * @param string $id 188 | * @return array 189 | */ 190 | public function getQrCodePix(string $id): array 191 | { 192 | return $this->get("payments/{$id}/pixQrCode"); 193 | } 194 | 195 | /** 196 | * confirm receipt 197 | * 198 | * @param string $id 199 | * @param array $data 200 | * @return array 201 | */ 202 | public function confirmReceipt(string $id, array $data): array 203 | { 204 | return $this->post("payments/{$id}/receiveInCash", $data); 205 | } 206 | 207 | /** 208 | * undo confirm receipt 209 | * 210 | * @param string $id 211 | * @return array 212 | */ 213 | public function undoConfirmReceipt(string $id): array 214 | { 215 | return $this->post("payments/{$id}/undoReceivedInCash"); 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /src/Gateways/Asaas/Resources/Charge/Enum/WebhookEventsEnum.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | public function getAll(): array; 13 | 14 | /** 15 | * find charge by id 16 | * 17 | * @param string $id 18 | * @return array 19 | */ 20 | public function find(string $id): array; 21 | 22 | /** 23 | * create charge 24 | * 25 | * @return array 26 | */ 27 | public function create(): array; 28 | 29 | /** 30 | * update charge by id 31 | * 32 | * @param string $id 33 | * @param array $data 34 | * @return array 35 | */ 36 | public function update(string $id, array $data): array; 37 | 38 | /** 39 | * delete charge by id 40 | * 41 | * @param string $id 42 | * @return bool 43 | */ 44 | public function destroy(string $id): bool; 45 | 46 | /** 47 | * restore charge by id 48 | * 49 | * @param string $id 50 | * @return array 51 | */ 52 | public function restore(string $id): array; 53 | 54 | /** 55 | * set customer 56 | * 57 | * @param array $customer 58 | * @return ChargeInterface 59 | */ 60 | public function setCustomer(array $customer): ChargeInterface; 61 | 62 | /** 63 | * set charge 64 | * 65 | * @param array $charge 66 | * @return ChargeInterface 67 | */ 68 | public function setCharge(array $charge): ChargeInterface; 69 | 70 | /** 71 | * set query params 72 | * 73 | * @param array $queryParams 74 | * @return ChargeInterface 75 | */ 76 | public function setQueryParams(array $queryParams): ChargeInterface; 77 | 78 | /** 79 | * get status charge by id 80 | * 81 | * @param string $id 82 | * @return array 83 | */ 84 | public function getStatus(string $id): array; 85 | 86 | /** 87 | * get charge digit line by id 88 | * 89 | * @param string $id 90 | * @return mixed 91 | */ 92 | public function getDigitableLine(string $id): mixed; 93 | 94 | /** 95 | * get charge qr code pix by id 96 | * 97 | * @param string $id 98 | * @return array 99 | */ 100 | public function getQrCodePix(string $id): array; 101 | 102 | /** 103 | * confirm receipt charge by id 104 | * 105 | * @param string $id 106 | * @param array $data 107 | * @return array 108 | */ 109 | public function confirmReceipt(string $id, array $data): array; 110 | 111 | /** 112 | * undo confirm receipt charge by id 113 | * 114 | * @param string $id 115 | * @return array 116 | */ 117 | public function undoConfirmReceipt(string $id): array; 118 | } 119 | -------------------------------------------------------------------------------- /src/Gateways/Asaas/Resources/Customer/Customer.php: -------------------------------------------------------------------------------- 1 | 24 | */ 25 | private array $filter = []; 26 | 27 | /** 28 | * construct 29 | * 30 | * @param array $customer 31 | */ 32 | public function __construct( 33 | private string $token, 34 | private array $customer = [], 35 | private bool $sandbox = true 36 | ) { 37 | $this->client = $this->clientAsaasBoot(); 38 | 39 | if (!empty($customer)) { 40 | $this->customer = $customer; 41 | } 42 | } 43 | 44 | /** 45 | * get all customers 46 | * 47 | * @return array 48 | */ 49 | public function getAll(): array 50 | { 51 | return $this->get('customers', $this->filter); 52 | } 53 | 54 | /** 55 | * get customer by id 56 | * 57 | * @param string $id 58 | * @return array 59 | */ 60 | public function find(string $id): array 61 | { 62 | return $this->get("customers/{$id}"); 63 | } 64 | 65 | /** 66 | * create customer 67 | * 68 | * @return array 69 | * @see available fields in https://docs.asaas.com/reference/criar-novo-cliente 70 | */ 71 | public function create(): array 72 | { 73 | AsaasCustomerRequest::validate($this->customer); 74 | 75 | return $this->post('customers', $this->customer); 76 | } 77 | 78 | /** 79 | * update customer 80 | * 81 | * @param string $id 82 | * @return array 83 | * @see available fields in https://docs.asaas.com/reference/criar-novo-cliente 84 | */ 85 | public function update(string $id): array 86 | { 87 | return $this->put("customers/{$id}", $this->customer); 88 | } 89 | 90 | /** 91 | * destroy customer 92 | * 93 | * @param string $id 94 | * @return bool 95 | */ 96 | public function destroy(string $id): bool 97 | { 98 | return $this->delete("customers/{$id}"); 99 | } 100 | 101 | /** 102 | * restore customer deleted 103 | * 104 | * @param string $id 105 | * @return array 106 | */ 107 | public function restore(string $id): array 108 | { 109 | return $this->post("customers/{$id}/restore"); 110 | } 111 | 112 | /** 113 | * get notifications 114 | * 115 | * @param string $id 116 | * @return array 117 | */ 118 | public function getNotifications(string $id): array 119 | { 120 | return $this->get("customers/{$id}/notifications"); 121 | } 122 | 123 | /** 124 | * set filter 125 | * 126 | * @param array $filter 127 | * @return CustomerInterface 128 | */ 129 | public function setFilter(array $filter = []): CustomerInterface 130 | { 131 | $this->filter = $filter; 132 | 133 | return $this; 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/Gateways/Asaas/Resources/Customer/Interface/CustomerInterface.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | public function find(string $id): array; 14 | 15 | /** 16 | * get all customers 17 | * 18 | * @return array 19 | */ 20 | public function getAll(): array; 21 | 22 | /** 23 | * create customer 24 | * 25 | * @return array 26 | */ 27 | public function create(): array; 28 | 29 | /** 30 | * update customer by id 31 | * 32 | * @param string $id 33 | * @return array 34 | */ 35 | public function update(string $id): array; 36 | 37 | /** 38 | * delete customer by id 39 | * 40 | * @param string $id 41 | * @return bool 42 | */ 43 | public function destroy(string $id): bool; 44 | 45 | /** 46 | * restore customer by id 47 | * 48 | * @param string $id 49 | * @return array 50 | */ 51 | public function restore(string $id): array; 52 | 53 | /** 54 | * get customer notifications by id 55 | * 56 | * @param string $id 57 | * @return array 58 | */ 59 | public function getNotifications(string $id): array; 60 | 61 | /** 62 | * set filter 63 | * 64 | * @param array $filter 65 | * @return self 66 | */ 67 | public function setFilter(array $filter = []): self; 68 | } 69 | -------------------------------------------------------------------------------- /src/Gateways/Asaas/Resources/Pix/Interface/PixInterface.php: -------------------------------------------------------------------------------- 1 | $queryParams 11 | * @return PixInterface 12 | */ 13 | public function setQueryParams(array $queryParams): PixInterface; 14 | 15 | /** 16 | * create pix key 17 | * 18 | * @return array 19 | */ 20 | public function createKey(): array; 21 | 22 | /** 23 | * find pix key 24 | * 25 | * @param string $id 26 | * @return array 27 | */ 28 | public function find(string $id): array; 29 | 30 | /** 31 | * get all pix keys 32 | * 33 | * @return array 34 | * @see params in https://docs.asaas.com/reference/list-keys 35 | */ 36 | public function getAll(): array; 37 | 38 | /** 39 | * destroy pix key 40 | * 41 | * @param string $id 42 | * @return bool 43 | */ 44 | public function destroy(string $id): bool; 45 | 46 | /** 47 | * static qr code 48 | * 49 | * @param array $params 50 | * @return array 51 | */ 52 | public function staticQrCode(array $params): array; 53 | 54 | /** 55 | * destroy static qr code 56 | * 57 | * @param string $id 58 | * @return bool 59 | */ 60 | public function destroyStaticQrCode(string $id): bool; 61 | } 62 | -------------------------------------------------------------------------------- /src/Gateways/Asaas/Resources/Pix/Pix.php: -------------------------------------------------------------------------------- 1 | 23 | */ 24 | private array $queryParams = []; 25 | 26 | /** 27 | * construct 28 | * 29 | * @param string $token 30 | */ 31 | public function __construct( 32 | private string $token, 33 | private bool $sandbox = true, 34 | ) { 35 | $this->client = $this->clientAsaasBoot(); 36 | } 37 | 38 | /** 39 | * set query params 40 | * 41 | * @param array $queryParams 42 | * @return PixInterface 43 | */ 44 | public function setQueryParams(array $queryParams): PixInterface 45 | { 46 | $this->queryParams = $queryParams; 47 | 48 | return $this; 49 | } 50 | 51 | /** 52 | * create pix key 53 | * 54 | * @return string 55 | * @return array 56 | */ 57 | public function createKey(): array 58 | { 59 | /* TODO: prepare response */ 60 | /* TODO: adding reponse with image qrcode */ 61 | return $this->post('pix/addressKeys', [ 62 | 'type' => 'EVP', 63 | ]); 64 | } 65 | 66 | /** 67 | * find pix key 68 | * 69 | * @param string $id 70 | * @return array 71 | */ 72 | public function find(string $id): array 73 | { 74 | return $this->get("pix/addressKeys/{$id}"); 75 | } 76 | 77 | /** 78 | * get all pix keys 79 | * 80 | * @return array 81 | * @see params in https://docs.asaas.com/reference/list-keys 82 | */ 83 | public function getAll(): array 84 | { 85 | $params = $this->queryParams; 86 | 87 | if (empty($params)) { 88 | $params = [ 89 | 'offset' => 0, 90 | 'limit' => 100, 91 | ]; 92 | } 93 | 94 | return $this->get('pix/addressKeys', $params); 95 | } 96 | 97 | /** 98 | * destroy pix key 99 | * 100 | * @param string $id 101 | * @return bool 102 | */ 103 | public function destroy(string $id): bool 104 | { 105 | return $this->delete("pix/addressKeys/{$id}"); 106 | } 107 | 108 | /** 109 | * static qr code 110 | * 111 | * @param array $params 112 | * @return array 113 | * @see params in https://docs.asaas.com/reference/create-static-qrcode 114 | */ 115 | public function staticQrCode(array $params): array 116 | { 117 | return $this->post('pix/qrCodes/static', $params); 118 | } 119 | 120 | /** 121 | * destroy static qr code 122 | * 123 | * @param string $id 124 | * @return bool 125 | */ 126 | public function destroyStaticQrCode(string $id): bool 127 | { 128 | return $this->delete("pix/qrCodes/static/{$id}"); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/Gateways/Asaas/Resources/Subscription/Interface/SubscriptionInterface.php: -------------------------------------------------------------------------------- 1 | $customer 15 | * @return Subscription 16 | */ 17 | public function setCustomer(array $customer): Subscription; 18 | 19 | /** 20 | * create subscription 21 | * 22 | * @param array $subscription 23 | * @return array 24 | */ 25 | public function create(array $subscription): array; 26 | 27 | // public function findAll(); 28 | // public function find(string $subscriptionId); 29 | // public function update(string $subscriptionId, array $subscription); 30 | // public function destroy(string $subscriptionId); 31 | // public function findCharges(string $subscriptionId); 32 | // public function generateCarnet(string $subscriptionId); 33 | // public function nfeSettings(string $subscriptionId, array $nfeSettings); 34 | // public function findNfeSettings(string $subscriptionId); 35 | // public function updateNfeSettings(string $subscriptionId, array $nfeSettings); 36 | // public function destroyNfeSettings(string $subscriptionId); 37 | // public function findNfes(string $subscriptionId); 38 | } 39 | -------------------------------------------------------------------------------- /src/Gateways/Asaas/Resources/Subscription/Requests/StoreSubscriptionAsaasRequest.php: -------------------------------------------------------------------------------- 1 | $charge 13 | * @return void 14 | */ 15 | public static function validate(array $charge): void 16 | { 17 | if (!isset($charge['customer']) && !is_string($charge['customer'])) { 18 | /** @phpstan-ignore property.notFound */ 19 | throw new \InvalidArgumentException(self::messages()->charge->customer, 400); 20 | } 21 | 22 | if (!isset($charge['billingType'])) { 23 | /** @phpstan-ignore property.notFound */ 24 | throw new \InvalidArgumentException(self::messages()->charge->billingType, 400); 25 | } 26 | 27 | if (!BillingTypeEnum::tryFrom($charge['billingType'])) { 28 | /** @phpstan-ignore property.notFound */ 29 | throw new \InvalidArgumentException(self::messages()->charge->billingType, 400); 30 | } 31 | 32 | if (!isset($charge['value']) && !is_numeric($charge['value'])) { 33 | /** @phpstan-ignore property.notFound */ 34 | throw new \InvalidArgumentException(self::messages()->charge->value, 400); 35 | } 36 | 37 | if (!isset($charge['nextDueDate']) && !is_string($charge['nextDueDate'])) { 38 | /** @phpstan-ignore property.notFound */ 39 | throw new \InvalidArgumentException(self::messages()->charge->nextDueDate, 400); 40 | } 41 | } 42 | 43 | /** 44 | * messages for validation 45 | * 46 | * @return object 47 | */ 48 | public static function messages(): object 49 | { 50 | return (object) [ 51 | 'customer' => (object) [ 52 | 'id' => 'Asaas: O identificador do customer é obrigatório.', 53 | ], 54 | 'charge' => (object) [ 55 | 'customer' => 'Asaas: O campo customer é obrigatório e deve ser do tipo string.', 56 | 'billingType' => 'Asaas: O campo billingType é obrigatório, e tem como disponível as seguintes opções: UNDEFINED, BOLETO, CREDIT_CARD, PIX', 57 | 'value' => 'Asaas: O campo value é obrigatório e deve ser do tipo numérico.', 58 | 'nextDueDate' => 'Asaas: O campo nextDueDate é obrigatório e deve ser do tipo string.', 59 | ], 60 | ]; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/Gateways/Asaas/Resources/Subscription/Subscription.php: -------------------------------------------------------------------------------- 1 | client = $this->clientAsaasBoot(); 24 | } 25 | 26 | /** 27 | * set customer 28 | * 29 | * @param array $customer 30 | * @return Subscription 31 | */ 32 | public function setCustomer(array $customer): Subscription 33 | { 34 | $customer = (new Customer( 35 | $this->token, 36 | $customer, 37 | $this->sandbox 38 | ))->create(); 39 | 40 | $this->customerId = $customer['id']; 41 | 42 | return $this; 43 | } 44 | 45 | public function create(array $subscription): array 46 | { 47 | $subscription['customer'] = $this->customerId; 48 | 49 | StoreSubscriptionAsaasRequest::validate($subscription); 50 | 51 | return $this->post('subscriptions', $subscription); 52 | } 53 | 54 | // public function findAll() 55 | // { 56 | // throw new \Exception('Method not implemented'); 57 | // } 58 | 59 | // public function find(string $subscriptionId) 60 | // { 61 | // throw new \Exception('Method not implemented'); 62 | // } 63 | 64 | // public function update(string $subscriptionId, array $subscription) 65 | // { 66 | // throw new \Exception('Method not implemented'); 67 | // } 68 | 69 | // public function destroy(string $subscriptionId) 70 | // { 71 | // throw new \Exception('Method not implemented'); 72 | // } 73 | 74 | // public function findCharges(string $subscriptionId) 75 | // { 76 | // throw new \Exception('Method not implemented'); 77 | // } 78 | 79 | // public function generateCarnet(string $subscriptionId) 80 | // { 81 | // throw new \Exception('Method not implemented'); 82 | // } 83 | 84 | // public function nfeSettings(string $subscriptionId, array $nfeSettings) 85 | // { 86 | // throw new \Exception('Method not implemented'); 87 | // } 88 | 89 | // public function findNfeSettings(string $subscriptionId) 90 | // { 91 | // throw new \Exception('Method not implemented'); 92 | // } 93 | 94 | // public function updateNfeSettings(string $subscriptionId, array $nfeSettings) 95 | // { 96 | // throw new \Exception('Method not implemented'); 97 | // } 98 | 99 | // public function destroyNfeSettings(string $subscriptionId) 100 | // { 101 | // throw new \Exception('Method not implemented'); 102 | // } 103 | 104 | // public function findNfes(string $subscriptionId) 105 | // { 106 | // throw new \Exception('Method not implemented'); 107 | // } 108 | } 109 | -------------------------------------------------------------------------------- /src/Gateways/Asaas/Resources/Webhook/Interface/WebhookInterface.php: -------------------------------------------------------------------------------- 1 | $webhook 11 | * @return array 12 | */ 13 | public function create(array $webhook = []): array; 14 | 15 | /** 16 | * get all webhooks 17 | * 18 | * @return array 19 | */ 20 | public function getAll(): array; 21 | 22 | /** 23 | * find webhook by id 24 | * 25 | * @param string $id 26 | * @return array 27 | */ 28 | public function find(string $id): array; 29 | 30 | /** 31 | * update webhook by id 32 | * 33 | * @param string $id 34 | * @param array $webhook 35 | * @return array 36 | */ 37 | public function update(string $id, array $webhook = []): array; 38 | 39 | /** 40 | * delete webhook by id 41 | * 42 | * @param string $id 43 | * @return bool 44 | */ 45 | public function destroy(string $id): bool; 46 | } 47 | -------------------------------------------------------------------------------- /src/Gateways/Asaas/Resources/Webhook/Webhook.php: -------------------------------------------------------------------------------- 1 | $webhook 25 | */ 26 | public function __construct( 27 | private string $token, 28 | private array $webhook = [], 29 | private bool $sandbox = true 30 | ) { 31 | $this->client = $this->clientAsaasBoot(); 32 | 33 | if (!empty($webhook)) { 34 | $this->webhook = $webhook; 35 | } 36 | } 37 | 38 | /** 39 | * construct 40 | * 41 | * @param array $webhook 42 | * @return array 43 | */ 44 | public function create(array $webhook = []): array 45 | { 46 | return $this->post('webhooks', $this->webhook); 47 | } 48 | 49 | /** 50 | * get all webhooks 51 | * 52 | * @return array 53 | */ 54 | public function getAll(): array 55 | { 56 | return $this->get("webhooks"); 57 | } 58 | 59 | /** 60 | * get webhook by id 61 | * 62 | * @param string $id 63 | * @return array 64 | */ 65 | public function find(string $id): array 66 | { 67 | return $this->get("webhooks/{$id}"); 68 | } 69 | 70 | /** 71 | * update webhook by id 72 | * 73 | * @param string $id 74 | * @param array $webhook 75 | * @return array 76 | */ 77 | public function update(string $id, array $webhook = []): array 78 | { 79 | return $this->put("webhooks/{$id}", $webhook); 80 | } 81 | 82 | /** 83 | * delete webhook by id 84 | * 85 | * @param string $id 86 | * @return bool 87 | */ 88 | public function destroy(string $id): bool 89 | { 90 | return $this->delete("webhooks/{$id}"); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/Gateways/Asaas/Traits/HasAsaasClient.php: -------------------------------------------------------------------------------- 1 | sandbox ? 17 | 'https://sandbox.asaas.com/api/v3/' : 18 | 'https://www.asaas.com/api/v3/'; 19 | 20 | return new Client([ 21 | 'base_uri' => $baseUrl, 22 | 'headers' => [ 23 | 'content-type' => 'application/json', 24 | 'user-agent' => 'PHPay', 25 | 'access_token' => $this->token, 26 | ], 27 | ]); 28 | } 29 | 30 | /** 31 | * get data 32 | * 33 | * @param string $endpoint 34 | * @param array $filters 35 | * @return array 36 | */ 37 | protected function get(string $endpoint, array $filters = []): array 38 | { 39 | try { 40 | $reposonse = $this->client->get($endpoint, [ 41 | 'query' => $filters, 42 | ]); 43 | 44 | $content = $reposonse 45 | ->getBody() 46 | ->getContents(); 47 | 48 | return (array) json_decode($content, true); 49 | } catch (\Exception $e) { 50 | return [ 51 | 'error' => $e->getCode(), 52 | 'message' => $e->getMessage(), 53 | ]; 54 | } 55 | } 56 | 57 | /** 58 | * post data 59 | * 60 | * @param string $endpoint 61 | * @param array $data 62 | * @return array 63 | */ 64 | protected function post(string $endpoint, array $data = []): array 65 | { 66 | try { 67 | $reposonse = $this->client->post($endpoint, [ 68 | 'json' => $data, 69 | ]); 70 | 71 | $content = $reposonse 72 | ->getBody() 73 | ->getContents(); 74 | 75 | return (array) json_decode($content, true); 76 | } catch (\Exception $e) { 77 | return [ 78 | 'error' => $e->getCode(), 79 | 'message' => $e->getMessage(), 80 | ]; 81 | } 82 | } 83 | 84 | /** 85 | * put data 86 | * 87 | * @param string $endpoint 88 | * @param array $data 89 | * @return array 90 | */ 91 | protected function put(string $endpoint, array $data): array 92 | { 93 | try { 94 | $response = $this->client->put($endpoint, [ 95 | 'json' => $data, 96 | ]); 97 | 98 | $content = $response 99 | ->getBody() 100 | ->getContents(); 101 | 102 | return (array) json_decode($content, true); 103 | } catch (\Exception $e) { 104 | return [ 105 | 'error' => $e->getCode(), 106 | 'message' => $e->getMessage(), 107 | ]; 108 | } 109 | } 110 | 111 | /** 112 | * delete data 113 | * 114 | * @param string $endpoint 115 | * @return bool 116 | */ 117 | protected function delete(string $endpoint): bool 118 | { 119 | try { 120 | $response = $this->client->delete($endpoint); 121 | 122 | return ($response->getStatusCode() == 200); 123 | } catch (\Exception $e) { 124 | return false; 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/Gateways/Efi/EfiGateway.php: -------------------------------------------------------------------------------- 1 | $token 24 | */ 25 | private array $token; 26 | 27 | /** 28 | * construct 29 | * 30 | * @param string $clientId 31 | * @param string $clientSecret 32 | * @param bool $sandbox 33 | */ 34 | public function __construct( 35 | private string $clientId, 36 | private string $clientSecret, 37 | private bool $sandbox = true, 38 | ) { 39 | $this->authorization(); 40 | } 41 | 42 | /** 43 | * get token 44 | * 45 | * @return array token 46 | */ 47 | public function getToken(): array 48 | { 49 | return $this->token; 50 | } 51 | 52 | /** 53 | * create charge 54 | * 55 | * @param array $charge 56 | * @return Charge 57 | */ 58 | public function charge(array $charge = []): Charge 59 | { 60 | return new Charge( 61 | $this->token, 62 | $charge, 63 | $this->sandbox 64 | ); 65 | } 66 | 67 | /** 68 | * create customer 69 | * 70 | * @param array $customer 71 | * @return object customer 72 | */ 73 | public function customer(array $customer = []): object 74 | { 75 | return new stdClass(); 76 | } 77 | 78 | /** 79 | * create webhook 80 | * 81 | * @param array $webhook 82 | * @return object webhook 83 | */ 84 | public function webhook(array $webhook = []): object 85 | { 86 | return new stdClass(); 87 | } 88 | 89 | /** 90 | * authorization 91 | * 92 | * @return void 93 | */ 94 | private function authorization(): void 95 | { 96 | $authorization = new Authorization( 97 | $this->clientId, 98 | $this->clientSecret, 99 | $this->sandbox 100 | ); 101 | 102 | $this->token = $authorization->getToken(); 103 | 104 | if (!isset($this->token['access_token'])) { 105 | throw new \Exception('Token not generated'); 106 | } 107 | } 108 | 109 | /** 110 | * create pix 111 | * 112 | * @param array $pix 113 | * @return object pix 114 | */ 115 | public function pix(array $pix = []): object 116 | { 117 | throw new Exception('Not implemented'); 118 | } 119 | 120 | public function subscription(): object 121 | { 122 | throw new Exception('Not implemented'); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/Gateways/Efi/Interface/EfiGatewayInterface.php: -------------------------------------------------------------------------------- 1 | token 14 | */ 15 | public function getToken(): array; 16 | 17 | /** 18 | * create charge 19 | * 20 | * @param array $charge 21 | * @return Charge charge 22 | */ 23 | public function charge(array $charge = []): Charge; 24 | 25 | /** 26 | * get resource customer from gateway. 27 | * 28 | * @param array $pix 29 | * @return object 30 | */ 31 | public function pix(array $pix = []): object; 32 | } 33 | -------------------------------------------------------------------------------- /src/Gateways/Efi/Resources/Authorization/Authorization.php: -------------------------------------------------------------------------------- 1 | 36 | */ 37 | public function getToken(): array 38 | { 39 | $this->client = $this->clientEfiAuthorize($this->clientId, $this->clientSecret); 40 | 41 | /** 42 | * @var array $response 43 | */ 44 | $response = $this->post("v1/authorize", [ 45 | 'grant_type' => 'client_credentials', 46 | ]); 47 | 48 | return $response; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Gateways/Efi/Resources/Authorization/Interface/AuthorizationInterface.php: -------------------------------------------------------------------------------- 1 | 23 | */ 24 | private array $customer; 25 | 26 | /** 27 | * @var array 28 | */ 29 | private array $items = []; 30 | 31 | /** 32 | * @var array 33 | */ 34 | private array $queryParams = []; 35 | 36 | /** 37 | * @var array 38 | */ 39 | private array $configuration = []; 40 | 41 | /** 42 | * construct 43 | * 44 | * @param array $token 45 | * @param array $charge 46 | * @param bool $sandbox 47 | */ 48 | public function __construct( 49 | array $token, 50 | private array $charge = [], 51 | private bool $sandbox = true, 52 | ) { 53 | $this->client = $this->clientEfiBoot( 54 | $token['access_token'], 55 | $token['token_type'] 56 | ); 57 | 58 | if (!empty($charge)) { 59 | $this->charge = $charge; 60 | } 61 | } 62 | 63 | /** 64 | * set customer 65 | * 66 | * @param array $customer 67 | * @return Charge 68 | */ 69 | public function setCustomer(array $customer): Charge 70 | { 71 | $this->customer = $this->bootCustomer($customer); 72 | 73 | return $this; 74 | } 75 | 76 | /** 77 | * set filters 78 | * 79 | * @param array $queryParams 80 | * @return ChargeInterface 81 | */ 82 | public function setQueryParams(array $queryParams): ChargeInterface 83 | { 84 | $this->queryParams = $queryParams; 85 | 86 | return $this; 87 | } 88 | 89 | /** 90 | * find all charges 91 | * 92 | * @return array 93 | */ 94 | public function getAll(): array 95 | { 96 | if (empty($this->queryParams)) { 97 | $this->setQueryParams([ 98 | 'charge_type' => 'billet', 99 | 'begin_date' => date('Y-m-d', strtotime('-30 days')), 100 | 'end_date' => date('Y-m-d'), 101 | 'status' => 'unpaid', 102 | ]); 103 | } 104 | 105 | return $this->get('v1/charges', $this->queryParams); 106 | } 107 | 108 | /** 109 | * find charge by id 110 | * 111 | * @return array 112 | */ 113 | public function find(string $id): array 114 | { 115 | return $this->get("v1/charge/{$id}"); 116 | } 117 | 118 | /** 119 | * create charge 120 | * 121 | * @return array 122 | * @see fields available in https://docs.Efi.com/reference/criar-nova-cobranca 123 | */ 124 | public function create(): array 125 | { 126 | // EfiChargeRequest::validate($this->charge); 127 | 128 | $items = $this->getItems(); 129 | $configurations = $this->getConfigurations(); 130 | 131 | return $this->post('v1/charge/one-step', [ 132 | 'items' => $items, 133 | 'payment' => [ 134 | 'banking_billet' => [ 135 | 'expire_at' => $this->charge['expire_at'], 136 | 'customer' => $this->customer, 137 | 'configurations' => $configurations, 138 | ], 139 | ], 140 | ]); 141 | } 142 | 143 | /** 144 | * update billet metadata 145 | * notification_url and custom_id 146 | * 147 | * @param string $id 148 | * @param array $data 149 | * @return array 150 | */ 151 | public function updateMetadata(string $id, array $data): array 152 | { 153 | return $this->put("v1/charge/{$id}/metadata", $data); 154 | } 155 | 156 | /** 157 | * cancel charge 158 | * 159 | * @param string $id 160 | * @return array 161 | */ 162 | public function cancel(string $id): array 163 | { 164 | return $this->put("v1/charge/{$id}/cancel", []); 165 | } 166 | 167 | /** 168 | * update due date 169 | * 170 | * @param string $id 171 | * @param string $dueDate 172 | * @return array 173 | */ 174 | public function updateDueDate(string $id, string $dueDate): array 175 | { 176 | return $this->put("v1/charge/{$id}/billet", [ 177 | 'expire_at' => $dueDate, 178 | ]); 179 | } 180 | 181 | /** 182 | * get status charge 183 | * 184 | * @param string $id 185 | * @return array 186 | */ 187 | public function getStatus(string $id): array 188 | { 189 | return $this->get("payments/{$id}/status"); 190 | } 191 | 192 | /** 193 | * confirm receipt 194 | * 195 | * @param string $id 196 | * @return array 197 | */ 198 | public function confirmReceipt(string $id): array 199 | { 200 | return $this->put("v1/charge/{$id}/settle", []); 201 | } 202 | 203 | /** 204 | * get items 205 | * 206 | * @return array 207 | */ 208 | private function getItems(): array 209 | { 210 | $items = $this->items; 211 | 212 | if (empty($this->items)) { 213 | $items[] = [ 214 | 'name' => $this->charge['description'], 215 | 'value' => $this->charge['value'], 216 | ]; 217 | 218 | unset($this->charge['description']); 219 | unset($this->charge['value']); 220 | } 221 | 222 | return $items; 223 | } 224 | 225 | /** 226 | * get configuration 227 | * 228 | * @return array 229 | */ 230 | private function getConfigurations(): array 231 | { 232 | $configurations = $this->configuration; 233 | 234 | if (empty($configurations)) { 235 | $configurations = [ 236 | 'fine' => 200, 237 | 'interest' => 33, 238 | ]; 239 | } 240 | 241 | return $configurations; 242 | } 243 | 244 | /** 245 | * boot customer 246 | * 247 | * @param array $customer 248 | * @return array 249 | */ 250 | private function bootCustomer(array $customer): array 251 | { 252 | if (!isset($customer['name'])) { 253 | throw new \Exception('Efí: Nome é obrigatório'); 254 | } 255 | 256 | if (!isset($customer['cpf_cnpj'])) { 257 | throw new \Exception('Efí: CPF/CNPJ é obrigatório'); 258 | } 259 | 260 | $isFiscalPerson = (strlen($customer['cpf_cnpj']) === 11); 261 | 262 | if ($isFiscalPerson) { 263 | $customerMounted = [ 264 | 'name' => $customer['name'], 265 | 'cpf' => $customer['cpf_cnpj'], 266 | ]; 267 | } else { 268 | $customerMounted = [ 269 | 'juridical_person' => [ 270 | 'corporate_name' => $customer['name'], 271 | 'cnpj' => $customer['cpf_cnpj'], 272 | ], 273 | ]; 274 | } 275 | 276 | if (array_key_exists('email', $customer)) { 277 | $customerMounted['email'] = $customer['email']; 278 | } 279 | 280 | if (array_key_exists('phone_number', $customer)) { 281 | $customerMounted['phone_number'] = $customer['phone_number']; 282 | } 283 | 284 | return $customerMounted; 285 | } 286 | } 287 | -------------------------------------------------------------------------------- /src/Gateways/Efi/Resources/Charge/Interface/ChargeInterface.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | public function getAll(): array; 15 | 16 | /** 17 | * find charge by id 18 | * 19 | * @param string $id 20 | * @return array 21 | */ 22 | public function find(string $id): array; 23 | 24 | /** 25 | * set customer 26 | * 27 | * @param array $customer 28 | * @return Charge 29 | */ 30 | public function setCustomer(array $customer): Charge; 31 | 32 | /** 33 | * set query params 34 | * 35 | * @param array $queryParams 36 | * @return ChargeInterface 37 | */ 38 | public function setQueryParams(array $queryParams): ChargeInterface; 39 | 40 | /** 41 | * @param string $id 42 | * @return array 43 | */ 44 | public function confirmReceipt(string $id): array; 45 | 46 | /** 47 | * cancel charge by id 48 | * 49 | * @param string $id 50 | * @return array 51 | */ 52 | public function cancel(string $id): array; 53 | 54 | /** 55 | * @param string $id 56 | * @param string $dueDate 57 | * @return array 58 | */ 59 | public function updateDueDate(string $id, string $dueDate): array; 60 | 61 | /** 62 | * update billet metadata 63 | * notification_url and custom_id 64 | * 65 | * @param string $id 66 | * @param array $data 67 | * @return array 68 | */ 69 | public function updateMetadata(string $id, array $data): array; 70 | } 71 | -------------------------------------------------------------------------------- /src/Gateways/Efi/Traits/HasEfiClient.php: -------------------------------------------------------------------------------- 1 | sandbox ? 21 | 'https://cobrancas-h.api.efipay.com.br/' : 22 | 'https://cobrancas.api.efipay.com.br/'; 23 | 24 | return new Client([ 25 | 'base_uri' => $baseUrl, 26 | 'headers' => [ 27 | 'Authorization' => 'Basic ' . base64_encode("{$clientId}:{$clientSecret}"), 28 | 'content-type' => 'application/json', 29 | ], 30 | ]); 31 | } 32 | 33 | /** 34 | * boot client 35 | * 36 | * @param string $token 37 | * @param string $type 38 | * @return Client 39 | */ 40 | protected function clientEfiBoot(string $token, string $type): Client 41 | { 42 | $baseUrl = $this->sandbox ? 43 | 'https://cobrancas-h.api.efipay.com.br/' : 44 | 'https://cobrancas.api.efipay.com.br/'; 45 | 46 | return new Client([ 47 | 'base_uri' => $baseUrl, 48 | 'headers' => [ 49 | 'Authorization' => "{$type} {$token}", 50 | 'content-type' => 'application/json', 51 | ], 52 | ]); 53 | } 54 | 55 | /** 56 | * get data 57 | * 58 | * @param string $endpoint 59 | * @param array $filters 60 | * @return array 61 | */ 62 | protected function get(string $endpoint, array $filters = []): array 63 | { 64 | try { 65 | $reposonse = $this->client->get($endpoint, [ 66 | 'query' => $filters, 67 | ]); 68 | 69 | $content = $reposonse 70 | ->getBody() 71 | ->getContents(); 72 | 73 | return (array) json_decode($content, true); 74 | } catch (\Exception $e) { 75 | return [ 76 | 'error' => $e->getCode(), 77 | 'message' => $e->getMessage(), 78 | ]; 79 | } 80 | } 81 | 82 | /** 83 | * post data 84 | * 85 | * @param string $endpoint 86 | * @param array $data 87 | * @return array 88 | */ 89 | protected function post(string $endpoint, array $data = []): array 90 | { 91 | try { 92 | $reposonse = $this->client->post($endpoint, [ 93 | 'json' => $data, 94 | ]); 95 | 96 | $content = $reposonse 97 | ->getBody() 98 | ->getContents(); 99 | 100 | return (array) json_decode($content, true); 101 | } catch (\Exception $e) { 102 | return [ 103 | 'error' => $e->getCode(), 104 | 'message' => $e->getMessage(), 105 | ]; 106 | } 107 | } 108 | 109 | /** 110 | * put data 111 | * 112 | * @param string $endpoint 113 | * @param array $data 114 | * @return array 115 | */ 116 | protected function put(string $endpoint, array $data): array 117 | { 118 | try { 119 | $response = $this->client->put($endpoint, [ 120 | 'json' => $data, 121 | ]); 122 | 123 | $content = $response 124 | ->getBody() 125 | ->getContents(); 126 | 127 | return (array) json_decode($content, true); 128 | } catch (\Exception $e) { 129 | return [ 130 | 'error' => $e->getCode(), 131 | 'message' => $e->getMessage(), 132 | ]; 133 | } 134 | } 135 | 136 | /** 137 | * delete data 138 | * 139 | * @param string $endpoint 140 | * @return bool 141 | */ 142 | protected function delete(string $endpoint): bool 143 | { 144 | try { 145 | $response = $this->client->delete($endpoint); 146 | 147 | return ($response->getStatusCode() == 200); 148 | } catch (\Exception $e) { 149 | return false; 150 | } 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /src/PHPay.php: -------------------------------------------------------------------------------- 1 | gateway = $gateway; 18 | } 19 | 20 | /** 21 | * instance of PHPay. 22 | * 23 | * @param GatewayInterface $gateway 24 | * @return PHPay 25 | */ 26 | public static function gateway(GatewayInterface $gateway): PHPay 27 | { 28 | return new PHPay($gateway); 29 | } 30 | 31 | /** 32 | * get resource customer from gateway. 33 | * 34 | * @param array $customer 35 | * @return object 36 | */ 37 | public function customer(array $customer = []): object 38 | { 39 | return $this->gateway->customer($customer); 40 | } 41 | 42 | /** 43 | * get resource charge from gateway. 44 | * 45 | * @return object 46 | */ 47 | public function charge(): object 48 | { 49 | return $this->gateway->charge(); 50 | } 51 | 52 | /** 53 | * get resource webhook from gateway. 54 | * 55 | * @param array $webhook 56 | * @return object 57 | */ 58 | public function webhook(array $webhook = []): object 59 | { 60 | return $this->gateway->webhook($webhook); 61 | } 62 | 63 | /** 64 | * get resource pix from gateway. 65 | * 66 | * @param array $pix 67 | * @return object 68 | */ 69 | public function pix(array $pix = []): object 70 | { 71 | return $this->gateway->pix($pix); 72 | } 73 | 74 | /** 75 | * get resource subscription from gateway. 76 | * 77 | * @return object 78 | */ 79 | public function subscription(): object 80 | { 81 | return $this->gateway->subscription(); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /tests/AsaasGatewayTest.php: -------------------------------------------------------------------------------- 1 | toBe(true); 9 | 10 | expect($asaas) 11 | ->toImplement(\PHPay\Contracts\GatewayInterface::class); 12 | 13 | expect($asaas) 14 | ->toImplement(\PHPay\Asaas\Interface\AsaasGatewayInterface::class); 15 | 16 | $assasInstance = new $phpay(new $asaas('token-here')); 17 | 18 | expect($assasInstance->customer([])) 19 | ->toBeObject() 20 | ->toBeInstanceOf(\PHPay\Asaas\Resources\Customer\Customer::class); 21 | 22 | expect($assasInstance->charge()) 23 | ->toBeObject() 24 | ->toBeInstanceOf(\PHPay\Asaas\Resources\Charge\Charge::class); 25 | 26 | expect($assasInstance->webhook()) 27 | ->toBeObject() 28 | ->toBeInstanceOf(\PHPay\Asaas\Resources\Webhook\Webhook::class); 29 | })->group('asaas'); 30 | -------------------------------------------------------------------------------- /tests/EfiGatewayTest.php: -------------------------------------------------------------------------------- 1 | toBe(true); 8 | 9 | expect($efi) 10 | ->toImplement(\PHPay\Contracts\GatewayInterface::class); 11 | 12 | expect($efi) 13 | ->toImplement(\Efi\Interface\EfiGatewayInterface::class); 14 | })->group('efi'); 15 | -------------------------------------------------------------------------------- /tests/PHPayTest.php: -------------------------------------------------------------------------------- 1 | toBe(true); 10 | 11 | expect($phpay) 12 | ->toImplement(\PHPay\Contracts\GatewayInterface::class); 13 | 14 | expect($phpay)->hasMethod('__construct'); 15 | expect($phpay)->hasMethod('customer'); 16 | expect($phpay)->hasMethod('charge'); 17 | expect($phpay)->hasMethod('webhook'); 18 | expect($phpay)->hasMethod('pix'); 19 | })->group('phpay'); 20 | -------------------------------------------------------------------------------- /tests/Pest.php: -------------------------------------------------------------------------------- 1 | extend(Tests\TestCase::class)->in('Feature'); 15 | 16 | /* 17 | |-------------------------------------------------------------------------- 18 | | Expectations 19 | |-------------------------------------------------------------------------- 20 | | 21 | | When you're writing tests, you often need to check that values meet certain conditions. The 22 | | "expect()" function gives you access to a set of "expectations" methods that you can use 23 | | to assert different things. Of course, you may extend the Expectation API at any time. 24 | | 25 | */ 26 | 27 | // expect()->extend('toBeOne', function () { 28 | // return $this->toBe(1); 29 | // }); 30 | 31 | /* 32 | |-------------------------------------------------------------------------- 33 | | Functions 34 | |-------------------------------------------------------------------------- 35 | | 36 | | While Pest is very powerful out-of-the-box, you may have some testing code specific to your 37 | | project that you don't want to repeat in every file. Here you can also expose helpers as 38 | | global functions to help you to reduce the number of lines of code in your test files. 39 | | 40 | */ 41 | 42 | // function something() 43 | // { 44 | // } 45 | -------------------------------------------------------------------------------- /tests/TestCase.php: -------------------------------------------------------------------------------- 1 |