1 | <?php |
||||
2 | |||||
3 | use BPT\BPT; |
||||
4 | use BPT\constants\cryptoCallbackStatus; |
||||
5 | use BPT\constants\dbTypes; |
||||
6 | use BPT\database\mysql; |
||||
7 | use BPT\pay\crypto; |
||||
8 | use BPT\types\cryptoCallback; |
||||
9 | use BPT\types\message; |
||||
10 | use function BPT\strReplace; |
||||
11 | |||||
12 | if (file_exists('vendor/autoload.php')) { |
||||
13 | require 'vendor/autoload.php'; |
||||
14 | } |
||||
15 | else { |
||||
16 | if (!file_exists('BPT.phar')) { |
||||
17 | copy('https://dl.bptlib.ir/BPT.phar', 'BPT.phar'); |
||||
18 | } |
||||
19 | require 'BPT.phar'; |
||||
20 | } |
||||
21 | |||||
22 | class handler extends BPT { |
||||
23 | const ADMIN = 123456789; |
||||
24 | |||||
25 | const MIN_TRANSFER = 0; |
||||
26 | const MAX_TRANSFER = 100000; |
||||
27 | |||||
28 | const MAX_MONEY_DECIMAL = 2; |
||||
29 | const MAX_MONEY_LENGTH = 10; |
||||
30 | |||||
31 | public function __construct (array $settings) { |
||||
32 | parent::__construct($settings); |
||||
33 | } |
||||
34 | |||||
35 | public function cryptoCallback (cryptoCallback $cryptoData) { |
||||
36 | $paid_amount = $cryptoData->paid_amount; |
||||
37 | $user_id = $cryptoData->user_id; |
||||
38 | $real_amount = $cryptoData->real_amount; |
||||
39 | $total_paid = $cryptoData->total_paid; |
||||
40 | if ($cryptoData->status !== cryptoCallbackStatus::FINISHED) { |
||||
41 | $order_id = $cryptoData->order_id; |
||||
42 | mysql::insert('history', ['type', 'amount', 'date', 'user_id', 'order_id'], ['deposit', $paid_amount, time(), $user_id, $order_id]); |
||||
43 | } |
||||
44 | if ($cryptoData->status === cryptoCallbackStatus::PARTIALLY_PAID) { |
||||
45 | $need_to_pay = $real_amount - $total_paid; |
||||
46 | mysql::update('users', ['balance' => '+=' . $paid_amount], ['id' => $user_id], 1); |
||||
47 | return $this->sendMessage(strReplace(['$amount' => $paid_amount, '$real_amount' => $real_amount, '$need_amount' => $need_to_pay], texts::PARTIALLY_PAID), $user_id); |
||||
0 ignored issues
–
show
|
|||||
48 | } |
||||
49 | if ($cryptoData->status === cryptoCallbackStatus::FINISHED) { |
||||
50 | if ($paid_amount != $total_paid) { |
||||
51 | $old_amount = $total_paid - $paid_amount; |
||||
52 | mysql::update('users', ['balance' => '+=' . $paid_amount], ['id' => $user_id], 1); |
||||
53 | return $this->sendMessage(strReplace(['$amount' => $total_paid, '$old_amount' => $old_amount, '$new_amount' => $paid_amount], texts::FINISHED_PARTIALLY), $user_id); |
||||
54 | } |
||||
55 | mysql::update('users', ['balance' => '+=' . $paid_amount], ['id' => $user_id], 1); |
||||
56 | return $this->sendMessage(strReplace(['$amount' => $paid_amount], texts::FINISHED), $user_id); |
||||
57 | } |
||||
58 | if ($cryptoData->status === cryptoCallbackStatus::EXTRA_PAID) { |
||||
59 | if ($paid_amount != $total_paid) { |
||||
60 | $old_amount = $total_paid - $paid_amount; |
||||
61 | mysql::update('users', ['balance' => '+=' . $paid_amount], ['id' => $user_id], 1); |
||||
62 | return $this->sendMessage(strReplace(['$amount' => $total_paid, '$real_amount' => $real_amount, '$old_amount' => $old_amount, '$new_amount' => $paid_amount], texts::EXTRA_PAID_PARTIALLY), $user_id); |
||||
63 | } |
||||
64 | mysql::update('users', ['balance' => '+=' . $paid_amount], ['id' => $user_id], 1); |
||||
65 | return $this->sendMessage(strReplace(['$amount' => $paid_amount, '$real_amount' => $real_amount], texts::EXTRA_PAID), $user_id); |
||||
66 | } |
||||
67 | if ($cryptoData->status === cryptoCallbackStatus::SUCCESS) { |
||||
68 | die('<html> |
||||
0 ignored issues
–
show
|
|||||
69 | <head> |
||||
70 | <link href="https://fonts.googleapis.com/css?family=Nunito+Sans:400,400i,700,900&display=swap" rel="stylesheet"> |
||||
71 | <title>Success</title> |
||||
72 | </head> |
||||
73 | <style> |
||||
74 | body { |
||||
75 | text-align: center; |
||||
76 | padding: 40px 0; |
||||
77 | background: #EBF0F5; |
||||
78 | } |
||||
79 | h1 { |
||||
80 | color: #88B04B; |
||||
81 | font-family: "Nunito Sans", "Helvetica Neue", sans-serif; |
||||
82 | font-weight: 900; |
||||
83 | font-size: 40px; |
||||
84 | margin-bottom: 10px; |
||||
85 | } |
||||
86 | p { |
||||
87 | color: #404F5E; |
||||
88 | font-family: "Nunito Sans", "Helvetica Neue", sans-serif; |
||||
89 | font-size:20px; |
||||
90 | margin: 0; |
||||
91 | } |
||||
92 | i { |
||||
93 | color: #9ABC66; |
||||
94 | font-size: 100px; |
||||
95 | line-height: 200px; |
||||
96 | margin-left:-15px; |
||||
97 | } |
||||
98 | .card { |
||||
99 | background: white; |
||||
100 | padding: 60px; |
||||
101 | border-radius: 4px; |
||||
102 | box-shadow: 0 2px 3px #C8D0D8; |
||||
103 | display: inline-block; |
||||
104 | margin: 0 auto; |
||||
105 | } |
||||
106 | </style> |
||||
107 | <body> |
||||
108 | <div class="card"> |
||||
109 | <div style="border-radius:200px; height:200px; width:200px; background: #F8FAF5; margin:0 auto;"> |
||||
110 | <i class="checkmark">✓</i> |
||||
111 | </div> |
||||
112 | <h1>Success</h1> |
||||
113 | <p>Check our bot for more information</p> |
||||
114 | </div> |
||||
115 | </body> |
||||
116 | </html>'); |
||||
117 | } |
||||
118 | } |
||||
119 | |||||
120 | public function message (message $update) { |
||||
121 | $text = $update->text ?? ''; |
||||
122 | |||||
123 | $user_id = $update->from->id; |
||||
124 | |||||
125 | $user = mysql::select('users', '*', ['id' => $user_id]); |
||||
126 | if ($user->num_rows < 1) { |
||||
127 | mysql::insert('users', ['id'], [$user_id]); |
||||
128 | $user = mysql::select('users', '*', ['id' => $user_id]); |
||||
129 | } |
||||
130 | $user = $user->fetch_object(); |
||||
131 | |||||
132 | if ($text === '/start') { |
||||
133 | mysql::update('users', ['step' => 'main', 'value' => ''], ['id' => $user_id], 1); |
||||
134 | return $this->sendMessage(texts::START, reply_markup: keyboards::START, answer: true); |
||||
0 ignored issues
–
show
The call to
BPT\BPT::sendMessage() has too many arguments starting with texts::START .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above. ![]() |
|||||
135 | } |
||||
136 | |||||
137 | if ($text === '/help') { |
||||
138 | return $this->sendMessage(texts::HELP, answer: true); |
||||
139 | } |
||||
140 | |||||
141 | if ($text === '/back') { |
||||
142 | $text = buttons::BACK; |
||||
143 | } |
||||
144 | |||||
145 | if ($user->step === 'main') { |
||||
146 | if ($text === buttons::BALANCE) { |
||||
147 | return $this->sendMessage(strReplace(['$balance' => $user->balance, '$coin' => texts::COIN], texts::BALANCE), answer: true); |
||||
148 | } |
||||
149 | if ($text === buttons::DEPOSIT) { |
||||
150 | mysql::update('users', ['step' => 'deposit'], ['id' => $user_id], 1); |
||||
151 | return $this->sendMessage(texts::DEPOSIT, reply_markup: keyboards::BACK, answer: true); |
||||
152 | } |
||||
153 | if ($text === buttons::TRANSFER) { |
||||
154 | if ($user->balance <= self::MIN_TRANSFER) { |
||||
155 | return $this->sendMessage(strReplace(['$min_transfer' => self::MIN_TRANSFER], texts::MIN_BALANCE), answer: true); |
||||
156 | } |
||||
157 | |||||
158 | mysql::update('users', ['step' => 'transfer'], ['id' => $user_id], 1); |
||||
159 | return $this->sendMessage(texts::TRANSFER, reply_markup: keyboards::SHARE_USER, answer: true); |
||||
160 | } |
||||
161 | if ($text === buttons::HISTORY) { |
||||
162 | return $this->sendMessage(texts::SOON, answer: true); |
||||
163 | } |
||||
164 | if ($text === buttons::SUPPORT) { |
||||
165 | return $this->sendMessage(texts::SOON, answer: true); |
||||
166 | } |
||||
167 | |||||
168 | return $this->sendMessage(texts::UNKNOWN, answer: true); |
||||
169 | } |
||||
170 | if ($user->step === 'transfer') { |
||||
171 | if ($text === buttons::BACK) { |
||||
172 | mysql::update('users', ['step' => 'main', 'value' => ''], ['id' => $user_id], 1); |
||||
173 | return $this->sendMessage(texts::START, reply_markup: keyboards::START, answer: true); |
||||
174 | } |
||||
175 | if (isset($update->user_shared)) { |
||||
0 ignored issues
–
show
The property
BPT\types\message::$user_shared has been deprecated: use users_shared instead
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This property has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead. ![]() |
|||||
176 | $target_id = $update->user_shared->user_id; |
||||
177 | } |
||||
178 | elseif (isset($update->forward_date)) { |
||||
0 ignored issues
–
show
The property
BPT\types\message::$forward_date has been deprecated: used forward_origin instead
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This property has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead. ![]() |
|||||
179 | if (!isset($update->forward_from)) { |
||||
180 | return $this->sendMessage(texts::USER_FORWARD_CLOSED, answer: true); |
||||
181 | } |
||||
182 | $target_id = $update->forward_from->id; |
||||
183 | } |
||||
184 | else { |
||||
185 | if (!is_numeric($text) || $text != floor($text)) { |
||||
0 ignored issues
–
show
$text of type string is incompatible with the type double|integer expected by parameter $num of floor() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
186 | return $this->sendMessage(texts::ONLY_INT, answer: true); |
||||
187 | } |
||||
188 | $target_id = $text; |
||||
189 | } |
||||
190 | |||||
191 | $target_user = mysql::select('users', '*', ['id' => $target_id], 1); |
||||
192 | if ($target_user->num_rows < 1) { |
||||
193 | return $this->sendMessage(texts::USER_NOT_FOUND, answer: true); |
||||
194 | } |
||||
195 | |||||
196 | mysql::update('users', ['step' => 'transfer_money', 'value' => $target_id], ['id' => $user_id], 1); |
||||
197 | return $this->sendMessage(strReplace(['$balance' => min($user->balance, self::MAX_TRANSFER)], texts::TRANSFER_MONEY), reply_markup: keyboards::BACK, answer: true); |
||||
198 | } |
||||
199 | if ($user->step === 'transfer_money') { |
||||
200 | if ($text === buttons::BACK) { |
||||
201 | mysql::update('users', ['step' => 'transfer'], ['id' => $user_id], 1); |
||||
202 | return $this->sendMessage(texts::TRANSFER, reply_markup: keyboards::SHARE_USER, answer: true); |
||||
203 | } |
||||
204 | |||||
205 | if (!is_numeric($text)) { |
||||
206 | return $this->sendMessage(texts::ONLY_NUMBER, answer: true); |
||||
207 | } |
||||
208 | |||||
209 | $text = floor($text * pow(10, self::MAX_MONEY_DECIMAL)) / pow(10, self::MAX_MONEY_DECIMAL); |
||||
210 | |||||
211 | if ($user->balance < $text) { |
||||
212 | return $this->sendMessage(texts::NOT_ENOUGH_BALANCE, answer: true); |
||||
213 | } |
||||
214 | |||||
215 | if ($text > self::MAX_TRANSFER) { |
||||
216 | return $this->sendMessage(strReplace(['$max_transfer' => self::MAX_TRANSFER], texts::MAX_TRANSFER), answer: true); |
||||
217 | } |
||||
218 | |||||
219 | mysql::update('users', ['balance' => '+=' . $text], ['id' => $user->value], 1); |
||||
220 | $this->sendMessage(strReplace(['$amount' => $text, '$id' => $user_id], texts::MONEY_RECEIVED), $user->value); |
||||
221 | |||||
222 | mysql::insert('history', ['type', 'amount', 'date', 'user_id', 'target_id'], ['transfer', $text, time(), $user_id, $user->value]); |
||||
223 | |||||
224 | mysql::update('users', ['balance' => '-=' . $text, 'step' => 'main', 'value' => ''], ['id' => $user_id], 1); |
||||
225 | return $this->sendMessage(texts::TRANSFER_DONE, reply_markup: keyboards::START, answer: true); |
||||
226 | } |
||||
227 | if ($user->step === 'deposit') { |
||||
228 | if ($text === buttons::BACK) { |
||||
229 | mysql::update('users', ['step' => 'main', 'value' => ''], ['id' => $user_id], 1); |
||||
230 | return $this->sendMessage(texts::START, reply_markup: keyboards::START, answer: true); |
||||
231 | } |
||||
232 | |||||
233 | if (!is_numeric($text)) { |
||||
234 | return $this->sendMessage(texts::ONLY_NUMBER, answer: true); |
||||
235 | } |
||||
236 | |||||
237 | $text = floor($text * pow(10, self::MAX_MONEY_DECIMAL)) / pow(10, self::MAX_MONEY_DECIMAL); |
||||
238 | |||||
239 | $max_deposit = pow(10, self::MAX_MONEY_LENGTH - self::MAX_MONEY_DECIMAL - 1); |
||||
240 | if ($text > pow(10, self::MAX_MONEY_LENGTH - self::MAX_MONEY_DECIMAL - 1)) { |
||||
241 | return $this->sendMessage(strReplace(['$max_deposit' => $max_deposit], texts::MAX_DEPOSIT), answer: true); |
||||
242 | } |
||||
243 | |||||
244 | $max_balance = pow(10, self::MAX_MONEY_LENGTH - self::MAX_MONEY_DECIMAL) - 1; |
||||
245 | if ($user->balance + $text >= $max_balance) { |
||||
246 | return $this->sendMessage(strReplace(['$max_balance' => $max_balance], texts::MAX_BALANCE), answer: true); |
||||
247 | } |
||||
248 | |||||
249 | $url = crypto::ezPay($text, $user_id, one_time_url: false); |
||||
250 | mysql::update('users', ['step' => 'main', 'value' => ''], ['id' => $user_id], 1); |
||||
251 | return $this->sendMessage(strReplace(['$url' => $url], texts::INVOICE_CREATED), reply_markup: keyboards::START, answer: true); |
||||
252 | } |
||||
253 | } |
||||
254 | } |
||||
255 | |||||
256 | class texts { |
||||
257 | const SOON = 'Will completed soon'; |
||||
258 | const UNKNOWN = 'Command does not found, please use buttons or send /start'; |
||||
259 | const ONLY_NUMBER = 'Only number is allowed'; |
||||
260 | const ONLY_INT = 'Only integer is allowed'; |
||||
261 | const START = 'Hello dear user |
||||
262 | Welcome to our bot |
||||
263 | If this is your first time, please send /help command'; |
||||
264 | const HELP = 'Hi, This is a simple wallet bot created by BPT library |
||||
265 | With this bot, you can easily deposit crypto, transfer it to another person. |
||||
266 | It is useful for saving crypto and trade with it at anytime you want'; |
||||
267 | const BALANCE = 'Your balance is : $balance$coin'; |
||||
268 | const COIN = '$'; |
||||
269 | const DEPOSIT = 'How much do you want to deposit?'; |
||||
270 | const MAX_DEPOSIT = 'You can not deposit more then $max_deposit'; |
||||
271 | const MAX_BALANCE = 'With this deposit, your balance will reach our max balance which is $max_balance'; |
||||
272 | const INVOICE_CREATED = 'Your payment created successfully |
||||
273 | Payment url : |
||||
274 | $url'; |
||||
275 | const MIN_BALANCE = 'You can not transfer when your balance is not more then $min_transfer'; |
||||
276 | const TRANSFER = 'Please send user id : |
||||
277 | You can forward a message too'; |
||||
278 | const USER_FORWARD_CLOSED = 'User forward is closed, Please send its user id'; |
||||
279 | const USER_NOT_FOUND = 'User not found, He/She must be a member of bot'; |
||||
280 | const TRANSFER_MONEY = 'How much do you want to transfer? |
||||
281 | Max is : $balance |
||||
282 | Note : Be aware that we do not get a confirmation from you! |
||||
283 | Transfer will be done after sending amount'; |
||||
284 | const NOT_ENOUGH_BALANCE = 'Your balance is not enough for this much transfer'; |
||||
285 | const MAX_TRANSFER = 'You can not transfer more then $max_transfer'; |
||||
286 | const MONEY_RECEIVED = 'Hello, You received $amount from $id'; |
||||
287 | const TRANSFER_DONE = 'Transfer is done successfully.'; |
||||
288 | |||||
289 | const PARTIALLY_PAID = 'Dear user, You paid $amount instead of your requested $real_amount |
||||
290 | Any how we added your paid amount to your balance |
||||
291 | If you want to complete your payment, you need to pay $need_amount more'; |
||||
292 | |||||
293 | const FINISHED = 'Dear user, You paid $amount and it added to your balance'; |
||||
294 | const FINISHED_PARTIALLY = 'Dear user, You paid $amount and it added to your balance |
||||
295 | You paid $old_amount before, so you got only $new_amount now'; |
||||
296 | |||||
297 | const EXTRA_PAID = 'Dear user, You paid $amount instead of your requested $real_amount |
||||
298 | Any how we added your paid amount to your balance'; |
||||
299 | |||||
300 | const EXTRA_PAID_PARTIALLY = 'Dear user, You paid $amount instead of your requested $real_amount |
||||
301 | Any how we added your paid amount to your balance |
||||
302 | You paid $old_amount before, so you got only $new_amount now'; |
||||
303 | } |
||||
304 | |||||
305 | class buttons { |
||||
306 | const BACK = 'Back'; |
||||
307 | const BALANCE = 'Balance'; |
||||
308 | const DEPOSIT = 'Deposit'; |
||||
309 | const TRANSFER = 'Transfer'; |
||||
310 | const HISTORY = 'History'; |
||||
311 | const SUPPORT = 'Support'; |
||||
312 | } |
||||
313 | |||||
314 | class keyboards { |
||||
315 | const BACK = [ |
||||
316 | 'resize_keyboard' => true, |
||||
317 | 'keyboard' => [ |
||||
318 | [ |
||||
319 | ['text' => buttons::BACK] |
||||
320 | ] |
||||
321 | ] |
||||
322 | ]; |
||||
323 | |||||
324 | const SHARE_USER = [ |
||||
325 | 'resize_keyboard' => true, |
||||
326 | 'keyboard' => [ |
||||
327 | [ |
||||
328 | ['text' => 'Choose user', 'request_user' => ['request_id' => 12, 'user_is_bot' => false]] |
||||
329 | ], |
||||
330 | [ |
||||
331 | ['text' => buttons::BACK] |
||||
332 | ] |
||||
333 | ] |
||||
334 | ]; |
||||
335 | const START = [ |
||||
336 | 'resize_keyboard' => true, |
||||
337 | 'keyboard' => [ |
||||
338 | [ |
||||
339 | ['text' => buttons::BALANCE] |
||||
340 | ], |
||||
341 | [ |
||||
342 | ['text' => buttons::DEPOSIT], ['text' => buttons::TRANSFER] |
||||
343 | ], |
||||
344 | [ |
||||
345 | ['text' => buttons::HISTORY], ['text' => buttons::SUPPORT] |
||||
346 | ] |
||||
347 | ] |
||||
348 | ]; |
||||
349 | } |
||||
350 | |||||
351 | /** |
||||
352 | * BPT settings |
||||
353 | * |
||||
354 | * @link https://bptlib.ir/multi |
||||
355 | */ |
||||
356 | $BPT = new handler([ |
||||
357 | 'token' => 'YOUR_BOT_TOKEN', |
||||
358 | 'db' => [ |
||||
359 | 'type' => dbTypes::MYSQL, |
||||
360 | 'user' => 'dbUser', |
||||
361 | 'pass' => 'dbPassword', |
||||
362 | 'dbname' => 'dbName', |
||||
363 | 'auto_process' => false, |
||||
364 | 'auto_load' => true |
||||
365 | ], |
||||
366 | 'pay' => [ |
||||
367 | 'crypto' => [ |
||||
368 | 'api_key' => 'API_KEY', |
||||
369 | 'ipn_secret' => 'IPN_SECRET', |
||||
370 | 'round_decimal' => handler::MAX_MONEY_DECIMAL |
||||
371 | ] |
||||
372 | ], |
||||
373 | 'allowed_updates' => ['message'] |
||||
374 | ]); |
||||
375 |
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.