├── .gitignore ├── README.md ├── composer.json └── src ├── Events └── SSLCommerzPaymentComplete.php ├── Facades └── SSLCommerzFacade.php ├── Http ├── Controllers │ └── SSLCommerzPaymentController.php └── Middleware │ └── VerifyCsrfToken.php ├── SSLCommerzServiceProvider.php ├── Services ├── AbstractSSLCommerz.php ├── SSLCommerz.php └── SSLCommerzInterface.php ├── config └── sslcommerz.php ├── database └── migrations │ └── 0000_00_00_000000_create_payments_table.php ├── resources └── views │ ├── exampleEasycheckout.blade.php │ └── exampleHosted.blade.php └── routes └── sslcommerzroutes.php /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | composer.lock 3 | /vendor 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rupokify\SSLCommerz 2 | 3 | SSLCommerz is a Laravel Package for the SSLCommerz Payment Gateway API 4 | 5 | ## Installation 6 | 7 | You will need [composer](https://getcomposer.org/) to install SSLCommerz. Then publish assets and migrate the table for payment records. 8 | 9 | ```bash 10 | composer require "rupokify/sslcommerz" --no-cache 11 | php artisan vendor:publish 12 | php artisan migrate 13 | ``` 14 | 15 | I haven't tested it below Laravel 5.5 . If you wanna try in below Laravel 5.5 , you will need to edit **config/app.php** and add the following line in the providers section. 16 | 17 | ```php 18 | Rupokify\SSLCommerz\SSLCommerzServiceProvider::class 19 | ``` 20 | 21 | Add the following constants in the **.env** file of your Laravel Project. 22 | 23 | ```bash 24 | API_DOMAIN_URL=https://sandbox.sslcommerz.com 25 | STORE_ID=PUT_YOUR_SANDBOX_STORE_ID 26 | STORE_PASSWORD=PUT_YOUR_SANDBOX_STORE_PASSWORD 27 | IS_LOCALHOST=true 28 | ``` 29 | 30 | Clear config cache if required. 31 | 32 | ```bash 33 | php artisan config:cache 34 | ``` 35 | 36 | That's it! Enjoy! 37 | 38 | ## Usage 39 | 40 | * Go to *http://yourdomain/example1* for testing the Payment Modal on your own site. 41 | * Go to *http://yourdomain/example2* for testing the Payment Modal from SSLCommerz site. 42 | 43 | For listening to the payment event, open your **app/Providers** directory and add your own listener for the **SSLCommerzPaymentComplete** event class. 44 | 45 | ## Changelog 46 | 47 | ### 1.0.0-alpha 48 | * Initial Release 49 | 50 | ### 1.0.1-alpha 51 | * Payment Event Added 52 | 53 | ## Nota Bene 54 | * I don't have any live SSLCommerz store. So could not test that. Please open an issue if you face any problem with **LIVE** payments so I can test with you and fix that. 55 | * I didn't refactor a single line of code from the [SSLCommerz Official Library](https://github.com/sslcommerz/Integration_in_Laravel-5.6-with-IPN). Don't blame/curse me for the coding of the Service Class, Abstract Class, Interface and the View Templates. Maybe someday I'll have some time and will refactor their code ;) 56 | * Update (1.0.1-alpha): I added payment Event code in the official Controller. 57 | 58 | ## Contributing 59 | Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. 60 | 61 | ## License 62 | [MIT](https://opensource.org/licenses/MIT) 63 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rupokify/sslcommerz", 3 | "description": "Laravel Package for SSLCommerz Payment Gateway API", 4 | "type": "library", 5 | "keywords": ["laravel", "sslcommerz", "paymentgateway", "api"], 6 | "require": { 7 | "php": ">=7.1.3", 8 | "laravel/laravel": ">=5.5" 9 | }, 10 | "minimum-stability": "dev", 11 | "license": "MIT", 12 | "authors": [ 13 | { 14 | "name": "Rupok Chowdhury Protik", 15 | "email": "rupokify@gmail.com" 16 | } 17 | ], 18 | "extra": { 19 | "laravel": { 20 | "providers": [ 21 | "Rupokify\\SSLCommerz\\SSLCommerzServiceProvider" 22 | ], 23 | "aliases": { 24 | "SSLCommerz": "Rupokify\\SSLCommerz\\Facades\\SSLCommerzFacade" 25 | } 26 | } 27 | }, 28 | "autoload": { 29 | "psr-4": { 30 | "Rupokify\\SSLCommerz\\": "src/" 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Events/SSLCommerzPaymentComplete.php: -------------------------------------------------------------------------------- 1 | paymentdata = $paymentdata; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/Facades/SSLCommerzFacade.php: -------------------------------------------------------------------------------- 1 | where('transaction_id', $post_data['tran_id']) 71 | ->updateOrInsert([ 72 | 'name' => $post_data['cus_name'], 73 | 'email' => $post_data['cus_email'], 74 | 'phone' => $post_data['cus_phone'], 75 | 'amount' => $post_data['total_amount'], 76 | 'status' => 'Pending', 77 | 'address' => $post_data['cus_add1'], 78 | 'transaction_id' => $post_data['tran_id'], 79 | 'currency' => $post_data['currency'] 80 | ]); 81 | 82 | $sslc = new SSLCommerz(); 83 | # initiate(Transaction Data , false: Redirect to SSLCOMMERZ gateway/ true: Show all the Payement gateway here ) 84 | $payment_options = $sslc->makePayment($post_data, 'hosted'); 85 | 86 | if (!is_array($payment_options)) { 87 | print_r($payment_options); 88 | $payment_options = array(); 89 | } 90 | 91 | } 92 | 93 | public function payViaAjax(Request $request) 94 | { 95 | 96 | # Here you have to receive all the order data to initate the payment. 97 | # Lets your oder trnsaction informations are saving in a table called "payments" 98 | # In payments table order uniq identity is "transaction_id","status" field contain status of the transaction, "amount" is the order amount to be paid and "currency" is for storing Site Currency which will be checked with paid currency. 99 | 100 | $post_data = array(); 101 | $post_data['total_amount'] = '10'; # You cant not pay less than 10 102 | $post_data['currency'] = "BDT"; 103 | $post_data['tran_id'] = uniqid(); // tran_id must be unique 104 | 105 | # CUSTOMER INFORMATION 106 | $post_data['cus_name'] = 'Customer Name'; 107 | $post_data['cus_email'] = 'customer@mail.com'; 108 | $post_data['cus_add1'] = 'Customer Address'; 109 | $post_data['cus_add2'] = ""; 110 | $post_data['cus_city'] = ""; 111 | $post_data['cus_state'] = ""; 112 | $post_data['cus_postcode'] = ""; 113 | $post_data['cus_country'] = "Bangladesh"; 114 | $post_data['cus_phone'] = '8801XXXXXXXXX'; 115 | $post_data['cus_fax'] = ""; 116 | 117 | # SHIPMENT INFORMATION 118 | $post_data['ship_name'] = "Store Test"; 119 | $post_data['ship_add1'] = "Dhaka"; 120 | $post_data['ship_add2'] = "Dhaka"; 121 | $post_data['ship_city'] = "Dhaka"; 122 | $post_data['ship_state'] = "Dhaka"; 123 | $post_data['ship_postcode'] = "1000"; 124 | $post_data['ship_phone'] = ""; 125 | $post_data['ship_country'] = "Bangladesh"; 126 | 127 | $post_data['shipping_method'] = "NO"; 128 | $post_data['product_name'] = "Computer"; 129 | $post_data['product_category'] = "Goods"; 130 | $post_data['product_profile'] = "physical-goods"; 131 | 132 | # OPTIONAL PARAMETERS 133 | $post_data['value_a'] = "ref001"; 134 | $post_data['value_b'] = "ref002"; 135 | $post_data['value_c'] = "ref003"; 136 | $post_data['value_d'] = "ref004"; 137 | 138 | 139 | #Before going to initiate the payment order status need to update as Pending. 140 | $update_product = DB::table('payments') 141 | ->where('transaction_id', $post_data['tran_id']) 142 | ->updateOrInsert([ 143 | 'name' => $post_data['cus_name'], 144 | 'email' => $post_data['cus_email'], 145 | 'phone' => $post_data['cus_phone'], 146 | 'amount' => $post_data['total_amount'], 147 | 'status' => 'Pending', 148 | 'address' => $post_data['cus_add1'], 149 | 'transaction_id' => $post_data['tran_id'], 150 | 'currency' => $post_data['currency'] 151 | ]); 152 | 153 | $sslc = new SSLCommerz(); 154 | # initiate(Transaction Data , false: Redirect to SSLCOMMERZ gateway/ true: Show all the Payement gateway here ) 155 | $payment_options = $sslc->makePayment($post_data, 'checkout', 'json'); 156 | 157 | if (!is_array($payment_options)) { 158 | print_r($payment_options); 159 | $payment_options = array(); 160 | } 161 | 162 | } 163 | 164 | public function success(Request $request) 165 | { 166 | echo "Transaction is Successful"; 167 | 168 | $tran_id = $request->input('tran_id'); 169 | $amount = $request->input('amount'); 170 | $currency = $request->input('currency'); 171 | 172 | $sslc = new SSLCommerz(); 173 | 174 | #Check order status in order tabel against the transaction id or order id. 175 | $order_detials = DB::table('payments') 176 | ->where('transaction_id', $tran_id) 177 | ->select('transaction_id', 'status', 'currency', 'amount')->first(); 178 | 179 | if ($order_detials->status == 'Pending') { 180 | $validation = $sslc->orderValidate($tran_id, $amount, $currency, $request->all()); 181 | 182 | if ($validation == TRUE) { 183 | /* 184 | That means IPN did not work or IPN URL was not set in your merchant panel. Here you need to update order status 185 | in order table as Processing or Complete. 186 | Here you can also sent sms or email for successfull transaction to customer 187 | */ 188 | $update_product = DB::table('payments') 189 | ->where('transaction_id', $tran_id) 190 | ->update(['status' => 'Processing']); 191 | 192 | echo "
Transaction is successfully Completed"; 193 | } else { 194 | /* 195 | That means IPN did not work or IPN URL was not set in your merchant panel and Transation validation failed. 196 | Here you need to update order status as Failed in order table. 197 | */ 198 | $update_product = DB::table('payments') 199 | ->where('transaction_id', $tran_id) 200 | ->update(['status' => 'Failed']); 201 | echo "validation Fail"; 202 | } 203 | } else if ($order_detials->status == 'Processing' || $order_detials->status == 'Complete') { 204 | /* 205 | That means through IPN Order status already updated. Now you can just show the customer that transaction is completed. No need to udate database. 206 | */ 207 | echo "Transaction is successfully Completed"; 208 | } else { 209 | #That means something wrong happened. You can redirect customer to your product page. 210 | echo "Invalid Transaction"; 211 | } 212 | 213 | $paymentdata = DB::table('payments') 214 | ->where('transaction_id', $tran_id) 215 | ->first(); 216 | 217 | event(new SSLCommerzPaymentComplete($paymentdata)); 218 | 219 | } 220 | 221 | public function fail(Request $request) 222 | { 223 | $tran_id = $request->input('tran_id'); 224 | 225 | $order_detials = DB::table('payments') 226 | ->where('transaction_id', $tran_id) 227 | ->select('transaction_id', 'status', 'currency', 'amount')->first(); 228 | 229 | if ($order_detials->status == 'Pending') { 230 | $update_product = DB::table('payments') 231 | ->where('transaction_id', $tran_id) 232 | ->update(['status' => 'Failed']); 233 | echo "Transaction is Falied"; 234 | } else if ($order_detials->status == 'Processing' || $order_detials->status == 'Complete') { 235 | echo "Transaction is already Successful"; 236 | } else { 237 | echo "Transaction is Invalid"; 238 | } 239 | 240 | $paymentdata = DB::table('payments') 241 | ->where('transaction_id', $tran_id) 242 | ->first(); 243 | 244 | event(new SSLCommerzPaymentComplete($paymentdata)); 245 | 246 | } 247 | 248 | public function cancel(Request $request) 249 | { 250 | $tran_id = $request->input('tran_id'); 251 | 252 | $order_detials = DB::table('payments') 253 | ->where('transaction_id', $tran_id) 254 | ->select('transaction_id', 'status', 'currency', 'amount')->first(); 255 | 256 | if ($order_detials->status == 'Pending') { 257 | $update_product = DB::table('payments') 258 | ->where('transaction_id', $tran_id) 259 | ->update(['status' => 'Canceled']); 260 | echo "Transaction is Cancel"; 261 | } else if ($order_detials->status == 'Processing' || $order_detials->status == 'Complete') { 262 | echo "Transaction is already Successful"; 263 | } else { 264 | echo "Transaction is Invalid"; 265 | } 266 | 267 | $paymentdata = DB::table('payments') 268 | ->where('transaction_id', $tran_id) 269 | ->first(); 270 | 271 | event(new SSLCommerzPaymentComplete($paymentdata)); 272 | 273 | } 274 | 275 | public function ipn(Request $request) 276 | { 277 | #Received all the payement information from the gateway 278 | if ($request->input('tran_id')) #Check transation id is posted or not. 279 | { 280 | 281 | $tran_id = $request->input('tran_id'); 282 | 283 | #Check order status in order tabel against the transaction id or order id. 284 | $order_details = DB::table('payments') 285 | ->where('transaction_id', $tran_id) 286 | ->select('transaction_id', 'status', 'currency', 'amount')->first(); 287 | 288 | if ($order_details->status == 'Pending') { 289 | $sslc = new SSLCommerz(); 290 | $validation = $sslc->orderValidate($tran_id, $order_details->amount, $order_details->currency, $request->all()); 291 | if ($validation == TRUE) { 292 | /* 293 | That means IPN worked. Here you need to update order status 294 | in order table as Processing or Complete. 295 | Here you can also sent sms or email for successful transaction to customer 296 | */ 297 | $update_product = DB::table('payments') 298 | ->where('transaction_id', $tran_id) 299 | ->update(['status' => 'Processing']); 300 | 301 | echo "Transaction is successfully Completed"; 302 | } else { 303 | /* 304 | That means IPN worked, but Transation validation failed. 305 | Here you need to update order status as Failed in order table. 306 | */ 307 | $update_product = DB::table('payments') 308 | ->where('transaction_id', $tran_id) 309 | ->update(['status' => 'Failed']); 310 | 311 | echo "validation Fail"; 312 | } 313 | 314 | } else if ($order_details->status == 'Processing' || $order_details->status == 'Complete') { 315 | 316 | #That means Order status already updated. No need to udate database. 317 | 318 | echo "Transaction is already successfully Completed"; 319 | } else { 320 | #That means something wrong happened. You can redirect customer to your product page. 321 | 322 | echo "Invalid Transaction"; 323 | } 324 | } else { 325 | echo "Invalid Data"; 326 | } 327 | } 328 | 329 | public function dump(){ 330 | dd('Hello SSLCommerz from the Controller'); 331 | } 332 | 333 | } 334 | -------------------------------------------------------------------------------- /src/Http/Middleware/VerifyCsrfToken.php: -------------------------------------------------------------------------------- 1 | registerSSLCommerz(); 18 | } 19 | 20 | /** 21 | * Register SSLCommerz. 22 | * 23 | * @return void 24 | */ 25 | protected function registerSSLCommerz() 26 | { 27 | $this->app->bind('sslcommerz', function () { 28 | return new SSLCommerz(); 29 | }); 30 | } 31 | 32 | /** 33 | * Bootstrap services. 34 | * 35 | * @return void 36 | */ 37 | public function boot() 38 | { 39 | $this->bootSSLCommerz(); 40 | } 41 | 42 | /** 43 | * Bootstrap SSLCommerz. 44 | * 45 | * @return void 46 | */ 47 | protected function bootSSLCommerz() 48 | { 49 | $this->publishes([ 50 | __DIR__.'/config/sslcommerz.php' => config_path('sslcommerz.php'), 51 | __DIR__.'/resources/views' => $this->app->resourcePath('views/vendor/rupokify/sslcommerz'), 52 | __DIR__.'/database/migrations' => $this->app->databasePath('/migrations') 53 | ]); 54 | $this->mergeConfigFrom( 55 | __DIR__.'/config/sslcommerz.php', 'sslcommerz' 56 | ); 57 | $this->loadRoutesFrom( 58 | __DIR__.'/routes/sslcommerzroutes.php' 59 | ); 60 | $this->app['router']->middleware('web', 'Rupokify\SSLCommerz\Http\Middleware\VerifyCsrfToken::class'); 61 | } 62 | 63 | /** 64 | * Get the service provided by the provider. 65 | * 66 | * @return string[] 67 | */ 68 | public function provides() 69 | { 70 | return [ 71 | 'sslcommerz' 72 | ]; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/Services/AbstractSSLCommerz.php: -------------------------------------------------------------------------------- 1 | storeId = $storeID; 14 | } 15 | 16 | protected function getStoreId() 17 | { 18 | return $this->storeId; 19 | } 20 | 21 | protected function setStorePassword($storePassword) 22 | { 23 | $this->storePassword = $storePassword; 24 | } 25 | 26 | protected function getStorePassword() 27 | { 28 | return $this->storePassword; 29 | } 30 | 31 | protected function setApiUrl($url) 32 | { 33 | $this->apiUrl = $url; 34 | } 35 | 36 | protected function getApiUrl() 37 | { 38 | return $this->apiUrl; 39 | } 40 | 41 | /** 42 | * @param $data 43 | * @param array $header 44 | * @param bool $setLocalhost 45 | * @return bool|string 46 | */ 47 | public function callToApi($data, $header = [], $setLocalhost = false) 48 | { 49 | $curl = curl_init(); 50 | 51 | if (!$setLocalhost) { 52 | curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true); 53 | curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); // The default value for this option is 2. It means, it has to have the same name in the certificate as is in the URL you operate against. 54 | } else { 55 | curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); 56 | curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0); // When the verify value is 0, the connection succeeds regardless of the names in the certificate. 57 | } 58 | 59 | curl_setopt($curl, CURLOPT_URL, $this->getApiUrl()); 60 | curl_setopt($curl, CURLOPT_HEADER, 0); 61 | curl_setopt($curl, CURLOPT_HTTPHEADER, $header); 62 | curl_setopt($curl, CURLOPT_TIMEOUT, 60); 63 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); 64 | 65 | curl_setopt($curl, CURLOPT_POST, 1); 66 | curl_setopt($curl, CURLOPT_POSTFIELDS, $data); 67 | 68 | $response = curl_exec($curl); 69 | $err = curl_error($curl); 70 | $code = curl_getinfo($curl, CURLINFO_HTTP_CODE); 71 | $curlErrorNo = curl_errno($curl); 72 | curl_close($curl); 73 | 74 | if ($code == 200 & !($curlErrorNo)) { 75 | return $response; 76 | } else { 77 | return "FAILED TO CONNECT WITH SSLCOMMERZ API"; 78 | //return "cURL Error #:" . $err; 79 | } 80 | } 81 | 82 | /** 83 | * @param $response 84 | * @param string $type 85 | * @param string $pattern 86 | * @return false|mixed|string 87 | */ 88 | public function formatResponse($response, $type = 'checkout', $pattern = 'json') 89 | { 90 | $sslcz = json_decode($response, true); 91 | 92 | if ($type != 'checkout') { 93 | return $sslcz; 94 | } else { 95 | if (isset($sslcz['GatewayPageURL']) && $sslcz['GatewayPageURL'] != "") { 96 | // this is important to show the popup, return or echo to send json response back 97 | if($this->getApiUrl() !=='' && $this->getApiUrl() == 'https://securepay.sslcommerz.com') { 98 | $response = json_encode(['status' => 'SUCCESS', 'data' => $sslcz['GatewayPageURL'], 'logo' => $sslcz['storeLogo']]); 99 | } else { 100 | $response = json_encode(['status' => 'success', 'data' => $sslcz['GatewayPageURL'], 'logo' => $sslcz['storeLogo']]); 101 | } 102 | } else { 103 | $response = json_encode(['status' => 'fail', 'data' => null, 'message' => "JSON Data parsing error!"]); 104 | } 105 | 106 | if ($pattern == 'json') { 107 | return $response; 108 | } else { 109 | echo $response; 110 | } 111 | } 112 | } 113 | 114 | /** 115 | * @param $url 116 | * @param bool $permanent 117 | */ 118 | public function redirect($url, $permanent = false) 119 | { 120 | header('Location: ' . $url, true, $permanent ? 301 : 302); 121 | 122 | exit(); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/Services/SSLCommerz.php: -------------------------------------------------------------------------------- 1 | config = config('sslcommerz'); 21 | 22 | $this->setStoreId($this->config['apiCredentials']['store_id']); 23 | $this->setStorePassword($this->config['apiCredentials']['store_password']); 24 | } 25 | 26 | public function orderValidate($trx_id = '', $amount = 0, $currency = "BDT", $post_data) 27 | { 28 | if ($post_data == '' && $trx_id == '' && !is_array($post_data)) { 29 | $this->error = "Please provide valid transaction ID and post request data"; 30 | return $this->error; 31 | } 32 | 33 | $validation = $this->validate($trx_id, $amount, $currency, $post_data); 34 | 35 | if ($validation) { 36 | return true; 37 | } else { 38 | return false; 39 | } 40 | } 41 | 42 | 43 | # VALIDATE SSLCOMMERZ TRANSACTION 44 | protected function validate($merchant_trans_id, $merchant_trans_amount, $merchant_trans_currency, $post_data) 45 | { 46 | # MERCHANT SYSTEM INFO 47 | if ($merchant_trans_id != "" && $merchant_trans_amount != 0) { 48 | 49 | # CALL THE FUNCTION TO CHECK THE RESULT 50 | $post_data['store_id'] = $this->getStoreId(); 51 | $post_data['store_pass'] = $this->getStorePassword(); 52 | 53 | if ($this->SSLCOMMERZ_hash_varify($this->getStorePassword(), $post_data)) { 54 | 55 | $val_id = urlencode($post_data['val_id']); 56 | $store_id = urlencode($this->getStoreId()); 57 | $store_passwd = urlencode($this->getStorePassword()); 58 | $requested_url = ($this->config['apiDomain'] . $this->config['apiUrl']['order_validate'] . "?val_id=" . $val_id . "&store_id=" . $store_id . "&store_passwd=" . $store_passwd . "&v=1&format=json"); 59 | 60 | $handle = curl_init(); 61 | curl_setopt($handle, CURLOPT_URL, $requested_url); 62 | curl_setopt($handle, CURLOPT_RETURNTRANSFER, true); 63 | 64 | if ($this->config['connect_from_localhost']) { 65 | curl_setopt($handle, CURLOPT_SSL_VERIFYHOST, false); 66 | curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, false); 67 | } else { 68 | curl_setopt($handle, CURLOPT_SSL_VERIFYHOST, true); 69 | curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, true); 70 | } 71 | 72 | 73 | $result = curl_exec($handle); 74 | 75 | $code = curl_getinfo($handle, CURLINFO_HTTP_CODE); 76 | 77 | if ($code == 200 && !(curl_errno($handle))) { 78 | 79 | # TO CONVERT AS ARRAY 80 | # $result = json_decode($result, true); 81 | # $status = $result['status']; 82 | 83 | # TO CONVERT AS OBJECT 84 | $result = json_decode($result); 85 | $this->sslc_data = $result; 86 | 87 | # TRANSACTION INFO 88 | $status = $result->status; 89 | $tran_date = $result->tran_date; 90 | $tran_id = $result->tran_id; 91 | $val_id = $result->val_id; 92 | $amount = $result->amount; 93 | $store_amount = $result->store_amount; 94 | $bank_tran_id = $result->bank_tran_id; 95 | $card_type = $result->card_type; 96 | $currency_type = $result->currency_type; 97 | $currency_amount = $result->currency_amount; 98 | 99 | # ISSUER INFO 100 | $card_no = $result->card_no; 101 | $card_issuer = $result->card_issuer; 102 | $card_brand = $result->card_brand; 103 | $card_issuer_country = $result->card_issuer_country; 104 | $card_issuer_country_code = $result->card_issuer_country_code; 105 | 106 | # API AUTHENTICATION 107 | $APIConnect = $result->APIConnect; 108 | $validated_on = $result->validated_on; 109 | $gw_version = $result->gw_version; 110 | 111 | # GIVE SERVICE 112 | if ($status == "VALID" || $status == "VALIDATED") { 113 | if ($merchant_trans_currency == "BDT") { 114 | if (trim($merchant_trans_id) == trim($tran_id) && (abs($merchant_trans_amount - $amount) < 1) && trim($merchant_trans_currency) == trim('BDT')) { 115 | return true; 116 | } else { 117 | # DATA TEMPERED 118 | $this->error = "Data has been tempered"; 119 | return false; 120 | } 121 | } else { 122 | //echo "trim($merchant_trans_id) == trim($tran_id) && ( abs($merchant_trans_amount-$currency_amount) < 1 ) && trim($merchant_trans_currency)==trim($currency_type)"; 123 | if (trim($merchant_trans_id) == trim($tran_id) && (abs($merchant_trans_amount - $currency_amount) < 1) && trim($merchant_trans_currency) == trim($currency_type)) { 124 | return true; 125 | } else { 126 | # DATA TEMPERED 127 | $this->error = "Data has been tempered"; 128 | return false; 129 | } 130 | } 131 | } else { 132 | # FAILED TRANSACTION 133 | $this->error = "Failed Transaction"; 134 | return false; 135 | } 136 | } else { 137 | # Failed to connect with SSLCOMMERZ 138 | $this->error = "Faile to connect with SSLCOMMERZ"; 139 | return false; 140 | } 141 | } else { 142 | # Hash validation failed 143 | $this->error = "Hash validation failed"; 144 | return false; 145 | } 146 | } else { 147 | # INVALID DATA 148 | $this->error = "Invalid data"; 149 | return false; 150 | } 151 | } 152 | 153 | # FUNCTION TO CHECK HASH VALUE 154 | protected function SSLCOMMERZ_hash_varify($store_passwd = "", $post_data) 155 | { 156 | if (isset($post_data) && isset($post_data['verify_sign']) && isset($post_data['verify_key'])) { 157 | # NEW ARRAY DECLARED TO TAKE VALUE OF ALL POST 158 | $pre_define_key = explode(',', $post_data['verify_key']); 159 | 160 | $new_data = array(); 161 | if (!empty($pre_define_key)) { 162 | foreach ($pre_define_key as $value) { 163 | // if (isset($post_data[$value])) { 164 | $new_data[$value] = ($post_data[$value]); 165 | // } 166 | } 167 | } 168 | # ADD MD5 OF STORE PASSWORD 169 | $new_data['store_passwd'] = md5($store_passwd); 170 | 171 | # SORT THE KEY AS BEFORE 172 | ksort($new_data); 173 | 174 | $hash_string = ""; 175 | foreach ($new_data as $key => $value) { 176 | $hash_string .= $key . '=' . ($value) . '&'; 177 | } 178 | $hash_string = rtrim($hash_string, '&'); 179 | 180 | if (md5($hash_string) == $post_data['verify_sign']) { 181 | 182 | return true; 183 | 184 | } else { 185 | $this->error = "Verification signature not matched"; 186 | return false; 187 | } 188 | } else { 189 | $this->error = 'Required data mission. ex: verify_key, verify_sign'; 190 | return false; 191 | } 192 | } 193 | 194 | /** 195 | * @param array $requestData 196 | * @param string $type 197 | * @param string $pattern 198 | * @return false|mixed|string 199 | */ 200 | public function makePayment(array $requestData, $type = 'checkout', $pattern = 'json') 201 | { 202 | if (empty($requestData)) { 203 | return "Please provide a valid information list about transaction with transaction id, amount, success url, fail url, cancel url, store id and pass at least"; 204 | } 205 | 206 | $header = []; 207 | 208 | $this->setApiUrl($this->config['apiDomain'] . $this->config['apiUrl']['make_payment']); 209 | 210 | // Set the required/additional params 211 | $this->setParams($requestData); 212 | 213 | // Set the authentication information 214 | $this->setAuthenticationInfo(); 215 | 216 | // Now, call the Gateway API 217 | $response = $this->callToApi($this->data, $header, $this->config['connect_from_localhost']); 218 | 219 | $formattedResponse = $this->formatResponse($response, $type, $pattern); // Here we will define the response pattern 220 | 221 | if ($type == 'hosted') { 222 | if (isset($formattedResponse['GatewayPageURL']) && $formattedResponse['GatewayPageURL'] != '') { 223 | $this->redirect($formattedResponse['GatewayPageURL']); 224 | } else { 225 | $errorMessage = "No redirect URL found!"; 226 | return $errorMessage; 227 | } 228 | } else { 229 | return $formattedResponse; 230 | } 231 | } 232 | 233 | 234 | protected function setSuccessUrl() 235 | { 236 | $this->successUrl = url('/') . $this->config['success_url']; 237 | } 238 | 239 | protected function getSuccessUrl() 240 | { 241 | return $this->successUrl; 242 | } 243 | 244 | protected function setFailedUrl() 245 | { 246 | $this->failedUrl = url('/') . $this->config['failed_url']; 247 | } 248 | 249 | protected function getFailedUrl() 250 | { 251 | return $this->failedUrl; 252 | } 253 | 254 | protected function setCancelUrl() 255 | { 256 | $this->cancelUrl = url('/') . $this->config['cancel_url']; 257 | } 258 | 259 | protected function getCancelUrl() 260 | { 261 | return $this->cancelUrl; 262 | } 263 | 264 | public function setParams($requestData) 265 | { 266 | ## Integration Required Parameters 267 | $this->setRequiredInfo($requestData); 268 | 269 | ## Customer Information 270 | $this->setCustomerInfo($requestData); 271 | 272 | ## Shipment Information 273 | $this->setShipmentInfo($requestData); 274 | 275 | ## Product Information 276 | $this->setProductInfo($requestData); 277 | 278 | ## Customized or Additional Parameters 279 | $this->setAdditionalInfo($requestData); 280 | } 281 | 282 | public function setAuthenticationInfo() 283 | { 284 | $this->data['store_id'] = $this->getStoreId(); 285 | $this->data['store_passwd'] = $this->getStorePassword(); 286 | 287 | return $this->data; 288 | } 289 | 290 | public function setRequiredInfo(array $info) 291 | { 292 | $this->data['total_amount'] = $info['total_amount']; // decimal (10,2) Mandatory - The amount which will process by SSLCommerz. It shall be decimal value (10,2). Example : 55.40. The transaction amount must be from 10.00 BDT to 500000.00 BDT 293 | $this->data['currency'] = $info['currency']; // string (3) Mandatory - The currency type must be mentioned. It shall be three characters. Example : BDT, USD, EUR, SGD, INR, MYR, etc. If the transaction currency is not BDT, then it will be converted to BDT based on the current convert rate. Example : 1 USD = 82.22 BDT. 294 | $this->data['tran_id'] = $info['tran_id']; // string (30) Mandatory - Unique transaction ID to identify your order in both your end and SSLCommerz 295 | $this->data['product_category'] = $info['product_category']; // string (50) Mandatory - Mention the product category. It is a open field. Example - clothing,shoes,watches,gift,healthcare, jewellery,top up,toys,baby care,pants,laptop,donation,etc 296 | 297 | // Set the SUCCESS, FAIL, CANCEL Redirect URL before setting the other parameters 298 | $this->setSuccessUrl(); 299 | $this->setFailedUrl(); 300 | $this->setCancelUrl(); 301 | 302 | $this->data['success_url'] = $this->getSuccessUrl(); // string (255) Mandatory - It is the callback URL of your website where user will redirect after successful payment (Length: 255) 303 | $this->data['fail_url'] = $this->getFailedUrl(); // string (255) Mandatory - It is the callback URL of your website where user will redirect after any failure occure during payment (Length: 255) 304 | $this->data['cancel_url'] = $this->getCancelUrl(); // string (255) Mandatory - It is the callback URL of your website where user will redirect if user canceled the transaction (Length: 255) 305 | 306 | /* 307 | * IPN is very important feature to integrate with your site(s). 308 | * Some transaction could be pending or customer lost his/her session, in such cases back-end IPN plays a very important role to update your backend office. 309 | * 310 | * Type: string (255) 311 | * Important! Not mandatory, however better to use to avoid missing any payment notification - It is the Instant Payment Notification (IPN) URL of your website where SSLCOMMERZ will send the transaction's status (Length: 255). 312 | * The data will be communicated as SSLCOMMERZ Server to your Server. So, customer session will not work. 313 | * */ 314 | $this->data['ipn_url'] = (isset($info['ipn_url'])) ? $info['ipn_url'] : null; 315 | 316 | /* 317 | * Type: string (30) 318 | * Do not Use! If you do not customize the gateway list - You can control to display the gateway list at SSLCommerz gateway selection page by providing this parameters. 319 | * Multi Card: 320 | brac_visa = BRAC VISA 321 | dbbl_visa = Dutch Bangla VISA 322 | city_visa = City Bank Visa 323 | ebl_visa = EBL Visa 324 | sbl_visa = Southeast Bank Visa 325 | brac_master = BRAC MASTER 326 | dbbl_master = MASTER Dutch-Bangla 327 | city_master = City Master Card 328 | ebl_master = EBL Master Card 329 | sbl_master = Southeast Bank Master Card 330 | city_amex = City Bank AMEX 331 | qcash = QCash 332 | dbbl_nexus = DBBL Nexus 333 | bankasia = Bank Asia IB 334 | abbank = AB Bank IB 335 | ibbl = IBBL IB and Mobile Banking 336 | mtbl = Mutual Trust Bank IB 337 | bkash = Bkash Mobile Banking 338 | dbblmobilebanking = DBBL Mobile Banking 339 | city = City Touch IB 340 | upay = Upay 341 | tapnpay = Tap N Pay Gateway 342 | * GROUP GATEWAY 343 | internetbank = For all internet banking 344 | mobilebank = For all mobile banking 345 | othercard = For all cards except visa,master and amex 346 | visacard = For all visa 347 | mastercard = For All Master card 348 | amexcard = For Amex Card 349 | * */ 350 | $this->data['multi_card_name'] = (isset($info['multi_card_name'])) ? $info['multi_card_name'] : null; 351 | 352 | /* 353 | * Type: string (255) 354 | * Do not Use! If you do not control on transaction - You can provide the BIN of card to allow the transaction must be completed by this BIN. You can declare by coma ',' separate of these BIN. 355 | * Example: 371598,371599,376947,376948,376949 356 | * */ 357 | $this->data['allowed_bin'] = (isset($info['allowed_bin'])) ? $info['allowed_bin'] : null; 358 | 359 | ## Parameters to Handle EMI Transaction ## 360 | $this->data['emi_option'] = (isset($info['emi_option'])) ? $info['emi_option'] : null; // integer (1) Mandatory - This is mandatory if transaction is EMI enabled and Value must be 1/0. Here, 1 means customer will get EMI facility for this transaction 361 | $this->data['emi_max_inst_option'] = (isset($info['emi_max_inst_option'])) ? $info['emi_max_inst_option'] : null; // integer (2) Max instalment Option, Here customer will get 3,6, 9 instalment at gateway page 362 | $this->data['emi_selected_inst'] = (isset($info['emi_selected_inst'])) ? $info['emi_selected_inst'] : null; // integer (2) Customer has selected from your Site, So no instalment option will be displayed at gateway page 363 | 364 | return $this->data; 365 | } 366 | 367 | public function setCustomerInfo(array $info) 368 | { 369 | $this->data['cus_name'] = $info['cus_name']; // string (50) Mandatory - Your customer name to address the customer in payment receipt email 370 | $this->data['cus_email'] = $info['cus_email']; // string (50) Mandatory - Valid email address of your customer to send payment receipt from SSLCommerz end 371 | $this->data['cus_add1'] = $info['cus_add1']; // string (50) Mandatory - Address of your customer. Not mandatory but useful if provided 372 | $this->data['cus_add2'] = $info['cus_add2']; // string (50) Address line 2 of your customer. Not mandatory but useful if provided 373 | $this->data['cus_city'] = $info['cus_city']; // string (50) Mandatory - City of your customer. Not mandatory but useful if provided 374 | $this->data['cus_state'] = (isset($info['cus_state'])) ? $info['cus_state'] : null; // string (50) State of your customer. Not mandatory but useful if provided 375 | $this->data['cus_postcode'] = $info['cus_postcode']; // string (30) Mandatory - Postcode of your customer. Not mandatory but useful if provided 376 | $this->data['cus_country'] = $info['cus_country']; // string (50) Mandatory - Country of your customer. Not mandatory but useful if provided 377 | $this->data['cus_phone'] = $info['cus_phone']; // string (20) Mandatory - The phone/mobile number of your customer to contact if any issue arises 378 | $this->data['cus_fax'] = (isset($info['cus_fax'])) ? $info['cus_fax'] : null; // string (20) Fax number of your customer. Not mandatory but useful if provided 379 | 380 | return $this->data; 381 | } 382 | 383 | public function setShipmentInfo(array $info) 384 | { 385 | 386 | $this->data['shipping_method'] = $info['shipping_method']; // string (50) Mandatory - Shipping method of the order. Example: YES or NO or Courier 387 | $this->data['num_of_item'] = isset($info['num_of_item']) ? $info['num_of_item'] : 1; // integer (1) Mandatory - No of product will be shipped. Example: 1 or 2 or etc 388 | $this->data['ship_name'] = $info['ship_name']; // string (50) Mandatory, if shipping_method is YES - Shipping Address of your order. Not mandatory but useful if provided 389 | $this->data['ship_add1'] = $info['ship_add1']; // string (50) Mandatory, if shipping_method is YES - Additional Shipping Address of your order. Not mandatory but useful if provided 390 | $this->data['ship_add2'] = (isset($info['ship_add2'])) ? $info['ship_add2'] : null; // string (50) Additional Shipping Address of your order. Not mandatory but useful if provided 391 | $this->data['ship_city'] = $info['ship_city']; // string (50) Mandatory, if shipping_method is YES - Shipping city of your order. Not mandatory but useful if provided 392 | $this->data['ship_state'] = (isset($info['ship_state'])) ? $info['ship_state'] : null; // string (50) Shipping state of your order. Not mandatory but useful if provided 393 | $this->data['ship_postcode'] = (isset($info['ship_postcode'])) ? $info['ship_postcode'] : null; // string (50) Mandatory, if shipping_method is YES - Shipping postcode of your order. Not mandatory but useful if provided 394 | $this->data['ship_country'] = (isset($info['ship_country'])) ? $info['ship_country'] : null; // string (50) Mandatory, if shipping_method is YES - Shipping country of your order. Not mandatory but useful if provided 395 | 396 | return $this->data; 397 | } 398 | 399 | public function setProductInfo(array $info) 400 | { 401 | 402 | $this->data['product_name'] = (isset($info['product_name'])) ? $info['product_name'] : ''; // String (256) Mandatory - Mention the product name briefly. Mention the product name by coma separate. Example: Computer,Speaker 403 | $this->data['product_category'] = (isset($info['product_category'])) ? $info['product_category'] : ''; // String (100) Mandatory - Mention the product category. Example: Electronic or topup or bus ticket or air ticket 404 | 405 | /* 406 | * String (100) 407 | * Mandatory - Mention goods vertical. It is very much necessary for online transactions to avoid chargeback. 408 | * Please use the below keys : 409 | 1) general 410 | 2) physical-goods 411 | 3) non-physical-goods 412 | 4) airline-tickets 413 | 5) travel-vertical 414 | 6) telecom-vertical 415 | */ 416 | $this->data['product_profile'] = (isset($info['product_profile'])) ? $info['product_profile'] : ''; 417 | 418 | $this->data['hours_till_departure'] = (isset($info['hours_till_departure'])) ? $info['hours_till_departure'] : null; // string (30) Mandatory, if product_profile is airline-tickets - Provide the remaining time of departure of flight till at the time of purchasing the ticket. Example: 12 hrs or 36 hrs 419 | $this->data['flight_type'] = (isset($info['flight_type'])) ? $info['flight_type'] : null; // string (30) Mandatory, if product_profile is airline-tickets - Provide the flight type. Example: Oneway or Return or Multistop 420 | $this->data['pnr'] = (isset($info['pnr'])) ? $info['pnr'] : null; // string (50) Mandatory, if product_profile is airline-tickets - Provide the PNR. 421 | $this->data['journey_from_to'] = (isset($info['journey_from_to'])) ? $info['journey_from_to'] : null; // string (256) - Mandatory, if product_profile is airline-tickets - Provide the journey route. Example: DAC-CGP or DAC-CGP CGP-DAC 422 | $this->data['third_party_booking'] = (isset($info['third_party_booking'])) ? $info['third_party_booking'] : null; // string (20) Mandatory, if product_profile is airline-tickets - No/Yes. Whether the ticket has been taken from third party booking system. 423 | $this->data['hotel_name'] = (isset($info['hotel_name'])) ? $info['hotel_name'] : null; // string (256) Mandatory, if product_profile is travel-vertical - Please provide the hotel name. Example: Sheraton 424 | $this->data['length_of_stay'] = (isset($info['length_of_stay'])) ? $info['length_of_stay'] : null; // string (30) Mandatory, if product_profile is travel-vertical - How long stay in hotel. Example: 2 days 425 | $this->data['check_in_time'] = (isset($info['check_in_time'])) ? $info['check_in_time'] : null; // string (30) Mandatory, if product_profile is travel-vertical - Checking hours for the hotel room. Example: 24 hrs 426 | $this->data['hotel_city'] = (isset($info['hotel_city'])) ? $info['hotel_city'] : null; // string (50) Mandatory, if product_profile is travel-vertical - Location of the hotel. Example: Dhaka 427 | $this->data['product_type'] = (isset($info['product_type'])) ? $info['product_type'] : null; // string (30) Mandatory, if product_profile is telecom-vertical - For mobile or any recharge, this information is necessary. Example: Prepaid or Postpaid 428 | $this->data['topup_number'] = (isset($info['topup_number'])) ? $info['topup_number'] : null; // string (150) Mandatory, if product_profile is telecom-vertical - Provide the mobile number which will be recharged. Example: 8801700000000 or 8801700000000,8801900000000 429 | $this->data['country_topup'] = (isset($info['country_topup'])) ? $info['country_topup'] : null; // string (30) Mandatory, if product_profile is telecom-vertical - Provide the country name in where the service is given. Example: Bangladesh 430 | 431 | /* 432 | * Type: JSON 433 | * JSON data with two elements. product : Max 255 characters, quantity : Quantity in numeric value and amount : Decimal (12,2) 434 | * Example: 435 | [{"product":"DHK TO BRS AC A1","quantity":"1","amount":"200.00"},{"product":"DHK TO BRS AC A2","quantity":"1","amount":"200.00"},{"product":"DHK TO BRS AC A3","quantity":"1","amount":"200.00"},{"product":"DHK TO BRS AC A4","quantity":"2","amount":"200.00"}] 436 | * */ 437 | $this->data['cart'] = (isset($info['cart'])) ? $info['cart'] : null; 438 | $this->data['product_amount'] = (isset($info['product_amount'])) ? $info['product_amount'] : null; // decimal (10,2) Product price which will be displayed in your merchant panel and will help you to reconcile the transaction. It shall be decimal value (10,2). Example : 50.40 439 | $this->data['vat'] = (isset($info['vat'])) ? $info['vat'] : null; // decimal (10,2) The VAT included on the product price which will be displayed in your merchant panel and will help you to reconcile the transaction. It shall be decimal value (10,2). Example : 4.00 440 | $this->data['discount_amount'] = (isset($info['discount_amount'])) ? $info['discount_amount'] : null; // decimal (10,2) Discount given on the invoice which will be displayed in your merchant panel and will help you to reconcile the transaction. It shall be decimal value (10,2). Example : 2.00 441 | $this->data['convenience_fee'] = (isset($info['convenience_fee'])) ? $info['convenience_fee'] : null; // decimal (10,2) Any convenience fee imposed on the invoice which will be displayed in your merchant panel and will help you to reconcile the transaction. It shall be decimal value (10,2). Example : 3.00 442 | 443 | return $this->data; 444 | } 445 | 446 | public function setAdditionalInfo(array $info) 447 | { 448 | $this->data['value_a'] = (isset($info['value_a'])) ? $info['value_a'] : null; // value_a [ string (255) - Extra parameter to pass your meta data if it is needed. Not mandatory] 449 | $this->data['value_b'] = (isset($info['value_b'])) ? $info['value_b'] : null; // value_b [ string (255) - Extra parameter to pass your meta data if it is needed. Not mandatory] 450 | $this->data['value_c'] = (isset($info['value_c'])) ? $info['value_c'] : null; // value_c [ string (255) - Extra parameter to pass your meta data if it is needed. Not mandatory] 451 | $this->data['value_d'] = (isset($info['value_d'])) ? $info['value_d'] : null; // value_d [ string (255) - Extra parameter to pass your meta data if it is needed. Not mandatory] 452 | 453 | return $this->data; 454 | } 455 | } -------------------------------------------------------------------------------- /src/Services/SSLCommerzInterface.php: -------------------------------------------------------------------------------- 1 | env("PROJECT_PATH"), 9 | "apiDomain" => env("API_DOMAIN_URL"), // For Sandbox, use "https://sandbox.sslcommerz.com". For Live, use "https://securepay.sslcommerz.com" 10 | "apiCredentials" => [ 11 | "store_id" => env("STORE_ID"), 12 | "store_password" => env("STORE_PASSWORD"), 13 | ], 14 | "apiUrl" => [ 15 | "make_payment" => "/gwprocess/v4/api.php", 16 | "transaction_status" => "/validator/api/merchantTransIDvalidationAPI.php", 17 | "order_validate" => "/validator/api/validationserverAPI.php", 18 | "refund_payment" => "/validator/api/merchantTransIDvalidationAPI.php", 19 | "refund_status" => "/validator/api/merchantTransIDvalidationAPI.php", 20 | ], 21 | "connect_from_localhost" => env("IS_LOCALHOST", true), // For Sandbox, use "true", For Live, use "false" 22 | "success_url" => "/success", 23 | "failed_url" => "/fail", 24 | "cancel_url" => "/cancel", 25 | "ipn_url" => "/ipn", 26 | ]; 27 | -------------------------------------------------------------------------------- /src/database/migrations/0000_00_00_000000_create_payments_table.php: -------------------------------------------------------------------------------- 1 | bigIncrements('id'); 18 | $table->string('name', 255); 19 | $table->string('email', 64); 20 | $table->string('phone', 20); 21 | $table->double('amount'); 22 | $table->text('address'); 23 | $table->string('status', 10); 24 | $table->string('transaction_id', 255); 25 | $table->string('currency', 20); 26 | $table->timestamps(); 27 | }); 28 | } 29 | 30 | /** 31 | * Reverse the migrations. 32 | * 33 | * @return void 34 | */ 35 | public function down() 36 | { 37 | Schema::dropIfExists('payments'); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/resources/views/exampleEasycheckout.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Example - EasyCheckout (Popup) | SSLCommerz 9 | 10 | 11 | 13 | 14 | 30 | 31 | 32 |
33 |
34 |

