├── README.md ├── application ├── controllers │ ├── notification.php │ ├── snap.php │ ├── transaction.php │ ├── vtdirect.php │ └── vtweb.php ├── libraries │ ├── Midtrans.php │ ├── Veritrans.php │ ├── index.html │ └── veritrans │ │ └── cacert.pem └── views │ ├── checkout_snap.php │ ├── checkout_vtweb.php │ ├── checkout_with_3ds.php │ └── transaction.php └── asset ├── css ├── blank.gif ├── fancybox_loading.gif ├── fancybox_loading@2x.gif ├── fancybox_overlay.png ├── fancybox_sprite.png ├── fancybox_sprite@2x.png └── jquery.fancybox.css └── js └── jquery.fancybox.pack.js /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 | Midtrans Codeigniter library 16 | ======================================================= 17 | MIdtrans :heart: CI! 18 | 19 | Veritrans now is Midtrans 20 | 21 | This is the all new Codeigniter client library for Veritrans 2.0. Visit [https://www.midtrans.com](https://www.veritrans.co.id) for more information about the product and see documentation at [http://docs.midtrans.com](http://docs.veritrans.co.id) for more technical details. 22 | 23 | ### What's new? 24 | SNAP! for technical info Visit [https://snap-docs.midtrans.com](https://snap-docs.midtrans.com) 25 | 26 | ### Requirements 27 | The following plugin is tested under following environment: 28 | * PHP v5.4.x or greater 29 | * Codeigniter v2.2.x 30 | 31 | ## Installation 32 | * Download the library and extract the .zip 33 | * Merge all the files to your codeigniter directory 34 | 35 | ## Using Veritrans Library 36 | 37 | ### load library 38 | ```php 39 | //set production to true for production environment 40 | $params = array('server_key' => '', 'production' => false); 41 | $this->load->library('veritrans'); 42 | $this->veritrans->config($params); 43 | ``` 44 | 45 | ### SNAP 46 | 47 | For more info please open dan read [snap docs](https://snap-docs.midtrans.com/) 48 | 49 | See the snap example [here](https://github.com/harrypujianto/Veritrans-Codeigniter/blob/master/application/controllers/snap.php) 50 | 51 | #### frontend requirement 52 | ``` 53 | Checkout 54 | 55 | 58 | 59 | 60 | 61 | ``` 62 | Change `src="https://app.sandbox.midtrans.com/snap/snap.js"` into `src="https://app.midtrans.com/snap/snap.js"` 63 | 64 | #### initialize 65 | ``` 66 | $params = array('server_key' => '', 'production' => false); 67 | $this->load->library('midtrans'); 68 | $this->midtrans->config($params); 69 | ``` 70 | set ``production =>true`` for production environment. 71 | 72 | 73 | #### Get Snap Token 74 | 75 | When button is clicked, call an ajax to the server. Located on 76 | [here](https://github.com/harrypujianto/Veritrans-Codeigniter/blob/master/application/views/checkout_snap.php#L12-L26) 77 | ``` 78 |
79 | 80 | 81 |
82 | 83 | 84 | 198 | 199 | 200 | 201 | ``` 202 | Change `src="https://app.sandbox.midtrans.com/snap/snap.js"` into `src="https://app.midtrans.com/snap/snap.js"` 203 | 204 | ### VT-Web 205 | 206 | You can see some VT-Web examples [here](https://github.com/harrypujianto/Veritrans-Codeigniter/blob/master/application/controllers/vtweb.php). 207 | 208 | #### Get Redirection URL of a Charge 209 | ```php 210 | //you don't have to use the function name 'vtweb_charge', it's just an example 211 | public function vtweb_charge() 212 | { 213 | $params = array( 214 | 'transaction_details' => array( 215 | 'order_id' => rand(), 216 | 'gross_amount' => 10000, 217 | ), 218 | 'vtweb' => array() 219 | ); 220 | 221 | try { 222 | // Redirect to Veritrans VTWeb page 223 | header('Location: ' . $this->veritrans->vtweb_charge($params)); 224 | } 225 | catch (Exception $e) { 226 | echo $e->getMessage(); 227 | } 228 | } 229 | ``` 230 | 231 | #### Handle Notification Callback 232 | You can see notification handler examples [here](https://github.com/harrypujianto/Veritrans-Codeigniter/blob/master/application/controllers/vtweb.php). 233 | ```php 234 | //you don't have to use the function name 'notification', it's just an example 235 | public function notificarion() 236 | { 237 | $json_result = file_get_contents('php://input'); 238 | $result = json_decode($json_result); 239 | if($result){ 240 | $notif = $this->veritrans->status($result->order_id); 241 | } 242 | 243 | $transaction = $notif->transaction_status; 244 | $type = $notif->payment_type; 245 | $order_id = $notif->order_id; 246 | $fraud = $notif->fraud_status; 247 | if ($transaction == 'capture') { 248 | // For credit card transaction, we need to check whether transaction is challenge by FDS or not 249 | if ($type == 'credit_card'){ 250 | if($fraud == 'challenge'){ 251 | // TODO set payment status in merchant's database to 'Challenge by FDS' 252 | // TODO merchant should decide whether this transaction is authorized or not in MAP 253 | echo "Transaction order_id: " . $order_id ." is challenged by FDS"; 254 | } 255 | else { 256 | // TODO set payment status in merchant's database to 'Success' 257 | echo "Transaction order_id: " . $order_id ." successfully captured using " . $type; 258 | } 259 | } 260 | } 261 | else if ($transaction == 'settlement' && $type != 'credit_card'){ 262 | // TODO set payment status in merchant's database to 'Settlement' 263 | echo "Transaction order_id: " . $order_id ." successfully transfered using " . $type; 264 | } 265 | else if($transaction == 'pending'){ 266 | // TODO set payment status in merchant's database to 'Pending' 267 | echo "Waiting customer to finish transaction order_id: " . $order_id . " using " . $type; 268 | } 269 | else if ($transaction == 'deny') { 270 | // TODO set payment status in merchant's database to 'Denied' 271 | echo "Payment using " . $type . " for transaction order_id: " . $order_id . " is denied."; 272 | } 273 | ``` 274 | 275 | ### VT-Direct 276 | You can see VT-Direct form [here](https://github.com/harrypujianto/Veritrans-Codeigniter/blob/master/application/views/checkout_with_3ds.php). 277 | 278 | you can see VT-Direct process [here](https://github.com/harrypujianto/Veritrans-Codeigniter/blob/master/application/controllers/vtdirect.php). 279 | 280 | #### Checkout Page 281 | 282 | ```html 283 | 284 | 285 | Checkout 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 |

Checkout

295 |
296 |
297 | Checkout 298 |

299 | 300 | 301 |

302 |

303 | 304 | 305 | / 306 | 307 |

308 |

309 | 310 | 311 |

312 | 313 |

314 | 315 | 316 |

317 | 318 | 319 | 320 |
321 |
322 | 323 | 324 | 391 | 392 | 393 | ``` 394 | 395 | #### Checkout Process 396 | 397 | ##### 1. Create Transaction Details 398 | 399 | ```php 400 | $transaction_details = array( 401 | 'order_id' => time(), 402 | 'gross_amount' => 10000 403 | ); 404 | ``` 405 | 406 | ##### 2. Create Item Details, Billing Address, Shipping Address, and Customer Details (Optional) 407 | 408 | ```php 409 | // Populate items 410 | $items = array( 411 | array( 412 | 'id' => 'item1', 413 | 'price' => 5000, 414 | 'quantity' => 1, 415 | 'name' => 'Adidas f50' 416 | ), 417 | array( 418 | 'id' => 'item2', 419 | 'price' => 2500, 420 | 'quantity' => 2, 421 | 'name' => 'Nike N90' 422 | )); 423 | 424 | // Populate customer's billing address 425 | $billing_address = array( 426 | 'first_name' => "Andri", 427 | 'last_name' => "Setiawan", 428 | 'address' => "Karet Belakang 15A, Setiabudi.", 429 | 'city' => "Jakarta", 430 | 'postal_code' => "51161", 431 | 'phone' => "081322311801", 432 | 'country_code' => 'IDN' 433 | ); 434 | 435 | // Populate customer's shipping address 436 | $shipping_address = array( 437 | 'first_name' => "John", 438 | 'last_name' => "Watson", 439 | 'address' => "Bakerstreet 221B.", 440 | 'city' => "Jakarta", 441 | 'postal_code' => "51162", 442 | 'phone' => "081322311801", 443 | 'country_code' => 'IDN' 444 | ); 445 | 446 | // Populate customer's info 447 | $customer_details = array( 448 | 'first_name' => "Andri", 449 | 'last_name' => "Setiawan", 450 | 'email' => "andri@email.co", 451 | 'phone' => "081322311801", 452 | 'billing_address' => $billing_address, 453 | 'shipping_address' => $shipping_address 454 | ); 455 | ``` 456 | 457 | ##### 3. Get Token ID from Checkout Page 458 | 459 | ```php 460 | // Token ID from checkout page 461 | $token_id = $_POST['token_id']; 462 | ``` 463 | ##### 4. Create Transaction Data 464 | 465 | ```php 466 | // Transaction data to be sent 467 | $transaction_data = array( 468 | 'payment_type' => 'credit_card', 469 | 'credit_card' => array( 470 | 'token_id' => $token_id, 471 | 'bank' => 'bni', 472 | 'save_token_id' => isset($_POST['save_cc']) 473 | ), 474 | 'transaction_details' => $transaction_details, 475 | 'item_details' => $items, 476 | 'customer_details' => $customer_details 477 | ); 478 | ``` 479 | 480 | ##### 5. Charge 481 | 482 | ```php 483 | $response= $this->veritrans->vtdirect_charge($transaction_data); 484 | ``` 485 | 486 | ##### 6. Handle Transaction Status 487 | 488 | ```php 489 | // Success 490 | if($response->transaction_status == 'capture') { 491 | echo "

Transaksi berhasil.

"; 492 | echo "

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

"; 494 | 495 | echo "

Detail transaksi:

"; 496 | echo "
";
497 |   var_dump($response);
498 |   echo "
"; 499 | } 500 | // Deny 501 | else if($response->transaction_status == 'deny') { 502 | echo "

Transaksi ditolak.

"; 503 | echo "

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

"; 505 | 506 | echo "

Detail transaksi:

"; 507 | echo "
";
508 |   var_dump($response);
509 |   echo "
"; 510 | } 511 | // Challenge 512 | else if($response->transaction_status == 'challenge') { 513 | echo "

Transaksi challenge.

"; 514 | echo "

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

"; 516 | 517 | echo "

Detail transaksi:

"; 518 | echo "
";
519 |   var_dump($response);
520 |   echo "
"; 521 | } 522 | // Error 523 | else { 524 | echo "

Terjadi kesalahan pada data transaksi yang dikirim.

"; 525 | echo "

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

"; 527 | 528 | echo "
";
529 |   var_dump($response);
530 |   echo "
"; 531 | } 532 | ``` 533 | 534 | #### Process Transaction 535 | 536 | ##### Get a Transaction Status 537 | 538 | ```php 539 | $status = $this->veritrans->status($order_id); 540 | var_dump($status); 541 | ``` 542 | ##### Approve a Transaction 543 | 544 | ```php 545 | $approve = $this->veritrans->approve($order_id); 546 | var_dump($approve); 547 | ``` 548 | 549 | ##### Cancel a Transaction 550 | 551 | ```php 552 | $cancel = $this->veritrans->cancel($order_id); 553 | var_dump($cancel); 554 | ``` 555 | -------------------------------------------------------------------------------- /application/controllers/notification.php: -------------------------------------------------------------------------------- 1 | 18 | * @see http://codeigniter.com/user_guide/general/urls.html 19 | */ 20 | 21 | 22 | public function __construct() 23 | { 24 | parent::__construct(); 25 | $params = array('server_key' => 'your_server_key', 'production' => false); 26 | $this->load->library('veritrans'); 27 | $this->veritrans->config($params); 28 | $this->load->helper('url'); 29 | 30 | } 31 | 32 | public function index() 33 | { 34 | echo 'test notification handler'; 35 | $json_result = file_get_contents('php://input'); 36 | $result = json_decode($json_result); 37 | 38 | if($result){ 39 | $notif = $this->veritrans->status($result->order_id); 40 | } 41 | 42 | error_log(print_r($result,TRUE)); 43 | 44 | //notification handler sample 45 | 46 | /* 47 | $transaction = $notif->transaction_status; 48 | $type = $notif->payment_type; 49 | $order_id = $notif->order_id; 50 | $fraud = $notif->fraud_status; 51 | 52 | if ($transaction == 'capture') { 53 | // For credit card transaction, we need to check whether transaction is challenge by FDS or not 54 | if ($type == 'credit_card'){ 55 | if($fraud == 'challenge'){ 56 | // TODO set payment status in merchant's database to 'Challenge by FDS' 57 | // TODO merchant should decide whether this transaction is authorized or not in MAP 58 | echo "Transaction order_id: " . $order_id ." is challenged by FDS"; 59 | } 60 | else { 61 | // TODO set payment status in merchant's database to 'Success' 62 | echo "Transaction order_id: " . $order_id ." successfully captured using " . $type; 63 | } 64 | } 65 | } 66 | else if ($transaction == 'settlement'){ 67 | // TODO set payment status in merchant's database to 'Settlement' 68 | echo "Transaction order_id: " . $order_id ." successfully transfered using " . $type; 69 | } 70 | else if($transaction == 'pending'){ 71 | // TODO set payment status in merchant's database to 'Pending' 72 | echo "Waiting customer to finish transaction order_id: " . $order_id . " using " . $type; 73 | } 74 | else if ($transaction == 'deny') { 75 | // TODO set payment status in merchant's database to 'Denied' 76 | echo "Payment using " . $type . " for transaction order_id: " . $order_id . " is denied."; 77 | }*/ 78 | 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /application/controllers/snap.php: -------------------------------------------------------------------------------- 1 | 18 | * @see http://codeigniter.com/user_guide/general/urls.html 19 | */ 20 | 21 | 22 | public function __construct() 23 | { 24 | parent::__construct(); 25 | $params = array('server_key' => 'your_server_key', 'production' => false); 26 | $this->load->library('midtrans'); 27 | $this->midtrans->config($params); 28 | $this->load->helper('url'); 29 | } 30 | 31 | public function index() 32 | { 33 | $this->load->view('checkout_snap'); 34 | } 35 | 36 | public function token() 37 | { 38 | 39 | // Required 40 | $transaction_details = array( 41 | 'order_id' => rand(), 42 | 'gross_amount' => 94000, // no decimal allowed for creditcard 43 | ); 44 | 45 | // Optional 46 | $item1_details = array( 47 | 'id' => 'a1', 48 | 'price' => 18000, 49 | 'quantity' => 3, 50 | 'name' => "Apple" 51 | ); 52 | 53 | // Optional 54 | $item2_details = array( 55 | 'id' => 'a2', 56 | 'price' => 20000, 57 | 'quantity' => 2, 58 | 'name' => "Orange" 59 | ); 60 | 61 | // Optional 62 | $item_details = array ($item1_details, $item2_details); 63 | 64 | // Optional 65 | $billing_address = array( 66 | 'first_name' => "Andri", 67 | 'last_name' => "Litani", 68 | 'address' => "Mangga 20", 69 | 'city' => "Jakarta", 70 | 'postal_code' => "16602", 71 | 'phone' => "081122334455", 72 | 'country_code' => 'IDN' 73 | ); 74 | 75 | // Optional 76 | $shipping_address = array( 77 | 'first_name' => "Obet", 78 | 'last_name' => "Supriadi", 79 | 'address' => "Manggis 90", 80 | 'city' => "Jakarta", 81 | 'postal_code' => "16601", 82 | 'phone' => "08113366345", 83 | 'country_code' => 'IDN' 84 | ); 85 | 86 | // Optional 87 | $customer_details = array( 88 | 'first_name' => "Andri", 89 | 'last_name' => "Litani", 90 | 'email' => "andri@litani.com", 91 | 'phone' => "081122334455", 92 | 'billing_address' => $billing_address, 93 | 'shipping_address' => $shipping_address 94 | ); 95 | 96 | // Data yang akan dikirim untuk request redirect_url. 97 | $credit_card['secure'] = true; 98 | //ser save_card true to enable oneclick or 2click 99 | //$credit_card['save_card'] = true; 100 | 101 | $time = time(); 102 | $custom_expiry = array( 103 | 'start_time' => date("Y-m-d H:i:s O",$time), 104 | 'unit' => 'minute', 105 | 'duration' => 2 106 | ); 107 | 108 | $transaction_data = array( 109 | 'transaction_details'=> $transaction_details, 110 | 'item_details' => $item_details, 111 | 'customer_details' => $customer_details, 112 | 'credit_card' => $credit_card, 113 | 'expiry' => $custom_expiry 114 | ); 115 | 116 | error_log(json_encode($transaction_data)); 117 | $snapToken = $this->midtrans->getSnapToken($transaction_data); 118 | error_log($snapToken); 119 | echo $snapToken; 120 | } 121 | 122 | public function finish() 123 | { 124 | $result = json_decode($this->input->post('result_data')); 125 | echo 'RESULT
';
126 |     	var_dump($result);
127 |     	echo '
' ; 128 | 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /application/controllers/transaction.php: -------------------------------------------------------------------------------- 1 | 18 | * @see http://codeigniter.com/user_guide/general/urls.html 19 | */ 20 | 21 | 22 | public function __construct() 23 | { 24 | parent::__construct(); 25 | $params = array('server_key' => 'your_server_key', 'production' => false); 26 | $this->load->library('veritrans'); 27 | $this->veritrans->config($params); 28 | $this->load->helper('url'); 29 | 30 | } 31 | 32 | public function index() 33 | { 34 | $this->load->view('transaction'); 35 | } 36 | 37 | public function process() 38 | { 39 | $order_id = $this->input->post('order_id'); 40 | $action = $this->input->post('action'); 41 | switch ($action) { 42 | case 'status': 43 | $this->status($order_id); 44 | break; 45 | case 'approve': 46 | $this->approve($order_id); 47 | break; 48 | case 'expire': 49 | $this->expire($order_id); 50 | break; 51 | case 'cancel': 52 | $this->cancel($order_id); 53 | break; 54 | } 55 | 56 | } 57 | 58 | public function status($order_id) 59 | { 60 | echo 'test get status
'; 61 | print_r ($this->veritrans->status($order_id) ); 62 | } 63 | 64 | public function cancel($order_id) 65 | { 66 | echo 'test cancel trx
'; 67 | echo $this->veritrans->cancel($order_id); 68 | } 69 | 70 | public function approve($order_id) 71 | { 72 | echo 'test get approve
'; 73 | print_r ($this->veritrans->approve($order_id) ); 74 | } 75 | 76 | public function expire($order_id) 77 | { 78 | echo 'test get expire
'; 79 | print_r ($this->veritrans->expire($order_id) ); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /application/controllers/vtdirect.php: -------------------------------------------------------------------------------- 1 | 18 | * @see http://codeigniter.com/user_guide/general/urls.html 19 | */ 20 | 21 | 22 | public function __construct() 23 | { 24 | parent::__construct(); 25 | $params = array('server_key' => 'your_server_key', 'production' => false); 26 | $this->load->library('veritrans'); 27 | $this->veritrans->config($params); 28 | $this->load->helper('url'); 29 | 30 | } 31 | 32 | public function index() 33 | { 34 | $this->load->view('checkout_with_3ds'); 35 | } 36 | 37 | public function vtdirect_cc_charge() 38 | { 39 | $token_id = $this->input->post('token_id'); 40 | $transaction_details = array( 41 | 'order_id' => uniqid(), 42 | 'gross_amount' => 10000 43 | ); 44 | 45 | // Populate items 46 | $items = [ 47 | array( 48 | 'id' => 'item1', 49 | 'price' => 5000, 50 | 'quantity' => 1, 51 | 'name' => 'Adidas f50' 52 | ), 53 | array( 54 | 'id' => 'item2', 55 | 'price' => 2500, 56 | 'quantity' => 2, 57 | 'name' => 'Nike N90' 58 | ) 59 | ]; 60 | 61 | // Populate customer's billing address 62 | $billing_address = array( 63 | 'first_name' => "Andri", 64 | 'last_name' => "Setiawan", 65 | 'address' => "Karet Belakang 15A, Setiabudi.", 66 | 'city' => "Jakarta", 67 | 'postal_code' => "51161", 68 | 'phone' => "081322311801", 69 | 'country_code' => 'IDN' 70 | ); 71 | 72 | // Populate customer's shipping address 73 | $shipping_address = array( 74 | 'first_name' => "John", 75 | 'last_name' => "Watson", 76 | 'address' => "Bakerstreet 221B.", 77 | 'city' => "Jakarta", 78 | 'postal_code' => "51162", 79 | 'phone' => "081322311801", 80 | 'country_code'=> 'IDN' 81 | ); 82 | 83 | // Populate customer's Info 84 | $customer_details = array( 85 | 'first_name' => "Andri", 86 | 'last_name' => "Setiawan", 87 | 'email' => "andrisetiawan@me.com", 88 | 'phone' => "081322311801", 89 | 'billing_address' => $billing_address, 90 | 'shipping_address'=> $shipping_address 91 | ); 92 | 93 | $transaction_data = array( 94 | 'payment_type' => 'credit_card', 95 | 'credit_card' => array( 96 | 'token_id' => $token_id, 97 | 'bank' => 'bni' 98 | ), 99 | 'transaction_details' => $transaction_details, 100 | ); 101 | 102 | $params = array('server_key' => 'VT-server-UJ4uPuXhwiNXwhpQx5-S76U1', 'production' => false); 103 | $this->load->library('veritrans',$params); 104 | $response = null; 105 | try 106 | { 107 | $response= $this->veritrans->vtdirect_charge($transaction_data); 108 | } 109 | catch (Exception $e) 110 | { 111 | echo $e->getMessage(); 112 | } 113 | 114 | //var_dump($response); 115 | if($response) 116 | { 117 | if($response->transaction_status == "capture") 118 | { 119 | //success 120 | echo "Transaksi berhasil.
"; 121 | echo "Status transaksi untuk order id ".$response->order_id.": ".$response->transaction_status; 122 | 123 | echo "

Detail transaksi:

"; 124 | echo "
";
125 |   				var_dump($response);
126 |   				echo "
"; 127 | } 128 | else if($response->transaction_status == "deny") 129 | { 130 | //deny 131 | echo "Transaksi ditolak.
"; 132 | echo "Status transaksi untuk order id ".$response->order_id.": ".$response->transaction_status; 133 | 134 | echo "

Detail transaksi:

"; 135 | echo "
";
136 |   				var_dump($response);
137 |   				echo "
"; 138 | } 139 | else if($response->transaction_status == "challenge") 140 | { 141 | //challenge 142 | echo "Transaksi challenge.
"; 143 | echo "Status transaksi untuk order id ".$response->order_id.": ".$response->transaction_status; 144 | 145 | echo "

Detail transaksi:

"; 146 | echo "
";
147 |   				var_dump($response);
148 |   				echo "
"; 149 | } 150 | else 151 | { 152 | //error 153 | echo "Terjadi kesalahan pada data transaksi yang dikirim.
"; 154 | echo "Status message: [".$response->status_code."] ".$response->status_message; 155 | 156 | echo "

Response:

"; 157 | echo "
";
158 |   				var_dump($response);
159 |   				echo "
"; 160 | } 161 | } 162 | 163 | } 164 | 165 | } 166 | -------------------------------------------------------------------------------- /application/controllers/vtweb.php: -------------------------------------------------------------------------------- 1 | 18 | * @see http://codeigniter.com/user_guide/general/urls.html 19 | */ 20 | 21 | 22 | public function __construct() 23 | { 24 | parent::__construct(); 25 | $params = array('server_key' => 'your_server_key', 'production' => false); 26 | $this->load->library('veritrans'); 27 | $this->veritrans->config($params); 28 | $this->load->helper('url'); 29 | 30 | } 31 | 32 | public function index() 33 | { 34 | $this->load->view('checkout_vtweb'); 35 | } 36 | 37 | public function vtweb_checkout() 38 | { 39 | $transaction_details = array( 40 | 'order_id' => uniqid(), 41 | 'gross_amount' => 200000 42 | ); 43 | 44 | // Populate items 45 | $items = [ 46 | array( 47 | 'id' => 'item1', 48 | 'price' => 100000, 49 | 'quantity' => 1, 50 | 'name' => 'Adidas f50' 51 | ), 52 | array( 53 | 'id' => 'item2', 54 | 'price' => 50000, 55 | 'quantity' => 2, 56 | 'name' => 'Nike N90' 57 | ) 58 | ]; 59 | 60 | // Populate customer's billing address 61 | $billing_address = array( 62 | 'first_name' => "Andri", 63 | 'last_name' => "Setiawan", 64 | 'address' => "Karet Belakang 15A, Setiabudi.", 65 | 'city' => "Jakarta", 66 | 'postal_code' => "51161", 67 | 'phone' => "081322311801", 68 | 'country_code' => 'IDN' 69 | ); 70 | 71 | // Populate customer's shipping address 72 | $shipping_address = array( 73 | 'first_name' => "John", 74 | 'last_name' => "Watson", 75 | 'address' => "Bakerstreet 221B.", 76 | 'city' => "Jakarta", 77 | 'postal_code' => "51162", 78 | 'phone' => "081322311801", 79 | 'country_code'=> 'IDN' 80 | ); 81 | 82 | // Populate customer's Info 83 | $customer_details = array( 84 | 'first_name' => "Andri", 85 | 'last_name' => "Setiawan", 86 | 'email' => "andrisetiawan@me.com", 87 | 'phone' => "081322311801", 88 | 'billing_address' => $billing_address, 89 | 'shipping_address'=> $shipping_address 90 | ); 91 | 92 | // Data yang akan dikirim untuk request redirect_url. 93 | // Uncomment 'credit_card_3d_secure' => true jika transaksi ingin diproses dengan 3DSecure. 94 | $transaction_data = array( 95 | 'payment_type' => 'vtweb', 96 | 'vtweb' => array( 97 | //'enabled_payments' => ['credit_card'], 98 | 'credit_card_3d_secure' => true 99 | ), 100 | 'transaction_details'=> $transaction_details, 101 | 'item_details' => $items, 102 | 'customer_details' => $customer_details 103 | ); 104 | 105 | try 106 | { 107 | $vtweb_url = $this->veritrans->vtweb_charge($transaction_data); 108 | header('Location: ' . $vtweb_url); 109 | } 110 | catch (Exception $e) 111 | { 112 | echo $e->getMessage(); 113 | } 114 | 115 | } 116 | 117 | public function notification() 118 | { 119 | echo 'test notification handler'; 120 | $json_result = file_get_contents('php://input'); 121 | $result = json_decode($json_result); 122 | 123 | if($result){ 124 | $notif = $this->veritrans->status($result->order_id); 125 | } 126 | 127 | error_log(print_r($result,TRUE)); 128 | 129 | //notification handler sample 130 | 131 | $transaction = $notif->transaction_status; 132 | $type = $notif->payment_type; 133 | $order_id = $notif->order_id; 134 | $fraud = $notif->fraud_status; 135 | 136 | if ($transaction == 'capture') { 137 | // For credit card transaction, we need to check whether transaction is challenge by FDS or not 138 | if ($type == 'credit_card'){ 139 | if($fraud == 'challenge'){ 140 | // TODO set payment status in merchant's database to 'Challenge by FDS' 141 | // TODO merchant should decide whether this transaction is authorized or not in MAP 142 | echo "Transaction order_id: " . $order_id ." is challenged by FDS"; 143 | } 144 | else { 145 | // TODO set payment status in merchant's database to 'Success' 146 | echo "Transaction order_id: " . $order_id ." successfully captured using " . $type; 147 | } 148 | } 149 | } 150 | else if ($transaction == 'settlement'){ 151 | // TODO set payment status in merchant's database to 'Settlement' 152 | echo "Transaction order_id: " . $order_id ." successfully transfered using " . $type; 153 | } 154 | else if($transaction == 'pending'){ 155 | // TODO set payment status in merchant's database to 'Pending' 156 | echo "Waiting customer to finish transaction order_id: " . $order_id . " using " . $type; 157 | } 158 | else if ($transaction == 'deny') { 159 | // TODO set payment status in merchant's database to 'Denied' 160 | echo "Payment using " . $type . " for transaction order_id: " . $order_id . " is denied."; 161 | } 162 | 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /application/libraries/Midtrans.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__) . "/veritrans/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 && !in_array($result_array->status_code, array(200, 201, 202, 407)) ) { 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 | /** 157 | * Retrieve transaction status 158 | * @param string $id Order ID or transaction ID 159 | * @return mixed[] 160 | */ 161 | public static function status($id) 162 | { 163 | return Midtrans::get( 164 | Midtrans::getBaseUrl() . '/' . $id . '/status', 165 | Midtrans::$serverKey, 166 | false); 167 | } 168 | 169 | /** 170 | * Appove challenge transaction 171 | * @param string $id Order ID or transaction ID 172 | * @return string 173 | */ 174 | public static function approve($id) 175 | { 176 | return Midtrans::post( 177 | Midtrans::getBaseUrl() . '/' . $id . '/approve', 178 | Midtrans::$serverKey, 179 | false)->status_code; 180 | } 181 | 182 | /** 183 | * Cancel transaction before it's setteled 184 | * @param string $id Order ID or transaction ID 185 | * @return string 186 | */ 187 | public static function cancel($id) 188 | { 189 | return Midtrans::post( 190 | Midtrans::getBaseUrl() . '/' . $id . '/cancel', 191 | Midtrans::$serverKey, 192 | false)->status_code; 193 | } 194 | 195 | /** 196 | * Expire transaction before it's setteled 197 | * @param string $id Order ID or transaction ID 198 | * @return mixed[] 199 | */ 200 | public static function expire($id) 201 | { 202 | return Midtrans::post( 203 | Midtrans::getBaseUrl() . '/' . $id . '/expire', 204 | Midtrans::$serverKey, 205 | false); 206 | } 207 | 208 | } 209 | -------------------------------------------------------------------------------- /application/libraries/Veritrans.php: -------------------------------------------------------------------------------- 1 | $url, 78 | CURLOPT_HTTPHEADER => array( 79 | 'Content-Type: application/json', 80 | 'Accept: application/json', 81 | 'Authorization: Basic ' . base64_encode($server_key . ':') 82 | ), 83 | CURLOPT_RETURNTRANSFER => 1, 84 | // CURLOPT_CAINFO => dirname(__FILE__) . "/veritrans/cacert.pem" 85 | ); 86 | 87 | // merging with Veritrans_Config::$curlOptions 88 | if (count(Veritrans::$curlOptions)) { 89 | // We need to combine headers manually, because it's array and it will no be merged 90 | if (Veritrans::$curlOptions[CURLOPT_HTTPHEADER]) { 91 | $mergedHeders = array_merge($curl_options[CURLOPT_HTTPHEADER], Veritrans::$curlOptions[CURLOPT_HTTPHEADER]); 92 | $headerOptions = array( CURLOPT_HTTPHEADER => $mergedHeders ); 93 | } else { 94 | $mergedHeders = array(); 95 | } 96 | 97 | $curl_options = array_replace_recursive($curl_options, Veritrans::$curlOptions, $headerOptions); 98 | } 99 | 100 | if ($post) { 101 | $curl_options[CURLOPT_POST] = 1; 102 | 103 | if ($data_hash) { 104 | $body = json_encode($data_hash); 105 | $curl_options[CURLOPT_POSTFIELDS] = $body; 106 | } else { 107 | $curl_options[CURLOPT_POSTFIELDS] = ''; 108 | } 109 | } 110 | 111 | curl_setopt_array($ch, $curl_options); 112 | 113 | $result = curl_exec($ch); 114 | // curl_close($ch); 115 | 116 | if ($result === FALSE) { 117 | throw new Exception('CURL Error: ' . curl_error($ch), curl_errno($ch)); 118 | } 119 | else { 120 | $result_array = json_decode($result); 121 | if (!in_array($result_array->status_code, array(200, 201, 202, 407))) { 122 | $message = 'Veritrans Error (' . $result_array->status_code . '): ' 123 | . $result_array->status_message; 124 | throw new Exception($message, $result_array->status_code); 125 | } 126 | else { 127 | return $result_array; 128 | } 129 | } 130 | } 131 | 132 | public static function vtweb_charge($payloads) 133 | { 134 | 135 | $result = Veritrans::post( 136 | Veritrans::getBaseUrl() . '/charge', 137 | Veritrans::$serverKey, 138 | $payloads); 139 | 140 | return $result->redirect_url; 141 | 142 | 143 | //$url = Veritrans::getBaseUrl(); 144 | //return Veritrans::$serverKey.Veritrans::getBaseUrl() . '/charge' ; 145 | } 146 | 147 | public static function vtdirect_charge($payloads) 148 | { 149 | 150 | $result = Veritrans::post( 151 | Veritrans::getBaseUrl() . '/charge', 152 | Veritrans::$serverKey, 153 | $payloads); 154 | 155 | return $result; 156 | 157 | 158 | //$url = Veritrans::getBaseUrl(); 159 | //return Veritrans::$serverKey.Veritrans::getBaseUrl() . '/charge' ; 160 | } 161 | 162 | /** 163 | * Retrieve transaction status 164 | * @param string $id Order ID or transaction ID 165 | * @return mixed[] 166 | */ 167 | public static function status($id) 168 | { 169 | return Veritrans::get( 170 | Veritrans::getBaseUrl() . '/' . $id . '/status', 171 | Veritrans::$serverKey, 172 | false); 173 | } 174 | 175 | /** 176 | * Appove challenge transaction 177 | * @param string $id Order ID or transaction ID 178 | * @return string 179 | */ 180 | public static function approve($id) 181 | { 182 | return Veritrans::post( 183 | Veritrans::getBaseUrl() . '/' . $id . '/approve', 184 | Veritrans::$serverKey, 185 | false)->status_code; 186 | } 187 | 188 | /** 189 | * Cancel transaction before it's setteled 190 | * @param string $id Order ID or transaction ID 191 | * @return string 192 | */ 193 | public static function cancel($id) 194 | { 195 | return Veritrans::post( 196 | Veritrans::getBaseUrl() . '/' . $id . '/cancel', 197 | Veritrans::$serverKey, 198 | false)->status_code; 199 | } 200 | 201 | /** 202 | * Expire transaction before it's setteled 203 | * @param string $id Order ID or transaction ID 204 | * @return mixed[] 205 | */ 206 | public static function expire($id) 207 | { 208 | return Veritrans::post( 209 | Veritrans::getBaseUrl() . '/' . $id . '/expire', 210 | Veritrans::$serverKey, 211 | false); 212 | } 213 | 214 | } 215 | -------------------------------------------------------------------------------- /application/libraries/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 403 Forbidden 4 | 5 | 6 | 7 |

