junopy

SDK Python3 para Integração com Juno API V2


Keywords
juno, pagamento, cartão, de, crédito, boleto, pix, pagamentos, transações, payment, payments, credit-card
License
MIT
Install
pip install junopy==0.0.7

Documentation

SDK Python3 para Integração com Juno

Esta SDK foi desenvolvida para abstrair aos desenvolvedores os principais detalhes da comunicação com API v2 da Juno tanto em produção quanto em ambiente sandbox.

Você pode acessar a documentação base da api aqui: Api V2 Juno.

Licença image image image image image image

Instalação

Instalação utilizando Pip

pip install junopy

Git/Clone

git clone https://github.com/robertons/junopy
cd junopy
pip install -r requirements.txt
python setup.py install

Objetos

Os objetos neste SDK podem ser criados em 3 (três) formas distintas a critério do utilizador.

Criação

Método 1 - Construção

objeto = Objeto(campo1 = 'valor', campo2 = 'valor 2', campo_datetime = datetime.now(), campo_float = 10.1)

Método 2 - Construção com Dicionário

objeto = Objeto(**{'campo1':'valor', 'campo2':'valor 2', 'campo_datetime':datetime.now(), 'campo_float' = 10.1})

Método 3 - Pós-Construção

objeto = Objeto()
objeto.campo1 = 'valor'
objeto.campo2 = 'valor 2'
objeto.campo_datetime = datetime.now()
objeto.campo_float = 10.1

Método toJSON

Método toJSON() retorna os dados do Objeto em formato diciciontario não codificados.

objeto = Objeto(...)
print(objeto.toJSON())

Configuração Inicial

posição campo obrigatório padrão descrição
1 private_token sim Token Privado Juno
2 clientId sim Id Cliente
3 clientSecret sim Chave Cliente
4 sandbox não False Ambiente Produção/Sandbox
5 debug não False Depuração Request Post, Get, Put, Patch e Delete
import junopy

junopy.Juno('PRIVATE_TOKEN', 'CLIENT_ID', 'CLIENT_SECRET', sandbox=True)

Obtenção de TOKEN

Cada token com permissão de acesso ao servidor de serviço tem validade de 1 hora, a recomendação da Juno é que um novo Token seja gerado apenas em caso de expiração. A instancia gerada administra isso automaticamente, contudo a função GetToken permite obter o token para que os dados sejam utilizado em outras instâncias. Este processo não é obrigatório, mas é recomendável principalmente em sistemas onde serão criadas novas instâncias junopy a cada transação

Mais detalhes em Documentação Oficial

import junopy

junopy.Juno('PRIVATE_TOKEN', 'CLIENT_ID', 'CLIENT_SECRET')
junopy.GetToken()
token_valido_1h = junopy.TOKEN

Definição Token de Acesso - Usando dados gerados anteriormente

É possível definir manualmente os dados de acesso através da função SetToken

import junopy

junopy.Juno('PRIVATE_TOKEN', 'CLIENT_ID', 'CLIENT_SECRET')
junopy.SetToken('access_token', 'token_type', 'expires')

Utilidades

Lista de Bancos

bancos = junopy.util.Banks()

Lista de Tipos de Empresas

tipos_empresas = junopy.util.CompanyTypes()

Tipos de Negócios

tipos_empresas = junopy.util.BusinessAreas()

Chave Publica de Criptografia

chave_publica = junopy.util.PublicKey()

Validação Webhook

Todo Webhook recebido da Juno traz consigo uma assinatura no header da Requisição Post. A assinatura é um hash para validar a autenticidade do conteúdo.

Ao criar um Webhook é gerado uma chave que deve ser armazenada em segurança e utilizada neste processo.

Leia atentamente como funciona o processo em Criação e Assinatura de Webhook

campo tipo obrigatório
x_signature string sim
body_content bytes sim
secret string sim

o retorno da função será True ou False

webhook_valido = junopy.util.IsValidWebhook(x_signature, body_content, secret)

Conta Digital

A seção compreende:

  • Criação de contas digitais
  • Consulta de contas digital
  • Alteração de dados da conta digital

Mais detalhes em Documentação Oficial

Criação

No exemplo abaixo foram utilizados os 3 métodos de criação de objeto de formas distintas:

