PayPal via API direta
Esta página inclui os passos necessários para integrar o PayPal usando a API DEUNA.
Assim que tivermos o order_token, devemos fazer o seguinte:
1. Criar usuário
Crie um usuário com DEUNA para obter o token de autorização para realizar a compra posteriormente. Esta API retornará o nome de um usuário token que será necessário para seguir os próximos passos.
Para criar um usuário, siga o Referência da API. Caso o email utilizado já exista, a API retornará a mensagem user already exists, para que você possa prosseguir para Solicite o OTP e então, Faça login com o OTP para obter um novo usuário token e prossiga com a compra.
2. Obtenha métodos de pagamento
Devemos verificar os métodos de pagamento para obter a configuração da Carteira PayPal. Você pode acompanhar isso guia.
-
Carga útil
curl --location '{{base_url}}/merchants/orders/{{order_token}}/payments-methods' \ --header 'x-api-key: {{merchant_private_key}}' \ --header 'Authorization: Bearer {{user_token}}'const response = await fetch("{{base_url}}/merchants/orders/{{order_token}}/payments-methods", { method: "GET", headers: { "x-api-key": "{{merchant_private_key}}", "Authorization": "Bearer {{user_token}}" } }); if (!response.ok) throw new Error(`Request failed: ${response.status}`); const data = await response.json();import requests response = requests.request( "GET", "{{base_url}}/merchants/orders/{{order_token}}/payments-methods", headers={ "x-api-key": "{{merchant_private_key}}", "Authorization": "Bearer {{user_token}}" }, ) response.raise_for_status() data = response.json()<?php $curl = curl_init(); curl_setopt_array($curl, [ CURLOPT_URL => "{{base_url}}/merchants/orders/{{order_token}}/payments-methods", CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "x-api-key: {{merchant_private_key}}", "Authorization: Bearer {{user_token}}" ] ]); $response = curl_exec($curl); curl_close($curl);import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; public class Example { public static void main(String[] args) throws Exception { HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("{{base_url}}/merchants/orders/{{order_token}}/payments-methods")) .header("x-api-key", "{{merchant_private_key}}") .header("Authorization", "Bearer {{user_token}}") .method("GET", HttpRequest.BodyPublishers.noBody()) .build(); HttpResponse<String> response = HttpClient.newHttpClient().send( request, HttpResponse.BodyHandlers.ofString() ); System.out.println(response.body()); } }package main import ( "fmt" "io" "net/http" ) func main() { request, err := http.NewRequest("GET", "{{base_url}}/merchants/orders/{{order_token}}/payments-methods", nil) if err != nil { panic(err) } request.Header.Set("x-api-key", "{{merchant_private_key}}") request.Header.Set("Authorization", "Bearer {{user_token}}") response, err := http.DefaultClient.Do(request) if err != nil { panic(err) } defer response.Body.Close() body, _ := io.ReadAll(response.Body) fmt.Println(string(body)) } -
Resposta
JSON{ "data": [ { "enabled": true, "method_type": "wallet", "processor_name": "paypal_wallet", // PayPal Wallet identifier "exclude_cvv": false, "stored_payment_methods": [ { "payment_method": "adb1ef51-e073-49f5-ba3b-a7e42344fd15", "account_identifier": "johndoe@deuna.com" } ], "id": "58745b8e-7127-44ea-84ef-656b3ffc611b", // Payment method ID "authorization": { "required": true, // true | false "flow": "consent" } } ] }
Fluxo de compra#
Dependendo da resposta obtida em Obter Métodos de Pagamento, podemos seguir os seguintes fluxos para finalizar uma compra:
Sem salto
Este é o fluxo a seguir quando a tokenização de uma conta PayPal não é necessária para concluir a compra.
A resposta de Obtenha métodos de pagamento seria o seguinte:
{
"data": [
{
"enabled": true,
"method_type": "wallet",
"processor_name": "paypal_wallet", // PayPal Wallet identifier
"exclude_cvv": false,
"stored_payment_methods": [],
"id": "58745b8e-7127-44ea-84ef-656b3ffc611b", // Payment method ID
"authorization": {
"required": false,
"flow": "consent"
}
}
]
}Neste fluxo, devemos fazer o seguinte:
-
Realize a compra
-
Use a guia da Purchase V2. Aqui está uma lista de campos obrigatórios para a carteira do PayPal:
Campo Descrição Valor order.callback_urls.on_successURL de redirecionamento após autorizar a compra com sua conta PayPal Wallet. https://example.com/payment_source.method_typeTipo de método de pagamento DEUNA. walletpayment_source.processorIdentificador do método de pagamento da Carteira PayPal. paypal_walletCarga útil
JSON{ "order_type": "DEUNA_CHECKOUT", "order_token": "{{order-token}}", "order": { "callback_urls": { "on_success": "https://example.com" // required for PayPal Wallet } }, "payer_info": { "email": "johndoe@deuna.com" }, "payment_source": { "method_type": "wallet", // required for PayPal Wallet "processor": "paypal_wallet" // required for PayPal Wallet }, "anti_fraud_info": { "device": { "id": "xxxxxxx" // PayPal device ID, used in STC } } }
Resposta
JSON{ "order": { "order_id": "620bbbf4-1f08-4cda-8609-dade541cb80e", "store_code": "all", "currency": "MXN", "tax_amount": 0, "display_tax_amount": "", "shipping_amount": 0, "display_shipping_amount": "MXN 0.00", "items_total_amount": 2175, "display_items_total_amount": "MXN 21.75", "sub_total": 2075, "display_sub_total": "MXN 20.75", "total_amount": 2190, "display_total_amount": "MXN 21.90", "items": [ { "id": "849fd015-2e1b-4ccc-a00c-aacbefeb71c8", "name": "Papas", "description": "Papas fritas con paprica", "options": "", "total_amount": { "amount": 2100, "original_amount": 2100, "display_amount": "MXN 21.00", "display_original_amount": "MXN 21.00", "currency": "MXN", "currency_symbol": "$", "total_discount": 100, "display_total_discount": "MXN 1.00" }, "unit_price": { "amount": 1050, "display_amount": "MXN 10.50", "currency": "MXN", "currency_symbol": "$" }, "tax_amount": { "amount": 50, "display_amount": "MXN 0.50", "currency": "MXN", "currency_symbol": "$" }, "quantity": 2, "uom": "", "upc": "", "sku": "", "isbn": "", "brand": "", "manufacturer": "", "category": "", "color": "", "size": "", "weight": { "weight": 0, "unit": "" }, "image_url": "https://media-cdn.tripadvisor.com/media/photo-s/1a/e2/c6/68/porcion-de-papas-a-la.jpg", "details_url": "", "type": "", "taxable": true, "discounts": [], "included_in_subscription": false, "item_details": [] }, { "id": "c871341d-317b-4fdb-9d72-b55e55958633", "name": "Refresco", "description": "Coca-cola Sprite", "options": "", "total_amount": { "amount": 90, "original_amount": 75, "display_amount": "MXN 0.90", "display_original_amount": "MXN 0.75", "currency": "MXN", "currency_symbol": "$", "total_discount": 0, "display_total_discount": "MXN 0.00" }, "unit_price": { "amount": 75, "display_amount": "MXN 0.75", "currency": "MXN", "currency_symbol": "$" }, "tax_amount": { "amount": 15, "display_amount": "MXN 0.15", "currency": "MXN", "currency_symbol": "$" }, "quantity": 1, "uom": "", "upc": "", "sku": "", "isbn": "", "brand": "", "manufacturer": "", "category": "", "color": "", "size": "", "weight": { "weight": 0, "unit": "" }, "image_url": "https://media-cdn.tripadvisor.com/media/photo-s/1a/e2/c6/68/porcion-de-papas-a-la.jpg", "details_url": "", "type": "", "taxable": true, "discounts": [], "included_in_subscription": false, "item_details": [] } ], "discounts": [], "shipping_address": { "id": 762, "user_id": "", "first_name": "Pablo", "last_name": "Murillo", "phone": "+551146733466", "identity_document": "", "lat": -22.943934, "lng": -43.182984, "address1": "Jose luis lagrange 3, 12", "address2": "Polanco I Sección", "city": "MIGUEL HIDALGO", "zipcode": "11510", "state_name": "CIUDAD DE MÉXICO", "country_code": "MX", "additional_description": "confirmar", "address_type": "home", "is_default": false, "created_at": "2025-02-26T21:38:07Z", "updated_at": "2025-02-26T21:38:07Z", "identity_document_type": "", "email": "johndoe@deuna.com", "state_code": "", "country": "MX" }, "shipping_options": null, "user_instructions": "", "metadata": { "cd_string_one": 1, "highrisk_txn_flag": 1, "vertical": "Retail" }, "status": "pending", "payment": { "data": { "amount": { "amount": 2190, "currency": "MXN" }, "metadata": { "authorization_code": "", "external_transaction_id": "6L9248503S6803027" }, "from_card": { "card_brand": "", "first_six": "", "last_four": "", "bank_name": "", "country_iso": "", "credential_source": "", "expiry_month": "", "expiry_year": "" }, "updated_at": "2025-02-26 21:38:12.748800962 +0000 UTC", "method_type": "wallet", "merchant": { "store_code": "all", "id": "2a18bdc9-d617-45cc-b718-838451dcf33a", "affiliation_code": "", "mcc": "" }, "created_at": "2025-02-26 21:38:12.747998969 +0000 UTC", "id": "620bbbf4-1f08-4cda-8609-dade541cb80e", "processor": "paypal_wallet", "customer": { "email": "user_dev_219@testuser.com", "id": "9d920735-c3b1-4908-aba2-762d86fda7e0", "first_name": "", "last_name": "" }, "status": "pending", "reason": "", "external_transaction_id": "6L9248503S6803027", "merchant_payment_processor_name": "", "authorization_code": "", "installment_interest_calculations": null, "next_action": { "action": "authorization_wallet", "url": "", "authorization_wallet": { "token": "6L9248503S6803027", "redirect_url": "https://www.sandbox.paypal.com/checkoutnow?token=6L9248503S6803027" } }, "merchant_payment_processor_id": "" } }, "gift_card": [], "redirect_url": "", "webhook_urls": null, "total_discount": 0, "display_total_discount": "MXN 0.00", "shipping": null, "cash_change": 0, "shipping_method": null, "shipping_methods": [], "timezone": "", "scheduled_at": "", "billing_address": { "id": 191, "user_id": "", "first_name": "Pablo", "last_name": "Murillo", "phone": "+551146733466", "identity_document": "", "lat": -22.943934, "lng": -43.182984, "address1": "Jose luis lagrange 3, 12", "address2": "Polanco I Sección", "city": "MIGUEL HIDALGO", "zipcode": "11510", "state_name": "CIUDAD DE MÉXICO", "country_code": "MX", "additional_description": "confirmar", "address_type": "home", "is_default": false, "created_at": "2025-02-26T21:38:07Z", "updated_at": "2025-02-26T21:38:07Z", "email": "johndoe@deuna.com", "identity_document_type": "", "country": "" }, "payment_link": "", "display_shipping_tax_amount": "MXN 0.00", "display_total_tax_amount": "MXN 1.15", "shipping_tax_amount": 0, "total_tax_amount": 115, "user_id": "", "include_payment_options": [], "redirect_urls": { "success": "", "pending": "", "error": "", "fallback": "", "close": "" }, "created_at": "", "updated_at": "", "payer_info": null, "discount_amount": 100, "shipping_discount_amount": 0, "device_fingerprint": "", "expired_at": "", "version": "0", "fraud": { "analysis": { "score": 0.113950945, "processor": "SIFT", "risk_level": "", "status": "automatic_decision", "type": "", "fraud_decision": "", "details": "", "processor_response": "" } }, "display_total_interest_amount": "", "payment_method": "", "token": "", "statement_descriptor": "", "browser_details": { "screen_height": 1000, "screen_width": 2000, "user_agent": "", "ip_address": "", "color_depth": 0, "java_enabled": false, "java_script_enabled": false, "language": "", "time_zone_offset": 0, "accept_header": "" }, "callback_urls": null }, "custom_fields": [] } -
-
Redirecionar para PayPal
A API de compra retornará uma resposta com um
pendingestatuto e umnext_actioncontendo a URL de checkout do PayPal, para a qual devemos redirecionar o usuário.JSON{ "order": { "order_id": "620bbbf4-1f08-4cda-8609-dade541cb80e", "store_code": "all", "currency": "MXN", "tax_amount": 0, "display_tax_amount": "", "shipping_amount": 0, "display_shipping_amount": "MXN 0.00", "items_total_amount": 2175, "display_items_total_amount": "MXN 21.75", "sub_total": 2075, "display_sub_total": "MXN 20.75", "total_amount": 2190, "display_total_amount": "MXN 21.90", ... "status": "pending", "payment": { "data": { "method_type": "wallet", "processor": "paypal_wallet", "status": "pending", "external_transaction_id": "6L9248503S6803027", "next_action": { "action": "authorization_wallet", "url": "", "authorization_wallet": { "token": "6L9248503S6803027", "redirect_url": "https://www.sandbox.paypal.com/checkoutnow?token=6L9248503S6803027" } }, ... } }, "created_at": "", "updated_at": "", ... }, "custom_fields": [] } -
Verifique o status do pedido (Polling).
Depois de direcionarmos o usuário ao PayPal, devemos verificar o status do pagamento enquanto ele o autoriza em sua conta, pesquisando até que o status mude.
Nós temos que Obter pedido e verifique o
payment.data.status.Os status esperados são:
pending: O usuário ainda não autorizou o pagamento no PayPal.processed: O usuário autorizou o pagamento no PayPal e a captura foi realizada com sucesso.denied: Ocorreu um erro ao processar o pagamento.
Resposta
JSON{ "token": "ce7f91cc-7306-4a36-b9a8-b266545c56ba", "order_type": "DEUNA_CHECKOUT", "order": { "order_id": "620bbbf4-1f08-4cda-8609-dade541cb80e", "store_code": "all", "currency": "MXN", "tax_amount": 0, "display_tax_amount": "MXN 0.00", "shipping_amount": 0, "display_shipping_amount": "MXN 0.00", "items_total_amount": 2175, "display_items_total_amount": "MXN 21.75", "sub_total": 2075, "display_sub_total": "MXN 20.75", "total_amount": 2190, "display_total_amount": "MXN 21.90", "discounts": [], "status": "succeeded", "payment": { "data": { "method_type": "wallet", "processor": "paypal_wallet", "status": "processed", "external_transaction_id": "5S773340XV029382D" } }, "created_at": "2025-02-26 21:38:07.860816361 +0000 UTC", "updated_at": "", "callback_urls": null }, "custom_fields": [], "checkout_modules": [], "refunds": [] }
Com salto
Este é o fluxo a seguir quando a tokenização de uma conta PayPal for necessária para concluir a compra.
A resposta de Obtenha métodos de pagamento seria o seguinte:
{
"data": [
{
"enabled": true,
"method_type": "wallet",
"processor_name": "paypal_wallet", // PayPal Wallet identifier
"exclude_cvv": false,
"stored_payment_methods": [
{
"payment_method": "adb1ef51-e073-49f5-ba3b-a7e42344fd15",
"account_identifier": "johndoe@deuna.com"
}
],
"id": "58745b8e-7127-44ea-84ef-656b3ffc611b", // Payment method ID
"authorization": {
"required": true,
"flow": "consent"
}
}
]
}Neste ponto, o usuário deverá ter a opção de adicionar uma nova conta ou prosseguir com a compra utilizando uma conta previamente tokenizada.
-
Adicione uma nova conta PayPal
Para tokenizar uma nova conta, as seguintes etapas devem ser seguidas:
- Crie o consentimento do cliente.
Nesta etapa, criaremos uma solicitação de autorização do PayPal para o usuário.- Solicitação
curl --location --request POST '{{base_url}}/merchants/orders/{{order_token}}/consent?payment_method_id={{payment_method_id}}' \ --header 'X-API-KEY: {{merchant_private_key}}' \ --header 'Content-Type: application/json' \ --header 'X-Request-Id: xxxxx' \ --header 'Authorization: Bearer {{user_token}}'const response = await fetch("{{base_url}}/merchants/orders/{{order_token}}/consent?payment_method_id={{payment_method_id}}", { method: "POST", headers: { "X-API-KEY": "{{merchant_private_key}}", "Content-Type": "application/json", "X-Request-Id": "xxxxx", "Authorization": "Bearer {{user_token}}" } }); if (!response.ok) throw new Error(`Request failed: ${response.status}`); const data = await response.json();import requests response = requests.request( "POST", "{{base_url}}/merchants/orders/{{order_token}}/consent?payment_method_id={{payment_method_id}}", headers={ "X-API-KEY": "{{merchant_private_key}}", "Content-Type": "application/json", "X-Request-Id": "xxxxx", "Authorization": "Bearer {{user_token}}" }, ) response.raise_for_status() data = response.json()<?php $curl = curl_init(); curl_setopt_array($curl, [ CURLOPT_URL => "{{base_url}}/merchants/orders/{{order_token}}/consent?payment_method_id={{payment_method_id}}", CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "X-API-KEY: {{merchant_private_key}}", "Content-Type: application/json", "X-Request-Id: xxxxx", "Authorization: Bearer {{user_token}}" ] ]); $response = curl_exec($curl); curl_close($curl);import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; public class Example { public static void main(String[] args) throws Exception { HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("{{base_url}}/merchants/orders/{{order_token}}/consent?payment_method_id={{payment_method_id}}")) .header("X-API-KEY", "{{merchant_private_key}}") .header("Content-Type", "application/json") .header("X-Request-Id", "xxxxx") .header("Authorization", "Bearer {{user_token}}") .method("POST", HttpRequest.BodyPublishers.noBody()) .build(); HttpResponse<String> response = HttpClient.newHttpClient().send( request, HttpResponse.BodyHandlers.ofString() ); System.out.println(response.body()); } }package main import ( "fmt" "io" "net/http" ) func main() { request, err := http.NewRequest("POST", "{{base_url}}/merchants/orders/{{order_token}}/consent?payment_method_id={{payment_method_id}}", nil) if err != nil { panic(err) } request.Header.Set("X-API-KEY", "{{merchant_private_key}}") request.Header.Set("Content-Type", "application/json") request.Header.Set("X-Request-Id", "xxxxx") request.Header.Set("Authorization", "Bearer {{user_token}}") response, err := http.DefaultClient.Do(request) if err != nil { panic(err) } defer response.Body.Close() body, _ := io.ReadAll(response.Body) fmt.Println(string(body)) } - Resposta
JSON
{ "id": "1625a32a-df4c-4d9b-aec1-4510b3625865", "type": "transaction.authentication.pending", "created": "1740608931", "data": { "order": { "order_token": "7e975d44-a061-4d70-af0f-673f6ee56445", "transaction_id": "51b38afd-150f-419a-b718-b583209160fe", "external_transaction_id": "" }, "consent": { "id": "6fe9a045-9a46-4b25-8b60-d5a9586494c5", "status": "pending", "expires_at": "2025-02-26T22:38:51Z", "authorization_id": "5KA20765HT8087515", "redirect_url": "https://www.sandbox.paypal.com/agreements/approve?approval_session_id=5KA20765HT8087515" }, "error": null } }
- Solicitação
- Redirecionar para PayPal
A API retornará o consentimento conformependinge uma URL do PayPal onde o usuário deve inserir os dados da sua conta e autorizar seu uso.JSON{ "id": "1625a32a-df4c-4d9b-aec1-4510b3625865", "type": "transaction.authentication.pending", "created": "1740608931", "data": { "order": { "order_token": "7e975d44-a061-4d70-af0f-673f6ee56445", "transaction_id": "51b38afd-150f-419a-b718-b583209160fe", "external_transaction_id": "" }, "consent": { "id": "6fe9a045-9a46-4b25-8b60-d5a9586494c5", "status": "pending", "expires_at": "2025-02-26T22:38:51Z", "authorization_id": "5KA20765HT8087515", "redirect_url": "https://www.sandbox.paypal.com/agreements/approve?approval_session_id=5KA20765HT8087515" }, "error": null } } - Obtenha o status de consentimento do cliente (sondagem)
Depois de direcionarmos o usuário ao PayPal, devemos verificar o status de consentimento enquanto ele autoriza o uso de sua conta, pesquisando até que o status mude.- Solicitação
curl --location '{{base_url}}/merchants/orders/{{order_token}}/consent' \ --header 'X-API-KEY: {{merchant_private_key}}' \ --header 'Content-Type: application/json' \ --header 'X-Request-Id: xxxxx' \ --header 'Authorization: {{user_token}}'const response = await fetch("{{base_url}}/merchants/orders/{{order_token}}/consent", { method: "GET", headers: { "X-API-KEY": "{{merchant_private_key}}", "Content-Type": "application/json", "X-Request-Id": "xxxxx", "Authorization": "{{user_token}}" } }); if (!response.ok) throw new Error(`Request failed: ${response.status}`); const data = await response.json();import requests response = requests.request( "GET", "{{base_url}}/merchants/orders/{{order_token}}/consent", headers={ "X-API-KEY": "{{merchant_private_key}}", "Content-Type": "application/json", "X-Request-Id": "xxxxx", "Authorization": "{{user_token}}" }, ) response.raise_for_status() data = response.json()<?php $curl = curl_init(); curl_setopt_array($curl, [ CURLOPT_URL => "{{base_url}}/merchants/orders/{{order_token}}/consent", CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "X-API-KEY: {{merchant_private_key}}", "Content-Type: application/json", "X-Request-Id: xxxxx", "Authorization: {{user_token}}" ] ]); $response = curl_exec($curl); curl_close($curl);import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; public class Example { public static void main(String[] args) throws Exception { HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("{{base_url}}/merchants/orders/{{order_token}}/consent")) .header("X-API-KEY", "{{merchant_private_key}}") .header("Content-Type", "application/json") .header("X-Request-Id", "xxxxx") .header("Authorization", "{{user_token}}") .method("GET", HttpRequest.BodyPublishers.noBody()) .build(); HttpResponse<String> response = HttpClient.newHttpClient().send( request, HttpResponse.BodyHandlers.ofString() ); System.out.println(response.body()); } }package main import ( "fmt" "io" "net/http" ) func main() { request, err := http.NewRequest("GET", "{{base_url}}/merchants/orders/{{order_token}}/consent", nil) if err != nil { panic(err) } request.Header.Set("X-API-KEY", "{{merchant_private_key}}") request.Header.Set("Content-Type", "application/json") request.Header.Set("X-Request-Id", "xxxxx") request.Header.Set("Authorization", "{{user_token}}") response, err := http.DefaultClient.Do(request) if err != nil { panic(err) } defer response.Body.Close() body, _ := io.ReadAll(response.Body) fmt.Println(string(body)) } - Resposta
Os status esperados são:JSON
{ "id": "4d226ecf-cd9a-4cc0-a3cf-fa8b2d0efab7", "type": "transaction.authentication.updated", "created": "1740609613", "callback_url": "", "data": { "request_id": "62551ffd-6d67-46cb-a436-f1ec3aa56087", "order": { "order_token": "00000000-0000-0000-0000-000000000000", "transaction_id": "", "external_transaction_id": "" }, "consent": { "id": "61fd7eb8-8a42-43fc-89d1-ab5c5ccaa0b9", "status": "success", "expires_at": "0001-01-01T00:00:00Z", "authorization_id": "95778196PH100683G", "redirect_url": "" }, "error": null } } pending: O usuário ainda não autorizou o uso de sua conta PayPal.success: o usuário autorizou o uso de sua conta do PayPal e a conta foi tokenizada com sucesso.denied: ocorreu um erro ao tokenizar a conta ou o usuário não autorizou o uso da conta.expired: O usuário não autorizou o uso de sua conta a tempo.\
Assim que o consentimento do usuário for autorizado, a conta aparecerá no
stored_payment_methodsda resposta de Obtenha métodos de pagamento.
JSON{ "data": [ { "enabled": true, "method_type": "wallet", "processor_name": "paypal_wallet", // PayPal Wallet identifier "exclude_cvv": false, "stored_payment_methods": [ { "payment_method": "6fe9a045-9a46-4b25-8b60-d5a9586494c5", // data.consent.id "account_identifier": "johndoe@deuna.com" } ], "id": "58745b8e-7127-44ea-84ef-656b3ffc611b", // Payment method ID "authorization": { "required": true, "flow": "consent" } } ] }Neste ponto, devemos ter uma conta PayPal tokenizada, esses tokens serão necessários para as próximas etapas. Este token de conta será o
payment_methodcampo da lista destored_payment_methodsna resposta de Obtenha métodos de pagamento, ou também pode ser odata.consent.idcampo da resposta da API de Criar ou Obtenha consentimento. - Solicitação
- Crie o consentimento do cliente.
-
Parcelas (opcional)
Podemos verificar as parcelas disponíveis para a conta PayPal do usuário com a seguinte solicitação:
curl --location '{{base_url}}/merchants/transactions/orders/{{order_token}}/installments?payment_method={{payment_method}}&method_type=wallet&payment_method_id={{payment_method_id}}' \ --header 'x-api-key: {{merchant_public_key}}'const response = await fetch("{{base_url}}/merchants/transactions/orders/{{order_token}}/installments?payment_method={{payment_method}}&method_type=wallet&payment_method_id={{payment_method_id}}", { method: "GET", headers: { "x-api-key": "{{merchant_public_key}}" } }); if (!response.ok) throw new Error(`Request failed: ${response.status}`); const data = await response.json();import requests response = requests.request( "GET", "{{base_url}}/merchants/transactions/orders/{{order_token}}/installments?payment_method={{payment_method}}&method_type=wallet&payment_method_id={{payment_method_id}}", headers={ "x-api-key": "{{merchant_public_key}}" }, ) response.raise_for_status() data = response.json()<?php $curl = curl_init(); curl_setopt_array($curl, [ CURLOPT_URL => "{{base_url}}/merchants/transactions/orders/{{order_token}}/installments?payment_method={{payment_method}}&method_type=wallet&payment_method_id={{payment_method_id}}", CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "x-api-key: {{merchant_public_key}}" ] ]); $response = curl_exec($curl); curl_close($curl);import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; public class Example { public static void main(String[] args) throws Exception { HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("{{base_url}}/merchants/transactions/orders/{{order_token}}/installments?payment_method={{payment_method}}&method_type=wallet&payment_method_id={{payment_method_id}}")) .header("x-api-key", "{{merchant_public_key}}") .method("GET", HttpRequest.BodyPublishers.noBody()) .build(); HttpResponse<String> response = HttpClient.newHttpClient().send( request, HttpResponse.BodyHandlers.ofString() ); System.out.println(response.body()); } }package main import ( "fmt" "io" "net/http" ) func main() { request, err := http.NewRequest("GET", "{{base_url}}/merchants/transactions/orders/{{order_token}}/installments?payment_method={{payment_method}}&method_type=wallet&payment_method_id={{payment_method_id}}", nil) if err != nil { panic(err) } request.Header.Set("x-api-key", "{{merchant_public_key}}") response, err := http.DefaultClient.Do(request) if err != nil { panic(err) } defer response.Body.Close() body, _ := io.ReadAll(response.Body) fmt.Println(string(body)) }Resposta
JSON{ "installments": [ { "installments": 3, "installments_amount": 3333, "display_installments_amount": "MXN 33.33", "installment_rate": 0, "display_installment_label": "3 de $33.33 sin interés", "plan_option_id": "2e0cc595-40e6-4ecf-b43b-35d5c33f88b6", "installment_total_amount": 10000, "installment_tax": [], "display_installment_total_amount": "MXN 100.00" }, { "installments": 6, "installments_amount": 1666, "display_installments_amount": "MXN 16.66", "installment_rate": 0, "display_installment_label": "6 de $16.66 sin interés", "plan_option_id": "25c7ef41-ebe8-4197-bdb3-f8651c261ea8", "installment_total_amount": 10000, "installment_tax": [], "display_installment_total_amount": "MXN 100.00" } ] } -
Realize a compra
Use a guia da Purchase V2. Aqui está uma lista de campos obrigatórios para a carteira do PayPal:
Campo Descrição Valor payment_source.method_typeTipo de método de pagamento DEUNA walletpayment_source.processorIdentificador do método de pagamento da Carteira PayPal. paypal_walletpayment_source.payment_methodToken de conta PayPal. 6fe9a045-9a46-4b25-8b60-d5a9586494c5payment_source.payment_method_idID do método de pagamento da Carteira PayPal retornado no idcampo do Obtenha métodos de pagamento response.58745b8e-7127-44ea-84ef-656b3ffc611b- Carga útil
JSON
{ "order_type": "DEUNA_CHECKOUT", "order_token": "{{order-token}}", "payer_info": { "email": "johndoe@deuna.com" }, "payment_source": { "method_type": "wallet", // required for PayPal Wallet "processor": "paypal_wallet", // required for PayPal Wallet "payment_method": "{{payment_method}}", // required "payment_method_id": "{{payment_method_id}}" // required }, "anti_fraud_info": { "device": { "id": "xxxxxxx" // PayPal device ID, used in STC } } }
Resposta
JSON{ "order_type": "DEUNA_CHECKOUT", "order_token": "c582917a-07d2-4f07-b107-fd535e5565cb", "order": { "order_id": "777e66e5-3326-4b04-ad0a-93be7f2028bb", "store_code": "all", "currency": "MXN", "tax_amount": 0, "display_tax_amount": "", "shipping_amount": 0, "display_shipping_amount": "MXN 0.00", "items_total_amount": 2175, "display_items_total_amount": "MXN 21.75", "sub_total": 2075, "display_sub_total": "MXN 20.75", "total_amount": 2190, "display_total_amount": "MXN 21.90", ... "status": "succeeded", "payment": { "data": { "method_type": "wallet", "processor": "paypal_wallet", "customer": { "email": "user_dev_219@testuser.com", "id": "9d920735-c3b1-4908-aba2-762d86fda7e0", "first_name": "", "last_name": "" }, "status": "processed", "external_transaction_id": "0YF74805EM9345944", ... } }, ... "callback_urls": null } }Status esperados:
succeeded: Pagamento concluído com sucesso.denied: Ocorreu um erro ao processar o pagamento.
- Carga útil
Integre o FraudNet#
Fraudnet é uma biblioteca desenvolvida pelo PayPal que analisa os dados enviados pelo navegador durante todo o processo de compra para evitar possíveis fraudes nas transações realizadas.
O Fraudnet deve estar em execução durante todo o processo de transação. Para sua integração, o PayPal fornece a seguinte documentação: Integre o FraudNet
Valores de desconto#
Os descontos no PayPal são suportados no nível do pedido. Na carga útil, você deve processar qualquer desconto por meio discount_amount.