Closed plutaniano closed 3 years ago
A resposta é sim para as duas perguntas, mas seria necessário implementar.
Na criação teriamos que ver qual o nome desse parametro e passar na query.
Para retornar esse identificador único provavelmente é um campo a mais na query graphql que trás o feed
A parte dificil é descobrir esses campo rs, precisa inspecionar como o app faz o request
Fiz umas modificações simples e consegui criar qr codes do pix com identificador e mensagem customizadas:
# pynubank/nubank.py
...
def create_pix_payment_qrcode(self,
account_id: str,
amount: float,
pix_key: dict,
message: str = '',
tx_id: str = ''
) -> dict:
payload = {
'createPaymentRequestInput': {
'amount': amount,
'pixAlias': pix_key.get('value'),
'savingsAccountId': account_id,
'message': message, # mensagem
'transactionId': tx_id, # Identificador, truncado em 12 chars
}
}
response = self._make_graphql_request('create_pix_money_request', payload)
data = response['data']['createPaymentRequest']['paymentRequest']
qr = QRCode()
qr.add_data(data['brcode'])
return {
'payment_url': data['url'],
'transactionId': data['transactionId'],
'message': data['message'],
'qr_code': qr,
}
...
Agora, na parte de fazer engenharia reversa na api pra pegar o identificador das transações eu estou com um pouco de dificuldade. Tentei chutar alguns nomes, mas sem sucesso. Também tentei utilizar o mitmproxy mas o app detecta algo de estranho na conexão e se recusa a funcionar.
Qual foi o metodo que vocês utilizaram para obter parametros que já estão na lib?
Também peguei essas informações do app com um proxy, no caso usei o Burp Suite.
Mas o app tem um mecanismo de segurança que não permite o uso de um certificado diferente do deles. Pra burlar isso eu usei o frida, acabei detalhando um pouco do processo em outra issue, o único problema é que é necessário um emulador ou celular com root para utilizar o frida
Fiz umas modificações simples e consegui criar qr codes do pix com identificador e mensagem customizadas:
# pynubank/nubank.py ... def create_pix_payment_qrcode(self, account_id: str, amount: float, pix_key: dict, message: str = '', tx_id: str = '' ) -> dict: payload = { 'createPaymentRequestInput': { 'amount': amount, 'pixAlias': pix_key.get('value'), 'savingsAccountId': account_id, 'message': message, # mensagem 'transactionId': tx_id, # Identificador, truncado em 12 chars } } response = self._make_graphql_request('create_pix_money_request', payload) data = response['data']['createPaymentRequest']['paymentRequest'] qr = QRCode() qr.add_data(data['brcode']) return { 'payment_url': data['url'], 'transactionId': data['transactionId'], 'message': data['message'], 'qr_code': qr, } ...
Agora, na parte de fazer engenharia reversa na api pra pegar o identificador das transações eu estou com um pouco de dificuldade. Tentei chutar alguns nomes, mas sem sucesso. Também tentei utilizar o mitmproxy mas o app detecta algo de estranho na conexão e se recusa a funcionar.
Qual foi o metodo que vocês utilizaram para obter parametros que já estão na lib?
Eu estou com um dispositivo tudo certo aqui só passar o print da página que te passo o request
O que eu preciso é das informações que aparecem quando você vai no app > Conta > Histórico, seleciona uma transação pix recebida > ver comprovante. Nessa página tem as informações que eu quero: descrição e identificador. imagem
Se você conseguir isso ai vai resolver o problema. Tentei mexer com os emuladores de android mas como tenho zero experiencia nessa plataforma não cheguei em lugar nenhum. Valeu.
Tranquilo te passo ou hoje de noite ou amanhã eu tenho que fazer engenharia reversa em diversos apps aí acabei adquirindo a experiência
O request do comprovante seria
{
"operationName": "get_generic_receipt_screen",
"variables": {
"type": "TRANSFER_IN",
"id": "AQUI SERIA O ID DA TRANSAÇÃO"
},
"query": "query get_generic_receipt_screen($type: String!, $id: ID!) {
viewer {
savingsAccount {
getGenericReceiptScreen(type: $type, id: $id) {
screenShowShareAction
screenType
screenPieces {
__typename
fallbackMessage
... on ReceiptHeaderPiece {
headerTitle
headerSubtitle
}
... on ReceiptMessagePiece {
messageTitle
messageContent
}
... on ReceiptFooterPiece {
footerTitle
footerContent
}
... on ReceiptTablePiece {
tableHeader {
icon
title
subtitle
deeplinkWithMeta {
href
analytics {
key
value
}
}
}
tableItems {
label
value
}
}
}
}
}
}
}"
}
O request sem prettify seria
{
"operationName": "get_generic_receipt_screen",
"variables": {
"type": "TRANSFER_IN",
"id": "AQUI SERIA O ID DA TRANSAÇÃO"
},
"query": "query get_generic_receipt_screen($type: String!, $id: ID!) {\n viewer {\n savingsAccount {\n getGenericReceiptScreen(type: $type, id: $id) {\n screenShowShareAction\n screenType\n screenPieces {\n __typename\n fallbackMessage\n ... on ReceiptHeaderPiece {\n headerTitle\n headerSubtitle\n }\n ... on ReceiptMessagePiece {\n messageTitle\n messageContent\n }\n ... on ReceiptFooterPiece {\n footerTitle\n footerContent\n }\n ... on ReceiptTablePiece {\n tableHeader {\n icon\n title\n subtitle\n deeplinkWithMeta {\n href\n analytics {\n key\n value\n }\n }\n }\n tableItems {\n label\n value\n }\n }\n }\n }\n }\n }\n}"
}
O request de detalhes da transação seria
Prettify
{
"operationName": "get_generic_transaction_details_screen",
"variables": {
"type": "TRANSFER_OUT",
"id": "AQUI SERIA O ID DA TRANSAÇÃO"
},
"query": "fragment deeplinkWithMeta on GenericDeeplink {
href
analytics {
key
value
}
}
query get_generic_transaction_details_screen($type: String!, $id: ID!) {
viewer {
savingsAccount {
getGenericTransactionDetailsScreen(type: $type, id: $id) {
screenTitle
screenType
screenPieces {
__typename
fallbackMessage
... on TransactionDetailsHeaderPiece {
headerAvatar {
initials
icon
badge
}
headerTitle
headerSubtitle
headerContent
}
... on TransactionDetailsActionsPiece {
actions {
title
deeplinkWithMeta {
...deeplinkWithMeta
}
icon
}
}
... on TransactionDetailsMessagePiece {
messageTitle
messageContent
}
... on TransactionDetailsTablePiece {
tableHeader {
icon
title
subtitle
deeplinkWithMeta {
...deeplinkWithMeta
}
}
tableItems {
label
value
}
}
}
}
}
}
}
"
}
Raw
{"operationName":"get_generic_transaction_details_screen","variables":{"type":"TRANSFER_OUT","id":"AQUI SERIA O ID DA TRANSAÇÃO"},"query":"fragment deeplinkWithMeta on GenericDeeplink {\n href\n analytics {\n key\n value\n }\n}\n\nquery get_generic_transaction_details_screen($type: String!, $id: ID!) {\n viewer {\n savingsAccount {\n getGenericTransactionDetailsScreen(type: $type, id: $id) {\n screenTitle\n screenType\n screenPieces {\n __typename\n fallbackMessage\n ... on TransactionDetailsHeaderPiece {\n headerAvatar {\n initials\n icon\n badge\n }\n headerTitle\n headerSubtitle\n headerContent\n }\n ... on TransactionDetailsActionsPiece {\n actions {\n title\n deeplinkWithMeta {\n ...deeplinkWithMeta\n }\n icon\n }\n }\n ... on TransactionDetailsMessagePiece {\n messageTitle\n messageContent\n }\n ... on TransactionDetailsTablePiece {\n tableHeader {\n icon\n title\n subtitle\n deeplinkWithMeta {\n ...deeplinkWithMeta\n }\n }\n tableItems {\n label\n value\n }\n }\n }\n }\n }\n }\n}"}
Você sabe qual é o id que tem que passar nessa query? Tentei passar o id que vem com as transações do nu.get_account_feed()
e também o id que eu destaquei na foto que eu mandei na outra mensagem, nenhum dos dois funcionou. Também testei com o id da conta, mas sem sucesso também.
O id é o id o get_account_feed sim, a diferença é que o type é diferente se usa TRANSFER_IN para entrada de dinheiro e TRANSFER_OUT para saída.
Vou te mandar o código que usei para testar, quando mandar um pull request no pynubank seria bom usar ao invés do txid o objeto da transação inteira e pelos __typenames das transações classificar em [TRANSFER_IN, TRANSFER_OUT]
pynubank/nubank.py
Eu adicionei na class Nubank
def get_generic_receipt_screen(self, txid):
data = self._make_graphql_request('get_generic_receipt_screen', {
'type':'TRANSFER_OUT',
'id':txid
})
return data
queries/get_generic_receipt_screen.gql
query get_generic_receipt_screen($type: String!, $id: ID!) {
viewer {
savingsAccount {
getGenericReceiptScreen(type: $type, id: $id) {
screenShowShareAction
screenType
screenPieces {
__typename
fallbackMessage
... on ReceiptHeaderPiece {
headerTitle
headerSubtitle
}
... on ReceiptMessagePiece {
messageTitle
messageContent
}
... on ReceiptFooterPiece {
footerTitle
footerContent
}
... on ReceiptTablePiece {
tableHeader {
icon
title
subtitle
deeplinkWithMeta {
href
analytics {
key
value
}
}
}
tableItems {
label
value
}
}
}
}
}
}
}
A propósito os campos que você queria era essa parte do request
... on ReceiptMessagePiece {
messageTitle
messageContent # Esse campo aqui mais específicamente
}
{'__typename': 'ReceiptMessagePiece', 'fallbackMessage': 'Atualize seu app para ver todas as informações!', 'messageTitle': 'Descrição', 'messageContent': 'teste'}
@Ulisses1478 é possível chamar esse objeto de query do comprovante como subquery do objeto feed? A fim de obter todos os comprovantes junto com o feed de TransferIn no mesmo objeto em um único hit na api?
@Ulisses1478 valeu pelos códigos, eu abri um PR com essa alteração e deu certo com o seu código...
Só preciso dar uma melhorada na utilização e documentar, mas no geral até que é "simples". Único problema é que não dá (Pelo menos não vi como) obter essa informação na listagem geral
@Ulisses1478 valeu pelos códigos, eu abri um PR com essa alteração e deu certo com o seu código...
Só preciso dar uma melhorada na utilização e documentar, mas no geral até que é "simples". Único problema é que não dá (Pelo menos não vi como) obter essa informação na listagem geral
Pelo que vi não tem como mesmo não na engenharia reversa pelo burp suite.
Boa tarde, estou tentando automatizar a criação e verificação de pagamento de qr codes que envio aos meus pagadores.
Na parte de criação: Existe alguma maneira de colocar um identificador único para cada transação nos qr codes? No app, existe a opção de incluir um identificador de 12 caracteres no processo de criação do qr code , mas o método create_pix_payment_qrcode não recebe essa informação.
Na parte de verificação: no app, indo nos detalhes da transferencia, é possível verificar o identificador único que eu mencionei anteriormente, mas esse identificador não é disponibilizado no método get_account_feed. Existe alguma maneira de obter esse identificador?
Eu ainda estou me familiarizando com a lib, mas posso tentar implementar essas funcionalidades caso elas ainda não existam. Obrigado