Package: junopy
SDK Python3 para Integração com JunoEsta SDK foi desenvolvida para abstrair aos desenvolvedores os principais detalhes da comunicação com API v2 da Juno tanto emproduçãoquanto em ambientesandbox.Você pode acessar a documentação base da api aqui:Api V2 Juno.InstalaçãoInstalação utilizando PippipinstalljunopyGit/Clonegit clone https://github.com/robertons/junopy
cd junopy
pip install -r requirements.txt
python setup.py installObjetosOs objetos neste SDK podem ser criados em 3 (três) formas distintas a critério do utilizador.CriaçãoMétodo 1 - Construçãoobjeto=Objeto(campo1='valor',campo2='valor 2',campo_datetime=datetime.now(),campo_float=10.1)Método 2 - Construção com Dicionárioobjeto=Objeto(**{'campo1':'valor','campo2':'valor 2','campo_datetime':datetime.now(),'campo_float'=10.1})Método 3 - Pós-Construçãoobjeto=Objeto()objeto.campo1='valor'objeto.campo2='valor 2'objeto.campo_datetime=datetime.now()objeto.campo_float=10.1Método toJSONMétodo toJSON() retorna os dados do Objeto em formatodiciciontarionão codificados.objeto=Objeto(...)print(objeto.toJSON())Configuração Inicialposiçãocampoobrigatóriopadrãodescrição1private_tokensimToken Privado Juno2clientIdsimId Cliente3clientSecretsimChave Cliente4sandboxnãoFalseAmbiente Produção/Sandbox5debugnãoFalseDepuração Request Post, Get, Put, Patch e Deleteimportjunopyjunopy.Juno('PRIVATE_TOKEN','CLIENT_ID','CLIENT_SECRET',sandbox=True)Obtenção de TOKENCada 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çãoGetTokenpermite obter o token para que os dados sejam utilizado em outras instâncias.  Este processonão é obrigatório, mas é recomendávelprincipalmente em sistemas onde serãocriadas novas instâncias junopy a cada transaçãoMais detalhes emDocumentação Oficialimportjunopyjunopy.Juno('PRIVATE_TOKEN','CLIENT_ID','CLIENT_SECRET')junopy.GetToken()token_valido_1h=junopy.TOKENDefinição Token de Acesso - Usando dados gerados anteriormenteÉ possível definir manualmente os dados de acesso através da funçãoSetTokenimportjunopyjunopy.Juno('PRIVATE_TOKEN','CLIENT_ID','CLIENT_SECRET')junopy.SetToken('access_token','token_type','expires')UtilidadesLista de Bancosbancos=junopy.util.Banks()Lista de Tipos de Empresastipos_empresas=junopy.util.CompanyTypes()Tipos de Negóciostipos_empresas=junopy.util.BusinessAreas()Chave Publica de Criptografiachave_publica=junopy.util.PublicKey()Validação WebhookTodo Webhook recebido da Juno traz consigo uma assinatura no header daRequisiçã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 emCriação e Assinatura de Webhookcampotipoobrigatóriox_signaturestringsimbody_contentbytessimsecretstringsimo retorno da função seráTrueouFalsewebhook_valido=junopy.util.IsValidWebhook(x_signature,body_content,secret)Conta DigitalA seção compreende:Criação de contas digitaisConsulta de contas digitalAlteração de dados da conta digitalMais detalhes emDocumentação OficialCriaçãoNo 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=2015conta.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_bancariaconta.Create()Consultaconta=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çãoconta=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 WhitelabelMais detalhes emDocumentação OficialNovo Onboarding - Somente Envio de Documentosonboarding=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 Documentosonboarding=junopy.onboarding.Account(referenceId='id_proprio',returnUrl="https://www.website.com.br/documents",refreshUrl="https://www.website.com.br/invalid")DocumentosMais detalhes emDocumentação OficialConsultadocumentos_esperados=junopy.Document(id='dac_E6FECDB17EAC5993').Get()Consulta de outra Conta Digital (Resource)documentos_esperados=junopy.Document(id='dac_E6FECDB17EAC5992',resourceToken='8A596ED1DEB738091FDE8AF11CCD6E7730970A95503AB32CEA340FAB190139C9').Get()Lista Documentosdocumentos_esperados=junopy.Document().Get()Lista Documentos de outra Conta Digital (Resource)documentos_esperados=junopy.Document(resourceToken='8A596ED1DEB738091FDE8AF11CCD6E7730970A95503AB32CEA340FAB190139C9').Get()Envio de Documentos/ArquivosMétodo path do arquivoUma array de string contendo o caminho local do arquivodocumentos_esperados=junopy.Document(id='doc_AD1E698AB61CF185',resourceToken='8A596ED1DEB738091FDE8AF11CCD6E7730970A95503AB32CEA340FAB190139C9').SendFiles(['arquivo_1.pdf','arquivo_2.pdf'])Método BufferedReader do arquivoUma array com tuplas onde posição 0 é o nome do arquivo e posição 1 os BufferedReaderdocumentos_esperados=junopy.Document(id='doc_AD1E698AB61CF185',resourceToken='8A596ED1DEB738091FDE8AF11CCD6E7730970A95503AB32CEA340FAB190139C9').SendFiles([('arquivo_1.pdf',file_buffered)])Método bytes do arquivoUma array com tuplas onde posição 0 é o nome do arquivo e posição 1 os bytesdocumentos_esperados=junopy.Document(id='doc_AD1E698AB61CF185',resourceToken='8A596ED1DEB738091FDE8AF11CCD6E7730970A95503AB32CEA340FAB190139C9').SendFiles([('arquivo_1.pdf',file_bytes)])SaldoMais detalhes emDocumentação Oficialimportjunopyjunopy.Juno('PRIVATE_TOKEN','CLIENT_ID','CLIENT_SECRET')saldo=junopy.Balance(){'balance': 0.0, 'withheldBalance': 0.0, 'transferableBalance': 0.0}ou de outra conta digitalimportjunopyjunopy.Juno('PRIVATE_TOKEN','CLIENT_ID','CLIENT_SECRET')saldo=junopy.Balance(resourceToken='8A596ED1DEB738091FDE8AF11CCD6E7730970A95503AB32CEA340FAB190139C9')TransferênciaMais detalhes emDocumentação OficialConta Bancária Padrãoimportjunopyjunopy.Juno('PRIVATE_TOKEN','CLIENT_ID','CLIENT_SECRET')transfer=junopy.transfers.Default(100.0)Transferência P2Pimportjunopyjunopy.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áriaimportjunopyjunopy.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 PIXimportjunopyjunopy.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çõesMais detalhes emDocumentação OficialListar Tipos de EventosRetorna uma lista de objetosEventTypeTipo de EventoDescriçãoDIGITAL_ACCOUNT_STATUS_CHANGEDMudanças destatusde uma conta digitalDIGITAL_ACCOUNT_CREATEDConfirmação de criação de uma conta digital -Válido somente para a solução WhitelabelDOCUMENT_STATUS_CHANGEDMudanças destatusde um documento da conta digitalTRANSFER_STATUS_CHANGEDMudanças destatusde uma transferênciaP2P_TRANSFER_STATUS_CHANGEDMudanças destatusde uma transferência P2PCHARGE_STATUS_CHANGEDMudanças destatusde uma cobrança emitidaCHARGE_READ_CONFIRMATIONConfirmação de leitura/visualização de uma cobrançaPAYMENT_NOTIFICATIONPagamento de uma cobrançasimportjunopyevents=junopy.EventTypes()WebhooksMais detalhes emDocumentação OficialCriaçãoCria e retorna um objetoWebhookimportjunopyjunopy.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 webhookswebhooks=junopy.Webhooks()Consultar Webhookswebhooks=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 Webhookswebhook=junopy.Webhook(id='wbh_6D7EF263A2755055').Delete()CobrançasMais detalhes emDocumentação OficialCriar Cobrançacobranca=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 objetoChargeResourceListar 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 compageSize=100.busca=junopy.charges.Search()oubusca=junopy.charges.Search(pageSize=100)oubusca=junopy.charges.Search(createdOnStart='2021-07-10')A partir da primeira busca é possível navegar pelas páginas superiores/inferiores através dos métodosNextePreviousPara avançar:proxima=junopy.charges.Next()Para voltar:anterior=junopy.charges.Previous()Consultar Cobrançacobranca=junopy.charges.Get(id="chr_8C87D875719FE478195F5AE32309F77B")Cancelar Cobrançajunopy.charges.Cancel(id="chr_8C87D875719FE478195F5AE32309F77B")Atualizar Splitjunopy.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 TransparenteTokenizar CartãoMais detalhes emDocumentação Oficialcartao_credito=junopy.creditcard.Tokenize(hash="0210da66-6c54-4f3b-9e95-9e044be38d79")Checkout TransparenteMais detalhes emDocumentação Oficial# CRIAÇÃO DE COBRANÇAcobranca=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 PAGAMENTOiflen(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éditoMais detalhes emDocumentação OficialIntegralestorno=junopy.payment.Refund(paymentId='pay_BDBBF5F40B8B94F23DB2117904EB4B08')Parcialestorno=junopy.payment.Refund(paymentId='pay_BDBBF5F40B8B94F23DB2117904EB4B08',amount=40.00)Splitestorno=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éditoMais detalhes emDocumentação OficialIntegralcaptura=junopy.payment.Capture(paymentId='pay_BDBBF5F40B8B94F23DB2117904EB4B08')Parcialcaptura=junopy.payment.Capture(paymentId='pay_BDBBF5F40B8B94F23DB2117904EB4B08',amount=100.00)Planos e AssinaturasPlanosCriar Planoplano=junopy.Plan(name="Plano Teste",amount=100.00).Create()Consultar Planoplano=junopy.Plan(id='pln_76A6AC4929EF068B').Get()Listar Planoplanos=junopy.Plan().Get()Desativar Planoplano=junopy.Plan(id='pln_76A6AC4929EF068B').Deactivate()Reativar Planoplano=junopy.Plan(id='pln_76A6AC4929EF068B').Reactivate()AssinaturasCriar Assinaturaassinatura=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 Assinaturaassinatura=junopy.Subscription(id='sub_EDA3F6CA13DFEC4C').Get()Listar Assinaturasassinaturas=junopy.Subscription().Get()Desativar Assinaturaassinatura=junopy.Subscription(id='sub_EDA3F6CA13DFEC4C').Deactivate()Reativar Assinaturaassinatura=junopy.Subscription(id='sub_EDA3F6CA13DFEC4C').Reactivate()Cancelar Assinaturaassinatura=junopy.Subscription(id='sub_EDA3F6CA13DFEC4C').Cancel()Completar Assinaturaassinatura=junopy.Subscription(id='sub_EDA3F6CA13DFEC4C').Complete()Pagar Contaspagamento_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()PIXGerar Chave  ( Pix Keys)# CHAVE GERADA UMA ÚNICA VEZuudi=str(uuid.uuid4())pix=junopy.pix.Keys(idempotency=uudi)OBTER QR CODE ESTÁTICOpix=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')PicPayEM DESENVOLVIMENTOSuporte Oficial da JunoEm caso de dúvidas, problemas ou sugestões:falecom@juno.com.brChange logVeja emCHANGELOGpara maiores informações sobre as mudanças recentesContribuiçõesAs contribuições  por meio dePull Requestssão bem-vindas e serão totalmente creditadas.SegurançaSe você descobrir qualquer problema relacionado à segurança, envie um e-mail pararobertonsilva@gmail.comCréditosAutorRoberto NevesLicençaVeja emLICENÇApara maiores informações sobre a licença de uso.