본문 바로가기

언어/Flutter

[ Flutter ] 안드로이드 인앱 결제 기능 구현하기

반응형

플러터(Flutter)에서 인앱 결제(In-App Purchases)를 구현하려면 in_app_purchase 패키지를 사용합니다. 이 패키지는 구글 플레이 스토어와 애플 앱 스토어 모두에서 작동하는 결제 기능을 제공합니다. 여기서는 안드로이드 폰에서 동작하는 간단한 인앱 결제 기능을 구현하는 예제를 작성해 보겠습니다.

1. 프로젝트 설정

1.1. pubspec.yamlin_app_purchase 추가

먼저 프로젝트의 pubspec.yaml 파일에 in_app_purchase 패키지를 추가합니다.

dependencies:
  flutter:
    sdk: flutter
  in_app_purchase: ^3.0.7  # 최신 버전 확인

1.2. 안드로이드 설정

AndroidManifest.xml 파일에 결제 관련 권한을 추가합니다.

<uses-permission android:name="com.android.vending.BILLING" />

2. 인앱 결제 코드 작성

2.1. 상품 정보 불러오기

먼저, 상품 정보를 불러오는 코드를 작성합니다. 상품 ID는 구글 플레이 콘솔에서 생성한 ID를 사용해야 합니다.

import 'package:flutter/material.dart';
import 'package:in_app_purchase/in_app_purchase.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'In-App Purchase Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final InAppPurchase _inAppPurchase = InAppPurchase.instance;
  bool _available = true;
  List<ProductDetails> _products = [];
  List<PurchaseDetails> _purchases = [];

  @override
  void initState() {
    super.initState();
    final purchaseUpdated = _inAppPurchase.purchaseStream;
    purchaseUpdated.listen((purchases) {
      _purchases.addAll(purchases);
      _handlePurchaseUpdates(purchases);
    });
    _initialize();
  }

  Future<void> _initialize() async {
    final bool available = await _inAppPurchase.isAvailable();
    if (!available) {
      setState(() {
        _available = false;
      });
      return;
    }

    const Set<String> _kIds = {'product_id_1', 'product_id_2'};  // 실제 상품 ID로 대체
    final ProductDetailsResponse response = await _inAppPurchase.queryProductDetails(_kIds);
    if (response.error != null) {
      // 오류 처리
      return;
    }

    setState(() {
      _products = response.productDetails;
    });
  }

  void _handlePurchaseUpdates(List<PurchaseDetails> purchases) {
    for (var purchase in purchases) {
      if (purchase.status == PurchaseStatus.purchased) {
        // 결제 성공 처리
        _verifyPurchase(purchase);
      } else if (purchase.status == PurchaseStatus.error) {
        // 결제 오류 처리
      }
    }
  }

  Future<void> _verifyPurchase(PurchaseDetails purchase) async {
    // 결제 검증 및 서버 검증 코드 추가
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('In-App Purchase Example'),
      ),
      body: _available
          ? ListView.builder(
              itemCount: _products.length,
              itemBuilder: (context, index) {
                return ListTile(
                  title: Text(_products[index].title),
                  subtitle: Text(_products[index].description),
                  trailing: TextButton(
                    child: Text(_products[index].price),
                    onPressed: () {
                      final PurchaseParam purchaseParam = PurchaseParam(
                        productDetails: _products[index],
                      );
                      _inAppPurchase.buyNonConsumable(purchaseParam: purchaseParam);
                    },
                  ),
                );
              },
            )
          : Center(child: Text('Store is unavailable')),
    );
  }
}

2.2. 결제 완료 처리

결제 성공 및 오류 처리를 위해 _handlePurchaseUpdates 메소드와 _verifyPurchase 메소드를 작성합니다. 결제 검증 및 서버 검증은 보안상의 이유로 중요합니다.

void _handlePurchaseUpdates(List<PurchaseDetails> purchases) {
  for (var purchase in purchases) {
    if (purchase.status == PurchaseStatus.purchased) {
      _verifyPurchase(purchase);
    } else if (purchase.status == PurchaseStatus.error) {
      // 결제 오류 처리
    }
  }
}

Future<void> _verifyPurchase(PurchaseDetails purchase) async {
  // 결제 검증 및 서버 검증 코드 추가
  if (purchase.pendingCompletePurchase) {
    await InAppPurchase.instance.completePurchase(purchase);
  }
}

이 코드에서는 인앱 결제를 처리하고, 결제가 완료되면 _verifyPurchase 메소드를 통해 결제 검증을 수행합니다.

3. 구글 플레이 콘솔 설정

  1. 구글 플레이 콘솔에 로그인합니다.
  2. 앱을 선택하고 "인앱 상품"을 설정합니다.
  3. 상품 ID를 생성하고 해당 ID를 코드에 추가합니다.

4. 테스트

  1. 테스트 계정을 구글 플레이 콘솔에 추가합니다.
  2. 앱을 디버그 모드로 실행하고 결제를 테스트합니다.

위 예제는 기본적인 인앱 결제 기능을 구현한 것입니다. 실제 앱에서는 결제 검증, 서버 통신, 보안 등 추가적인 구현이 필요합니다. in_app_purchase 패키지의 공식 문서를 참조하여 더 많은 기능과 상세한 설정 방법을 확인할 수 있습니다.

반응형