< ios 인앱 결제 >
flutter in-app-purchase 흐름 설명~,~
1. 앱에서 결제 시스템을 셋팅
ios 콘솔에서 앱 내 구독 세션에 셋팅 할거 많아요. 그리고 상품 올리고 소모품을 승인 받아야만 구현이 가능합니다 !
프론트에서는 사용자에게 상품 목록이 보일 수 있도록 표시해야합니다. 일회성 구매인지, 정기 구독인지, 상품의 가격, 설명등을 표시해야 함. 이전에 구매한 소모성 아이템을 소비 처리하기, 구독확인하기 등등
백엔드(서버)에서는 사용자의 구독 상태를 확인하는 api를 호출하고 구독 중인지, 결제 내역이 있는지 응답을 반환해야한다.
2. 결제 요청
스토어 연결 상태 리스너 설정 및 결제 업데이트, 결제 오류 이벤트 추가하는 기능 넣어야함.
3. 영수증 검증 (서버)
구매 성공 시 트랜젝션 id를 서버에 보내야만 영수증 검증이 가능하다.
여기선 서버에서 할게 많음 : 결제가 성공했다고 해서 끝이 아니라 영수증 검증을 해야하는데
appStore에서 직접 영수증 확인 요청을 한다. https://buy.itunes.apple.com/verifyReceipt
그리고 웹 훅을 활용해서 구매 상태가 변경 되면 서버로 알림을 보낸다. ios 인앱결제 환불은 사용자가 직접하는걸로 알고 있다. 우리는 따로 신경 안써도 됨.
결제에 성공하면 구독처리해줘야함. + 소모 처리 및 에러 로그 출력 등
sandbox 환경을 분리하여 검증해서 테스트 여러번 해볼 수 있디 ㅎㅎ!!
결론은 flutter 인앱 결제는 클라이언트 -> 스토어 -> 서버 -> 검증 + 웹 훅
구매 프로세스를 구현해서 백엔드에서 영수증 검증을 수행한 후 웹훅Webhook으로 결제 상태 변경을 감지해서 구독 갱신을 처리하는 과정이다 !!
1. 클라이언트 -> 스토어
- 사용자가 Flutter 앱에서 인앱 결제를 진행하면, FlutterInappPurchase.instance.requestPurchase()를 호출해서 결제를 시작.
- 결제가 완료되면 purchaseUpdated 리스너에서 transactionId를 가져옴.
2. 서버 → 스토어 API (영수증 검증)
- 서버는 받은 영수증을 Apple/Google API에 보내서 검증.
- 검증이 성공하면 서버 DB에 결제 내역 저장 및 사용자 권한 업데이트.
- 이때, 구독 상품 만료 날짜를 저장.
3. 스토어 → 서버 (웹훅 전송, 구독 관리)
- 사용자가 구독 갱신, 취소, 환불하면 스토어에서 자동으로 웹훅을 서버로 전송.
- 웹훅을 받은 서버는 DB 업데이트 및 사용자 구독 상태를 변경.
4. 서버 → 클라이언트 (상태 동기화)
- 사용자가 앱을 열 때 restorePurchases()를 호출해서 최신 구독 상태를 동기화할 수도 있음.
인 흐름이다. 이해하는데 오래 걸렸디 ^^~^^* 하지만 재미있었다.
이제 Flutter 간단한 코드 설명이다.
FlutterInappPurchase.instance
.consumeAll()
.then((_) {
print("모든 소모성 아이템이 소비되었습니다.");
}).catchError((e) {
print("모든 소모성 아이템 소비 오류: $e");
});
사용자가 이전에 구매 했는지 확인하는 것.
_connectionSubscription = FlutterInappPurchase.connectionUpdated
.listen((connected) {
print('connected: $connected');
});
_purchaseUpdatedSubscription =
FlutterInappPurchase.purchaseUpdated
.listen((productItem) {
스토어 연결상태 체크임. 결제 업데이트 리스너임.
if (productItem?.transactionId == null) {
print("transactionId가 없습니다. 요청 중단.");
return;
}
if (_processedTransactionIds.contains(productItem!.transactionId)) {
print("중복 요청 방지: 이미 처리된 transactionId: ${productItem.transactionId}");
return;
}
_processedTransactionIds.add(productItem.transactionId!);
트랜젝션 아이디 가져와서 중복 요청 방지. 이 과정 중요한게. . . 결제한다고 했다가 중간에 취소하고 다시 결제했을때 이부분이 없으면 두번 요청이 될 수도 있어요.
context.read<PayIosBloc>().add(PayIosEvent.get(
transactionId: productItem.transactionId.toString()));
context.removeOverlayProgress();
print("구매가 완료되었습니다! transactionId: ${productItem.transactionId}");
if (productItem.productId == 'chooseme12900') {
try {
if (Platform.isAndroid) {
FlutterInappPurchase.instance
.consumePurchaseAndroid(productItem.purchaseToken!);
} else if (Platform.isIOS) {
FlutterInappPurchase.instance
.finishTransactionIOS(productItem.transactionId!);
}
} catch (e) {
print("구매 소모 처리 중 오류 발생: $e");
}
}
PayIosBloc을 사용하여 트랜잭션 ID를 서버로 보내서 영수증 검증 진행해서 구매 소비 처리
if (_items.isNotEmpty) {
IAPItem firstItem = _items[0];
FlutterInappPurchase.instance.requestPurchase(
firstItem.productId!,
obfuscatedAccountId: obfuscatedAccountId,
);
} else {
print('구매 가능한 상품이 없습니다.');
context.removeOverlayProgress();
}
그래서 ~!! requestPurchase()를 호출하여 실제로 결제를 진행.
PayIosBloc에서 서버와 통신하여 영수증 검증을 하면, 최종적으로 결제 처리가 완료됩니다...
ios는 따로 개인적인 서버 로그를 보지는 못하네요
이거는 번외로 ios는 아니고 부트페이 결제시 나오는 서버 로그와 웹 훅 로그입니다 이런식으로 생겼어요. (참고용)
아무튼 부트페이나 IOS인앱결제나
두개 다
매우 매우 아주 잘 됩니다. . . 🙇♂️
많이 배웠던 결제였다 !!!!!!!!!! 🤍
서버 측 구현입니다.
IOS 인앱 결제 영수증 검증 서버 구현 (verifyReceipt X)
이전에 사이드 프로젝트를 진행하면서 IOS 인앱 결제 서버 측 로직을 구현한 적이 있다.간단한 로직은 이렇다.결제 구간은 클라이언트 측에서 진행하고, 결제 완료 후 서버 측에 결제 정보를 전
velog.io
'플러터' 카테고리의 다른 글
앱 버전 업데이트 관리 - Firebase Remote Config 에 대해 (0) | 2025.01.04 |
---|---|
앱링크를 이용해 카카오톡 초대하기, 공유하기 기능 (1) | 2024.10.15 |
프로젝트 어플 만들면서 겪었던 경험들 (2) | 2024.08.05 |
Postman - 토큰 자동 저장 방법 (0) | 2024.06.28 |
Pagination 페이지네이션이란 (0) | 2024.06.28 |