如何在Flutter应用程序中开始使用Stripe集成功能

903 阅读6分钟

在Flutter应用程序中开始使用Stripe集成功能

Stripe是一个在线支付平台,促进了支付处理。除了处理支付,该公司还提供应用编程接口,用于将支付系统集成到第三方应用程序中。

目标

本教程旨在说明如何将Stripe结账集成到flutter应用程序中。最后,读者应该能够很好地理解这些代码片段,并使用它们来构建一个使用Stripe结账的小型应用程序。

前提条件

  1. Flutter有一个基本的了解。
  2. 在您的电脑上安装Flutter SDK
  3. 代码编辑器,Android Studio,或vscode是最受欢迎的。
  4. 一个模拟器或一个移动设备来运行该项目。

基本概述

该项目从主主页上将有两条路线。第一条路线将引导用户添加新卡进行支付,而第二条路线将引导用户使用现有卡进行支付。

当用户选择一张新卡进行支付时,我们将使用flutter_credit_card 包产生一个好看的卡片表格,用户将在其中输入卡号、到期日和安全代码。

然后,一个支付请求被发送到服务器,服务器处理该请求并通知用户支付过程的状态是成功还是失败。

创建一个Stripe账户

要获得访问API所需的publishable keysecret key ,请前往[Stripe网站]并免费创建一个账户。导航到开发人员的仪表板,获得您的publishable keysecret key

项目结构

创建一个新的flutter应用程序。

在你的项目的lib 文件夹中,创建两个文件夹pages ,包含渲染给用户的屏幕,services ,包含项目的驱动代码文件。

pages 文件夹中,添加两个文件。home.dart 用于登陆页面,cards.dart 用于放置现有卡片的代码。

services 文件夹中,我们将添加一个文件services.dart ,该文件将处理项目的大部分后端逻辑。你的项目结构应该如下所示。

lib
    ┣ Services
    ┃   ┗ services.dart
    ┣ Pages
    ┃   ┗ home.dart
    ┃   ┗ cards.dart
    ┗ main.dart

添加依赖性

我们的项目需要以下依赖项。

  • flutter_credit_card.当用户想在应用程序中添加一个新卡时,这个依赖将产生一个漂亮的信用卡表单。
  • stripe_payment.这个插件将使我们能够轻松地集成Stripe结账。
  • HTTP.我们需要这个来消耗我们将从Stripe API获取的http资源。
  • progress_dialog.我们将用它来指示用户等待处理请求的进度。

前往pubspec.yml ,添加以下代码块。

dependencies:
  flutter:
    sdk: flutter
  flutter_credit_card: ^0.1.3
  stripe_payment: ^1.0.7
  http: ^0.11.3+17
  progress_dialog: ^1.2.2

创建路由

main.dart ,我们将创建一个路由到homepage ,另一个到existing cards 页面。

main.dart 文件中添加下面的代码块来创建路由。

import 'package:flutter/material.dart';
import 'package:flutter_stripe_payments/pages/cards.dart';
import 'package:flutter_stripe_payments/pages/home.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'STRIPE CHECKOUT', //app title
      theme: ThemeData(
        primarySwatch: Colors.green,
      ),
      //initial route
      initialRoute: '/home',
      routes: {
          //home and existing cards routes
        '/home': (context) => HomePage(),
        '/cards': (context) => ExistingCardsPage()},
    );
  }
}

选择支付方式的用户界面

home.dart 文件中,我们将添加以下代码,使用户能够选择是添加新卡还是使用现有的卡进行支付。

Widget build(BuildContext context) {
    ThemeData theme = Theme.of(context);
    return Scaffold(
        appBar: AppBar(
            title: Text('Home'),
        ),
        body: Container(
            padding: EdgeInsets.all(23),
            child: ListView.separated(
            itemBuilder: (context, index) {
                Icon icon;
                Text text;
                switch (index) {
                    case 0:
                        icon = Icon(Icons.add_circle, color: Colors.green);
                        text = Text('ADD CARD');
                        break;
                    case 1:
                        icon = Icon(Icons.credit_card, color: Colors.green);
                        text = Text('CHOOSE CARD');
                        break;
                }

                return InkWell(
                    onTap: () {
                        onItemPress(context, index); //called to select the function to call depending on the method chosen
                    },
                    child: ListTile(
                        title: text,
                        leading: icon,
                    ),
                );
            },
            separatorBuilder: (context, index) => Divider(
                color: Colors.green,
            ),
            itemCount: 2),
        ),
    );
  }

onItemPress() 方法有一个开关案例,根据用户的选择来选择一个功能。下面的代码显示了该方法的实现。

