├── ShippingAbstract.php ├── ShoppingOrdersManagement.css ├── ShippingFixedCost.module ├── PaymentAbstract.php ├── PaymentSimpleExample.module ├── PaymentInvoice.module ├── README.md ├── PaymentExample.module ├── ShoppingStepsMarkup.module ├── ShoppingOrdersManagement.module ├── ShoppingCart.module └── ShoppingCheckout.module /ShippingAbstract.php: -------------------------------------------------------------------------------- 1 | 'Fixed cost shipping', 11 | 'version' => 001, 12 | 'summary' => 'Simple shipping option, which sets fixed shipping cost for all orders.', 13 | 'singular' => false, 14 | 'autoload' => false 15 | ); 16 | } 17 | public function init() { 18 | $this->title = $this->_("Fixed shipping cost"); 19 | } 20 | 21 | public function calculateShippingCost() { 22 | return $this->shippingCost; 23 | } 24 | 25 | static public function getModuleConfigInputfields(Array $data) { 26 | // this is a container for fields, basically like a fieldset 27 | $fields = new InputfieldWrapper(); 28 | 29 | // since this is a static function, we can't use $this->modules, so get them from the global wire() function 30 | $modules = wire('modules'); 31 | 32 | $field = $modules->get("InputfieldFloat"); 33 | $field->attr('name', 'shippingCost'); 34 | $field->attr('value', $data['shippingCost']); 35 | $field->label = "Shipping cost for all orders"; 36 | $fields->add($field); 37 | 38 | 39 | return $fields; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /PaymentAbstract.php: -------------------------------------------------------------------------------- 1 | modules->getModuleConfigData('ShoppingCheckout'); 14 | if (!isset($data['completedUrlSegment'])) { 15 | $module = $this->modules->get('ShoppingCheckout'); 16 | $data = $module::getDefaultData(); 17 | } 18 | $page = $this->page; 19 | $this->currentUrl = $page->url . $data['paymentUrlSegment'] . '/'; 20 | $this->completedUrl = $page->url . $data['completedUrlSegment'] . '/'; 21 | } 22 | 23 | /* 24 | * 25 | * returns nothing. You should edit and save $order page. If payment was succesful, 26 | * then do $order->removeStatus(Page::statusUnpublished) and remember to save the order! 27 | * 28 | * If order was also paid, then do $order->sc_paid = time(); 29 | * 30 | * If order was not paid, but it was succesful (like invoice, money on delivery etc) 31 | * then just publish the order, but do not set sc_paid value. 32 | * 33 | * After you have manipulated the order, then just to redirect to $this->completedUrl 34 | * 35 | * 36 | * @param Page $order keeps the page object for the order 37 | * 38 | */ 39 | abstract function processPayment(Page $order); 40 | 41 | } 42 | -------------------------------------------------------------------------------- /PaymentSimpleExample.module: -------------------------------------------------------------------------------- 1 | 'Simple Payment Example', 11 | 'version' => 001, 12 | 'summary' => 'Simplest possible payment example module for PW Shop', 13 | 'singular' => false, 14 | 'autoload' => false 15 | ); 16 | } 17 | public function init() { 18 | $this->title = $this->_("Simple Payment Example"); 19 | } 20 | 21 | /* 22 | * 23 | * returns nothing. You should edit and save $order page. If payment was succesful, 24 | * then do $order->removeStatus(Page::statusUnpublished) and remember to save the order! 25 | * 26 | * If order was also paid, then do $order->sc_paid = time(); 27 | * 28 | * If order was not paid, but it was succesful (like invoice, money on delivery etc) 29 | * then just publish the order, but do not set sc_paid value. 30 | * 31 | * After you have manipulated the order, then just to redirect to $this->completedUrl 32 | * 33 | * 34 | * @param Page $order keeps the page object for the order 35 | * 36 | */ 37 | public function processPayment(Page $order) { 38 | 39 | /* 40 | * If you need to know how to access order details, please look for PaymentExample.module 41 | */ 42 | 43 | $order->setOutputFormatting(false); 44 | $order->sc_paid = time(); // Set order as paid 45 | $order->removeStatus(Page::statusUnpublished); // Set order as finished 46 | $order->save(); 47 | 48 | /* 49 | * You always end with redirect to $this->completedUrl; 50 | */ 51 | $this->session->redirect($this->completedUrl); 52 | 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /PaymentInvoice.module: -------------------------------------------------------------------------------- 1 | 'Invoice Payment', 11 | 'version' => 001, 12 | 'summary' => 'Very simple payment method, where payment will be invoiced later on.', 13 | 'singular' => false, 14 | 'autoload' => false 15 | ); 16 | } 17 | public function init() { 18 | $this->title = $this->_("Invoice"); 19 | } 20 | 21 | /* 22 | * 23 | * returns nothing. You should edit and save $order page. If payment was succesful, 24 | * then do $order->removeStatus(Page::statusUnpublished) and remember to save the order! 25 | * 26 | * If order was also paid, then do $order->sc_paid = time(); 27 | * 28 | * If order was not paid, but it was succesful (like invoice, money on delivery etc) 29 | * then just publish the order, but do not set sc_paid value. 30 | * 31 | * After you have manipulated the order, then just to redirect to $this->completedUrl 32 | * 33 | * 34 | * @param Page $order keeps the page object for the order 35 | * 36 | */ 37 | public function processPayment(Page $order) { 38 | 39 | /* 40 | * If you need to know how to access order details, please look for PaymentExample.module 41 | */ 42 | 43 | $order->setOutputFormatting(false); 44 | //$order->sc_paid = time(); // No payment here 45 | $order->removeStatus(Page::statusUnpublished); // Set order as finished 46 | $order->save(); 47 | 48 | /* 49 | * You always end with redirect to $this->completedUrl; 50 | */ 51 | $this->session->redirect($this->completedUrl); 52 | 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 1. Install Shopping Cart 2 | 2. Add sc_price field to your product template (can be added into multiple templates) 3 | 3. Edit few of your products and give them price 4 | 4. Add get("ShoppingCart")->renderAddToCart(); ?> to your product template. If you don't like the markup it generates, you can put the wanted markup directly into template. 5 | 5. At this point you can add products to your cart. If you want to show somewhere how many products there is in your cart, do this in your template: 6 | echo $modules->get('ShoppingCart')->getNumberOfItems(false); // Total number of items 7 | or 8 | echo $modules->get('ShoppingCart')->getNumberOfItems(); // Different items only, ie. qty doesn't matter 9 | 6. How about the actual cart page, where you can see all the products in your cart? Add this to any of your templates where you want to see it: 10 | get("ShoppingCart")->renderCart() ?> 11 | This is starting to take shape. But there is no checkout at all? How to actually order something? 12 | 7. Install Shopping Checkout module 13 | 8. Now you see "Continue to checkout" under your renderCart() output. Clicking that would result in page not found error. Shopping Checkout module creates system template called sc-checkout. You need to create corresponding template file. So create sc-checkout.php to your /site/templates/ folder. Only code you need to put there is: 14 | get("ShoppingCheckout")->renderCheckout(); ?> 15 | 9. If you need to customize the fields etc, you can do that in certain degree by editing the ShoppingCheckout module. Also, pw-shop is fully multilang, so you probably do want to translate the module files. 16 | 10. Checkout doesn't let you go through unless you install at least one payment method. So do so if you want to continue. 17 | 11. You might want to show checkout steps (kind of a breadcrumb). That is possible with yet another module. Just put this to your sc-checkout template: 18 | get("ShoppingStepsMarkup")->render(); ?> 19 | 12. When someone orders something, you probably want to see those in your admin. That is what Shopping Orders Management module is for. Go ahead and install that also (it has basic functionality, but very much wip). 20 | 21 | You find PayPal payment method module from here: https://github.com/apeisa/PaymentPaypal 22 | -------------------------------------------------------------------------------- /PaymentExample.module: -------------------------------------------------------------------------------- 1 | 'Example Payment Method', 11 | 'version' => 001, 12 | 'summary' => 'Demonstrates how to create payment methods for PW Shop', 13 | 'singular' => false, 14 | 'autoload' => false 15 | ); 16 | } 17 | public function init() { 18 | 19 | } 20 | 21 | /* 22 | * 23 | * returns nothing. You should edit and save $order page. If payment was succesful, 24 | * then do $order->removeStatus(Page::statusUnpublished) and remember to save the order! 25 | * 26 | * If order was also paid, then do $order->sc_paid = time(); 27 | * 28 | * If order was not paid, but it was succesful (like invoice, money on delivery etc) 29 | * then just publish the order, but do not set sc_paid value. 30 | * 31 | * After you have manipulated the order, then just to redirect to $this->completedUrl 32 | * 33 | * 34 | * @param Page $order keeps the page object for the order 35 | * 36 | */ 37 | public function processPayment(Page $order) { 38 | if ($this->input->get->ok) { 39 | 40 | if ($this->input->get->ok == 'fail') { 41 | // We don't remove statusUnpublished. That means failed or cancelled payment 42 | $this->session->redirect($this->completedUrl); 43 | } 44 | 45 | if ($this->input->get->ok == 'paid') { 46 | $order->setOutputFormatting(false); 47 | $order->sc_paid = time(); 48 | } 49 | 50 | $order->removeStatus(Page::statusUnpublished); 51 | $order->save(); 52 | 53 | $this->session->redirect($this->completedUrl); 54 | 55 | 56 | } 57 | 58 | // No need to really do anything like this on payment module, this is here just for educational purposes): 59 | $out = "

Products ordered

"; 60 | 61 | $out .= ""; 67 | 68 | $out .= "

Shipping details

"; 69 | 70 | $out .= ""; 81 | 82 | $out .= "

Other interesting stuff

"; 83 | $out .= ""; 87 | 88 | // Usually we would use some payment api or send people to 3rd party service like paypal 89 | // and process their reply 90 | 91 | $out .= "

How do we proceed?

"; 92 | 93 | $out .= "