File History: src/main/java/com/paymentlink/service/StripePaymentService.java

← View file content

File Content at Commit 188fc92

1 package com.paymentlink.service;
2
3 import com.stripe.exception.StripeException;
4 import com.stripe.model.PaymentIntent;
5 import com.stripe.model.checkout.Session;
6 import com.stripe.param.PaymentIntentCreateParams;
7 import com.stripe.param.checkout.SessionCreateParams;
8 import com.paymentlink.model.entity.Order;
9 import com.paymentlink.model.entity.Product;
10 import com.paymentlink.repository.OrderRepository;
11 import org.slf4j.Logger;
12 import org.slf4j.LoggerFactory;
13 import org.springframework.beans.factory.annotation.Value;
14 import org.springframework.stereotype.Service;
15
16 @Service
17 public class StripePaymentService {
18
19 private static final Logger logger = LoggerFactory.getLogger(StripePaymentService.class);
20
21 private final CurrencyService currencyService;
22 private final OrderRepository orderRepository;
23
24 @Value("${stripe.publishable.key}")
25 private String publishableKey;
26
27 @Value("${stripe.success.url:http://localhost:8080/order-confirmation}")
28 private String successUrl;
29
30 @Value("${stripe.cancel.url:http://localhost:8080/checkout}")
31 private String cancelUrl;
32
33 public StripePaymentService(CurrencyService currencyService, OrderRepository orderRepository) {
34 this.currencyService = currencyService;
35 this.orderRepository = orderRepository;
36 }
37
38 /**
39 * Create a PaymentIntent for a payment (legacy method)
40 */
41 public PaymentIntent createPaymentIntent(long amount, String currency) throws StripeException {
42 logger.info("Creating Stripe PaymentIntent: amount={}, currency={}", amount, currency);
43
44 PaymentIntentCreateParams params = PaymentIntentCreateParams.builder()
45 .setAmount(amount)
46 .setCurrency(currency.toLowerCase())
47 .addPaymentMethodType("card")
48 .build();
49
50 PaymentIntent paymentIntent = PaymentIntent.create(params);
51 logger.info("Created PaymentIntent: {}", paymentIntent.getId());
52
53 return paymentIntent;
54 }
55
56 /**
57 * Create a Checkout Session with multi-currency support
58 * CRITICAL: Charges in target currency, not USD
59 */
60 public String createCheckoutSession(Order order, String targetCurrency) throws StripeException {
61 // Validate currency is supported by Stripe
62 if (!currencyService.isCurrencySupported(targetCurrency)) {
63 logger.warn("Currency {} not supported by Stripe, falling back to USD", targetCurrency);
64 targetCurrency = "USD";
65 }
66
67 // Make targetCurrency effectively final for lambda usage
68 final String finalTargetCurrency = targetCurrency;
69
70 // Convert total to target currency
71 Long convertedAmount = currencyService.convertPrice(
72 order.getTotal(),
73 order.getCurrency() != null ? order.getCurrency() : "USD",
74 finalTargetCurrency
75 );
76
77 // Store conversion details in order
78 order.setCurrency(finalTargetCurrency);
79 order.setOriginalCurrency(order.getCurrency() != null ? order.getCurrency() : "USD");
80 order.setOriginalAmount(order.getTotal());
81 order.setExchangeRate(currencyService.getRate(
82 order.getOriginalCurrency(),
83 finalTargetCurrency
84 ));
85 orderRepository.save(order);
86
87 // Build line items from order items
88 SessionCreateParams.Builder paramsBuilder = SessionCreateParams.builder()
89 .setMode(SessionCreateParams.Mode.PAYMENT)
90 .setSuccessUrl(successUrl + "?orderId=" + order.getOrderId())
91 .setCancelUrl(cancelUrl + "?orderId=" + order.getOrderId())
92 .putMetadata("orderId", order.getOrderId())
93 .putMetadata("originalCurrency", order.getOriginalCurrency())
94 .putMetadata("originalAmount", String.valueOf(order.getOriginalAmount()));
95
96 // Add line items for each product in the order
97 order.getItems().forEach(item -> {
98 // Convert item price to target currency
99 Long itemPrice = currencyService.convertPrice(
100 item.getPrice(),
101 order.getOriginalCurrency(),
102 finalTargetCurrency
103 );
104
105 SessionCreateParams.LineItem lineItem = SessionCreateParams.LineItem.builder()
106 .setPriceData(
107 SessionCreateParams.LineItem.PriceData.builder()
108 .setCurrency(finalTargetCurrency.toLowerCase()) // Stripe requires lowercase
109 .setUnitAmount(itemPrice) // Amount in cents
110 .setProductData(
111 SessionCreateParams.LineItem.PriceData.ProductData.builder()
112 .setName(item.getProductName() != null ? item.getProductName() : "Product")
113 .build()
114 )
115 .build()
116 )
117 .setQuantity((long) item.getQuantity())
118 .build();
119
120 paramsBuilder.addLineItem(lineItem);
121 });
122
123 SessionCreateParams params = paramsBuilder.build();
124 Session session = Session.create(params);
125
126 logger.info("Created Stripe Checkout Session: {} for order: {} in currency: {} (converted from {} {})",
127 session.getId(), order.getOrderId(), finalTargetCurrency, order.getOriginalAmount(), order.getOriginalCurrency());
128
129 return session.getUrl();
130 }
131
132 /**
133 * Retrieve a PaymentIntent
134 */
135 public PaymentIntent retrievePaymentIntent(String paymentIntentId) throws StripeException {
136 return PaymentIntent.retrieve(paymentIntentId);
137 }
138
139 /**
140 * Get publishable key (for frontend)
141 */
142 public String getPublishableKey() {
143 return publishableKey;
144 }
145
146 /**
147 * Check if payment intent is successful
148 */
149 public boolean isPaymentSuccessful(PaymentIntent paymentIntent) {
150 return "succeeded".equals(paymentIntent.getStatus());
151 }
152 }
153
154

Commits

Commit Author Date Message File SHA Actions
f0438c2 <f69e50@finnacloud.com> 1766443042 +0300 12/22/2025, 10:37:22 PM increment once more 4f6261c View
188fc92 <f69e50@finnacloud.com> 1766442998 +0300 12/22/2025, 10:36:38 PM increment 4f6261c Hide
4617f76 <f69e50@finnacloud.com> 1766442953 +0300 12/22/2025, 10:35:53 PM rename branch from main to master oops 4f6261c View
e6d1548 <f69e50@finnacloud.com> 1766442769 +0300 12/22/2025, 10:32:49 PM add initial test workflow file 4f6261c View
9c24ca4 <f69e50@finnacloud.com> 1766442705 +0300 12/22/2025, 10:31:45 PM add CI configuration and test script for Jenkins build 4f6261c View
690c1f6 <f69e50@finnacloud.com> 1766368110 +0300 12/22/2025, 1:48:30 AM initialize backend structure with controllers, DTOs, and configuration files 4f6261c View