= CakePHP Setup and Configuration = == Configure for Use == * Edit ''[cakephp]/app/Config/core.php'' and modify the following: // A random string used in security hashing methods. Configure::write('Security.salt', 'DYhG93b0qyJfIxfs2guVoUubWwvniR2G0FgaC9mi'); // A random numeric string (digits only) used to encrypt/decrypt strings. Configure::write('Security.cipherSeed', '76859309657453542496749683645'); * For system-wide user-defined variables, edit ''[cakephp]/app/Config/core.php'' and add the following: /** //####################################################### //# User-defined system strings. //####################################################### Configure::write('Company.Name', 'Acme Inc.'); // Company Name Configure::write('Company.Email', 'info@acme.com'); // Company Email Read a config variable using: Configure::read('Company.Name') == Database Configuration == Edit file ''[cakephp]/app/Config/database.php'': public $default = array( 'datasource' => 'Database/Mysql', 'persistent' => false, 'host' => 'localhost', 'port' => '', 'login' => 'acmeusr', 'password' => 'c4k3-rUl3Z', 'database' => 'acme_cakephp_db', 'schema' => '', 'prefix' => '', 'encoding' => 'utf8' ); == Email Configuration == Edit file ''[cakephp]/app/Config/email.php'': class EmailConfig { public $default = array( 'transport' => 'Mail', //'from' => Configure::read('Company.Email'), 'from' => 'info@acme.com', 'charset' => 'utf-8', 'headerCharset' => 'utf-8', ); public $smtp = array( 'transport' => 'Smtp', //'from' => array('site@localhost' => 'My Site'), //'from' => array(Configure::read('Company.Email') => Configure::read('Company.Name')), 'from' => array('info@acme.com' => 'Acme Inc'), 'host' => 'localhost', 'port' => 25, 'timeout' => 30, //'username' => 'user', //'password' => 'secret', 'username' => null, 'password' => null, 'client' => null, 'log' => false, 'charset' => 'utf-8', 'headerCharset' => 'utf-8', ); public $fast = array( //'from' => 'you@localhost', //'from' => Configure::read('Company.Email'), 'from' => 'info@acme.com', 'sender' => null, 'to' => null, 'cc' => null, 'bcc' => null, 'replyTo' => null, 'readReceipt' => null, 'returnPath' => null, 'messageId' => true, 'subject' => null, 'message' => null, 'headers' => null, 'viewRender' => null, 'template' => false, 'layout' => false, 'viewVars' => null, 'attachments' => null, 'emailFormat' => null, 'transport' => 'Smtp', 'host' => 'localhost', 'port' => 25, 'timeout' => 30, //'username' => 'user', //'password' => 'secret', 'username' => null, 'password' => null, 'client' => null, 'log' => true, 'charset' => 'utf-8', 'headerCharset' => 'utf-8', ); /* // To use this feature, you will need to have the SSL configured in your PHP install. public $gmail = array( 'host' => 'ssl://smtp.gmail.com', 'port' => 465, 'username' => 'my@gmail.com', 'password' => 'secret', 'transport' => 'Smtp' ); // or using TLS SMTP public $gmail = array( 'host' => 'smtp.gmail.com', 'port' => 465, 'username' => 'my@gmail.com', 'password' => 'secret', 'transport' => 'Smtp', 'tls' => true ); */ } == Setup AppController == Edit file ''[cakephp]/app/Controller/AppController.php'': App::uses('Controller', 'Controller'); App::uses('SessionComponent', 'Controller/Component'); App::uses('SessionHelper', 'Controller/Component'); App::uses('AuthHelper ', 'Controller/Component'); class AppController extends Controller { public $components = array( 'Session', 'Auth' => array( //'loginRedirect' => array('controller' => 'articles', 'action' => 'index'), // at login, go to Articles list 'loginRedirect' => array('controller' => 'pages', 'action' => 'display', 'home'), // at login, go to Home //'logoutRedirect' => array('controller' => 'users', 'action' => 'login'), 'logoutRedirect' => array('controller' => 'pages', 'action' => 'display', 'home'), // at logout, go to Home 'authError' => 'You must be logged in to view this page.', 'loginError' => 'Invalid Username or Password entered, please try again.', 'authorize' => array('Controller') ), 'DebugKit.Toolbar', // see https://github.com/cakephp/debug_kit for more details ); // only allow the login controllers only public function beforeFilter() { $this->Auth->allow('login'); } public function isAuthorized($user) { // Here is where we should verify the role and give access based on role //return true; // Admin can access every action if (isset($user['role']) && $user['role'] === 'admin') { return true; } // Default deny return false; } } == Setup UserController == Edit file ''[cakephp]/app/Config/routes.php'' to include custome routes: // ###--- Custom Routes ---### // Let us modify the core components of CakePHP to support the UserController login module. // First, we need to modify routes.php so that we can have a custom link for login, logout // and the dashboard. This step is not required but I do it so that the URLs look clean. Router::connect('/dashboard', array('controller' => 'users', 'action' => 'index')); Router::connect('/login', array('controller' => 'users', 'action' => 'login')); Router::connect('/logout', array('controller' => 'users', 'action' => 'logout')); // We also need to modify the home page so that it now points to the UserController login action. //Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home')); // default Router::connect('/', array('controller' => 'users', 'action' => 'login')); == Install Basic Components/Plugins == === DebugKit === * Download ''DebugKit'' from here: https://github.com/cakephp/debug_kit * Unpack to ''[cakephp]/app/Plugin'' directory. * Edit ''[cakephp]/app/Config/bootstrap.php'' and uncomment the following: CakePlugin::loadAll(); // Loads all plugins at once (optional) CakePlugin::load('DebugKit'); * Edit ''[cakephp]/app/Config/core.php'' and uncomment one of the following: //Configure::write('debug', 0); // for production mode Configure::write('debug', 1); // for development mode //Configure::write('debug', 2); // for development mode (with sql dump) * Include the toolbar component in your ''[cakephp]/app/Controller/AppController.php'': class AppController extends Controller { public $components = array('DebugKit.Toolbar', ...); ... } === Articles == * Articles Component: http://book.cakephp.org/2.0/en/getting-started.html#blog-tutorial === Authentication === * Authentication Component: http://book.cakephp.org/2.0/en/tutorials-and-examples/blog-auth-example/auth.html === AuthorizeNetComponent == * Include the following file ''[cakephp/app/Controller/Component/AuthorizeNetComponent.php]'': "First", "lname" => "Last", "company" => "Acme Inc.", "address" => "123 Fake St. Suite 0", "city" => "City", "state" => "ST", "zip" => "90210", "country" => "USA"); $shippinginfo = array("fname" => "First", "lname" => "Last", "company" => "Acme Inc.", "address" => "123 Fake St. Suite 0", "city" => "City", "state" => "ST", "zip" => "90210", "country" => "USA"); $response = $this->AuthorizeNet->chargeCard('########', '##############', '4111111111111111', '01', '2010', '123', true, 110, 5, 5, "Purchase of Goods", $billinginfo, "customeremail@example.com", "555-555-5555", $shippinginfo, 'INV123', false); $response:Array = $this->AuthorizeNet->chargeCard($loginid:String, $trankey:String, $ccnum:String, $ccexpmonth:String, $ccexpyear:String, $ccver:String, $live:Boolean, $amount:Number, $tax:Number, $shipping:Number, $desc:String, $billinginfo:Array, $email:String, $phone:String, $shippinginfo:Array, $invoicenum:String, $testmode:Boolean); } } ////////// USAGE NOTES \\\\\\\\\\\\ PARAMETERS $loginid : Your Authorize.net Login ID $trankey : Your Authorize.net Transaction Key $ccnum : The system removes any spaces in the string to meet Authorize.net requirements $ccexpmonth : 2 digit month string $ccexpyear : 2 or 4 digit year string $ccver : The 3 or 4 digit card verificaton code found on the back of Visa/Mastercard and the front of AmEx $live : Whether to process as a live or test transaction - true : Live Transcation - false : Test Transaction $amount : Total amount of the transaction. This must include both tax and shipping if applicable. $tax : Tax amount charged (if any) $shipping : Shipping cost (if any) $desc : Description of the transaction to be logged into Authorize.net system $billinginfo : Associative Array containing values for customer billing details $email : Customer email $phone : Customer phone $billinginfo : Associative Array containing values for customer shipping details $invoicenum : The merchant-assigned invoice number for the transaction $testmode : transaction is a test (true) or not (false). Use Visa test credit card number “4222222222222”, and to test the AVS response reason code (eg. number 27), submit the test transaction with the credit card number “4222222222222” and the amount matching the AVS code (eg “27.00.”) RESPONSE $response : Array (1 based) containing the Payment Gateway Reasons fields // Important Response Values $response[1] = Response Code (1 = Approved, 2 = Declined, 3 = Error, 4 = Held for Review) $response[2] = Response Subcode (Code used for Internal Transaction Details) $response[3] = Response Reason Code (Code detailing response code) $response[4] = Response Reason Text (Text detailing response code and response reason code) $response[5] = Authorization Code (Authorization or approval code - 6 characters) $response[6] = AVS Response (Address Verification Service response code - A, B, E, G, N, P, R, S, U, W, X, Y, Z) (A, P, W, X, Y, Z are default AVS confirmation settings - Use your Authorize.net Merchant Interface to change these settings) (B, E, G, N, R, S, U are default AVS rejection settings - Use your Authorize.net Merchant Interface to change these settings) $response[7] = Transaction ID (Gateway assigned id number for the transaction) $response[8] = Transaction Invoice Number (Merchant assigned invoice number for the transaction) $response[9] = Transaction Description (Merchant assigned description for the transaction) $response[10] = Transaction Amount (Merchant assigned amount for the transaction) $response[11] = Payment method (CC, ECHECK) $response[12] = Transaction type (AUTH_CAPTURE, AUTH_ONLY, CAPTURE_ONLY, CREDIT, PRIOR_AUTH_CAPTUREVOID) $response[13] = Customer ID (Merchant-assigned) $response[14] = First name associated with the customer’s billing address $response[15] = Last name associated with the customer’s billing address $response[16] = Company associated with the customer’s billing address $response[17] = Street for customer’s billing address $response[18] = City for customer’s billing address $response[19] = State for customer’s billing address $response[20] = ZIP Code for customer’s billing address $response[21] = Country for customer’s billing address $response[22] = Phone for customer’s billing address $response[23] = Fax for customer’s billing address $response[24] = Email $response[25] = First name for shipping address $response[26] = Last name for shipping address $response[27] = Company name for shipping address $response[28] = Street for shipping address $response[29] = City for shipping address $response[30] = State for shipping address $response[31] = ZIP Code for shipping address $response[32] = Country for shipping address $response[33] = Tax $response[34] = Duty $response[35] = Freight $response[36] = Tax Exempt $response[37] = Purchase Order Number $response[38] = MD5 Hash (Gateway generated MD5 has used to authenticate transaction response) $response[39] = Card Code Response (CCV Card Code Verification response code: M = Match, N = No Match, P = No Processed, S = Should have been present, U = Issuer unable to process request) $response[40] = Cardholder Authentication Verification Response $response[51] = Account Number (Last 4-digits Cr Card Number with XXXX prefix) $response[52] = Card Type (Visa, MasterCard, American Express, Discover) $response[53] = Split Tender ID $response[54] = Requested Amount $response[55] = Balance on card For more information about the Authorize.net AIM response consult their AIM Implementation Guide at http://developer.authorize.net/guides/AIM/ and go to Section Four : Fields in the Payment Gateway Response for more details. NOTES This component is meant to abstract payment processing on a website. As varying sites require different requirements for information, security, or card processing (like changing Address Verification requirement) the component does not try to provide any logic to determine if a transaction was successful. It is up to the user implementing this code to process the response array and provide response accordingly. */ // class variables go here public $arrLastResponse = array(); //--------------------------------------------------------------------------------------------- // description: // parameters : // return : //--------------------------------------------------------------------------------------------- // function startup(&$controller) // used in cakephp 1.x function startup(Controller $controller) { parent::startup($controller); // This method takes a reference to the controller which is loading it. // Perform controller initialization here. $this->arrLastResponse = array(); } //--------------------------------------------------------------------------------------------- // description: Charge credit card with the specified data. // parameters : $loginid, $trankey, $ccnum, $ccexpmonth, $ccexpyear, $ccver, $live, // $amount, $tax, $shipping, $desc, $billinginfo, $email, $phone, $shippinginfo, $invoicenum, $testmode // return : $responsearray //--------------------------------------------------------------------------------------------- function chargeCard($loginid, $trankey, $ccnum, $ccexpmonth, $ccexpyear, $ccver, $live, $amount, $tax, $shipping, $desc, $billinginfo, $email, $phone, $shippinginfo, $invoicenum, $testmode) { // setup variables $ccexp = $ccexpmonth . '/' . $ccexpyear; $DEBUGGING = 1; # Display additional information to track down problems $TESTING = 1; # Set the testing flag so that transactions are not live $ERROR_RETRIES = 2; # Number of transactions to post if soft errors occur $auth_net_login_id = $loginid; $auth_net_tran_key = $trankey; ### Uncomment the appropriate line for test or live merchant accounts //$auth_net_url = "https://certification.authorize.net/gateway/transact.dll"; // test account $auth_net_url = "https://secure.authorize.net/gateway/transact.dll"; // live account $authnet_values = array( "x_login" => $auth_net_login_id, "x_version" => "3.1", "x_delim_char" => "|", "x_delim_data" => "TRUE", "x_url" => "FALSE", "x_type" => "AUTH_CAPTURE", "x_method" => "CC", "x_tran_key" => $auth_net_tran_key, "x_relay_response" => "FALSE", "x_card_num" => str_replace(" ", "", $ccnum), "x_card_code" => $ccver, "x_exp_date" => $ccexp, "x_description" => $desc, "x_amount" => $amount, "x_tax" => $tax, "x_freight" => $shipping, "x_first_name" => $billinginfo["fname"], "x_last_name" => $billinginfo["lname"], "x_company" => $billinginfo["company"], "x_address" => $billinginfo["address"], "x_city" => $billinginfo["city"], "x_state" => $billinginfo["state"], "x_zip" => $billinginfo["zip"], "x_country" => $billinginfo["country"], "x_email" => $email, "x_phone" => $phone, "x_ship_to_first_name" => $shippinginfo["fname"], "x_ship_to_last_name" => $shippinginfo["lname"], "x_ship_to_company" => $shippinginfo["company"], "x_ship_to_address" => $shippinginfo["address"], "x_ship_to_city" => $shippinginfo["city"], "x_ship_to_state" => $shippinginfo["state"], "x_ship_to_zip" => $shippinginfo["zip"], "x_ship_to_country" => $shippinginfo["country"], "x_invoice_num" => $invoicenum, "x_test_request" => ($ccnum == '4222222222222' ? true : $testmode), // always set testmode on when using test cr card number ); $fields = ""; foreach ( $authnet_values as $key => $value ) $fields .= "$key=" . urlencode( $value ) . "&"; /////////////////////////////////////////////////////////// // Post the transaction (see the code for specific information) ### Uncomment the appropriate line BELOW for test or live merchant accounts //$ch = curl_init("https://certification.authorize.net/gateway/transact.dll"); // test account $ch = curl_init("https://secure.authorize.net/gateway/transact.dll"); // live account //curl_setopt($ch, CURLOPT_URL, "https://secure.authorize.net/gateway/transact.dll"); curl_setopt($ch, CURLOPT_HEADER, 0); // set to 0 to eliminate header info from response curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // Returns response data instead of TRUE(1) curl_setopt($ch, CURLOPT_POSTFIELDS, rtrim( $fields, "& " )); // use HTTP POST to send form data ### Go Daddy Specific CURL Options //curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, true); //curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); //curl_setopt($ch, CURLOPT_PROXY, 'http://proxy.shr.secureserver.net:3128'); //curl_setopt($ch, CURLOPT_TIMEOUT, 120); ### End Go Daddy Specific CURL Options curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); // uncomment this line if you get no gateway response. ### $resp = curl_exec($ch); // execute post and get results curl_close ($ch); // Parse through response string $text = $resp; $h = substr_count($text, "|"); $h++; $responsearray = array(); for($j=1; $j <= $h; $j++) { $p = strpos($text, "|"); if ($p === false) // note: three equal signs { // x_delim_char is obviously not found in the last go-around // This is final response string $responsearray[$j] = $text; } else { $p++; // get one portion of the response at a time $pstr = substr($text, 0, $p); // This prepares the text and returns one value of the submitted // and processed name/value pairs at a time. // For AIM-specific interpretations of the responses, // please consult the AuthorizeNet AIM Guide, and look up // the section called Gateway Response API. $pstr_trimmed = substr($pstr, 0, -1); // removes "|" at the end if($pstr_trimmed=="") { $pstr_trimmed=""; } $responsearray[$j] = $pstr_trimmed; // remove the part that we identified and work with the rest of the string $text = substr($text, $p); } // end if $p === false } // end parsing for loop $this->arrLastResponse = $responsearray; //print_r($responsearray); // debug return $responsearray; } // end chargeCard function //--------------------------------------------------------------------------------------------- // description: // parameters : // return : //--------------------------------------------------------------------------------------------- function testChargeCard() { $billinginfo = array("fname" => "John", "lname" => "Doe", "company" => "Acme Inc.", "address" => "123 Fake St. Suite 0", "city" => "Longwood", "state" => "FL", "zip" => "32750", "country" => "United States"); $shippinginfo = array("fname" => "John", "lname" => "Doe", "company" => "Acme Inc.", "address" => "123 Fake St. Suite 0", "city" => "Longwood", "state" => "FL", "zip" => "32750", "country" => "United States"); //$loginid = '92a6ZYS8Mhn'; // AuthorizeNet API login ID //$trankey = '6CG8xU3ZB346WjhU'; // AuthorizeNet Transaction Key $loginid = Configure::read('Company.AuthorizeNetLoginID'); // AuthorizeNet API login ID $trankey = Configure::read('Company.AuthorizeNetTransKey'); // AuthorizeNet Transaction Key $ccnum = '4222222222222'; // Visa test number $ccexpmonth = '12'; $ccexpyear = '2014'; $ccver = '123'; $live = false; $amount = '1.00'; // amount to charge. NOTE: In testmode, the amount is the code to use for testing the response reason. // For example, for response reason code number 27 (AVS address mismatch), submit the test transaction with // the credit card number '4222222222222' and the amount '27.00.' $tax = '0.00'; // tax charge $shipping = '0.00'; // shipping charge $desc = 'Workshop Registration: FL_2014'; $email = Configure::read('Workshop.Payment.NotificationEmailRecipientsForTest'); // Eg: 'smayr@acme.com'; $phone = '407-333-4444'; $invoicenum = 'INV123'; $testmode = true; // Method (x_method): CC // Transaction Type (x_type): auth_capture // Customer ID (x_cust_id): FL0077 // Company (x_company): Acme $responsearray = $this->chargeCard($loginid, $trankey, $ccnum, $ccexpmonth, $ccexpyear, $ccver, $live, $amount, $tax, $shipping, $desc, $billinginfo, $email, $phone, $shippinginfo, $invoicenum, $testmode); //print_r($responsearray); // debug return $responsearray; } //--------------------------------------------------------------------------------------------- // description: // parameters : // return : //--------------------------------------------------------------------------------------------- function GetResponseStr($idx) { if ($this->arrLastResponse != null) { switch($idx) { case 1: // Response Code $msg = 'Credit Card Transaction Response: '; switch($this->arrLastResponse[1]) { case 1: $msg .= 'Approved'; break; case 2: $msg .= 'Declined'; break; case 3: $msg .= 'Error'; break; case 4: $msg .= 'Held for Review'; break; default: $msg .= 'Error'; break; } $msg .= ' (Reason Code ' . $this->arrLastResponse[3] . ').
' . $this->arrLastResponse[4]; // Response Reason Code (3) and Text (4) break; case 6: // Address Verification Service (AVS) response: // (A, P, W, X, Y, Z are default AVS confirmation settings) // (B, E, G, N, R, S, U are default AVS rejection settings) // A = Address (Street) matches, ZIP does not // B = Address information not provided for AVS check // E = AVS error // G = Non-U.S. Card Issuing Bank // N = No Match on Address (Street) or ZIP // P = AVS not applicable for this transaction // R = Retry—System unavailable or timed out // S = Service not supported by issuer // U = Address information is unavailable // W = Nine digit ZIP matches, Address (Street) does not // X = Address (Street) and nine digit ZIP match // Y = Address (Street) and five digit ZIP match // Z = Five digit ZIP matches, Address (Street) does not $msg = 'Address verification: '; switch($this->arrLastResponse[6]) { case 'A': $msg .= 'Address (Street) matches, ZIP does not.'; break; case 'B': $msg .= 'Address information not provided for AVS check.'; break; case 'E': $msg .= 'AVS error.'; break; case 'G': $msg .= 'Non-U.S. Card Issuing Bank.'; break; case 'N': $msg .= 'No Match on Address (Street) or ZIP.'; break; case 'P': $msg = ''; break; // Clear message since AVS is not applicable here //$msg .= 'AVS not applicable for this transaction.'; break; case 'R': $msg .= 'Retry—System unavailable or timed out.'; break; case 'S': $msg .= 'Service not supported by issuer.'; break; case 'U': $msg .= 'Address information is unavailable.'; break; case 'W': $msg .= 'Nine digit ZIP matches, Address (Street) does not.'; break; case 'X': $msg .= 'Address (Street) and nine digit ZIP match.'; break; case 'Y': $msg .= 'Address (Street) and five digit ZIP match.'; break; case 'Z': $msg .= 'Five digit ZIP matches, Address (Street) does not.'; break; default: $msg = ''; break; // clear message } break; case 39: // Card Code Verification (CCV) response code: // M = Match, N = No Match, P = No Processed, S = Should have been present, U = Issuer unable to process request $msg = 'Card Code Verification (CCV) Response: '; switch($this->arrLastResponse[39]) { case 'M': $msg = ''; break; // clear message since it is a match //$msg .= 'Match.'; break; case 'N': $msg .= 'No Match.'; break; case 'P': $msg .= 'Not Processed.'; break; case 'S': $msg .= 'Should have been present.'; break; case 'U': $msg .= 'Issuer unable to process request.'; break; default: $msg = ''; break; // clear message } break; case 40: // $response[40] = Cardholder Authentication Verification (CAVV) Response // Value: The cardholder authentication verification response code // Format: Blank or not present = CAVV not validated // - 0 = CAVV not validated because erroneous data was submitted // - 1 = CAVV failed validation // - 2 = CAVV passed validation // - 3 = CAVV validation could not be performed; issuer attempt incomplete // - 4 = CAVV validation could not be performed; issuer system error // - 5 = Reserved for future use // - 6 = Reserved for future use // - 7 = CAVV attempt – failed validation – issuer available (U.S.-issued card/non-U.S acquirer) // - 8 = CAVV attempt – passed validation – issuer available (U.S.-issued card/non-U.S. acquirer) // - 9 = CAVV attempt – failed validation – issuer unavailable (U.S.-issued card/non-U.S. acquirer) // - A = CAVV attempt – passed validation – issuer unavailable (U.S.-issued card/non-U.S. acquirer) // - B = CAVV passed validation, information only, no liability shift $msg = 'Cardholder Authentication Verification (CAVV) Response: '; switch($this->arrLastResponse[40]) { case '0': $msg .= 'CAVV not validated because erroneous data was submitted.'; break; case '1': $msg .= 'CAVV failed validation.'; break; case '2': $msg .= 'CAVV passed validation'; break; case '3': $msg .= 'CAVV validation could not be performed; issuer attempt incomplete'; break; case '4': $msg .= 'CAVV validation could not be performed; issuer system error'; break; case '5': $msg .= 'Reserved for future use'; break; case '6': $msg .= 'Reserved for future use'; break; case '7': $msg .= 'CAVV attempt – failed validation – issuer available (U.S.-issued card/non-U.S acquirer)'; break; case '8': $msg .= 'CAVV attempt – passed validation – issuer available (U.S.-issued card/non-U.S. acquirer)'; break; case '9': $msg .= 'CAVV attempt – failed validation – issuer unavailable (U.S.-issued card/non-U.S. acquirer)'; break; case 'A': $msg .= 'CAVV attempt – passed validation – issuer unavailable (U.S.-issued card/non-U.S. acquirer)'; break; case 'B': $msg .= 'CAVV passed validation, information only, no liability shift'; break; default: $msg = ''; break; // clear message } break; case 51: $msg = 'Credit Card Number: ' . $this->arrLastResponse[51] . '. '; break; default: $msg = ''; } } return $msg; } } ?>
Add component references to the controller using it: Use it. Call the component from the controller needing it: "First", "lname" => "Last", "company" => "Acme Inc.", "address" => "123 Fake St. Suite 0", "city" => "City", "state" => "ST", "zip" => "90210", "country" => "USA"); $shippinginfo = array("fname" => "First", "lname" => "Last", "company" => "Acme Inc.", "address" => "123 Fake St. Suite 0", "city" => "City", "state" => "ST", "zip" => "90210", "country" => "USA"); $response = $this->AuthorizeNet->chargeCard('########', '##############', '4111111111111111', '01', '2010', '123', true, 110, 5, 5, "PurchaseofGoods", $billinginfo, "customeremail@example.com", 555-5555", $shippinginfo); } } ?> The call to the component function chargeCard uses the following format: $response:Array = $this->AuthorizeNet->chargeCard($loginid:String, $trankey:String, $ccnum:String, $ccexpmonth:String, $ccexpyear:String, $ccver:String, $live:Boolean, $amount:Number, $tax:Number, $shipping:Number, $desc:String, $billinginfo:Array, $email:String, $phone:String, $shippinginfo:Array); PARAMETERS * $loginid : Your Authorize.net Login ID * $trankey : Your Authorize.net Transaction Key * $ccnum : The system removes any spaces in the string to meet Authorize.net requirements * $ccexpmonth : 2 digit month string * $ccexpyear : 2 or 4 digit year string * $ccver : The 3 or 4 digit card verificaton code found on the back of Visa/Mastercard and the front of AmEx * $live : Whether to process as a live or test transaction - true : Live Transcation - false : Test Transaction * $amount : Total amount of the transaction. This must include both tax and shipping if applicable. * $tax : Tax amount charged (if any) * $shipping : Shipping cost (if any) * $desc : Description of the transaction to be logged into Authorize.net system * $billinginfo : Associative Array containing values for customer billing details * $email : Customer email * $phone : Customer phone * $billinginfo : Associative Array containing values for customer shipping details RESPONSE * $response : Array (1 based) containing the Payment Gateway Resonse fields The response is an array of all the response codes from Authorize.net's system. Details on all these responses is available at [[http://developer.authorize.net/guides/AIM/]]. Here are some of the most important fields: $response[1] = Response Code (1 = Approved, 2 = Declined, 3 = Error, 4 = Held for Review) $response[2] = Response Subcode (Code used for Internal Transaction Details) $response[3] = Response Reason Code (Code detailing response code) $response[4] = Response Reason Text (Text detailing response code and response reason code) $response[5] = Authorization Code (Authorization or approval code - 6 characters) $response[6] = AVS Response (Address Verification Service response code - A, B, E, G, N, P, R, S, U, W, X, Y, Z) (A, P, W, X, Y, Z are default AVS confirmation settings - Use your Authorize.net Merchant Interface to change these settings) (B, E, G, N, R, S, U are default AVS rejection settings - Use your Authorize.net Merchant Interface to change these settings) $response[7] = Transaction ID (Gateway assigned id number for the transaction) $response[38] = MD5 Hash (Gateway generated MD5 has used to authenticate transaction response) $response[39] = Card Code Response (CCV Card Code Verification response code - M = Match, N = No Match, P = No Processed, S = Should have been present, U = Issuer unable to process request) === TCPDF === * Download [[http://www.tcpdf.org|TCPDF]] and unzip. * Move folder to ''[cakephp]/app/Vendor/tcpdf'' * Create ''[cakephp]/app/Vendor/xtcpdf.php'' (see [[http://www.martin-schenk.es/en/cakephp-2-pdf-with-tcpdf]]): * Create ''[cakephp]app/View/Layouts/pdf/default.ctp'': * In your Controller, for example in ''[cakephp]/app/Controller/ArticlesController.php'', create a new action: public function create_pdf() { $users = $this->User->find('all'); $this->set(compact('users')); $this->layout = '/pdf/default'; $this->render('/Pdf/my_pdf_view'); } * Create a new view file ''[cakephp]/app/View/Pdf/my_pdf_view.ctp'': AddPage(); $html = '

hello world

';
 
foreach ( $posts as $post ){
    $html .= "\n
" . $post['Post']['title']; } $pdf->writeHTML($html, true, false, true, false, ''); $pdf->lastPage(); echo $pdf->Output(APP . 'files/pdf' . DS . 'test.pdf', 'I' /* Dest: F = File to disk, I = Inline to browser */); ?>
For example: * In controller, generate the data and call PDF generator: //--------------------------------------------------------------------------------------------- // description: Generate packet labels form. // parameters : // return : //--------------------------------------------------------------------------------------------- public function GenFormPacketLabels($aWorkshopCode, $aContentType="attendees", $id=0) { $this->GenFormData($aWorkshopCode, $aContentType, $id); $this->SetFormDimensions("PacketLabels"); } //--------------------------------------------------------------------------------------------- // description: Generate course evaluation form. // parameters : // return : //--------------------------------------------------------------------------------------------- private function GenFormData($aWorkshopCode, $aContentType="attendees", $id=0) { $attendees = array(); $this->set('attendees', $attendees); // Get workshop data if (!empty($aWorkshopCode)) { $workshop = ClassRegistry::init('Workshop')->find('first', array( 'conditions' => array('Workshop.Code' => $aWorkshopCode), 'recursive' => 0, )); if (!$workshop) { throw new NotFoundException(__('Invalid workshop')); } } $this->set('workshop', $workshop); // Generate PDF report with custom data if ($this->request->is('post')) { if ($this->request->data) { // Get custom name tag data $attendees = $this->GenAttendeeRec($aWorkshopCode, $this->request->data); $this->set('attendees', $attendees); // Set Header Response to PDF content type $this->layout = '/pdf/default'; $this->response->type('application/pdf'); $this->render('/MyEntity/genlabels'); } } } //--------------------------------------------------------------------------------------------- // description: Set form dimensions. // parameters : $aTemplateType - Template type (string) to use: PacketLabels, MailingLabels, NameTags. // return : void //--------------------------------------------------------------------------------------------- private function SetFormDimensions($aTemplateType) { $this->set('topmargin', $this->GetAppSetting($aTemplateType.'TopMargin')); // mm $this->set('leftmargin', $this->GetAppSetting($aTemplateType.'LeftMargin')); // mm $this->set('rightmargin', $this->GetAppSetting($aTemplateType.'RightMargin')); // mm $this->set('bottommargin', $this->GetAppSetting($aTemplateType.'BottomMargin')); // mm $this->set('intercolmargin', $this->GetAppSetting($aTemplateType.'InterColMargin')); // mm $this->set('interrowmargin', $this->GetAppSetting($aTemplateType.'InterRowMargin')); // mm $this->set('colsperpage', $this->GetAppSetting($aTemplateType.'ColsPerPage')); // label cols $this->set('rowsperpage', $this->GetAppSetting($aTemplateType.'RowsPerPage')); // label rows $this->set('cellborder', $this->GetAppSetting($aTemplateType.'CellBorder')); // 0: no border //0: no border (default), 1: frame, L: left, T: top, R: right, B: bottom } * Create view ''/app/View/MyEntity/genlabels.ctp'': '', 'align' => 'C', 'stretch' => false, 'fitwidth' => true, 'cellfitalign' => '', 'border' => false, 'hpadding' => 'auto', 'vpadding' => 'auto', 'fgcolor' => array(0,0,0), 'bgcolor' => false, //array(255,255,255), 'text' => true, 'font' => 'helvetica', 'fontsize' => 8, 'stretchtext' => 4 ); //$aWorkshopName = $workshop['Workshop']['Code'] . ' - ' . $workshop['Workshop']['Name']; $aWorkshopName = $this->Text->truncate( $workshop['Workshop']['Code'] . ' - ' . $workshop['Workshop']['Name'], 120 /* max chars per line */ / $colsperpage /* max chars */, array('ellipsis' => '...', 'exact' => false ) ); $aWorkshopLocation = $workshop['Workshop']['Address']; ?> SetCreator(PDF_CREATOR); $pdf->SetAuthor(Configure::read('Company.Name')); $pdf->SetTitle($headertitle); $pdf->SetSubject($headersubtitle); $pdf->SetKeywords(''); // set default header data $pdf->SetHeaderData(PDF_HEADER_LOGO, PDF_HEADER_LOGO_WIDTH, $headertitle, $headersubtitle); // set header and footer fonts $pdf->setHeaderFont(Array(PDF_FONT_NAME_MAIN, '', PDF_FONT_SIZE_MAIN)); $pdf->setFooterFont(Array(PDF_FONT_NAME_DATA, '', PDF_FONT_SIZE_DATA)); $pdf->setPrintHeader(false); // do not print footer $pdf->setPrintFooter(false); // do not print footer // set default monospaced font $pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED); // set margins //$pdf->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT); $pdf->SetMargins($leftmargin, $topmargin, $rightmargin); $pdf->SetHeaderMargin(PDF_MARGIN_HEADER); $pdf->SetFooterMargin(PDF_MARGIN_FOOTER); // set auto page breaks //$pdf->SetAutoPageBreak(FALSE, PDF_MARGIN_BOTTOM); $pdf->SetAutoPageBreak(FALSE, $bottommargin); // set image scale factor $pdf->setImageScale(PDF_IMAGE_SCALE_RATIO); // set some language-dependent strings (optional) if (@file_exists(dirname(__FILE__).'/lang/eng.php')) { require_once(dirname(__FILE__).'/lang/eng.php'); $pdf->setLanguageArray($l); } // --------------------------------------------------------- // Add Page // --------------------------------------------------------- set_time_limit(0); // set execution time limit to None // --------------------------------------------------------- // Doc Content $pdf->SetFont($defaultfont, 'B', 18); $labelcount = 0; $isLineBreak = 0; $rowcount = 0; foreach($attendees as $row) { if (($labelcount % $labelsperpage) == 0) { $pdf->AddPage(); $rowcount = 0; } $colcount = ($labelcount % $colsperpage); if ($colcount == 0) { // First cell in row $Xoffset = $leftmargin; $Yoffset = $topmargin + (($cellheight + $interrowmargin) * $rowcount); $isLineBreak = 0; } else { // Any cell (except First cell) in row $Xoffset = $leftmargin + (($cellwidth + $intercolmargin) * $colcount); $Yoffset = $topmargin + (($cellheight + $interrowmargin) * $rowcount); $isLineBreak = 0; // Last cell in row if ($colcount == ($colsperpage-1)) { $isLineBreak = 1; $rowcount++; } } if (!empty($row['Registration']['LastName']) && !empty($row['Registration']['FirstName'])) { $aFullName = StringUtils::nameize($row['Registration']['LastName'] . ', ' . $row['Registration']['FirstName']); //require_once(APP . 'Lib' . DS . 'StringUtils.php'); } else { $aFullName = ""; } $aPacketID = $row['Registration']['PacketID']; $aPacketID = ( ($aPacketID > 0) ? (substr($aPacketID, 0, 4) . '-' . substr($aPacketID, 4, 4)) : 0); $pdf->SetFont($defaultfont, 'B', 18); //$aPacketLabel = "\n" . $aFullName . "\n" . $aPacketID . "\n" . $labelcount; // with counter (debug) $aPacketLabel = "\n" . $aFullName . "\n" . $aPacketID; // Barcode (print in X,Y coordinates of next cell) $x = $pdf->GetX(); // save X pos $y = $pdf->GetY(); // save Y pos $Xoffsetbarcode = $Xoffset + (($cellwidth - 50 /* barcode width */) / 2); $Yoffsetbarcode = $Yoffset + (($cellheight - 15 /* barcode height */) / 2) + 18 /* offset from ctr */; $pdf->write1DBarcode($aPacketID, 'C128', $Xoffsetbarcode, $Yoffsetbarcode, 50 /* width */, 15 /* height */, 0.4 /* bar resolution */, $barcodestyle, 'N'); // Workshop name $pdf->SetXY($Xoffset, $Yoffset); $pdf->SetFont($defaultfont, '', 8); $pdf->Write($height, $aWorkshopName, '', 0, 'L', 0 /*$isnewline*/, $stretch, $isfirstline, $isfirstblock, $heightmax); // Cell $pdf->SetXY($x, $y); // Reset X,Y so wrapping cell wraps around the barcode's cell. $pdf->SetFont($defaultfont, 'B', 22); $pdf->MultiCell($cellwidth, $cellheight, $aPacketLabel, $cellborder, 'C' /* align */, $cellfill, $isLineBreak, $Xoffset, $Yoffset, true /* reset height */, 'M'); if ($isLineBreak) { $pdf->Ln(1); } $labelcount++; } //$pdf->SetFont($defaultfont, '', 8); //date_default_timezone_set('America/New_York'); //$pdf->Write($height, 'Generated: ' . date("Y-m-d H:i:s"), '', $isbgfilled, 'L', true /* newline */, $stretch, $isfirstline, $isfirstblock, $heightmax); // Close and output PDF document ob_end_clean(); // Clean (erase) the output buffer and turn off output buffering ob_start(); // Turn on output buffering, to avoid errors $pdf->Output($workshop['Workshop']['Code'] . '-' . 'PacketLabels.pdf', 'I' /* Inline file dest */); //ob_end_flush(); // Turn off output buffering // --------------------- // End // --------------------- ?> === StringUtils === * Include this file in ''[cakephp]/app/Lib/StringUtils.php'': === SVGGraph === * Get SVGGraph from [[http://www.goat1000.com/svggraph.php]]. * Unpack files to ''[cakephp]/app/Vendor/svggraph''. * Create file ''[cakephp]/app/Vendor/xsvggraph.php'': * Create a View to include graph (Eg: ''[cakephp]/app/View/MyEntity/graphview.ctp''): Values(1, 4, 8, 9, 16, 25, 27); $graph->Render('LineGraph'); ?> * To include graph in a PDF, edit a View (using TCPDF) to include graph (Eg: ''[cakephp]/app/View/MyEntity/pdfgraphview.ctp''): App::import('Vendor','xtcpdf'); $pdf = new XTCPDF('L' /* L=Letter, P=Portrait */, PDF_UNIT, 'Letter' /* Page Size */, true, 'UTF-8', false); $pdf->AddPage(); //------------------------------ // Graph (using SVGGraph) //------------------------------ //require_once 'svggraph/SVGGraph.php'; App::import('Vendor', 'xsvggraph'); $graph = new XSVGGraph(500, 400); $graph->Values(1, 4, 8, 9, 16, 25, 27); $output = $graph->fetch('LineGraph'); // Feed it to TCPDF (Since fetch without options generates the XML declaration and doctype). // This should generate $output of the format: // // // // // // // Feed it like this: $pdf->ImageSVG('@' . $output, $x=15, $y=30, $w='', $h='', $link='http://www.tcpdf.org', $align='', $palign='', $border=1, $fitonpage=false); // Of course you can also save the output in a file, and then provide the path to the file: //$pdf->ImageSVG($file='images/file.svg', $x=15, $y=30, $w='', $h='', // $link='', $align='', $palign='', $border=0, $fitonpage=false); $pdf->lastPage(); echo $pdf->Output(APP . 'files/pdf' . DS . 'articles.pdf', 'I' /* Dest: F = File saved to disk, I = Inline to browser */); === PHPExcel === * Download a copy of PhpExcel helper and component for CakePHP 2.x: [[https://github.com/segy/PhpExcel]]. * Copy files to respective folders in CakePHP app. * Get PHPExcel updates from [[https://github.com/PHPOffice/PHPExcel]], and update helper files in ''[app]/vendor/PhpExcel''. * See documentation: * [[https://github.com/segy/PhpExcel/blob/master/View/Helper/PhpExcelHelper.php|PhpExcelHelper]] * [[http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2009/05/07/4606.aspx|Use PHP to create Open XML Spreadsheet reports]]. In PhpExcel helper, edit function ''createdWorksheet()'' to look like this: public function createWorksheet() { // load vendor classes App::import('Vendor', 'PHPExcel'); // <-- Check class name $this->_xls = new PHPExcel(); $this->_row = 1; return $this; } In controller, add references to helper: class MyController extends AppController { ... public $helpers = array('Html', 'Form', 'Session', ..., 'PhpExcel'); ... } In controller, add action to generate data: ... function actionGetData($id) { $data = ClassRegistry::init('Customer')->find('all', array( 'conditions' => array('Customer.id' => $id), )); $this->set('data', $data); // Create a view that does not display any html header code except for the Excel data. // To do this, set the layout to be 'ajax', which just happens to contain no html outside the main content. $this->layout = 'ajax'; } Create view. Eg: actiongetdata // create new empty worksheet and set default font $this->PhpExcel->createWorksheet()->setDefaultFont('Calibri', 12); // define table cells $table = array( array('label' => __('User'), 'filter' => true), array('label' => __('Type'), 'filter' => true), array('label' => __('Date')), array('label' => __('Description'), 'width' => 50, 'wrap' => true), array('label' => __('Modified')) ); // add heading with different font and bold text $this->PhpExcel->addTableHeader($table, array('name' => 'Cambria', 'bold' => true)); // add data foreach ($data as $d) { $this->PhpExcel->addTableRow(array( $d['User']['name'], $d['Type']['name'], $d['User']['date'], $d['User']['description'], $d['User']['modified'] )); } // close table $this->PhpExcel->addTableFooter(); // Save to Excel file ob_end_clean(); // remove all output (very important, otherwise data is garbage) this->PhpExcel->output('MyExcelFile.xlsx'); == Delete Cached Models == After updating a model, clear the cache to see the changes on the site. $ rm -f /app/tmp/cache/models/cake_model_* $ rm -f /app/tmp/cache/persistent/cake_core_*