EasyCheckout (Popup) - SSLCommerz

35 | 36 |

Below is an example form built entirely with Bootstrap’s form controls. We have provided this 37 | sample form for understanding EasyCheckout (Popup) Payment integration with SSLCommerz.

38 |
39 | 40 |
41 |
42 |

43 | Your cart 44 | 3 45 |

46 |
    47 |
  • 48 |
    49 |
    Product name
    50 | Brief description 51 |
    52 | 1000 53 |
  • 54 |
  • 55 |
    56 |
    Second product
    57 | Brief description 58 |
    59 | 50 60 |
  • 61 |
  • 62 |
    63 |
    Third item
    64 | Brief description 65 |
    66 | 150 67 |
  • 68 |
  • 69 | Total (BDT) 70 | 1200 TK 71 |
  • 72 |
73 |
74 |
75 |

Billing address

76 |
77 |
78 |
79 | 80 | 82 |
83 | Valid customer name is required. 84 |
85 |
86 |
87 | 88 |
89 | 90 |
91 |
92 | +88 93 |
94 | 96 |
97 | Your Mobile number is required. 98 |
99 |
100 |
101 | 102 |
103 | 104 | 106 |
107 | Please enter a valid email address for shipping updates. 108 |
109 |
110 | 111 |
112 | 113 | 115 |
116 | Please enter your shipping address. 117 |
118 |
119 | 120 |
121 | 122 | 123 |
124 | 125 |
126 |
127 | 128 | 132 |
133 | Please select a valid country. 134 |
135 |
136 |
137 | 138 | 142 |
143 | Please provide a valid state. 144 |
145 |
146 |
147 | 148 | 149 |
150 | Zip code required. 151 |
152 |
153 |
154 |
155 |
156 | 157 | 158 | 160 |
161 |
162 | 163 | 164 |
165 |
166 | 172 |
173 |
174 |
175 | 176 | 184 |
185 | 188 | 191 | 194 | 195 | 196 | 197 | 218 | 219 | -------------------------------------------------------------------------------- /src/resources/views/exampleHosted.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Example - Hosted Checkout | SSLCommerz 9 | 10 | 11 | 13 | 14 | 30 | 31 | 32 |
33 |
34 |