Após o preenchimento do Objeto o comando Create, realiza o Post na ApiV2.

	conta = junopy.DigitalAccount()
    conta.name = "Usuário Teste"
    conta.document = "123.456.789-00"
    conta.email = "usu.teste@email.com"
    conta.birthDate = "1980-01-01" #
    conta.phone = "9999999999"
    conta.businessArea = 2015
    conta.linesOfBusiness = "INDIVIDUAL"

    conta.address = junopy.Address(**{
    		'street': 'Nome da Rua',
    		'number': '01',
    		'complement': 'Casa',
    		'neighborhood': 'Bairro',
    		'city': 'Cidade',
    		'state': 'UF',
    		'postCode': '99999999'
    })

    conta_bancaria =  junopy.BankAccount()
    conta_bancaria.bankNumber = "000"
    conta_bancaria.agencyNumber = "1111"
    conta_bancaria.accountNumber = "22334455"
    conta_bancaria.accountComplementNumber = "0"
    conta_bancaria.accountType = "CHECKING"
    conta_bancaria.accountHolder = junopy.AccountHolder(name='Usuario Teste', document='00000000000')
    conta.bankAccount = conta_bancaria

    conta.Create()

Consulta

	conta = junopy.DigitalAccount(id='dac_E6FECDB17EAC5992').Get()

** Consulta de conta digital criada a partir do token privado da conta digital**

	conta_digital_criada = junopy.DigitalAccount(id='dac_E6FECDB17EAC5992', resourceToken='8A596ED1DEB738091FDE8AF11CCD6E7730970A95503AB32CEA340FAB190139C9').Get()

Atualização

	conta = junopy.DigitalAccount()
	conta.id = "dac_E6FECDB17EAC5992"
	conta.resourceToken = '8A596ED1DEB738091FDE8AF11CCD6E7730970A95503AB32CEA340FAB190139C9'
	conta.address = junopy.Address(
    		street = 'Nome da Rua',
    		number = '01',
    		complement = 'Casa',
    		neighborhood = 'Bairro',
    		city = 'Cidade',
    		state = 'UF',
    		postCode = '99999999'
    })
	conta.Update()

Soluções Whitelabel

Mais detalhes em Documentação Oficial

Novo Onboarding - Somente Envio de Documentos

onboarding = junopy.onboarding.Documents(
        returnUrl="https://www.website.com.br/documents",
        refreshUrl="https://www.website.com.br/invalid")

Novo Onboarding - Solução Completa Conta e Envio de Documentos

onboarding = junopy.onboarding.Account(
        referenceId='id_proprio',
        returnUrl="https://www.website.com.br/documents",
        refreshUrl="https://www.website.com.br/invalid"
    )

Documentos

Mais detalhes em Documentação Oficial

Consulta

documentos_esperados = junopy.Document(id='dac_E6FECDB17EAC5993').Get()

Consulta de outra Conta Digital (Resource)

documentos_esperados = junopy.Document(id='dac_E6FECDB17EAC5992', resourceToken='8A596ED1DEB738091FDE8AF11CCD6E7730970A95503AB32CEA340FAB190139C9').Get()

Lista Documentos

documentos_esperados = junopy.Document().Get()

Lista Documentos de outra Conta Digital (Resource)

documentos_esperados = junopy.Document(resourceToken='8A596ED1DEB738091FDE8AF11CCD6E7730970A95503AB32CEA340FAB190139C9').Get()

Envio de Documentos/Arquivos

Método path do arquivo Uma array de string contendo o caminho local do arquivo

documentos_esperados = junopy.Document(
        id='doc_AD1E698AB61CF185',
        resourceToken='8A596ED1DEB738091FDE8AF11CCD6E7730970A95503AB32CEA340FAB190139C9').SendFiles(['arquivo_1.pdf', 'arquivo_2.pdf'])

Método BufferedReader do arquivo Uma array com tuplas onde posição 0 é o nome do arquivo e posição 1 os BufferedReader

documentos_esperados = junopy.Document(
        id='doc_AD1E698AB61CF185', resourceToken='8A596ED1DEB738091FDE8AF11CCD6E7730970A95503AB32CEA340FAB190139C9').SendFiles([('arquivo_1.pdf', file_buffered)])

Método bytes do arquivo Uma array com tuplas onde posição 0 é o nome do arquivo e posição 1 os bytes

