Backend Low Level Design 4
About Lesson
Create a package named `controllers` and within it, create a `PaymentController` class. In this class, write a method `createPaymentService` that
  • Returns: a String
  • Accepts: @RequestParam String orderId
  • Uses: @Autowired to inject PaymentService
  • Calls: the createLink method from PaymentService with the orderId
  • Returns: the result
@RestController
public class PaymentController {
   PaymentService paymentService;
 
@Autowired
PaymentController(PaymentService paymentService){
    this.paymentService = paymentService;
}
 
  @PostMapping(“payment/createLink”)
  public String createPaymentLink(@RequestParam String orderId){
        return paymentService.createLink(orderId);
  }
}

Next, create a package named services and within it, create a method createLink that:

  • Returns a String
  • Accepts a String orderId

Next, create a services package and within it, create a method createLink that:

  • Returns a String
  • Accepts a String orderId

Inside this method:

  1. First, get the order details by calling the relevant service.
  2. Send these details to the payment gateway.
Since we are using Razorpay, it is better to create an instance of it and use it directly here. However, for scalability and future implementation of more payment gateways, it is a good idea to create an interface that implements the payment gateway. Create an instance of the `PaymentGateway` interface in the `services` package and use `@Autowired` to inject it.

@Service
public class PaymentService {
private PaymentGateway paymentGateway;
@Autowired
public PaymentService(PaymentGateway paymentGateway) {
this.paymentGateway = paymentGateway;
}


public String createLink(String orderId){
/*
Make a call to order service and get the order details.
OrderDetail order = restTemplate.getMapping(orderId)
name = order.getCustomerName()
amount = order.getAmount()
phone = order.getCustomerPhone()
*/
return null;
}
}

Next, create the PaymentGateway interface in the services package with an abstract method createPaymentLink that:

  • Accepts String orderId, String customerName, String phone, and int amount
  • Returns a String
  • Add Annotation @Component which will tell Spring Boot to create a bean

@Component
public interface PaymentGateway {
String createPaymentLink( String orderId, String customerName, String phone, int amount);
}

Next, in the `PaymentService` class, call the `createPaymentLink` method from the `PaymentGateway` interface. In the `createLink` method, pass the required details obtained from the order service (which is not implemented in this project) and return the result.

@Service
public class PaymentService {

private final PaymentGateway paymentGateway;
private final PaymentRepository paymentRepository;

@Autowired
public PaymentService(PaymentGateway paymentGateway, PaymentRepository paymentRepository) {
this.paymentGateway = paymentGateway;
this.paymentRepository = paymentRepository;
}

public String createLink(String orderId){
/*
Make a call to order service and get the order details.
OrderDetail order = restTemplate.getMapping(orderId)
name = order.getCustomerName()
amount = order.getAmount()
phone = order.getCustomerPhone()
*/
PaymentLinkRequestDto paymentLinkRequestDto = new PaymentLinkRequestDto();
paymentLinkRequestDto.setCustomerName(“Sanjay”);
paymentLinkRequestDto.setOrderId(orderId);
paymentLinkRequestDto.setPhone(“8310206130”);
paymentLinkRequestDto.setAmount(100);

// Generate payment link using the payment gateway
String paymentLink = paymentGateway.createPaymentLink(paymentLinkRequestDto);

// Save payment details in the repository
PaymentDetails paymentResponse = new PaymentDetails();
paymentResponse.setPaymentLink(paymentLink);
paymentResponse.setOrderId(orderId);
paymentRepository.save(paymentResponse);

return paymentLink;
}
}

Next create a “dtos” package and “PaymentLinkRequestDto” class

@Getter
@Setter
public class PaymentLinkRequestDto {
private String orderId;
private String customerName;
private String phone;
private int amount;
}

Next Create PaymentDetails Class:

  • In the models package, create a new class named PaymentDetails.
  • Make PaymentDetails extend BaseModel.
  • Add the @Enumerated(EnumType.STRING) annotation to the status field since it is an enum type.

@Getter
@Setter
@Entity
public class PaymentDetails extends BaseModel{
private String orderId;
private String paymentId;
private String PaymentLink;
@Enumerated(EnumType.STRING)
private PaymentStatus status;
}

Create PaymentRepository Interface:

  • In the repositories package, create a new interface named PaymentRepository.
  • Extend JpaRepository<PaymentDetails, Long>, specifying PaymentDetails as the entity type and Long as the primary key type.
  • Add a custom method findByOrderId to the repository interface, since this method is not available by default.

@Repository
public interface PaymentRepository extends JpaRepository<PaymentDetails,Long> {
Optional<PaymentDetails> findByOrderId(String orderId);
}

Next, create a class `RazorPayGateway` that implements the `PaymentGateway` interface and implement the `createPaymentLink` method.

public class RazorPayGateway implements PaymentGateway{
@Override
public String createPaymentLink(PaymentLinkRequestDto paymentLinkRequestDto) {
/*
There are generally two ways to integrate with a 3rd party
1. Make an api call
2. Client sdk (Code in a jar)
*/
return “”;
}
}

© GeekySanjay