# 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. ![](https://d37ugbyn3rpeym.cloudfront.net/docs/mobile/ios/card-field.mp4) 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 ![](https://d37ugbyn3rpeym.cloudfront.net/docs/mobile/android/android-card-input-widget-with-postal.mp4) 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