documentos_esperados = junopy.Document(
        id='doc_AD1E698AB61CF185', resourceToken='8A596ED1DEB738091FDE8AF11CCD6E7730970A95503AB32CEA340FAB190139C9').SendFiles([('arquivo_1.pdf', file_bytes)])

Saldo

Mais detalhes em Documentação Oficial

import junopy

junopy.Juno('PRIVATE_TOKEN', 'CLIENT_ID', 'CLIENT_SECRET')
saldo = junopy.Balance()

{'balance': 0.0, 'withheldBalance': 0.0, 'transferableBalance': 0.0}

ou de outra conta digital

import junopy

junopy.Juno('PRIVATE_TOKEN', 'CLIENT_ID', 'CLIENT_SECRET')
saldo = junopy.Balance(resourceToken = '8A596ED1DEB738091FDE8AF11CCD6E7730970A95503AB32CEA340FAB190139C9')

Transferência

Mais detalhes em Documentação Oficial

Conta Bancária Padrão

import junopy

junopy.Juno('PRIVATE_TOKEN', 'CLIENT_ID', 'CLIENT_SECRET')
transfer = junopy.transfers.Default(100.0)

Transferência P2P

import junopy

junopy.Juno('PRIVATE_TOKEN', 'CLIENT_ID', 'CLIENT_SECRET')
#P2P(name:str, document:str, amount:float, accountNumber:str)
transfer = junopy.transfers.P2P('Nome', 'CPF/CNPJ', 100.0, 'NUMERO_CONTA_2P')

Transferência Bancária

import junopy

junopy.Juno('PRIVATE_TOKEN', 'CLIENT_ID', 'CLIENT_SECRET')
#Bank(name:str, document:str, amount:float, bank:BankAccount)

conta_bancaria =  junopy.BankAccount()
conta_bancaria.bankNumber = "000"
conta_bancaria.agencyNumber = "1111"
conta_bancaria.accountNumber = "22334455"
conta_bancaria.accountComplementNumber = "0"
conta_bancaria.accountType = "CHECKING"
transfer = junopy.transfers.Bank('Nome', 'CPF/CNPJ', 100.0, conta_bancaria)

Transferência PIX

import junopy

junopy.Juno('PRIVATE_TOKEN', 'CLIENT_ID', 'CLIENT_SECRET')
#Pix(name:str, document:str, amount:float, bank:BankAccount)
transfer = junopy.transfers.Pix('Nome', 'CPF/CNPJ', 100.0, junopy.BankAccount(
	ispb='0000000',
	bankNumber="000",
	agencyNumber="1111",
	accountNumber="22334455",
	accountComplementNumber="0",
	accountType="SAVINGS"
}))

Notificações

Mais detalhes em Documentação Oficial

Listar Tipos de Eventos

Retorna uma lista de objetos EventType

Tipo de Evento Descrição
DIGITAL_ACCOUNT_STATUS_CHANGED Mudanças de status de uma conta digital
DIGITAL_ACCOUNT_CREATED Confirmação de criação de uma conta digital - Válido somente para a solução Whitelabel
DOCUMENT_STATUS_CHANGED Mudanças de status de um documento da conta digital
TRANSFER_STATUS_CHANGED Mudanças de status de uma transferência
P2P_TRANSFER_STATUS_CHANGED Mudanças de status de uma transferência P2P
CHARGE_STATUS_CHANGED Mudanças de status de uma cobrança emitida
CHARGE_READ_CONFIRMATION Confirmação de leitura/visualização de uma cobrança
PAYMENT_NOTIFICATION Pagamento de uma cobranças
import junopy
events = junopy.EventTypes()

Webhooks

Mais detalhes em Documentação Oficial

Criação

Cria e retorna um objeto Webhook

import junopy

junopy.Juno('PRIVATE_TOKEN', 'CLIENT_ID', 'CLIENT_SECRET')
#Webhook().Create(url:str, eventTypes:list)
webhook = junopy.Webhook().Create("https://url.segura_recebe_notificacao.com", ["DIGITAL_ACCOUNT_CREATED", "DIGITAL_ACCOUNT_STATUS_CHANGED"])

Listar webhooks

webhooks = junopy.Webhooks()

Consultar Webhooks

webhooks = junopy.Webhook(id='wbh_6D7EF263A2755055').Get()

Atualizar Webhooks