Directory access is forbidden.

8 | 9 | 10 | -------------------------------------------------------------------------------- /application/views/checkout_snap.php: -------------------------------------------------------------------------------- 1 | 2 | Checkout 3 | 4 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 |
16 | 17 | 18 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /application/views/checkout_vtweb.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | Checkout 4 | 5 | 6 | 7 |

Checkout

8 |
9 | 10 | 11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /application/views/checkout_with_3ds.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | Checkout 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |

Checkout

13 |
14 |
15 | Checkout 16 |

17 | 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 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /application/views/transaction.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | Checkout 4 | 5 | 6 | 7 |

Transaction action

8 |
9 |

10 | 11 | 12 |

13 |

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

20 | 21 |
22 | 23 | 24 | -------------------------------------------------------------------------------- /asset/css/blank.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Midtrans/Midtrans-Codeigniter/53d4f5bff7d5980070cbca145711c348b0abf43a/asset/css/blank.gif -------------------------------------------------------------------------------- /asset/css/fancybox_loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Midtrans/Midtrans-Codeigniter/53d4f5bff7d5980070cbca145711c348b0abf43a/asset/css/fancybox_loading.gif -------------------------------------------------------------------------------- /asset/css/fancybox_loading@2x.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Midtrans/Midtrans-Codeigniter/53d4f5bff7d5980070cbca145711c348b0abf43a/asset/css/fancybox_loading@2x.gif -------------------------------------------------------------------------------- /asset/css/fancybox_overlay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Midtrans/Midtrans-Codeigniter/53d4f5bff7d5980070cbca145711c348b0abf43a/asset/css/fancybox_overlay.png -------------------------------------------------------------------------------- /asset/css/fancybox_sprite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Midtrans/Midtrans-Codeigniter/53d4f5bff7d5980070cbca145711c348b0abf43a/asset/css/fancybox_sprite.png -------------------------------------------------------------------------------- /asset/css/fancybox_sprite@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Midtrans/Midtrans-Codeigniter/53d4f5bff7d5980070cbca145711c348b0abf43a/asset/css/fancybox_sprite@2x.png -------------------------------------------------------------------------------- /asset/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 | } -------------------------------------------------------------------------------- /asset/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); --------------------------------------------------------------------------------