Hosted Payment - SSLCommerz

35 |

Below is an example form built entirely with Bootstrap’s form controls. We have provided this sample form for understanding Hosted Checkout Payment with SSLCommerz.

36 |
37 | 38 |
39 |
40 |

41 | Your cart 42 | 3 43 |

44 |
    45 |
  • 46 |
    47 |
    Product name
    48 | Brief description 49 |
    50 | 1000 51 |
  • 52 |
  • 53 |
    54 |
    Second product
    55 | Brief description 56 |
    57 | 50 58 |
  • 59 |
  • 60 |
    61 |
    Third item
    62 | Brief description 63 |
    64 | 150 65 |
  • 66 |
  • 67 | Total (BDT) 68 | 1200 TK 69 |
  • 70 |
71 |
72 |
73 |

Billing address

74 |
75 | 76 |
77 |
78 | 79 | 81 |
82 | Valid customer name is required. 83 |
84 |
85 |
86 | 87 |
88 | 89 |
90 |
91 | +88 92 |
93 | 95 |
96 | Your Mobile number is required. 97 |
98 |
99 |
100 | 101 |
102 | 103 | 105 |
106 | Please enter a valid email address for shipping updates. 107 |
108 |
109 | 110 |
111 | 112 | 114 |
115 | Please enter your shipping address. 116 |
117 |
118 | 119 |
120 | 121 | 122 |
123 | 124 |
125 |
126 | 127 | 131 |
132 | Please select a valid country. 133 |
134 |
135 |
136 | 137 | 141 |
142 | Please provide a valid state. 143 |
144 |
145 |
146 | 147 | 148 |
149 | Zip code required. 150 |
151 |
152 |
153 |
154 |
155 | 156 | 157 | 159 |
160 |
161 | 162 | 163 |
164 |
165 | 166 |
167 |
168 |
169 | 170 | 178 |
179 | 182 | 185 | 188 | 189 | -------------------------------------------------------------------------------- /src/routes/sslcommerzroutes.php: -------------------------------------------------------------------------------- 1 |