Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#40] [FEATURE] 결제 API 추가 #42

Merged
merged 3 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@

import core.startup.mealtoktok.api.fulldining.dto.FullDiningResponse;
import core.startup.mealtoktok.common.dto.Response;
import core.startup.mealtoktok.domain.fulldining.CollectingState;
import core.startup.mealtoktok.domain.fulldining.FullDining;
import core.startup.mealtoktok.domain.fulldining.FullDiningId;
import core.startup.mealtoktok.domain.fulldining.FullDiningService;
import core.startup.mealtoktok.domain.fulldining.TargetFullDining;
import core.startup.mealtoktok.domain.mealdelivery.CollectingState;
import core.startup.mealtoktok.domain.mealdelivery.Recipient;
import core.startup.mealtoktok.domain.user.User;

Expand All @@ -30,8 +30,7 @@ public class FullDingingApi implements FullDiningApiDocs {
@PatchMapping("/full-dinings/{fullDiningId}/{collectingState}")
public Response<Void> changeCollectingState(
@PathVariable Long fullDiningId, @PathVariable CollectingState collectingState) {
fullDiningService.changeCollectingState(
TargetFullDining.from(fullDiningId), collectingState);
fullDiningService.changeCollectingState(FullDiningId.from(fullDiningId), collectingState);
return Response.success("수거 상태 변경 성공");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import core.startup.mealtoktok.api.fulldining.dto.FullDiningResponse;
import core.startup.mealtoktok.common.dto.Response;
import core.startup.mealtoktok.domain.mealdelivery.CollectingState;
import core.startup.mealtoktok.domain.fulldining.CollectingState;
import core.startup.mealtoktok.domain.user.User;

import io.swagger.v3.oas.annotations.Operation;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import java.time.LocalDateTime;

import core.startup.mealtoktok.domain.fulldining.CollectingState;
import core.startup.mealtoktok.domain.fulldining.FullDining;
import core.startup.mealtoktok.domain.mealdelivery.CollectingState;

public record FullDiningResponse(
Long fullDiningId,
Expand All @@ -13,8 +13,8 @@ public record FullDiningResponse(

public static FullDiningResponse from(FullDining fullDining) {
return new FullDiningResponse(
fullDining.getFullDiningId(),
fullDining.getMealDeliveryId(),
fullDining.getFullDiningId().getValue(),
fullDining.getMealDeliveryId().getValue(),
fullDining.getCollectState(),
fullDining.getCollectedDateTime());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ protected void doFilterInternal(
Optional<String> refreshToken = JwtTokenizer.extractRefreshToken(request);

if (refreshToken.isPresent()) {
TargetUser targetUser = JwtTokenizer.extractTargetUser(refreshToken.get());
validateRefreshToken(targetUser, refreshToken.get());
reIssueToken(targetUser, response);
log.info("userEntity - {} 리프레시 토큰 재발급", targetUser.userId());
UserId userId = JwtTokenizer.extractTargetUser(refreshToken.get());
validateRefreshToken(userId, refreshToken.get());
reIssueToken(userId, response);
log.info("userEntity - {} 리프레시 토큰 재발급", userId.getValue());
return;
}

Expand All @@ -59,17 +59,17 @@ protected void doFilterInternal(
filterChain.doFilter(request, response);
}

public void validateRefreshToken(TargetUser targetUser, String givenRefreshToken) {
public void validateRefreshToken(UserId userId, String givenRefreshToken) {
tokenManager
.getRefreshToken(targetUser)
.getRefreshToken(userId)
.filter(existRefreshToken -> existRefreshToken.equals(givenRefreshToken))
.orElseThrow(() -> InvalidTokenException.EXCEPTION);
}

private void reIssueToken(TargetUser targetUser, HttpServletResponse response) {
String reIssuedAccessToken = JwtTokenizer.generateAccessToken(targetUser);
String reIssuedRefreshToken = JwtTokenizer.generateRefreshToken(targetUser);
tokenManager.saveRefreshToken(RefreshToken.of(targetUser, reIssuedRefreshToken));
private void reIssueToken(UserId userId, HttpServletResponse response) {
String reIssuedAccessToken = JwtTokenizer.generateAccessToken(userId);
String reIssuedRefreshToken = JwtTokenizer.generateRefreshToken(userId);
tokenManager.saveRefreshToken(RefreshToken.of(userId, reIssuedRefreshToken));
JwtTokenizer.setInHeader(response, reIssuedAccessToken, reIssuedRefreshToken);
response.setStatus(HttpServletResponse.SC_CREATED);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import core.startup.mealtoktok.api.auth.exception.InvalidTokenException;
import core.startup.mealtoktok.domain.auth.JwtTokens;
import core.startup.mealtoktok.domain.auth.TokenGenerator;
import core.startup.mealtoktok.domain.user.TargetUser;
import core.startup.mealtoktok.domain.user.UserId;

import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
Expand All @@ -27,22 +27,22 @@
@Component
public class JwtTokenizer implements TokenGenerator {

public static String generateAccessToken(TargetUser targetUser) {
public static String generateAccessToken(UserId userId) {
Key key = getKeyFromSecretKey(SECRET_KEY);

return Jwts.builder()
.setSubject(String.valueOf(targetUser.userId()))
.setSubject(String.valueOf(userId.getValue()))
.setIssuedAt(Calendar.getInstance().getTime())
.setExpiration(getTokenExpiration())
.signWith(key, SignatureAlgorithm.HS256)
.compact();
}

public static String generateRefreshToken(TargetUser targetUser) {
public static String generateRefreshToken(UserId userId) {
Key key = getKeyFromSecretKey(SECRET_KEY);

return Jwts.builder()
.setSubject(String.valueOf(targetUser.userId()))
.setSubject(String.valueOf(userId.getValue()))
.setIssuedAt(Calendar.getInstance().getTime())
.signWith(key, SignatureAlgorithm.HS256)
.compact();
Expand Down Expand Up @@ -77,9 +77,9 @@ public static Optional<String> extractRefreshToken(HttpServletRequest request) {
.map(refreshToken -> refreshToken.replace(BEARER, ""));
}

public static TargetUser extractTargetUser(String token) {
public static UserId extractTargetUser(String token) {
try {
return TargetUser.from(
return UserId.from(
Long.parseLong(
Jwts.parserBuilder()
.setSigningKey(getKeyFromSecretKey(SECRET_KEY))
Expand All @@ -96,7 +96,7 @@ public static TargetUser extractTargetUser(String token) {
;

@Override
public JwtTokens generate(TargetUser targetUser) {
return JwtTokens.of(generateAccessToken(targetUser), generateRefreshToken(targetUser));
public JwtTokens generate(UserId userId) {
return JwtTokens.of(generateAccessToken(userId), generateRefreshToken(userId));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,14 @@ public GroupedOpenApi mealDelivery() {
.build();
}

@Bean
public GroupedOpenApi payment() {
return GroupedOpenApi.builder()
.group("결제")
.packagesToScan("core.startup.mealtoktok.api.payment")
.build();
}

@Bean
public OpenAPI openAPI() {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
import core.startup.mealtoktok.common.dto.Response;
import core.startup.mealtoktok.common.dto.SliceResult;
import core.startup.mealtoktok.domain.mealdelivery.DeliveryState;
import core.startup.mealtoktok.domain.mealdelivery.MealDeliveryId;
import core.startup.mealtoktok.domain.mealdelivery.MealDeliverySearchCond;
import core.startup.mealtoktok.domain.mealdelivery.MealDeliveryService;
import core.startup.mealtoktok.domain.mealdelivery.Recipient;
import core.startup.mealtoktok.domain.mealdelivery.TargetMealDelivery;
import core.startup.mealtoktok.domain.user.User;

@RequestMapping("/api/v1/meal-deliveries")
Expand Down Expand Up @@ -52,8 +52,7 @@ public Response<SliceResult<MealDeliveryResponse>> searchMealDeliveries(
public Response<MealDeliveryResponse> mealDelivery(@PathVariable Long mealDeliveryId) {
return Response.success(
MealDeliveryResponse.from(
mealDeliveryService.getMealDelivery(
TargetMealDelivery.from(mealDeliveryId))));
mealDeliveryService.getMealDelivery(MealDeliveryId.from(mealDeliveryId))));
}

@GetMapping("/count")
Expand All @@ -73,7 +72,7 @@ public Response<MealDeliveryResponse> recentDeliveredMeal(
}

@GetMapping("/next-delivery")
public Response<MealDeliveryResponse> nextDeliveryMeal(@RequestParam Long orderId) {
public Response<MealDeliveryResponse> nextDeliveryMeal(@RequestParam String orderId) {
return Response.success(
MealDeliveryResponse.from(mealDeliveryService.getNextDeliveryMeal(orderId)));
}
Expand All @@ -84,13 +83,11 @@ public Response<Void> changeDeliveryState(

switch (deliveryState) {
case DELIVERY_REQUESTED ->
mealDeliveryService.reserveMealDelivery(
TargetMealDelivery.from(mealDeliveryId));
mealDeliveryService.reserveMealDelivery(MealDeliveryId.from(mealDeliveryId));
case DELIVERING ->
mealDeliveryService.startMealDelivery(TargetMealDelivery.from(mealDeliveryId));
mealDeliveryService.startMealDelivery(MealDeliveryId.from(mealDeliveryId));
case DELIVERED ->
mealDeliveryService.completeMealDelivery(
TargetMealDelivery.from(mealDeliveryId));
mealDeliveryService.completeMealDelivery(MealDeliveryId.from(mealDeliveryId));
}

return Response.success("배송 상태 변경 성공");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package core.startup.mealtoktok.api.mealdelivery;

import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.RequestParam;

import core.startup.mealtoktok.api.mealdelivery.dto.MealDeliveryResponse;
import core.startup.mealtoktok.common.dto.Cursor;
Expand Down Expand Up @@ -35,7 +34,7 @@ Response<Integer> countByDeliveryState(
Response<MealDeliveryResponse> recentDeliveredMeal(User currentUser);

@Operation(summary = "해당 주문의 다음 도시락 배송 조회")
Response<MealDeliveryResponse> nextDeliveryMeal(@RequestParam Long orderId);
Response<MealDeliveryResponse> nextDeliveryMeal(String orderId);

@Operation(summary = "도시락 배송 상태 변경")
Response<Void> changeDeliveryState(Long mealDeliveryId, DeliveryState deliveryState);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@
@JsonInclude(NON_NULL)
public record MealDeliveryResponse(
Long mealDeliveryId,
Long orderId,
String orderId,
OrderTypeForDelivery orderType,
OrderedMeal orderedMeal,
DeliveryState deliveryState,
DeliveryDateTime deliveryDateTime) {

public static MealDeliveryResponse from(MealDelivery mealDelivery) {
return new MealDeliveryResponse(
mealDelivery.getMealDeliveryId(),
mealDelivery.getOrderId(),
mealDelivery.getMealDeliveryId().getValue(),
mealDelivery.getOrderId().toString(),
mealDelivery.getOrderType(),
mealDelivery.getOrderedMeal(),
mealDelivery.getDeliveryState(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@
import core.startup.mealtoktok.common.dto.SliceResult;
import core.startup.mealtoktok.domain.order.Order;
import core.startup.mealtoktok.domain.order.OrderDetail;
import core.startup.mealtoktok.domain.order.OrderId;
import core.startup.mealtoktok.domain.order.OrderSearchCond;
import core.startup.mealtoktok.domain.order.OrderService;
import core.startup.mealtoktok.domain.order.OrderState;
import core.startup.mealtoktok.domain.order.Orderer;
import core.startup.mealtoktok.domain.order.TargetOrder;
import core.startup.mealtoktok.domain.user.User;

@RestController
Expand All @@ -34,7 +34,7 @@ public class OrderApi implements OrderApiDocs {
private final OrderService orderService;

@PostMapping
public Response<TargetOrder> orderMeals(
public Response<OrderId> orderMeals(
@AuthenticationPrincipal User currentUser, @RequestBody MealOrderRequest request) {
return Response.success(
orderService.orderMeals(
Expand All @@ -55,17 +55,17 @@ public Response<SliceResult<OrderResponse>> searchOrders(

@GetMapping("/{orderId}")
public Response<OrderDetailResponse> orderDetail(
@AuthenticationPrincipal User currentUser, @PathVariable Long orderId) {
@AuthenticationPrincipal User currentUser, @PathVariable String orderId) {
OrderDetail orderDetail =
orderService.getOrderDetail(Orderer.from(currentUser), TargetOrder.from(orderId));
orderService.getOrderDetail(Orderer.from(currentUser), OrderId.from(orderId));
return Response.success(OrderDetailResponse.from(orderDetail));
}

@GetMapping("/{orderId}/state")
public Response<OrderState> orderState(
@AuthenticationPrincipal User currentUser, @PathVariable Long orderId) {
@AuthenticationPrincipal User currentUser, @PathVariable String orderId) {
return Response.success(
orderService.getOrderState(Orderer.from(currentUser), TargetOrder.from(orderId)));
orderService.getOrderState(Orderer.from(currentUser), OrderId.from(orderId)));
}

@GetMapping("/count")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
import core.startup.mealtoktok.common.dto.Cursor;
import core.startup.mealtoktok.common.dto.Response;
import core.startup.mealtoktok.common.dto.SliceResult;
import core.startup.mealtoktok.domain.order.OrderId;
import core.startup.mealtoktok.domain.order.OrderSearchCond;
import core.startup.mealtoktok.domain.order.OrderState;
import core.startup.mealtoktok.domain.order.TargetOrder;
import core.startup.mealtoktok.domain.user.User;

import io.swagger.v3.oas.annotations.Operation;
Expand All @@ -18,17 +18,17 @@
public interface OrderApiDocs {

@Operation(summary = "도시락 주문")
Response<TargetOrder> orderMeals(User currentUser, MealOrderRequest request);
Response<OrderId> orderMeals(User currentUser, MealOrderRequest request);

@Operation(summary = "주문 내역 검색")
Response<SliceResult<OrderResponse>> searchOrders(
User currentUser, OrderSearchCond cond, Cursor cursor);

@Operation(summary = "주문 내역 상세 조회")
Response<OrderDetailResponse> orderDetail(User currentUser, Long orderId);
Response<OrderDetailResponse> orderDetail(User currentUser, String orderId);

@Operation(summary = "주문 상태 조회")
Response<OrderState> orderState(User currentUser, Long orderId);
Response<OrderState> orderState(User currentUser, String orderId);

@Operation(summary = "상태별 주문 건수 조회")
Response<Integer> countOrders(User currentUser, OrderState orderState);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import core.startup.mealtoktok.domain.order.Orderer;

public record OrderResponse(
Long orderId,
String orderId,
OrderType orderType,
OrderState orderState,
String specialInstruction,
Expand All @@ -21,7 +21,7 @@ public record OrderResponse(

public static OrderResponse from(Order order) {
return new OrderResponse(
order.getOrderId(),
order.getOrderId().toString(),
order.getOrderType(),
order.getOrderState(),
order.getSpecialInstruction(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package core.startup.mealtoktok.api.payment;

import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import lombok.RequiredArgsConstructor;

import core.startup.mealtoktok.api.payment.dto.PaymentCancelRequest;
import core.startup.mealtoktok.api.payment.dto.PaymentFailReason;
import core.startup.mealtoktok.api.payment.dto.PaymentRequest;
import core.startup.mealtoktok.api.payment.dto.PaymentResponse;
import core.startup.mealtoktok.common.dto.Response;
import core.startup.mealtoktok.domain.payment.PaymentId;
import core.startup.mealtoktok.domain.payment.PaymentService;

@RestController
@RequestMapping("/api/v1/payments")
@RequiredArgsConstructor
public class PaymentApi implements PaymentApiDocs {

private final PaymentService paymentService;

@PostMapping("/success")
public Response<PaymentResponse> pay(PaymentRequest request) {
return Response.success(
PaymentResponse.from(
paymentService.pay(
request.paymentKey(), request.toOrderId(), request.toAmount())));
}

@PostMapping("/fail")
public Response<Void> fail(PaymentFailReason paymentFailReason) {
paymentService.fail(paymentFailReason.message(), paymentFailReason.toOrderId());
return Response.error(paymentFailReason.code(), paymentFailReason.message());
}

@PostMapping("/{paymentId}/cancel")
public Response<Void> cancel(
@PathVariable Long paymentId, @RequestBody PaymentCancelRequest request) {
paymentService.cancel(PaymentId.from(paymentId), request.cancelReason());
return Response.success("성공적으로 결제가 취소되었습니다.");
}
}
Loading