From c940305ee9e6dfb8bf9fd638011603758fdc0382 Mon Sep 17 00:00:00 2001 From: hvs-flick Date: Sat, 11 Nov 2023 19:22:39 +0530 Subject: [PATCH 1/3] Refactor code and add uniqueEventId --- .../bean/confugration/ProxyConfiguration.java | 23 ++++++++ .../graphql/builder/EventBuilder.java | 10 ++-- .../graphql/controller/PaymentController.java | 53 +++---------------- .../graphql/input/InitiatePaymentInput.java | 3 +- .../platform/graphql/type/Event.java | 1 + .../platform/proxy/PhonePeProxy.java | 51 ++++++++++++++++++ .../resources/application-beta.properties | 6 ++- .../main/resources/application-dev.properties | 6 ++- .../resources/application-prod.properties | 6 ++- .../main/resources/graphql/schema.graphqls | 6 +-- .../resources/application-test.properties | 3 ++ 11 files changed, 110 insertions(+), 58 deletions(-) create mode 100644 platform/src/main/java/com/flickmatch/platform/bean/confugration/ProxyConfiguration.java create mode 100644 platform/src/main/java/com/flickmatch/platform/proxy/PhonePeProxy.java diff --git a/platform/src/main/java/com/flickmatch/platform/bean/confugration/ProxyConfiguration.java b/platform/src/main/java/com/flickmatch/platform/bean/confugration/ProxyConfiguration.java new file mode 100644 index 00000000..d6ad1e84 --- /dev/null +++ b/platform/src/main/java/com/flickmatch/platform/bean/confugration/ProxyConfiguration.java @@ -0,0 +1,23 @@ +package com.flickmatch.platform.bean.confugration; + +import com.phonepe.sdk.pg.Env; +import com.phonepe.sdk.pg.payments.v1.PhonePePaymentClient; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ProxyConfiguration { + + @Value("${phonepe.merchant.id}") + private String merchantId; + @Value("${phonepe.saltkey}") + private String saltKey; + @Value("${phonepe.saltkey.index}") + private Integer saltIndex; + + @Bean + PhonePePaymentClient phonePePaymentClient() { + return new PhonePePaymentClient(merchantId, saltKey, saltIndex, Env.PROD, true); + } +} diff --git a/platform/src/main/java/com/flickmatch/platform/graphql/builder/EventBuilder.java b/platform/src/main/java/com/flickmatch/platform/graphql/builder/EventBuilder.java index fbb68401..dab17f76 100644 --- a/platform/src/main/java/com/flickmatch/platform/graphql/builder/EventBuilder.java +++ b/platform/src/main/java/com/flickmatch/platform/graphql/builder/EventBuilder.java @@ -14,8 +14,6 @@ import java.text.ParseException; import java.text.SimpleDateFormat; -import java.time.LocalDate; -import java.time.ZoneId; import java.time.temporal.ChronoUnit; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; @@ -111,7 +109,7 @@ public List getEvents(String cityId, List dailyEventList = eventData.get().getEventDetailsList().stream() .filter(eventDetails -> eventDetails.getStartTime().after(currentTime)) - .map(eventDetails -> mapEventToGQLType(eventDetails, formattedDate, localTimeZone)) + .map(eventDetails -> mapEventToGQLType(eventDetails, formattedDate, localTimeZone, cityId)) .toList(); eventList.addAll(dailyEventList); } @@ -132,7 +130,7 @@ public List getPastEvents(String cit eventDetails.getStartTime().before(currentTime) && eventDetails.getStartTime().after(dateBeforeInDays) ).map(eventDetails -> - mapEventToGQLType(eventDetails, event.getDate(), localTimeZone) + mapEventToGQLType(eventDetails, event.getDate(), localTimeZone, cityId) ).toList(); pastEventList.addAll(pastEventsInCity); } @@ -189,8 +187,9 @@ private String getPaymentUrlForEvent(SportsVenue sportsVenue, Double amount) { return stripePaymentLinkForAmount.get().getUrl(); } - private com.flickmatch.platform.graphql.type.Event mapEventToGQLType(Event.EventDetails eventDetails, String date, String localTimeZone) { + private com.flickmatch.platform.graphql.type.Event mapEventToGQLType(Event.EventDetails eventDetails, String date, String localTimeZone, String cityId) { String eventId = date + "-" + eventDetails.getIndex(); + String uniqueEventId = cityId + "-" + date + "-" + eventDetails.getIndex(); int players = eventDetails.getReservedPlayersCount() / 2; String eventType = players + "v" + players; //Todo: clean up this field from schema @@ -203,6 +202,7 @@ private com.flickmatch.platform.graphql.type.Event mapEventToGQLType(Event.Event .currency(eventDetails.getCurrency()) .endTime(eventDetails.getEndTime()) .eventId(eventId) + .uniqueEventId(uniqueEventId) .displayTitle(title) .date(getFormattedEventDate(eventDetails.getStartTime(), localTimeZone)) .time(getFormattedEventTime(eventDetails.getStartTime(), eventDetails.getEndTime(), localTimeZone)) diff --git a/platform/src/main/java/com/flickmatch/platform/graphql/controller/PaymentController.java b/platform/src/main/java/com/flickmatch/platform/graphql/controller/PaymentController.java index cf00a95b..1e125576 100644 --- a/platform/src/main/java/com/flickmatch/platform/graphql/controller/PaymentController.java +++ b/platform/src/main/java/com/flickmatch/platform/graphql/controller/PaymentController.java @@ -2,67 +2,30 @@ import com.flickmatch.platform.graphql.input.InitiatePaymentInput; import com.flickmatch.platform.graphql.type.InitiatePaymentOutput; -import com.phonepe.sdk.pg.Env; -import com.phonepe.sdk.pg.common.http.PhonePeResponse; -import com.phonepe.sdk.pg.payments.v1.PhonePePaymentClient; -import com.phonepe.sdk.pg.payments.v1.models.request.PgPayRequest; -import com.phonepe.sdk.pg.payments.v1.models.response.PayPageInstrumentResponse; -import com.phonepe.sdk.pg.payments.v1.models.response.PgPayResponse; +import com.flickmatch.platform.proxy.PhonePeProxy; import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.graphql.data.method.annotation.Argument; import org.springframework.graphql.data.method.annotation.MutationMapping; import org.springframework.stereotype.Controller; -import java.util.UUID; - @Controller @Log4j2 public class PaymentController { + @Autowired + PhonePeProxy phonePeProxy; + @MutationMapping public InitiatePaymentOutput initiatePayment(@Argument InitiatePaymentInput input) { String paymentLink = "https://example.com/payment/link"; try { - paymentLink = initiate(); + paymentLink = phonePeProxy.initiatePayment(); } catch (Exception exception) { exception.printStackTrace(); } - InitiatePaymentOutput output = new InitiatePaymentOutput(paymentLink); - output.setPaymentLink(paymentLink); - return output; - } - - /* - Calls PhonePe Pay API using sdk - https://developer.phonepe.com/v1/reference/pay-api-1 - https://developer.phonepe.com/v1/reference/java-standard-pay-page - */ - private String initiate() { - String merchantId = "M1FPXNBFIGDG"; - String saltKey = "e7a5693b-0ccf-47ac-a258-c5d77e701e2c"; - Integer saltIndex = Integer.valueOf(2); - Env env = Env.PROD; - boolean shouldPublishEvents = true; - PhonePePaymentClient phonepeClient = new PhonePePaymentClient(merchantId, saltKey, saltIndex, env, shouldPublishEvents); - - String merchantTransactionId = UUID.randomUUID().toString().substring(0,34); - long amount = 200; - String callbackUrl = "https://service.flickmatch.in:8443/platform-0.0.1-SNAPSHOT/payment"; - String merchantUserId = "merchantUserId"; - - PgPayRequest pgPayRequest = PgPayRequest.PayPagePayRequestBuilder() - .amount(amount) - .merchantId(merchantId) - .merchantTransactionId(merchantTransactionId) - .callbackUrl(callbackUrl) - .callbackMode("REDIRECT") - .redirectUrl("https://play.flickmatch.in/") - .redirectMode("REDIRECT") - .merchantUserId(merchantUserId) + return InitiatePaymentOutput.builder() + .paymentLink(paymentLink) .build(); - - PhonePeResponse payResponse = phonepeClient.pay(pgPayRequest); - PayPageInstrumentResponse payPageInstrumentResponse = (PayPageInstrumentResponse) payResponse.getData().getInstrumentResponse(); - return payPageInstrumentResponse.getRedirectInfo().getUrl(); } } diff --git a/platform/src/main/java/com/flickmatch/platform/graphql/input/InitiatePaymentInput.java b/platform/src/main/java/com/flickmatch/platform/graphql/input/InitiatePaymentInput.java index 7b4555b0..d7de7892 100644 --- a/platform/src/main/java/com/flickmatch/platform/graphql/input/InitiatePaymentInput.java +++ b/platform/src/main/java/com/flickmatch/platform/graphql/input/InitiatePaymentInput.java @@ -6,7 +6,6 @@ @Builder @Getter public class InitiatePaymentInput { - String eventId; - String cityId; + String uniqueEventId; PlayerInput player; } diff --git a/platform/src/main/java/com/flickmatch/platform/graphql/type/Event.java b/platform/src/main/java/com/flickmatch/platform/graphql/type/Event.java index bb3986e7..20734fe1 100644 --- a/platform/src/main/java/com/flickmatch/platform/graphql/type/Event.java +++ b/platform/src/main/java/com/flickmatch/platform/graphql/type/Event.java @@ -10,6 +10,7 @@ public class Event { private Date startTime; private Date endTime; private String eventId; + private String uniqueEventId; //TODO: Remove displayTitle and logic from mapEventToGQLType, // after WA client start using individual fields private String displayTitle; diff --git a/platform/src/main/java/com/flickmatch/platform/proxy/PhonePeProxy.java b/platform/src/main/java/com/flickmatch/platform/proxy/PhonePeProxy.java new file mode 100644 index 00000000..e0f3a07b --- /dev/null +++ b/platform/src/main/java/com/flickmatch/platform/proxy/PhonePeProxy.java @@ -0,0 +1,51 @@ +package com.flickmatch.platform.proxy; + +import com.phonepe.sdk.pg.common.http.PhonePeResponse; +import com.phonepe.sdk.pg.payments.v1.PhonePePaymentClient; +import com.phonepe.sdk.pg.payments.v1.models.request.PgPayRequest; +import com.phonepe.sdk.pg.payments.v1.models.response.PayPageInstrumentResponse; +import com.phonepe.sdk.pg.payments.v1.models.response.PgPayResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.util.UUID; + +@Service +public class PhonePeProxy { + + @Autowired + private PhonePePaymentClient phonePeClient; + + @Value("${phonepe.merchant.id}") + private String merchantId; + + /** + * Calls PhonePe Pay API using sdk + * https://developer.phonepe.com/v1/reference/pay-api-1 + * https://developer.phonepe.com/v1/reference/java-standard-pay-page + * + * @return payment link + */ + public String initiatePayment() { + String merchantTransactionId = UUID.randomUUID().toString().substring(0,34); + long amount = 200; + String callbackUrl = "https://service.flickmatch.in:8443/platform-0.0.1-SNAPSHOT/payment"; + String merchantUserId = "merchantUserId"; + + PgPayRequest pgPayRequest = PgPayRequest.PayPagePayRequestBuilder() + .merchantId(merchantId) + .amount(amount) + .merchantTransactionId(merchantTransactionId) + .callbackUrl(callbackUrl) + .callbackMode("REDIRECT") + .redirectUrl("https://play.flickmatch.in/") + .redirectMode("REDIRECT") + .merchantUserId(merchantUserId) + .build(); + + PhonePeResponse payResponse = phonePeClient.pay(pgPayRequest); + PayPageInstrumentResponse payPageInstrumentResponse = (PayPageInstrumentResponse) payResponse.getData().getInstrumentResponse(); + return payPageInstrumentResponse.getRedirectInfo().getUrl(); + } +} diff --git a/platform/src/main/resources/application-beta.properties b/platform/src/main/resources/application-beta.properties index 4583ec41..f137bbcf 100644 --- a/platform/src/main/resources/application-beta.properties +++ b/platform/src/main/resources/application-beta.properties @@ -3,4 +3,8 @@ spring.graphql.cors.allowed-origins=* amazon.dynamodb.endpoint=https://dynamodb.ap-south-1.amazonaws.com amazon.aws.region=ap-south-1 -amazon.aws.profile=beta \ No newline at end of file +amazon.aws.profile=beta + +phonepe.merchant.id=M1FPXNBFIGDG +phonepe.saltkey=e7a5693b-0ccf-47ac-a258-c5d77e701e2c +phonepe.saltkey.index=2 \ No newline at end of file diff --git a/platform/src/main/resources/application-dev.properties b/platform/src/main/resources/application-dev.properties index b6a570f2..8158da68 100644 --- a/platform/src/main/resources/application-dev.properties +++ b/platform/src/main/resources/application-dev.properties @@ -2,4 +2,8 @@ spring.graphql.graphiql.enabled=true amazon.dynamodb.endpoint=http://localhost:8000/ amazon.aws.region=ap-south-1 -amazon.aws.profile=dev \ No newline at end of file +amazon.aws.profile=dev + +phonepe.merchant.id=test +phonepe.saltkey=test +phonepe.saltkey.index=1 \ No newline at end of file diff --git a/platform/src/main/resources/application-prod.properties b/platform/src/main/resources/application-prod.properties index c66bd4e4..a662cb7d 100644 --- a/platform/src/main/resources/application-prod.properties +++ b/platform/src/main/resources/application-prod.properties @@ -3,4 +3,8 @@ spring.graphql.cors.allowed-origins=* amazon.dynamodb.endpoint=https://dynamodb.ap-south-1.amazonaws.com amazon.aws.region=ap-south-1 -amazon.aws.profile=prod \ No newline at end of file +amazon.aws.profile=prod + +phonepe.merchant.id=M1FPXNBFIGDG +phonepe.saltkey=e7a5693b-0ccf-47ac-a258-c5d77e701e2c +phonepe.saltkey.index=2 diff --git a/platform/src/main/resources/graphql/schema.graphqls b/platform/src/main/resources/graphql/schema.graphqls index ab0f0027..a9ef443d 100644 --- a/platform/src/main/resources/graphql/schema.graphqls +++ b/platform/src/main/resources/graphql/schema.graphqls @@ -52,8 +52,7 @@ input JoinEventInput { } input InitiatePaymentInput { - eventId: ID! - cityId: ID! + uniqueEventId: ID! player: PlayerInput! } @@ -124,7 +123,8 @@ type EVENT { currency: String! startTime: String! endTime: String! - eventId: String! + eventId: String! @deprecated(reason: "Use `uniqueEventId`.") + uniqueEventId: String! displayTitle: String! venueLocationLink: String! charges: Float! diff --git a/platform/src/test/resources/application-test.properties b/platform/src/test/resources/application-test.properties index fd7964ff..9529f667 100644 --- a/platform/src/test/resources/application-test.properties +++ b/platform/src/test/resources/application-test.properties @@ -6,3 +6,6 @@ amazon.aws.profile=beta application.local.endpoint=http://localhost:8080/graphql +phonepe.merchant.id=test +phonepe.saltkey=test +phonepe.saltkey.index=1 From 247b3b8c5e410272a7d9921676a3c8c55386942d Mon Sep 17 00:00:00 2001 From: hvs-flick Date: Sat, 11 Nov 2023 19:47:01 +0530 Subject: [PATCH 2/3] Use uniqueEventId in joinEvent --- .../graphql/builder/EventBuilder.java | 36 +++++++++++++------ .../graphql/input/JoinEventInput.java | 3 ++ .../main/resources/graphql/schema.graphqls | 5 +-- 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/platform/src/main/java/com/flickmatch/platform/graphql/builder/EventBuilder.java b/platform/src/main/java/com/flickmatch/platform/graphql/builder/EventBuilder.java index dab17f76..5e0c74a7 100644 --- a/platform/src/main/java/com/flickmatch/platform/graphql/builder/EventBuilder.java +++ b/platform/src/main/java/com/flickmatch/platform/graphql/builder/EventBuilder.java @@ -11,6 +11,7 @@ import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -54,21 +55,34 @@ public Event createEvent(CreateEventInput input, boolean shouldValidateStartTime public void joinEvent(JoinEventInput input) { int index = 0; - //TODO: Remove hardcoded value once whatsApp is not used for joining event - String date = input.getEventId(); - String[] parts = date.split("-"); - try{ - date = parts[0] + "-" + parts[1] + "-" + parts[2]; - index = Integer.parseInt(parts[3]); - } - catch (NumberFormatException e) - { - System.out.println("Error: The given string cannot be converted to an integer."); + String date = null; + String cityId = null; + if (StringUtils.hasText(input.getUniqueEventId())) { + String[] parts = input.getUniqueEventId().split("-"); + try{ + cityId = parts[0]; + date = parts[1] + "-" + parts[2] + "-" + parts[3]; + index = Integer.parseInt(parts[4]); + } catch (NumberFormatException e) { + log.error(input.getUniqueEventId()); + throw new IllegalArgumentException("Input is invalid"); + } + } else { + String[] parts = input.getEventId().split("-"); + try{ + date = parts[0] + "-" + parts[1] + "-" + parts[2]; + index = Integer.parseInt(parts[3]); + cityId = input.getCityId(); + } catch (NumberFormatException e) { + log.error(input.getEventId()); + throw new IllegalArgumentException("Input is invalid"); + } } log.info(date); log.info(index); + log.info(cityId); Optional eventsInCity = - eventRepository.findById(new Event.EventId(input.getCityId(),date)); + eventRepository.findById(new Event.EventId(cityId, date)); if (eventsInCity.isPresent()) { final int finalIndex = index; Optional selectedEvent = eventsInCity.get().getEventDetailsList() diff --git a/platform/src/main/java/com/flickmatch/platform/graphql/input/JoinEventInput.java b/platform/src/main/java/com/flickmatch/platform/graphql/input/JoinEventInput.java index b5034015..8c38a6fa 100644 --- a/platform/src/main/java/com/flickmatch/platform/graphql/input/JoinEventInput.java +++ b/platform/src/main/java/com/flickmatch/platform/graphql/input/JoinEventInput.java @@ -7,7 +7,10 @@ @Getter public class JoinEventInput { + @Deprecated String eventId; + @Deprecated String cityId; + String uniqueEventId; PlayerInput player; } diff --git a/platform/src/main/resources/graphql/schema.graphqls b/platform/src/main/resources/graphql/schema.graphqls index a9ef443d..22caed9a 100644 --- a/platform/src/main/resources/graphql/schema.graphqls +++ b/platform/src/main/resources/graphql/schema.graphqls @@ -46,8 +46,9 @@ input CreateEventInput { } input JoinEventInput { - eventId: ID! - cityId: ID! + eventId: ID @deprecated(reason: "Use `uniqueEventId`.") + cityId: ID @deprecated(reason: "Use `uniqueEventId`.") + uniqueEventId: ID player: PlayerInput! } From 3ac52c9616b3dbb41370d7909db539bebf9d4a88 Mon Sep 17 00:00:00 2001 From: hvs-flick Date: Sat, 11 Nov 2023 23:05:35 +0530 Subject: [PATCH 3/3] Add PaymentRequest table and add logic to persist data --- .../dynamodb/model/PaymentRequest.java | 59 +++++++++++++++++++ .../dynamodb/repository/CityRepository.java | 1 - .../repository/PaymentRequestRepository.java | 10 ++++ .../graphql/builder/EventBuilder.java | 43 ++++++++++++++ .../builder/PaymentRequestBuilder.java | 36 +++++++++++ .../graphql/controller/PaymentController.java | 28 +++++++-- .../graphql/input/InitiatePaymentInput.java | 4 +- .../graphql/type/InitiatePaymentOutput.java | 4 +- .../platform/proxy/PhonePeProxy.java | 6 +- .../main/resources/graphql/schema.graphqls | 6 +- 10 files changed, 178 insertions(+), 19 deletions(-) create mode 100644 platform/src/main/java/com/flickmatch/platform/dynamodb/model/PaymentRequest.java create mode 100644 platform/src/main/java/com/flickmatch/platform/dynamodb/repository/PaymentRequestRepository.java create mode 100644 platform/src/main/java/com/flickmatch/platform/graphql/builder/PaymentRequestBuilder.java diff --git a/platform/src/main/java/com/flickmatch/platform/dynamodb/model/PaymentRequest.java b/platform/src/main/java/com/flickmatch/platform/dynamodb/model/PaymentRequest.java new file mode 100644 index 00000000..07c9c082 --- /dev/null +++ b/platform/src/main/java/com/flickmatch/platform/dynamodb/model/PaymentRequest.java @@ -0,0 +1,59 @@ +package com.flickmatch.platform.dynamodb.model; + +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute; +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey; +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable; +import lombok.AllArgsConstructor; +import lombok.Builder; + +import java.util.List; + +@DynamoDBTable(tableName="PaymentRequest") +@Builder +@AllArgsConstructor +public class PaymentRequest { + + private String merchantTransactionId; + private String uniqueEventId; + private List playerDetailsList; + /* + status values can be INITIATED, PAID, FAILED + */ + private String status; + + @DynamoDBHashKey(attributeName="merchantTransactionId") + public String getMerchantTransactionId() { + return merchantTransactionId; + } + + public void setMerchantTransactionId(String merchantTransactionId) { + this.merchantTransactionId = merchantTransactionId; + } + + @DynamoDBAttribute(attributeName="uniqueEventId") + public String getUniqueEventId() { + return uniqueEventId; + } + + public void setUniqueEventId(String uniqueEventId) { + this.uniqueEventId = uniqueEventId; + } + + @DynamoDBAttribute(attributeName="playerDetailsList") + public List getPlayerDetailsList() { + return playerDetailsList; + } + + public void setPlayerDetailsList(List playerDetailsList) { + this.playerDetailsList = playerDetailsList; + } + + @DynamoDBAttribute(attributeName="status") + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } +} diff --git a/platform/src/main/java/com/flickmatch/platform/dynamodb/repository/CityRepository.java b/platform/src/main/java/com/flickmatch/platform/dynamodb/repository/CityRepository.java index 8f6a362c..e4da4a91 100644 --- a/platform/src/main/java/com/flickmatch/platform/dynamodb/repository/CityRepository.java +++ b/platform/src/main/java/com/flickmatch/platform/dynamodb/repository/CityRepository.java @@ -3,7 +3,6 @@ import com.flickmatch.platform.dynamodb.model.City; import org.socialsignin.spring.data.dynamodb.repository.EnableScan; import org.springframework.data.repository.CrudRepository; -import org.springframework.stereotype.Repository; import java.util.List; import java.util.Optional; diff --git a/platform/src/main/java/com/flickmatch/platform/dynamodb/repository/PaymentRequestRepository.java b/platform/src/main/java/com/flickmatch/platform/dynamodb/repository/PaymentRequestRepository.java new file mode 100644 index 00000000..47354581 --- /dev/null +++ b/platform/src/main/java/com/flickmatch/platform/dynamodb/repository/PaymentRequestRepository.java @@ -0,0 +1,10 @@ +package com.flickmatch.platform.dynamodb.repository; + +import com.flickmatch.platform.dynamodb.model.PaymentRequest; +import org.socialsignin.spring.data.dynamodb.repository.EnableScan; +import org.springframework.data.repository.CrudRepository; + +@EnableScan +public interface PaymentRequestRepository extends CrudRepository { + +} diff --git a/platform/src/main/java/com/flickmatch/platform/graphql/builder/EventBuilder.java b/platform/src/main/java/com/flickmatch/platform/graphql/builder/EventBuilder.java index 5e0c74a7..c4237405 100644 --- a/platform/src/main/java/com/flickmatch/platform/graphql/builder/EventBuilder.java +++ b/platform/src/main/java/com/flickmatch/platform/graphql/builder/EventBuilder.java @@ -13,6 +13,7 @@ import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; +import java.math.BigDecimal; import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.temporal.ChronoUnit; @@ -152,6 +153,48 @@ public List getPastEvents(String cit return pastEventList; } + /** + * Gets amount for event. + * + * @param uniqueEventId the unique event id + * @return the amount for event in paise + */ + public long getAmountForEvent(final String uniqueEventId) { + int index = 0; + String date = null; + String cityId = null; + if (StringUtils.hasText(uniqueEventId)) { + String[] parts = uniqueEventId.split("-"); + try{ + cityId = parts[0]; + date = parts[1] + "-" + parts[2] + "-" + parts[3]; + index = Integer.parseInt(parts[4]); + } catch (NumberFormatException e) { + log.error(uniqueEventId); + throw new IllegalArgumentException("Input is invalid"); + } + } else { + log.error(uniqueEventId); + throw new IllegalArgumentException("Input is invalid"); + } + Optional eventsInCity = + eventRepository.findById(new Event.EventId(cityId, date)); + if (eventsInCity.isPresent()) { + final int finalIndex = index; + Optional selectedEvent = eventsInCity.get().getEventDetailsList() + .stream().filter(eventDetails -> eventDetails.getIndex().equals(finalIndex)).findFirst(); + if (selectedEvent.isPresent()) { + BigDecimal amount = BigDecimal.valueOf(selectedEvent.get().getCharges()); + amount = amount.multiply(BigDecimal.valueOf(100)); + return amount.longValue(); + } else { + throw new IllegalArgumentException("Invalid Event selected"); + } + } else { + throw new IllegalArgumentException("Invalid Event selected"); + } + } + private Event.EventDetails buildEventDetails(CreateEventInput input, int index) throws ParseException { List sportsVenueList = sportsVenueBuilder.getSportsVenues(input.getCityId()); String currency = getCurrencyForCity(input.getCityId()); diff --git a/platform/src/main/java/com/flickmatch/platform/graphql/builder/PaymentRequestBuilder.java b/platform/src/main/java/com/flickmatch/platform/graphql/builder/PaymentRequestBuilder.java new file mode 100644 index 00000000..f98644f7 --- /dev/null +++ b/platform/src/main/java/com/flickmatch/platform/graphql/builder/PaymentRequestBuilder.java @@ -0,0 +1,36 @@ +package com.flickmatch.platform.graphql.builder; + +import com.flickmatch.platform.dynamodb.model.Event; +import com.flickmatch.platform.dynamodb.model.PaymentRequest; +import com.flickmatch.platform.dynamodb.repository.PaymentRequestRepository; +import com.flickmatch.platform.graphql.input.PlayerInput; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class PaymentRequestBuilder { + + @Autowired + private PaymentRequestRepository paymentRequestRepository; + + public PaymentRequest createPaymentRequest(final String merchantTransactionId, + final String uniqueEventId, + final List playerInputList) { + List playerDetailsList = playerInputList.stream() + .map(playerInput -> Event.PlayerDetails.builder() + .name(playerInput.getName()) + .waNumber(playerInput.getWaNumber()) + .build()) + .collect(Collectors.toList()); + PaymentRequest paymentRequest = PaymentRequest.builder() + .merchantTransactionId(merchantTransactionId) + .uniqueEventId(uniqueEventId) + .playerDetailsList(playerDetailsList) + .status("INITIATED") + .build(); + return paymentRequestRepository.save(paymentRequest); + } +} diff --git a/platform/src/main/java/com/flickmatch/platform/graphql/controller/PaymentController.java b/platform/src/main/java/com/flickmatch/platform/graphql/controller/PaymentController.java index 1e125576..1a5d5355 100644 --- a/platform/src/main/java/com/flickmatch/platform/graphql/controller/PaymentController.java +++ b/platform/src/main/java/com/flickmatch/platform/graphql/controller/PaymentController.java @@ -1,5 +1,7 @@ package com.flickmatch.platform.graphql.controller; +import com.flickmatch.platform.graphql.builder.EventBuilder; +import com.flickmatch.platform.graphql.builder.PaymentRequestBuilder; import com.flickmatch.platform.graphql.input.InitiatePaymentInput; import com.flickmatch.platform.graphql.type.InitiatePaymentOutput; import com.flickmatch.platform.proxy.PhonePeProxy; @@ -9,23 +11,37 @@ import org.springframework.graphql.data.method.annotation.MutationMapping; import org.springframework.stereotype.Controller; +import java.util.UUID; + @Controller @Log4j2 public class PaymentController { @Autowired PhonePeProxy phonePeProxy; + @Autowired + PaymentRequestBuilder paymentRequestBuilder; + @Autowired + EventBuilder eventBuilder; @MutationMapping public InitiatePaymentOutput initiatePayment(@Argument InitiatePaymentInput input) { - String paymentLink = "https://example.com/payment/link"; try { - paymentLink = phonePeProxy.initiatePayment(); + String merchantTransactionId = UUID.randomUUID().toString().substring(0,34); + long eventAmount = eventBuilder.getAmountForEvent(input.getUniqueEventId()); + long amount = eventAmount * input.getPlayerInputList().size(); + String paymentLink = phonePeProxy.initiatePayment(merchantTransactionId, amount); + paymentRequestBuilder.createPaymentRequest(merchantTransactionId, + input.getUniqueEventId(), input.getPlayerInputList()); + return InitiatePaymentOutput.builder() + .paymentLink(paymentLink) + .isInitiated(true) + .build(); } catch (Exception exception) { - exception.printStackTrace(); + log.error("Couldn't initiate payment", exception); + return InitiatePaymentOutput.builder() + .isInitiated(false) + .build(); } - return InitiatePaymentOutput.builder() - .paymentLink(paymentLink) - .build(); } } diff --git a/platform/src/main/java/com/flickmatch/platform/graphql/input/InitiatePaymentInput.java b/platform/src/main/java/com/flickmatch/platform/graphql/input/InitiatePaymentInput.java index d7de7892..19d2d4ac 100644 --- a/platform/src/main/java/com/flickmatch/platform/graphql/input/InitiatePaymentInput.java +++ b/platform/src/main/java/com/flickmatch/platform/graphql/input/InitiatePaymentInput.java @@ -3,9 +3,11 @@ import lombok.Builder; import lombok.Getter; +import java.util.List; + @Builder @Getter public class InitiatePaymentInput { String uniqueEventId; - PlayerInput player; + List playerInputList; } diff --git a/platform/src/main/java/com/flickmatch/platform/graphql/type/InitiatePaymentOutput.java b/platform/src/main/java/com/flickmatch/platform/graphql/type/InitiatePaymentOutput.java index 5f99bf4c..2fc99457 100644 --- a/platform/src/main/java/com/flickmatch/platform/graphql/type/InitiatePaymentOutput.java +++ b/platform/src/main/java/com/flickmatch/platform/graphql/type/InitiatePaymentOutput.java @@ -9,7 +9,5 @@ @Getter public class InitiatePaymentOutput { private String paymentLink; - public InitiatePaymentOutput(String paymentLink) { - this.paymentLink = paymentLink; - } + private boolean isInitiated; } diff --git a/platform/src/main/java/com/flickmatch/platform/proxy/PhonePeProxy.java b/platform/src/main/java/com/flickmatch/platform/proxy/PhonePeProxy.java index e0f3a07b..1920d800 100644 --- a/platform/src/main/java/com/flickmatch/platform/proxy/PhonePeProxy.java +++ b/platform/src/main/java/com/flickmatch/platform/proxy/PhonePeProxy.java @@ -9,8 +9,6 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; -import java.util.UUID; - @Service public class PhonePeProxy { @@ -27,9 +25,7 @@ public class PhonePeProxy { * * @return payment link */ - public String initiatePayment() { - String merchantTransactionId = UUID.randomUUID().toString().substring(0,34); - long amount = 200; + public String initiatePayment(final String merchantTransactionId, final long amount) { String callbackUrl = "https://service.flickmatch.in:8443/platform-0.0.1-SNAPSHOT/payment"; String merchantUserId = "merchantUserId"; diff --git a/platform/src/main/resources/graphql/schema.graphqls b/platform/src/main/resources/graphql/schema.graphqls index 22caed9a..22bc26af 100644 --- a/platform/src/main/resources/graphql/schema.graphqls +++ b/platform/src/main/resources/graphql/schema.graphqls @@ -54,11 +54,12 @@ input JoinEventInput { input InitiatePaymentInput { uniqueEventId: ID! - player: PlayerInput! + playerInputList: [PlayerInput!]! } type InitiatePaymentOutput { - paymentLink: String! + paymentLink: String + isInitiated: Boolean! } input CreateSportsVenueInput { @@ -103,7 +104,6 @@ input RegisterModeratorInput { input PlayerInput { waNumber: String name: String! - paymentStatus: PaymentStatus } type MutationResult {