2024. 2. 12. 14:50ㆍ모바일어플개발/Flutter 실전어플 개발
안녕하세요~ totally 개발자입니다.
오늘은 결제시작 부분에서 결제 버튼을 눌렀을 때, 주문하고자 하는 제품들을 파이어스토어에 담아보도록 하겠습니다.
Step 1: 파이어스토어에 접속하셔서 orders 컬렉션을 생성해주시기 바랍니다. 다음을 눌러서 임의로 문서(document) 하나 추가해주시면 됩니다.
Step 2: lib > item_checkout_page.dart에서 checkoutContainer 부분에 혹시 height 지정을 안하신 경우에 height: 130 정도로 설정해주시기 바랍니다.
Step 3: lib > models > order.dart 파일을 열어서 아래처럼 수정해줍니다. class Order로 하면 다른 dart 파일과 겹치는 내용들이 있는 것 같아 ProductOrder로 변경하여 구분하였습니다.
class ProductOrder {
String? orderNo;
int? productNo;
String? orderDate;
String? buyerName;
String? buyerEmail;
String? buyerPhone;
String? receiverName;
String? receiverPhone;
String? receiverZip;
String? receiverAddress1;
String? receiverAddress2;
String? userPwd;
String? paymentMethod;
int? quantity;
double? unitPrice;
double? totalPrice;
String? paymentStatus;
String? deliveryStatus;
ProductOrder({
this.orderNo,
this.productNo,
this.orderDate,
this.buyerName,
this.buyerEmail,
this.buyerPhone,
this.receiverName,
this.receiverPhone,
this.receiverZip,
this.receiverAddress1,
this.receiverAddress2,
this.userPwd,
this.paymentMethod,
this.quantity,
this.unitPrice,
this.totalPrice,
this.paymentStatus,
this.deliveryStatus,
});
ProductOrder.fromJson(Map<String, dynamic> json) {
orderNo = json['orderNo'];
productNo = json['productNo'];
orderDate = json['orderDate'];
buyerName = json['buyerName'];
buyerEmail = json['buyerEmail'];
buyerPhone = json['buyerPhone'];
receiverName = json['receiverName'];
receiverPhone = json['receiverPhone'];
receiverZip = json['receiverZip'];
receiverAddress1 = json['receiverAddress1'];
receiverAddress2 = json['receiverAddress2'];
userPwd = json['userPwd'];
paymentMethod = json['paymentMethod'];
quantity = json['quantity'];
unitPrice = double.parse(json['unitPrice']);
totalPrice = double.parse(json['totalPrice']);
paymentStatus = json['paymentStatus'];
deliveryStatus = json['deliveryStatus'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = {};
data['orderNo'] = orderNo;
data['productNo'] = productNo;
data['orderDate'] = orderDate;
data['buyerName'] = buyerName;
data['buyerEmail'] = buyerEmail;
data['buyerPhone'] = buyerPhone;
data['receiverName'] = receiverName;
data['receiverPhone'] = receiverPhone;
data['receiverZip'] = receiverZip;
data['receiverAddress1'] = receiverAddress1;
data['receiverAddress2'] = receiverAddress2;
data['userPwd'] = userPwd;
data['paymentMethod'] = paymentMethod;
data['quantity'] = quantity;
data['unitPrice'] = unitPrice;
data['totalPrice'] = totalPrice;
data['paymentStatus'] = paymentStatus;
data['deliveryStatus'] = deliveryStatus;
return data;
}
}
Step 4: lib > enums > delivery_status.dart 파일을 아래처럼 업데이트해줍니다.
enum DeliveryStatus {
//! 상태 열거
waiting('waiting', '배송대기'),
delivering('delivering', '배송중'),
delivered('delivered', '배송완료');
//! 생성자
const DeliveryStatus(this.status, this.statusName);
final String status;
final String statusName;
//! 상태 이름 변환
factory DeliveryStatus.getStatusName(String status) {
return DeliveryStatus.values.firstWhere((value) => value.status == status,
orElse: () => DeliveryStatus.waiting);
}
}
여기에서 enum을 사용해서 각각의 상태를 체계적으로 관리하기 위함입니다. 보통 직접적으로 데이터를 다룰 때 위와 같이 정해진 값을 사용하는 경우에는 위처럼 enum 등을 사용하여 체계적으로 관리하는 것이 좋습니다.
Step 5: lib > enums > payment_status.dart 파일도 아래처럼 수정해줍니다.
enum PaymentStatus {
//! 상태 열거
waiting('waiting', '입금대기'),
completed('completed', '결제완료'),
cancelled('cancelled', '주문취소');
//! 생성자
const PaymentStatus(this.status, this.statusName);
final String status;
final String statusName;
//! 상태 이름 변환
factory PaymentStatus.getStatusName(String status) {
return PaymentStatus.values.firstWhere((value) => value.status == status,
orElse: () => PaymentStatus.waiting);
}
}
Step 6: 먼저 pubspec.yaml에서 crypto 패키지를 설치해주시고 item_checkout_page.dart 파일로 가셔서 intl, crypto 패키지 임포트 해주신 뒤에 아래 빨간색 박스 내용을 추가합니다. 245-247번째 줄은 비밀번호를 sha256 알고리즘으로 암호화하기 위함이고 248-249번째 줄은 주문번호를 현재 일시에 맞춰서 생성하기 위함입니다. (물론 이 경우에도 중복은 나올 수 있습니다)
Step 7: 빨간 박스 아래에 아래 내용을 추가해줍니다. 이 강좌에서는 한 데이터 document에 여러 제품을 포함할 수 없는 구조이며 무조건 문서 1개당 제품 하나만 담을 수 있는 구조입니다. 그래서 여러 제품을 담는 경우에는 orderNo로 묶어서 표현할 수 있습니다. 실제 업무에서는 아래처럼 하기 보다는 products 변수가 별도로 있어서 배열 형태로 들어가는 것이 권장됩니다. 다만 제 강좌에서는 최대한 간단하게 하기 위해 배제하였습니다. try catch 구문을 넣어 예외 처리 해주시고, database.collection("orders").add 메소드를 통해서 데이터를 추가하면 됩니다.
//! 이 부분에 파이어스토어에 접근해서 데이터 insert 작업 진행함.
snapshot.data?.docs.forEach(
(document) {
ProductOrder productOrder = ProductOrder(
orderNo: orderNo,
productNo: document.data().productNo,
orderDate: DateFormat("y-M-d h:m:s")
.format(DateTime.now()),
buyerName: buyerNameController.text,
buyerEmail: buyerEmailController.text,
buyerPhone: buyerPhoneController.text,
receiverName: receiverNameController.text,
receiverPhone: receiverPhoneController.text,
receiverZip: receiverZipController.text,
receiverAddress1:
receiverAddress1Controller.text,
receiverAddress2:
receiverAddress2Controller.text,
userPwd: hashPwd.toString(),
paymentMethod: selectedPaymentMethod,
quantity: cartMap[
document.data().productNo.toString()],
unitPrice: document.data().price,
totalPrice: cartMap[document
.data()
.productNo
.toString()] *
document.data().price,
paymentStatus:
PaymentStatus.waiting.statusName,
deliveryStatus:
DeliveryStatus.waiting.statusName,
);
print(jsonEncode(productOrder));
try {
database
.collection("orders")
.add(productOrder.toJson());
} catch (e) {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
content: Padding(
padding: const EdgeInsets.all(15.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Center(
child: Text("오류가 발생 했습니다.")),
],
),
),
actions: [
Center(
child: FilledButton(
onPressed: () =>
Navigator.pop(context),
child: Text("확인")),
),
],
);
},
);
//! 아래 부분이 더 이상 호출되지 않도록 return합니다.
return;
}
},
);
예외가 있는 경우 아래처럼 Dialog를 띄워서 오류가 발생했는지 띄워주시면 됩니다. (실제로는 어떤 오류인지까지 표현하는 것이 권장됩니다)
Step 8: 아래처럼 제품을 담고 입력한 뒤 테스트해봅니다.
제가 위 코드에 print로 productOrder 객체를 출력되도록 한 결과는 아래와 같습니다.
그리고 아래처럼 주문완료 페이지로 넘어가게 됩니다.
Step 9: 파이어스토어(Firestore)에서 아래처럼 바로 제품 3개의 주문이 들어간 것을 확인해볼 수 있습니다.
다음 시간에는 내가 주문한 데이터들을 확인해볼 수 있도록 작업을 진행하겠습니다. 감사합니다.
[전체 소스 코드]
[item_checkout_page.dart]
[유튜브 강좌 영상]