# Aceite pagamentos com cartão sem webhooks
Saiba como confirmar um pagamento com cartão no servidor e processar solicitações de autenticação de cartão.
# Web
> A Stripe recomenda usar o [Payment Element](https://docs.stripe.com/payments/quickstart-checkout-sessions.md) mais recente em vez do Card Element. Ele permite aceitar várias formas de pagamento com um único Element. Saiba mais sobre [quando usar o Card Element e o Payment Element](https://docs.stripe.com/payments/payment-card-element-comparison.md).
Para ter mais opções de suporte e preparo para o futuro, use a [integração padrão](https://docs.stripe.com/payments/accept-a-payment.md) para pagamentos assíncronos.
Esta integração aguarda a resposta do cliente e finaliza o pagamento no servidor, sem usar *webhooks* (A webhook is a real-time push notification sent to your application as a JSON payload through HTTPS requests) nem processar eventos offline. Embora possa parecer mais simples, essa integração é difícil de escalar à medida que sua empresa cresce e apresenta várias limitações:
Se você estiver migrando uma integração Stripe existente da API Charges, use o [guia de migração](https://docs.stripe.com/payments/payment-intents/migration.md).
- **Só aceita cartões**: será preciso programar seu código separadamente para aceitar ACH e formas de pagamento regionais populares.
- **Risco de cobrança dupla**: ao criar um novo PaymentIntent de forma sincronizada sempre que o cliente tenta pagar, você corre o risco de cobrar o cliente duas vezes. Siga as [práticas recomendadas](https://docs.stripe.com/error-low-level.md#idempotency).
- **Ações adicionais do cliente**: cartões com 3D Secure ou sujeitos a normas como a *Autenticação Forte de Cliente* (Strong Customer Authentication (SCA) is a regulatory requirement in effect as of September 14, 2019, that impacts many European online payments. It requires customers to use two-factor authentication like 3D Secure to verify their purchase) exigem mais ações do cliente.
Se decidir usar esta integração, considere essas limitações. Caso contrário, use a [integração padrão](https://docs.stripe.com/payments/accept-a-payment.md).
## Configurar a Stripe
Primeiro, você precisa de uma conta Stripe. [Inscreva-se aqui](https://dashboard.stripe.com/register).
Use nossas bibliotecas oficiais para acessar a API Stripe no seu aplicativo:
#### Ruby
```bash
# Available as a gem
sudo gem install stripe
```
```ruby
# If you use bundler, you can add this line to your Gemfile
gem 'stripe'
```
## Coletar dados do cartão [Lado do cliente]
Obtenha os dados do cartão do cliente com o Stripe.js e o Stripe Elements. O Elements é um conjunto de componentes de IU pré-configurados para coleta e validação de número de cartão, código postal e data de validade.
Um Stripe Element contém um iframe que envia com segurança os dados de pagamento para a Stripe por uma conexão HTTPS. O endereço da página de checkout também deve iniciar com https://, e não http://, para que sua integração funcione.
Você pode testar sua integração sem usar HTTPS. [Habilite-o](https://docs.stripe.com/security/guide.md#tls) quando estiver pronto para aceitar pagamentos no modo de produção.
#### HTML + JS
Inclua o script [Stripe.js](https://docs.stripe.com/js.md) no cabeçalho de todas as páginas do seu site. O Elements fica automaticamente disponível como recurso do Stripe.js.
```html
```
Incluir o script em todas as páginas do site permite aproveitar as [funções antifraude avançadas](https://docs.stripe.com/radar.md) da Stripe e a detecção de comportamentos anormais de navegação.
### Montar o formulário de pagamentos
Para coletar com segurança dados dos cartões dos clientes, o Elements cria componentes de IU para você hospedados pela Stripe. Eles são colocados no seu formulário de pagamento como um iframe. Para determinar onde os componentes serão inseridos, crie elementos DOM vazios (contêineres) com IDs exclusivos no formulário de pagamento.
#### HTML
```html
```
Em seguida, crie uma instância do [objeto Stripe](https://docs.stripe.com/js.md#stripe-function), fornecendo sua [chave de API](https://docs.stripe.com/keys.md) publicável como o primeiro parâmetro. Em seguida, crie uma instância do [objeto Elements](https://docs.stripe.com/js.md#stripe-elements) e use-a para [montar](https://docs.stripe.com/js.md#element-mount) um elemento Card no espaço reservado correspondente da página.
```javascript
const stripe = Stripe('<>');
const elements = stripe.elements();
// Set up Stripe.js and Elements to use in checkout form
const style = {
base: {
color: "#32325d",
fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
fontSmoothing: "antialiased",
fontSize: "16px",
"::placeholder": {
color: "#aab7c4"
}
},
invalid: {
color: "#fa755a",
iconColor: "#fa755a"
},
};
const cardElement = elements.create('card', {style});
cardElement.mount('#card-element');
```
O elemento `card` simplifica o formulário e minimiza o número de campos necessários, inserindo um único campo de entrada flexível que coleta com segurança todos os dados necessários do cartão.
Do contrário, combine os elementos `cardNumber`, `cardExpiry` e `cardCvc` para criar um formulário de cartão flexível, com vários campos.
> Sempre colete um código postal para aumentar as taxas de aceitação de cartão e reduzir fraudes.
>
> O [Card Element de uma única linha](https://docs.stripe.com/js/element/other_element?type=card) coleta e envia automaticamente o código postal do cliente à Stripe. Se você criar um formulário de pagamento com Elements divididos ([Card Number](https://docs.stripe.com/js/element/other_element?type=cardNumber), [Expiry](https://docs.stripe.com/js/element/other_element?type=cardExpiry), [CVC](https://docs.stripe.com/js/element/other_element?type=cardCvc)), adicione um campo de entrada separado para o código postal do cliente.
### Criar um PaymentMethod
Por último, use [stripe.createPaymentMethod](https://docs.stripe.com/js/payment_methods/create_payment_method) no cliente para obter os dados do cartão e criar um [PaymentMethod](https://docs.stripe.com/api/payment_methods.md) quando o usuário clicar no botão Enviar.
```javascript
const form = document.getElementById('payment-form');
form.addEventListener('submit', async (event) => {
// We don't want to let default form submission happen here,
// which would refresh the page.
event.preventDefault();
const result = await stripe.createPaymentMethod({
type: 'card',
card: cardElement,
billing_details: {
// Include any additional collected billing details.
name: 'Jenny Rosen',
},
});
stripePaymentMethodHandler(result);
});
```
#### React
#### npm
Instale o [React Stripe.js](https://www.npmjs.com/package/@stripe/react-stripe-js) e o [carregador Stripe.js](https://www.npmjs.com/package/@stripe/stripe-js) do registro público npm.
```bash
npm install --save @stripe/react-stripe-js @stripe/stripe-js
```
#### umd
Também fornecemos uma compilação UMD para sites que não usam npm nem módulos.
Insira o script Stripe.js, que exporta uma função `Stripe` global, e a compilação UMD de React Stripe.js, que exporta um objeto `ReactStripe` global. Sempre carregue o script Stripe.js diretamente de **js.stripe.com** para manter a conformidade com PCI. Não insira o script em um pacote nem hospede sua própria cópia dele.
```html
```
> A [demonstração da CodeSandbox](https://codesandbox.io/s/react-stripe-official-q1loc?fontsize=14&hidenavigation=1&theme=dark) permite testar o React Stripe.js sem criar um novo projeto.
### Adicione Stripe.js e Elements à sua página
Para usar componentes do Elements, encapsule o componente da página de checkout em um [provedor do Elements](https://docs.stripe.com/sdks/stripejs-react.md#elements-provider). Chame `loadStripe` com sua chave publicável e passe a `Promise` retornada para o provedor `Elements`.
```jsx
import React from 'react';
import ReactDOM from 'react-dom';
import {Elements} from '@stripe/react-stripe-js';
import {loadStripe} from '@stripe/stripe-js';
import CheckoutForm from './CheckoutForm';
// Make sure to call `loadStripe` outside of a component's render to avoid
// recreating the `Stripe` object on every render.
const stripePromise = loadStripe('<>');
function App() {
return (
);
};
ReactDOM.render(, document.getElementById('root'));
```
### Adicionar e configurar um componente CardElement
Use Elements individuais, como `CardElement`, para montar seu formulário.
#### JSX
```jsx
/**
* Use the CSS tab above to style your Element's container.
*/
import React from 'react';
import {CardElement} from '@stripe/react-stripe-js';
import './Styles.css'
const CARD_ELEMENT_OPTIONS = {
style: {
base: {
color: "#32325d",
fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
fontSmoothing: "antialiased",
fontSize: "16px",
"::placeholder": {
color: "#aab7c4",
},
},
invalid: {
color: "#fa755a",
iconColor: "#fa755a",
},
},
};
function CardSection() {
return (
);
};
export default CardSection;
```
Os elementos são totalmente personalizáveis. Você pode [modificar o Elements](https://docs.stripe.com/js/elements_object/create_element?type=card#elements_create-options) de acordo com a aparência do seu site, proporcionando um checkout perfeito para seus clientes. Também é possível modificar vários estados de entrada, como quando o Element está em foco.
O `CardElement` simplifica o formulário e minimiza o número de campos necessários, inserindo um campo único e flexível que coleta com segurança todos os dados de cartão e faturamento. Você também pode combinar `CardNumberElement`, `CardExpiryElement` e `CardCvcElement` para montar um formulário flexível com vários campos para os dados de cartão.
> Sempre colete um código postal para aumentar as taxas de aceitação de cartão e reduzir fraudes.
>
> O [Card Element de uma única linha](https://docs.stripe.com/js/element/other_element?type=card) coleta e envia automaticamente o código postal do cliente à Stripe. Se você criar um formulário de pagamento com Elements divididos ([Card Number](https://docs.stripe.com/js/element/other_element?type=cardNumber), [Expiry](https://docs.stripe.com/js/element/other_element?type=cardExpiry), [CVC](https://docs.stripe.com/js/element/other_element?type=cardCvc)), adicione um campo de entrada separado para o código postal do cliente.
### Criar um PaymentMethod
No gerenciador de envio de sua forma de pagamento, use [stripe.createPaymentMethod](https://docs.stripe.com/js/payment_methods/create_payment_method) para coletar os dados do cartão e criar um [PaymentMethod](https://docs.stripe.com/api/payment_methods.md).
Para chamar `stripe.createPaymentMethod` pelo componente de formulário de pagamentos, use os hooks [useStripe](https://docs.stripe.com/sdks/stripejs-react.md#usestripe-hook) e [useElements](https://docs.stripe.com/sdks/stripejs-react.md#useelements-hook).
Se preferir componentes de classe tradicionais em vez de hooks, use um [ElementsConsumer](https://docs.stripe.com/sdks/stripejs-react.md#elements-consumer).
#### Hooks
```jsx
import React from 'react';
import {useStripe, useElements, CardElement} from '@stripe/react-stripe-js';
import CardSection from './CardSection';
export default function CheckoutForm() {
const stripe = useStripe();
const elements = useElements();
const handleSubmit = async (event) => {
// We don't want to let default form submission happen here,
// which would refresh the page.
event.preventDefault();
if (!stripe || !elements) {
// Stripe.js hasn't yet loaded.
// Make sure to disable form submission until Stripe.js has loaded.
return;
}const result = await stripe.createPaymentMethod({
type: 'card',
card: elements.getElement(CardElement),
billing_details: {
// Include any additional collected billing details.
name: 'Jenny Rosen',
},
});
stripePaymentMethodHandler(result);
};
return (
);
}
```
#### Componentes de classe
```jsx
import React from 'react';
import {ElementsConsumer, CardElement} from '@stripe/react-stripe-js';
import CardSection from './CardSection';
class CheckoutForm extends React.Component {
handleSubmit = async (event) => {
// We don't want to let default form submission happen here,
// which would refresh the page.
event.preventDefault();
const {stripe, elements} = this.props
if (!stripe || !elements) {
// Stripe.js hasn't yet loaded.
// Make sure to disable form submission until Stripe.js has loaded.
return;
}const result = await stripe.createPaymentMethod({
type: 'card',
card: elements.getElement(CardElement),
billing_details: {
// Include any additional collected billing details.
name: 'Jenny Rosen',
}
});
stripePaymentMethodHandler(result);
};
render() {
const {stripe} = this.props;
return (
);
}
}
export default function InjectedCheckoutForm() {
return (
{({stripe, elements}) => (
)}
);
}
```
## Envie o PaymentMethod ao seu servidor [Lado do cliente]
Se o *PaymentMethod* (PaymentMethods represent your customer's payment instruments, used with the Payment Intents or Setup Intents APIs) for criado corretamente, envie o ID dele para o seu servidor.
```javascript
const stripePaymentMethodHandler = async (result) => {
if (result.error) {
// Show error in payment form
} else {
// Otherwise send paymentMethod.id to your server (see Step 4)
const res = await fetch('/pay', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
payment_method_id: result.paymentMethod.id,
}),
})
const paymentResponse = await res.json();
// Handle server response (see Step 4)
handleServerResponse(paymentResponse);
}
}
```
## Criar um PaymentIntent [Lado do servidor]
Configure um endpoint no seu servidor para receber a solicitação. Esse endpoint também será usado [mais à frente](https://docs.stripe.com/payments/accept-a-payment-synchronously.md#confirm-again), para gerenciar cartões que exijam mais uma etapa de autenticação.
[Crie um novo PaymentIntent](https://docs.stripe.com/payments/payment-intents.md#creating-a-paymentintent) com o ID do [PaymentMethod](https://docs.stripe.com/api/payment_methods/object.md) criado no cliente. Você pode *confirmar* (Confirming a PaymentIntent indicates that the customer intends to pay with the current or provided payment method. Upon confirmation, the PaymentIntent attempts to initiate a payment) o PaymentIntent definindo a propriedade [confirm](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-confirm) como verdadeira quando o PaymentIntent for criado ou invocando [confirm](https://docs.stripe.com/api/payment_intents/confirm.md) após a criação. Também permitimos [autorização e captura separadas](https://docs.stripe.com/payments/place-a-hold-on-a-payment-method.md) para pagamentos com cartão.
Se o pagamento exigir ações adicionais, como autenticação do 3D Secure, o status do PaymentIntent será definido como `requires_action`. Se o pagamento falhar, o status será definido novamente como `requires_payment_method` e você deverá mostrar um erro ao usuário. Se o pagamento não exigir autenticação adicional, uma cobrança será criada e o status do PaymentIntent será definido como `succeeded`.
> Nas versões do API anteriores a [2019-02-11](https://docs.stripe.com/upgrades.md#2019-02-11), `requires_payment_method` aparece como `requires_source` e `requires_action` aparece como `requires_source_action`.
#### curl
```bash
curl https://api.stripe.com/v1/payment_intents \
-u <>: \
-d "payment_method"="{{PAYMENT_METHOD_ID}}" \
-d "amount"=1099 \
-d "currency"="usd" \
-d "confirmation_method"="manual" \
-d "confirm"="true"
```
Para salvar o cartão e poder reutilizá-lo depois, crie um [Customer](https://docs.stripe.com/api/customers/create.md) para armazenar o *PaymentMethod* (PaymentMethods represent your customer's payment instruments, used with the Payment Intents or Setup Intents APIs) e insira os seguintes parâmetros ao criar o PaymentIntent:
- [cliente](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-customer). Configurado com o ID do *Cliente* (Customer objects represent customers of your business. They let you reuse payment methods and give you the ability to track multiple payments).
- [setup_future_usage](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-setup_future_usage). Defina como `off_session` para avisar Stripe que você planeja reutilizar esta forma de pagamento para *off-session payments* (A payment is described as off-session if it occurs without the direct involvement of the customer, using previously-collected payment information) quando sua cliente não estiver presente. Definir essa propriedade salva a forma de pagamento para o cliente após a confirmação do PaymentIntent e todas as ações necessárias do usuário forem concluídas. Veja o exemplo de código em [ salvar cartões após um pagamento](https://github.com/stripe-samples/saving-card-after-payment/tree/master/without-webhooks) para saber mais detalhes.
## Gerenciar outras ações [Lado do cliente]
Programe o gerenciamento de situações em que o cliente precisa intervir. Um pagamento normalmente é finalizado após a confirmação no servidor, na [etapa 4](https://docs.stripe.com/payments/accept-a-payment-synchronously.md#create-payment-intent). No entanto, se o PaymentIntent exigir mais alguma ação do cliente, como autenticação com *3D Secure* (3D Secure (3DS) provides an additional layer of authentication for credit card transactions that protects businesses from liability for fraudulent card payments), este código é acionado.
Use [stripe.handleCardAction](https://docs.stripe.com/js/payment_intents/handle_card_action) para acionar a IU para gerenciar a ação do cliente. Se a autenticação for bem-sucedida, o status do PaymentIntent será `requires_confirmation`. Confirme o PaymentIntent novamente no servidor para finalizar o pagamento.
Durante os testes, use um [número de cartão para testes](https://docs.stripe.com/testing.md#regulatory-cards) com autenticação obrigatória (por exemplo, 4000002760003184) para testar esse fluxo. Se você usar um cartão que não exige autenticação (por exemplo, 4242424242424242), esta parte do fluxo será ignorada, e ela será concluída na etapa 4.
```javascript
const handleServerResponse = async (response) => {
if (response.error) {
// Show error from server on payment form
} else if (response.requires_action) {
// Use Stripe.js to handle the required card action
const { error: errorAction, paymentIntent } =
await stripe.handleCardAction(response.payment_intent_client_secret);
if (errorAction) {
// Show error from Stripe.js in payment form
} else {
// The card action has been handled
// The PaymentIntent can be confirmed again on the server
const serverResponse = await fetch('/pay', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ payment_intent_id: paymentIntent.id })
});
handleServerResponse(await serverResponse.json());
}
} else {
// Show success message
}
}
```
> `stripe.handleCardAction` pode levar vários segundos para ser concluído. Durante esse período, desative o formulário para impedir que seja reenviado e exiba um indicador de espera, como um spinner. Se receber um erro, mostre-o ao cliente, ative o formulário novamente e oculte o indicador de espera. Se o cliente precisar executar etapas adicionais para concluir o pagamento, como autenticação, o Stripe.js o orienta durante esse processo.
## Confirmar o PaymentIntent novamente [Lado do servidor]
Esse código só é executado quando um pagamento exige autenticação adicional, assim como no gerenciamento da etapa anterior. O código em si não é opcional, porque qualquer pagamento pode exigir essa etapa extra.
Com o mesmo endpoint que você configurou [acima](https://docs.stripe.com/payments/accept-a-payment-synchronously.md#create-payment-intent), *confirme* (Confirming an intent indicates that the customer intends to use the current or provided payment method. Upon confirmation, the intent attempts to initiate the portions of the flow that have real-world side effects) o PaymentIntent mais uma vez para finalizar o pagamento e *executar* (Fulfillment is the process of providing the goods or services purchased by a customer, typically after payment is collected) o pedido. Esta confirmação precisa acontecer no máximo uma hora após a tentativa de pagamento. Do contrário, o pagamento falha e volta ao status `requires_payment_method`.
#### curl
```bash
curl https://api.stripe.com/v1/payment_intents/{{PAYMENT_INTENT_ID}}/confirm \
-u <>: \
-X "POST"
```
## Testar a integração
Vários cartões de teste estão disponíveis para você usar em uma área restrita para assegurar que essa integração esteja pronta. Use-os com qualquer CVC e uma data de validade no futuro.
| Número | Descrição |
| ---------------- | -------------------------------------------------------------------------------------------- |
| 4242424242424242 | Finaliza e processa o pagamento imediatamente. |
| 4000002500003155 | Requer autenticação. A Stripe abre uma janela solicitando que o cliente faça a autenticação. |
| 4000000000009995 | Sempre falha, com o código de recusa `insufficient_funds`. |
Veja a lista completa de cartões de teste em nosso guia de [testes](https://docs.stripe.com/testing.md).
## Optional: Coletar novamente um CVC
When creating subsequent payments on a saved card, you might want to re-collect the CVC of the card as an additional fraud measure to verify the user.
Comece [relacionando](https://docs.stripe.com/api/payment_methods/list.md) as formas de pagamento associadas ao *cliente* (Customer objects represent customers of your business. They let you reuse payment methods and give you the ability to track multiple payments) para determinar qual delas será exibida para nova coleta de CVC. No cliente, use o elemento `cardCvc` para coletar novamente um valor de CVC de uma das formas de pagamento do usuário e, em seguida, tokenize os dados do CVC usando [stripe.createToken](https://docs.stripe.com/js/tokens/create_token?type=cvc_update).
Depois de enviar o token de CVC para seu servidor, crie um PaymentIntent no servidor com o valor, a moeda e o token de CVC no parâmetro `payment_method_options[card][cvc_token]`. Assim como os outros tokens, você não pode usar tokens de CVC mais de uma vez, então cada PaymentIntent deve usar seu próprio token de CVC exclusivo.
```curl
curl https://api.stripe.com/v1/payment_intents \
-u "<>:" \
-d payment_method={{PAYMENT_METHOD_ID}} \
-d customer={{CUSTOMER_ID}} \
-d amount=1099 \
-d currency=usd \
-d confirmation_method=manual \
-d confirm=true \
-d "payment_method_options[card][cvc_token]={{CVC_TOKEN_ID}}"
```
A payment might succeed even with a failed CVC check. To prevent this, configure your [Radar rules](https://docs.stripe.com/radar/rules.md#traditional-bank-checks) to block payments when CVC verification fails.
# iOS
Para ter mais opções de suporte e preparo para o futuro, use a [integração padrão](https://docs.stripe.com/payments/accept-a-payment.md) para pagamentos assíncronos.
Esta integração usa um único fluxo do cliente para o servidor para processar pagamentos, sem usar *webhooks* (A webhook is a real-time push notification sent to your application as a JSON payload through HTTPS requests) ou processar eventos offline. Embora possa parecer mais simples, essa integração é difícil de escalar à medida que sua empresa cresce e apresenta várias limitações:
- **Só aceita cartões**: será preciso programar seu código separadamente para aceitar ACH e formas de pagamento regionais populares.
- **Risco de cobrança dupla**: ao criar um novo PaymentIntent de forma sincronizada sempre que o cliente tenta pagar, você corre o risco de cobrar o cliente duas vezes. Siga as [práticas recomendadas](https://docs.stripe.com/error-low-level.md#should-retry).
- **Gerenciamento manual da autenticação**: cartões com 3D Secure ou sujeitos a normas como a *Autenticação Forte de Cliente* (Strong Customer Authentication (SCA) is a regulatory requirement in effect as of September 14, 2019, that impacts many European online payments. It requires customers to use two-factor authentication like 3D Secure to verify their purchase) exigem mais ações do cliente.
Se decidir usar esta integração, considere essas limitações. Caso contrário, use a [integração padrão](https://docs.stripe.com/payments/accept-a-payment.md).
## Configurar a Stripe [Lado do cliente] [Lado do servidor]
Primeiro, você precisa de uma conta Stripe. [Inscreva-se aqui](https://dashboard.stripe.com/register).
### Lado do servidor
Esta integração exige que os endpoints do seu servidor se comuniquem com a API da Stripe. Use nossas bibliotecas oficiais para acessar a API da Stripe a partir do seu servidor:
#### Ruby
```bash
# Available as a gem
sudo gem install stripe
```
```ruby
# If you use bundler, you can add this line to your Gemfile
gem 'stripe'
```
### Lado do cliente
O [SDK da Stripe para iOS](https://github.com/stripe/stripe-ios) é de código aberto, [totalmente documentado](https://stripe.dev/stripe-ios/index.html) e compatível com aplicativos que aceitam iOS 13 ou versões mais recentes.
#### Gerenciador de pacotes Swift
Para instalar o SDK, siga estas etapas:
1. No Xcode, selecione **Arquivo** > **Adicionar dependências de pacote…** e insira `https://github.com/stripe/stripe-ios-spm` como URL do repositório.
1. Selecione o número da última versão da nossa [página de lançamentos](https://github.com/stripe/stripe-ios/releases).
1. Adicione o produto **StripePaymentsUI** ao [alvo do seu aplicativo](https://developer.apple.com/documentation/swift_packages/adding_package_dependencies_to_your_app).
#### CocoaPods
1. Se ainda não o fez, instale a versão mais recente do [CocoaPods](https://guides.cocoapods.org/using/getting-started.html).
1. Se não tiver um [Podfile](https://guides.cocoapods.org/syntax/podfile.html), execute o seguinte comando para criar um:
```bash
pod init
```
1. Adicione esta linha ao seu `Podfile`:
```podfile
pod 'StripePaymentsUI'
```
1. Execute o seguinte comando:
```bash
pod install
```
1. Não se esqueça de usar o arquivo `.xcworkspace` para abrir seu projeto em Xcode, em vez do arquivo `.xcodeproj`, daqui em diante.
1. No futuro, para atualizar para a versão mais recente do SDK, execute:
```bash
pod update StripePaymentsUI
```
#### Carthage
1. Se ainda não o fez, instale a versão mais recente do [Carthage](https://github.com/Carthage/Carthage#installing-carthage).
1. Adicione esta linha ao seu `Cartfile`:
```cartfile
github "stripe/stripe-ios"
```
1. Siga as [instruções de instalação do Carthage](https://github.com/Carthage/Carthage#if-youre-building-for-ios-tvos-or-watchos). Certifique-se de integrar todas as estruturas necessárias listadas [here](https://github.com/stripe/stripe-ios/tree/master/StripePaymentsUI/README.md#manual-linking).
1. No futuro, para atualizar para a versão mais recente do SDK, execute o seguinte comando:
```bash
carthage update stripe-ios --platform ios
```
#### Estrutura manual
1. Vá até a nossa [página de lançamentos do GitHub](https://github.com/stripe/stripe-ios/releases/latest) e baixe e descompacte o **Stripe.xcframework.zip**.
1. Arraste **StripePaymentsUI.xcframework** até a seção **Embedded Binaries** das configurações **General** no seu projeto Xcode. Certifique-se de selecionar **Copy items if needed**.
1. Repita a etapa 2 para todas as estruturas necessárias listadas [here](https://github.com/stripe/stripe-ios/tree/master/StripePaymentsUI/README.md#manual-linking).
1. No futuro, para atualizar para a versão mais recente do nosso SDK, repita as etapas 1 a 3.
> Para obter mais informações sobre a versão mais recente e as versões anteriores do SDK, consulte a página [Lançamentos](https://github.com/stripe/stripe-ios/releases) no GitHub. Para receber notificações quando um novo lançamento for publicado, [assista aos lançamentos](https://help.github.com/en/articles/watching-and-unwatching-releases-for-a-repository#watching-releases-for-a-repository) do repositório.
Configure o SDK com sua [chave publicável da Stripe](https://dashboard.stripe.com/test/apikeys) na inicialização do aplicativo. Isso permite que seu aplicativo faça solicitações à API da Stripe .
#### Swift
```swift
import UIKitimportStripePaymentsUI
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {StripeAPI.defaultPublishableKey = "<>"
// do any other necessary launch configuration
return true
}
}
```
> Use suas [chaves de teste](https://docs.stripe.com/keys.md#obtain-api-keys) enquanto testa e desenvolve, e suas chaves de [modo de produção](https://docs.stripe.com/keys.md#test-live-modes) quando publicar seu aplicativo.
## Crie sua tela de checkout [Lado do cliente]
Colete dados de cartões com segurança usando [STPPaymentCardTextField](https://stripe.dev/stripe-ios/stripe-payments-ui/Classes/STPPaymentCardTextField.html), um componente de IU inserível fornecido pelo SDK que coleta o número do cartão, a data de validade, o CVC e o código postal.

Crie uma instância do componente de cartão e um botão “Pagar”, com o seguinte código:
#### Swift
```swift
import UIKit
import StripePaymentsUI
class CheckoutViewController: UIViewController {
lazy var cardTextField: STPPaymentCardTextField = {
let cardTextField = STPPaymentCardTextField()
return cardTextField
}()
lazy var payButton: UIButton = {
let button = UIButton(type: .custom)
button.layer.cornerRadius = 5
button.backgroundColor = .systemBlue
button.titleLabel?.font = UIFont.systemFont(ofSize: 22)
button.setTitle("Pay", for: .normal)
button.addTarget(self, action: #selector(pay), for: .touchUpInside)
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
let stackView = UIStackView(arrangedSubviews: [cardTextField, payButton])
stackView.axis = .vertical
stackView.spacing = 20
stackView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(stackView)
NSLayoutConstraint.activate([
stackView.leftAnchor.constraint(equalToSystemSpacingAfter: view.leftAnchor, multiplier: 2),
view.rightAnchor.constraint(equalToSystemSpacingAfter: stackView.rightAnchor, multiplier: 2),
stackView.topAnchor.constraint(equalToSystemSpacingBelow: view.topAnchor, multiplier: 2),
])
}
@objc
func pay() {
// ...
}
}
```
Execute seu aplicativo e verifique se a tela de checkout mostra o componente de cartão e o botão de pagamento.
## Coletar dados do cartão [Lado do cliente]
Quando o cliente estiver pronto para fazer o checkout, crie um *PaymentMethod* (PaymentMethods represent your customer's payment instruments, used with the Payment Intents or Setup Intents APIs) com os detalhes coletados pelo elemento do cartão.
#### Swift
```swift
class CheckoutViewController: UIViewController {
// ...
@objc
func pay() {
// Collect card details on the client
STPAPIClient.shared.createPaymentMethod(with: cardTextField.paymentMethodParams) { [weak self] paymentMethod, error in
// Create PaymentMethod failed
if let createError = error {
self?.displayAlert(title: "Payment failed", message: createError.localizedDescription)
}
if let paymentMethodId = paymentMethod?.stripeId {
self?.pay(withPaymentMethod: paymentMethodId)
}
}
}
func pay(withPaymentMethod paymentMethodId: String? = nil, withPaymentIntent paymentIntentId: String? = nil) {
// ...continued in the next step
}
// ...
}
```
## Criar um PaymentIntent [Lado do cliente] [Lado do servidor]
A Stripe usa o objeto `PaymentIntent` para representar sua intenção de coletar o pagamento de um cliente, acompanhando suas tentativas de cobrança e alterações no estado do pagamento durante todo o processo.
### No servidor
Adicione um endpoint que crie o PaymentIntent com os parâmetros a seguir:
- [payment_method_id](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-payment_method) - o ID do PaymentMethod da etapa anterior
- [return_url](https://docs.stripe.com/api/payment_intents/confirm.md#confirm_payment_intent-return_url) - inclua se você tiver [configurado um URL de retorno](https://docs.stripe.com/payments/3d-secure.md)
- [use_stripe_sdk](https://docs.stripe.com/api/payment_intents/confirm.md#confirm_payment_intent-use_stripe_sdk)
- Para os aplicativos que se integram com o [SDK da Stripe para iOS versão 16.0.0](https://github.com/stripe/stripe-ios/blob/master/CHANGELOG.md#1600-2019-07-18) e mais recentes, o valor desse parâmetro deve ser definido como `true`
- Para os aplicativos que se integram com versões mais antigas do SDK, **não passe esse parâmetro**.
- [confirmar](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-confirm) - Defina como verdadeiro para *confirmar* (Confirming a PaymentIntent indicates that the customer intends to pay with the current or provided payment method. Upon confirmation, the PaymentIntent attempts to initiate a payment) o PaymentIntent
Para salvar o cartão e poder reutilizá-lo depois, crie um [Customer](https://docs.stripe.com/api/customers/create.md) para armazenar o PaymentMethod e insira os seguintes parâmetros ao criar o PaymentIntent:
- [cliente](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-customer) - configurado com o ID do *Customer* (Customer objects represent customers of your business. They let you reuse payment methods and give you the ability to track multiple payments).
- [setup_future_usage](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-setup_future_usage) - definido como `off_session` para a Stripe informar que você pretende usar este PaymentMethod para *pagamentos fora da sessão* (A payment is described as off-session if it occurs without the direct involvement of the customer, using previously-collected payment information), sem a presença do cliente. Esta configuração salva o PaymentMethod no Customer depois da confirmação do PaymentIntent e de todas as outras ações obrigatórias para o usuário.
Após a criação do PaymentIntent, retorne o seguinte para o cliente:
- O [segredo do cliente](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-client_secret) do PaymentIntent
- `requiresAction: true` se o [status](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-status) PaymentIntent for `requires_action`
> Veja um [exemplo de implementação no servidor](https://github.com/stripe-samples/accept-a-payment/tree/master/custom-payment-flow/server).
### No cliente
Solicite um `PaymentIntent` do seu servidor. Esse exemplo passa ao servidor uma lista de items para determinar o preço. Sempre defina o valor a ser cobrado no servidor, que é um ambiente seguro, e não no cliente. Dessa forma, você evita que clientes mal-intencionados escolham os próprios preços.
#### Swift
```swift
let BackendUrl = "http://127.0.0.1:4242/"
class CheckoutViewController: UIViewController {
// ...
func displayAlert(title: String, message: String, restartDemo: Bool = false) {
// ...omitted for brevity
}
func pay(withPaymentMethod paymentMethodId: String? = nil, withPaymentIntent paymentIntentId: String? = nil) {
// Create a PaymentIntent on the server
let url = URL(string: BackendUrl + "pay")!
var json: [String: Any] = [:]
if let paymentMethodId = paymentMethodId {
json = [
"useStripeSdk": true,
"paymentMethodId": paymentMethodId,
"currency": "usd",
"items": [
"id": "photo_subscription"
]
]
}
else if let paymentIntentId = paymentIntentId {
json = [
"paymentIntentId": paymentIntentId,
]
}
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: json)
let task = URLSession.shared.dataTask(with: request, completionHandler: { [weak self] (data, response, requestError) in
guard let response = response as? HTTPURLResponse,
response.statusCode == 200,
let data = data,
let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String : Any] else {
self?.displayAlert(title: "Payment failed", message: requestError?.localizedDescription ?? "")
return
}
let payError = json["error"] as? String
let clientSecret = json["clientSecret"] as? String
let requiresAction = json["requiresAction"] as? Bool
// Payment failed
if let payError = payError {
self?.displayAlert(title: "Payment failed", message: payError)
}
// Payment succeeded, no additional action required
else if clientSecret != nil && (requiresAction == nil || requiresAction == false) {
self?.displayAlert(title: "Payment succeeded", message: clientSecret ?? "", restartDemo: true)
}
// Payment requires additional action
else if clientSecret != nil && requiresAction == true && self != nil {
// ...continued in the next step
}
})
task.resume()
}
}
```
## Gerenciar outras ações [Lado do cliente]
Programe o gerenciamento de situações em que o cliente precisa intervir. Os pagamentos costumam ser finalizados após você confirmá-los no servidor, na [etapa 4](https://docs.stripe.com/payments/accept-a-payment-synchronously.md#ios-create-payment-intent). No entanto, se o PaymentIntent exigir mais alguma ação do cliente, como autenticação com *3D Secure* (3D Secure (3DS) provides an additional layer of authentication for credit card transactions that protects businesses from liability for fraudulent card payments), este código é acionado.
Nesses casos, o status do PaymentIntent é definido como `requires_action`. No cliente, passe o ID do PaymentIntent para [STPPaymentHandler handleNextActionForPayment](https://stripe.dev/stripe-ios/stripe-payments/Classes/STPPaymentHandler.html#/c:@M@StripePayments@objc\(cs\)STPPaymentHandler\(im\)handleNextActionForPayment:withAuthenticationContext:returnURL:completion:). `STPPaymentHandler` apresenta controladores de visualização usando o [STPAuthenticationContext](https://stripe.dev/stripe-ios/stripe-payments/Protocols/STPAuthenticationContext.html) passado e orienta o cliente durante a autenticação. Para obter mais detalhes, leia sobre a [autenticação 3D Secure no iOS](https://docs.stripe.com/payments/3d-secure.md?platform=ios).
Depois de gerenciar as ações necessárias no cliente, o status do PaymentIntent muda para `requires_confirmation`. Essa etapa permite que sua integração *execute* (Fulfillment is the process of providing the goods or services purchased by a customer, typically after payment is collected) sincronizadamente o pedido no seu backend e retorne o resultado da execução para o cliente.
Envie o ID do PaymentIntent para seu backend e confirme novamente em até uma hora para finalizar o pagamento. Caso contrário, a tentativa de pagamento falha e o status do SetupIntent volta a ser `requires_payment_method`.
#### Swift
```swift
class CheckoutViewController: UIViewController {
// ...
// Create or confirm a PaymentIntent on the server
func pay(withPaymentMethod paymentMethodId: String? = nil, withPaymentIntent paymentIntentId: String? = nil) {
// ...
// Payment requires additional action
else if clientSecret != nil && requiresAction == true && self != nil {
let paymentHandler = STPPaymentHandler.shared()
paymentHandler.handleNextAction(forPayment: clientSecret!, with: self!, returnURL: nil) { status, paymentIntent, handleActionError in
switch (status) {
case .failed:
self?.displayAlert(title: "Payment failed", message: handleActionError?.localizedDescription ?? "")
break
case .canceled:
self?.displayAlert(title: "Payment canceled", message: handleActionError?.localizedDescription ?? "")
break
case .succeeded:
if let paymentIntent = paymentIntent, paymentIntent.status == STPPaymentIntentStatus.requiresConfirmation {
print("Re-confirming PaymentIntent after handling action")
self?.pay(withPaymentIntent: paymentIntent.stripeId)
}
else {
self?.displayAlert(title: "Payment succeeded", message: paymentIntent?.description ?? "", restartDemo: true)
}
break
@unknown default:
fatalError()
break
}
}
}
// ...
}
}
extension CheckoutViewController: STPAuthenticationContext {
func authenticationPresentingViewController() -> UIViewController {
return self
}
}
```
## Testar a integração
Vários cartões de teste estão disponíveis para você usar em uma área restrita para assegurar que essa integração esteja pronta. Use-os com qualquer CVC e uma data de validade no futuro.
| Número | Descrição |
| ---------------- | -------------------------------------------------------------------------------------------- |
| 4242424242424242 | Finaliza e processa o pagamento imediatamente. |
| 4000002500003155 | Requer autenticação. A Stripe abre uma janela solicitando que o cliente faça a autenticação. |
| 4000000000009995 | Sempre falha, com o código de recusa `insufficient_funds`. |
Veja a lista completa de cartões de teste em nosso guia de [testes](https://docs.stripe.com/testing.md).
## Optional: Coletar novamente um CVC
When creating subsequent payments on a saved card, you might want to re-collect the CVC of the card as an additional fraud measure to verify the user.
Comece [listando](https://docs.stripe.com/api/payment_methods/list.md) as formas de pagamento associadas ao *cliente* (Customer objects represent customers of your business. They let you reuse payment methods and give you the ability to track multiple payments) para determinar qual delas será exibida para nova coleta de CVC. Depois de coletar novamente as informações de CVC do cliente, tokenize os dados do CVC usando [STPAPIClient createTokenForCVCUpdate](https://stripe.dev/stripe-ios/stripe-payments/Classes/STPAPIClient.html#/c:@CM@StripePayments@StripeCore@objc\(cs\)STPAPIClient\(im\)createTokenForCVCUpdate:completion:).
#### Swift
```swift
import UIKit
import StripePaymentsUI
class CheckoutViewController: UIViewController {
// ...
func tokenizeCVC() {
guard let cvc = cvc else {
return;
}
STPAPIClient.shared.createToken(forCVCUpdate: cvc) { (token, error) in
if error != nil || token == nil {
// handle error
} else {
let tokenId = token?.tokenId
// pass the token ID to your backend
}
}
}
// ...
}
```
Depois de enviar o token de CVC para seu servidor, crie um PaymentIntent no servidor com o valor, a moeda e o token de CVC no parâmetro `payment_method_options[card][cvc_token]`.
```curl
curl https://api.stripe.com/v1/payment_intents \
-u "<>:" \
-d payment_method={{PAYMENT_METHOD_ID}} \
-d customer={{CUSTOMER_ID}} \
-d amount=1099 \
-d currency=usd \
-d confirmation_method=manual \
-d confirm=true \
-d "payment_method_options[card][cvc_token]={{CVC_TOKEN_ID}}"
```
A payment might succeed even with a failed CVC check. To prevent this, configure your [Radar rules](https://docs.stripe.com/radar/rules.md#traditional-bank-checks) to block payments when CVC verification fails.
## See also
- [Aceitar Apple Pay](https://docs.stripe.com/apple-pay.md)
# Android
Para ter mais opções de suporte e preparo para o futuro, use a [integração padrão](https://docs.stripe.com/payments/accept-a-payment.md) para pagamentos assíncronos.
Esta integração usa um único fluxo do cliente para o servidor para processar pagamentos, sem usar *webhooks* (A webhook is a real-time push notification sent to your application as a JSON payload through HTTPS requests) ou processar eventos offline. Embora possa parecer mais simples, essa integração é difícil de escalar à medida que sua empresa cresce e apresenta várias limitações:
- **Só aceita cartões**: será preciso programar seu código separadamente para aceitar ACH e formas de pagamento regionais populares.
- **Risco de cobrança dupla**: ao criar um novo PaymentIntent de forma sincronizada sempre que o cliente tenta pagar, você corre o risco de cobrar o cliente duas vezes. Siga as [práticas recomendadas](https://docs.stripe.com/error-low-level.md#should-retry).
- **Gerenciamento manual da autenticação**: cartões com 3D Secure ou sujeitos a normas como a *Autenticação Forte de Cliente* (Strong Customer Authentication (SCA) is a regulatory requirement in effect as of September 14, 2019, that impacts many European online payments. It requires customers to use two-factor authentication like 3D Secure to verify their purchase) exigem mais ações do cliente.
Se decidir usar esta integração, considere essas limitações. Caso contrário, use a [integração padrão](https://docs.stripe.com/payments/accept-a-payment.md).
## Configurar a Stripe [Lado do cliente] [Lado do servidor]
Primeiro, você precisa de uma conta Stripe. [Inscreva-se aqui](https://dashboard.stripe.com/register).
### Lado do servidor
Esta integração exige que os endpoints do seu servidor se comuniquem com a API da Stripe. Use nossas bibliotecas oficiais para acessar a API da Stripe a partir do seu servidor:
#### Ruby
```bash
# Available as a gem
sudo gem install stripe
```
```ruby
# If you use bundler, you can add this line to your Gemfile
gem 'stripe'
```
### Lado do cliente
O [SDK da Stripe para Android](https://github.com/stripe/stripe-android) é de código aberto e [totalmente documentado](https://stripe.dev/stripe-android/).
Para instalar o SDK, adicione `stripe-android` ao bloco `dependencies` do arquivo [app/build.gradle](https://developer.android.com/studio/build/dependencies):
#### Kotlin
```kotlin
plugins {
id("com.android.application")
}
android { ... }
dependencies {
// ...
// Stripe Android SDK
implementation("com.stripe:stripe-android:23.9.1")
// Include the financial connections SDK to support US bank account as a payment method
implementation("com.stripe:financial-connections:23.9.1")
}
```
> Veja mais informações sobre o último lançamento de SDK e as versões anteriores na página [Lançamentos](https://github.com/stripe/stripe-android/releases) no GitHub. Para receber notificações quando um novo lançamento for publicado, [assista aos lançamentos do repositório](https://docs.github.com/en/github/managing-subscriptions-and-notifications-on-github/configuring-notifications#configuring-your-watch-settings-for-an-individual-repository).
Configure o SDK com sua [chave publicável](https://dashboard.stripe.com/apikeys) da Stripe, de modo que seja possível fazer solicitações à API Stripe, como em sua subcategoria `Application`:
#### Kotlin
```kotlin
import com.stripe.android.PaymentConfiguration
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
PaymentConfiguration.init(
applicationContext,
"<>"
)
}
}
```
> Use suas [chaves de teste](https://docs.stripe.com/keys.md#obtain-api-keys) enquanto testa e desenvolve, e suas chaves de [modo de produção](https://docs.stripe.com/keys.md#test-live-modes) quando publicar seu aplicativo.
Nossas amostras de código também usam [OkHttp](https://github.com/square/okhttp) e [GSON](https://github.com/google/gson) para fazer solicitações HTTP a um servidor.
## Crie sua tela de checkout [Lado do cliente]
Colete dados de cartão com segurança no cliente usando o [CardInputWidget](https://stripe.dev/stripe-android/payments-core/com.stripe.android.view/-card-input-widget/index.html), um componente de IU inserível fornecido pelo SDK que coleta número do cartão, data de validade, CVC e código postal

Crie uma instância do componente de cartão e um botão “Pagar”, acrescentando o seguinte ao layout de sua página de checkout:
```xml
```
Execute seu aplicativo e verifique se a tela de checkout mostra o componente de cartão e o botão de pagamento.
## Coletar dados do cartão [Lado do cliente]
Quando o cliente estiver pronto para fazer o checkout, crie um *PaymentMethod* (PaymentMethods represent your customer's payment instruments, used with the Payment Intents or Setup Intents APIs) com os detalhes coletados pelo elemento do cartão.
#### Kotlin
```kotlin
class CheckoutActivity : AppCompatActivity() {
private lateinit var stripe: Stripe
// ...
private fun pay() {
val weakActivity = WeakReference(this)
// Collect card details on the client
val cardInputWidget =
findViewById(R.id.cardInputWidget)
val params = cardInputWidget.paymentMethodCreateParams
if (params == null) {
return
}
// Configure the SDK with your Stripe publishable key so that it can make requests to the Stripe API
stripe = Stripe(applicationContext, PaymentConfiguration.getInstance(applicationContext).publishableKey)
lifecycleScope.launch {
runCatching {
stripe.createPaymentMethod(params)
}.fold(
onSuccess = { result ->
// Create a PaymentIntent on the server with a PaymentMethod
print("Created PaymentMethod")
pay(result.id, null)
},
onFailure = {
displayAlert(weakActivity.get(), "Payment failed", "Error: $it")
}
)
}
}
private fun pay(paymentMethod: String?, paymentIntent: String?) {
// ...
}
}
```
## Criar um PaymentIntent [Lado do cliente] [Lado do servidor]
A Stripe usa o objeto `PaymentIntent` para representar sua intenção de coletar o pagamento de um cliente, acompanhando suas tentativas de cobrança e alterações no estado do pagamento durante todo o processo.
### No servidor
Adicione um endpoint que crie o PaymentIntent com os parâmetros a seguir:
- [payment_method_id](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-payment_method) - o ID do PaymentMethod da etapa anterior
- [use_stripe_sdk](https://docs.stripe.com/api/payment_intents/confirm.md#confirm_payment_intent-use_stripe_sdk)
- Para os aplicativos que se integram com o [SDK da Stripe para Android versão 10.0.0](https://github.com/stripe/stripe-android/blob/master/CHANGELOG.md#1000---2019-07-19) e mais recentes, o valor desse parâmetro deve ser definido como `true`
- Para os aplicativos que se integram com versões mais antigas do SDK, **não passe esse parâmetro**.
- [confirmar](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-confirm) - Defina como verdadeiro para *confirmar* (Confirming a PaymentIntent indicates that the customer intends to pay with the current or provided payment method. Upon confirmation, the PaymentIntent attempts to initiate a payment) o PaymentIntent
Para salvar o cartão e poder reutilizá-lo depois, crie um [Customer](https://docs.stripe.com/api/customers/create.md) para armazenar o PaymentMethod e insira os seguintes parâmetros ao criar o PaymentIntent:
- O [cliente](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-customer) - configurado com o ID do *Customer* (Customer objects represent customers of your business. They let you reuse payment methods and give you the ability to track multiple payments).
- [setup_future_usage](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-setup_future_usage) - definido como `off_session` para a Stripe informar que você pretende usar este PaymentMethod para *pagamentos fora da sessão* (A payment is described as off-session if it occurs without the direct involvement of the customer, using previously-collected payment information), sem a presença do cliente. Esta configuração salva o PaymentMethod no Customer depois da confirmação do PaymentIntent e de todas as outras ações obrigatórias para o usuário.
Após a criação do PaymentIntent, retorne o seguinte para o cliente:
- O [segredo do cliente](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-client_secret) do PaymentIntent
- `requiresAction: true` se o [status](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-status) PaymentIntent for `requires_action`
> Veja um [exemplo de implementação no servidor](https://github.com/stripe-samples/accept-a-payment/tree/master/custom-payment-flow/server).
### No cliente
Solicite um `PaymentIntent` do seu servidor. Esse exemplo passa ao servidor uma lista de items para determinar o preço. Sempre defina o valor a ser cobrado no servidor, que é um ambiente seguro, e não no cliente. Dessa forma, você evita que clientes mal-intencionados escolham os próprios preços.
#### Kotlin
```kotlin
class CheckoutActivity : AppCompatActivity() {
private val backendUrl = "http://10.0.2.2:4242/"
private val httpClient = OkHttpClient()
private fun displayAlert(activity: Activity?, title: String, message: String, restartDemo: Boolean = false) {
// omitted for brevity
}
private fun pay(paymentMethod: String?, paymentIntent: String?) {
val weakActivity = WeakReference(this)
var json = ""
if (!paymentMethod.isNullOrEmpty()) {
json = """
{
"useStripeSdk":true,
"paymentMethodId":"$paymentMethod",
"currency":"usd",
"items": [
{"id":"photo_subscription"}
]
}
"""
}
else if (!paymentIntent.isNullOrEmpty()) {
json = """
{
"paymentIntentId":"$paymentIntent"
}
"""
}
// Create a PaymentIntent on the server
val mediaType = "application/json; charset=utf-8".toMediaType()
val body = json.toRequestBody(mediaType)
val request = Request.Builder()
.url(backendUrl + "pay")
.post(body)
.build()
httpClient.newCall(request)
.enqueue(object: Callback {
override fun onFailure(call: Call, e: IOException) {
displayAlert(weakActivity.get(), "Payment failed", "Error: $e")
}
override fun onResponse(call: Call, response: Response) {
// Request failed
if (!response.isSuccessful) {
displayAlert(weakActivity.get(), "Payment failed", "Error: $response")
} else {
val responseData = response.body?.string()
var responseJson = JSONObject(responseData)
val payError: String? = responseJson.optString("error")
val clientSecret: String? = responseJson.optString("clientSecret")
val requiresAction: Boolean? = responseJson.optBoolean("requiresAction")
// Payment failed
if (payError != null && payError.isNotEmpty()) {
displayAlert(weakActivity.get(), "Payment failed", "Error: $payError")
}
// Payment succeeded
else if ((clientSecret != null && clientSecret.isNotEmpty())
&& (requiresAction == null || requiresAction == false)) {
displayAlert(weakActivity.get(), "Payment succeeded", "$clientSecret", restartDemo = true)
}
// Payment requires additional actions
else if ((clientSecret != null && clientSecret.isNotEmpty())
&& requiresAction == true) {
runOnUiThread {
if (weakActivity.get() != null) {
// ...continued in the next step
}
}
}
}
}
})
}
}
```
## Gerenciar outras ações [Lado do cliente]
Se o pagamento exigir ações adicionais, como *autenticação do 3D Secure* (3D Secure (3DS) provides an additional layer of authentication for credit card transactions that protects businesses from liability for fraudulent card payments), o status do PaymentIntent é definido como `requires_action`. No cliente, passe o ID do `PaymentIntent` para [handleNextActionForPayment](https://stripe.dev/stripe-android/payments-core/com.stripe.android/-stripe/handle-next-action-for-payment.html). Esse SDK apresenta atividades adicionais e orienta o cliente durante a autenticação. Consulte [Suporte à autenticação do 3D Secure no Android](https://docs.stripe.com/payments/3d-secure.md?platform=android) para saber mais.
Depois de gerenciar as ações necessárias no cliente, o status do PaymentIntent é `requires_confirmation`. Essa etapa permite que sua integração *execute* (Fulfillment is the process of providing the goods or services purchased by a customer, typically after payment is collected) sincronizadamente o pedido no seu backend e retorne o resultado da execução para o cliente.
Envie o ID do PaymentIntent para seu backend e confirme novamente em até uma hora para finalizar o pagamento. Caso contrário, a tentativa de pagamento falha e o status do SetupIntent volta a ser `requires_payment_method`.
#### Kotlin
```kotlin
class CheckoutActivity : AppCompatActivity() {
// ...
private fun pay(paymentMethod: String?, paymentIntent: String?) {
// ...
val activity = weakActivity.get()!!
stripe.handleNextActionForPayment(activity, clientSecret)
// ...
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
val weakActivity = WeakReference(this)
// Handle the result of stripe.handleNextActionForPayment
if (stripe.isPaymentResult(requestCode, data)) {
lifecycleScope.launch {
runCatching {
stripe.getPaymentIntentResult(requestCode, data!!)
}.fold(
onSuccess = { result ->
val paymentIntent = result.intent
val status = paymentIntent.status
if (status == StripeIntent.Status.Succeeded) {
val gson = GsonBuilder().setPrettyPrinting().create()
displayAlert(
weakActivity.get(),
"Payment succeeded",
gson.toJson(paymentIntent),
restartDemo = true
)
} else if (status == StripeIntent.Status.RequiresPaymentMethod) {
// Payment failed – allow retrying using a different payment method
displayAlert(
weakActivity.get(),
"Payment failed",
paymentIntent.lastPaymentError!!.message ?: ""
)
} else if (status == StripeIntent.Status.RequiresConfirmation) {
print("Re-confirming PaymentIntent after handling a required action")
pay(null, paymentIntent.id)
} else {
displayAlert(
weakActivity.get(),
"Payment status unknown",
"unhandled status: $status",
restartDemo = true
)
}
}, onFailure = {
// Payment request failed – allow retrying using the same payment method
displayAlert(weakActivity.get(), "Payment failed", it.toString())
}
)
}
}
}
}
```
O resultado da autenticação do pagamento é retornado à atividade que fez a chamada por meio de [Activity#onActivityResult()](https://developer.android.com/reference/android/app/Activity.html#onActivityResult\(int,%20int,%20android.content.Intent\)). Processe o resultado chamando [Stripe#onPaymentResult()](https://stripe.dev/stripe-android/payments-core/com.stripe.android/-stripe/on-payment-result.html) em `Activity#onActivityResult()`. O [PaymentIntentResult](https://stripe.dev/stripe-android/payments-core/com.stripe.android/-payment-intent-result/index.html) retornado em [ApiResultCallback#onSuccess()](https://stripe.dev/stripe-android/payments-core/com.stripe.android/-api-result-callback/on-success.html) tem dois métodos getter:
- `getIntent()` – um objeto [PaymentIntent](https://stripe.dev/stripe-android/payments-core/com.stripe.android/-stripe-intent-result/index.html#com.stripe.android/StripeIntentResult/intent/#/PointingToDeclaration/) obtido após a confirmação/autenticação
- `getOutcome()` – um valor [StripeIntentResult.Status](https://stripe.dev/stripe-android/payments-core/com.stripe.android/-stripe-intent-result/index.html#com.stripe.android/StripeIntentResult/outcome/#/PointingToDeclaration/) que indica o resultado da autenticação do pagamento
- `SUCCEEDED` – autenticação do pagamento realizada
- `FAILED` – falha na autenticação do pagamento
- `CANCELED` – o cliente cancelou a autenticação de pagamento obrigatória
- `TIMEDOUT` – a tentativa de autenticação do pagamento esgotou o limite de tempo
## Testar a integração
Vários cartões de teste estão disponíveis para você usar em uma área restrita para assegurar que essa integração esteja pronta. Use-os com qualquer CVC e uma data de validade no futuro.
| Número | Descrição |
| ---------------- | -------------------------------------------------------------------------------------------- |
| 4242424242424242 | Finaliza e processa o pagamento imediatamente. |
| 4000002500003155 | Requer autenticação. A Stripe abre uma janela solicitando que o cliente faça a autenticação. |
| 4000000000009995 | Sempre falha, com o código de recusa `insufficient_funds`. |
Veja a lista completa de cartões de teste em nosso guia de [testes](https://docs.stripe.com/testing.md).
## Optional: Coletar novamente um CVC
When creating subsequent payments on a saved card, you might want to re-collect the CVC of the card as an additional fraud measure to verify the user.
Comece [relacionando](https://docs.stripe.com/api/payment_methods/list.md) as formas de pagamento associadas ao *cliente* (Customer objects represent customers of your business. They let you reuse payment methods and give you the ability to track multiple payments) para determinar qual delas será exibida para nova coleta de CVC. Depois de coletar novamente as informações de CVC do cliente, tokenize os dados do CVC usando [Stripe#createCvcUpdateToken()](https://stripe.dev/stripe-android/payments-core/com.stripe.android/-stripe/create-cvc-update-token.html).
#### Kotlin
```kotlin
class CheckoutActivity : AppCompatActivity() {
private val stripe: Stripe by lazy {
Stripe(this, "<>")
}
private fun tokenizeCvc(cvc: String) {
stripe.createCvcUpdateToken(
cvc,
callback = CvcUpdateResultCallback()
)
}
private class CvcUpdateResultCallback : ApiResultCallback {
override fun onSuccess(result: Token) {
val tokenId = result.id
// pass token ID to your backend
}
override fun onError(e: Exception) {
// handle error
}
}
}
```
Depois de enviar o token de CVC para seu servidor, crie um PaymentIntent no servidor com o valor, a moeda e o token de CVC no parâmetro `payment_method_options[card][cvc_token]`.
```curl
curl https://api.stripe.com/v1/payment_intents \
-u "<>:" \
-d payment_method={{PAYMENT_METHOD_ID}} \
-d customer={{CUSTOMER_ID}} \
-d amount=1099 \
-d currency=usd \
-d confirmation_method=manual \
-d confirm=true \
-d "payment_method_options[card][cvc_token]={{CVC_TOKEN_ID}}"
```
A payment might succeed even with a failed CVC check. To prevent this, configure your [Radar rules](https://docs.stripe.com/radar/rules.md#traditional-bank-checks) to block payments when CVC verification fails.
## See also
- [Aceitar Google Pay](https://docs.stripe.com/google-pay.md)
# React Native
Para ter mais opções de suporte e preparo para o futuro, use a [integração padrão](https://docs.stripe.com/payments/accept-a-payment.md) para pagamentos assíncronos.
Esta integração usa um único fluxo do cliente para o servidor para processar pagamentos, sem usar *webhooks* (A webhook is a real-time push notification sent to your application as a JSON payload through HTTPS requests) ou processar eventos offline. Embora possa parecer mais simples, essa integração é difícil de escalar à medida que sua empresa cresce e apresenta várias limitações:
- **Só aceita cartões**: será preciso programar seu código separadamente para aceitar ACH e formas de pagamento regionais populares.
- **Risco de cobrança dupla**: ao criar um novo PaymentIntent de forma sincronizada sempre que o cliente tenta pagar, você corre o risco de cobrar o cliente duas vezes. Siga as [práticas recomendadas](https://docs.stripe.com/error-low-level.md#should-retry).
- **Gerenciamento manual da autenticação**: cartões com 3D Secure ou sujeitos a normas como a *Autenticação Forte de Cliente* (Strong Customer Authentication (SCA) is a regulatory requirement in effect as of September 14, 2019, that impacts many European online payments. It requires customers to use two-factor authentication like 3D Secure to verify their purchase) exigem mais ações do cliente.
Se decidir usar esta integração, considere essas limitações. Caso contrário, use a [integração padrão](https://docs.stripe.com/payments/accept-a-payment.md).
## Configurar a Stripe [Lado do servidor] [Lado do cliente]
### Servidor
Esta integração exige que os endpoints do seu servidor se comuniquem com a API da Stripe. Use nossas bibliotecas oficiais para acessar a API da Stripe a partir do seu servidor:
#### Ruby
```bash
# Available as a gem
sudo gem install stripe
```
```ruby
# If you use bundler, you can add this line to your Gemfile
gem 'stripe'
```
### Cliente
O [SDK do React Native](https://github.com/stripe/stripe-react-native) é de código aberto e totalmente documentado. Internamente, utiliza as SDKs de [iOS nativo](https://github.com/stripe/stripe-ios) e [Android](https://github.com/stripe/stripe-android). Para instalar o SDK do React Native da Stripe, execute um dos seguintes comandos no diretório do seu projeto (dependendo de qual gerenciador de pacotes você usa):
#### yarn
```bash
yarn add @stripe/stripe-react-native
```
#### npm
```bash
npm install @stripe/stripe-react-native
```
Em seguida, instale algumas outras dependências necessárias:
- Para iOS, vá para o diretório **ios** e execute `pod install` para garantir a instalação das dependências nativas necessárias.
- Para Android, não há mais dependências para instalar.
> Recomendamos seguir o [guia oficial do TypeScript](https://reactnative.dev/docs/typescript#adding-typescript-to-an-existing-project) para adicionar suporte ao TypeScript.
### Inicialização da Stripe
Para inicializar a Stripe no aplicativo React Native, insira sua tela de pagamento com o componente `StripeProvider` ou use o método de inicialização `initStripe`. Somente a [chave da API publicável](https://docs.stripe.com/keys.md#obtain-api-keys) em `publishableKey` é necessária. O exemplo a seguir mostra como inicializar a Stripe usando o componente `StripeProvider`.
```jsx
import { useState, useEffect } from 'react';
import { StripeProvider } from '@stripe/stripe-react-native';
function App() {
const [publishableKey, setPublishableKey] = useState('');
const fetchPublishableKey = async () => {
const key = await fetchKey(); // fetch key from your server here
setPublishableKey(key);
};
useEffect(() => {
fetchPublishableKey();
}, []);
return (
{/* Your app code here */}
);
}
```
> Use suas [chaves de API de teste](https://docs.stripe.com/keys.md#obtain-api-keys) enquanto testa e desenvolve, e as chaves de [modo de produção](https://docs.stripe.com/keys.md#test-live-modes) quando publica seu aplicativo.
## Crie sua página de checkout [Lado do cliente]
Colete dados do cartão com segurança no cliente usando `CardField`, um componente de IU fornecido pelo SDK que coleta número do cartão, data de valide, CVC e código postal.

Adicione o componente `CardField` à tela de pagamentos para coletar com segurança dados de cartão dos clientes. Use o retorno de chamada `onCardChange` para examinar dados não confidenciais do cartão, como a bandeira, e verificar se os dados estão completos.
```javascript
import { CardField, useStripe } from '@stripe/stripe-react-native';
function PaymentScreen() {
// ...
return (
{
console.log('cardDetails', cardDetails);
}}
onFocus={(focusedField) => {
console.log('focusField', focusedField);
}}
/>
);
}
```
Execute o aplicativo e verifique se a página de checkout mostra o componente `CardField`.
## Coletar dados do cartão [Lado do cliente]
Quando o cliente estiver pronto para fazer o checkout, crie um *PaymentMethod* (PaymentMethods represent your customer's payment instruments, used with the Payment Intents or Setup Intents APIs) com os detalhes coletados pelo componente `CardField` do cartão.
```javascript
import { CardField, useStripe } from '@stripe/stripe-react-native';
function PaymentScreen() {
const { createPaymentMethod, handleNextAction } = useStripe();
const pay = async () => {
// Gather customer billing information (for example, email)
const billingDetails: CreatePaymentMethod.BillingDetails = {
email: 'email@stripe.com',
phone: '+48888000888',
addressCity: 'Houston',
addressCountry: 'US',
addressLine1: '1459 Circle Drive',
addressLine2: 'Texas',
addressPostalCode: '77063',
};
// Create payment method
const { paymentMethod, error } = await createPaymentMethod({
paymentMethodType: 'Card',
paymentMethodData: {
billingDetails,
}
});
};
// ...
}
```
## Envie o PaymentMethod ao seu servidor [Lado do cliente]
Se o PaymentMethod for criado corretamente, envie o ID dele para o seu servidor.
```javascript
// ...
const pay = async () => {
// ...
// Send the PaymentMethod to your server to create a PaymentIntent
const response = await fetch(`/pay`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ paymentMethodId: paymentMethod.id }),
});
const { error, requires_action, payment_intent_client_secret } = await response.json();
if (error) {
// Error creating or confirming PaymentIntent
Alert.alert('Error', paymentIntentError);
return;
}
if (payment_intent_client_secret && !requires_action) {
// Payment succeeded
Alert.alert('Success', 'The payment was confirmed successfully!');
}
if (payment_intent_client_secret && requires_action) {
// ...continued below
}
};
// ...
```
## Criar um PaymentIntent [Lado do servidor]
Configure um endpoint no seu servidor para receber a solicitação. Esse endpoint também será usado [mais à frente](https://docs.stripe.com/payments/accept-a-payment-synchronously.md#confirm-again), para gerenciar cartões que exijam mais uma etapa de autenticação.
[Crie um novo PaymentIntent](https://docs.stripe.com/payments/payment-intents.md#creating-a-paymentintent) com o ID do [PaymentMethod](https://docs.stripe.com/api/payment_methods/object.md) criado no cliente. Você pode *confirmar* (Confirming a PaymentIntent indicates that the customer intends to pay with the current or provided payment method. Upon confirmation, the PaymentIntent attempts to initiate a payment) o PaymentIntent definindo a propriedade [confirm](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-confirm) como verdadeira quando o PaymentIntent for criado ou invocando [confirm](https://docs.stripe.com/api/payment_intents/confirm.md) após a criação. Também permitimos [autorização e captura separadas](https://docs.stripe.com/payments/place-a-hold-on-a-payment-method.md) para pagamentos com cartão.
Se o pagamento exigir ações adicionais, como autenticação do 3D Secure, o status do PaymentIntent será definido como `requires_action`. Se o pagamento falhar, o status será definido novamente como `requires_payment_method` e você deverá mostrar um erro ao usuário. Se o pagamento não exigir autenticação adicional, uma cobrança será criada e o status do PaymentIntent será definido como `succeeded`.
> Nas versões do API anteriores a [2019-02-11](https://docs.stripe.com/upgrades.md#2019-02-11), `requires_payment_method` aparece como `requires_source` e `requires_action` aparece como `requires_source_action`.
#### curl
```bash
curl https://api.stripe.com/v1/payment_intents \
-u <>: \
-d "payment_method"="{{PAYMENT_METHOD_ID}}" \
-d "amount"=1099 \
-d "currency"="usd" \
-d "confirmation_method"="manual" \
-d "confirm"="true"
```
Para salvar o cartão e poder reutilizá-lo depois, crie um [Customer](https://docs.stripe.com/api/customers/create.md) para armazenar o *PaymentMethod* (PaymentMethods represent your customer's payment instruments, used with the Payment Intents or Setup Intents APIs) e insira os seguintes parâmetros ao criar o PaymentIntent:
- [cliente](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-customer). Configurado com o ID do *Cliente* (Customer objects represent customers of your business. They let you reuse payment methods and give you the ability to track multiple payments).
- [setup_future_usage](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-setup_future_usage). Defina como `off_session` para avisar Stripe que você planeja reutilizar esta forma de pagamento para *off-session payments* (A payment is described as off-session if it occurs without the direct involvement of the customer, using previously-collected payment information) quando sua cliente não estiver presente. Definir essa propriedade salva a forma de pagamento para o cliente após a confirmação do PaymentIntent e todas as ações necessárias do usuário forem concluídas. Veja o exemplo de código em [ salvar cartões após um pagamento](https://github.com/stripe-samples/saving-card-after-payment/tree/master/without-webhooks) para saber mais detalhes.
## Gerenciar outras ações [Lado do cliente]
Os pagamentos costumam ser finalizados após você *confirmá-los* (Confirming an intent indicates that the customer intends to use the current or provided payment method. Upon confirmation, the intent attempts to initiate the portions of the flow that have real-world side effects) no servidor, na etapa 4. No entanto, alguns fluxos de pagamento exigem mais alguma ação do cliente, como autenticação com *3D Secure* (3D Secure (3DS) provides an additional layer of authentication for credit card transactions that protects businesses from liability for fraudulent card payments).
Para os casos que exigem outras ações, o status do PaymentIntent é `requires_action`. No cliente, passe o *segredo do cliente* (The client secret is a unique key returned from Stripe as part of a PaymentIntent. This key lets the client access important fields from the PaymentIntent (status, amount, currency) while hiding sensitive ones (metadata, customer)) do PaymentIntent para `handleNextAction`. O gerenciador nativo apresenta uma visualização e orienta o cliente pelo fluxo de autenticação. Depois de gerenciar as ações necessárias no cliente, o status do PaymentIntent muda para `requires_confirmation`. Isso permite que sua integração execute o pedido no seu backend e retorne o resultado da *execução* (Fulfillment is the process of providing the goods or services purchased by a customer, typically after payment is collected) para o cliente.
Envie o ID do PaymentIntent para seu backend e confirme novamente em até uma hora para finalizar o pagamento. Caso contrário, a tentativa de pagamento falha e o status do SetupIntent volta a ser `requires_payment_method`.
```javascript
// ...
const pay = async () => {
// ...
// If PaymentIntent requires action, call handleNextAction
if (payment_intent_client_secret && requires_action) {
const { error, paymentIntent } = await handleNextAction(payment_intent_client_secret);
if (error) {
Alert.alert(`Error code: ${error.code}`, error.message);
} else if (paymentIntent) {
if (
paymentIntent.status === PaymentIntents.Status.RequiresConfirmation
) {
// Confirm the PaymentIntent again on your server
const response = await fetch(`/pay`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ payment_intent_id: paymentIntent.id }),
});
const { error, success } = await response.json();
if (error) {
// Error during confirming Intent
Alert.alert('Error', error);
} else if (success) {
Alert.alert('Success', 'The payment was confirmed successfully!');
}
} else {
// Payment succedeed
Alert.alert('Success', 'The payment was confirmed successfully!');
}
}
}
};
// ...
```
## Confirmar o PaymentIntent novamente [Lado do servidor]
Esse código só é executado quando um pagamento exige autenticação adicional, assim como no gerenciamento da etapa anterior. O código em si não é opcional, porque qualquer pagamento pode exigir essa etapa extra.
Com o mesmo endpoint que você configurou [acima](https://docs.stripe.com/payments/accept-a-payment-synchronously.md#create-payment-intent), *confirme* (Confirming an intent indicates that the customer intends to use the current or provided payment method. Upon confirmation, the intent attempts to initiate the portions of the flow that have real-world side effects) o PaymentIntent mais uma vez para finalizar o pagamento e *executar* (Fulfillment is the process of providing the goods or services purchased by a customer, typically after payment is collected) o pedido. Esta confirmação precisa acontecer no máximo uma hora após a tentativa de pagamento. Do contrário, o pagamento falha e volta ao status `requires_payment_method`.
#### curl
```bash
curl https://api.stripe.com/v1/payment_intents/{{PAYMENT_INTENT_ID}}/confirm \
-u <>: \
-X "POST"
```
## Testar a integração
Vários cartões de teste estão disponíveis para você usar em uma área restrita para assegurar que essa integração esteja pronta. Use-os com qualquer CVC e uma data de validade no futuro.
| Número | Descrição |
| ---------------- | -------------------------------------------------------------------------------------------- |
| 4242424242424242 | Finaliza e processa o pagamento imediatamente. |
| 4000002500003155 | Requer autenticação. A Stripe abre uma janela solicitando que o cliente faça a autenticação. |
| 4000000000009995 | Sempre falha, com o código de recusa `insufficient_funds`. |
Veja a lista completa de cartões de teste em nosso guia de [testes](https://docs.stripe.com/testing.md).
## Optional: Coletar novamente um CVC
Ao criar pagamentos subsequentes em um cartão salvo, você pode pedir novamente o CVC do cartão como medida adicional de segurança contra fraudes para verificar o usuário.
Comece [relacionando](https://docs.stripe.com/api/payment_methods/list.md) as formas de pagamento associadas ao *cliente* (Customer objects represent customers of your business. They let you reuse payment methods and give you the ability to track multiple payments) para determinar qual delas será exibida para nova coleta de CVC. Depois de coletar novamente as informações de CVC do cliente, tokenize os dados do CVC com `createTokenForCVCUpdate`.
```javascript
function PaymentScreen() {
// ...
const { createTokenForCVCUpdate } = useStripe();
const tokenizeCVC = async () => {
const { error, tokenId } = await createTokenForCVCUpdate();
if (error) {
// handle error
} else if (tokenId) {
// pass the token ID to your backend
}
};
}
```
Depois de enviar o token de CVC para seu servidor, crie um PaymentIntent no servidor com o valor, a moeda e o token de CVC no parâmetro `payment_method_options[card][cvc_token]`.
```curl
curl https://api.stripe.com/v1/payment_intents \
-u "<>:" \
-d payment_method={{PAYMENT_METHOD_ID}} \
-d customer={{CUSTOMER_ID}} \
-d amount=1099 \
-d currency=usd \
-d confirmation_method=manual \
-d confirm=true \
-d "payment_method_options[card][cvc_token]={{CVC_TOKEN_ID}}"
```
A payment might succeed even with a failed CVC check. To prevent this, configure your [Radar rules](https://docs.stripe.com/radar/rules.md#traditional-bank-checks) to block payments when CVC verification fails.