onItemPress(BuildContext context, int index) async {
    switch (index) {
      case 0:
        addNewCard(context); // call pay via new card function
        break;
      case 1:
        Navigator.pushNamed(context, '/cards'); //calls the list of cards screen
        break;
    }

现有卡页面

现有的卡包含一个可以用于测试应用程序的卡的列表。您可以从flutter stripe仪表板上获得这些卡片的列表。

下面的代码片断显示了现有卡片页面的实现。

//an array of existing cards
 List cards = [
    {
      'cardNumber': '4242424242434242',
      'expiryDate': '04/22',
      'cardHolderName': 'Kaura Jerim',
      'cvvCode': '424',
      'showBackView': false,
    },
    {
      'cardNumber': '55555345966554444',
      'expiryDate': '02/25',
      'cardHolderName': 'Jerim Kaura',
      'cvvCode': '123',
      'showBackView': false,
    }
  ];

//Page widget
Widget build(BuildContext context) {
return Scaffold(
    appBar: AppBar(
        title: Text('CHOSE YOUR CARD'),
    ),
    body: Container(
        padding: EdgeInsets.all(23),
        child: ListView.builder(
            itemCount: cards.length,
            itemBuilder: (BuildContext context, int index) {
            var card = cards[index];
            return InkWell(
                onTap: () {
                    choseExistingCard(context, card);
                },
                child: CreditCardWidget(
                    cardNumber: card['cardNumber'],
                    expiryDate: card['expiryDate'],
                    cardHolderName: card['cardHolderName'],
                    cvvCode: card['cvvCode'],
                    showBackView: false,
                ),
            );
            },
        ),
    ),
);

Select Card

创建服务处理程序

service.dart 文件中,我们将创建一个包含API_URL、API_KEY和秘钥的类作为类成员。我们需要这些变量来访问stripe支付API服务。

下面的片段显示了这个类。


class PaymentService {
    static String apiURL = 'https://api.stripe.com/v1';
    static String paymentApiUrl = '${PaymentService.apiURL}/payment_intents';
    static String secret =   'YOUR STRIPE SECRET'; //your secret from stripe dashboard
    static Map<String, String> headers = {
        'Authorization': 'Bearer ${PaymentService.secret}',
        'Content-Type': 'application/x-www-form-urlencoded'
    };
    static init() {
        StripePayment.setOptions(
            StripeOptions(
                publishableKey:"YOUR PUBLISHABLE KEY", // user your api key
                merchantId: "Test",
                androidPayMode: 'test'
            )
        );
    }
}

接下来,我们将创建一个类,包含在处理支付请求后给用户的响应。在services.dart 文件中添加下面的片段。


class PaymentResponse {
    String message; // message from the response
    bool success; //state of the processs

    //class constructor
    PaymentResponse({this.message, this.success});
}

卡片方法

我们需要在StripeService 类中有两个方法,根据用户选择的付款方式来处理付款。在services.dart 文件中的StripeService 类中添加下面的代码片段。

  1. 通过现有的卡方法支付。
  static Future<PaymentResponse> choseExistingCard(
    {String amount, String currency, CreditCard card}) async {
    try {
        var stripePaymentMethod = await StripePayment.createPaymentMethod(PaymentMethodRequest(card: card));
        var stripePaymentIntent = await StripeService.createPaymentIntent(amount, currency);
        var response = await StripePayment.confirmPaymentIntent(
            PaymentIntent(
                clientSecret: stripePaymentIntent['client_secret'],
                paymentMethodId: stripePaymentMethod.id
            )
        );

        if (response.status == 'succeeded') {
            //if the payment process success
            return new StripeTransactionResponse(
                message: 'Transaction successful',
                success: true
            );
        }else {
            //payment process fail
            return new StripeTransactionResponse(
                message: 'Transaction failed', 
                success: false
            );
        }
    } on PlatformException catch (error) {
        return StripeService.getPlatformExceptionErrorResult(err);
    } catch (error) {
        return new StripeTransactionResponse(
             //convert the error to string and assign to message variable for json resposne
            message: 'Transaction failed: ${error.toString()}',
            success: false
        );
    }
}
  1. 通过一个新的卡的方法支付。
  static Future<StripeTransactionResponse> addNewCard({String amount, String currency}) async {
    try {
        var stripePaymentMethod = await StripePayment.paymentRequestWithCardForm(CardFormPaymentRequest());
        var stripePaymentIntent = await StripeService.createPaymentIntent(amount, currency);
        var response = await StripePayment.confirmPaymentIntent(
            PaymentIntent(clientSecret: stripePaymentIntent['client_secret'], paymentMethodId: stripePaymentMethod.id));

        if (response.status == 'succeeded') { //if the payment process success
            return new StripeTransactionResponse(
                message: 'Transaction successful',
                success: true
            );
        }else { //payment process fail
            return new StripeTransactionResponse(
                message: 'Transaction failed',
                success: false
            );
        }
    } on PlatformException catch (error) {
        return StripeService.getPlatformExceptionErrorResult(error);
    } catch (error) {
        return new StripeTransactionResponse(
            //convert the error to string and assign to message variable
            message: 'Transaction failed: ${error.toString()}', 
            success: false
        );
    }
}

这个方法也带来了预先建立的新卡形式,如下图所示。

New Card

支付意图

我们需要一个支付意图,使用StripeService 类中提供的URL,用一个post请求向API发送一个支付请求。下面的片段显示了如何创建支付意图。支付意图是在StripeService 类中创建的。

static Future<Map<String, dynamic>> createPaymentIntent(String amount, String currency) async {
    try {
        Map<String, dynamic> body = {
            'amount': amount, // amount charged will be specified when the method is called
            'currency': currency, // the currency
            'payment_method_types[]': 'card' //card
        };
        var response =
            await http.post(
                StripeService.paymentApiUrl,  //api url
                body: body,  //request body
                headers: StripeService.headers //headers of the request specified in the base class
            );
        return jsonDecode(response.body); //decode the response to json
    } catch (error) {
        print('Error occured : ${error.toString()}');
    }
    return null;
}

确认付款状态

构建并运行应用程序来测试它。为了确认付款,API会记录每一个关于新卡或付款的请求。前往Stripe仪表板并导航到日志下的开发者部分。你应该能够看到如下所示的请求列表。

Logs

要查看支付情况,请浏览仪表板侧边栏上的支付链接。它应该引导你到一个已付款的列表,如下图所示。

payments

总结

在本教程中,我们学习了如何在Flutter应用程序中集成stripe结账。该教程用一个小项目解释了一个逐步实现的过程。