flutter

paypal 결제 시스템 연동 (1)

이나주니 2025. 1. 2. 16:17
반응형

https://developer.paypal.com/home/

 

PayPal Developer

Learn how to create and integrate scalable PayPal checkout solutions for web and mobile applications.

developer.paypal.com

접속후 계정만들기

먼저 디폴트로 API 키가 만들어진다

해당 키를 이용해서

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:flutter_inappwebview/flutter_inappwebview.dart';

class PayPalService {
  // 테스트
  final String clientId = "AZSJ......"; // PayPal 클라이언트 ID
  final String clientSecret = "EMNs....."; // PayPal 클라이언트 Secret
  final String sandboxBaseUrl = "https://api-m.sandbox.paypal.com";

  // 실제
  // final String clientId = "ATTr...."; // PayPal 클라이언트 ID
  // final String clientSecret = "ECDTK..."; // PayPal 클라이언트 Secret
  // final String sandboxBaseUrl = "https://api-m.paypal.com";

  // **1. PayPal Access Token 생성**
  Future<String?> getAccessToken() async {
    final String url = "$sandboxBaseUrl/v1/oauth2/token";
    try {
      final response = await http.post(
        Uri.parse(url),
        headers: {
          "Authorization": "Basic ${base64Encode(utf8.encode('$clientId:$clientSecret'))}",
          "Content-Type": "application/x-www-form-urlencoded",
        },
        body: "grant_type=client_credentials",
      );

      if (response.statusCode == 200) {
        final data = jsonDecode(response.body);
        return data['access_token'];
      } else {
        print("Error getting access token: ${response.statusCode} - ${response.body}");
      }
    } catch (e) {
      print("Error: $e");
    }
    return null;
  }

  // **2. PayPal Checkout 생성**
  Future<String?> createOrder(String accessToken, double amount, String currency) async {
    final String url = "$sandboxBaseUrl/v2/checkout/orders";
    final Map<String, dynamic> orderData = {
      "intent": "CAPTURE",
      "application_context": {
        "return_url": "https://your-domain.com/success",
        "cancel_url": "https://your-domain.com/cancel",
        "shipping_preference": "NO_SHIPPING",
      },
      "purchase_units": [
        {
          "amount": {
            "currency_code": currency,
            "value": amount.toString(),
          }
        }
      ]
    };


    try {
      final response = await http.post(
        Uri.parse(url),
        headers: {
          "Authorization": "Bearer $accessToken",
          "Content-Type": "application/json",
        },
        body: jsonEncode(orderData),
      );

      if (response.statusCode == 201) {
        final data = jsonDecode(response.body);
        final approvalUrl = data['links']
            .firstWhere((link) => link['rel'] == 'approve')['href'];
        return approvalUrl;
      } else {
        print("Error creating order: ${response.statusCode} - ${response.body}");
      }
    } catch (e) {
      print("Error: $e");
    }
    return null;
  }
}

class PayPalPaymentPage extends StatefulWidget {
  @override
  _PayPalPaymentPageState createState() => _PayPalPaymentPageState();
}

class _PayPalPaymentPageState extends State<PayPalPaymentPage> {
  final PayPalService _payPalService = PayPalService();
  late InAppWebViewController webViewController;
  String approvalUrl = "";
  bool _isLoading = true;

  Future<void> initiatePayment() async {
    final accessToken = await _payPalService.getAccessToken();
    if (accessToken != null) {
      final url =
      await _payPalService.createOrder(accessToken, 1.00, "USD");
      if (url != null) {
        setState(() {
          approvalUrl = url;
          _isLoading = false;
        });
      } else {
        print("Failed to create order.");
      }
    } else {
      print("Failed to get access token.");
    }
  }

  @override
  void initState() {
    super.initState();
    initiatePayment();
  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('PayPal 결제'),
      ),
      body: Stack(
        children: [
          if (!_isLoading)
            InAppWebView(
              initialUrlRequest: URLRequest(url: WebUri(approvalUrl)),
              onWebViewCreated: (controller) {
                webViewController = controller;
              },

              onLoadStop: (controller, url) async {
                final currentUrl = url.toString();

                if (currentUrl.contains("https://your-domain.com/success")) {
                  // 결제 성공 처리
                  print("결제 성공: $currentUrl");
                  Navigator.pop(context, "success");
                } else if (currentUrl.contains("https://your-domain.com/cancel")) {
                  // 결제 취소 처리
                  print("결제 취소: $currentUrl");
                  Navigator.pop(context, "cancel");
                }
              },
            ),
          if (_isLoading)
            Center(child: CircularProgressIndicator()),
        ],
      ),
    );
  }
}

void main() {
  runApp(MaterialApp(
    debugShowCheckedModeBanner: false,
    home: PayPalPaymentPage(),
  ));
}

 

 

참고로 

국내 거래(예: 구매자와 판매자 모두 한국인)는 불가합니다.

또한, 지원하는 통화 종류에 제약이 있으니 반드시 숙지

반응형