├── README.md ├── app ├── Exceptions │ └── VeritransException.php ├── Http │ ├── Controllers │ │ ├── SnapController.php │ │ ├── TransactionController.php │ │ ├── VtdirectController.php │ │ └── VtwebController.php │ └── routes.php └── Veritrans │ ├── Midtrans.php │ ├── Veritrans.php │ └── data │ └── cacert.pem ├── public ├── css │ └── jquery.fancybox.css └── js │ └── jquery.fancybox.pack.js └── resources └── views ├── checkout.blade.php ├── snap_checkout.blade.php └── transaction.blade.php /README.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------- 3 | 4 | > **:warning::warning: ANNOUNCEMENT :warning::warning:** 5 | 6 | **Please use the updated and composer compatible library: [Midtrans PHP](https://github.com/Midtrans/midtrans-php). 7 | For better more modern composer compatibility.** 8 | 9 | This repo still be here for archive and compatibility purpose. But it's always recommended to use the newer version [Midtrans PHP](https://github.com/Midtrans/midtrans-php). 10 | 11 | > **:speaker: END OF ANNOUNCEMENT :speaker:** 12 | 13 | --------------------- 14 | 15 | 16 | 17 | Veritrans Laravel library 18 | ======================================================= 19 | Veritrans :heart: Laravel! 20 | 21 | This is the all new Laravel client library for Veritrans 2.0. Visit [https://www.veritrans.co.id](https://www.veritrans.co.id) for more information about the product and see documentation at [http://docs.veritrans.co.id](http://docs.veritrans.co.id) for more technical details. 22 | 23 | ### Requirements 24 | The following plugin is tested under following environment: 25 | * PHP v5.4.x or greater 26 | * Laravel 5 27 | 28 | ## Installation 29 | * Download the library and extract the .zip 30 | * Merge all the files. 31 | * install from composer (Soon :) ) 32 | 33 | ## Using Veritrans Library 34 | 35 | ### Use Veritrans Class 36 | ###### Add this following line in your controller 37 | ```php 38 | //before 39 | namespace App\Http\Controllers; 40 | use Illuminate\Http\Request; 41 | use App\Http\Requests; 42 | use App\Http\Controllers\Controller; 43 | 44 | class YourController extends Controller 45 | { 46 | ... 47 | 48 | // after 49 | namespace App\Http\Controllers; 50 | use Illuminate\Http\Request; 51 | use App\Http\Requests; 52 | use App\Http\Controllers\Controller; 53 | 54 | use App\Veritrans\Veritrans; 55 | 56 | class YourController extends Controller 57 | { 58 | ... 59 | ``` 60 | ###### Add/Edit this following line in your __construct() function 61 | ```php 62 | //set $isproduction to true for prodution environment 63 | //before 64 | class YourController extends Controller 65 | { 66 | 67 | ... 68 | 69 | // after 70 | use App\Veritrans\Veritrans; 71 | class YourController extends Controller 72 | { 73 | public function __construct(){ 74 | Veritrans::$serverKey = 'your-server-key'; 75 | Veritrans::$isProduction = false; 76 | } 77 | ... 78 | ``` 79 | ### SNAP 80 | You can see how to get snap token by reading the controller [here](https://github.com/harrypujianto/Veritrans-Laravel5/blob/master/app/Http/Controllers/SnapController.php). 81 | 82 | #### Get Snap Token 83 | ```php 84 | public function token() 85 | { 86 | error_log('masuk ke snap token adri ajax'); 87 | $midtrans = new Midtrans; 88 | $transaction_details = array( 89 | 'order_id' => uniqid(), 90 | 'gross_amount' => 200000 91 | ); 92 | // Populate items 93 | $items = [ 94 | array( 95 | 'id' => 'item1', 96 | 'price' => 100000, 97 | 'quantity' => 1, 98 | 'name' => 'Adidas f50' 99 | ), 100 | array( 101 | 'id' => 'item2', 102 | 'price' => 50000, 103 | 'quantity' => 2, 104 | 'name' => 'Nike N90' 105 | ) 106 | ]; 107 | // Populate customer's billing address 108 | $billing_address = array( 109 | 'first_name' => "Andri", 110 | 'last_name' => "Setiawan", 111 | 'address' => "Karet Belakang 15A, Setiabudi.", 112 | 'city' => "Jakarta", 113 | 'postal_code' => "51161", 114 | 'phone' => "081322311801", 115 | 'country_code' => 'IDN' 116 | ); 117 | // Populate customer's shipping address 118 | $shipping_address = array( 119 | 'first_name' => "John", 120 | 'last_name' => "Watson", 121 | 'address' => "Bakerstreet 221B.", 122 | 'city' => "Jakarta", 123 | 'postal_code' => "51162", 124 | 'phone' => "081322311801", 125 | 'country_code'=> 'IDN' 126 | ); 127 | // Populate customer's Info 128 | $customer_details = array( 129 | 'first_name' => "Andri", 130 | 'last_name' => "Setiawan", 131 | 'email' => "andrisetiawan@asdasd.com", 132 | 'phone' => "081322311801", 133 | 'billing_address' => $billing_address, 134 | 'shipping_address'=> $shipping_address 135 | ); 136 | // Data yang akan dikirim untuk request redirect_url. 137 | $transaction_data = array( 138 | 'transaction_details'=> $transaction_details, 139 | 'item_details' => $items, 140 | 'customer_details' => $customer_details 141 | ); 142 | 143 | try 144 | { 145 | $snap_token = $midtrans->getSnapToken($transaction_data); 146 | //return redirect($vtweb_url); 147 | echo $snap_token; 148 | } 149 | catch (Exception $e) 150 | { 151 | return $e->getMessage; 152 | } 153 | } 154 | ``` 155 | 156 | #### SNAP UI 157 | In this section you could see the code, how to get snap token with ajax and open the snap pop up on the page. Please refer [here](https://github.com/harrypujianto/Veritrans-Laravel5/blob/master/resources/views/snap_checkout.blade.php) 158 | 159 | For sandbox use https://app.sandbox.midtrans.com/snap/snap.js 160 | For production use https://app.midtrans.com/snap/snap.js 161 | ``` 162 | 163 | Checkout 164 | 165 | 168 | 169 | 170 | 171 | 172 | 173 |
174 | 175 | 176 | 177 |
178 | 179 | 180 | 225 | 226 | 227 | 228 | 229 | 230 | ``` 231 | 232 | ### VT-Web 233 | 234 | You can see some more details of VT-Web examples [here](https://github.com/harrypujianto/Veritrans-Laravel5/blob/master/app/Http/Controllers/VtwebController.php). 235 | 236 | #### Get Redirection URL of a Charge 237 | ```php 238 | //you don't have to use the function name 'vtweb', it's just an example 239 | public function vtweb() 240 | { 241 | $vt = new Veritrans; 242 | $transaction_details = array( 243 | 'order_id' => uniqid(), 244 | 'gross_amount' => 200000 245 | ); 246 | // Populate items 247 | $items = [ 248 | array( 249 | 'id' => 'item1', 250 | 'price' => 100000, 251 | 'quantity' => 1, 252 | 'name' => 'Adidas f50' 253 | ), 254 | array( 255 | 'id' => 'item2', 256 | 'price' => 50000, 257 | 'quantity' => 2, 258 | 'name' => 'Nike N90' 259 | ) 260 | ]; 261 | // Populate customer's billing address 262 | $billing_address = array( 263 | 'first_name' => "Andri", 264 | 'last_name' => "Setiawan", 265 | 'address' => "Karet Belakang 15A, Setiabudi.", 266 | 'city' => "Jakarta", 267 | 'postal_code' => "51161", 268 | 'phone' => "081322311801", 269 | 'country_code' => 'IDN' 270 | ); 271 | // Populate customer's shipping address 272 | $shipping_address = array( 273 | 'first_name' => "John", 274 | 'last_name' => "Watson", 275 | 'address' => "Bakerstreet 221B.", 276 | 'city' => "Jakarta", 277 | 'postal_code' => "51162", 278 | 'phone' => "081322311801", 279 | 'country_code'=> 'IDN' 280 | ); 281 | // Populate customer's Info 282 | $customer_details = array( 283 | 'first_name' => "Andri", 284 | 'last_name' => "Setiawan", 285 | 'email' => "andrisetiawan@asdasd.com", 286 | 'phone' => "081322311801", 287 | 'billing_address' => $billing_address, 288 | 'shipping_address'=> $shipping_address 289 | ); 290 | // Data yang akan dikirim untuk request redirect_url. 291 | // Uncomment 'credit_card_3d_secure' => true jika transaksi ingin diproses dengan 3DSecure. 292 | $transaction_data = array( 293 | 'payment_type' => 'vtweb', 294 | 'vtweb' => array( 295 | //'enabled_payments' => [], 296 | 'credit_card_3d_secure' => true 297 | ), 298 | 'transaction_details'=> $transaction_details, 299 | 'item_details' => $items, 300 | 'customer_details' => $customer_details 301 | ); 302 | 303 | try 304 | { 305 | $vtweb_url = $vt->vtweb_charge($transaction_data); 306 | return redirect($vtweb_url); 307 | } 308 | catch (Exception $e) 309 | { 310 | return $e->getMessage; 311 | } 312 | } 313 | ``` 314 | 315 | #### Handle Notification Callback 316 | 317 | Create a route in the route.php. The route must be post, since we're getting http post notification. 318 | ```php 319 | Route::post('/vt_notif', 'VtwebController@notification'); 320 | ``` 321 | 322 | You need to exclude the notification route from CsrfToken Verification 323 | Edit VerifyCsrfToken.php which located in App/http/middleware/VerifyCsrfToken.php 324 | ```php 325 | //before 326 | class VerifyCsrfToken extends BaseVerifier 327 | { 328 | protected $except = [ 329 | // 330 | ]; 331 | } 332 | 333 | //after 334 | class VerifyCsrfToken extends BaseVerifier 335 | { 336 | protected $except = [ 337 | // 338 | 'vt_notif' 339 | ]; 340 | } 341 | ``` 342 | 343 | You can see some more details of notification handler examples [here](https://github.com/harrypujianto/Veritrans-Laravel5/blob/master/app/Http/Controllers/VtwebController.php) (line 101). 344 | ```php 345 | //you don't have to use the function name 'notification', it's just an example 346 | public function notification() 347 | { 348 | $vt = new Veritrans; 349 | echo 'test notification handler'; 350 | $json_result = file_get_contents('php://input'); 351 | $result = json_decode($json_result); 352 | if($result){ 353 | $notif = $vt->status($result->order_id); 354 | } 355 | /* 356 | $transaction = $notif->transaction_status; 357 | $type = $notif->payment_type; 358 | $order_id = $notif->order_id; 359 | $fraud = $notif->fraud_status; 360 | 361 | if ($transaction == 'capture') { 362 | // For credit card transaction, we need to check whether transaction is challenge by FDS or not 363 | if ($type == 'credit_card'){ 364 | if($fraud == 'challenge'){ 365 | // TODO set payment status in merchant's database to 'Challenge by FDS' 366 | // TODO merchant should decide whether this transaction is authorized or not in MAP 367 | echo "Transaction order_id: " . $order_id ." is challenged by FDS"; 368 | } 369 | else { 370 | // TODO set payment status in merchant's database to 'Success' 371 | echo "Transaction order_id: " . $order_id ." successfully captured using " . $type; 372 | } 373 | } 374 | } 375 | else if ($transaction == 'settlement'){ 376 | // TODO set payment status in merchant's database to 'Settlement' 377 | echo "Transaction order_id: " . $order_id ." successfully transfered using " . $type; 378 | } 379 | else if($transaction == 'pending'){ 380 | // TODO set payment status in merchant's database to 'Pending' 381 | echo "Waiting customer to finish transaction order_id: " . $order_id . " using " . $type; 382 | } 383 | else if ($transaction == 'deny') { 384 | // TODO set payment status in merchant's database to 'Denied' 385 | echo "Payment using " . $type . " for transaction order_id: " . $order_id . " is denied."; 386 | }*/ 387 | ``` 388 | 389 | ### VT-Direct 390 | You can see VT-Direct form [here](https://github.com/harrypujianto/Veritrans-Laravel5/blob/master/resources/views/checkout.blade.php). 391 | 392 | you can see VT-Direct process [here](https://github.com/harrypujianto/Veritrans-Laravel5/blob/master/app/Http/Controllers/VtdirectController.php). 393 | 394 | #### Checkout Page 395 | 396 | ```html 397 | 398 | 399 | Checkout 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 |

Checkout

409 |
410 |
411 | Checkout 412 |

413 | 414 | 415 |

416 |

417 | 418 | 419 | / 420 | 421 |

422 |

423 | 424 | 425 |

426 | 427 |

428 | 429 | 430 |

431 | 432 | 433 | 434 |
435 |
436 | 437 | 438 | 505 | 506 | 507 | ``` 508 | 509 | #### Checkout Process 510 | 511 | ##### 1. Create Transaction Details 512 | 513 | ```php 514 | $transaction_details = array( 515 | 'order_id' => time(), 516 | 'gross_amount' => 10000 517 | ); 518 | ``` 519 | 520 | ##### 2. Create Item Details, Billing Address, Shipping Address, and Customer Details (Optional) 521 | 522 | ```php 523 | // Populate items 524 | $items = array( 525 | array( 526 | 'id' => 'item1', 527 | 'price' => 5000, 528 | 'quantity' => 1, 529 | 'name' => 'Adidas f50' 530 | ), 531 | array( 532 | 'id' => 'item2', 533 | 'price' => 2500, 534 | 'quantity' => 2, 535 | 'name' => 'Nike N90' 536 | )); 537 | 538 | // Populate customer's billing address 539 | $billing_address = array( 540 | 'first_name' => "Andri", 541 | 'last_name' => "Setiawan", 542 | 'address' => "Karet Belakang 15A, Setiabudi.", 543 | 'city' => "Jakarta", 544 | 'postal_code' => "51161", 545 | 'phone' => "081322311801", 546 | 'country_code' => 'IDN' 547 | ); 548 | 549 | // Populate customer's shipping address 550 | $shipping_address = array( 551 | 'first_name' => "John", 552 | 'last_name' => "Watson", 553 | 'address' => "Bakerstreet 221B.", 554 | 'city' => "Jakarta", 555 | 'postal_code' => "51162", 556 | 'phone' => "081322311801", 557 | 'country_code' => 'IDN' 558 | ); 559 | 560 | // Populate customer's info 561 | $customer_details = array( 562 | 'first_name' => "Andri", 563 | 'last_name' => "Setiawan", 564 | 'email' => "payment-api@veritrans.co.id", 565 | 'phone' => "081322311801", 566 | 'billing_address' => $billing_address, 567 | 'shipping_address' => $shipping_address 568 | ); 569 | ``` 570 | 571 | ##### 3. Get Token ID from Checkout Page 572 | 573 | ```php 574 | // Token ID from checkout page 575 | $token_id = $request->input('token_id'); 576 | ``` 577 | ##### 4. Create Transaction Data 578 | 579 | ```php 580 | // Transaction data to be sent 581 | $transaction_data = array( 582 | 'payment_type' => 'credit_card', 583 | 'credit_card' => array( 584 | 'token_id' => $token_id, 585 | 'bank' => 'bni', 586 | 'save_token_id' => isset($_POST['save_cc']) 587 | ), 588 | 'transaction_details' => $transaction_details, 589 | 'item_details' => $items, 590 | 'customer_details' => $customer_details 591 | ); 592 | ``` 593 | 594 | ##### 5. Charge 595 | 596 | ```php 597 | //create new object from Veritrans class 598 | $vt = new Veritrans; 599 | $response= $vt->vtdirect_charge($transaction_data); 600 | ``` 601 | 602 | ##### 6. Handle Transaction Status 603 | 604 | ```php 605 | // Success 606 | if($response->transaction_status == 'capture') { 607 | echo "

Transaksi berhasil.

"; 608 | echo "

Status transaksi untuk order id $response->order_id: " . 609 | "$response->transaction_status

"; 610 | 611 | echo "

Detail transaksi:

"; 612 | echo "
";
613 |   var_dump($response);
614 |   echo "
"; 615 | } 616 | // Deny 617 | else if($response->transaction_status == 'deny') { 618 | echo "

Transaksi ditolak.

"; 619 | echo "

Status transaksi untuk order id .$response->order_id: " . 620 | "$response->transaction_status

"; 621 | 622 | echo "

Detail transaksi:

"; 623 | echo "
";
624 |   var_dump($response);
625 |   echo "
"; 626 | } 627 | // Challenge 628 | else if($response->transaction_status == 'challenge') { 629 | echo "

Transaksi challenge.

"; 630 | echo "

Status transaksi untuk order id $response->order_id: " . 631 | "$response->transaction_status

"; 632 | 633 | echo "

Detail transaksi:

"; 634 | echo "
";
635 |   var_dump($response);
636 |   echo "
"; 637 | } 638 | // Error 639 | else { 640 | echo "

Terjadi kesalahan pada data transaksi yang dikirim.

"; 641 | echo "

Status message: [$response->status_code] " . 642 | "$response->status_message

"; 643 | 644 | echo "
";
645 |   var_dump($response);
646 |   echo "
"; 647 | } 648 | ``` 649 | 650 | #### Process Transaction 651 | More details can be found [here](https://github.com/harrypujianto/Veritrans-Laravel5/blob/master/app/Http/Controllers/TransactionController.php) 652 | 653 | Don't forget to create new veritrans object 654 | ```php 655 | //creating new veritrans object 656 | $vt = new Veritrans; 657 | ``` 658 | ##### Get a Transaction Status 659 | ```php 660 | $status = $vt->status($order_id); 661 | var_dump($status); 662 | ``` 663 | ##### Approve a Transaction 664 | ```php 665 | $approve = $vt->approve($order_id); 666 | var_dump($approve); 667 | ``` 668 | ##### Cancel a Transaction 669 | ```php 670 | $cancel = $vt->cancel($order_id); 671 | var_dump($cancel); 672 | ``` 673 | -------------------------------------------------------------------------------- /app/Exceptions/VeritransException.php: -------------------------------------------------------------------------------- 1 | uniqid(), 31 | 'gross_amount' => 200000 32 | ); 33 | 34 | // Populate items 35 | $items = [ 36 | array( 37 | 'id' => 'item1', 38 | 'price' => 100000, 39 | 'quantity' => 1, 40 | 'name' => 'Adidas f50' 41 | ), 42 | array( 43 | 'id' => 'item2', 44 | 'price' => 50000, 45 | 'quantity' => 2, 46 | 'name' => 'Nike N90' 47 | ) 48 | ]; 49 | 50 | // Populate customer's billing address 51 | $billing_address = array( 52 | 'first_name' => "Andri", 53 | 'last_name' => "Setiawan", 54 | 'address' => "Karet Belakang 15A, Setiabudi.", 55 | 'city' => "Jakarta", 56 | 'postal_code' => "51161", 57 | 'phone' => "081322311801", 58 | 'country_code' => 'IDN' 59 | ); 60 | 61 | // Populate customer's shipping address 62 | $shipping_address = array( 63 | 'first_name' => "John", 64 | 'last_name' => "Watson", 65 | 'address' => "Bakerstreet 221B.", 66 | 'city' => "Jakarta", 67 | 'postal_code' => "51162", 68 | 'phone' => "081322311801", 69 | 'country_code' => 'IDN' 70 | ); 71 | 72 | // Populate customer's Info 73 | $customer_details = array( 74 | 'first_name' => "Andri", 75 | 'last_name' => "Setiawan", 76 | 'email' => "andrisetiawan@asdasd.com", 77 | 'phone' => "081322311801", 78 | 'billing_address' => $billing_address, 79 | 'shipping_address'=> $shipping_address 80 | ); 81 | 82 | // Data yang akan dikirim untuk request redirect_url. 83 | $credit_card['secure'] = true; 84 | //ser save_card true to enable oneclick or 2click 85 | //$credit_card['save_card'] = true; 86 | 87 | $time = time(); 88 | $custom_expiry = array( 89 | 'start_time' => date("Y-m-d H:i:s O",$time), 90 | 'unit' => 'hour', 91 | 'duration' => 2 92 | ); 93 | 94 | $transaction_data = array( 95 | 'transaction_details'=> $transaction_details, 96 | 'item_details' => $items, 97 | 'customer_details' => $customer_details, 98 | 'credit_card' => $credit_card, 99 | 'expiry' => $custom_expiry 100 | ); 101 | 102 | try 103 | { 104 | $snap_token = $midtrans->getSnapToken($transaction_data); 105 | //return redirect($vtweb_url); 106 | echo $snap_token; 107 | } 108 | catch (Exception $e) 109 | { 110 | return $e->getMessage; 111 | } 112 | } 113 | 114 | public function finish(Request $request) 115 | { 116 | $result = $request->input('result_data'); 117 | $result = json_decode($result); 118 | echo $result->status_message . '
'; 119 | echo 'RESULT
';
120 |         var_dump($result);
121 |         echo '
' ; 122 | } 123 | 124 | public function notification() 125 | { 126 | $midtrans = new Midtrans; 127 | echo 'test notification handler'; 128 | $json_result = file_get_contents('php://input'); 129 | $result = json_decode($json_result); 130 | 131 | if($result){ 132 | $notif = $midtrans->status($result->order_id); 133 | } 134 | 135 | error_log(print_r($result,TRUE)); 136 | 137 | /* 138 | $transaction = $notif->transaction_status; 139 | $type = $notif->payment_type; 140 | $order_id = $notif->order_id; 141 | $fraud = $notif->fraud_status; 142 | 143 | if ($transaction == 'capture') { 144 | // For credit card transaction, we need to check whether transaction is challenge by FDS or not 145 | if ($type == 'credit_card'){ 146 | if($fraud == 'challenge'){ 147 | // TODO set payment status in merchant's database to 'Challenge by FDS' 148 | // TODO merchant should decide whether this transaction is authorized or not in MAP 149 | echo "Transaction order_id: " . $order_id ." is challenged by FDS"; 150 | } 151 | else { 152 | // TODO set payment status in merchant's database to 'Success' 153 | echo "Transaction order_id: " . $order_id ." successfully captured using " . $type; 154 | } 155 | } 156 | } 157 | else if ($transaction == 'settlement'){ 158 | // TODO set payment status in merchant's database to 'Settlement' 159 | echo "Transaction order_id: " . $order_id ." successfully transfered using " . $type; 160 | } 161 | else if($transaction == 'pending'){ 162 | // TODO set payment status in merchant's database to 'Pending' 163 | echo "Waiting customer to finish transaction order_id: " . $order_id . " using " . $type; 164 | } 165 | else if ($transaction == 'deny') { 166 | // TODO set payment status in merchant's database to 'Denied' 167 | echo "Payment using " . $type . " for transaction order_id: " . $order_id . " is denied."; 168 | }*/ 169 | 170 | } 171 | } -------------------------------------------------------------------------------- /app/Http/Controllers/TransactionController.php: -------------------------------------------------------------------------------- 1 | '; 15 | Veritrans::$isProduction = false; 16 | } 17 | 18 | public function transaction() 19 | { 20 | return view('transaction'); 21 | } 22 | 23 | public function transaction_process(Request $request) 24 | { 25 | $vt = new Veritrans; 26 | $order_id = $request->input('order_id'); 27 | $action = $request->input('action'); 28 | switch ($action) { 29 | case 'status': 30 | $this->status($order_id); 31 | break; 32 | case 'approve': 33 | $this->approve($order_id); 34 | break; 35 | case 'expire': 36 | $this->expire($order_id); 37 | break; 38 | case 'cancel': 39 | $this->cancel($order_id); 40 | break; 41 | } 42 | } 43 | 44 | public function status($order_id) 45 | { 46 | $vt = new Veritrans; 47 | echo 'test get status
'; 48 | print_r ($vt->status($order_id) ); 49 | } 50 | 51 | public function cancel($order_id) 52 | { 53 | $vt = new Veritrans; 54 | echo 'test cancel trx
'; 55 | echo $vt->cancel($order_id); 56 | } 57 | 58 | public function approve($order_id) 59 | { 60 | $vt = new Veritrans; 61 | echo 'test get approve
'; 62 | print_r ($vt->approve($order_id) ); 63 | } 64 | 65 | public function expire($order_id) 66 | { 67 | $vt = new Veritrans; 68 | echo 'test get expire
'; 69 | print_r ($vt->expire($order_id) ); 70 | } 71 | 72 | 73 | } -------------------------------------------------------------------------------- /app/Http/Controllers/VtdirectController.php: -------------------------------------------------------------------------------- 1 | '; 15 | Veritrans::$isProduction = false; 16 | } 17 | 18 | public function vtdirect() 19 | { 20 | return view('checkout'); 21 | } 22 | 23 | public function checkout_process(Request $request) 24 | { 25 | $token = $request->input('token_id'); 26 | $vt = new Veritrans; 27 | 28 | $transaction_details = array( 29 | 'order_id' => uniqid(), 30 | 'gross_amount' => 10000 31 | ); 32 | 33 | // Populate items 34 | $items = [ 35 | array( 36 | 'id' => 'item1', 37 | 'price' => 5000, 38 | 'quantity' => 1, 39 | 'name' => 'Adidas f50' 40 | ), 41 | array( 42 | 'id' => 'item2', 43 | 'price' => 2500, 44 | 'quantity' => 2, 45 | 'name' => 'Nike N90' 46 | ) 47 | ]; 48 | 49 | // Populate customer's billing address 50 | $billing_address = array( 51 | 'first_name' => "Andri", 52 | 'last_name' => "Setiawan", 53 | 'address' => "Karet Belakang 15A, Setiabudi.", 54 | 'city' => "Jakarta", 55 | 'postal_code' => "51161", 56 | 'phone' => "081322311801", 57 | 'country_code' => 'IDN' 58 | ); 59 | 60 | // Populate customer's shipping address 61 | $shipping_address = array( 62 | 'first_name' => "John", 63 | 'last_name' => "Watson", 64 | 'address' => "Bakerstreet 221B.", 65 | 'city' => "Jakarta", 66 | 'postal_code' => "51162", 67 | 'phone' => "081322311801", 68 | 'country_code'=> 'IDN' 69 | ); 70 | 71 | // Populate customer's Info 72 | $customer_details = array( 73 | 'first_name' => "Andri", 74 | 'last_name' => "Setiawan", 75 | 'email' => "andrisetiawan@me.com", 76 | 'phone' => "081322311801", 77 | 'billing_address' => $billing_address, 78 | 'shipping_address'=> $shipping_address 79 | ); 80 | 81 | $transaction_data = array( 82 | 'payment_type' => 'credit_card', 83 | 'credit_card' => array( 84 | 'token_id' => $token, 85 | 'bank' => 'bni' 86 | ), 87 | 'transaction_details' => $transaction_details, 88 | 'item_details' => $items 89 | ); 90 | 91 | 92 | $response = null; 93 | try 94 | { 95 | $response= $vt->vtdirect_charge($transaction_data); 96 | } 97 | catch (Exception $e) 98 | { 99 | return $e->getMessage; 100 | } 101 | 102 | //var_dump($response); 103 | if($response) 104 | { 105 | if($response->transaction_status == "capture") 106 | { 107 | //success 108 | echo "Transaksi berhasil.
"; 109 | echo "Status transaksi untuk order id ".$response->order_id.": ".$response->transaction_status; 110 | 111 | echo "

Detail transaksi:

"; 112 | var_dump($response); 113 | } 114 | else if($response->transaction_status == "deny") 115 | { 116 | //deny 117 | echo "Transaksi ditolak.
"; 118 | echo "Status transaksi untuk order id ".$response->order_id.": ".$response->transaction_status; 119 | 120 | echo "

Detail transaksi:

"; 121 | var_dump($response); 122 | } 123 | else if($response->transaction_status == "challenge") 124 | { 125 | //challenge 126 | echo "Transaksi challenge.
"; 127 | echo "Status transaksi untuk order id ".$response->order_id.": ".$response->transaction_status; 128 | 129 | echo "

Detail transaksi:

"; 130 | var_dump($response); 131 | } 132 | else 133 | { 134 | //error 135 | echo "Terjadi kesalahan pada data transaksi yang dikirim.
"; 136 | echo "Status message: [".$response->status_code."] ".$response->status_message; 137 | 138 | echo "

Response:

"; 139 | var_dump($response); 140 | } 141 | } 142 | 143 | } 144 | } -------------------------------------------------------------------------------- /app/Http/Controllers/VtwebController.php: -------------------------------------------------------------------------------- 1 | '; 15 | 16 | //set Veritrans::$isProduction value to true for production mode 17 | Veritrans::$isProduction = false; 18 | } 19 | 20 | public function vtweb() 21 | { 22 | $vt = new Veritrans; 23 | 24 | $transaction_details = array( 25 | 'order_id' => uniqid(), 26 | 'gross_amount' => 200000 27 | ); 28 | 29 | // Populate items 30 | $items = [ 31 | array( 32 | 'id' => 'item1', 33 | 'price' => 100000, 34 | 'quantity' => 1, 35 | 'name' => 'Adidas f50' 36 | ), 37 | array( 38 | 'id' => 'item2', 39 | 'price' => 50000, 40 | 'quantity' => 2, 41 | 'name' => 'Nike N90' 42 | ) 43 | ]; 44 | 45 | // Populate customer's billing address 46 | $billing_address = array( 47 | 'first_name' => "Andri", 48 | 'last_name' => "Setiawan", 49 | 'address' => "Karet Belakang 15A, Setiabudi.", 50 | 'city' => "Jakarta", 51 | 'postal_code' => "51161", 52 | 'phone' => "081322311801", 53 | 'country_code' => 'IDN' 54 | ); 55 | 56 | // Populate customer's shipping address 57 | $shipping_address = array( 58 | 'first_name' => "John", 59 | 'last_name' => "Watson", 60 | 'address' => "Bakerstreet 221B.", 61 | 'city' => "Jakarta", 62 | 'postal_code' => "51162", 63 | 'phone' => "081322311801", 64 | 'country_code'=> 'IDN' 65 | ); 66 | 67 | // Populate customer's Info 68 | $customer_details = array( 69 | 'first_name' => "Andri", 70 | 'last_name' => "Setiawan", 71 | 'email' => "andrisetiawan@asdasd.com", 72 | 'phone' => "081322311801", 73 | 'billing_address' => $billing_address, 74 | 'shipping_address'=> $shipping_address 75 | ); 76 | 77 | // Data yang akan dikirim untuk request redirect_url. 78 | // Uncomment 'credit_card_3d_secure' => true jika transaksi ingin diproses dengan 3DSecure. 79 | $transaction_data = array( 80 | 'payment_type' => 'vtweb', 81 | 'vtweb' => array( 82 | //'enabled_payments' => [], 83 | 'credit_card_3d_secure' => true 84 | ), 85 | 'transaction_details'=> $transaction_details, 86 | 'item_details' => $items, 87 | 'customer_details' => $customer_details 88 | ); 89 | 90 | try 91 | { 92 | $vtweb_url = $vt->vtweb_charge($transaction_data); 93 | return redirect($vtweb_url); 94 | } 95 | catch (Exception $e) 96 | { 97 | return $e->getMessage; 98 | } 99 | } 100 | 101 | public function notification() 102 | { 103 | $vt = new Veritrans; 104 | echo 'test notification handler'; 105 | $json_result = file_get_contents('php://input'); 106 | $result = json_decode($json_result); 107 | 108 | if($result){ 109 | $notif = $vt->status($result->order_id); 110 | } 111 | 112 | error_log(print_r($result,TRUE)); 113 | 114 | /* 115 | $transaction = $notif->transaction_status; 116 | $type = $notif->payment_type; 117 | $order_id = $notif->order_id; 118 | $fraud = $notif->fraud_status; 119 | 120 | if ($transaction == 'capture') { 121 | // For credit card transaction, we need to check whether transaction is challenge by FDS or not 122 | if ($type == 'credit_card'){ 123 | if($fraud == 'challenge'){ 124 | // TODO set payment status in merchant's database to 'Challenge by FDS' 125 | // TODO merchant should decide whether this transaction is authorized or not in MAP 126 | echo "Transaction order_id: " . $order_id ." is challenged by FDS"; 127 | } 128 | else { 129 | // TODO set payment status in merchant's database to 'Success' 130 | echo "Transaction order_id: " . $order_id ." successfully captured using " . $type; 131 | } 132 | } 133 | } 134 | else if ($transaction == 'settlement'){ 135 | // TODO set payment status in merchant's database to 'Settlement' 136 | echo "Transaction order_id: " . $order_id ." successfully transfered using " . $type; 137 | } 138 | else if($transaction == 'pending'){ 139 | // TODO set payment status in merchant's database to 'Pending' 140 | echo "Waiting customer to finish transaction order_id: " . $order_id . " using " . $type; 141 | } 142 | else if ($transaction == 'deny') { 143 | // TODO set payment status in merchant's database to 'Denied' 144 | echo "Payment using " . $type . " for transaction order_id: " . $order_id . " is denied."; 145 | }*/ 146 | 147 | } 148 | } -------------------------------------------------------------------------------- /app/Http/routes.php: -------------------------------------------------------------------------------- 1 | $url, 89 | CURLOPT_HTTPHEADER => array( 90 | 'Content-Type: application/json', 91 | 'Accept: application/json', 92 | 'Authorization: Basic ' . base64_encode($server_key . ':') 93 | ), 94 | CURLOPT_RETURNTRANSFER => 1, 95 | // CURLOPT_CAINFO => dirname(__FILE__) . "/data/cacert.pem" 96 | ); 97 | 98 | // merging with Veritrans_Config::$curlOptions 99 | if (count(Midtrans::$curlOptions)) { 100 | // We need to combine headers manually, because it's array and it will no be merged 101 | if (Midtrans::$curlOptions[CURLOPT_HTTPHEADER]) { 102 | $mergedHeders = array_merge($curl_options[CURLOPT_HTTPHEADER], Midtrans::$curlOptions[CURLOPT_HTTPHEADER]); 103 | $headerOptions = array( CURLOPT_HTTPHEADER => $mergedHeders ); 104 | } else { 105 | $mergedHeders = array(); 106 | } 107 | 108 | $curl_options = array_replace_recursive($curl_options, Midtrans::$curlOptions, $headerOptions); 109 | } 110 | 111 | if ($post) { 112 | $curl_options[CURLOPT_POST] = 1; 113 | 114 | if ($data_hash) { 115 | $body = json_encode($data_hash); 116 | $curl_options[CURLOPT_POSTFIELDS] = $body; 117 | } else { 118 | $curl_options[CURLOPT_POSTFIELDS] = ''; 119 | } 120 | } 121 | 122 | curl_setopt_array($ch, $curl_options); 123 | 124 | $result = curl_exec($ch); 125 | $info = curl_getinfo($ch); 126 | // curl_close($ch); 127 | 128 | if ($result === FALSE) { 129 | throw new Exception('CURL Error: ' . curl_error($ch), curl_errno($ch)); 130 | } 131 | else { 132 | $result_array = json_decode($result); 133 | if ($info['http_code'] != 201) { 134 | $message = 'Midtrans Error (' . $info['http_code'] . '): ' 135 | . implode(',', $result_array->error_messages); 136 | throw new Exception($message, $info['http_code']); 137 | 138 | } 139 | else { 140 | return $result_array; 141 | } 142 | } 143 | } 144 | 145 | public static function getSnapToken($params) 146 | { 147 | 148 | $result = Midtrans::post( 149 | Midtrans::getSnapBaseUrl() . '/transactions', 150 | Midtrans::$serverKey, 151 | $params); 152 | 153 | return $result->token; 154 | } 155 | 156 | } -------------------------------------------------------------------------------- /app/Veritrans/Veritrans.php: -------------------------------------------------------------------------------- 1 | $url, 82 | CURLOPT_HTTPHEADER => array( 83 | 'Content-Type: application/json', 84 | 'Accept: application/json', 85 | 'Authorization: Basic ' . base64_encode($server_key . ':') 86 | ), 87 | CURLOPT_RETURNTRANSFER => 1, 88 | // CURLOPT_CAINFO => dirname(__FILE__) . "/data/cacert.pem" 89 | ); 90 | 91 | // merging with Veritrans_Config::$curlOptions 92 | if (count(Veritrans::$curlOptions)) { 93 | // We need to combine headers manually, because it's array and it will no be merged 94 | if (Veritrans::$curlOptions[CURLOPT_HTTPHEADER]) { 95 | $mergedHeders = array_merge($curl_options[CURLOPT_HTTPHEADER], Veritrans::$curlOptions[CURLOPT_HTTPHEADER]); 96 | $headerOptions = array( CURLOPT_HTTPHEADER => $mergedHeders ); 97 | } else { 98 | $mergedHeders = array(); 99 | } 100 | 101 | $curl_options = array_replace_recursive($curl_options, Veritrans::$curlOptions, $headerOptions); 102 | } 103 | 104 | if ($post) { 105 | $curl_options[CURLOPT_POST] = 1; 106 | 107 | if ($data_hash) { 108 | $body = json_encode($data_hash); 109 | $curl_options[CURLOPT_POSTFIELDS] = $body; 110 | } else { 111 | $curl_options[CURLOPT_POSTFIELDS] = ''; 112 | } 113 | } 114 | 115 | curl_setopt_array($ch, $curl_options); 116 | 117 | $result = curl_exec($ch); 118 | // curl_close($ch); 119 | 120 | if ($result === FALSE) { 121 | throw new Exception('CURL Error: ' . curl_error($ch), curl_errno($ch)); 122 | } 123 | else { 124 | $result_array = json_decode($result); 125 | if (!in_array($result_array->status_code, array(200, 201, 202, 407))) { 126 | $message = 'Veritrans Error (' . $result_array->status_code . '): ' 127 | . $result_array->status_message; 128 | //throw new Exception($message, $result_array->status_code); 129 | throw new Exception($message, $result_array->status_code); 130 | } 131 | else { 132 | return $result_array; 133 | } 134 | } 135 | } 136 | 137 | public function vtweb_charge($payloads) 138 | { 139 | 140 | $result = Veritrans::post( 141 | Veritrans::getBaseUrl() . '/charge', 142 | Veritrans::$serverKey, 143 | $payloads); 144 | 145 | return $result->redirect_url; 146 | } 147 | 148 | public function vtdirect_charge($payloads) 149 | { 150 | 151 | $result = Veritrans::post( 152 | Veritrans::getBaseUrl() . '/charge', 153 | Veritrans::$serverKey, 154 | $payloads); 155 | 156 | return $result; 157 | } 158 | 159 | /** 160 | * Retrieve transaction status 161 | * @param string $id Order ID or transaction ID 162 | * @return mixed[] 163 | */ 164 | public static function status($id) 165 | { 166 | return Veritrans::get( 167 | Veritrans::getBaseUrl() . '/' . $id . '/status', 168 | Veritrans::$serverKey, 169 | false); 170 | } 171 | 172 | /** 173 | * Appove challenge transaction 174 | * @param string $id Order ID or transaction ID 175 | * @return string 176 | */ 177 | public static function approve($id) 178 | { 179 | return Veritrans::post( 180 | Veritrans::getBaseUrl() . '/' . $id . '/approve', 181 | Veritrans::$serverKey, 182 | false)->status_code; 183 | } 184 | 185 | /** 186 | * Cancel transaction before it's setteled 187 | * @param string $id Order ID or transaction ID 188 | * @return string 189 | */ 190 | public static function cancel($id) 191 | { 192 | return Veritrans::post( 193 | Veritrans::getBaseUrl() . '/' . $id . '/cancel', 194 | Veritrans::$serverKey, 195 | false)->status_code; 196 | } 197 | 198 | /** 199 | * Expire transaction before it's setteled 200 | * @param string $id Order ID or transaction ID 201 | * @return mixed[] 202 | */ 203 | public static function expire($id) 204 | { 205 | return Veritrans::post( 206 | Veritrans::getBaseUrl() . '/' . $id . '/expire', 207 | Veritrans::$serverKey, 208 | false); 209 | } 210 | 211 | } -------------------------------------------------------------------------------- /public/css/jquery.fancybox.css: -------------------------------------------------------------------------------- 1 | /*! fancyBox v2.1.5 fancyapps.com | fancyapps.com/fancybox/#license */ 2 | .fancybox-wrap, 3 | .fancybox-skin, 4 | .fancybox-outer, 5 | .fancybox-inner, 6 | .fancybox-image, 7 | .fancybox-wrap iframe, 8 | .fancybox-wrap object, 9 | .fancybox-nav, 10 | .fancybox-nav span, 11 | .fancybox-tmp 12 | { 13 | padding: 0; 14 | margin: 0; 15 | border: 0; 16 | outline: none; 17 | vertical-align: top; 18 | } 19 | 20 | .fancybox-wrap { 21 | position: absolute; 22 | top: 0; 23 | left: 0; 24 | z-index: 8020; 25 | } 26 | 27 | .fancybox-skin { 28 | position: relative; 29 | background: #f9f9f9; 30 | color: #444; 31 | text-shadow: none; 32 | -webkit-border-radius: 4px; 33 | -moz-border-radius: 4px; 34 | border-radius: 4px; 35 | } 36 | 37 | .fancybox-opened { 38 | z-index: 8030; 39 | } 40 | 41 | .fancybox-opened .fancybox-skin { 42 | -webkit-box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5); 43 | -moz-box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5); 44 | box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5); 45 | } 46 | 47 | .fancybox-outer, .fancybox-inner { 48 | position: relative; 49 | } 50 | 51 | .fancybox-inner { 52 | overflow: hidden; 53 | } 54 | 55 | .fancybox-type-iframe .fancybox-inner { 56 | -webkit-overflow-scrolling: touch; 57 | } 58 | 59 | .fancybox-error { 60 | color: #444; 61 | font: 14px/20px "Helvetica Neue",Helvetica,Arial,sans-serif; 62 | margin: 0; 63 | padding: 15px; 64 | white-space: nowrap; 65 | } 66 | 67 | .fancybox-image, .fancybox-iframe { 68 | display: block; 69 | width: 100%; 70 | height: 100%; 71 | } 72 | 73 | .fancybox-image { 74 | max-width: 100%; 75 | max-height: 100%; 76 | } 77 | 78 | #fancybox-loading, .fancybox-close, .fancybox-prev span, .fancybox-next span { 79 | background-image: url('fancybox_sprite.png'); 80 | } 81 | 82 | #fancybox-loading { 83 | position: fixed; 84 | top: 50%; 85 | left: 50%; 86 | margin-top: -22px; 87 | margin-left: -22px; 88 | background-position: 0 -108px; 89 | opacity: 0.8; 90 | cursor: pointer; 91 | z-index: 8060; 92 | } 93 | 94 | #fancybox-loading div { 95 | width: 44px; 96 | height: 44px; 97 | background: url('fancybox_loading.gif') center center no-repeat; 98 | } 99 | 100 | .fancybox-close { 101 | position: absolute; 102 | top: -18px; 103 | right: -18px; 104 | width: 36px; 105 | height: 36px; 106 | cursor: pointer; 107 | z-index: 8040; 108 | } 109 | 110 | .fancybox-nav { 111 | position: absolute; 112 | top: 0; 113 | width: 40%; 114 | height: 100%; 115 | cursor: pointer; 116 | text-decoration: none; 117 | background: transparent url('blank.gif'); /* helps IE */ 118 | -webkit-tap-highlight-color: rgba(0,0,0,0); 119 | z-index: 8040; 120 | } 121 | 122 | .fancybox-prev { 123 | left: 0; 124 | } 125 | 126 | .fancybox-next { 127 | right: 0; 128 | } 129 | 130 | .fancybox-nav span { 131 | position: absolute; 132 | top: 50%; 133 | width: 36px; 134 | height: 34px; 135 | margin-top: -18px; 136 | cursor: pointer; 137 | z-index: 8040; 138 | visibility: hidden; 139 | } 140 | 141 | .fancybox-prev span { 142 | left: 10px; 143 | background-position: 0 -36px; 144 | } 145 | 146 | .fancybox-next span { 147 | right: 10px; 148 | background-position: 0 -72px; 149 | } 150 | 151 | .fancybox-nav:hover span { 152 | visibility: visible; 153 | } 154 | 155 | .fancybox-tmp { 156 | position: absolute; 157 | top: -99999px; 158 | left: -99999px; 159 | visibility: hidden; 160 | max-width: 99999px; 161 | max-height: 99999px; 162 | overflow: visible !important; 163 | } 164 | 165 | /* Overlay helper */ 166 | 167 | .fancybox-lock { 168 | overflow: hidden !important; 169 | width: auto; 170 | } 171 | 172 | .fancybox-lock body { 173 | overflow: hidden !important; 174 | } 175 | 176 | .fancybox-lock-test { 177 | overflow-y: hidden !important; 178 | } 179 | 180 | .fancybox-overlay { 181 | position: absolute; 182 | top: 0; 183 | left: 0; 184 | overflow: hidden; 185 | display: none; 186 | z-index: 8010; 187 | background: url('fancybox_overlay.png'); 188 | } 189 | 190 | .fancybox-overlay-fixed { 191 | position: fixed; 192 | bottom: 0; 193 | right: 0; 194 | } 195 | 196 | .fancybox-lock .fancybox-overlay { 197 | overflow: auto; 198 | overflow-y: scroll; 199 | } 200 | 201 | /* Title helper */ 202 | 203 | .fancybox-title { 204 | visibility: hidden; 205 | font: normal 13px/20px "Helvetica Neue",Helvetica,Arial,sans-serif; 206 | position: relative; 207 | text-shadow: none; 208 | z-index: 8050; 209 | } 210 | 211 | .fancybox-opened .fancybox-title { 212 | visibility: visible; 213 | } 214 | 215 | .fancybox-title-float-wrap { 216 | position: absolute; 217 | bottom: 0; 218 | right: 50%; 219 | margin-bottom: -35px; 220 | z-index: 8050; 221 | text-align: center; 222 | } 223 | 224 | .fancybox-title-float-wrap .child { 225 | display: inline-block; 226 | margin-right: -100%; 227 | padding: 2px 20px; 228 | background: transparent; /* Fallback for web browsers that doesn't support RGBa */ 229 | background: rgba(0, 0, 0, 0.8); 230 | -webkit-border-radius: 15px; 231 | -moz-border-radius: 15px; 232 | border-radius: 15px; 233 | text-shadow: 0 1px 2px #222; 234 | color: #FFF; 235 | font-weight: bold; 236 | line-height: 24px; 237 | white-space: nowrap; 238 | } 239 | 240 | .fancybox-title-outside-wrap { 241 | position: relative; 242 | margin-top: 10px; 243 | color: #fff; 244 | } 245 | 246 | .fancybox-title-inside-wrap { 247 | padding-top: 10px; 248 | } 249 | 250 | .fancybox-title-over-wrap { 251 | position: absolute; 252 | bottom: 0; 253 | left: 0; 254 | color: #fff; 255 | padding: 10px; 256 | background: #000; 257 | background: rgba(0, 0, 0, .8); 258 | } 259 | 260 | /*Retina graphics!*/ 261 | @media only screen and (-webkit-min-device-pixel-ratio: 1.5), 262 | only screen and (min--moz-device-pixel-ratio: 1.5), 263 | only screen and (min-device-pixel-ratio: 1.5){ 264 | 265 | #fancybox-loading, .fancybox-close, .fancybox-prev span, .fancybox-next span { 266 | background-image: url('fancybox_sprite@2x.png'); 267 | background-size: 44px 152px; /*The size of the normal image, half the size of the hi-res image*/ 268 | } 269 | 270 | #fancybox-loading div { 271 | background-image: url('fancybox_loading@2x.gif'); 272 | background-size: 24px 24px; /*The size of the normal image, half the size of the hi-res image*/ 273 | } 274 | } -------------------------------------------------------------------------------- /public/js/jquery.fancybox.pack.js: -------------------------------------------------------------------------------- 1 | /*! fancyBox v2.1.5 fancyapps.com | fancyapps.com/fancybox/#license */ 2 | (function(r,G,f,v){var J=f("html"),n=f(r),p=f(G),b=f.fancybox=function(){b.open.apply(this,arguments)},I=navigator.userAgent.match(/msie/i),B=null,s=G.createTouch!==v,t=function(a){return a&&a.hasOwnProperty&&a instanceof f},q=function(a){return a&&"string"===f.type(a)},E=function(a){return q(a)&&0
',image:'',iframe:'",error:'

The requested content cannot be loaded.
Please try again later.

',closeBtn:'',next:'',prev:''},openEffect:"fade",openSpeed:250,openEasing:"swing",openOpacity:!0, 6 | openMethod:"zoomIn",closeEffect:"fade",closeSpeed:250,closeEasing:"swing",closeOpacity:!0,closeMethod:"zoomOut",nextEffect:"elastic",nextSpeed:250,nextEasing:"swing",nextMethod:"changeIn",prevEffect:"elastic",prevSpeed:250,prevEasing:"swing",prevMethod:"changeOut",helpers:{overlay:!0,title:!0},onCancel:f.noop,beforeLoad:f.noop,afterLoad:f.noop,beforeShow:f.noop,afterShow:f.noop,beforeChange:f.noop,beforeClose:f.noop,afterClose:f.noop},group:{},opts:{},previous:null,coming:null,current:null,isActive:!1, 7 | isOpen:!1,isOpened:!1,wrap:null,skin:null,outer:null,inner:null,player:{timer:null,isActive:!1},ajaxLoad:null,imgPreload:null,transitions:{},helpers:{},open:function(a,d){if(a&&(f.isPlainObject(d)||(d={}),!1!==b.close(!0)))return f.isArray(a)||(a=t(a)?f(a).get():[a]),f.each(a,function(e,c){var k={},g,h,j,m,l;"object"===f.type(c)&&(c.nodeType&&(c=f(c)),t(c)?(k={href:c.data("fancybox-href")||c.attr("href"),title:c.data("fancybox-title")||c.attr("title"),isDom:!0,element:c},f.metadata&&f.extend(!0,k, 8 | c.metadata())):k=c);g=d.href||k.href||(q(c)?c:null);h=d.title!==v?d.title:k.title||"";m=(j=d.content||k.content)?"html":d.type||k.type;!m&&k.isDom&&(m=c.data("fancybox-type"),m||(m=(m=c.prop("class").match(/fancybox\.(\w+)/))?m[1]:null));q(g)&&(m||(b.isImage(g)?m="image":b.isSWF(g)?m="swf":"#"===g.charAt(0)?m="inline":q(c)&&(m="html",j=c)),"ajax"===m&&(l=g.split(/\s+/,2),g=l.shift(),l=l.shift()));j||("inline"===m?g?j=f(q(g)?g.replace(/.*(?=#[^\s]+$)/,""):g):k.isDom&&(j=c):"html"===m?j=g:!m&&(!g&& 9 | k.isDom)&&(m="inline",j=c));f.extend(k,{href:g,type:m,content:j,title:h,selector:l});a[e]=k}),b.opts=f.extend(!0,{},b.defaults,d),d.keys!==v&&(b.opts.keys=d.keys?f.extend({},b.defaults.keys,d.keys):!1),b.group=a,b._start(b.opts.index)},cancel:function(){var a=b.coming;a&&!1!==b.trigger("onCancel")&&(b.hideLoading(),b.ajaxLoad&&b.ajaxLoad.abort(),b.ajaxLoad=null,b.imgPreload&&(b.imgPreload.onload=b.imgPreload.onerror=null),a.wrap&&a.wrap.stop(!0,!0).trigger("onReset").remove(),b.coming=null,b.current|| 10 | b._afterZoomOut(a))},close:function(a){b.cancel();!1!==b.trigger("beforeClose")&&(b.unbindEvents(),b.isActive&&(!b.isOpen||!0===a?(f(".fancybox-wrap").stop(!0).trigger("onReset").remove(),b._afterZoomOut()):(b.isOpen=b.isOpened=!1,b.isClosing=!0,f(".fancybox-item, .fancybox-nav").remove(),b.wrap.stop(!0,!0).removeClass("fancybox-opened"),b.transitions[b.current.closeMethod]())))},play:function(a){var d=function(){clearTimeout(b.player.timer)},e=function(){d();b.current&&b.player.isActive&&(b.player.timer= 11 | setTimeout(b.next,b.current.playSpeed))},c=function(){d();p.unbind(".player");b.player.isActive=!1;b.trigger("onPlayEnd")};if(!0===a||!b.player.isActive&&!1!==a){if(b.current&&(b.current.loop||b.current.index=c.index?"next":"prev"],b.router=e||"jumpto",c.loop&&(0>a&&(a=c.group.length+a%c.group.length),a%=c.group.length),c.group[a]!==v&&(b.cancel(),b._start(a)))},reposition:function(a,d){var e=b.current,c=e?e.wrap:null,k;c&&(k=b._getPosition(d),a&&"scroll"===a.type?(delete k.position,c.stop(!0,!0).animate(k,200)):(c.css(k),e.pos=f.extend({},e.dim,k)))},update:function(a){var d= 13 | a&&a.type,e=!d||"orientationchange"===d;e&&(clearTimeout(B),B=null);b.isOpen&&!B&&(B=setTimeout(function(){var c=b.current;c&&!b.isClosing&&(b.wrap.removeClass("fancybox-tmp"),(e||"load"===d||"resize"===d&&c.autoResize)&&b._setDimension(),"scroll"===d&&c.canShrink||b.reposition(a),b.trigger("onUpdate"),B=null)},e&&!s?0:300))},toggle:function(a){b.isOpen&&(b.current.fitToView="boolean"===f.type(a)?a:!b.current.fitToView,s&&(b.wrap.removeAttr("style").addClass("fancybox-tmp"),b.trigger("onUpdate")), 14 | b.update())},hideLoading:function(){p.unbind(".loading");f("#fancybox-loading").remove()},showLoading:function(){var a,d;b.hideLoading();a=f('
').click(b.cancel).appendTo("body");p.bind("keydown.loading",function(a){if(27===(a.which||a.keyCode))a.preventDefault(),b.cancel()});b.defaults.fixed||(d=b.getViewport(),a.css({position:"absolute",top:0.5*d.h+d.y,left:0.5*d.w+d.x}))},getViewport:function(){var a=b.current&&b.current.locked||!1,d={x:n.scrollLeft(), 15 | y:n.scrollTop()};a?(d.w=a[0].clientWidth,d.h=a[0].clientHeight):(d.w=s&&r.innerWidth?r.innerWidth:n.width(),d.h=s&&r.innerHeight?r.innerHeight:n.height());return d},unbindEvents:function(){b.wrap&&t(b.wrap)&&b.wrap.unbind(".fb");p.unbind(".fb");n.unbind(".fb")},bindEvents:function(){var a=b.current,d;a&&(n.bind("orientationchange.fb"+(s?"":" resize.fb")+(a.autoCenter&&!a.locked?" scroll.fb":""),b.update),(d=a.keys)&&p.bind("keydown.fb",function(e){var c=e.which||e.keyCode,k=e.target||e.srcElement; 16 | if(27===c&&b.coming)return!1;!e.ctrlKey&&(!e.altKey&&!e.shiftKey&&!e.metaKey&&(!k||!k.type&&!f(k).is("[contenteditable]")))&&f.each(d,function(d,k){if(1h[0].clientWidth||h[0].clientHeight&&h[0].scrollHeight>h[0].clientHeight),h=f(h).parent();if(0!==c&&!j&&1g||0>k)b.next(0>g?"up":"right");d.preventDefault()}}))},trigger:function(a,d){var e,c=d||b.coming||b.current;if(c){f.isFunction(c[a])&&(e=c[a].apply(c,Array.prototype.slice.call(arguments,1)));if(!1===e)return!1;c.helpers&&f.each(c.helpers,function(d,e){if(e&&b.helpers[d]&&f.isFunction(b.helpers[d][a]))b.helpers[d][a](f.extend(!0, 18 | {},b.helpers[d].defaults,e),c)});p.trigger(a)}},isImage:function(a){return q(a)&&a.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\?|#).*)?$)/i)},isSWF:function(a){return q(a)&&a.match(/\.(swf)((\?|#).*)?$/i)},_start:function(a){var d={},e,c;a=l(a);e=b.group[a]||null;if(!e)return!1;d=f.extend(!0,{},b.opts,e);e=d.margin;c=d.padding;"number"===f.type(e)&&(d.margin=[e,e,e,e]);"number"===f.type(c)&&(d.padding=[c,c,c,c]);d.modal&&f.extend(!0,d,{closeBtn:!1,closeClick:!1,nextClick:!1,arrows:!1, 19 | mouseWheel:!1,keys:null,helpers:{overlay:{closeClick:!1}}});d.autoSize&&(d.autoWidth=d.autoHeight=!0);"auto"===d.width&&(d.autoWidth=!0);"auto"===d.height&&(d.autoHeight=!0);d.group=b.group;d.index=a;b.coming=d;if(!1===b.trigger("beforeLoad"))b.coming=null;else{c=d.type;e=d.href;if(!c)return b.coming=null,b.current&&b.router&&"jumpto"!==b.router?(b.current.index=a,b[b.router](b.direction)):!1;b.isActive=!0;if("image"===c||"swf"===c)d.autoHeight=d.autoWidth=!1,d.scrolling="visible";"image"===c&&(d.aspectRatio= 20 | !0);"iframe"===c&&s&&(d.scrolling="scroll");d.wrap=f(d.tpl.wrap).addClass("fancybox-"+(s?"mobile":"desktop")+" fancybox-type-"+c+" fancybox-tmp "+d.wrapCSS).appendTo(d.parent||"body");f.extend(d,{skin:f(".fancybox-skin",d.wrap),outer:f(".fancybox-outer",d.wrap),inner:f(".fancybox-inner",d.wrap)});f.each(["Top","Right","Bottom","Left"],function(a,b){d.skin.css("padding"+b,w(d.padding[a]))});b.trigger("onReady");if("inline"===c||"html"===c){if(!d.content||!d.content.length)return b._error("content")}else if(!e)return b._error("href"); 21 | "image"===c?b._loadImage():"ajax"===c?b._loadAjax():"iframe"===c?b._loadIframe():b._afterLoad()}},_error:function(a){f.extend(b.coming,{type:"html",autoWidth:!0,autoHeight:!0,minWidth:0,minHeight:0,scrolling:"no",hasError:a,content:b.coming.tpl.error});b._afterLoad()},_loadImage:function(){var a=b.imgPreload=new Image;a.onload=function(){this.onload=this.onerror=null;b.coming.width=this.width/b.opts.pixelRatio;b.coming.height=this.height/b.opts.pixelRatio;b._afterLoad()};a.onerror=function(){this.onload= 22 | this.onerror=null;b._error("image")};a.src=b.coming.href;!0!==a.complete&&b.showLoading()},_loadAjax:function(){var a=b.coming;b.showLoading();b.ajaxLoad=f.ajax(f.extend({},a.ajax,{url:a.href,error:function(a,e){b.coming&&"abort"!==e?b._error("ajax",a):b.hideLoading()},success:function(d,e){"success"===e&&(a.content=d,b._afterLoad())}}))},_loadIframe:function(){var a=b.coming,d=f(a.tpl.iframe.replace(/\{rnd\}/g,(new Date).getTime())).attr("scrolling",s?"auto":a.iframe.scrolling).attr("src",a.href); 23 | f(a.wrap).bind("onReset",function(){try{f(this).find("iframe").hide().attr("src","//about:blank").end().empty()}catch(a){}});a.iframe.preload&&(b.showLoading(),d.one("load",function(){f(this).data("ready",1);s||f(this).bind("load.fb",b.update);f(this).parents(".fancybox-wrap").width("100%").removeClass("fancybox-tmp").show();b._afterLoad()}));a.content=d.appendTo(a.inner);a.iframe.preload||b._afterLoad()},_preloadImages:function(){var a=b.group,d=b.current,e=a.length,c=d.preload?Math.min(d.preload, 24 | e-1):0,f,g;for(g=1;g<=c;g+=1)f=a[(d.index+g)%e],"image"===f.type&&f.href&&((new Image).src=f.href)},_afterLoad:function(){var a=b.coming,d=b.current,e,c,k,g,h;b.hideLoading();if(a&&!1!==b.isActive)if(!1===b.trigger("afterLoad",a,d))a.wrap.stop(!0).trigger("onReset").remove(),b.coming=null;else{d&&(b.trigger("beforeChange",d),d.wrap.stop(!0).removeClass("fancybox-opened").find(".fancybox-item, .fancybox-nav").remove());b.unbindEvents();e=a.content;c=a.type;k=a.scrolling;f.extend(b,{wrap:a.wrap,skin:a.skin, 25 | outer:a.outer,inner:a.inner,current:a,previous:d});g=a.href;switch(c){case "inline":case "ajax":case "html":a.selector?e=f("
").html(e).find(a.selector):t(e)&&(e.data("fancybox-placeholder")||e.data("fancybox-placeholder",f('
').insertAfter(e).hide()),e=e.show().detach(),a.wrap.bind("onReset",function(){f(this).find(e).length&&e.hide().replaceAll(e.data("fancybox-placeholder")).data("fancybox-placeholder",!1)}));break;case "image":e=a.tpl.image.replace("{href}", 26 | g);break;case "swf":e='',h="",f.each(a.swf,function(a,b){e+='';h+=" "+a+'="'+b+'"'}),e+='"}(!t(e)||!e.parent().is(a.inner))&&a.inner.append(e);b.trigger("beforeShow");a.inner.css("overflow","yes"===k?"scroll": 27 | "no"===k?"hidden":k);b._setDimension();b.reposition();b.isOpen=!1;b.coming=null;b.bindEvents();if(b.isOpened){if(d.prevMethod)b.transitions[d.prevMethod]()}else f(".fancybox-wrap").not(a.wrap).stop(!0).trigger("onReset").remove();b.transitions[b.isOpened?a.nextMethod:a.openMethod]();b._preloadImages()}},_setDimension:function(){var a=b.getViewport(),d=0,e=!1,c=!1,e=b.wrap,k=b.skin,g=b.inner,h=b.current,c=h.width,j=h.height,m=h.minWidth,u=h.minHeight,n=h.maxWidth,p=h.maxHeight,s=h.scrolling,q=h.scrollOutside? 28 | h.scrollbarWidth:0,x=h.margin,y=l(x[1]+x[3]),r=l(x[0]+x[2]),v,z,t,C,A,F,B,D,H;e.add(k).add(g).width("auto").height("auto").removeClass("fancybox-tmp");x=l(k.outerWidth(!0)-k.width());v=l(k.outerHeight(!0)-k.height());z=y+x;t=r+v;C=E(c)?(a.w-z)*l(c)/100:c;A=E(j)?(a.h-t)*l(j)/100:j;if("iframe"===h.type){if(H=h.content,h.autoHeight&&1===H.data("ready"))try{H[0].contentWindow.document.location&&(g.width(C).height(9999),F=H.contents().find("body"),q&&F.css("overflow-x","hidden"),A=F.outerHeight(!0))}catch(G){}}else if(h.autoWidth|| 29 | h.autoHeight)g.addClass("fancybox-tmp"),h.autoWidth||g.width(C),h.autoHeight||g.height(A),h.autoWidth&&(C=g.width()),h.autoHeight&&(A=g.height()),g.removeClass("fancybox-tmp");c=l(C);j=l(A);D=C/A;m=l(E(m)?l(m,"w")-z:m);n=l(E(n)?l(n,"w")-z:n);u=l(E(u)?l(u,"h")-t:u);p=l(E(p)?l(p,"h")-t:p);F=n;B=p;h.fitToView&&(n=Math.min(a.w-z,n),p=Math.min(a.h-t,p));z=a.w-y;r=a.h-r;h.aspectRatio?(c>n&&(c=n,j=l(c/D)),j>p&&(j=p,c=l(j*D)),cz||y>r)&&(c>m&&j>u)&&!(19n&&(c=n,j=l(c/D)),g.width(c).height(j),e.width(c+x),a=e.width(),y=e.height();else c=Math.max(m,Math.min(c,c-(a-z))),j=Math.max(u,Math.min(j,j-(y-r)));q&&("auto"===s&&jz||y>r)&&c>m&&j>u;c=h.aspectRatio?cu&&j
').appendTo(b.coming?b.coming.parent:a.parent);this.fixed=!1;a.fixed&&b.defaults.fixed&&(this.overlay.addClass("fancybox-overlay-fixed"),this.fixed=!0)},open:function(a){var d=this;a=f.extend({},this.defaults,a);this.overlay?this.overlay.unbind(".overlay").width("auto").height("auto"):this.create(a);this.fixed||(n.bind("resize.overlay",f.proxy(this.update,this)),this.update());a.closeClick&&this.overlay.bind("click.overlay",function(a){if(f(a.target).hasClass("fancybox-overlay"))return b.isActive? 40 | b.close():d.close(),!1});this.overlay.css(a.css).show()},close:function(){var a,b;n.unbind("resize.overlay");this.el.hasClass("fancybox-lock")&&(f(".fancybox-margin").removeClass("fancybox-margin"),a=n.scrollTop(),b=n.scrollLeft(),this.el.removeClass("fancybox-lock"),n.scrollTop(a).scrollLeft(b));f(".fancybox-overlay").remove().hide();f.extend(this,{overlay:null,fixed:!1})},update:function(){var a="100%",b;this.overlay.width(a).height("100%");I?(b=Math.max(G.documentElement.offsetWidth,G.body.offsetWidth), 41 | p.width()>b&&(a=p.width())):p.width()>n.width()&&(a=p.width());this.overlay.width(a).height(p.height())},onReady:function(a,b){var e=this.overlay;f(".fancybox-overlay").stop(!0,!0);e||this.create(a);a.locked&&(this.fixed&&b.fixed)&&(e||(this.margin=p.height()>n.height()?f("html").css("margin-right").replace("px",""):!1),b.locked=this.overlay.append(b.wrap),b.fixed=!1);!0===a.showEarly&&this.beforeShow.apply(this,arguments)},beforeShow:function(a,b){var e,c;b.locked&&(!1!==this.margin&&(f("*").filter(function(){return"fixed"=== 42 | f(this).css("position")&&!f(this).hasClass("fancybox-overlay")&&!f(this).hasClass("fancybox-wrap")}).addClass("fancybox-margin"),this.el.addClass("fancybox-margin")),e=n.scrollTop(),c=n.scrollLeft(),this.el.addClass("fancybox-lock"),n.scrollTop(e).scrollLeft(c));this.open(a)},onUpdate:function(){this.fixed||this.update()},afterClose:function(a){this.overlay&&!b.coming&&this.overlay.fadeOut(a.speedOut,f.proxy(this.close,this))}};b.helpers.title={defaults:{type:"float",position:"bottom"},beforeShow:function(a){var d= 43 | b.current,e=d.title,c=a.type;f.isFunction(e)&&(e=e.call(d.element,d));if(q(e)&&""!==f.trim(e)){d=f('
'+e+"
");switch(c){case "inside":c=b.skin;break;case "outside":c=b.wrap;break;case "over":c=b.inner;break;default:c=b.skin,d.appendTo("body"),I&&d.width(d.width()),d.wrapInner(''),b.current.margin[2]+=Math.abs(l(d.css("margin-bottom")))}d["top"===a.position?"prependTo":"appendTo"](c)}}};f.fn.fancybox=function(a){var d, 44 | e=f(this),c=this.selector||"",k=function(g){var h=f(this).blur(),j=d,k,l;!g.ctrlKey&&(!g.altKey&&!g.shiftKey&&!g.metaKey)&&!h.is(".fancybox-wrap")&&(k=a.groupAttr||"data-fancybox-group",l=h.attr(k),l||(k="rel",l=h.get(0)[k]),l&&(""!==l&&"nofollow"!==l)&&(h=c.length?f(c):e,h=h.filter("["+k+'="'+l+'"]'),j=h.index(this)),a.index=j,!1!==b.open(h,a)&&g.preventDefault())};a=a||{};d=a.index||0;!c||!1===a.live?e.unbind("click.fb-start").bind("click.fb-start",k):p.undelegate(c,"click.fb-start").delegate(c+ 45 | ":not('.fancybox-item, .fancybox-nav')","click.fb-start",k);this.filter("[data-fancybox-start=1]").trigger("click");return this};p.ready(function(){var a,d;f.scrollbarWidth===v&&(f.scrollbarWidth=function(){var a=f('
').appendTo("body"),b=a.children(),b=b.innerWidth()-b.height(99).innerWidth();a.remove();return b});if(f.support.fixedPosition===v){a=f.support;d=f('
').appendTo("body");var e=20=== 46 | d[0].offsetTop||15===d[0].offsetTop;d.remove();a.fixedPosition=e}f.extend(b.defaults,{scrollbarWidth:f.scrollbarWidth(),fixed:f.support.fixedPosition,parent:f("body")});a=f(r).width();J.addClass("fancybox-lock-test");d=f(r).width();J.removeClass("fancybox-lock-test");f("").appendTo("head")})})(window,document,jQuery); -------------------------------------------------------------------------------- /resources/views/checkout.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | Checkout 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

Checkout

14 |
15 | 16 |
17 | Checkout 18 |

19 | 20 | 21 |

22 |

23 | 24 | 25 | / 26 | 27 |

28 |

29 | 30 | 31 |

32 | 33 |

34 | 35 | 36 |

37 | 38 | 39 | 40 |
41 |
42 | 43 | 44 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /resources/views/snap_checkout.blade.php: -------------------------------------------------------------------------------- 1 | 2 | Checkout 3 | 4 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 |
15 | 16 | 17 | 18 | 19 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /resources/views/transaction.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | Checkout 4 | 5 | 6 | 7 |

Transaction action

8 |
9 | 10 |

11 | 12 | 13 |

14 |

15 |
16 | Get Status
17 | Approve
18 | Cancel
19 | Expire
20 |

21 | 22 |
23 | 24 | 25 | --------------------------------------------------------------------------------