├── README.md └── PaymentSuomenVerkkomaksut.module /README.md: -------------------------------------------------------------------------------- 1 | You need Verkkomaksut_Module_Rest.php class which can be downloaded from here: http://docs.verkkomaksut.fi/files/Verkkomaksut_Module_Rest.php.zip -------------------------------------------------------------------------------- /PaymentSuomenVerkkomaksut.module: -------------------------------------------------------------------------------- 1 | 'Suomen Verkkomaksut', 24 | 'version' => 001, 25 | 'summary' => 'Uses REST-API and requires CURL', 26 | 'singular' => false, 27 | 'autoload' => false 28 | ); 29 | } 30 | public function init() { 31 | require_once(dirname(__FILE__) . '/Verkkomaksut_Module_Rest.php'); 32 | } 33 | 34 | public function processPayment(Page $order) { 35 | 36 | if ($this->input->urlSegment(2) == "success") { 37 | $module = new Verkkomaksut_Module_Rest($this->merchantId, $this->merchantSecret); 38 | if($module->confirmPayment($_GET["ORDER_NUMBER"], $_GET["TIMESTAMP"], $_GET["PAID"], $_GET["METHOD"], $_GET["RETURN_AUTHCODE"])) { 39 | // Valid notification, confirm payment 40 | $order->setOutputFormatting(false); 41 | $order->sc_paid = time(); 42 | $order->removeStatus(Page::statusUnpublished); 43 | $order->save(); 44 | } 45 | 46 | $this->session->redirect($this->completedUrl); 47 | } 48 | 49 | if ($this->input->urlSegment(2) == "failure") { 50 | $this->session->redirect($this->completedUrl); 51 | } 52 | 53 | 54 | if ($this->input->urlSegment(2) == "pending") { 55 | // Valid notification, confirm payment but don't mark as paid since it is pending payment 56 | $order->setOutputFormatting(false); 57 | $order->removeStatus(Page::statusUnpublished); 58 | $order->save(); 59 | $this->session->redirect($this->completedUrl); 60 | } 61 | 62 | $data = $this->modules->getModuleConfigData('PaymentSuomenVerkkomaksut'); 63 | foreach($data as $key => $value) { 64 | $this->$key = $value; 65 | } 66 | 67 | 68 | $http = ($this->config->https) ? 'https://' : 'http://'; 69 | 70 | // An object is created to model all payment return addresses. 71 | $this->urlset = new Verkkomaksut_Module_Rest_Urlset( 72 | $http . $this->config->httpHost . $this->currentUrl . "success/", // return address for successful payment 73 | $http . $this->config->httpHost . $this->currentUrl . "failure/", // return address for failed payment 74 | 75 | // You should create notify page somewhere, which can accept the notify. We are not in the order context 76 | // when notify comes, so that is why it cannot be done here in this payment module. We do have processNotify() method 77 | // that you can and should use. 78 | $http . $this->config->httpHost, // address for payment confirmation from SV server 79 | $http . $this->config->httpHost . $this->currentUrl . "pending/" // address for notification on pending payment (NetPosti) 80 | ); 81 | 82 | /* Let's see if we have enough information for orderDetails or do we go with price only */ 83 | if ($order->sc_firstname && $order->sc_lastname && $order->email && $order->sc_streetaddress && $order->sc_zip && $order->sc_city) { 84 | $this->createOrderDetailsOrder($order); 85 | } else { 86 | $this->createSimpleOrder($order); 87 | } 88 | } 89 | 90 | public function createOrderDetailsOrder(Page $order) { 91 | // An object is created to model payer’s data 92 | $contact = new Verkkomaksut_Module_Rest_Contact( 93 | $order->sc_firstname, // first name 94 | $order->sc_lastname, // surname 95 | $order->email, // email address 96 | $order->sc_streetaddress, // street address 97 | $order->sc_zip, // postal code 98 | $order->sc_city, // post office 99 | "FI", // maa (ISO-3166) TODO: How to handle multiple countries? 100 | $order->sc_phone, // telephone number 101 | "", // mobile phone number 102 | "" // company name 103 | ); 104 | 105 | // Payment creation 106 | $orderNumber = $order->id; // Use distinguished order number 107 | $payment = new Verkkomaksut_Module_Rest_Payment_E1($orderNumber, $this->urlset, $contact); 108 | 109 | foreach($order->children("check_access=0") as $p) { 110 | 111 | // Adding one or more product rows to the payment 112 | $payment->addProduct( 113 | $p->title, // product title 114 | $p->id, // product code 115 | $p->sc_qty, // product quantity 116 | $p->sc_price, // product price (/apiece) 117 | "23.00", // Tax percentage TODO: Implement real product VAT 118 | "0.00", // Discount percentage 119 | Verkkomaksut_Module_Rest_Product::TYPE_NORMAL // Product type 120 | ); 121 | } 122 | 123 | // Sending payment to Suomen Verkkomaksut service and handling possible errors 124 | $module = new Verkkomaksut_Module_Rest($this->merchantId, "{$this->merchantSecret}"); 125 | try { 126 | $result = $module->processPayment($payment); 127 | } 128 | catch(Verkkomaksut_Exception $e) { 129 | // processing the error 130 | // Error description available $e->getMessage() 131 | $errormsg = $e->getMessage(); 132 | throw new WireException($errormsg); 133 | } 134 | 135 | $this->renderFormOrRedirect($result); 136 | 137 | } 138 | 139 | public function createSimpleOrder(Page $order) { 140 | $orderNumber = $order->id; // Use distinguished order number 141 | $price = $order->sc_price; 142 | $payment = new Verkkomaksut_Module_Rest_Payment_S1($orderNumber, $this->urlset, $price); 143 | 144 | $module = new Verkkomaksut_Module_Rest($this->merchantId, "{$this->merchantSecret}"); 145 | try { 146 | $result = $module->processPayment($payment); 147 | } 148 | catch(Verkkomaksut_Exception $e) { 149 | // processing the error 150 | // Error description available $e->getMessage() 151 | $errormsg = $e->getMessage(); 152 | throw new WireException($errormsg); 153 | } 154 | 155 | $this->renderFormOrRedirect($result); 156 | } 157 | 158 | public function processNotify() { 159 | // Check if we have all required params 160 | if (empty($_GET["ORDER_NUMBER"]) || empty($_GET["TIMESTAMP"]) || empty($_GET["PAID"]) || empty($_GET["METHOD"]) || empty($_GET["RETURN_AUTHCODE"])) 161 | return false; 162 | 163 | // Check if params match 164 | $module = new Verkkomaksut_Module_Rest($this->merchantId, $this->merchantSecret); 165 | if(!$module->confirmPayment($_GET["ORDER_NUMBER"], $_GET["TIMESTAMP"], $_GET["PAID"], $_GET["METHOD"], $_GET["RETURN_AUTHCODE"])) 166 | return false; 167 | 168 | // All good, save the order information 169 | $orderId = (int) $_GET["ORDER_NUMBER"]; 170 | $order = $this->pages->get($orderId); 171 | $order->setOutputFormatting(false); 172 | $order->sc_paid = time(); 173 | $order->removeStatus(Page::statusUnpublished); 174 | $order->save(); 175 | return true; 176 | } 177 | 178 | public function renderFormOrRedirect($result) { 179 | $token = $result->getToken(); 180 | $url = $result->getUrl(); 181 | 182 | if ($this->embeddedForm) { 183 | echo "
"; 184 | echo "Siirry maksamaan"; 185 | echo "
"; 186 | 187 | echo "" . 188 | ""; 193 | } else { 194 | $this->session->redirect($url); 195 | } 196 | 197 | } 198 | 199 | static public function getModuleConfigInputfields(Array $data) { 200 | // this is a container for fields, basically like a fieldset 201 | $fields = new InputfieldWrapper(); 202 | 203 | // since this is a static function, we can't use $this->modules, so get them from the global wire() function 204 | $modules = wire('modules'); 205 | 206 | 207 | if(empty($data['merchantId'])) $data['merchantId'] = '13466'; 208 | if(empty($data['merchantSecret'])) $data['merchantSecret'] = '6pKF4jkv97zmqBJ3ZL8gUw5DfT2NMQ'; 209 | 210 | $field = $modules->get("InputfieldText"); 211 | $field->attr('name', 'merchantId'); 212 | $field->attr('value', $data['merchantId']); 213 | $field->label = "Merchant ID"; 214 | $fields->add($field); 215 | 216 | $field = $modules->get("InputfieldText"); 217 | $field->attr('name', 'merchantSecret'); 218 | $field->attr('value', $data['merchantSecret']); 219 | $field->label = "Merchant Secret"; 220 | $fields->add($field); 221 | 222 | 223 | $field = $modules->get("InputfieldCheckbox"); 224 | $field->name = 'embeddedForm'; 225 | $field->label = "Use embedded SVM form instead of redirect?"; 226 | $field->value = 1; 227 | $field->attr('checked', empty($data['embeddedForm']) ? '' : 'checked'); 228 | $fields->add($field); 229 | 230 | return $fields; 231 | } 232 | } 233 | --------------------------------------------------------------------------------