#Webhook().Update(status:str, eventTypes:list)
webhook = junopy.Webhook(id='wbh_6D7EF263A2755055').Update("INACTIVE", ["DIGITAL_ACCOUNT_CREATED", "DIGITAL_ACCOUNT_STATUS_CHANGED"])

Excluir Webhooks

webhook = junopy.Webhook(id='wbh_6D7EF263A2755055').Delete()

Cobranças

Mais detalhes em Documentação Oficial

Criar Cobrança

cobranca = junopy.charges.Create(
            junopy.Charge(
                description = 'Cobrança Teste',
                amount = 10.0,
                paymentTypes = ['BOLETO', 'CREDIT_CARD']
            ),
            junopy.Billing(
                name = 'Nome do Usuário',
                document = 'CPF',
                email = 'email',
                address = junopy.Address(
                    street= 'Rua',
            		number='Numero',
            		complement='Complemento',
            		neighborhood='Bairro',
            		city='Cidade',
            		state='UF',
            		postCode='99999999'
                ),
                phone = '99999199999',
                notify = False
            )
        )

O Retorno será uma lista objeto ChargeResource

Listar Cobrança

É possível realizar buscas utilizando filtros, veja na documentação oficial: (Documentação)

Devolve 20 cobranças por páginas, podendo ser estendido até 100 páginas com pageSize=100.

busca = junopy.charges.Search()

ou

busca = junopy.charges.Search(pageSize=100)

ou

busca = junopy.charges.Search(createdOnStart='2021-07-10')

A partir da primeira busca é possível navegar pelas páginas superiores/inferiores através dos métodos Next e Previous

Para avançar:

proxima = junopy.charges.Next()

Para voltar:

anterior = junopy.charges.Previous()

Consultar Cobrança

cobranca = junopy.charges.Get(id="chr_8C87D875719FE478195F5AE32309F77B")

Cancelar Cobrança

junopy.charges.Cancel(id="chr_8C87D875719FE478195F5AE32309F77B")

Atualizar Split

junopy.charges.SetSplit(id="chr_8C87D875719FE478195F5AE32309F77B", split=[
        junopy.Split(
            recipientToken = "Token",
            amount = 10.0,
            amountRemainder = True,
            chargeFee= True),
        junopy.Split(
            recipientToken = "Token2",
            amount = 10.0,
            amountRemainder = False,
            chargeFee= True)
        ])

Checkout Transparente

Tokenizar Cartão

Mais detalhes em Documentação Oficial

cartao_credito = junopy.creditcard.Tokenize(hash="0210da66-6c54-4f3b-9e95-9e044be38d79")

Checkout Transparente

Mais detalhes em Documentação Oficial

    # CRIAÇÃO DE COBRANÇA
    cobranca = junopy.charges.Create(
            junopy.Charge(
                description = 'Produto Exemplo',
                amount = 340.0,
                paymentTypes = ['CREDIT_CARD']
            ),
            junopy.Billing(
                name = 'Usuario Teste',
                document = 'cpf',
                email = 'usuario@email.com.br',
                address = junopy.Address(
                    		street = 'Endereco',
                    		number = 'Numero',
                    		complement = 'Complemento',
                    		neighborhood = 'Bairro',
                    		city = 'Cidade',
                    		state = 'UF',
                    		postCode = '99999999'),
                phone = '99999999999',
                notify = False
            )
        )

    # PROCESSAMENTO DE PAGAMENTO
    if len(cobranca) > 0:
        pagamento = junopy.payment.Create(
            chargeId = cobranca[0].id,
            creditcard =  junopy.CreditCard(
                    creditCardId = '9a453d71-3ec1-44a5-b2f3-0596ced42a35'
                ),
            billing = junopy.Billing(
                    name = 'Usuario Teste',
                    email = 'usuario@email.com.br',
                    address = junopy.Address(
                    		street = 'Endereco',
                    		number = 'Numero',
                    		complement = 'Complemento',
                    		neighborhood = 'Bairro',
                    		city = 'Cidade',
                    		state = 'UF',
                    		postCode = '99999999'),
                    delayed = False
                )
        )

Estornar transações de cartão de crédito

Mais detalhes em Documentação Oficial

Integral

 estorno = junopy.payment.Refund(paymentId='pay_BDBBF5F40B8B94F23DB2117904EB4B08')

Parcial

