· 7 years ago · Jan 11, 2019, 07:54 PM
1package com.wigo.riders.service;
2
3import com.stripe.Stripe;
4import com.stripe.exception.StripeException;
5import com.stripe.model.Charge;
6import com.stripe.model.Customer;
7import com.stripe.net.RequestOptions;
8import com.wigo.riders.exceptions.PaymentException;
9import com.wigo.riders.model.pago.Pago;
10import com.wigo.riders.model.pago.util.PagoRequest;
11import com.wigo.riders.model.pago.util.PagoResponse;
12import com.wigo.riders.model.pago.util.TarjetaStatus;
13import com.wigo.riders.model.user.Rider;
14import org.json.JSONArray;
15import org.json.JSONException;
16import org.json.JSONObject;
17import org.slf4j.Logger;
18import org.slf4j.LoggerFactory;
19import org.springframework.beans.factory.annotation.Autowired;
20import org.springframework.beans.factory.annotation.Value;
21import org.springframework.security.core.userdetails.UsernameNotFoundException;
22import org.springframework.stereotype.Service;
23
24import javax.annotation.PostConstruct;
25import java.util.*;
26
27@Service
28public class PaymentService {
29
30 private static final Logger logger = LoggerFactory.getLogger(PaymentService.class);
31
32
33 private final UserService<Rider> userService;
34 private final RequestOptions requestOptions;
35
36 @Value("${stripe.secret.key}")
37 private String secretKey;
38
39 @Value("${stripe.api.version}")
40 private String apiVersion;
41
42 @Value("${stripe.cardLimit}")
43 private int cardsLimit;
44
45 private TestService testService;
46
47 @Autowired
48 public PaymentService(UserService<Rider> userService, TestService testService) {
49 this.testService = testService;
50 this.userService = userService;
51 requestOptions = (new RequestOptions.RequestOptionsBuilder()).setStripeVersion(apiVersion).build();
52 }
53
54 @PostConstruct
55 public void init() {
56 Stripe.apiKey = secretKey;
57 }
58
59
60 public PagoResponse processPayment(PagoRequest pagoRequest) {
61 Map<String, Object> cardParams = new HashMap<>();
62 List<String> cardsId = new ArrayList<>();
63 cardParams.put("limit", cardsLimit);
64 cardParams.put("object", "card");
65
66 Optional<Rider> userOptional = Optional.of(userService.getbyId(pagoRequest.getUserId()));
67
68 if (!userOptional.isPresent()) {
69 return invalidPayment("no se encontro el usuario para hacer el cobro", null);
70 }
71
72 Rider user = userOptional.get();
73
74 try {
75 logger.info("el id de stripe es: " + user.getStripeCustomerId());
76
77 JSONObject data = new JSONObject(Customer.retrieve(user.getStripeCustomerId(), requestOptions).getSources().all(cardParams));
78 JSONArray tarjetas = data.getJSONArray("data");
79
80 logger.info(data.toString());
81
82 for (int i = 0; i < tarjetas.length(); i++) {
83 JSONObject card = tarjetas.getJSONObject(i);
84 cardsId.add(card.getString("id"));
85 }
86
87 } catch (StripeException e) {
88 return invalidPayment("no se pudieron obtener las tarjetas del usuario " + e.getCode(), user);
89 } catch (JSONException e) {
90 return invalidPayment("no se pudieron obtener las tarjetas del usuario " + e.getMessage(), user);
91 }
92
93 return pay(cardsId, pagoRequest, user);
94
95
96 }
97
98
99 private PagoResponse pay(List<String> cards, PagoRequest pagoRequest, Rider user) {
100 logger.info("el listado de tarjetas es: " + cards.size());
101
102
103 if (Objects.isNull(cards) || cards.isEmpty()) {
104 return invalidPayment("el usuario no tiene tarjetas asociadas", user);
105 }
106
107 PagoResponse pagoResponse = new PagoResponse();
108 List<TarjetaStatus> cardStatus = new ArrayList<>();
109 ListIterator<String> iter = cards.listIterator();
110 boolean cobrado = false;
111 while (iter.hasNext()) {
112 String card = iter.next();
113 Pago pago = new Pago();
114 pago.setAmount(pagoRequest.getAmount());
115 pago.setDescription(pagoRequest.getDescription());
116 pago.setUser(user);
117 pago.setToken(card);
118 try {
119 logger.info("intando cobrar con tarjeta " + card);
120 makePayment(pago);
121 cobrado = true;
122 break;
123 } catch (StripeException e) {
124 logger.info("no se pudo cobrar", e.getCode());
125 iter.remove();
126 cobrado = false;
127 cardStatus.add(new TarjetaStatus(card, e.getCode()));
128 }
129
130 }
131
132 if (cobrado) {
133 logger.info("desbloqueando usuario");
134 pagoResponse.setUserBlocked(!toggleActiveUser(user, true));
135 pagoResponse.setMessage("Pago Realizado exitosamente");
136 } else {
137 logger.info("bloqueando usuario");
138 pagoResponse.setUserBlocked(!toggleActiveUser(user, false));
139 }
140
141 pagoResponse.setPaymentSucess(cobrado);
142 pagoResponse.setCardStatuses(cardStatus);
143 pagoResponse.setPaymentDate(new Date());
144
145 return pagoResponse;
146 }
147
148 private PagoResponse invalidPayment(String message, Rider user) {
149 PagoResponse pagoResponse = new PagoResponse();
150 pagoResponse.setPaymentSucess(false);
151 pagoResponse.setPaymentDate(new Date());
152 pagoResponse.setMessage(message);
153 if (Objects.nonNull(user) && Objects.nonNull(user.getId())) {
154 pagoResponse.setUserBlocked(!toggleActiveUser(user, false));
155 }
156
157 return pagoResponse;
158 }
159
160
161 public boolean userHasCards(long userId) {
162 boolean hasCards = false;
163 Map<String, Object> cardParams = new HashMap<>();
164 cardParams.put("limit", cardsLimit);
165 cardParams.put("object", "card");
166
167 Optional<Rider> userOptional = Optional.of(userService.getbyId(userId));
168
169 if (!userOptional.isPresent()) {
170 throw new UsernameNotFoundException("no se encontro el usuario");
171 }
172 Rider user;
173
174 if(userOptional.get() instanceof Rider){
175 user = userOptional.get();
176 }else {
177 throw new PaymentException("el usuario no es un rider");
178 }
179
180
181 try {
182 logger.info("el id de stripe es: " + user.getStripeCustomerId());
183
184 JSONObject data = new JSONObject(Customer.retrieve(user.getStripeCustomerId(), requestOptions).getSources().all(cardParams));
185 JSONArray tarjetas = data.getJSONArray("data");
186
187 if (Objects.nonNull(tarjetas)) {
188 if (tarjetas.length() > 0) {
189 hasCards = true;
190 }
191 }
192
193 } catch (StripeException | JSONException ignored) {
194 //ignored.printStackTrace();
195 }
196
197 return hasCards;
198 }
199
200 private boolean toggleActiveUser(Rider user, boolean active) {
201 user.setActive(active);
202 return userService.update(user).getActive();
203 }
204
205
206 private long converTocents(float amount) {
207 long allCents = Math.round(amount * 100);
208 logger.info("enviando esta cantidad de dinero " + allCents);
209 return allCents;
210 }
211
212
213 private void makePayment(Pago pago) throws StripeException {
214 Map<String, Object> chargeParams = new HashMap<>();
215 chargeParams.put("amount", converTocents(pago.getAmount()));// en centavos
216 chargeParams.put("currency", pago.getCurrency());
217 chargeParams.put("source", pago.getToken());
218 chargeParams.put("customer", pago.getUser().getStripeCustomerId());
219 chargeParams.put("description", pago.getUser().getUsername());
220 chargeParams.put("receipt_email", pago.getUser().getEmail());
221 Charge.create(chargeParams, requestOptions);
222 }
223}