├── .gitignore ├── LICENSE ├── README.md ├── composer.json ├── config └── larapay.php ├── database └── migrations │ └── create_larapay_transaction_table.php.stub ├── src ├── Adapter │ ├── AdapterAbstract.php │ ├── AdapterInterface.php │ ├── Exception.php │ ├── Idpay.php │ ├── Idpay │ │ └── Exception.php │ ├── Mellat.php │ ├── Mellat │ │ └── Exception.php │ ├── Nextpay.php │ ├── Nextpay │ │ ├── Exception.php │ │ └── Helper.php │ ├── Parsian.php │ ├── Parsian │ │ └── Exception.php │ ├── Pasargad.php │ ├── Pasargad │ │ ├── Helper.php │ │ ├── PasargadResult.php │ │ ├── RSA.php │ │ ├── RSAProcessor.php │ │ └── certificate.xml │ ├── PayIr │ │ ├── Exception.php │ │ └── Helper.php │ ├── Payir.php │ ├── Saderat.php │ ├── Saderat │ │ ├── Exception.php │ │ └── Helper.php │ ├── Saman.php │ ├── Saman │ │ └── Exception.php │ ├── Zarinpal.php │ ├── Zarinpal │ │ └── Exception.php │ ├── Zibal.php │ └── Zibal │ │ ├── Exception.php │ │ └── Helper.php ├── Contracts │ └── LarapayTransaction.php ├── Exception.php ├── Exceptions │ ├── EmptyAmountException.php │ ├── FailedReverseTransactionException.php │ ├── FailedTransactionException.php │ └── TransactionNotFoundException.php ├── Facades │ └── Larapay.php ├── Factory.php ├── LarapayServiceProvider.php ├── Models │ ├── Enum │ │ ├── Bank.php │ │ └── Sharing.php │ ├── LarapayTransaction.php │ └── Traits │ │ └── OnlineTransactionTrait.php ├── Payable.php └── Transaction │ └── TransactionInterface.php ├── translations ├── en │ └── larapay.php └── fa │ └── larapay.php └── views ├── idpay-form.blade.php ├── mellat-form.blade.php ├── nextpay-form.blade.php ├── parsian-form.blade.php ├── pasargad-form.blade.php ├── payir-form.blade.php ├── sadad-form.blade.php ├── saderat-form.blade.php ├── saman-form.blade.php ├── zarinpal-form.blade.php └── zibal-form.blade.php /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | /vendor 3 | composer.lock 4 | phpunit.xml 5 | 6 | *.DS_Store 7 | .DS_Store 8 | # Thumbnails 9 | ._* 10 | 11 | # Files that might appear in the root of a volume 12 | .DocumentRevisions-V100 13 | .fseventsd 14 | .Spotlight-V100 15 | .TemporaryItems 16 | .Trashes 17 | .VolumeIcon.icns 18 | .com.apple.timemachine.donotpresent 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | # Laravel Online Payment Module v1.0.0 for Laravel 5 2 | 3 | ## Laravel 4 | 5 | 6 | The MIT License (MIT) 7 | 8 | Copyright (c) 2016 Aboozar Ghaffari 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Laravel Iranian Online Payment Component 2 | Online Payment Module handler for Laravel 5+ known as LaraPay component completely compatible with [BankTest](http://banktest.ir) sandbox. 3 | Larapay integrated all Iranian payment gateways into one component. 4 | 5 | Here are a few short examples of what you can do: 6 | * create new transaction form your order model and generate bank form 7 | ```php 8 | $transaction = $order->createTransaction(Bank::MELLAT); 9 | $form = $transaction->generateForm(); 10 | ``` 11 | * handle gateway callback (verify/settle/...) 12 | ```php 13 | $transaction = Larapay::verifyTransaction($request); 14 | //if the gateway supports reverse method 15 | $transaction->reverseTransaction(); 16 | $order = $transaction->model; 17 | ``` 18 | * get order transaction information 19 | ```php 20 | $allTransactions = $order->transations; 21 | $accomplishedTransactions = $order->accomplishedTransactions; 22 | $isPaid = $order->isPaid(); 23 | $paidAmount = $order->paidAmount(); 24 | ``` 25 | 26 | ## Currenctly supports: 27 | 28 | - Mellat Bank Gateway - درگاه بانک ملت لاراول 29 | - Saman Bank Gateway - درگاه بانک سامان لاراول 30 | - Saderat/Sepehr Pay Bank Gateway - درگاه بانک صادرات / سپهر 31 | - Pasargad Bank Gateway - درگاه بانک پاسارگاد لاراول 32 | - Parsian Bank Gateway - درگاه بانک پارسیان لاراول 33 | - Melli/Sadad Bank Gateway (Sadad) - درگاه بانک ملی / سداد لاراول 34 | - Pay.ir Gateway / درگاه پرداخت پی 35 | - Zarinpal Gateway / درگاه پرداخت زرین پال 36 | - IDPay Gateway / درگاه آیدی پی 37 | - Zibal Gateway / درگاه زیبال 38 | - nextpay Gateway / درگاه نکست پی 39 | 40 | - ... 41 | - Other gateways, coming soon... لطفا شما هم در تکمیل پکیج مشارکت کنید 42 | 43 | #### But what is B‌anktest sandbox? 44 | - [BankTest](http://banktest.ir) is a sandbox service for all Iranian online payment gateways 45 | - [بانک تست](http://banktest.ir) یک سرویس شبیه ساز درگاه های پرداخت آنلاین ایرانی برای اهداف توسعه و تست نرم افزار می باشد 46 | 47 | 48 | ## Requirements 49 | Larapay Version 6+ required PHP 7+ 50 | 51 | ## Installation 52 | 1. Installing via composer 53 | 54 | ```bash 55 | composer require php-monsters/laravel-online-payment 56 | ``` 57 | 2. Add package service provider to your app service providers (only for Laravel < 5.5): 58 | 59 | ```php 60 | PhpMonsters\Larapay\LarapayServiceProvider::class, 61 | PhpMonsters\Log\XLogServiceProvider::class, 62 | ``` 63 | 3. Add package alias to your app aliases (only for Laravel < 5.5): 64 | 65 | ```php 66 | 'Larapay' => PhpMonsters\Larapay\Facades\Larapay::class, 67 | 'XLog' => PhpMonsters\Log\Facades\XLog::class, 68 | ``` 69 | 4. Publish package assets and configs 70 | 71 | ```bash 72 | php artisan vendor:publish --provider="PhpMonsters\Larapay\LarapayServiceProvider" 73 | ``` 74 | 75 | 5. Run migration 76 | ```bash 77 | php artisan migrate 78 | ``` 79 | 80 | ## Configuration 81 | If you complete installation step correctly, you can find Larapay config file as larapay.php in you project config file. 82 | 83 | For sandbox (banktest) you should set ```LARAPAY_MODE=development``` in your .env file otherwise set ```LARAPAY_MODE=production``` 84 | 85 | If you choose development mode, Larapay use banktest.ir as it's payment gateway. 86 | 87 | Set your gateway(s) configs in your .env file. Here are some example: 88 | ```ini 89 | LARAPAY_MODE=development 90 | 91 | SAMAN_MERCHANT_ID=bmcf**** 92 | SAMAN_MERCHANT_PASS=98221*** 93 | 94 | MELLAT_USERNAME=user*** 95 | MELLAT_PASSWORD=80714*** 96 | MELLAT_TERMINAL_ID=747 97 | ``` 98 | 99 | ### Setup callback route 100 | you should create a route for handling callback from bank and set your route name in .env 101 | 102 | For example create a POST route in routes folder, web.php like this: 103 | ```php 104 | Route::post('payment/callback', 'YourController@handleCallback')->name('payment.callback'); 105 | ``` 106 | 107 | then set the route name in .env file: 108 | 109 | ```ini 110 | LARAPAY_PAYMENT_CALLBACK=payment.callback 111 | ``` 112 | 113 | 114 | ## Usage 115 | 116 | ### Prepare payable model 117 | 118 | Use `Payable` trait in your order model or any other model like user which will get payment feature and implement it. 119 | 120 | You can impalement getAmount() method to return `Iranian Rail` amount of your model. 121 | ```php 122 | use PhpMonsters\Larapay\Payable; 123 | 124 | class Order extends Model 125 | { 126 | use Payable; 127 | 128 | public function getAmount(){ 129 | return intval($this->amount) * 10; 130 | } 131 | 132 | } 133 | ``` 134 | 135 | Now you just have 3 steps to complete your payment: 136 | 137 | ### 1- create transaction 138 | 139 | In your bank controller create a transaction for your order and generate bank for to transfer user to payment gateway. 140 | ```php 141 | use PhpMonsters\Larapay\Models\Enum\Bank; 142 | 143 | class BankController extends Controller 144 | { 145 | public function index() 146 | { 147 | //your logic and prepare your order 148 | // ... 149 | 150 | //if you implement getAmount() method you can set amount to null 151 | $amount = 1200000; //Rial at least 1000 152 | //order or user description 153 | $description = 'I pay my order with Larapay <3'; 154 | //some additional data that you need store on transaction 155 | $additionalData = []; 156 | //create transaction 157 | $transaction = $order->createTransaction(Bank::MELLAT, $amount, $description, $additionalData); 158 | 159 | //auto submit bank form and transfer user to gateway 160 | $autoSubmit = true; 161 | //callback route name. if you set it on your .env file you can set this to null 162 | $callbackRouteName = 'payment.callback'; 163 | //adapter config 164 | $adapterConfig = []; 165 | //generate bank form 166 | $form = $transaction->generateForm($autoSubmit, $callbackRouteName, $adapterConfig); 167 | 168 | return view('go-to-bank',[ 169 | 'form' => $form, 170 | ]); 171 | } 172 | } 173 | ``` 174 | 175 | ### 2- show bank transfer form 176 | 177 | Now you can show you `$form` in your `go-to-bank` view file: 178 | ```php 179 |
180 | {!! $form !!} 181 |
182 | ``` 183 | 184 | You can modify bank forms in: 185 | ``` 186 | resources/views/vendor/larapy 187 | ``` 188 | 189 | ### 3- handle callback 190 | 191 | After payment, bank call you callback route 192 | 193 | ```php 194 | use Illuminate\Http\Request; 195 | use PhpMonsters\Larapay\Facades\Larapay; 196 | 197 | class YourController extends Controller 198 | { 199 | public function handleCallback(Request $request) 200 | { 201 | try{ 202 | $adapterConfig = []; 203 | $transaction = Larapay::verifyTransaction($request, $adapterConfig); 204 | $order = $transaction->model; 205 | //transaction done. payment is successful 206 | } catch (\Exception $e){ 207 | // transaction not complete!!! 208 | // show error to your user 209 | } 210 | } 211 | } 212 | ``` 213 | 214 | If you want to revers transaction and your bank support it, you can do this way: 215 | ```php 216 | $transaction->reverseTransaction(); 217 | ``` 218 | 219 | ## Methods 220 | 221 | ### Methods available in `Paybel` trait and your order model: 222 | 223 | * `$order->transactions` : get all transactions of this model 224 | * `$order->accomplishedTransactions`: get all accomplished transactions 225 | * `$order->isPaid()`: return true if this model has at least one accomplished transaction 226 | * `$order->paidAmount()`: return sum of accomplished transactions amount in Rial 227 | * `$order->createTransaction( 228 | $paymentGateway, 229 | $amount = null, 230 | $description = null, 231 | array $additionalData = [] 232 | )`: create a transaction. 233 | 234 | 235 | ### Methods available in `LarapayTransaction` model: 236 | 237 | * `$transaction->model`: return the model that create this transaction. for example `$order` 238 | * `$transaction->reverseTransaction()`: reverse transaction and get back money to user. (if bank support reverse transaction) 239 | * `$transaction->generateForm($autoSubmit = false, $callback = null)`: generate bank transfer form 240 | * `$transaction->gatewayHandler()`: get gatewayHandler for advance use. 241 | 242 | ### Fields available in `LarapayTransaction` model: 243 | * `id` 244 | * `created_at` 245 | * `updated_at` 246 | 247 | Status in boolean: 248 | * `accomplished` 249 | * `verified` 250 | * `after_verified` 251 | * `reversed` 252 | * `submitted` 253 | * `approved` 254 | * `rejected` 255 | 256 | Gate information: 257 | * `payment_method` 258 | * `bank_order_id` 259 | * `gate_name` 260 | * `gate_refid` 261 | * `gate_status` 262 | * `extra_params` 263 | * `additional_data` 264 | 265 | Order information: 266 | * `amount` 267 | * `description` 268 | * `paid_at` 269 | 270 | 271 | ## LarapayTransaction 272 | 273 | You can use `LarapayTransaction` model to find your transaction: 274 | 275 | ```php 276 | use PhpMonsters\Larapay\Models\LarapayTransaction; 277 | 278 | public function getTransaction($transactionId){ 279 | 280 | //find single transaction by transaction id 281 | $transaction = LarapayTransaction::find($transactionId); 282 | 283 | //get all accomplished transaction 284 | $accomplishedTransactions = LarapayTransaction::where('accomplished',true)->get(); 285 | 286 | //get all reversed transaction 287 | $reversedTransactions = LarapayTransaction::where('reversed',true)->get(); 288 | } 289 | ``` 290 | 291 | This class use SoftDeletes. you can call delete() on your transaction model to softDelete it or forceDelete() to truly remove it from your database. 292 | 293 | ## Security 294 | 295 | If you discover any security related issues, please email a6oozar@gmail.com or milad.kian@gmail.com instead of using the issue tracker. 296 | 297 | ## Team 298 | 299 | This component is developed by the following person(s) and a bunch of [awesome contributors](https://github.com/php-monsters/laravel-online-payment/graphs/contributors). 300 | 301 | [![Aboozar Ghaffari](https://avatars2.githubusercontent.com/u/502961?v=3&s=130)](https://github.com/samuraee) | [![Milad Kianmehr](https://avatars3.githubusercontent.com/u/4578704?v=3&s=130)](https://github.com/miladkian) | [![Sina Miandashti](https://avatars3.githubusercontent.com/u/195868?v=3&s=130)](https://github.com/sinamiandashti) | [![XShaan](https://avatars3.githubusercontent.com/u/4527899?v=3&s=130)](https://github.com/xshaan) 302 | | --- | --- | --- | --- | 303 | [Aboozar Ghaffari](https://github.com/samuraee) | [Milad Kianmehr](https://github.com/miladkian) | [Sina Miandashti](https://github.com/sinamiandashti) | [XShaan](https://github.com/xshaan) 304 | 305 | 306 | ## Support This Project 307 | 308 | Please contribute in package completion. This is the best support. 309 | 310 | ## License 311 | 312 | The Laravel Online Payment Module is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT) 313 | 314 | 315 | 316 | 317 | 318 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "php-monsters/laravel-online-payment", 3 | "description": "Iranian payment gateways handler for laravel applications", 4 | "keywords": ["payment","shetab", "bank", "online payment", "gateway", "iran"], 5 | "type": "library", 6 | "license": "MIT", 7 | "authors": [ 8 | { 9 | "name": "Aboozar Ghaffari ", 10 | "email": "aboozar.ghf@gmail.com" 11 | }, 12 | { 13 | "name": "Milad Kianmehr", 14 | "email": "milad.kian@gmail.com" 15 | } 16 | ], 17 | "require": { 18 | "php": ">=7.4", 19 | "ext-soap" : "*", 20 | "ext-json": "*", 21 | "ext-bcmath": "*", 22 | "ext-simplexml": "*", 23 | "illuminate/contracts": ">=7.0", 24 | "illuminate/database": ">=7.0", 25 | "illuminate/http": ">=7.0", 26 | "illuminate/routing": ">=7.0", 27 | "illuminate/support": ">=7.0", 28 | "illuminate/view": ">=7.0", 29 | "php-monsters/laravel-xlog": "^1.3.0" 30 | }, 31 | "require-dev": { 32 | "mockery/mockery": "^1.0", 33 | "orchestra/testbench": "^3.8|^4.0|^5.0", 34 | "phpunit/phpunit": "^7.5|^8.0" 35 | }, 36 | "autoload": { 37 | "psr-4": { 38 | "PhpMonsters\\Larapay\\": "src/" 39 | } 40 | }, 41 | "extra": { 42 | "laravel": { 43 | "providers": [ 44 | "PhpMonsters\\Larapay\\LarapayServiceProvider" 45 | ], 46 | "aliases": { 47 | "Larapay": "PhpMonsters\\Larapay\\Facades\\Larapay" 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /config/larapay.php: -------------------------------------------------------------------------------- 1 | env('LARAPAY_MODE', 'production'), 18 | 19 | /* 20 | |-------------------------------------------------------------------------- 21 | | ready to serve gateways 22 | |-------------------------------------------------------------------------- 23 | | 24 | | specifies ready to serve gateways. 25 | | gateway characters are case sensitive and should be exactly same as their folder name. 26 | | eg, "Asanpay" is correct not "AsanPay" or "asanpay" 27 | | the gateways list is comma separated 28 | | 29 | */ 30 | 'gateways' => env('LARAPAY_GATES', 'Mellat,Saman,Pasargad,Parsian,ZarinPal,Idpay,Payir,Saderat,Zibal,Nextpay'), 31 | 32 | /* 33 | |-------------------------------------------------------------------------- 34 | | Mellat gateway configuration 35 | |-------------------------------------------------------------------------- 36 | */ 37 | 'mellat' => [ 38 | 'username' => env('MELLAT_USERNAME', ''), 39 | 'password' => env('MELLAT_PASSWORD', ''), 40 | 'terminal_id' => env('MELLAT_TERMINAL_ID', ''), 41 | ], 42 | 43 | /* 44 | |-------------------------------------------------------------------------- 45 | | Parsian gateway configuration 46 | |-------------------------------------------------------------------------- 47 | */ 48 | 'parsian' => [ 49 | 'pin' => env('PARSIAN_PIN', ''), 50 | 'timeout' => env('PARSIAN_TIMEOUT', 15), 51 | 52 | ], 53 | /* 54 | |-------------------------------------------------------------------------- 55 | | Pasargad gateway configuration 56 | |-------------------------------------------------------------------------- 57 | */ 58 | 'pasargad' => [ 59 | 'terminalId' => env('PASARGAD_TERMINAL_ID', ''), 60 | 'merchantId' => env('PASARGAD_MERCHANT_ID', ''), 61 | 'certificate_path' => storage_path(env('PASARGAD_CERT_PATH', 'payment/pasargad/certificate.xml')), 62 | ], 63 | 64 | /* 65 | |-------------------------------------------------------------------------- 66 | | Sadad gateway configuration 67 | |-------------------------------------------------------------------------- 68 | */ 69 | 'sadad' => [ 70 | 'merchant' => env('SADAD_MERCHANT', ''), 71 | 'transaction_key' => env('SADAD_TRANS_KEY', ''), 72 | 'terminal_id' => env('SADAD_TERMINAL_ID', ''), 73 | ], 74 | 75 | /* 76 | |-------------------------------------------------------------------------- 77 | | Saderat - Sepehr Pay gateway configuration 78 | |-------------------------------------------------------------------------- 79 | */ 80 | 'saderat' => [ 81 | 'terminalId' => env('SADERAT_TERMINAL_ID', ''), 82 | 'callbackUrl' => env('SADERAT_CALLBACK_URL', ''), 83 | 'description' => env('SADERAT_DESCRIPTION', 'powered-by-Larapay saderat(sepehr)'), 84 | ], 85 | 86 | /* 87 | |-------------------------------------------------------------------------- 88 | | Saman gateway configuration 89 | |-------------------------------------------------------------------------- 90 | */ 91 | 'saman' => [ 92 | 'merchant_id' => env('SAMAN_MERCHANT_ID', ''), 93 | 'merchant_pass' => env('SAMAN_MERCHANT_PASS', ''), 94 | 'with_token' => 1, 95 | ], 96 | 97 | /* 98 | |-------------------------------------------------------------------------- 99 | | Zarinpal gateway configuration 100 | |-------------------------------------------------------------------------- 101 | | 102 | | types: acceptable values --- zarin-gate or normal 103 | | server: acceptable values --- germany or iran or test 104 | | 105 | */ 106 | 'zarinpal' => [ 107 | 'merchant_id' => env('ZARINPAL_MERCHANT_ID', ''), 108 | 'type' => env('ZARINPAL_TYPE', 'zarin-gate'), 109 | 'callback_url' => env('ZARINPAL_CALLBACK_URL', ''), 110 | 'server' => env('ZARINPAL_SERVER', 'germany'), 111 | 'email' => env('ZARINPAL_EMAIL', ''), 112 | 'mobile' => env('ZARINPAL_MOBILE', '09xxxxxxxxx'), 113 | 'description' => env('ZARINPAL_DESCRIPTION', 'powered-by-Larapay'), 114 | ], 115 | 116 | /* 117 | |-------------------------------------------------------------------------- 118 | | Pay.ir gateway configuration 119 | |-------------------------------------------------------------------------- 120 | | 121 | | api: For the sandbox gateway, set API to 'test' 122 | | 123 | */ 124 | 'payir' => [ 125 | 'api' => env('PAY_IR_API_KEY', ''), 126 | ], 127 | 128 | /* 129 | |-------------------------------------------------------------------------- 130 | | Idpay gateway configuration 131 | |-------------------------------------------------------------------------- 132 | | 133 | | types: acceptable values --- normal 134 | | 135 | */ 136 | 'idpay' => [ 137 | 'merchant_id' => env('IDPAY_MERCHANT_ID', ''), 138 | 'type' => env('IDPAY_TYPE', 'normal'), 139 | 'callback_url' => env('IDPAY_CALLBACK_URL', ''), 140 | 'email' => env('IDPAY_EMAIL', ''), 141 | 'mobile' => env('IDPAY_MOBILE', '09xxxxxxxxx'), 142 | 'description' => env('IDPAY_DESCRIPTION', 'powered-by-Larapay'), 143 | ], 144 | 145 | /* 146 | |-------------------------------------------------------------------------- 147 | | Zibal gateway configuration 148 | |-------------------------------------------------------------------------- 149 | | 150 | | merchant_id: For the sandbox gateway, set merchant_id to 'zibal' 151 | | 152 | */ 153 | 'zibal' => [ 154 | 'merchant_id' => env('ZIBAL_MERCHANT_ID', ''), 155 | 'type' => env('ZIBAL_TYPE', 'normal'), 156 | 'callback_url' => env('ZIBAL_CALLBACK_URL', ''), 157 | 'email' => env('ZIBAL_EMAIL', ''), 158 | 'mobile' => env('ZIBAL_MOBILE', '09xxxxxxxxx'), 159 | 'description' => env('ZIBAL_DESCRIPTION', 'powered-by-Larapay'), 160 | ], 161 | 162 | /* 163 | |-------------------------------------------------------------------------- 164 | | Nextpay gateway configuration 165 | |-------------------------------------------------------------------------- 166 | | 167 | */ 168 | 'nextpay' => [ 169 | 'api_key' => env('NEXTPAY_MERCHANT_ID', ''), 170 | 'type' => env('NEXTPAY_TYPE', 'normal'), 171 | 'callback_url' => env('NEXTPAY_CALLBACK_URL', ''), 172 | 'email' => env('NEXTPAY_EMAIL', ''), 173 | 'mobile' => env('NEXTPAY_MOBILE', '09xxxxxxxxx'), 174 | 'description' => env('NEXTPAY_DESCRIPTION', 'powered-by-Larapay'), 175 | ], 176 | 177 | /* 178 | |-------------------------------------------------------------------------- 179 | | SoapClient Options 180 | |-------------------------------------------------------------------------- 181 | | 182 | | useOptions: true/false 183 | | options: soapClient Options 184 | | 185 | */ 186 | 'soap' => [ 187 | 'useOptions' => env('SOAP_HAS_OPTIONS', false), 188 | 'options' => [ 189 | 'proxy_host' => env('SOAP_PROXY_HOST', ''), 190 | 'proxy_port' => env('SOAP_PROXY_PORT', ''), 191 | 'stream_context' => stream_context_create( 192 | [ 193 | 'ssl' => [ 194 | 'verify_peer' => false, 195 | 'verify_peer_name' => false, 196 | ], 197 | ] 198 | ), 199 | ], 200 | ], 201 | /* 202 | |-------------------------------------------------------------------------- 203 | | Route name for handle payment callback 204 | |-------------------------------------------------------------------------- 205 | */ 206 | 207 | 'payment_callback' => env('LARAPAY_PAYMENT_CALLBACK' , '') 208 | ]; 209 | -------------------------------------------------------------------------------- /database/migrations/create_larapay_transaction_table.php.stub: -------------------------------------------------------------------------------- 1 | increments('id'); 19 | 20 | //morph to model like order or user 21 | $table->morphs('model'); 22 | 23 | //status 24 | $table->boolean('accomplished')->default(false); 25 | $table->boolean('verified')->default(false); 26 | $table->boolean('after_verified')->default(false); 27 | $table->boolean('reversed')->default(false); 28 | $table->boolean('submitted')->default(false); 29 | $table->boolean('approved')->default(false); 30 | $table->boolean('rejected')->default(false); 31 | 32 | $table->string('payment_method', 255)->default('ONLINE'); 33 | 34 | $table->string('bank_order_id', 20)->nullable(); // gateway order ID 35 | 36 | $table->string('gate_name', 20)->nullable(); 37 | $table->string('gate_refid', 50)->nullable(); 38 | $table->string('gate_status')->nullable(); 39 | 40 | $table->text('description')->nullable(); 41 | $table->bigInteger('amount')->default(0); 42 | 43 | if (env('DB_CONNECTION') == 'pgsql') { // for POSTGRESQL 44 | $table->jsonb('extra_params')->nullable()->default('{}'); 45 | $table->jsonb('additional_data')->nullable()->default('{}'); 46 | $table->jsonb('sharing')->nullable()->default('{}'); 47 | } else { // for MYSQL 48 | $table->jsonb('extra_params')->nullable(); 49 | $table->jsonb('additional_data')->nullable(); 50 | $table->jsonb('sharing')->nullable(); 51 | } 52 | 53 | $table->dateTime('paid_at')->nullable(); 54 | $table->timestamps(); 55 | $table->softDeletes(); 56 | }); 57 | } 58 | 59 | /** 60 | * Reverse the migrations. 61 | */ 62 | public function down() 63 | { 64 | Schema::dropIfExists('larapay_transactions'); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/Adapter/AdapterAbstract.php: -------------------------------------------------------------------------------- 1 | transaction = $transaction; 67 | 68 | $this->setParameters($configs); 69 | $this->init(); 70 | } 71 | 72 | /** 73 | * Adapter`s init method that called after construct method 74 | */ 75 | public function init() { } 76 | 77 | /** 78 | * @param string $key 79 | * @param mixed $val 80 | */ 81 | public function __set($key, $val) 82 | { 83 | $key = strtolower($key); 84 | $this->parameters[$key] = trim($val); 85 | } 86 | 87 | /** 88 | * @param string $key 89 | * 90 | * @return mixed|null 91 | */ 92 | public function __get($key) 93 | { 94 | $key = strtolower($key); 95 | return isset($this->parameters[$key]) ? trim($this->parameters[$key]) : null; 96 | } 97 | 98 | 99 | /** 100 | * @return TransactionInterface 101 | */ 102 | public function getTransaction(): TransactionInterface 103 | { 104 | return $this->transaction; 105 | } 106 | 107 | /** 108 | * @param array $parameters 109 | * 110 | * @return $this 111 | */ 112 | public function setParameters(array $parameters = []): AdapterInterface 113 | { 114 | foreach ($parameters as $key => $value) { 115 | if($key === 'customer_card_number'){ 116 | continue; 117 | } 118 | $key = strtolower($key); 119 | $this->parameters[$key] = is_array($value) ? $value : trim($value); 120 | } 121 | 122 | return $this; 123 | } 124 | 125 | /** 126 | * @param string $key 127 | * 128 | * @return mixed|null 129 | */ 130 | public function getParameter($key) 131 | { 132 | $key = strtolower($key); 133 | return isset($this->parameters[$key]) ? trim($this->parameters[$key]) : null; 134 | } 135 | 136 | /** 137 | * @return array 138 | */ 139 | public function getParameters(): array 140 | { 141 | return $this->parameters; 142 | } 143 | 144 | /** 145 | * @return string 146 | */ 147 | public function form(): string 148 | { 149 | return $this->generateForm(); 150 | } 151 | 152 | /** 153 | * @return true 154 | */ 155 | public function verify(): bool 156 | { 157 | return $this->verifyTransaction(); 158 | } 159 | 160 | /** 161 | * @return bool 162 | */ 163 | public function afterVerify(): bool 164 | { 165 | $this->getTransaction()->setAfterVerified(); // عملیات پیش فرض در صورت عدم نیاز 166 | 167 | return true; 168 | } 169 | 170 | /** 171 | * @return bool 172 | */ 173 | public function reverse(): bool 174 | { 175 | return $this->reverseTransaction(); 176 | } 177 | 178 | /** 179 | * check for required parameters 180 | * 181 | * @param array $parameters 182 | * 183 | * @throws Exception 184 | */ 185 | protected function checkRequiredParameters(array $parameters) 186 | { 187 | foreach ($parameters as $parameter) { 188 | $parameter = strtolower($parameter); 189 | 190 | if (!array_key_exists($parameter, $this->parameters) || trim($this->parameters[$parameter]) == "") { 191 | throw new Exception("Parameters array must have a not null value for key: '$parameter'"); 192 | } 193 | } 194 | } 195 | 196 | /** 197 | * @return string 198 | */ 199 | protected function getWSDL(): string 200 | { 201 | if (config('larapay.mode') === 'production') { 202 | return $this->WSDL; 203 | } else { 204 | return $this->testWSDL; 205 | } 206 | } 207 | 208 | /** 209 | * @return string 210 | */ 211 | protected function getEndPoint(): string 212 | { 213 | if (config('larapay.mode') === 'production') { 214 | return $this->endPoint; 215 | } else { 216 | return $this->testEndPoint; 217 | } 218 | } 219 | 220 | /** 221 | * @param array $options 222 | * 223 | * @deprecated 224 | * 225 | * 'login' => config('api.basic.username'), 226 | * 'password' => config('api.basic.password'), 227 | * 'proxy_host' => 'localhost', 228 | * 'proxy_port' => '8080' 229 | * 230 | */ 231 | public function setSoapOptions(array $options = []) 232 | { 233 | XLog::debug('soap options set', $options); 234 | $this->soapOptions = $options; 235 | } 236 | 237 | /** 238 | * @return array 239 | */ 240 | protected function getSoapOptions(): array 241 | { 242 | return $this->soapOptions; 243 | } 244 | 245 | 246 | /** 247 | * @return SoapClient 248 | * @throws \SoapFault 249 | */ 250 | protected function getSoapClient(): SoapClient 251 | { 252 | return new SoapClient($this->getWSDL(), $this->getSoapOptions()); 253 | } 254 | 255 | /** 256 | * @return mixed 257 | * @throws Exception 258 | */ 259 | public function getGatewayReferenceId(): string 260 | { 261 | throw new Exception(__METHOD__ . ' not implemented'); 262 | } 263 | 264 | /** 265 | * @return bool 266 | */ 267 | public function reverseSupport(): bool 268 | { 269 | return $this->reverseSupport; 270 | } 271 | 272 | /** 273 | * @return bool 274 | */ 275 | public function canContinueWithCallbackParameters(): bool 276 | { 277 | return true; 278 | } 279 | 280 | /** 281 | * @param $obj 282 | * 283 | * @return array 284 | */ 285 | protected function obj2array($obj): array 286 | { 287 | $out = []; 288 | foreach ($obj as $key => $val) { 289 | switch (true) { 290 | case is_object($val): 291 | $out[$key] = $this->obj2array($val); 292 | break; 293 | case is_array($val): 294 | $out[$key] = $this->obj2array($val); 295 | break; 296 | default: 297 | $out[$key] = $val; 298 | } 299 | } 300 | 301 | return $out; 302 | } 303 | } 304 | -------------------------------------------------------------------------------- /src/Adapter/AdapterInterface.php: -------------------------------------------------------------------------------- 1 | adapter ); 27 | $gate = end($gate); 28 | $gate = strtolower($gate); 29 | 30 | switch ($message) 31 | { 32 | case is_numeric($message): { 33 | $code = $message; 34 | $message = 'larapay::larapay.'.$gate.'.errors.error_' . str_replace('-', '_', strval($message)); // fetch message from translation file 35 | break; 36 | } 37 | 38 | case preg_match('/^larapay::/', $message) == 1 : { 39 | $code = static::UNHANDLED_ERR; 40 | $message = trans(strval($message)); // fetch message from translation file 41 | break; 42 | } 43 | } 44 | 45 | parent::__construct($message, $code, $previous); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Adapter/Idpay.php: -------------------------------------------------------------------------------- 1 | requestToken(); 32 | 33 | return [ 34 | 'endPoint' => strtr($this->getEndPoint(), ['{authority}' => $authority]), 35 | ]; 36 | } 37 | 38 | /** 39 | * @return bool 40 | */ 41 | public function canContinueWithCallbackParameters(): bool 42 | { 43 | if (!empty($this->transaction['gate_refid'])) { 44 | return true; 45 | } 46 | 47 | return false; 48 | } 49 | 50 | public function getGatewayReferenceId(): string 51 | { 52 | $this->checkRequiredParameters([ 53 | 'merchant_id', 54 | ]); 55 | 56 | return strval($this->transaction['gate_refid']); 57 | } 58 | 59 | /** 60 | * @return string 61 | * @throws Exception 62 | * @throws \PhpMonsters\Larapay\Adapter\Exception 63 | */ 64 | protected function generateForm(): string 65 | { 66 | $authority = $this->requestToken(); 67 | 68 | $form = view('larapay::idpay-form', [ 69 | 'endPoint' => strtr($this->getEndPoint(), ['{order-id}' => $authority]), 70 | 'submitLabel' => !empty($this->submit_label) ? $this->submit_label : trans("larapay::larapay.goto_gate"), 71 | 'autoSubmit' => boolval($this->auto_submit), 72 | ]); 73 | 74 | return $form->__toString(); 75 | } 76 | 77 | /** 78 | * @return string 79 | * @throws Exception 80 | * @throws \PhpMonsters\Larapay\Adapter\Exception 81 | */ 82 | protected function requestToken(): string 83 | { 84 | if ($this->getTransaction()->checkForRequestToken() === false) { 85 | throw new Exception('larapay::larapay.could_not_request_payment'); 86 | } 87 | 88 | $this->checkRequiredParameters([ 89 | 'order_id', 90 | 'amount', 91 | 'redirect_url', 92 | ]); 93 | 94 | $sendParams = [ 95 | 'order_id' => $this->getTransaction()->bank_order_id, 96 | 'amount' => intval($this->amount), 97 | 'desc' => $this->description ? $this->description : '', 98 | 'mail' => $this->email ? $this->email : '', 99 | 'phone' => $this->mobile ? $this->mobile : '', 100 | 'callback' => $this->redirect_url, 101 | ]; 102 | 103 | $header = [ 104 | 'Content-Type: application/json', 105 | 'X-API-KEY:'.$this->merchant_id, 106 | 'X-SANDBOX:'.$this->getSandbox() 107 | ]; 108 | try { 109 | XLog::debug('PaymentRequest call', $sendParams); 110 | $ch = curl_init(); 111 | curl_setopt($ch, CURLOPT_URL, $this->WSDL); 112 | curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($sendParams)); 113 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 114 | curl_setopt($ch, CURLOPT_HTTPHEADER, $header); 115 | $response = curl_exec($ch); 116 | $ch_error = curl_error($ch); 117 | curl_close($ch); 118 | $result = json_decode($response); 119 | 120 | if (isset($result->error_code)) { 121 | throw new Exception($result->error_code); 122 | } 123 | 124 | XLog::info('PaymentRequest response', $this->obj2array($result)); 125 | $this->getTransaction()->setGatewayToken(strval($result->id)); // update transaction reference id 126 | return $result->id; 127 | } catch (\Exception $e) { 128 | throw new Exception($e->getMessage()); 129 | }; 130 | } 131 | 132 | public function getSandbox(): string 133 | { 134 | if (config('larapay.mode') === 'production') { 135 | return "0"; 136 | } else { 137 | return "1"; 138 | } 139 | } 140 | 141 | /** 142 | * @return bool 143 | * @throws Exception 144 | * @throws \PhpMonsters\Larapay\Adapter\Exception 145 | */ 146 | protected function verifyTransaction(): bool 147 | { 148 | if ($this->getTransaction()->checkForVerify() === false) { 149 | throw new Exception('larapay::larapay.could_not_verify_payment'); 150 | } 151 | 152 | $this->checkRequiredParameters([ 153 | 'merchant_id', 154 | ]); 155 | 156 | $sendParams = [ 157 | 'id' => $this->getTransaction()->gate_refid, 158 | 'order_id' => $this->getTransaction()->bank_order_id, 159 | ]; 160 | 161 | $header = [ 162 | 'Content-Type: application/json', 163 | 'X-API-KEY:'.$this->merchant_id, 164 | 'X-SANDBOX:'.$this->getSandbox() 165 | ]; 166 | 167 | try { 168 | $ch = curl_init(); 169 | curl_setopt($ch, CURLOPT_URL, $this->endPointVerify); 170 | curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($sendParams)); 171 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 172 | curl_setopt($ch, CURLOPT_HTTPHEADER, $header); 173 | $response = curl_exec($ch); 174 | $ch_error = curl_error($ch); 175 | curl_close($ch); 176 | XLog::debug('PaymentVerification call', $sendParams); 177 | $result = json_decode($response); 178 | XLog::info('PaymentVerification response', $this->obj2array($result)); 179 | 180 | if (isset($result->status)) { 181 | if ($result->status == 100 || $result->status == 101) { 182 | $this->getTransaction()->setVerified(); 183 | $this->getTransaction()->setReferenceId((string) $result->id); 184 | return true; 185 | } else { 186 | throw new Exception($result->status); 187 | } 188 | } else { 189 | throw new Exception($result->error_code); 190 | } 191 | } catch (\Exception $e) { 192 | throw new Exception($e->getMessage()); 193 | } 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /src/Adapter/Idpay/Exception.php: -------------------------------------------------------------------------------- 1 | getTransaction()->checkForRequestToken() === false) { 32 | throw new Exception('larapay::larapay.could_not_request_payment'); 33 | } 34 | 35 | $this->checkRequiredParameters([ 36 | 'terminal_id', 37 | 'username', 38 | 'password', 39 | 'order_id', 40 | 'amount', 41 | 'redirect_url', 42 | ]); 43 | 44 | $sendParams = [ 45 | 'terminalId' => intval($this->terminal_id), 46 | 'userName' => $this->username, 47 | 'userPassword' => $this->password, 48 | 'orderId' => intval($this->order_id), 49 | 'amount' => intval($this->amount), 50 | 'localDate' => $this->local_date ? $this->local_date : date('Ymd'), 51 | 'localTime' => $this->local_time ? $this->local_time : date('His'), 52 | 'additionalData' => $this->additional_data ? $this->additional_data : '', 53 | 'callBackUrl' => $this->redirect_url, 54 | 'payerId' => intval($this->payer_id), 55 | ]; 56 | 57 | try { 58 | $soapClient = $this->getSoapClient(); 59 | 60 | XLog::debug('bpPayRequest call', $sendParams); 61 | 62 | $response = $soapClient->bpPayRequest($sendParams); 63 | 64 | if (isset($response->return)) { 65 | XLog::info('bpPayRequest response', ['return' => $response->return]); 66 | 67 | $response = explode(',', $response->return); 68 | 69 | if ($response[0] == 0) { 70 | $this->getTransaction()->setGatewayToken(strval($response[1])); // update transaction reference id 71 | 72 | return $response[1]; 73 | } else { 74 | throw new Exception($response[0]); 75 | } 76 | } else { 77 | throw new Exception('larapay::larapay.invalid_response'); 78 | } 79 | } catch (SoapFault $e) { 80 | throw new Exception('SoapFault: ' . $e->getMessage() . ' #' . $e->getCode(), $e->getCode()); 81 | } 82 | } 83 | 84 | /** 85 | * @return string 86 | * @throws Exception 87 | */ 88 | protected function generateForm(): string 89 | { 90 | $refId = $this->requestToken(); 91 | 92 | $form = view('larapay::mellat-form', [ 93 | 'endPoint' => $this->getEndPoint(), 94 | 'refId' => $refId, 95 | 'submitLabel' => !empty($this->submit_label) ? $this->submit_label : trans("larapay::larapay.goto_gate"), 96 | 'autoSubmit' => boolval($this->auto_submit), 97 | ]); 98 | 99 | return $form->__toString(); 100 | } 101 | 102 | /** 103 | * @return array 104 | * @throws Exception 105 | */ 106 | public function formParams(): array 107 | { 108 | $refId = $this->requestToken(); 109 | 110 | return [ 111 | 'endPoint' => $this->getEndPoint(), 112 | 'refId' => $refId, 113 | ]; 114 | } 115 | 116 | /** 117 | * @return bool 118 | * @throws Exception 119 | * @throws \PhpMonsters\Larapay\Adapter\Exception 120 | */ 121 | protected function verifyTransaction() 122 | { 123 | if ($this->getTransaction()->checkForVerify() === false) { 124 | throw new Exception('larapay::larapay.could_not_verify_payment'); 125 | } 126 | 127 | $this->checkRequiredParameters([ 128 | 'terminal_id', 129 | 'username', 130 | 'password', 131 | 'RefId', 132 | 'ResCode', 133 | 'SaleOrderId', 134 | 'SaleReferenceId', 135 | 'CardHolderInfo', 136 | 'CardHolderPan', 137 | ]); 138 | 139 | $sendParams = [ 140 | 'terminalId' => intval($this->terminal_id), 141 | 'userName' => $this->username, 142 | 'userPassword' => $this->password, 143 | 'orderId' => intval($this->SaleOrderId), // same as SaleOrderId 144 | 'saleOrderId' => intval($this->SaleOrderId), 145 | 'saleReferenceId' => intval($this->SaleReferenceId), 146 | ]; 147 | 148 | $this->getTransaction()->setCardNumber(strval($this->CardHolderInfo)); 149 | 150 | try { 151 | $soapClient = $this->getSoapClient(); 152 | 153 | XLog::debug('bpVerifyRequest call', $sendParams); 154 | 155 | //$response = $soapClient->__soapCall('bpVerifyRequest', $sendParams); 156 | $response = $soapClient->bpVerifyRequest($sendParams); 157 | 158 | if (isset($response->return)) { 159 | XLog::info('bpVerifyRequest response', ['return' => $response->return]); 160 | 161 | if ($response->return != '0') { 162 | throw new Exception($response->return); 163 | } else { 164 | $this->getTransaction()->setVerified(); 165 | 166 | return true; 167 | } 168 | } else { 169 | throw new Exception('larapay::larapay.invalid_response'); 170 | } 171 | 172 | } catch (SoapFault $e) { 173 | 174 | throw new Exception('SoapFault: ' . $e->getMessage() . ' #' . $e->getCode(), $e->getCode()); 175 | } 176 | } 177 | 178 | /** 179 | * @return bool 180 | * @throws Exception 181 | * @throws \PhpMonsters\Larapay\Adapter\Exception 182 | */ 183 | public function inquiryTransaction() 184 | { 185 | if ($this->getTransaction()->checkForInquiry() === false) { 186 | throw new Exception('larapay::larapay.could_not_inquiry_payment'); 187 | } 188 | 189 | $this->checkRequiredParameters([ 190 | 'terminal_id', 191 | 'terminal_user', 192 | 'terminal_pass', 193 | 'RefId', 194 | 'ResCode', 195 | 'SaleOrderId', 196 | 'SaleReferenceId', 197 | 'CardHolderInfo', 198 | ]); 199 | 200 | $sendParams = [ 201 | 'terminalId' => intval($this->terminal_id), 202 | 'userName' => $this->username, 203 | 'userPassword' => $this->password, 204 | 'orderId' => intval($this->SaleOrderId), // same as SaleOrderId 205 | 'saleOrderId' => intval($this->SaleOrderId), 206 | 'saleReferenceId' => intval($this->SaleReferenceId), 207 | ]; 208 | 209 | $this->getTransaction()->setCardNumber(strval($this->CardHolderInfo)); 210 | 211 | try { 212 | $soapClient = $this->getSoapClient(); 213 | 214 | XLog::debug('bpInquiryRequest call', $sendParams); 215 | //$response = $soapClient->__soapCall('bpInquiryRequest', $sendParams); 216 | $response = $soapClient->bpInquiryRequest($sendParams); 217 | 218 | if (isset($response->return)) { 219 | XLog::info('bpInquiryRequest response', ['return' => $response->return]); 220 | if ($response->return != '0') { 221 | throw new Exception($response->return); 222 | } else { 223 | $this->getTransaction()->setVerified(); 224 | 225 | return true; 226 | } 227 | } else { 228 | throw new Exception('larapay::larapay.invalid_response'); 229 | } 230 | 231 | } catch (SoapFault $e) { 232 | 233 | throw new Exception('SoapFault: ' . $e->getMessage() . ' #' . $e->getCode(), $e->getCode()); 234 | } 235 | } 236 | 237 | /** 238 | * Send settle request 239 | * 240 | * @return bool 241 | * 242 | * @throws Exception 243 | * @throws \PhpMonsters\Larapay\Adapter\Exception 244 | */ 245 | protected function settleTransaction() 246 | { 247 | if ($this->getTransaction()->checkForAfterVerify() === false) { 248 | throw new Exception('larapay::larapay.could_not_settle_payment'); 249 | } 250 | 251 | $this->checkRequiredParameters([ 252 | 'terminal_id', 253 | 'username', 254 | 'password', 255 | 'RefId', 256 | 'ResCode', 257 | 'SaleOrderId', 258 | 'SaleReferenceId', 259 | 'CardHolderInfo', 260 | ]); 261 | 262 | $sendParams = [ 263 | 'terminalId' => intval($this->terminal_id), 264 | 'userName' => $this->username, 265 | 'userPassword' => $this->password, 266 | 'orderId' => intval($this->SaleOrderId), // same as orderId 267 | 'saleOrderId' => intval($this->SaleOrderId), 268 | 'saleReferenceId' => intval($this->SaleReferenceId), 269 | ]; 270 | 271 | try { 272 | $soapClient = $this->getSoapClient(); 273 | 274 | XLog::debug('bpSettleRequest call', $sendParams); 275 | //$response = $soapClient->__soapCall('bpSettleRequest', $sendParams); 276 | $response = $soapClient->bpSettleRequest($sendParams); 277 | 278 | if (isset($response->return)) { 279 | XLog::info('bpSettleRequest response', ['return' => $response->return]); 280 | 281 | if ($response->return == '0' || $response->return == '45') { 282 | $this->getTransaction()->setAfterVerified(); 283 | 284 | return true; 285 | } else { 286 | throw new Exception($response->return); 287 | } 288 | } else { 289 | throw new Exception('larapay::larapay.invalid_response'); 290 | } 291 | 292 | } catch (\SoapFault $e) { 293 | throw new Exception('SoapFault: ' . $e->getMessage() . ' #' . $e->getCode(), $e->getCode()); 294 | } 295 | 296 | } 297 | 298 | /** 299 | * @return bool 300 | * @throws Exception 301 | * @throws \PhpMonsters\Larapay\Adapter\Exception 302 | */ 303 | protected function reverseTransaction(): bool 304 | { 305 | if ($this->reverseSupport === false || $this->getTransaction()->checkForReverse() === false) { 306 | throw new Exception('larapay::larapay.could_not_reverse_payment'); 307 | } 308 | 309 | $this->checkRequiredParameters([ 310 | 'terminal_id', 311 | 'username', 312 | 'password', 313 | 'RefId', 314 | 'ResCode', 315 | 'SaleOrderId', 316 | 'SaleReferenceId', 317 | 'CardHolderInfo', 318 | ]); 319 | 320 | $sendParams = [ 321 | 'terminalId' => intval($this->terminal_id), 322 | 'userName' => $this->username, 323 | 'userPassword' => $this->password, 324 | 'orderId' => intval($this->SaleOrderId), // same as orderId 325 | 'saleOrderId' => intval($this->SaleOrderId), 326 | 'saleReferenceId' => intval($this->SaleReferenceId), 327 | ]; 328 | 329 | try { 330 | $soapClient = $this->getSoapClient(); 331 | 332 | XLog::debug('bpReversalRequest call', $sendParams); 333 | //$response = $soapClient->__soapCall('bpReversalRequest', $sendParams); 334 | $response = $soapClient->bpReversalRequest($sendParams); 335 | 336 | XLog::info('bpReversalRequest response', ['return' => $response->return]); 337 | 338 | if (isset($response->return)) { 339 | if ($response->return == '0' || $response->return == '45') { 340 | $this->getTransaction()->setRefunded(); 341 | 342 | return true; 343 | } else { 344 | throw new Exception($response->return); 345 | } 346 | } else { 347 | throw new Exception('larapay::larapay.invalid_response'); 348 | } 349 | 350 | } catch (SoapFault $e) { 351 | throw new Exception('SoapFault: ' . $e->getMessage() . ' #' . $e->getCode(), $e->getCode()); 352 | } 353 | } 354 | 355 | 356 | /** 357 | * @return bool 358 | */ 359 | public function canContinueWithCallbackParameters(): bool 360 | { 361 | if ($this->ResCode === "0" || $this->ResCode === 0) { 362 | return true; 363 | } 364 | 365 | return false; 366 | } 367 | 368 | public function getGatewayReferenceId(): string 369 | { 370 | $this->checkRequiredParameters([ 371 | 'RefId', 372 | ]); 373 | 374 | return strval($this->RefId); 375 | } 376 | 377 | public function afterVerify(): bool 378 | { 379 | return $this->settleTransaction(); 380 | } 381 | } 382 | -------------------------------------------------------------------------------- /src/Adapter/Mellat/Exception.php: -------------------------------------------------------------------------------- 1 | requestToken(); 32 | 33 | return [ 34 | 'endPoint' => strtr($this->endPointForm, ['{trans_id}' => $authority]), 35 | ]; 36 | } 37 | 38 | /** 39 | * @return bool 40 | */ 41 | public function canContinueWithCallbackParameters(): bool 42 | { 43 | if (!empty($this->parameters['trans_id'])) { 44 | return true; 45 | } 46 | 47 | return false; 48 | } 49 | 50 | /** 51 | * @return string 52 | * @throws \PhpMonsters\Larapay\Adapter\Exception 53 | */ 54 | public function getGatewayReferenceId(): string 55 | { 56 | $this->checkRequiredParameters([ 57 | 'trans_id', 58 | ]); 59 | 60 | return strval($this->trans_id); 61 | } 62 | 63 | /** 64 | * @return string 65 | * @throws Exception 66 | * @throws \PhpMonsters\Larapay\Adapter\Exception 67 | */ 68 | protected function generateForm(): string 69 | { 70 | $authority = $this->requestToken(); 71 | 72 | $form = view('larapay::nextpay-form', [ 73 | 'endPoint' => strtr($this->endPointForm, ['{trans_id}' => $authority]), 74 | 'submitLabel' => !empty($this->submit_label) ? $this->submit_label : trans("larapay::larapay.goto_gate"), 75 | 'autoSubmit' => true, 76 | ]); 77 | return $form->__toString(); 78 | } 79 | 80 | /** 81 | * @return string 82 | * @throws Exception 83 | * @throws \PhpMonsters\Larapay\Adapter\Exception 84 | */ 85 | protected function requestToken(): string 86 | { 87 | if ($this->getTransaction()->checkForRequestToken() === false) { 88 | throw new Exception('larapay::larapay.could_not_request_payment'); 89 | } 90 | 91 | $this->checkRequiredParameters([ 92 | 'api_key', 93 | 'amount', 94 | 'redirect_url', 95 | 'order_id', 96 | ]); 97 | 98 | $sendParams = [ 99 | 'api_key' => $this->api_key, 100 | 'amount' => intval($this->amount), 101 | 'order_id' => ($this->order_id), 102 | 'payer_desc' => $this->description ? $this->description : '', 103 | 'customer_phone' => $this->mobile ? $this->mobile : '', 104 | 'callback_uri' => $this->redirect_url, 105 | ]; 106 | 107 | try { 108 | XLog::debug('PaymentRequest call', $sendParams); 109 | $result = Helper::post2https($sendParams, $this->endPoint); 110 | $resultObj = json_decode($result); 111 | 112 | XLog::info('PaymentRequest response', $this->obj2array($resultObj)); 113 | 114 | if (isset($resultObj->code)) { 115 | if ($resultObj->code == -1) { 116 | $this->getTransaction()->setGatewayToken(strval($resultObj->trans_id)); // update transaction reference id 117 | return $resultObj->trans_id; 118 | } else { 119 | throw new Exception('larapay::larapay.nextpay.errors.error_'.$resultObj->code); 120 | } 121 | } else { 122 | throw new Exception('larapay::larapay.invalid_response'); 123 | } 124 | } catch (\Exception $e) { 125 | throw new Exception('Nextpay Fault: '.$e->getMessage().' #'.$e->getCode(), $e->getCode()); 126 | } 127 | } 128 | 129 | /** 130 | * @return bool 131 | * @throws Exception 132 | * @throws \PhpMonsters\Larapay\Adapter\Exception 133 | */ 134 | protected function verifyTransaction(): bool 135 | { 136 | if ($this->getTransaction()->checkForVerify() === false) { 137 | throw new Exception('larapay::larapay.could_not_verify_payment'); 138 | } 139 | 140 | $this->checkRequiredParameters([ 141 | 'api_key', 142 | 'trans_id', 143 | 'amount' 144 | ]); 145 | 146 | $sendParams = [ 147 | 'api_key' => $this->api_key, 148 | 'trans_id' => $this->trans_id, 149 | 'amount' => $this->amount, 150 | ]; 151 | 152 | try { 153 | XLog::debug('PaymentVerification call', $sendParams); 154 | $result = Helper::post2https($sendParams, $this->endPointVerify); 155 | $response = json_decode($result); 156 | XLog::info('PaymentVerification response', $this->obj2array($response)); 157 | if (isset($response->code, $response->Shaparak_Ref_Id)) { 158 | if ($response->code == 0) { 159 | $this->getTransaction()->setVerified(); 160 | $this->getTransaction()->setReferenceId(strval($response->Shaparak_Ref_Id)); // update transaction reference id 161 | return true; 162 | } else { 163 | throw new Exception('larapay::larapay.nextpay.errors.error_'.$response->code); 164 | } 165 | } else { 166 | throw new Exception('larapay::larapay.invalid_response'); 167 | } 168 | } catch (\Exception $e) { 169 | throw new Exception('Nextpay Fault: '.$e->getMessage().' #'.$e->getCode(), $e->getCode()); 170 | } 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /src/Adapter/Nextpay/Exception.php: -------------------------------------------------------------------------------- 1 | 'SOAP_1_1', 38 | 'cache_wsdl' => WSDL_CACHE_BOTH, 39 | 'encoding' => 'UTF-8', 40 | ); 41 | 42 | 43 | public function init() 44 | { 45 | ini_set("default_socket_timeout", strval(config('larapay.parsian.timeout'))); 46 | } 47 | 48 | /** 49 | * @return array 50 | * @throws Exception 51 | * @throws \PhpMonsters\Larapay\Adapter\Exception 52 | */ 53 | protected function requestToken() 54 | { 55 | if ($this->getTransaction()->checkForRequestToken() == false) { 56 | throw new Exception('larapay::larapay.could_not_request_payment'); 57 | } 58 | 59 | 60 | $this->checkRequiredParameters([ 61 | 'pin', 62 | 'order_id', 63 | 'amount', 64 | 'redirect_url', 65 | ]); 66 | 67 | 68 | $sendParams = [ 69 | 'LoginAccount' => $this->pin, 70 | 'Amount' => intval($this->amount), 71 | 'OrderId' => intval($this->order_id), 72 | 'CallBackUrl' => $this->redirect_url, 73 | 'AdditionalData' => $this->additional_data ?? '', 74 | 'Originator' => $this->originator ?? '', 75 | ]; 76 | 77 | 78 | if (!empty($this->sharing) && is_array($this->sharing)) { 79 | return $this->requestTokenWithSharing($sendParams); 80 | } else { 81 | return $this->requestTokenWithoutSharing($sendParams); 82 | } 83 | } 84 | 85 | /** 86 | * @param array $sendParams 87 | * 88 | * @return mixed 89 | * @throws Exception 90 | */ 91 | private function requestTokenWithoutSharing($sendParams) 92 | { 93 | for ($i = 1; $i <= 3; $i++) { 94 | try { 95 | 96 | $this->requestType = 'request'; 97 | $soapClient = $this->getSoapClient(); 98 | 99 | XLog::debug('SalePaymentRequest call', $sendParams); 100 | 101 | $response = $soapClient->SalePaymentRequest(array("requestData" => $sendParams)); 102 | 103 | XLog::debug('SalePaymentRequest response', $this->obj2array($response)); 104 | 105 | if (isset($response->SalePaymentRequestResult->Status, $response->SalePaymentRequestResult->Token)) { 106 | if ($response->SalePaymentRequestResult->Status == 0) { 107 | $this->getTransaction()->setGatewayToken(strval($response->SalePaymentRequestResult->Token)); // update transaction reference id 108 | 109 | return $response->SalePaymentRequestResult->Token; 110 | } else { 111 | if ($i == 3) { 112 | throw new Exception($response->SalePaymentRequestResult->Status); 113 | } 114 | usleep(500); 115 | } 116 | } else { 117 | if ($i == 3) { 118 | throw new Exception('larapay::parsian.errors.invalid_response'); 119 | } 120 | usleep(500); 121 | } 122 | 123 | } catch (SoapFault $e) { 124 | if ($i == 3) { 125 | throw new Exception('SoapFault: ' . $e->getMessage() . ' #' . $e->getCode(), $e->getCode()); 126 | } 127 | usleep(500); 128 | } 129 | } 130 | } 131 | 132 | /** 133 | * @param array $sendParams 134 | * 135 | * @return mixed 136 | * @throws Exception 137 | */ 138 | private function requestTokenWithSharing($sendParams) 139 | { 140 | if (!isset($this->sharing['type']) || !isset($this->sharing['data'])) { 141 | throw new Exception('larapay::larapay.invalid_sharing_data'); 142 | } 143 | 144 | 145 | if ($this->sharing['type'] == Sharing::DYNAMIC) { 146 | // dynamic sharing 147 | $method = 'MultiplexedSaleWithIBANPaymentRequest'; 148 | $respo = 'MultiplexedSaleWithIBANPaymentResult'; 149 | foreach ($this->sharing['data'] as $item) { 150 | $sendParams['MultiplexedAccounts']['Account'][] = [ 151 | 'Amount' => $item->share, 152 | 'PayId' => $item->pay_id ?? '', 153 | 'IBAN' => $item->iban, 154 | ]; 155 | } 156 | } else { 157 | // fix sharing 158 | $method = 'MultiplexedSalePaymentRequest'; 159 | $respo = 'MultiplexedSalePaymentResult'; 160 | foreach ($this->sharing['data'] as $item) { 161 | $sendParams['MultiplexedAccounts']['Account'][] = [ 162 | 'Amount' => $item->share, 163 | 'PayId' => $item->pay_id ?? '', 164 | ]; 165 | } 166 | } 167 | 168 | try { 169 | $this->requestType = 'multiplex'; 170 | $soapClient = $this->getSoapClient(); 171 | 172 | XLog::debug("{$method} call", $sendParams); 173 | 174 | $response = $soapClient->$method(array("requestData" => $sendParams)); 175 | 176 | XLog::debug("{$method} response", $this->obj2array($response)); 177 | 178 | if (isset($response->$respo->Status, $response->$respo->Token)) { 179 | if ($response->$respo->Status == 0) { 180 | $this->getTransaction()->setGatewayToken(strval($response->$respo->Token)); // update transaction reference id 181 | 182 | return $response->$respo->Token; 183 | } else { 184 | throw new Exception($response->$respo->Status); 185 | } 186 | } else { 187 | throw new Exception('larapay::parsian.errors.invalid_response'); 188 | } 189 | } catch (SoapFault $e) { 190 | throw new Exception('SoapFault: ' . $e->getMessage() . ' #' . $e->getCode(), $e->getCode()); 191 | } 192 | } 193 | 194 | /** 195 | * @return string 196 | * @throws Exception 197 | * @throws \PhpMonsters\Larapay\Adapter\Exception 198 | */ 199 | protected function generateForm(): string 200 | { 201 | $authority = $this->requestToken(); 202 | 203 | $form = view('larapay::parsian-form', [ 204 | 'endPoint' => $this->getEndPoint(), 205 | 'refId' => $authority, 206 | 'submitLabel' => !empty($this->submit_label) ? $this->submit_label : trans("larapay::larapay.goto_gate"), 207 | 'autoSubmit' => boolval($this->auto_submit), 208 | ]); 209 | 210 | return $form->__toString(); 211 | } 212 | 213 | /** 214 | * @return array 215 | * @throws Exception 216 | * @throws \PhpMonsters\Larapay\Adapter\Exception 217 | */ 218 | public function formParams(): array 219 | { 220 | $authority = $this->requestToken(); 221 | 222 | return [ 223 | 'endPoint' => $this->getEndPoint(), 224 | 'refId' => $authority, 225 | ]; 226 | } 227 | 228 | /** 229 | * @return bool 230 | * @throws Exception 231 | * @throws \PhpMonsters\Larapay\Adapter\Exception 232 | */ 233 | protected function verifyTransaction(): bool 234 | { 235 | if ($this->getTransaction()->checkForVerify() == false) { 236 | throw new Exception('larapay::larapay.could_not_verify_payment'); 237 | } 238 | $this->requestType = 'confirm'; 239 | 240 | $this->checkRequiredParameters([ 241 | 'Token', 242 | ]); 243 | 244 | if ($this->status !== '0') { 245 | throw new Exception('larapay::parsian.errors.could_not_continue_with_non0_rs'); 246 | } 247 | 248 | $sendParams = [ 249 | 'LoginAccount' => $this->pin, 250 | 'Token' => $this->Token, 251 | ]; 252 | 253 | 254 | try { 255 | $soapClient = $this->getSoapClient(); 256 | 257 | 258 | XLog::debug('ConfirmPayment call', $sendParams); 259 | 260 | $response = $soapClient->ConfirmPayment(array("requestData" => $sendParams)); 261 | 262 | XLog::debug('ConfirmPayment response', $this->obj2array($response)); 263 | 264 | if (isset($response->ConfirmPaymentResult)) { 265 | if ($response->ConfirmPaymentResult->Status == 0) { 266 | $this->getTransaction()->setVerified(); 267 | 268 | return true; 269 | } else { 270 | throw new Exception($response->ConfirmPaymentResult->Status); 271 | } 272 | } else { 273 | throw new Exception('larapay::parsian.errors.invalid_response'); 274 | } 275 | 276 | } catch (SoapFault $e) { 277 | throw new Exception('SoapFault: ' . $e->getMessage() . ' #' . $e->getCode(), $e->getCode()); 278 | } 279 | } 280 | 281 | 282 | /** 283 | * @return bool 284 | * @throws Exception 285 | * @throws \PhpMonsters\Larapay\Adapter\Exception 286 | */ 287 | protected function reverseTransaction(): bool 288 | { 289 | if ($this->reverseSupport == false || $this->getTransaction()->checkForReverse() == false) { 290 | throw new Exception('larapay::larapay.could_not_reverse_payment'); 291 | } 292 | 293 | $this->requestType = 'reversal'; 294 | 295 | 296 | $this->checkRequiredParameters([ 297 | 'Token', 298 | ]); 299 | 300 | $sendParams = [ 301 | 'LoginAccount' => $this->pin, 302 | 'Token' => $this->Token, 303 | ]; 304 | 305 | try { 306 | $soapClient = $this->getSoapClient(); 307 | XLog::debug('ReversalRequest call', $sendParams); 308 | 309 | $response = $soapClient->ReversalRequest(array("requestData" => $sendParams)); 310 | 311 | XLog::debug('ReversalRequest response', $this->obj2array($response)); 312 | 313 | if (isset($response->ReversalRequestResult->Status)) { 314 | if ($response->ReversalRequestResult->Status == 0) { 315 | $this->getTransaction()->setRefunded(); 316 | 317 | return true; 318 | } else { 319 | throw new Exception($response->ReversalRequestResult->Status); 320 | } 321 | } else { 322 | throw new Exception('larapay::parsian.errors.invalid_response'); 323 | } 324 | } catch (SoapFault $e) { 325 | throw new Exception('SoapFault: ' . $e->getMessage() . ' #' . $e->getCode(), $e->getCode()); 326 | } 327 | } 328 | 329 | public function getGatewayReferenceId(): string 330 | { 331 | $this->checkRequiredParameters([ 332 | 'Token', 333 | ]); 334 | 335 | return strval($this->Token); 336 | } 337 | 338 | 339 | protected function getWSDL(): string 340 | { 341 | 342 | $type = $this->requestType; 343 | 344 | switch ($type) { 345 | case 'request': 346 | if (config('larapay.mode') == 'production') { 347 | return $this->WSDLSale; 348 | } else { 349 | return $this->testWSDLSale; 350 | } 351 | break; 352 | case 'confirm': 353 | if (config('larapay.mode') == 'production') { 354 | return $this->WSDLConfirm; 355 | } else { 356 | return $this->testWSDLConfirm; 357 | } 358 | break; 359 | case 'reversal': 360 | if (config('larapay.mode') == 'production') { 361 | return $this->WSDLReversal; 362 | } else { 363 | return $this->testWSDLReversal; 364 | } 365 | break; 366 | case 'multiplex': 367 | if (config('larapay.mode') == 'production') { 368 | return $this->WSDLMultiplex; 369 | } else { 370 | return $this->testWSDLMultiplex; 371 | } 372 | break; 373 | } 374 | } 375 | } 376 | -------------------------------------------------------------------------------- /src/Adapter/Parsian/Exception.php: -------------------------------------------------------------------------------- 1 | checkRequiredParameters([ 37 | 'amount', 38 | 'order_id', 39 | 'redirect_url' 40 | ]); 41 | 42 | $processor = new RSAProcessor(config('larapay.pasargad.certificate_path'), RSAKeyType::XMLFile); 43 | 44 | $url = $this->getEndPoint(); 45 | $redirectUrl = $this->redirect_url; 46 | $invoiceNumber = $this->order_id; 47 | $amount = $this->amount; 48 | $terminalCode = config('larapay.pasargad.terminalId'); 49 | $merchantCode = config('larapay.pasargad.merchantId'); 50 | $timeStamp = date("Y/m/d H:i:s"); 51 | $invoiceDate = date("Y/m/d H:i:s"); 52 | $action = 1003; // sell code 53 | $submitLabel = !empty($this->submit_label) ? $this->submit_label : trans("larapay::larapay.goto_gate"); 54 | $autoSubmit = boolval($this->auto_submit); 55 | 56 | $data = "#" . $merchantCode . "#" . $terminalCode . "#" . $invoiceNumber . "#" . $invoiceDate . "#" . $amount . "#" . $redirectUrl . "#" . $action . "#" . $timeStamp . "#"; 57 | $data = sha1($data, true); 58 | $data = $processor->sign($data); // امضاي ديجيتال 59 | $sign = base64_encode($data); // base64_encode 60 | 61 | $form = view('larapay::pasargad-form')->with(compact( 62 | 'url', 63 | 'redirectUrl', 64 | 'invoiceNumber', 65 | 'invoiceDate', 66 | 'amount', 67 | 'terminalCode', 68 | 'merchantCode', 69 | 'timeStamp', 70 | 'action', 71 | 'sign', 72 | 'submitLabel', 73 | 'autoSubmit' 74 | )); 75 | 76 | return $form->__toString(); 77 | } 78 | 79 | /** 80 | * @return array 81 | * @throws Exception 82 | */ 83 | public function formParams(): array 84 | { 85 | $this->checkRequiredParameters([ 86 | 'amount', 87 | 'order_id', 88 | 'redirect_url' 89 | ]); 90 | 91 | $processor = new RSAProcessor(config('larapay.pasargad.certificate_path'), RSAKeyType::XMLFile); 92 | 93 | $url = $this->getEndPoint(); 94 | $redirectUrl = $this->redirect_url; 95 | $invoiceNumber = $this->order_id; 96 | $amount = $this->amount; 97 | $terminalCode = config('larapay.pasargad.terminalId'); 98 | $merchantCode = config('larapay.pasargad.merchantId'); 99 | $timeStamp = date("Y/m/d H:i:s"); 100 | $invoiceDate = date("Y/m/d H:i:s"); 101 | $action = 1003; // sell code 102 | 103 | $data = "#" . $merchantCode . "#" . $terminalCode . "#" . $invoiceNumber . "#" . $invoiceDate . "#" . $amount . "#" . $redirectUrl . "#" . $action . "#" . $timeStamp . "#"; 104 | $data = sha1($data, true); 105 | $data = $processor->sign($data); // امضاي ديجيتال 106 | $sign = base64_encode($data); // base64_encode 107 | 108 | return [ 109 | 'url' => $url, 110 | 'redirectUrl' => $redirectUrl, 111 | 'invoiceNumber' => $invoiceNumber, 112 | 'invoiceDate' => $invoiceDate, 113 | 'amount' => $amount, 114 | 'terminalCode' => $terminalCode, 115 | 'merchantCode' => $merchantCode, 116 | 'timeStamp' => $timeStamp, 117 | 'action' => $action, 118 | 'sign' => $sign, 119 | ]; 120 | } 121 | 122 | // public function inquiryTransaction () 123 | // { 124 | // 125 | // } 126 | 127 | /** 128 | * @return bool 129 | * @throws Exception 130 | */ 131 | protected function verifyTransaction(): bool 132 | { 133 | $this->checkRequiredParameters([ 134 | 'iN', 135 | 'iD', 136 | 'tref', 137 | ]); 138 | 139 | // update transaction reference number 140 | if (!empty($this->tref)) { 141 | $this->setInvoiceReferenceId($this->tref); // update transaction reference id 142 | } 143 | 144 | $processor = new RSAProcessor(config('larapay.pasargad.certificate_path'), RSAKeyType::XMLFile); 145 | 146 | $terminalCode = config('larapay.pasargad.terminalId'); 147 | $merchantCode = config('larapay.pasargad.merchantId'); 148 | $invoiceNumber = $this->iN; 149 | $invoiceDate = $this->iD; 150 | $amount = $this->getTransaction()->getPayableAmount(); 151 | $timeStamp = date("Y/m/d H:i:s"); 152 | 153 | $data = "#" . $merchantCode . "#" . $terminalCode . "#" . $invoiceNumber . "#" . $invoiceDate . "#" . $amount . "#" . $timeStamp . "#"; 154 | XLog::debug('pasargad generated sign string: ' . $data); 155 | $data = sha1($data, true); 156 | $data = $processor->sign($data); // امضاي ديجيتال 157 | $sign = base64_encode($data); // base64_encode 158 | XLog::debug('pasargad generated hash: ' . $sign); 159 | 160 | $parameters = compact( 161 | 'terminalCode', 162 | 'merchantCode', 163 | 'invoiceNumber', 164 | 'invoiceDate', 165 | 'amount', 166 | 'timeStamp', 167 | 'sign' 168 | ); 169 | 170 | $result = Helper::post2https($parameters , $this->getVerifyUrl()); 171 | 172 | $array = Helper::parseXML($result, [ 173 | 'invoiceNumber' => $this->iN, 174 | 'invoiceDate' => $this->iD 175 | ]); 176 | 177 | XLog::debug('pasargad verify parseXML result', $array); 178 | 179 | if ($array['actionResult']['result'] != "True") { 180 | throw new Exception('larapay::larapay.verification_failed'); 181 | } else { 182 | $this->getTransaction()->setVerified(); 183 | return true; 184 | } 185 | } 186 | 187 | /** 188 | * @return bool 189 | * @throws Exception 190 | */ 191 | protected function reverseTransaction(): bool 192 | { 193 | $this->checkRequiredParameters([ 194 | 'iN', 195 | 'iD', 196 | 'tref', 197 | ]); 198 | 199 | // update transaction reference number 200 | if (!empty($this->tref)) { 201 | $this->setInvoiceReferenceId($this->tref); // update transaction reference id 202 | } 203 | 204 | $processor = new RSAProcessor(config('larapay.pasargad.certificate_path'), RSAKeyType::XMLFile); 205 | 206 | $terminalCode = config('larapay.pasargad.terminalId'); 207 | $merchantCode = config('larapay.pasargad.merchantId'); 208 | $invoiceNumber = $this->iN; 209 | $invoiceDate = $this->iD; 210 | $amount = $this->getTransaction()->getPayableAmount(); 211 | $timeStamp = date("Y/m/d H:i:s"); 212 | $action = 1004; // reverse code 213 | 214 | $data = "#" . $merchantCode . "#" . $terminalCode . "#" . $invoiceNumber . "#" . $invoiceDate . "#" . $amount . "#" . $action . "#" . $timeStamp . "#"; 215 | $data = sha1($data, true); 216 | $data = $processor->sign($data); // امضاي ديجيتال 217 | $sign = base64_encode($data); // base64_encode 218 | 219 | $parameters = compact( 220 | 'terminalCode', 221 | 'merchantCode', 222 | 'invoiceNumber', 223 | 'invoiceDate', 224 | 'amount', 225 | 'timeStamp', 226 | 'action', 227 | 'sign' 228 | ); 229 | 230 | $result = Helper::post2https($parameters , $this->getRefundUrl()); 231 | $array = Helper::parseXML($result, [ 232 | 'invoiceNumber' => $this->iN, 233 | 'invoiceDate' => $this->iD 234 | ]); 235 | 236 | XLog::debug('pasargad refund parseXML result', $array); 237 | 238 | if ($array['actionResult']['result'] != "True") { 239 | throw new Exception('larapay::larapay.reversed_failed'); 240 | } else { 241 | $this->getTransaction()->setRefunded(); 242 | return true; 243 | } 244 | } 245 | 246 | /** 247 | * @return string 248 | */ 249 | protected function getVerifyUrl(): string 250 | { 251 | if (config('larapay.mode') == 'production') { 252 | return $this->verifyUrl; 253 | } else { 254 | return $this->testVerifyUrl; 255 | } 256 | } 257 | 258 | /** 259 | * @return string 260 | */ 261 | protected function getRefundUrl(): string 262 | { 263 | if (config('larapay.mode') == 'production') { 264 | return $this->refundUrl; 265 | } else { 266 | return $this->testRefundUrl; 267 | } 268 | } 269 | 270 | /** 271 | * @return string 272 | */ 273 | protected function getInquiryUrl(): string 274 | { 275 | if (config('larapay.mode') == 'production') { 276 | return $this->checkTransactionUrl; 277 | } else { 278 | return $this->testCheckTransactionUrl; 279 | } 280 | } 281 | 282 | /** 283 | * @return bool 284 | */ 285 | public function canContinueWithCallbackParameters(): bool 286 | { 287 | if (!empty($this->getParameter('tref'))) { 288 | return true; 289 | } 290 | return false; 291 | } 292 | 293 | 294 | public function getGatewayReferenceId(): string 295 | { 296 | $this->checkRequiredParameters([ 297 | 'tref', 298 | ]); 299 | 300 | return strval($this->tref); 301 | } 302 | } 303 | -------------------------------------------------------------------------------- /src/Adapter/Pasargad/Helper.php: -------------------------------------------------------------------------------- 1 | $val) { 27 | switch ($val['type']) { 28 | case 'open': 29 | array_push($hash_stack, $val['tag']); 30 | break; 31 | case 'close': 32 | array_pop($hash_stack); 33 | break; 34 | case 'complete': 35 | array_push($hash_stack, $val['tag']); 36 | if(!isset($val['value'])){ 37 | $val['value'] = $temp[$val['tag']]; 38 | } 39 | 40 | @eval("\$ret['" . implode($hash_stack, "']['") . "'] = '{$val['value']}';"); 41 | array_pop($hash_stack); 42 | break; 43 | } 44 | } 45 | 46 | return $ret; 47 | } 48 | 49 | 50 | /** 51 | * CURL POST TO HTTPS 52 | * 53 | * @param $fields_arr 54 | * @param $url 55 | * @return mixed 56 | */ 57 | public static function post2https($fields_arr, $url) 58 | { 59 | $fields_string = ''; 60 | //url-ify the data for the POST 61 | foreach ($fields_arr as $key => $value) { 62 | $fields_string .= $key . '=' . $value . '&'; 63 | } 64 | $fields_string = substr($fields_string, 0, -1); 65 | 66 | //open connection 67 | $ch = curl_init(); 68 | 69 | //set the url, number of POST vars, POST data 70 | curl_setopt($ch, CURLOPT_URL, $url); 71 | curl_setopt($ch, CURLOPT_POST, count($fields_arr)); 72 | curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string); 73 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); 74 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 75 | 76 | 77 | //execute post 78 | $res = curl_exec($ch); 79 | 80 | //close connection 81 | curl_close($ch); 82 | 83 | XLog::debug('pasargad call result: '. $res); 84 | return $res; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/Adapter/Pasargad/PasargadResult.php: -------------------------------------------------------------------------------- 1 | = 0; $i--) { 133 | $digit = ord($data[$i]); 134 | $part_res = bcmul($digit, $radix); 135 | $result = bcadd($result, $part_res); 136 | $radix = bcmul($radix, $base); 137 | } 138 | 139 | return $result; 140 | } 141 | 142 | public static function number_to_binary($number, $blocksize) 143 | { 144 | $base = "256"; 145 | $result = ""; 146 | $div = $number; 147 | while ($div > 0) { 148 | $mod = bcmod($div, $base); 149 | $div = bcdiv($div, $base); 150 | $result = chr($mod) . $result; 151 | } 152 | 153 | return str_pad($result, $blocksize, "\x00", STR_PAD_LEFT); 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /src/Adapter/Pasargad/RSAProcessor.php: -------------------------------------------------------------------------------- 1 | modulus = RSA::binary_to_number(base64_decode($xmlObj->Modulus)); 39 | $this->public_key = RSA::binary_to_number(base64_decode($xmlObj->Exponent)); 40 | $this->private_key = RSA::binary_to_number(base64_decode($xmlObj->D)); 41 | $this->key_length = strlen(base64_decode($xmlObj->Modulus)) * 8; 42 | } 43 | 44 | public function getPublicKey () 45 | { 46 | return $this->public_key; 47 | } 48 | 49 | public function getPrivateKey () 50 | { 51 | return $this->private_key; 52 | } 53 | 54 | public function getKeyLength (): int 55 | { 56 | return $this->key_length; 57 | } 58 | 59 | public function getModulus () 60 | { 61 | return $this->modulus; 62 | } 63 | 64 | public function encrypt ($data) 65 | { 66 | return base64_encode(RSA::rsa_encrypt($data, $this->public_key, $this->modulus, $this->key_length)); 67 | } 68 | 69 | public function decrypt ($data) 70 | { 71 | return RSA::rsa_decrypt($data, $this->private_key, $this->modulus, $this->key_length); 72 | } 73 | 74 | public function sign ($data) 75 | { 76 | return RSA::rsa_sign($data, $this->private_key, $this->modulus, $this->key_length); 77 | } 78 | 79 | public function verify ($data) 80 | { 81 | return RSA::rsa_verify($data, $this->public_key, $this->modulus, $this->key_length); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/Adapter/Pasargad/certificate.xml: -------------------------------------------------------------------------------- 1 | tCZiqDS5BVQQZDBUYbyeoP4rENN4mX5FZJjjMNfGbyzfzH45RY2/YsMaY0yI1jMCOpukvkUyl153tcn0LXhMCDdsEhhZPoKbPUGMniKtFGjs18rv/b5FFUUW1utgwoL8+WJqjOqhQGgvbja63X9+WMFP0nM3d8yudn9C/X55KyM=AQAB

5HXvmU4IfqUG2jFLSqi/BMEQ3x1NsUDvx3zN5O1p9yLLspJ4sqAt4RUkxzcGodYgBSdXsR9IGcPwjQfbx3a7nQ==

yd2hDCF/5Zqtz9DXjY1NRYGvBjTS4AQn83ERR46Y5eBSnLjpVjv6gPfARuhsUP44nikrQPvwPnjxQcOhJaOlvw==ztuqUplBP8qU5cN0dOlN7DQT3rFdw30Unv/2Pa5qIAc1gT72YmZ+pCrM3kSIkMicvY3d7NZyJkIv8MKI0ZZEUQ==QFLJ5YarLWubZPQEK4vSCornTY/5ff51CIKH4ghTOjS/vkbBu4PDL+NCNpYLJcfMHMG7kap2BEIfhjgjGk5KGw==WE6TqpcexQJwt9Mnp1FbeLtarBcFkXVdBauouFKHcbHCfQjA3IjUrGTxgSO74O/4QSKqaF2gnlL6GI7gKuGbzQ==czYtWDfHsFGv3fNOs+cGaB3E+xDTiw7HYGuquJz2qjk/s69x/zqFEKuIH8Ndq+eZYFQUCx+EGGxxENDkmYPa0z8wbfFI6JEHpxaLmQfpkkbSL1BJIp9Z5BNM2gy6jJqgbWwQPcN/4jpiMefHZWAqhMKqenUu1KIq1ZX6Bz5xKYk=
-------------------------------------------------------------------------------- /src/Adapter/PayIr/Exception.php: -------------------------------------------------------------------------------- 1 | requestToken(); 32 | 33 | return [ 34 | 'endPoint' => $this->endPointForm.$authority, 35 | ]; 36 | } 37 | 38 | /** 39 | * @return bool 40 | */ 41 | public function canContinueWithCallbackParameters(): bool 42 | { 43 | if (!empty($this->parameters['token'])) { 44 | return true; 45 | } 46 | 47 | return false; 48 | } 49 | 50 | /** 51 | * @return string 52 | * @throws \PhpMonsters\Larapay\Adapter\Exception 53 | */ 54 | public function getGatewayReferenceId(): string 55 | { 56 | $this->checkRequiredParameters([ 57 | 'token', 58 | ]); 59 | 60 | return strval($this->transId); 61 | } 62 | 63 | /** 64 | * @return string 65 | * @throws Exception 66 | * @throws \PhpMonsters\Larapay\Adapter\Exception 67 | */ 68 | protected function generateForm(): string 69 | { 70 | $authority = $this->requestToken(); 71 | 72 | $form = view('larapay::payir-form', [ 73 | 'endPoint' => $this->endPointForm.$authority, 74 | 'submitLabel' => !empty($this->submit_label) ? $this->submit_label : trans("larapay::larapay.goto_gate"), 75 | 'autoSubmit' => true, 76 | ]); 77 | return $form->__toString(); 78 | } 79 | 80 | /** 81 | * @return string 82 | * @throws Exception 83 | * @throws \PhpMonsters\Larapay\Adapter\Exception 84 | */ 85 | protected function requestToken(): string 86 | { 87 | if ($this->getTransaction()->checkForRequestToken() === false) { 88 | throw new Exception('larapay::larapay.could_not_request_payment'); 89 | } 90 | 91 | $this->checkRequiredParameters([ 92 | 'api', 93 | 'amount', 94 | 'redirect_url', 95 | 'order_id', 96 | ]); 97 | 98 | $sendParams = [ 99 | 'api' => $this->api, 100 | 'amount' => intval($this->amount), 101 | 'orderId' => ($this->order_id), 102 | 'description' => $this->description ? $this->description : '', 103 | 'mobile' => $this->mobile ? $this->mobile : '', 104 | 'redirect' => $this->redirect_url, 105 | ]; 106 | 107 | try { 108 | XLog::debug('PaymentRequest call', $sendParams); 109 | $result = Helper::post2https($sendParams, $this->endPoint); 110 | 111 | $resultObj = json_decode($result); 112 | 113 | XLog::info('PaymentRequest response', $this->obj2array($resultObj)); 114 | 115 | 116 | if (isset($resultObj->status)) { 117 | if ($resultObj->status == 1) { 118 | $this->getTransaction()->setGatewayToken(strval($resultObj->token)); // update transaction reference id 119 | 120 | return $resultObj->token; 121 | } else { 122 | throw new Exception($resultObj->status); 123 | } 124 | } else { 125 | throw new Exception('larapay::larapay.invalid_response'); 126 | } 127 | } catch (\Exception $e) { 128 | throw new Exception('PayIr Fault: '.$e->getMessage().' #'.$e->getCode(), $e->getCode()); 129 | } 130 | } 131 | 132 | /** 133 | * @return bool 134 | * @throws Exception 135 | * @throws \PhpMonsters\Larapay\Adapter\Exception 136 | */ 137 | protected function verifyTransaction(): bool 138 | { 139 | if ($this->getTransaction()->checkForVerify() === false) { 140 | throw new Exception('larapay::larapay.could_not_verify_payment'); 141 | } 142 | 143 | $this->checkRequiredParameters([ 144 | 'api', 145 | 'token', 146 | ]); 147 | 148 | $sendParams = [ 149 | 'api' => $this->api, 150 | 'token' => $this->token, 151 | ]; 152 | 153 | try { 154 | XLog::debug('PaymentVerification call', $sendParams); 155 | $result = Helper::post2https($sendParams, $this->endPointVerify); 156 | $response = json_decode($result); 157 | XLog::info('PaymentVerification response', $this->obj2array($response)); 158 | 159 | if (isset($response->status, $response->amount)) { 160 | if ($response->status == 1) { 161 | $this->getTransaction()->setVerified(); 162 | $this->getTransaction()->setReferenceId(strval($this->token)); // update transaction reference id 163 | return true; 164 | } else { 165 | throw new Exception($response->status); 166 | } 167 | } else { 168 | throw new Exception($response->status); 169 | } 170 | } catch (\Exception $e) { 171 | throw new Exception('Payir Fault: '.$e->getMessage().' #'.$e->getCode(), $e->getCode()); 172 | } 173 | } 174 | } -------------------------------------------------------------------------------- /src/Adapter/Saderat.php: -------------------------------------------------------------------------------- 1 | getTransaction()->checkForRequestToken() === false) { 34 | throw new Exception('larapay::larapay.could_not_request_payment'); 35 | } 36 | 37 | $this->checkRequiredParameters([ 38 | 'terminalid', 39 | 'amount', 40 | 'order_id', 41 | 'redirect_url', 42 | ]); 43 | 44 | $sendParams = [ 45 | "Amount" => $this->amount, 46 | "callbackURL" => $this->redirect_url, 47 | "invoiceID" => $this->order_id, 48 | "terminalID" => $this->terminalid, 49 | ]; 50 | 51 | try { 52 | XLog::debug('reservation call', $sendParams); 53 | 54 | $result = Helper::post2https($sendParams, $this->getWSDL()); 55 | $response = json_decode($result); 56 | 57 | XLog::info('reservation response', $response); 58 | 59 | if (isset($response->Accesstoken)) { 60 | 61 | if ($response->Status == 0) { 62 | $this->getTransaction()->setGatewayToken(strval($response->Accesstoken)); // update transaction reference id 63 | return $response->Accesstoken; 64 | } else { 65 | throw new Exception($response->Status); 66 | } 67 | } else { 68 | throw new Exception('larapay::larapay.invalid_response'); 69 | } 70 | } catch (\Exception $e) { 71 | throw new Exception('Saderat(Sepehr) Fault: ' . $e->getMessage() . ' #' . $e->getCode(), $e->getCode()); 72 | } 73 | } 74 | 75 | /** 76 | * @return string 77 | * @throws Exception 78 | */ 79 | protected function generateForm(): string 80 | { 81 | $token = $this->requestToken(); 82 | $form = view('larapay::saderat-form', [ 83 | 'endPoint' => $this->getEndPoint(), 84 | 'token' => $token, 85 | 'terminalID' => $this->terminalID, 86 | 'submitLabel' => !empty($this->submit_label) ? $this->submit_label : trans("larapay::larapay.goto_gate"), 87 | 'autoSubmit' => boolval($this->auto_submit) 88 | ]); 89 | 90 | return $form->__toString(); 91 | } 92 | 93 | /** 94 | * @return array 95 | * @throws Exception 96 | */ 97 | public function formParams(): array 98 | { 99 | $token = $this->requestToken(); 100 | 101 | return [ 102 | 'endPoint' => $this->getEndPoint() . $token, 103 | ]; 104 | } 105 | 106 | /** 107 | * @return bool 108 | * @throws Exception 109 | * @throws \PhpMonsters\Larapay\Adapter\Exception 110 | */ 111 | protected function verifyTransaction(): bool 112 | { 113 | if ($this->getTransaction()->checkForVerify() === false) { 114 | throw new Exception('larapay::larapay.could_not_verify_payment'); 115 | } 116 | 117 | 118 | $this->checkRequiredParameters([ 119 | 'rrn', 120 | 'tracenumber', 121 | 'digitalreceipt', 122 | 'respcode', 123 | 'amount', 124 | ]); 125 | 126 | $sendParams = [ 127 | "digitalreceipt" => $this->digitalreceipt, 128 | "Tid" => $this->terminalid, 129 | ]; 130 | 131 | try { 132 | XLog::debug('PaymentVerification call', $sendParams); 133 | $result = Helper::post2https($sendParams, $this->getVerifyWSDL()); 134 | $response = json_decode($result); 135 | XLog::info('PaymentVerification response', $this->obj2array($response)); 136 | 137 | if (isset($response->Status)) { 138 | if ($response->Status == "Ok" and $response->ReturnId == $this->getTransaction()->getPayableAmount()) { 139 | $this->getTransaction()->setReferenceId(strval($this->rrn)); // update transaction reference id 140 | $this->getTransaction()->setVerified(); 141 | return true; 142 | } else { 143 | throw new Exception($response->Message); 144 | } 145 | } else { 146 | throw new Exception($response->Message); 147 | } 148 | } catch (\Exception $e) { 149 | throw new Exception('Saderat Fault: ' . $e->getMessage() . ' #' . $e->getCode(), $e->getCode()); 150 | } 151 | } 152 | 153 | 154 | /** 155 | * @return string 156 | */ 157 | private function getVerifyWSDL(): string 158 | { 159 | if (config('larapay.mode') == 'production') { 160 | return $this->verifyWSDL; 161 | } else { 162 | return $this->testVerifyWSDL; 163 | } 164 | } 165 | 166 | /** 167 | * @return bool 168 | */ 169 | public function canContinueWithCallbackParameters(): bool 170 | { 171 | if ($this->respcode == "0") { 172 | return true; 173 | } 174 | 175 | return false; 176 | } 177 | 178 | public function getGatewayReferenceId(): string 179 | { 180 | $this->checkRequiredParameters([ 181 | 'digitalreceipt', 182 | ]); 183 | 184 | return strval($this->digitalreceipt); 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /src/Adapter/Saderat/Exception.php: -------------------------------------------------------------------------------- 1 | getTransaction()->checkForRequestToken() == false) { 37 | throw new Exception('larapay::larapay.could_not_request_payment'); 38 | } 39 | 40 | $this->checkRequiredParameters([ 41 | 'merchant_id', 42 | 'order_id', 43 | 'amount', 44 | 'redirect_url', 45 | ]); 46 | 47 | $sendParams = [ 48 | 'TermID' => $this->merchant_id, 49 | 'ResNum' => $this->order_id, 50 | 'TotalAmount' => intval($this->amount), 51 | ]; 52 | 53 | try { 54 | $soapClient = $this->getSoapClient('token'); 55 | 56 | XLog::debug('RequestToken call', $sendParams); 57 | 58 | $response = $soapClient->__soapCall('RequestToken', $sendParams); 59 | 60 | if (!empty($response)) { 61 | XLog::info('RequestToken response', ['response' => $response]); 62 | 63 | if (strlen($response) > 10) { // got string token 64 | $this->getTransaction()->setGatewayToken(strval($response)); // update transaction reference id 65 | 66 | return $response; 67 | } else { 68 | throw new Exception($response); // negative integer as error 69 | } 70 | } else { 71 | throw new Exception('larapay::larapay.invalid_response'); 72 | } 73 | 74 | } catch (SoapFault $e) { 75 | throw new Exception('SoapFault: ' . $e->getMessage() . ' #' . $e->getCode(), $e->getCode()); 76 | } 77 | } 78 | 79 | public function generateForm(): string 80 | { 81 | XLog::debug(__METHOD__); 82 | 83 | if ($this->with_token) { 84 | return $this->generateFormWithToken()->__toString(); 85 | } else { 86 | return $this->generateFormWithoutToken()->__toString(); // default 87 | } 88 | } 89 | 90 | public function formParams(): array 91 | { 92 | if ($this->with_token) { 93 | return $this->formParamsWithToken(); 94 | } else { 95 | return $this->formParamsWithoutToken(); // default 96 | } 97 | } 98 | 99 | protected function generateFormWithoutToken(): \Illuminate\View\View 100 | { 101 | XLog::debug(__METHOD__, $this->getParameters()); 102 | 103 | $this->checkRequiredParameters([ 104 | 'merchant_id', 105 | 'amount', 106 | 'order_id', 107 | 'redirect_url', 108 | ]); 109 | 110 | return view('larapay::saman-form', [ 111 | 'endPoint' => $this->getEndPoint(), 112 | 'amount' => intval($this->amount), 113 | 'merchantId' => $this->merchant_id, 114 | 'orderId' => $this->order_id, 115 | 'redirectUrl' => $this->redirect_url, 116 | 'submitLabel' => !empty($this->submit_label) ? $this->submit_label : trans("larapay::larapay.goto_gate"), 117 | 'autoSubmit' => boolval($this->auto_submit), 118 | ]); 119 | } 120 | 121 | protected function formParamsWithoutToken(): array 122 | { 123 | XLog::debug(__METHOD__, $this->getParameters()); 124 | 125 | $this->checkRequiredParameters([ 126 | 'merchant_id', 127 | 'amount', 128 | 'order_id', 129 | 'redirect_url', 130 | ]); 131 | 132 | return [ 133 | 'endPoint' => $this->getEndPoint(), 134 | 'amount' => intval($this->amount), 135 | 'merchantId' => $this->merchant_id, 136 | 'orderId' => $this->order_id, 137 | 'redirectUrl' => $this->redirect_url, 138 | ]; 139 | } 140 | 141 | protected function generateFormWithToken(): \Illuminate\View\View 142 | { 143 | XLog::debug(__METHOD__, $this->getParameters()); 144 | $this->checkRequiredParameters([ 145 | 'merchant_id', 146 | 'order_id', 147 | 'amount', 148 | 'redirect_url', 149 | ]); 150 | 151 | $token = $this->requestToken(); 152 | 153 | XLog::info(__METHOD__, ['fetchedToken' => $token]); 154 | 155 | return view('larapay::saman-form', [ 156 | 'endPoint' => $this->getEndPoint(), 157 | 'amount' => '',// just because of view 158 | 'merchantId' => '', // just because of view 159 | 'orderId' => '', // just because of view 160 | 'token' => $token, 161 | 'redirectUrl' => $this->redirect_url, 162 | 'submitLabel' => !empty($this->submit_label) ? $this->submit_label : trans("larapay::larapay.goto_gate"), 163 | 'autoSubmit' => boolval($this->auto_submit), 164 | ]); 165 | } 166 | 167 | protected function formParamsWithToken(): array 168 | { 169 | XLog::debug(__METHOD__, $this->getParameters()); 170 | $this->checkRequiredParameters([ 171 | 'merchant_id', 172 | 'order_id', 173 | 'amount', 174 | 'redirect_url', 175 | ]); 176 | 177 | $token = $this->requestToken(); 178 | 179 | XLog::info(__METHOD__, ['fetchedToken' => $token]); 180 | 181 | return [ 182 | 'endPoint' => $this->getEndPoint(), 183 | 'amount' => '',// just because of view 184 | 'merchantId' => '', // just because of view 185 | 'orderId' => '', // just because of view 186 | 'token' => $token, 187 | 'redirectUrl' => $this->redirect_url, 188 | ]; 189 | } 190 | 191 | /** 192 | * @return bool 193 | * @throws Exception 194 | * @throws \PhpMonsters\Larapay\Adapter\Exception 195 | */ 196 | protected function verifyTransaction(): bool 197 | { 198 | if ($this->getTransaction()->checkForVerify() == false) { 199 | throw new Exception('larapay::larapay.could_not_verify_payment'); 200 | } 201 | 202 | $this->checkRequiredParameters([ 203 | 'State', 204 | 'RefNum', 205 | 'ResNum', 206 | 'merchant_id', 207 | 'TraceNo', 208 | 'SecurePan' 209 | ]); 210 | 211 | if ($this->State != 'OK') { 212 | throw new Exception('Error: ' . $this->State); 213 | } 214 | 215 | try { 216 | $soapClient = $this->getSoapClient(); 217 | 218 | XLog::info('VerifyTransaction call', [$this->RefNum, $this->merchant_id]); 219 | $response = $soapClient->VerifyTransaction($this->RefNum, $this->merchant_id); 220 | 221 | if (isset($response)) { 222 | XLog::info('VerifyTransaction response', ['response' => $response]); 223 | 224 | if ($response == $this->getTransaction()->getPayableAmount()) { 225 | // double check the amount by transaction amount 226 | $this->getTransaction()->setCardNumber(strval($this->SecurePan), false); // no save() 227 | $this->getTransaction()->setVerified(); // with save() 228 | 229 | return true; 230 | } else { 231 | throw new Exception($response); 232 | } 233 | } else { 234 | throw new Exception('larapay::larapay.invalid_response'); 235 | } 236 | 237 | } catch (SoapFault $e) { 238 | throw new Exception('SoapFault: ' . $e->getMessage() . ' #' . $e->getCode(), $e->getCode()); 239 | } 240 | } 241 | 242 | /** 243 | * @return bool 244 | * @throws Exception 245 | * @throws \PhpMonsters\Larapay\Adapter\Exception 246 | */ 247 | protected function reverseTransaction(): bool 248 | { 249 | if ($this->reverseSupport == false || $this->getTransaction()->checkForReverse() == false) { 250 | throw new Exception('larapay::larapay.could_not_reverse_payment'); 251 | } 252 | 253 | $this->checkRequiredParameters([ 254 | 'RefNum', 255 | 'merchant_id', 256 | 'merchant_pass', 257 | 'amount', 258 | ]); 259 | 260 | try { 261 | $soapClient = $this->getSoapClient(); 262 | 263 | XLog::info('reverseTransaction call', [$this->RefNum, $this->merchant_id]); 264 | $response = $soapClient->reverseTransaction1( 265 | $this->RefNum, 266 | $this->merchant_id, 267 | $this->merchant_pass, 268 | $this->amount 269 | ); 270 | 271 | if (isset($response)) { 272 | XLog::info('reverseTransaction response', ['response' => $response]); 273 | 274 | if ($response == 1) { // check by transaction amount 275 | $this->getTransaction()->setRefunded(true); 276 | 277 | return true; 278 | } else { 279 | throw new Exception($response); 280 | } 281 | } else { 282 | throw new Exception('larapay::larapay.invalid_response'); 283 | } 284 | 285 | } catch (SoapFault $e) { 286 | throw new Exception('SoapFault: ' . $e->getMessage() . ' #' . $e->getCode(), $e->getCode()); 287 | } 288 | } 289 | 290 | /** 291 | * @return bool 292 | */ 293 | public function canContinueWithCallbackParameters(): bool 294 | { 295 | try { 296 | $this->checkRequiredParameters([ 297 | 'RefNum', 298 | 'State', 299 | ]); 300 | } catch (\Exception $e) { 301 | return false; 302 | } 303 | 304 | if ($this->State == 'OK') { 305 | return true; 306 | } 307 | 308 | return false; 309 | } 310 | 311 | /** 312 | * @return string 313 | * @throws \PhpMonsters\Larapay\Adapter\Exception 314 | */ 315 | public function getGatewayReferenceId(): string 316 | { 317 | $this->checkRequiredParameters([ 318 | 'RefNum', 319 | ]); 320 | 321 | return strval($this->RefNum); 322 | } 323 | 324 | /** 325 | * @param string $type 326 | * 327 | * @return string 328 | */ 329 | protected function getWSDL($type = null): string 330 | { 331 | 332 | $type = $type !== null ? strtoupper($type) : null; 333 | if (config('larapay.mode') == 'production') { 334 | switch ($type) { 335 | case 'TOKEN': 336 | return $this->tokenWSDL; 337 | break; 338 | default: 339 | return $this->WSDL; 340 | break; 341 | } 342 | } else { 343 | switch ($type) { 344 | case 'TOKEN': 345 | return $this->testTokenWSDL; 346 | break; 347 | default: 348 | return $this->testWSDL; 349 | break; 350 | } 351 | } 352 | } 353 | 354 | /** 355 | * @param string type 356 | * 357 | * @return SoapClient 358 | * @throws SoapFault 359 | */ 360 | protected function getSoapClient($type = null): SoapClient 361 | { 362 | return new SoapClient($this->getWSDL($type), $this->getSoapOptions()); 363 | } 364 | } 365 | -------------------------------------------------------------------------------- /src/Adapter/Saman/Exception.php: -------------------------------------------------------------------------------- 1 | getTransaction()->checkForRequestToken() === false) { 36 | throw new Exception('larapay::larapay.could_not_request_payment'); 37 | } 38 | 39 | $this->checkRequiredParameters([ 40 | 'merchant_id', 41 | 'amount', 42 | 'redirect_url', 43 | ]); 44 | 45 | $sendParams = [ 46 | 'MerchantID' => $this->merchant_id, 47 | 'Amount' => intval($this->amount), 48 | 'Description' => $this->description ? $this->description : '', 49 | 'Email' => $this->email ? $this->email : '', 50 | 'Mobile' => $this->mobile ? $this->mobile : '', 51 | 'CallbackURL' => $this->redirect_url, 52 | ]; 53 | 54 | try { 55 | $soapClient = new SoapClient($this->getWSDL()); 56 | 57 | XLog::debug('PaymentRequest call', $sendParams); 58 | 59 | $response = $soapClient->PaymentRequest($sendParams); 60 | 61 | XLog::info('PaymentRequest response', $this->obj2array($response)); 62 | 63 | 64 | if (isset($response->Status)) { 65 | 66 | if ($response->Status == 100) { 67 | $this->getTransaction()->setGatewayToken(strval($response->Authority)); // update transaction reference id 68 | 69 | return $response->Authority; 70 | } else { 71 | throw new Exception($response->Status); 72 | } 73 | } else { 74 | throw new Exception('larapay::larapay.invalid_response'); 75 | } 76 | } catch (SoapFault $e) { 77 | throw new Exception('SoapFault: ' . $e->getMessage() . ' #' . $e->getCode(), $e->getCode()); 78 | } 79 | } 80 | 81 | 82 | /** 83 | * @return string 84 | * @throws Exception 85 | * @throws \PhpMonsters\Larapay\Adapter\Exception 86 | */ 87 | protected function generateForm(): string 88 | { 89 | $authority = $this->requestToken(); 90 | 91 | $form = view('larapay::zarinpal-form', [ 92 | 'endPoint' => strtr($this->getEndPoint(), ['{authority}' => $authority]), 93 | 'submitLabel' => !empty($this->submit_label) ? $this->submit_label : trans("larapay::larapay.goto_gate"), 94 | 'autoSubmit' => boolval($this->auto_submit), 95 | ]); 96 | 97 | return $form->__toString(); 98 | } 99 | 100 | /** 101 | * @return array 102 | * @throws Exception 103 | * @throws \PhpMonsters\Larapay\Adapter\Exception 104 | */ 105 | public function formParams(): array 106 | { 107 | $authority = $this->requestToken(); 108 | 109 | return [ 110 | 'endPoint' => strtr($this->getEndPoint(), ['{authority}' => $authority]), 111 | ]; 112 | } 113 | 114 | /** 115 | * @return bool 116 | * @throws Exception 117 | * @throws \PhpMonsters\Larapay\Adapter\Exception 118 | */ 119 | protected function verifyTransaction(): bool 120 | { 121 | if ($this->getTransaction()->checkForVerify() == false) { 122 | throw new Exception('larapay::larapay.could_not_verify_payment'); 123 | } 124 | 125 | $this->checkRequiredParameters([ 126 | 'merchant_id', 127 | 'Authority', 128 | ]); 129 | 130 | $sendParams = [ 131 | 'MerchantID' => $this->merchant_id, 132 | 'Authority' => $this->Authority, 133 | 'Amount' => intval($this->transaction->amount), 134 | ]; 135 | 136 | try { 137 | $soapClient = new SoapClient($this->getWSDL()); 138 | 139 | XLog::debug('PaymentVerification call', $sendParams); 140 | 141 | $response = $soapClient->PaymentVerification($sendParams); 142 | 143 | XLog::info('PaymentVerification response', $this->obj2array($response)); 144 | 145 | 146 | if (isset($response->Status, $response->RefID)) { 147 | 148 | if ($response->Status == 100) { 149 | $this->getTransaction()->setVerified(); 150 | $this->getTransaction()->setReferenceId((string)$response->RefID); // update transaction reference id 151 | 152 | return true; 153 | } else { 154 | throw new Exception($response->Status); 155 | } 156 | } else { 157 | throw new Exception('larapay::larapay.invalid_response'); 158 | } 159 | 160 | } catch (SoapFault $e) { 161 | 162 | throw new Exception('SoapFault: ' . $e->getMessage() . ' #' . $e->getCode(), $e->getCode()); 163 | } 164 | } 165 | 166 | /** 167 | * @return bool 168 | */ 169 | public function canContinueWithCallbackParameters(): bool 170 | { 171 | if ($this->Status == "OK") { 172 | return true; 173 | } 174 | 175 | return false; 176 | } 177 | 178 | public function getGatewayReferenceId(): string 179 | { 180 | $this->checkRequiredParameters([ 181 | 'Authority', 182 | ]); 183 | 184 | return strval($this->Authority); 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /src/Adapter/Zarinpal/Exception.php: -------------------------------------------------------------------------------- 1 | requestToken(); 33 | 34 | return [ 35 | 'endPoint' => strtr($this->getEndPoint(), ['{authority}' => $authority]), 36 | ]; 37 | } 38 | 39 | /** 40 | * @return bool 41 | */ 42 | public function canContinueWithCallbackParameters(): bool 43 | { 44 | if ($this->success == 1) { 45 | return true; 46 | } 47 | 48 | return false; 49 | } 50 | 51 | public function getGatewayReferenceId(): string 52 | { 53 | $this->checkRequiredParameters([ 54 | 'trackid', 55 | ]); 56 | return strval($this->trackid); 57 | } 58 | 59 | /** 60 | * @return string 61 | * @throws Exception 62 | * @throws \PhpMonsters\Larapay\Adapter\Exception 63 | */ 64 | protected function generateForm(): string 65 | { 66 | $authority = $this->requestToken(); 67 | 68 | $form = view('larapay::zibal-form', [ 69 | 'endPoint' => strtr($this->getEndPoint(), ['{trackId}' => $authority]), 70 | 'submitLabel' => !empty($this->submit_label) ? $this->submit_label : trans("larapay::larapay.goto_gate"), 71 | 'autoSubmit' => boolval($this->auto_submit), 72 | ]); 73 | 74 | return $form->__toString(); 75 | } 76 | 77 | /** 78 | * @return string 79 | * @throws Exception 80 | * @throws \PhpMonsters\Larapay\Adapter\Exception 81 | */ 82 | protected function requestToken(): string 83 | { 84 | if ($this->getTransaction()->checkForRequestToken() === false) { 85 | throw new Exception('larapay::larapay.could_not_request_payment'); 86 | } 87 | 88 | $this->checkRequiredParameters([ 89 | 'merchant_id', 90 | 'amount', 91 | 'redirect_url', 92 | ]); 93 | 94 | $sendParams = [ 95 | 'merchant' => $this->getSandbox(), 96 | 'orderId' => $this->getTransaction()->bank_order_id, 97 | 'amount' => intval($this->amount), 98 | 'description' => $this->description ? $this->description : '', 99 | 'mobile' => $this->mobile ? $this->mobile : '', 100 | 'callbackUrl' => $this->redirect_url, 101 | ]; 102 | 103 | try { 104 | XLog::debug('PaymentRequest call', $sendParams); 105 | $result = Helper::post2https($sendParams, $this->WSDL); 106 | $resultObj = json_decode($result); 107 | 108 | XLog::info('PaymentRequest response', $this->obj2array($resultObj)); 109 | 110 | if (isset($resultObj->result)) { 111 | if ($resultObj->result == 100) { 112 | $this->getTransaction()->setGatewayToken(strval($resultObj->trackId)); // update transaction reference id 113 | return strval($resultObj->trackId); 114 | } else { 115 | throw new Exception($resultObj->result); 116 | } 117 | } else { 118 | throw new Exception('larapay::larapay.invalid_response'); 119 | } 120 | } catch (\Exception $e) { 121 | throw new Exception($e->getMessage()); 122 | } 123 | } 124 | 125 | public function getSandbox(): string 126 | { 127 | if (config('larapay.mode') == 'production') { 128 | return $this->merchant_id; 129 | } else { 130 | return "zibal"; 131 | } 132 | } 133 | 134 | /** 135 | * @return bool 136 | * @throws Exception 137 | * @throws \PhpMonsters\Larapay\Adapter\Exception 138 | */ 139 | protected function verifyTransaction(): bool 140 | { 141 | if ($this->getTransaction()->checkForVerify() === false) { 142 | throw new Exception('larapay::larapay.could_not_verify_payment'); 143 | } 144 | 145 | $this->checkRequiredParameters([ 146 | 'status', 147 | 'trackid', 148 | ]); 149 | 150 | $sendParams = [ 151 | 'merchant' => $this->getSandbox(), 152 | 'trackId' => $this->trackid, 153 | ]; 154 | 155 | 156 | try { 157 | XLog::debug('PaymentRequest call', $sendParams); 158 | $result = Helper::post2https($sendParams, $this->endPointVerify); 159 | $resultObj = json_decode($result); 160 | 161 | XLog::info('PaymentRequest response', $this->obj2array($resultObj)); 162 | if (isset($resultObj->result)) { 163 | if ($resultObj->result == 100 || $resultObj->result == 201) { 164 | $this->getTransaction()->setVerified(); 165 | $this->getTransaction()->setReferenceId((string) $this->trackId); 166 | return true; 167 | } else { 168 | throw new Exception($resultObj->result); 169 | } 170 | } else { 171 | throw new Exception('larapay::larapay.invalid_response'); 172 | } 173 | } catch (\Exception $e) { 174 | throw new Exception($e->getMessage()); 175 | } 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /src/Adapter/Zibal/Exception.php: -------------------------------------------------------------------------------- 1 | setSoapOptions(config('larapay.soap.options')); 65 | } 66 | 67 | $this->gateway = $bankAdapter; 68 | 69 | return $this; 70 | } 71 | 72 | public function verifyTransaction(Request $request, array $adapterConfig = []) 73 | { 74 | //get gateway and transaction id from request 75 | $gateway = $request->gateway; 76 | $transactionId = $request->transaction_id; 77 | 78 | $parameters = $request->all(); 79 | $parameters ['routes'] = $request->route()->parameters(); 80 | //log all incoming data for debug request 81 | XLog::debug('request: ', $parameters); 82 | 83 | 84 | $referenceId = ''; 85 | $paidTime = ''; 86 | $amount = ''; 87 | 88 | //validate incoming request parameters 89 | $validator = Validator::make([ 90 | 'transactionId' => $transactionId, 91 | 'gateway' => $gateway, 92 | ], [ 93 | 'transactionId' => [ 94 | 'required', 95 | 'numeric', 96 | ], 97 | 'gateway' => [ 98 | 'required', 99 | ], 100 | ]); 101 | 102 | // validate required route parameters 103 | if ($validator->fails()) { 104 | throw new FailedTransactionException(trans('larapay::larapay.invalid_response')); 105 | } 106 | // find the transaction by token 107 | $transaction = LarapayTransaction::find($transactionId); 108 | //transaction not found in our database 109 | if (!$transaction) { 110 | throw new TransactionNotFoundException(trans('larapay::larapay.transaction_not_found'), 2); 111 | } 112 | //transaction gateway conflict 113 | if ($transaction->gate_name != $gateway) { 114 | throw new TransactionNotFoundException(trans('larapay::larapay.transaction_not_found'), 3); 115 | } 116 | 117 | try { 118 | // update transaction`s callback parameter 119 | $transaction->setCallBackParameters($request->all(), true); 120 | 121 | //read gateway property from transaction and make payment gateway handler 122 | $paymentGatewayHandler = $this->make($gateway, $transaction, $adapterConfig); 123 | 124 | //check that it's correct data and we can continue with this parameters 125 | if ($paymentGatewayHandler->canContinueWithCallbackParameters($request->all()) !== true) { 126 | throw new FailedTransactionException(trans('larapay::larapay.invalid_response')); 127 | } 128 | 129 | //get reference id from callback data 130 | $referenceId = $paymentGatewayHandler->getGatewayReferenceId(); 131 | 132 | //search or transaction to detect double spending 133 | $doubleInvoice = LarapayTransaction::where('gate_refid', $referenceId) 134 | ->where('verified', true)//قبلا وریفای شده 135 | ->where('gate_name', $transaction->gate_name) 136 | ->first(); 137 | 138 | //found double transaction 139 | if (!empty($doubleInvoice)) { 140 | // log double spending details 141 | XLog::emergency('referenceId double spending detected', [ 142 | 'tag' => $referenceId, 143 | 'order_id' => $transaction->gateway_order_id, 144 | 'ips' => $request->ips(), 145 | 'gateway' => $gateway, 146 | ]); 147 | 148 | //update transaction and log double spending 149 | if (!preg_match('/DOUBLE_SPENDING/i', $transaction->description)) { 150 | $transaction->description = "#DOUBLE_SPENDING_BY_{$doubleInvoice->id}#\n" . $transaction->description; 151 | $transaction->save(); 152 | } 153 | //throw new exception and stop verify transaction 154 | throw new FailedTransactionException(trans('larapay::larapay.could_not_verify_transaction')); 155 | } 156 | 157 | //set reference id on transaction 158 | $transaction->setReferenceId($referenceId); 159 | 160 | // verify start ---------------------------------------------------------------------------------------- 161 | $verified = false; 162 | // try 3 times for verify transaction 163 | for ($i = 1; $i <= 3; $i++) { 164 | try { 165 | XLog::info('trying to verify payment', 166 | ['try' => $i, 'tag' => $referenceId, 'gateway' => $gateway]); 167 | 168 | $verifyResult = $paymentGatewayHandler->verify(); 169 | if ($verifyResult) { 170 | $verified = true; 171 | } 172 | XLog::info('verify result', 173 | ['result' => $verifyResult, 'try' => $i, 'tag' => $referenceId, 'gateway' => $gateway]); 174 | break; 175 | } catch (Exception $e) { 176 | XLog::error('Exception: ' . $e->getMessage(), 177 | ['try' => $i, 'tag' => $referenceId, 'gateway' => $gateway]); 178 | usleep(500); 179 | continue; 180 | } 181 | } 182 | 183 | //check if transaction verified 184 | if ($verified !== true) { 185 | XLog::error('transaction verification failed', ['tag' => $referenceId, 'gateway' => $gateway]); 186 | throw new FailedTransactionException(trans('larapay::larapay.verification_failed')); 187 | } else { 188 | XLog::info('invoice verified successfully', ['tag' => $referenceId, 'gateway' => $gateway]); 189 | } 190 | // verify end ------------------------------------------------------------------------------------------ 191 | 192 | // after verify start ---------------------------------------------------------------------------------- 193 | $afterVerified = false; 194 | // try 3 times for after verify transaction 195 | for ($i = 1; $i <= 3; $i++) { 196 | try { 197 | XLog::info('trying to after verify payment', 198 | ['try' => $i, 'tag' => $referenceId, 'gateway' => $gateway]); 199 | 200 | $afterVerifyResult = $paymentGatewayHandler->afterVerify(); 201 | if ($afterVerifyResult) { 202 | $afterVerified = true; 203 | } 204 | XLog::info('after verify result', [ 205 | 'result' => $afterVerifyResult, 206 | 'try' => $i, 207 | 'tag' => $referenceId, 208 | 'gateway' => $gateway, 209 | ]); 210 | break; 211 | } catch (Exception $e) { 212 | XLog::error('Exception: ' . $e->getMessage(), 213 | ['try' => $i, 'tag' => $referenceId, 'gateway' => $gateway]); 214 | usleep(500); 215 | continue; 216 | } 217 | } 218 | 219 | if ($afterVerified !== true) { 220 | XLog::error('transaction after verification failed', 221 | ['tag' => $referenceId, 'gateway' => $gateway]); 222 | throw new FailedTransactionException(trans('larapay::larapay.after_verification_failed')); 223 | } else { 224 | XLog::info('invoice after verified successfully', ['tag' => $referenceId, 'gateway' => $gateway]); 225 | } 226 | 227 | // after verify end ------------------------------------------------------------------------------------ 228 | } catch (Exception $e) { 229 | XLog::emergency($e->getMessage() . ' code:' . $e->getCode() . ' ' . $e->getFile() . ':' . $e->getLine()); 230 | throw new FailedTransactionException($e->getMessage(), $e->getCode(), $e); 231 | } 232 | 233 | //transaction done successfully 234 | XLog::info('invoice completed successfully', ['tag' => $referenceId, 'gateway' => $gateway]); 235 | //set transaction date time 236 | $transaction->setPaidAt('now'); 237 | //set accomplished true on transaction and save it. 238 | $transaction->setAccomplished(true); 239 | //return transaction 240 | return $transaction; 241 | } 242 | 243 | /** 244 | * @param $name 245 | * @param $arguments 246 | * 247 | * @return mixed 248 | * @throws Exception 249 | */ 250 | public function __call($name, $arguments) 251 | { 252 | if (empty($this->gateway)) { 253 | throw new Exception("Gateway not defined before! please use make method to initialize gateway"); 254 | } 255 | 256 | XLog::info($name, $arguments); 257 | 258 | // چو ن همیشه متد ها با یک پارامتر کلی بصورت آرایه فراخوانی میشوند. مثلا: 259 | // $paymentGatewayHandler->generateForm($ArrayOfExtraPaymentParams) 260 | if (count($arguments) > 0) { 261 | $this->gateway->setParameters($arguments[0]); // set parameters 262 | } 263 | 264 | try { 265 | return call_user_func_array([$this->gateway, $name], $arguments); // call desire method 266 | } catch (Exception $e) { 267 | XLog::error($e->getMessage() . ' Code:' . $e->getCode() . ' File:' . $e->getFile() . ':' . $e->getLine()); 268 | throw $e; 269 | } 270 | } 271 | } 272 | -------------------------------------------------------------------------------- /src/LarapayServiceProvider.php: -------------------------------------------------------------------------------- 1 | registerResources(); 22 | $this->registerPublishing(); 23 | $this->registerModelBindings(); 24 | } 25 | 26 | /** 27 | * Get the services provided by the provider. 28 | * 29 | * @return array 30 | */ 31 | public function register() 32 | { 33 | $this->app->singleton('larapay', function ($app) { 34 | return new Factory; 35 | }); 36 | } 37 | 38 | protected function registerResources() 39 | { 40 | $this->loadViewsFrom(__DIR__ . '/../views/', 'larapay'); 41 | 42 | $this->publishes([ 43 | __DIR__ . '/../translations/' => resource_path('lang/vendor/larapay'), 44 | ], 'translations'); 45 | 46 | $this->loadTranslationsFrom(__DIR__ . '/../translations', 'larapay'); 47 | } 48 | 49 | protected function registerPublishing() 50 | { 51 | $this->publishes([ 52 | __DIR__ . '/../config/larapay.php' => config_path('larapay.php') 53 | ], 'config'); 54 | 55 | $this->publishes([ 56 | __DIR__ . '/../views/' => resource_path('/views/vendor/larapay'), 57 | ], 'views'); 58 | 59 | 60 | $this->publishes([ 61 | __DIR__ . '/../database/migrations/create_larapay_transaction_table.php.stub' => database_path('migrations/' . date('Y_m_d_His', 62 | time()) . '_create_larapay_transaction_table.php'), 63 | ], 'migrations'); 64 | } 65 | 66 | 67 | protected function registerModelBindings() 68 | { 69 | $this->app->bind(LarapayTransactionContract::class, LarapayTransaction::class); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/Models/Enum/Bank.php: -------------------------------------------------------------------------------- 1 | morphTo(); 53 | } 54 | 55 | public function reverseTransaction() 56 | { 57 | //make payment gateway handler 58 | $gatewayProperties = json_decode($this->extra_params, true); 59 | $paymentGatewayHandler = Larapay::make($this->gate_name, $this, $gatewayProperties); 60 | //$paymentGatewayHandler->setParameters($gatewayProperties); 61 | //get reference id 62 | $referenceId = $paymentGatewayHandler->getGatewayReferenceId(); 63 | //try 3 times to reverse transaction 64 | $reversed = false; 65 | for ($i = 1; $i <= 3; $i++) { 66 | try { 67 | $reverseResult = $paymentGatewayHandler->reverse(); 68 | if ($reverseResult) { 69 | $reversed = true; 70 | } 71 | 72 | break; 73 | } catch (Exception $e) { 74 | XLog::error('Exception: ' . $e->getMessage(), ['try' => $i, 'tag' => $referenceId]); 75 | usleep(500); 76 | continue; 77 | } 78 | } 79 | //throw exception when 3 times failed 80 | if ($reversed !== true) { 81 | XLog::error('invoice reverse failed', ['tag' => $referenceId]); 82 | throw new FailedReverseTransactionException(trans('larapay::larapay.reversed_failed')); 83 | } 84 | 85 | //set reversed flag 86 | $this->reversed = true; 87 | $this->save(); 88 | //log true result 89 | XLog::info('invoice reversed successfully', ['tag' => $referenceId]); 90 | 91 | return true; 92 | } 93 | 94 | public function generateForm($autoSubmit = false, $callback = null, $adapterConfig = []) 95 | { 96 | $paymentGatewayHandler = $this->gatewayHandler($adapterConfig); 97 | 98 | $callbackRoute = route(config("larapay.payment_callback"), [ 99 | 'gateway' => $this->gate_name, 100 | 'transaction_id' => $this->id, 101 | ]); 102 | 103 | if ($callback != null) { 104 | $callbackRoute = route($callback, [ 105 | 'gateway' => $this->gate_name, 106 | 'transaction_id' => $this->id, 107 | ]); 108 | } 109 | 110 | $paymentParams = [ 111 | 'order_id' => $this->getBankOrderId(), 112 | 'redirect_url' => $callbackRoute, 113 | 'amount' => $this->amount, 114 | 'sharing' => json_decode($this->sharing, true), 115 | 'submit_label' => trans('larapay::larapay.goto_gate'), 116 | ]; 117 | 118 | try { 119 | if ($autoSubmit) { 120 | $paymentParams['auto_submit'] = true; 121 | } 122 | 123 | $form = $paymentGatewayHandler->form($paymentParams); 124 | 125 | return $form; 126 | } catch (Exception $e) { 127 | XLog::emergency($this->gate_name . ' #' . $e->getCode() . '-' . $e->getMessage()); 128 | 129 | throw $e; 130 | } 131 | } 132 | 133 | public function formParams($callback = null, $adapterConfig = []): array 134 | { 135 | 136 | $paymentGatewayHandler = $this->gatewayHandler($adapterConfig); 137 | 138 | $callbackRoute = route(config("larapay.payment_callback"), [ 139 | 'gateway' => $this->gate_name, 140 | 'transaction_id' => $this->id, 141 | ]); 142 | 143 | if ($callback != null) { 144 | $callbackRoute = route($callback, [ 145 | 'gateway' => $this->gate_name, 146 | 'transaction_id' => $this->id, 147 | ]); 148 | } 149 | 150 | $paymentParams = [ 151 | 'order_id' => $this->getBankOrderId(), 152 | 'redirect_url' => $callbackRoute, 153 | 'amount' => $this->amount, 154 | 'sharing' => json_decode($this->sharing, true), 155 | 'submit_label' => trans('larapay::larapay.goto_gate'), 156 | ]; 157 | 158 | try { 159 | return $paymentGatewayHandler->formParams($paymentParams); 160 | } catch (Exception $e) { 161 | XLog::emergency($this->gate_name . ' #' . $e->getCode() . '-' . $e->getMessage()); 162 | 163 | return []; 164 | } 165 | } 166 | 167 | public function gatewayHandler($adapterConfig = []) 168 | { 169 | return Larapay::make($this->gate_name, $this, $adapterConfig); 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /src/Models/Traits/OnlineTransactionTrait.php: -------------------------------------------------------------------------------- 1 | gate_refid = $referenceId; 11 | if ($save) { 12 | return $this->save(); 13 | } 14 | 15 | return true; 16 | } 17 | 18 | public function checkForRequestToken(): bool 19 | { 20 | return $this->veified != true; 21 | } 22 | 23 | public function checkForVerify(): bool 24 | { 25 | return $this->veified != true; 26 | } 27 | 28 | public function checkForInquiry(): bool 29 | { 30 | return true; 31 | } 32 | 33 | public function checkForAfterVerify(): bool 34 | { 35 | return $this->after_verified != true; 36 | } 37 | 38 | public function checkForReverse(): bool 39 | { 40 | return $this->after_verified == true && $this->reversed != true; 41 | } 42 | 43 | public function setCardNumber(string $cardNumber, bool $save = true): bool 44 | { 45 | return $this->setExtra('customer_card_number', $cardNumber, $save); 46 | } 47 | 48 | public function setVerified(bool $save = true): bool 49 | { 50 | $this->verified = true; 51 | 52 | if ($save) { 53 | return $this->save(); 54 | } 55 | 56 | return true; 57 | } 58 | 59 | public function setAfterVerified(bool $save = true): bool 60 | { 61 | $this->after_verified = true; 62 | 63 | if ($save) { 64 | return $this->save(); 65 | } 66 | 67 | return true; 68 | } 69 | 70 | public function setSuccessful($flag, $save = true): bool 71 | { 72 | $this->accomplished = boolval($flag); 73 | 74 | if ($save) { 75 | return $this->save(); 76 | } 77 | 78 | return true; 79 | } 80 | 81 | public function setReversed($save = true): bool 82 | { 83 | $this->reversed = true; 84 | $this->accomplished = false; 85 | 86 | if ($save) { 87 | return $this->save(); 88 | } 89 | 90 | return true; 91 | } 92 | 93 | public function getAmount() 94 | { 95 | return abs($this->amount); 96 | } 97 | 98 | public function getBankOrderId() 99 | { 100 | return $this->bank_order_id; 101 | } 102 | 103 | public function setPaidAt($time = 'now', $save = false) 104 | { 105 | $this->paid_at = date('Y-m-d H:i:s', strtotime($time)); 106 | 107 | if ($save) { 108 | return $this->save(); 109 | } 110 | 111 | return true; 112 | } 113 | 114 | 115 | public function getPayableAmount(): int 116 | { 117 | return $this->getAmount(); 118 | } 119 | 120 | public function setRefunded(bool $save = true): bool 121 | { 122 | $this->reversed = true; 123 | $this->accomplished = false; 124 | 125 | if ($save) { 126 | return $this->save(); 127 | } 128 | 129 | return true; 130 | } 131 | 132 | public function setAccomplished(bool $save = true): bool 133 | { 134 | 135 | $this->accomplished = true; 136 | 137 | if ($save) { 138 | return $this->save(); 139 | } 140 | 141 | return true; 142 | } 143 | 144 | public function setCallBackParameters(array $parameters, bool $save = true): bool 145 | { 146 | $this->extra_params = json_encode($parameters, JSON_UNESCAPED_UNICODE); 147 | 148 | if ($save) { 149 | $this->save(); 150 | } 151 | 152 | return true; 153 | } 154 | 155 | public function setGatewayToken(string $token, bool $save = true): bool 156 | { 157 | $this->gate_refid = $token; 158 | if ($save) { 159 | $this->save(); 160 | } 161 | 162 | return true; 163 | } 164 | 165 | public function setExtra(string $key, $value, bool $save = true): bool 166 | { 167 | $value = (array)$value; 168 | 169 | $extra = json_decode($this->extra_params, true); 170 | 171 | if (isset($extra[$key])) { 172 | $oldKey = $key . '_' . time(); 173 | $extra[$oldKey] = $extra[$key]; 174 | } 175 | 176 | $extra[$key] = $value; 177 | $this->extra_params = json_encode($extra, JSON_UNESCAPED_UNICODE); 178 | 179 | if ($save) { 180 | $this->save(); 181 | } 182 | 183 | return true; 184 | } 185 | 186 | } 187 | -------------------------------------------------------------------------------- /src/Payable.php: -------------------------------------------------------------------------------- 1 | morphMany(app(LarapayTransactionContract::class), 'model'); 16 | } 17 | 18 | public function accomplishedTransactions() 19 | { 20 | return $this->morphMany(app(LarapayTransactionContract::class), 'model')->where('accomplished', true); 21 | } 22 | 23 | public function isPaid() 24 | { 25 | $accomplishedTransactions = $this->accomplishedTransactions; 26 | if ($accomplishedTransactions->count() != 0) { 27 | return true; 28 | } 29 | 30 | return false; 31 | } 32 | 33 | public function paidAmount() 34 | { 35 | $accomplishedTransactions = $this->accomplishedTransactions; 36 | $amount = 0; 37 | foreach ($accomplishedTransactions as $accomplishedTransaction) { 38 | $amount += $accomplishedTransaction->amount; 39 | } 40 | 41 | return $amount; 42 | } 43 | 44 | public function createTransaction( 45 | $paymentGateway, 46 | $amount = null, 47 | $description = null, 48 | array $additionalData = [], 49 | array $sharing = [] 50 | ) { 51 | 52 | $transactionData = []; 53 | 54 | $transactionData['amount'] = $amount; 55 | if ($amount == null) { 56 | $transactionData['amount'] = $this->getAmount(); 57 | } 58 | 59 | if ($transactionData['amount'] == null || $transactionData['amount'] == 0) { 60 | throw new EmptyAmountException(); 61 | } 62 | 63 | $paymentGateway = ucfirst(strtolower($paymentGateway)); 64 | 65 | $transactionData['description'] = $description; 66 | $transactionData['gate_name'] = $paymentGateway; 67 | $transactionData['submitted'] = true; 68 | $transactionData['bank_order_id'] = $this->generateBankOrderId($paymentGateway); 69 | $transactionData['payment_method'] = 'ONLINE'; 70 | $transactionData['additional_data'] = empty($additionalData) ? '{}' : json_encode($additionalData, JSON_UNESCAPED_UNICODE); 71 | $transactionData['sharing'] = empty($sharing) ? '{}' : json_encode($sharing, JSON_UNESCAPED_UNICODE); 72 | 73 | return $this->transactions()->create($transactionData); 74 | } 75 | 76 | public function getAmount() 77 | { 78 | return intval($this->amount) * 10; 79 | } 80 | 81 | public function generateBankOrderId(string $bank = null): int 82 | { 83 | // handle each gateway exception 84 | switch ($bank) { 85 | default: 86 | { 87 | return time() . mt_rand(10, 99); 88 | } 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/Transaction/TransactionInterface.php: -------------------------------------------------------------------------------- 1 | 'خطای هندل نشده!', // unofficial error code --- added by PhpMonsters 5 | 6 | 'canceled_by_user' => 'تراکنش بانکی توسط کاربر لغو شد', 7 | 'could_not_request_payment' => 'امکان درخواست توکن برای این تراکنش وجود ندارد', 8 | 'could_not_verify_transaction' => 'امکان تایید این تراکنش وجود ندارد', 9 | 'could_not_inquiry_payment' => 'امکان استعلام این تراکنش وجود ندارد', 10 | 'could_not_settle_payment' => 'امکان درخواست واریز وجه برای این تراکنش وجود ندارد', 11 | 'could_not_reverse_payment' => 'انمان بازگشت این تراکنش وجود ندارد', 12 | 'gate_not_ready' => 'درگاه پرداختی یا وجود ندارد یا آماده سرویس دهی نمی باشد', 13 | 'gate_not_implemented_larapay' => 'دروازه پرداخت :name از PhpMonsters\\Larapay\\Adapter\\AdapterInterface پیروی نمی کند', 14 | 'goto_gate' => 'اتصال به درگاه پرداخت', 15 | 'invalid_response' => 'پاسخ معتبر از سرور درگاه پرداخت دریافت نشد!', 16 | 'reversed_failed' => 'بازگشت تراکنش با موفقیت انجام نشد!', 17 | 'verification_failed' => 'تایید تراکنش با موفقیت انجام نشد!', 18 | 'after_verification_failed' => 'تایید بعد از تراکنش با موفقیت انجام نشد!', 19 | 'invalid_sharing_data' => 'اطلاعات تسهیم معتبر نیست', 20 | 'transaction_not_found' => 'تراکنش پیدا نشد', 21 | 22 | 'mellat' => [ 23 | 'errors' => [ 24 | 'error_11' => 'شماره کارت نامعتبر است', 25 | 'error_12' => 'موجودی کافی نیست', 26 | 'error_13' => 'رمز نادرست است', 27 | 'error_14' => 'تعداد دفعات وارد کردن رمز بیش از حد مجاز است', 28 | 'error_15' => 'کارت نامعتبر است', 29 | 'error_16' => 'دفعات برداشت وجه بیش از حد مجاز است', 30 | 'error_17' => 'کاربر از انجام تراکنش منصرف شده است', 31 | 'error_18' => 'تاریخ انقضای کارت گذشته است', 32 | 'error_19' => 'مبلغ برداشت وجه بیش از حد مجاز است', 33 | 'error_21' => 'پذیرنده نامعتبر است', 34 | 'error_23' => 'خطای امنیتی رخ داده است', 35 | 'error_24' => 'اطلاعات کاربری پذیرنده نامعتبر است', 36 | 'error_25' => 'مبلغ نامعتبر است', 37 | 'error_31' => 'پاسخ نامعتبر است', 38 | 'error_32' => 'فرمت اطلاعات وارد شده صحیح نمی‌باشد', 39 | 'error_33' => 'حساب نامعتبر است', 40 | 'error_34' => 'خطای سیستمی', 41 | 'error_35' => 'تاریخ نامعتبر است', 42 | 'error_41' => 'شماره درخواست تکراری است', 43 | 'error_42' => 'تراکنش Sale یافت نشد', 44 | 'error_43' => 'قبلا درخواست Verfiy داده شده است', 45 | 'error_44' => 'درخواست Verfiy یافت نشد', 46 | 'error_45' => 'تراکنش Settle شده است', 47 | 'error_46' => 'تراکنش Settle نشده است', 48 | 'error_47' => 'تراکنش Settle یافت نشد', 49 | 'error_48' => 'تراکنش Reverse شده است', 50 | 'error_49' => 'تراکنش Refund یافت نشد.', 51 | 'error_51' => 'تراکنش تکراری است', 52 | 'error_54' => 'تراکنش مرجع موجود نیست', 53 | 'error_55' => 'تراکنش نامعتبر است', 54 | 'error_61' => 'خطا در واریز', 55 | 'error_111' => 'صادر کننده کارت نامعتبر است', 56 | 'error_112' => 'خطای سوییچ صادر کننده کارت', 57 | 'error_113' => 'پاسخی از صادر کننده کارت دریافت نشد', 58 | 'error_114' => 'دارنده این کارت مجاز به انجام این تراکنش نیست', 59 | 'error_412' => 'شناسه قبض نادرست است', 60 | 'error_413' => 'شناسه پرداخت نادرست است', 61 | 'error_414' => 'سازمان صادر کننده قبض نامعتبر است', 62 | 'error_415' => 'زمان جلسه کاری به پایان رسیده است', 63 | 'error_416' => 'خطا در ثبت اطلاعات', 64 | 'error_417' => 'شناسه پرداخت کننده نامعتبر است', 65 | 'error_418' => 'اشکال در تعریف اطلاعات مشتری', 66 | 'error_419' => 'تعداد دفعات ورود اطلاعات از حد مجاز گذشته است', 67 | 'error_421' => 'IP نامعتبر است', 68 | 69 | 'invalid_response' => 'پاسخ معتبر از سرور درگاه پرداخت دریافت نشد!', 70 | ] 71 | ], 72 | 'parsian' => [ 73 | 'errors' => [ 74 | 'error_20' => 'پین فروشنده درست نمی باشد', 75 | 'error_22' => 'پین فروشنده درست نمی باشد', 76 | 'error_30' => 'عملیات قبلا با موفقیت انجام شده است', 77 | 'error_34' => 'شماره تراکنش فرونشده درست نمی باشد', 78 | 79 | 'could_not_continue_with_non0_rs' => 'امکان تایید این تراکنش از سمت درگاه پرداخت وجود ندارد', 80 | 'invalid_response' => 'پاسخ معتبر از سرور درگاه پرداخت دریافت نشد!', 81 | ] 82 | ], 83 | 'pasargad' => [ 84 | 'errors' => [ 85 | 86 | ] 87 | ], 88 | 'saderat' => [ 89 | 'errors' => [ 90 | 'error_1' => 'وجود خطا در فرمت اطلاعات ارسالی', 91 | 'error_2' => 'عدم وجود پذیرنده و ترمینال مورد درخواست در سیستم', 92 | 'error_3' => 'رد درخواست به علت دریافت درخواست توسط آدرس آی پی نامعتبر', 93 | 'error_4' => 'پذیرنده مورد نظر امکان استفاده از سیستم را ندارد', 94 | 'error_5' => 'برخورد با مشکل در انجام درخواست مورد نظر', 95 | 'error_6' => 'خطا در پردازش درخواست', 96 | 'error_7' => 'بروز خطا در تشخیص اصالت اطلاعات (امضای دیجیتالی نامعتبر است)', 97 | 'error_8' => 'شماره خرید ارائه شده توسط پذیرنده (CRN) تکراری است', 98 | 'error_9' => 'سیستم در حال حاضر قادر به سرویس دهی نمی باشد (این پیام هنگام بروزرسانی سرور برگردانده می شود)', 99 | 'error_102' => 'تراکنش مورد نظر برگشت خورده است', 100 | 'error_103' => 'تایید انجام نشد', 101 | 'error_106' => 'پیامی از سوییچ پرداخت دریافت نشد', 102 | 'error_107' => 'تراکنش درخواستی موجود نیست', 103 | 'error_111' => 'مشکل در ارتباط با سوییچ', 104 | 'error_112' => 'مقادیر ارسالی در درخواست معتبر نیستند', 105 | 'error_113' => 'خطای سمت سرور (مربوط به واحد فنی PSP)', 106 | 'error_200' => 'تراکنش بانکی توسط کاربر لغو شد', 107 | 'error__1' => 'امضای دیجیتال مشکل دارد و با اطلاعات ارسالی همخوانی ندارد', 108 | 'error__2' => 'دسترسی از IP غیر مجاز است', 109 | 110 | 'making_openssl_sign_error' => 'ایجاد امضای دیجیتال با استفاده از openssl موفقیت آمیز نبود', 111 | 'invalid_verify_result' => 'اطلاعات دریافتی از درگاه پرداخت معتبر نمی باشد', 112 | 'invalid_transaction' => 'تراکنش شما معتبر نیست', 113 | 'public_key_file_not_found' => 'فایل public key در مسیر مورد نظر وجود ندارد', 114 | 'private_key_file_not_found' => 'فایل private key در مسیر مورد نظر وجود ندارد', 115 | ] 116 | ], 117 | 'zarinpal' => [ 118 | 'errors' => [ 119 | 'error_101' => 'عملیات پرداخت موفق بوده و قبلا PaymentVerification تراکنش انجام شده است', 120 | 121 | 'error__1' => 'اطلاعات ارسال شده ناقص است', //-1 122 | 'error__2' => 'IP و یا مرچنت کد پذیرنده صحیح نیست', //-1 123 | 'error__3' => 'با توجه به محدودیت‌های شاپرک امکان پرداخت با رقم درخواست شده میسر نمی باشد', 124 | 'error__4' => 'سطح تایید پذیرنده پایین تز از سطح نقره است', 125 | 'error__11' => 'درخواست مورد نظر یافت نشد', 126 | 'error__12 '=> 'امکان ویرایش درخواست میسر نمی باشد', 127 | 'error__21 '=> 'هیچ نوع عملیات مالی برای این تراکنش یافت نشد', 128 | 'error__22 '=> 'تراکنش ناموفق می باشد', 129 | 'error__33 '=> 'رقم تراکنش با رقم پرداخت شده مطابقت ندارد', 130 | 'error__34 '=> 'سقف تقیسم تراکنش از لحاظ تعداد یا رقم عبور نموده است', 131 | 'error__40 '=> 'اجازه دسترسی به متد مربوطه وجود ندارد', 132 | 'error__41 '=> 'اطلاعات ارسال شده به AdditionalData غیر معتبر می باشد', 133 | 'error__42 '=> 'مدت زمان معتبر طول عمر شناسه پرداخت باید بین ۳۰ دقیقه تا ۴۵ روز باشد', 134 | 'error__54 '=> 'درخواست مورد نظر آرشیو شده است', 135 | ] 136 | ], 137 | 'idpay' => [ 138 | 'errors' => [ 139 | "error_1" => "پرداخت انجام نشده است.", 140 | "error_2" => "پرداخت ناموفق بوده است.", 141 | "error_3" => "خطا رخ داده است.", 142 | "error_4" => "بلوکه شده.", 143 | "error_5" => "برگشت به پرداخت کننده.", 144 | "error_6" => "برگشت خورده سیستمی.", 145 | "error_10" => "در انتظار تایید پرداخت.", 146 | "error_100" => "پرداخت تایید شده است.", 147 | "error_101" => "پرداخت قبلا تایید شده است.", 148 | "error_200" => "به دریافت کننده واریز شد.", 149 | "error_11" => "کاربر مسدود شده است.", 150 | "error_12" => "API Key یافت نشد.", 151 | "error_13" => "درخواست شما از {ip} ارسال شده است. این IP با IP های ثبت شده در وب سرویس همخوانی ندارد.", 152 | "error_14" => "وب سرویس تایید نشده است.", 153 | "error_21" => "حساب بانکی متصل به وب سرویس تایید نشده است.", 154 | "error_31" => "کد تراکنش id نباید خالی باشد.", 155 | "error_32" => "شماره سفارش order_id نباید خالی باشد.", 156 | "error_33" => "مبلغ amount نباید خالی باشد.", 157 | "error_34" => "مبلغ amount باید بیشتر از {min-amount} ریال باشد.", 158 | "error_35" => "مبلغ amount باید کمتر از {max-amount} ریال باشد.", 159 | "error_36" => "مبلغ amount بیشتر از حد مجاز است.", 160 | "error_37" => "آدرس بازگشت callback نباید خالی باشد.", 161 | "error_38" => "درخواست شما از آدرس {domain} ارسال شده است. دامنه آدرس بازگشت callback با آدرس ثبت شده در وب سرویس همخوانی ندارد.", 162 | "error_51" => "تراکنش ایجاد نشد.", 163 | "error_52" => "استعلام نتیجه ای نداشت.", 164 | "error_53" => "تایید پرداخت امکان پذیر نیست.", 165 | "error_54" => "مدت زمان تایید پرداخت سپری شده است.", 166 | ] 167 | ], 168 | 'zibal' => [ 169 | 'errors' => [ 170 | "error_-1" => "در انتظار پردخت.", 171 | "error_-2" => "خطای داخلی.", 172 | "error_1" => "پرداخت شده - تاییدشده.", 173 | "error_2" => "پرداخت شده - تاییدنشده.", 174 | "error_3" => "لغوشده توسط کاربر.", 175 | "error_4" => "‌شماره کارت نامعتبر می‌باشد.", 176 | "error_5" => "‌موجودی حساب کافی نمی‌باشد.", 177 | "error_6" => "رمز واردشده اشتباه می‌باشد.", 178 | "error_8" => "‌تعداد درخواست‌ها بیش از حد مجاز می‌باشد.", 179 | "error_9" => "‌مبلغ پرداخت اینترنتی روزانه بیش از حد مجاز می‌باشد.", 180 | "error_10" => "‌صادرکننده‌ی کارت نامعتبر می‌باشد.", 181 | "error_11" => "‌خطای سوییچ", 182 | "error_12" => "کارت قابل دسترسی نمی‌باشد.", 183 | "error_102" => "merchant یافت نشد.", 184 | "error_104" => "merchant نامعتبر", 185 | "error_103" => "merchant غیرفعال", 186 | "error_201" => "پرداخت قبلا تایید شده است.", 187 | "error_202" => "سفارش پرداخت نشده یا ناموفق بوده است. جهت اطلاعات بیشتر جدول وضعیت‌ها را مطالعه کنید.", 188 | "error_203" => "trackId نامعتبر می‌باشد.", 189 | ] 190 | ], 191 | 'payir' => [ 192 | 'errors' => [ 193 | 'error_0' => 'درحال حاضر درگاه بانکی قطع شده و مشکل بزودی برطرف می شود', 194 | 'error_-1' => 'API Key ارسال نمی شود', 195 | 'error_-2' => 'Token ارسال نمی شود', 196 | 'error_-3' => 'API Key ارسال شده اشتباه است', 197 | 'error_-4' => 'امکان انجام تراکنش برای این پذیرنده وجود ندارد', 198 | 'error_-5' => 'تراکنش با خطا مواجه شده است', 199 | 'error_-6' => 'تراکنش تکراریست یا قبلا انجام شده', 200 | 'error_-7' => 'مقدار Token ارسالی اشتباه است', 201 | 'error_-8' => 'شماره تراکنش ارسالی اشتباه است', 202 | 'error_-9' => 'زمان مجاز برای انجام تراکنش تمام شده', 203 | 'error_-10' => 'مبلغ تراکنش ارسال نمی شود', 204 | 'error_-11' => 'مبلغ تراکنش باید به صورت عددی و با کاراکترهای لاتین باشد', 205 | 'error_-12' => 'مبلغ تراکنش می بایست عددی بین 10,000 و 500,000,000 ریال باشد', 206 | 'error_-13' => 'مقدار آدرس بازگشتی ارسال نمی شود', 207 | 'error_-14' => 'آدرس بازگشتی ارسالی با آدرس درگاه ثبت شده در شبکه پرداخت پی یکسان نیست', 208 | 'error_-15' => 'امکان وریفای وجود ندارد. این تراکنش پرداخت نشده است', 209 | 'error_-16' => 'یک یا چند شماره موبایل از اطلاعات پذیرندگان ارسال شده اشتباه است', 210 | 'error_-17' => 'میزان سهم ارسالی باید بصورت عددی و بین 1 تا 100 باشد', 211 | 'error_-18' => 'فرمت پذیرندگان صحیح نمی باشد', 212 | 'error_-19' => 'هر پذیرنده فقط یک سهم میتواند داشته باشد', 213 | 'error_-20' => 'مجموع سهم پذیرنده ها باید 100 درصد باشد', 214 | 'error_-21' => 'Reseller ID ارسالی اشتباه است', 215 | 'error_-22' => 'فرمت یا طول مقادیر ارسالی به درگاه اشتباه است', 216 | 'error_-23' => 'سوییچ PSP ( درگاه بانک ) قادر به پردازش درخواست نیست. لطفا لحظاتی بعد مجددا تلاش کنید', 217 | 'error_-24' => 'شماره کارت باید بصورت 16 رقمی، لاتین و چسبیده بهم باشد', 218 | 'error_-25' => 'امکان استفاده از سرویس در کشور مبدا شما وجود نداره', 219 | 'error_-26' => 'امکان انجام تراکنش برای این درگاه وجود ندارد', 220 | 'error_-27' => 'در انتظار تایید درگاه توسط شاپرک', 221 | 'error_-28' => 'امکان تسهیم تراکنش برای این درگاه وجود ندارد', 222 | ] 223 | ], 224 | 'nextpay' => [ 225 | 'errors' => [ 226 | 'error_0' => "تراکنش تکمیل و موفق است", 227 | 'error_-1' => "حالت پیش فرض تراکنش", 228 | 'error_-2' => "خطای بانکی یا انصراف از پرداخت", 229 | 'error_-3' => "در انتظار پرداخت بانکی", 230 | 'error_-4' => "انصراف در درگاه بانک", 231 | 'error_-20' => "کلید مجوزدهی ارسال نشده است", 232 | 'error_-21' => "شماره تراکنش ارسال نشده است", 233 | 'error_-22' => "مبلغ ارسال نشده است", 234 | 'error_-23' => "مسیر بازگشت ارسال نشده است", 235 | 'error_-24' => "مبلغ اشتباه است", 236 | 'error_-25' => "شماره تراکنش تکراریست و قادر به ادامه کار نیستید", 237 | 'error_-26' => "توکن ارسال نشده است", 238 | 'error_-30' => "مقدار مبلغ کمتر از ۱۰۰ تومان است", 239 | 'error_-32' => "مسیر بازگشت خطا دارد", 240 | 'error_-33' => "ساختار کلید مجوز دهی صحیح نیست", 241 | 'error_-34' => "شماره تراکنش صحیح نیست", 242 | 'error_-35' => "نوع کلید مجوز دهی صحیح نیست", 243 | 'error_-36' => "شماره سفارش ارسال نشده است", 244 | 'error_-37' => "تراکنش یافت نشد", 245 | 'error_-38' => "توکن یافت نشد", 246 | 'error_-39' => "کلید مجوز دهی یافت نشد", 247 | 'error_-40' => "کلید مجوز دهی مسدود شده است", 248 | 'error_-41' => "پارامتر های ارسالی از بانک مورد تایید نیست", 249 | 'error_-42' => "سیستم پرداخت دچار مشکل شده است", 250 | 'error_-43' => "درگاهی برای پرداخت یافت نشد", 251 | 'error_-44' => "پاسخ بانک صحیح نیست", 252 | 'error_-45' => "سیستم پرداخت غیر فعال شده است", 253 | 'error_-46' => "درخواست اشتباه", 254 | 'error_-48' => "نرخ کمیسیون تعیین نشده است", 255 | 'error_-49' => "تراکنش تکراریست", 256 | 'error_-50' => "حساب کاربری یافت نشد", 257 | 'error_-51' => "کاربر یافت نشد", 258 | 'error_-60' => "ایمیل صحیح نیست", 259 | 'error_-61' => "کد ملی صحیح نیست", 260 | 'error_-62' => "کد پستی صحیح نیست", 261 | 'error_-63' => "آدرس پستی صحیح نیست", 262 | 'error_-64' => "توضیحات صحیح نیست", 263 | 'error_-65' => "نام و نام خانوادگی صحیح نیست", 264 | 'error_-66' => "شماره تلفن صحیح نیست", 265 | 'error_-67' => "نام کاربری صحیح نیست", 266 | 'error_-68' => "نام محصول صحیح نیست", 267 | 'error_-69' => "مسیر بازگشت برای حالت موفق صحیح نیست", 268 | 'error_-70' => "مسیر بازگشت برای حالت ناموفق صحیح نیست", 269 | 'error_-71' => "شماره موبایل صحیح نیست", 270 | 'error_-72' => "بانک عامل پاسخ گو نیست" 271 | ] 272 | ] 273 | 274 | ]; 275 | -------------------------------------------------------------------------------- /translations/fa/larapay.php: -------------------------------------------------------------------------------- 1 | 'خطای هندل نشده!', // unofficial error code --- added by PhpMonsters 5 | 6 | 'canceled_by_user' => 'تراکنش بانکی توسط کاربر لغو شد', 7 | 'could_not_request_payment' => 'امکان درخواست توکن برای این تراکنش وجود ندارد', 8 | 'could_not_verify_transaction' => 'امکان تایید این تراکنش وجود ندارد', 9 | 'could_not_inquiry_payment' => 'امکان استعلام این تراکنش وجود ندارد', 10 | 'could_not_settle_payment' => 'امکان درخواست واریز وجه برای این تراکنش وجود ندارد', 11 | 'could_not_reverse_payment' => 'انمان بازگشت این تراکنش وجود ندارد', 12 | 'gate_not_ready' => 'درگاه پرداختی یا وجود ندارد یا آماده سرویس دهی نمی باشد', 13 | 'gate_not_implemented_larapay' => 'دروازه پرداخت :name از PhpMonsters\\Larapay\\Adapter\\AdapterInterface پیروی نمی کند', 14 | 'goto_gate' => 'اتصال به درگاه پرداخت', 15 | 'invalid_response' => 'پاسخ معتبر از سرور درگاه پرداخت دریافت نشد!', 16 | 'reversed_failed' => 'بازگشت تراکنش با موفقیت انجام نشد!', 17 | 'verification_failed' => 'تایید تراکنش با موفقیت انجام نشد!', 18 | 'after_verification_failed' => 'تایید بعد از تراکنش با موفقیت انجام نشد!', 19 | 'invalid_sharing_data' => 'اطلاعات تسهیم معتبر نیست', 20 | 'transaction_not_found' => 'تراکنش پیدا نشد', 21 | 22 | 'mellat' => [ 23 | 'errors' => [ 24 | 'error_11' => 'شماره کارت نامعتبر است', 25 | 'error_12' => 'موجودی کافی نیست', 26 | 'error_13' => 'رمز نادرست است', 27 | 'error_14' => 'تعداد دفعات وارد کردن رمز بیش از حد مجاز است', 28 | 'error_15' => 'کارت نامعتبر است', 29 | 'error_16' => 'دفعات برداشت وجه بیش از حد مجاز است', 30 | 'error_17' => 'کاربر از انجام تراکنش منصرف شده است', 31 | 'error_18' => 'تاریخ انقضای کارت گذشته است', 32 | 'error_19' => 'مبلغ برداشت وجه بیش از حد مجاز است', 33 | 'error_21' => 'پذیرنده نامعتبر است', 34 | 'error_23' => 'خطای امنیتی رخ داده است', 35 | 'error_24' => 'اطلاعات کاربری پذیرنده نامعتبر است', 36 | 'error_25' => 'مبلغ نامعتبر است', 37 | 'error_31' => 'پاسخ نامعتبر است', 38 | 'error_32' => 'فرمت اطلاعات وارد شده صحیح نمی‌باشد', 39 | 'error_33' => 'حساب نامعتبر است', 40 | 'error_34' => 'خطای سیستمی', 41 | 'error_35' => 'تاریخ نامعتبر است', 42 | 'error_41' => 'شماره درخواست تکراری است', 43 | 'error_42' => 'تراکنش Sale یافت نشد', 44 | 'error_43' => 'قبلا درخواست Verfiy داده شده است', 45 | 'error_44' => 'درخواست Verfiy یافت نشد', 46 | 'error_45' => 'تراکنش Settle شده است', 47 | 'error_46' => 'تراکنش Settle نشده است', 48 | 'error_47' => 'تراکنش Settle یافت نشد', 49 | 'error_48' => 'تراکنش Reverse شده است', 50 | 'error_49' => 'تراکنش Refund یافت نشد.', 51 | 'error_51' => 'تراکنش تکراری است', 52 | 'error_54' => 'تراکنش مرجع موجود نیست', 53 | 'error_55' => 'تراکنش نامعتبر است', 54 | 'error_61' => 'خطا در واریز', 55 | 'error_111' => 'صادر کننده کارت نامعتبر است', 56 | 'error_112' => 'خطای سوییچ صادر کننده کارت', 57 | 'error_113' => 'پاسخی از صادر کننده کارت دریافت نشد', 58 | 'error_114' => 'دارنده این کارت مجاز به انجام این تراکنش نیست', 59 | 'error_412' => 'شناسه قبض نادرست است', 60 | 'error_413' => 'شناسه پرداخت نادرست است', 61 | 'error_414' => 'سازمان صادر کننده قبض نامعتبر است', 62 | 'error_415' => 'زمان جلسه کاری به پایان رسیده است', 63 | 'error_416' => 'خطا در ثبت اطلاعات', 64 | 'error_417' => 'شناسه پرداخت کننده نامعتبر است', 65 | 'error_418' => 'اشکال در تعریف اطلاعات مشتری', 66 | 'error_419' => 'تعداد دفعات ورود اطلاعات از حد مجاز گذشته است', 67 | 'error_421' => 'IP نامعتبر است', 68 | 69 | 'invalid_response' => 'پاسخ معتبر از سرور درگاه پرداخت دریافت نشد!', 70 | ] 71 | ], 72 | 'parsian' => [ 73 | 'errors' => [ 74 | 'error_20' => 'پین فروشنده درست نمی باشد', 75 | 'error_22' => 'پین فروشنده درست نمی باشد', 76 | 'error_30' => 'عملیات قبلا با موفقیت انجام شده است', 77 | 'error_34' => 'شماره تراکنش فرونشده درست نمی باشد', 78 | 79 | 'could_not_continue_with_non0_rs' => 'امکان تایید این تراکنش از سمت درگاه پرداخت وجود ندارد', 80 | 'invalid_response' => 'پاسخ معتبر از سرور درگاه پرداخت دریافت نشد!', 81 | ] 82 | ], 83 | 'pasargad' => [ 84 | 'errors' => [ 85 | 86 | ] 87 | ], 88 | 'saderat' => [ 89 | 'errors' => [ 90 | 'error_1' => 'وجود خطا در فرمت اطلاعات ارسالی', 91 | 'error_2' => 'عدم وجود پذیرنده و ترمینال مورد درخواست در سیستم', 92 | 'error_3' => 'رد درخواست به علت دریافت درخواست توسط آدرس آی پی نامعتبر', 93 | 'error_4' => 'پذیرنده مورد نظر امکان استفاده از سیستم را ندارد', 94 | 'error_5' => 'برخورد با مشکل در انجام درخواست مورد نظر', 95 | 'error_6' => 'خطا در پردازش درخواست', 96 | 'error_7' => 'بروز خطا در تشخیص اصالت اطلاعات (امضای دیجیتالی نامعتبر است)', 97 | 'error_8' => 'شماره خرید ارائه شده توسط پذیرنده (CRN) تکراری است', 98 | 'error_9' => 'سیستم در حال حاضر قادر به سرویس دهی نمی باشد (این پیام هنگام بروزرسانی سرور برگردانده می شود)', 99 | 'error_102' => 'تراکنش مورد نظر برگشت خورده است', 100 | 'error_103' => 'تایید انجام نشد', 101 | 'error_106' => 'پیامی از سوییچ پرداخت دریافت نشد', 102 | 'error_107' => 'تراکنش درخواستی موجود نیست', 103 | 'error_111' => 'مشکل در ارتباط با سوییچ', 104 | 'error_112' => 'مقادیر ارسالی در درخواست معتبر نیستند', 105 | 'error_113' => 'خطای سمت سرور (مربوط به واحد فنی PSP)', 106 | 'error_200' => 'تراکنش بانکی توسط کاربر لغو شد', 107 | 'error__1' => 'امضای دیجیتال مشکل دارد و با اطلاعات ارسالی همخوانی ندارد', 108 | 'error__2' => 'دسترسی از IP غیر مجاز است', 109 | 110 | 'making_openssl_sign_error' => 'ایجاد امضای دیجیتال با استفاده از openssl موفقیت آمیز نبود', 111 | 'invalid_verify_result' => 'اطلاعات دریافتی از درگاه پرداخت معتبر نمی باشد', 112 | 'invalid_transaction' => 'تراکنش شما معتبر نیست', 113 | 'public_key_file_not_found' => 'فایل public key در مسیر مورد نظر وجود ندارد', 114 | 'private_key_file_not_found' => 'فایل private key در مسیر مورد نظر وجود ندارد', 115 | ] 116 | ], 117 | 'zarinpal' => [ 118 | 'errors' => [ 119 | 'error_101' => 'عملیات پرداخت موفق بوده و قبلا PaymentVerification تراکنش انجام شده است', 120 | 121 | 'error__1' => 'اطلاعات ارسال شده ناقص است', //-1 122 | 'error__2' => 'IP و یا مرچنت کد پذیرنده صحیح نیست', //-1 123 | 'error__3' => 'با توجه به محدودیت‌های شاپرک امکان پرداخت با رقم درخواست شده میسر نمی باشد', 124 | 'error__4' => 'سطح تایید پذیرنده پایین تز از سطح نقره است', 125 | 'error__11' => 'درخواست مورد نظر یافت نشد', 126 | 'error__12 '=> 'امکان ویرایش درخواست میسر نمی باشد', 127 | 'error__21 '=> 'هیچ نوع عملیات مالی برای این تراکنش یافت نشد', 128 | 'error__22 '=> 'تراکنش ناموفق می باشد', 129 | 'error__33 '=> 'رقم تراکنش با رقم پرداخت شده مطابقت ندارد', 130 | 'error__34 '=> 'سقف تقیسم تراکنش از لحاظ تعداد یا رقم عبور نموده است', 131 | 'error__40 '=> 'اجازه دسترسی به متد مربوطه وجود ندارد', 132 | 'error__41 '=> 'اطلاعات ارسال شده به AdditionalData غیر معتبر می باشد', 133 | 'error__42 '=> 'مدت زمان معتبر طول عمر شناسه پرداخت باید بین ۳۰ دقیقه تا ۴۵ روز باشد', 134 | 'error__54 '=> 'درخواست مورد نظر آرشیو شده است', 135 | ] 136 | ], 137 | 'idpay' => [ 138 | 'errors' => [ 139 | "error_1" => "پرداخت انجام نشده است.", 140 | "error_2" => "پرداخت ناموفق بوده است.", 141 | "error_3" => "خطا رخ داده است.", 142 | "error_4" => "بلوکه شده.", 143 | "error_5" => "برگشت به پرداخت کننده.", 144 | "error_6" => "برگشت خورده سیستمی.", 145 | "error_10" => "در انتظار تایید پرداخت.", 146 | "error_100" => "پرداخت تایید شده است.", 147 | "error_101" => "پرداخت قبلا تایید شده است.", 148 | "error_200" => "به دریافت کننده واریز شد.", 149 | "error_11" => "کاربر مسدود شده است.", 150 | "error_12" => "API Key یافت نشد.", 151 | "error_13" => "درخواست شما از {ip} ارسال شده است. این IP با IP های ثبت شده در وب سرویس همخوانی ندارد.", 152 | "error_14" => "وب سرویس تایید نشده است.", 153 | "error_21" => "حساب بانکی متصل به وب سرویس تایید نشده است.", 154 | "error_31" => "کد تراکنش id نباید خالی باشد.", 155 | "error_32" => "شماره سفارش order_id نباید خالی باشد.", 156 | "error_33" => "مبلغ amount نباید خالی باشد.", 157 | "error_34" => "مبلغ amount باید بیشتر از {min-amount} ریال باشد.", 158 | "error_35" => "مبلغ amount باید کمتر از {max-amount} ریال باشد.", 159 | "error_36" => "مبلغ amount بیشتر از حد مجاز است.", 160 | "error_37" => "آدرس بازگشت callback نباید خالی باشد.", 161 | "error_38" => "درخواست شما از آدرس {domain} ارسال شده است. دامنه آدرس بازگشت callback با آدرس ثبت شده در وب سرویس همخوانی ندارد.", 162 | "error_51" => "تراکنش ایجاد نشد.", 163 | "error_52" => "استعلام نتیجه ای نداشت.", 164 | "error_53" => "تایید پرداخت امکان پذیر نیست.", 165 | "error_54" => "مدت زمان تایید پرداخت سپری شده است.", 166 | ] 167 | ], 168 | 'zibal' => [ 169 | 'errors' => [ 170 | "error_-1" => "در انتظار پردخت.", 171 | "error_-2" => "خطای داخلی.", 172 | "error_1" => "پرداخت شده - تاییدشده.", 173 | "error_2" => "پرداخت شده - تاییدنشده.", 174 | "error_3" => "لغوشده توسط کاربر.", 175 | "error_4" => "‌شماره کارت نامعتبر می‌باشد.", 176 | "error_5" => "‌موجودی حساب کافی نمی‌باشد.", 177 | "error_6" => "رمز واردشده اشتباه می‌باشد.", 178 | "error_8" => "‌تعداد درخواست‌ها بیش از حد مجاز می‌باشد.", 179 | "error_9" => "‌مبلغ پرداخت اینترنتی روزانه بیش از حد مجاز می‌باشد.", 180 | "error_10" => "‌صادرکننده‌ی کارت نامعتبر می‌باشد.", 181 | "error_11" => "‌خطای سوییچ", 182 | "error_12" => "کارت قابل دسترسی نمی‌باشد.", 183 | "error_102" => "merchant یافت نشد.", 184 | "error_104" => "merchant نامعتبر", 185 | "error_103" => "merchant غیرفعال", 186 | "error_201" => "پرداخت قبلا تایید شده است.", 187 | "error_202" => "سفارش پرداخت نشده یا ناموفق بوده است. جهت اطلاعات بیشتر جدول وضعیت‌ها را مطالعه کنید.", 188 | "error_203" => "trackId نامعتبر می‌باشد.", 189 | ] 190 | ], 191 | 'payir' => [ 192 | 'errors' => [ 193 | 'error_0' => 'درحال حاضر درگاه بانکی قطع شده و مشکل بزودی برطرف می شود', 194 | 'error_-1' => 'API Key ارسال نمی شود', 195 | 'error_-2' => 'Token ارسال نمی شود', 196 | 'error_-3' => 'API Key ارسال شده اشتباه است', 197 | 'error_-4' => 'امکان انجام تراکنش برای این پذیرنده وجود ندارد', 198 | 'error_-5' => 'تراکنش با خطا مواجه شده است', 199 | 'error_-6' => 'تراکنش تکراریست یا قبلا انجام شده', 200 | 'error_-7' => 'مقدار Token ارسالی اشتباه است', 201 | 'error_-8' => 'شماره تراکنش ارسالی اشتباه است', 202 | 'error_-9' => 'زمان مجاز برای انجام تراکنش تمام شده', 203 | 'error_-10' => 'مبلغ تراکنش ارسال نمی شود', 204 | 'error_-11' => 'مبلغ تراکنش باید به صورت عددی و با کاراکترهای لاتین باشد', 205 | 'error_-12' => 'مبلغ تراکنش می بایست عددی بین 10,000 و 500,000,000 ریال باشد', 206 | 'error_-13' => 'مقدار آدرس بازگشتی ارسال نمی شود', 207 | 'error_-14' => 'آدرس بازگشتی ارسالی با آدرس درگاه ثبت شده در شبکه پرداخت پی یکسان نیست', 208 | 'error_-15' => 'امکان وریفای وجود ندارد. این تراکنش پرداخت نشده است', 209 | 'error_-16' => 'یک یا چند شماره موبایل از اطلاعات پذیرندگان ارسال شده اشتباه است', 210 | 'error_-17' => 'میزان سهم ارسالی باید بصورت عددی و بین 1 تا 100 باشد', 211 | 'error_-18' => 'فرمت پذیرندگان صحیح نمی باشد', 212 | 'error_-19' => 'هر پذیرنده فقط یک سهم میتواند داشته باشد', 213 | 'error_-20' => 'مجموع سهم پذیرنده ها باید 100 درصد باشد', 214 | 'error_-21' => 'Reseller ID ارسالی اشتباه است', 215 | 'error_-22' => 'فرمت یا طول مقادیر ارسالی به درگاه اشتباه است', 216 | 'error_-23' => 'سوییچ PSP ( درگاه بانک ) قادر به پردازش درخواست نیست. لطفا لحظاتی بعد مجددا تلاش کنید', 217 | 'error_-24' => 'شماره کارت باید بصورت 16 رقمی، لاتین و چسبیده بهم باشد', 218 | 'error_-25' => 'امکان استفاده از سرویس در کشور مبدا شما وجود نداره', 219 | 'error_-26' => 'امکان انجام تراکنش برای این درگاه وجود ندارد', 220 | 'error_-27' => 'در انتظار تایید درگاه توسط شاپرک', 221 | 'error_-28' => 'امکان تسهیم تراکنش برای این درگاه وجود ندارد', 222 | ] 223 | ], 224 | 'nextpay' => [ 225 | 'errors' => [ 226 | 'error_0' => "تراکنش تکمیل و موفق است", 227 | 'error_-1' => "حالت پیش فرض تراکنش", 228 | 'error_-2' => "خطای بانکی یا انصراف از پرداخت", 229 | 'error_-3' => "در انتظار پرداخت بانکی", 230 | 'error_-4' => "انصراف در درگاه بانک", 231 | 'error_-20' => "کلید مجوزدهی ارسال نشده است", 232 | 'error_-21' => "شماره تراکنش ارسال نشده است", 233 | 'error_-22' => "مبلغ ارسال نشده است", 234 | 'error_-23' => "مسیر بازگشت ارسال نشده است", 235 | 'error_-24' => "مبلغ اشتباه است", 236 | 'error_-25' => "شماره تراکنش تکراریست و قادر به ادامه کار نیستید", 237 | 'error_-26' => "توکن ارسال نشده است", 238 | 'error_-30' => "مقدار مبلغ کمتر از ۱۰۰ تومان است", 239 | 'error_-32' => "مسیر بازگشت خطا دارد", 240 | 'error_-33' => "ساختار کلید مجوز دهی صحیح نیست", 241 | 'error_-34' => "شماره تراکنش صحیح نیست", 242 | 'error_-35' => "نوع کلید مجوز دهی صحیح نیست", 243 | 'error_-36' => "شماره سفارش ارسال نشده است", 244 | 'error_-37' => "تراکنش یافت نشد", 245 | 'error_-38' => "توکن یافت نشد", 246 | 'error_-39' => "کلید مجوز دهی یافت نشد", 247 | 'error_-40' => "کلید مجوز دهی مسدود شده است", 248 | 'error_-41' => "پارامتر های ارسالی از بانک مورد تایید نیست", 249 | 'error_-42' => "سیستم پرداخت دچار مشکل شده است", 250 | 'error_-43' => "درگاهی برای پرداخت یافت نشد", 251 | 'error_-44' => "پاسخ بانک صحیح نیست", 252 | 'error_-45' => "سیستم پرداخت غیر فعال شده است", 253 | 'error_-46' => "درخواست اشتباه", 254 | 'error_-48' => "نرخ کمیسیون تعیین نشده است", 255 | 'error_-49' => "تراکنش تکراریست", 256 | 'error_-50' => "حساب کاربری یافت نشد", 257 | 'error_-51' => "کاربر یافت نشد", 258 | 'error_-60' => "ایمیل صحیح نیست", 259 | 'error_-61' => "کد ملی صحیح نیست", 260 | 'error_-62' => "کد پستی صحیح نیست", 261 | 'error_-63' => "آدرس پستی صحیح نیست", 262 | 'error_-64' => "توضیحات صحیح نیست", 263 | 'error_-65' => "نام و نام خانوادگی صحیح نیست", 264 | 'error_-66' => "شماره تلفن صحیح نیست", 265 | 'error_-67' => "نام کاربری صحیح نیست", 266 | 'error_-68' => "نام محصول صحیح نیست", 267 | 'error_-69' => "مسیر بازگشت برای حالت موفق صحیح نیست", 268 | 'error_-70' => "مسیر بازگشت برای حالت ناموفق صحیح نیست", 269 | 'error_-71' => "شماره موبایل صحیح نیست", 270 | 'error_-72' => "بانک عامل پاسخ گو نیست" 271 | ] 272 | ] 273 | 274 | ]; 275 | -------------------------------------------------------------------------------- /views/idpay-form.blade.php: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 |
6 |
7 |
8 | 9 | @if($autoSubmit === true) 10 | 14 | @endif 15 | -------------------------------------------------------------------------------- /views/mellat-form.blade.php: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 | 6 |
7 |
8 |
9 | 10 | @if($autoSubmit === true) 11 | 15 | @endif -------------------------------------------------------------------------------- /views/nextpay-form.blade.php: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 |
6 |
7 |
8 | 9 | @if($autoSubmit === true) 10 | 14 | @endif 15 | -------------------------------------------------------------------------------- /views/parsian-form.blade.php: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 | 6 |
7 |
8 |
9 | 10 | @if($autoSubmit === true) 11 | 15 | @endif 16 | 17 | 18 | -------------------------------------------------------------------------------- /views/pasargad-form.blade.php: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 | 14 |
15 |
16 |
17 | 18 | @if($autoSubmit === true) 19 | 23 | @endif 24 | -------------------------------------------------------------------------------- /views/payir-form.blade.php: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 |
6 |
7 |
8 | 9 | @if($autoSubmit === true) 10 | 14 | @endif -------------------------------------------------------------------------------- /views/sadad-form.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | {!! $form !!} 4 |
5 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /views/saderat-form.blade.php: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 | 6 |
7 |
8 |
9 | 10 | @if($autoSubmit === true) 11 | 15 | @endif -------------------------------------------------------------------------------- /views/saman-form.blade.php: -------------------------------------------------------------------------------- 1 |
2 | @if(isset($token) && !empty($token)) 3 | 4 | @else 5 | 6 | 7 | 8 | @endif 9 | 10 |
11 |
12 | 13 |
14 |
15 |
16 | 17 | @if($autoSubmit === true) 18 | 22 | @endif 23 | 24 | 25 | -------------------------------------------------------------------------------- /views/zarinpal-form.blade.php: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 |
6 |
7 |
8 | 9 | @if($autoSubmit === true) 10 | 14 | @endif -------------------------------------------------------------------------------- /views/zibal-form.blade.php: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 |
6 |
7 |
8 | 9 | @if($autoSubmit === true) 10 | 14 | @endif 15 | --------------------------------------------------------------------------------