Accept Payments with Paystack in Spring Boot
To accept Paystack payments in Spring Boot, create a PaystackService that uses RestTemplate to call the Paystack API. Build a controller with endpoints for initialization and verification. Store your secret key in application.properties and inject it with @Value.
Setup
Add your key to application.properties:
paystack.secret-key=sk_test_xxxxxxxxxxxxxxxxxxxxx
PaystackService
// src/main/java/com/example/payment/PaystackService.java
@Service
public class PaystackService {
@Value("${paystack.secret-key}")
private String secretKey;
private final RestTemplate restTemplate = new RestTemplate();
public Map<String, Object> initializeTransaction(String email, int amountKobo, String reference, String callbackUrl) {
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer " + secretKey);
headers.setContentType(MediaType.APPLICATION_JSON);
Map<String, Object> body = Map.of(
"email", email,
"amount", amountKobo,
"reference", reference,
"callback_url", callbackUrl
);
HttpEntity<Map<String, Object>> request = new HttpEntity<>(body, headers);
ResponseEntity<Map> response = restTemplate.postForEntity(
"https://api.paystack.co/transaction/initialize", request, Map.class);
return response.getBody();
}
public Map<String, Object> verifyTransaction(String reference) {
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer " + secretKey);
HttpEntity<?> request = new HttpEntity<>(headers);
ResponseEntity<Map> response = restTemplate.exchange(
"https://api.paystack.co/transaction/verify/" + reference,
HttpMethod.GET, request, Map.class);
return response.getBody();
}
}
Payment Controller
@RestController
@RequestMapping("/api/payment")
public class PaymentController {
@Autowired
private PaystackService paystackService;
@PostMapping("/initialize")
public ResponseEntity<?> initialize(@RequestBody Map<String, Object> payload) {
String email = (String) payload.get("email");
double amount = ((Number) payload.get("amount")).doubleValue();
String reference = "order_" + UUID.randomUUID().toString().substring(0, 12);
Map<String, Object> result = paystackService.initializeTransaction(
email, (int)(amount * 100), reference, "http://localhost:8080/api/payment/callback");
if (Boolean.TRUE.equals(result.get("status"))) {
Map<String, Object> data = (Map<String, Object>) result.get("data");
return ResponseEntity.ok(Map.of(
"authorization_url", data.get("authorization_url"),
"reference", data.get("reference")
));
}
return ResponseEntity.badRequest().body(Map.of("error", result.get("message")));
}
@GetMapping("/callback")
public ResponseEntity<?> callback(@RequestParam String reference) {
Map<String, Object> result = paystackService.verifyTransaction(reference);
if (Boolean.TRUE.equals(result.get("status"))) {
Map<String, Object> data = (Map<String, Object>) result.get("data");
if ("success".equals(data.get("status"))) {
// TODO: Verify amount, mark order as paid
return ResponseEntity.ok(Map.of("success", true));
}
}
return ResponseEntity.badRequest().body(Map.of("success", false));
}
}
Production Checklist
- Use profiles. Spring profiles for dev/prod keys: application-dev.properties vs application-prod.properties.
- Set up webhooks. See Handle Paystack Webhooks in Spring Boot.
- HTTPS. Required for callbacks and webhooks.
- Validate amounts. Check against your JPA entity, not request params.
Key Takeaways
- ✓Spring Boot RestTemplate or WebClient handles all Paystack REST API calls.
- ✓Store your Paystack secret key in application.properties. Inject with @Value.
- ✓Use @Service for the PaystackService and @RestController for endpoints.
- ✓Amounts are in kobo (NGN), pesewas (GHS), or cents. Multiply by 100.
- ✓Always verify transactions server-side after the redirect callback.
- ✓Spring Boot dependency injection makes PaystackService easily testable.
Frequently Asked Questions
- Should I use RestTemplate or WebClient?
- RestTemplate is simpler and works for synchronous calls. WebClient is non-blocking and preferred for reactive applications. Both work with Paystack.
- Do I need a Paystack Java library?
- No. RestTemplate handles all REST API calls. The Paystack API is a standard REST API that works with any HTTP client.
- How do I handle CSRF for webhooks?
- If using Spring Security, disable CSRF for the webhook endpoint. Add a security configuration that permits the webhook URL without CSRF.
Ready to build real-world apps?
Join the McTaba Labs full-stack marathon (4 months full-time · 6 months part-time). Learn M-Pesa, USSD, and WhatsApp engineering while shipping 8 production apps.
Apply to the McTaba Marathon