estorno = junopy.payment.Refund(paymentId='pay_BDBBF5F40B8B94F23DB2117904EB4B08', amount=40.00)

Split

estorno = junopy.payment.Refund(paymentId='pay_BDBBF5F40B8B94F23DB2117904EB4B08', amount=40.00, split=[
		junopy.Split(
            recipientToken="Token",
            amount=10.0,
            amountRemainder=True,
            chargeFee=True),
        junopy.Split(
            recipientToken="Token2",
            amount=10.0,
            amountRemainder=False,
            chargeFee=True)])

Capturar pagamento de cartão de crédito

Mais detalhes em Documentação Oficial

Integral

 captura = junopy.payment.Capture(paymentId='pay_BDBBF5F40B8B94F23DB2117904EB4B08')

Parcial

captura = junopy.payment.Capture(paymentId='pay_BDBBF5F40B8B94F23DB2117904EB4B08', amount=100.00)

Planos e Assinaturas

Planos

Criar Plano

plano = junopy.Plan(name="Plano Teste", amount=100.00).Create()

Consultar Plano

plano = junopy.Plan(id='pln_76A6AC4929EF068B').Get()

Listar Plano

planos = junopy.Plan().Get()

Desativar Plano

plano = junopy.Plan(id='pln_76A6AC4929EF068B').Deactivate()

Reativar Plano

plano = junopy.Plan(id='pln_76A6AC4929EF068B').Reactivate()

Assinaturas

Criar Assinatura

assinatura = junopy.Subscription(
        dueDay=10,
        planId='pln_76A6AC4929EF068B',
        chargeDescription='Assinatura Recorrente Plano de Teste',
        creditCardDetails=junopy.CreditCard(
            creditCardId='9a453d71-3ec1-44a5-b2f3-0596ced42a35'
        ),
        billing=junopy.Billing(
            name='Usuario Teste',
            document='cpf',
            email='usuario@email.com.br',
            address=junopy.Address(
                street='Rua',
                number='numero',
                complement='completemento',
                neighborhood='bairro',
                city='cidade',
                state='UF',
                postCode='99999999')),
            notify=False
    ).Create()

Consultar Assinatura

assinatura = junopy.Subscription(id='sub_EDA3F6CA13DFEC4C').Get()

Listar Assinaturas

assinaturas = junopy.Subscription().Get()

Desativar Assinatura

assinatura = junopy.Subscription(id='sub_EDA3F6CA13DFEC4C').Deactivate()

Reativar Assinatura

assinatura = junopy.Subscription(id='sub_EDA3F6CA13DFEC4C').Reactivate()

Cancelar Assinatura

assinatura = junopy.Subscription(id='sub_EDA3F6CA13DFEC4C').Cancel()

Completar Assinatura

assinatura = junopy.Subscription(id='sub_EDA3F6CA13DFEC4C').Complete()

Pagar Contas

pagamento_conta = junopy.Bill(
        numericalBarCode="00190500954014481606906809350314337370000001000",
        paymentDescription="Boleto Bancário",
        beneficiaryDocument="CPF/CNPJ",
        dueDate="2021-07-12",
        paymentDate="yyyy-MM-dd",
        billAmount=10.00,
        paidAmount=10.00,
    ).Create()

PIX

Gerar Chave ( Pix Keys)

# CHAVE GERADA UMA ÚNICA VEZ
uudi = str(uuid.uuid4())
pix = junopy.pix.Keys(idempotency=uudi)

OBTER QR CODE ESTÁTICO

pix = junopy.pix.StaticQRCode(
        idempotency='d63313cd-d01a-4091-b352-182a0a96baca',
        key='06c4e6fe-48cb-4263-89a3-c8bc342ce65e',
        includeImage=True,
        amount=100.00,
        reference='Teste de Pix',
        additionalData='Teste de Pix com Dados Adicionais')

PicPay

EM DESENVOLVIMENTO

Suporte Oficial da Juno

Em caso de dúvidas, problemas ou sugestões: falecom@juno.com.br

Change log

Veja em CHANGELOG para maiores informações sobre as mudanças recentes

Contribuições

As contribuições por meio de Pull Requests são bem-vindas e serão totalmente creditadas.

Segurança

Se você descobrir qualquer problema relacionado à segurança, envie um e-mail para robertonsilva@gmail.com

Créditos

Licença

Veja em LICENÇA para maiores informações sobre a licença de uso.