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(),
));
}
참고로
국내 거래(예: 구매자와 판매자 모두 한국인)는 불가합니다.
또한, 지원하는 통화 종류에 제약이 있으니 반드시 숙지
반응형