quickpos 1.0.901 → 1.0.903
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/example-bufpay.js +68 -0
- package/example.js +3 -3
- package/lib/bufpay.js +216 -0
- package/package.json +1 -1
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
const express = require('express');
|
|
2
|
+
const bodyParser = require('body-parser');
|
|
3
|
+
const QuickPos = require('./app');
|
|
4
|
+
|
|
5
|
+
const app = express();
|
|
6
|
+
app.use(bodyParser.urlencoded({ extended: true }));
|
|
7
|
+
// app.use(require('multer')().none());
|
|
8
|
+
|
|
9
|
+
const quickPos = new QuickPos({
|
|
10
|
+
providers: {
|
|
11
|
+
bufpay: {
|
|
12
|
+
appId: 'xxxx',
|
|
13
|
+
appSecret: 'xxx'
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
app.use(quickPos.middleware());
|
|
19
|
+
|
|
20
|
+
quickPos.providers['bufpay'].createPayment({
|
|
21
|
+
name: 'Product Name',
|
|
22
|
+
payType: 'alipay',
|
|
23
|
+
price: '100.00',
|
|
24
|
+
orderId: 'ORDER123',
|
|
25
|
+
orderUid: 'user@example.com',
|
|
26
|
+
notifyUrl: 'https://your-domain.com/webhook'
|
|
27
|
+
})
|
|
28
|
+
.then(response => console.log(response))
|
|
29
|
+
.catch(error => console.error(error));
|
|
30
|
+
|
|
31
|
+
app.post('/shopierWebhook', quickPos.handleCallback('shopier'), (req, res) => {
|
|
32
|
+
try {
|
|
33
|
+
console.log('Payment result:', req.paymentResult.data.chartDetails);
|
|
34
|
+
/*
|
|
35
|
+
Payment result: {
|
|
36
|
+
status: 'success',
|
|
37
|
+
data: {
|
|
38
|
+
email: 'fastuptime@gmail.com',
|
|
39
|
+
orderId: '313758163',
|
|
40
|
+
currency: 0,
|
|
41
|
+
price: '1',
|
|
42
|
+
buyerName: 'Can',
|
|
43
|
+
buyerSurname: 'Kaya',
|
|
44
|
+
productId: 31857020,
|
|
45
|
+
productCount: 1,
|
|
46
|
+
customerNote: '',
|
|
47
|
+
productList: '31857020',
|
|
48
|
+
chartDetails: [ [Object] ],
|
|
49
|
+
isTest: 1
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
*/
|
|
53
|
+
if (!(req.body.res && req.body.hash)) {
|
|
54
|
+
return res.status(400).send('missing parameter');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// İşlem başarılı
|
|
58
|
+
res.send('success');
|
|
59
|
+
} catch (error) {
|
|
60
|
+
console.error('Webhook error:', error);
|
|
61
|
+
res.status(500).send('error');
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const PORT = 80;
|
|
66
|
+
app.listen(PORT, () => {
|
|
67
|
+
console.log(`Webhook server running on port ${PORT}`);
|
|
68
|
+
});
|
package/example.js
CHANGED
|
@@ -9,9 +9,9 @@ app.use(bodyParser.json());
|
|
|
9
9
|
const quickPos = new QuickPos({
|
|
10
10
|
providers: {
|
|
11
11
|
paytr: {
|
|
12
|
-
merchantId: '
|
|
13
|
-
merchantKey: '
|
|
14
|
-
merchantSalt: '
|
|
12
|
+
merchantId: 'xx',
|
|
13
|
+
merchantKey: 'xx',
|
|
14
|
+
merchantSalt: 'xxx',
|
|
15
15
|
mode: 'test',
|
|
16
16
|
}
|
|
17
17
|
},
|
package/lib/bufpay.js
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
const crypto = require('crypto');
|
|
2
|
+
const axios = require('axios');
|
|
3
|
+
|
|
4
|
+
class BufPay {
|
|
5
|
+
constructor(config) {
|
|
6
|
+
this.config = config || {};
|
|
7
|
+
const requiredFields = ['appId', 'appSecret'];
|
|
8
|
+
for (let field of requiredFields) {
|
|
9
|
+
if (!config[field]) throw new Error(`Missing required field: ${field}`);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
this.appId = config.appId;
|
|
13
|
+
this.appSecret = config.appSecret;
|
|
14
|
+
this.baseUrl = 'https://bufpay.com/api';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async createPayment(paymentDetails) {
|
|
18
|
+
try {
|
|
19
|
+
// console.log('Creating payment with details:', JSON.stringify(paymentDetails, null, 2));
|
|
20
|
+
|
|
21
|
+
let requiredData = ['name', 'payType', 'price', 'orderId', 'orderUid', 'notifyUrl'];
|
|
22
|
+
for (let data of requiredData) {
|
|
23
|
+
if (!paymentDetails[data]) throw new Error(`Missing required data: ${data}`);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const signature = this.generateToken(
|
|
27
|
+
paymentDetails.name,
|
|
28
|
+
paymentDetails.payType,
|
|
29
|
+
paymentDetails.price,
|
|
30
|
+
paymentDetails.orderId,
|
|
31
|
+
paymentDetails.orderUid,
|
|
32
|
+
paymentDetails.notifyUrl,
|
|
33
|
+
paymentDetails.returnUrl || '',
|
|
34
|
+
paymentDetails.feedbackUrl || '',
|
|
35
|
+
this.appSecret
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
// console.log('Generated signature:', signature);
|
|
39
|
+
|
|
40
|
+
const formData = {
|
|
41
|
+
name: paymentDetails.name,
|
|
42
|
+
pay_type: paymentDetails.payType,
|
|
43
|
+
price: paymentDetails.price,
|
|
44
|
+
order_id: paymentDetails.orderId,
|
|
45
|
+
order_uid: paymentDetails.orderUid,
|
|
46
|
+
notify_url: paymentDetails.notifyUrl,
|
|
47
|
+
return_url: paymentDetails.returnUrl || '',
|
|
48
|
+
feedback_url: paymentDetails.feedbackUrl || '',
|
|
49
|
+
sign: signature
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// console.log('Sending request with form data:', JSON.stringify(formData, null, 2));
|
|
53
|
+
|
|
54
|
+
const response = await axios({
|
|
55
|
+
method: 'POST',
|
|
56
|
+
url: `${this.baseUrl}/pay/${this.appId}?format=json`,
|
|
57
|
+
headers: {
|
|
58
|
+
'Content-Type': 'application/x-www-form-urlencoded'
|
|
59
|
+
},
|
|
60
|
+
data: new URLSearchParams(formData).toString()
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// console.log('Received response:', JSON.stringify(response.data, null, 2));
|
|
64
|
+
|
|
65
|
+
if (!response.data) {
|
|
66
|
+
throw new Error('Empty response received from BufPay API');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const responseData = response.data;
|
|
70
|
+
|
|
71
|
+
// Log the full response for debugging
|
|
72
|
+
// console.log('Response status:', responseData.status);
|
|
73
|
+
// console.log('Full response:', JSON.stringify(responseData, null, 2));
|
|
74
|
+
|
|
75
|
+
if (responseData.status === 'success' || responseData.status === 'ok') {
|
|
76
|
+
return {
|
|
77
|
+
status: 'success',
|
|
78
|
+
data: {
|
|
79
|
+
aoid: responseData.aoid,
|
|
80
|
+
pay_type: responseData?.pay_type,
|
|
81
|
+
price: responseData?.price,
|
|
82
|
+
qr_price: responseData?.qr_price,
|
|
83
|
+
qr_img: responseData?.qr_img,
|
|
84
|
+
qr: responseData?.qr,
|
|
85
|
+
cid: responseData?.cid,
|
|
86
|
+
expires_in: responseData?.expires_in,
|
|
87
|
+
return_url: responseData?.return_url,
|
|
88
|
+
feedback_url: responseData?.feedback_url
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
} else {
|
|
92
|
+
return {
|
|
93
|
+
status: 'fail',
|
|
94
|
+
message: responseData?.status
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
} catch (error) {
|
|
98
|
+
// console.error('Error details:', error);
|
|
99
|
+
|
|
100
|
+
if (error.response) {
|
|
101
|
+
// console.error('API Response Error:', {
|
|
102
|
+
// status: error.response.status,
|
|
103
|
+
// data: error.response.data,
|
|
104
|
+
// headers: error.response.headers
|
|
105
|
+
// });
|
|
106
|
+
throw new Error(`BufPay API error: ${JSON.stringify(error.response.data)}`);
|
|
107
|
+
} else if (error.request) {
|
|
108
|
+
// console.error('No Response Error:', error.request);
|
|
109
|
+
throw new Error('No response received from BufPay API');
|
|
110
|
+
} else {
|
|
111
|
+
// console.error('Request Setup Error:', error.message);
|
|
112
|
+
throw new Error(`Error in BufPay payment creation: ${error.message}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
generateToken(...params) {
|
|
118
|
+
try {
|
|
119
|
+
const concatenated = params
|
|
120
|
+
.filter(param => param !== undefined && param !== null)
|
|
121
|
+
.map(param => String(param))
|
|
122
|
+
.join('');
|
|
123
|
+
|
|
124
|
+
// console.log('Generating token with params:', concatenated);
|
|
125
|
+
|
|
126
|
+
const token = crypto
|
|
127
|
+
.createHash('md5')
|
|
128
|
+
.update(concatenated, 'utf8')
|
|
129
|
+
.digest('hex')
|
|
130
|
+
.toUpperCase();
|
|
131
|
+
|
|
132
|
+
// console.log('Generated token:', token);
|
|
133
|
+
return token;
|
|
134
|
+
} catch (error) {
|
|
135
|
+
// console.error('Token generation error:', error);
|
|
136
|
+
throw new Error(`Error generating token: ${error.message}`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
verifyCallback(callbackData) {
|
|
141
|
+
try {
|
|
142
|
+
console.log('Verifying callback data:', JSON.stringify(callbackData, null, 2));
|
|
143
|
+
|
|
144
|
+
const { aoid, order_id, order_uid, price, pay_price, sign } = callbackData;
|
|
145
|
+
|
|
146
|
+
if (!aoid || !order_id || !order_uid || !price || !pay_price || !sign) {
|
|
147
|
+
console.log('Missing required callback fields');
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const expectedSignature = this.generateToken(
|
|
152
|
+
aoid,
|
|
153
|
+
order_id,
|
|
154
|
+
order_uid,
|
|
155
|
+
price,
|
|
156
|
+
pay_price,
|
|
157
|
+
this.appSecret
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
console.log('Expected signature:', expectedSignature);
|
|
161
|
+
console.log('Received signature:', sign);
|
|
162
|
+
|
|
163
|
+
return sign === expectedSignature;
|
|
164
|
+
} catch (error) {
|
|
165
|
+
console.error('Callback verification error:', error);
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
async handleCallback(callbackData) {
|
|
171
|
+
try {
|
|
172
|
+
console.log('Processing callback data:', JSON.stringify(callbackData, null, 2));
|
|
173
|
+
|
|
174
|
+
const isValid = this.verifyCallback(callbackData);
|
|
175
|
+
if (!isValid) {
|
|
176
|
+
throw new Error("BufPay notification failed: invalid signature");
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (callbackData.status === 'success') {
|
|
180
|
+
return {
|
|
181
|
+
status: 'success',
|
|
182
|
+
orderId: callbackData.order_id,
|
|
183
|
+
transactionId: callbackData.aoid,
|
|
184
|
+
amount: parseFloat(callbackData.pay_price),
|
|
185
|
+
originalAmount: parseFloat(callbackData.price),
|
|
186
|
+
orderUid: callbackData.order_uid
|
|
187
|
+
};
|
|
188
|
+
} else {
|
|
189
|
+
throw new Error(`Payment failed: ${JSON.stringify(callbackData)}`);
|
|
190
|
+
}
|
|
191
|
+
} catch (error) {
|
|
192
|
+
console.error('Callback handling error:', error);
|
|
193
|
+
throw new Error(`Error in BufPay callback handling: ${error.message}`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
async queryPayment(aoid) {
|
|
198
|
+
try {
|
|
199
|
+
console.log('Querying payment with AOID:', aoid);
|
|
200
|
+
|
|
201
|
+
if (!aoid) {
|
|
202
|
+
throw new Error('Transaction ID (AOID) is required');
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const response = await axios.get(`${this.baseUrl}/query/${aoid}`);
|
|
206
|
+
console.log('Query response:', JSON.stringify(response.data, null, 2));
|
|
207
|
+
|
|
208
|
+
return response.data;
|
|
209
|
+
} catch (error) {
|
|
210
|
+
console.error('Payment query error:', error);
|
|
211
|
+
throw new Error(`Payment query failed: ${error.message}`);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
module.exports = BufPay;
|