Skip to content

Commit 2237664

Browse files
authored
Merge pull request #42 from adityacosmos24/payment_gateway_system
feat: added payment gateway system
2 parents 236c33a + 9d097a4 commit 2237664

File tree

3 files changed

+330
-0
lines changed

3 files changed

+330
-0
lines changed
Lines changed: 313 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,313 @@
1+
#include <iostream>
2+
#include <string>
3+
#include <cstdlib>
4+
#include <ctime>
5+
6+
7+
using namespace std;
8+
9+
// ----------------------------
10+
// Data structure for payment details
11+
// ----------------------------
12+
struct PaymentRequest {
13+
string sender;
14+
string reciever;
15+
double amount;
16+
string currency;
17+
18+
PaymentRequest(const string& sender, const string& reciever, double amt, const string& curr) {
19+
this->sender = sender;
20+
this->reciever = reciever;
21+
this->amount = amt;
22+
this->currency = curr;
23+
}
24+
};
25+
26+
// ----------------------------
27+
// Banking System interface and implementations (Strategy for actual payment logic)
28+
// ----------------------------
29+
class BankingSystem {
30+
public:
31+
virtual bool processPayment(double amount) = 0;
32+
virtual ~BankingSystem() {}
33+
};
34+
35+
class PaytmBankingSystem : public BankingSystem {
36+
public:
37+
PaytmBankingSystem() {}
38+
bool processPayment(double amount) override {
39+
// Simulate 20% success
40+
int r = rand() % 100;
41+
return r < 80;
42+
}
43+
};
44+
45+
class RazorpayBankingSystem : public BankingSystem {
46+
public:
47+
RazorpayBankingSystem() {}
48+
bool processPayment(double amount) override {
49+
cout << "[BankingSystem-Razorpay] Processing payment of " << amount << "...\n";
50+
// Simulate 90% success
51+
int r = rand() % 100;
52+
return r < 90;
53+
}
54+
};
55+
56+
// ----------------------------
57+
// Abstract base class for Payment Gateway (Template Method Pattern)
58+
// ----------------------------
59+
class PaymentGateway {
60+
protected:
61+
BankingSystem* bankingSystem;
62+
public:
63+
PaymentGateway() {
64+
bankingSystem = nullptr;
65+
}
66+
virtual ~PaymentGateway() {
67+
delete bankingSystem;
68+
}
69+
70+
// Template method defining the standard payment flow
71+
virtual bool processPayment(PaymentRequest* request) {
72+
if (!validatePayment(request)) {
73+
cout << "[PaymentGateway] Validation failed for " << request->sender << ".\n";
74+
return false;
75+
}
76+
if (!initiatePayment(request)) {
77+
cout << "[PaymentGateway] Initiation failed for " << request->sender << ".\n";
78+
return false;
79+
}
80+
if (!confirmPayment(request)) {
81+
cout << "[PaymentGateway] Confirmation failed for " << request->sender << ".\n";
82+
return false;
83+
}
84+
return true;
85+
}
86+
87+
// Steps to be implemented by concrete gateways
88+
virtual bool validatePayment(PaymentRequest* request) = 0;
89+
virtual bool initiatePayment(PaymentRequest* request) = 0;
90+
virtual bool confirmPayment(PaymentRequest* request) = 0;
91+
};
92+
93+
// ----------------------------
94+
// Concrete Payment Gateway for Paytm
95+
// ----------------------------
96+
class PaytmGateway : public PaymentGateway {
97+
public:
98+
PaytmGateway() {
99+
bankingSystem = new PaytmBankingSystem();
100+
}
101+
bool validatePayment(PaymentRequest* request) override {
102+
cout << "[Paytm] Validating payment for " << request->sender << ".\n";
103+
104+
if (request->amount <= 0 || request->currency != "INR") {
105+
return false;
106+
}
107+
return true;
108+
}
109+
bool initiatePayment(PaymentRequest* request) override {
110+
cout << "[Paytm] Initiating payment of " << request->amount
111+
<< " " << request->currency << " for " << request->sender << ".\n";
112+
113+
return bankingSystem->processPayment(request->amount);
114+
}
115+
bool confirmPayment(PaymentRequest* request) override {
116+
cout << "[Paytm] Confirming payment for " << request->sender << ".\n";
117+
118+
// Confirmation always succeeds in this simulation
119+
return true;
120+
}
121+
};
122+
123+
// ----------------------------
124+
// Concrete Payment Gateway for Razorpay
125+
// ----------------------------
126+
class RazorpayGateway : public PaymentGateway {
127+
public:
128+
RazorpayGateway() {
129+
bankingSystem = new RazorpayBankingSystem();
130+
}
131+
bool validatePayment(PaymentRequest* request) override {
132+
cout << "[Razorpay] Validating payment for " << request->sender << ".\n";
133+
134+
if (request->amount <= 0) {
135+
return false;
136+
}
137+
return true;
138+
}
139+
bool initiatePayment(PaymentRequest* request) override {
140+
cout << "[Razorpay] Initiating payment of " << request->amount
141+
<< " " << request->currency << " for " << request->sender << ".\n";
142+
143+
return bankingSystem->processPayment(request->amount);
144+
145+
}
146+
bool confirmPayment(PaymentRequest* request) override {
147+
cout << "[Razorpay] Confirming payment for " << request->sender << ".\n";
148+
149+
// Confirmation always succeeds in this simulation
150+
return true;
151+
}
152+
};
153+
154+
// ----------------------------
155+
// Proxy class that wraps a PaymentGateway to add retries (Proxy Pattern)
156+
// ----------------------------
157+
class PaymentGatewayProxy : public PaymentGateway {
158+
PaymentGateway* realGateway;
159+
int retries;
160+
public:
161+
PaymentGatewayProxy(PaymentGateway* gateway, int maxRetries) {
162+
realGateway = gateway;
163+
retries = maxRetries;
164+
}
165+
~PaymentGatewayProxy() {
166+
delete realGateway;
167+
}
168+
bool processPayment(PaymentRequest* request) override {
169+
bool result = false;
170+
for (int attempt = 0; attempt < retries; ++attempt) {
171+
if (attempt > 0) {
172+
cout << "[Proxy] Retrying payment (attempt " << (attempt+1)
173+
<< ") for " << request->sender << ".\n";
174+
}
175+
result = realGateway->processPayment(request);
176+
if (result) break;
177+
}
178+
if (!result) {
179+
cout << "[Proxy] Payment failed after " << (retries)
180+
<< " attempts for " << request->sender << ".\n";
181+
}
182+
return result;
183+
}
184+
bool validatePayment(PaymentRequest* request) override {
185+
return realGateway->validatePayment(request);
186+
}
187+
bool initiatePayment(PaymentRequest* request) override {
188+
return realGateway->initiatePayment(request);
189+
}
190+
bool confirmPayment(PaymentRequest* request) override {
191+
return realGateway->confirmPayment(request);
192+
}
193+
};
194+
195+
// ----------------------------
196+
// Gateway Factory for creating gateway (Singleton)
197+
// ----------------------------
198+
enum class GatewayType {
199+
PAYTM,
200+
RAZORPAY
201+
};
202+
203+
class GatewayFactory {
204+
private:
205+
static GatewayFactory instance;
206+
// Private constructor and delete copy/assignment to ensure no one can clone or reassign your singleton.
207+
GatewayFactory() {}
208+
GatewayFactory(const GatewayFactory&) = delete;
209+
GatewayFactory& operator=(const GatewayFactory&) = delete;
210+
211+
public:
212+
static GatewayFactory& getInstance() {
213+
return instance;
214+
}
215+
PaymentGateway* getGateway(GatewayType type) {
216+
if (type == GatewayType::PAYTM) {
217+
PaymentGateway* paymentGateway = new PaytmGateway();
218+
return new PaymentGatewayProxy(paymentGateway, 3);
219+
} else {
220+
PaymentGateway* paymentGateway = new RazorpayGateway();
221+
return new PaymentGatewayProxy(paymentGateway, 1);
222+
}
223+
}
224+
};
225+
226+
// define static instance
227+
GatewayFactory GatewayFactory::instance;
228+
229+
// ----------------------------
230+
// Unified API service (Singleton)
231+
// ----------------------------
232+
class PaymentService {
233+
private:
234+
static PaymentService instance;
235+
PaymentGateway* gateway;
236+
237+
PaymentService() {
238+
gateway = nullptr;
239+
}
240+
~PaymentService() {
241+
delete gateway;
242+
}
243+
244+
// Private constructor and delete copy/assignment to ensure no one can clone or reassign your singleton.
245+
PaymentService(const PaymentService&) = delete;
246+
PaymentService& operator=(const PaymentService&) = delete;
247+
248+
public:
249+
static PaymentService& getInstance() {
250+
return instance;
251+
}
252+
void setGateway(PaymentGateway* g) {
253+
if (gateway) delete gateway;
254+
gateway = g;
255+
}
256+
bool processPayment(PaymentRequest* request) {
257+
if (!gateway) {
258+
cout << "[PaymentService] No payment gateway selected.\n";
259+
return false;
260+
}
261+
return gateway->processPayment(request);
262+
}
263+
};
264+
265+
PaymentService PaymentService::instance;
266+
267+
// ----------------------------
268+
// Controller class for all client requests (Singleton)
269+
// ----------------------------
270+
class PaymentController {
271+
private:
272+
static PaymentController instance;
273+
PaymentController() {}
274+
PaymentController(const PaymentController&) = delete;
275+
PaymentController& operator=(const PaymentController&) = delete;
276+
public:
277+
static PaymentController& getInstance() {
278+
return instance;
279+
}
280+
bool handlePayment(GatewayType type, PaymentRequest* req) {
281+
PaymentGateway* paymentGateway = GatewayFactory::getInstance().getGateway(type);
282+
PaymentService::getInstance().setGateway(paymentGateway);
283+
return PaymentService::getInstance().processPayment(req);
284+
}
285+
};
286+
287+
PaymentController PaymentController::instance;
288+
289+
// ----------------------------
290+
// Main: Client code now goes through controller
291+
// ----------------------------
292+
int main() {
293+
294+
srand(static_cast<unsigned>(time(nullptr)));
295+
296+
PaymentRequest* req1 = new PaymentRequest("Aditya", "Shubham", 1000.0, "INR");
297+
298+
cout << "Processing via Paytm\n";
299+
cout << "------------------------------\n";
300+
bool res1 = PaymentController::getInstance().handlePayment(GatewayType::PAYTM, req1);
301+
cout << "Result: " << (res1 ? "SUCCESS" : "FAIL") << "\n";
302+
cout << "------------------------------\n\n";
303+
304+
PaymentRequest* req2 = new PaymentRequest("Shubham", "Aditya", 500.0, "USD");
305+
306+
cout << "Processing via Razorpay\n";
307+
cout << "------------------------------\n";
308+
bool res2 = PaymentController::getInstance().handlePayment(GatewayType::RAZORPAY, req2);
309+
cout << "Result: " << (res2 ? "SUCCESS" : "FAIL") << "\n";
310+
cout << "------------------------------\n";
311+
312+
return 0;
313+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
@echo off
2+
echo C++ Payment Gateway Application...
3+
4+
REM Compile the main program
5+
g++ -std=c++11 -o payment_gateway PaymentGatewayApplication.cpp
6+
7+
if %errorlevel% equ 0 (
8+
echo Compilation successful!
9+
echo Running the Payment Gateway application...
10+
echo.
11+
payment_gateway.exe
12+
) else (
13+
echo Compilation failed!
14+
echo Please check for any syntax errors.
15+
)
16+
17+
pause
70.9 KB
Binary file not shown.

0 commit comments

Comments
 (0)