| <!-- |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| --> |
| <!DOCTYPE html> |
| <html> |
| <head> |
| <title>Sample: Payment Processor</title> |
| |
| <style> |
| body, td, div, span, p { |
| font-family:arial,sans-serif; |
| } |
| body { |
| padding:0px; |
| margin:0px; |
| } |
| .payment-processor-shadow { |
| filter: alpha(opacity=30); |
| -moz-opacity:.3; |
| opacity:0.3; |
| background-color:#000; |
| width:690px; |
| height:390px; |
| margin:5px 0px 0px 5px; |
| position:absolute; |
| z-index:100; |
| } |
| .payment-processor-border1 { |
| background-color:#E5ECF9; |
| width:690px; |
| height:390px; |
| position:absolute; |
| z-index:200; |
| } |
| .payment-processor-border2 { |
| background-color:#FFF; |
| margin:5px; |
| height:380px; |
| } |
| .payment-processor-content { |
| padding:20px; |
| font-size:13px; |
| } |
| .payment-processor-content #loading-tab { |
| color:#777; |
| } |
| .caption { |
| font-weight:bold; |
| width:80px; |
| display:inline; |
| } |
| .desc { |
| color:#007F00; |
| } |
| .head { |
| font-weight:bold; |
| } |
| </style> |
| |
| |
| <script type="text/javascript"> |
| |
| /** |
| * @static |
| * @class A sample payment process panel provides the UI and logic for the real payment excution on |
| * container api server. |
| * |
| * NOTE: |
| * |
| * All functions or logics or names in this page are customizable. Indeed containers have |
| * to customize them to make the UI consistent. This sample panel page is embeded in the |
| * parent container page as an iframe for better code structure, but indeed it is not |
| * necessary. It can be on the same page as container page. |
| * |
| * You can implement their processor panel page using this file but replace the UI and |
| * mock codes, or use your completely own codes. If you use your own page, just to make |
| * sure <code>shindig.paymentprocessor.initPayment</code> function is called with necessary |
| * callbacks (open and close event handlers) passed in when initializing the page. |
| * |
| */ |
| var myProcessorPanel = (function() { |
| |
| /** Element which holding this processor panel page in parent window. */ |
| var parentDiv; |
| |
| /** Just a reference to <code>shindig.paymentprocessor</code> object, which holding necessary |
| parameters needed in the payment process */ |
| var processor; |
| |
| /** |
| * Called by <code>shindig.paymentprocessor</code> when the counter |
| * panel is closing. |
| */ |
| function closeEvent() { |
| // Set the div in the parent window to invisible. |
| parentDiv.style.display = 'none'; |
| }; |
| |
| |
| /** |
| * Draws the pay counter panel UI itself. |
| * (NOTE that this page is a iframe in its parent container window); |
| * Assigns the submit callback and cancel callback to the buttons. |
| * So from this panel, submit or cancel actions can be made. |
| * |
| * @param {Object} paymentJson The payment parameters. |
| * @param {Object} extraParams The extra parameters for the payment |
| * procedure, including handler url, app title and spec. |
| * @param {Function} submitCallback The submit callback in |
| * <code>shindig.paymentprocessor</code>. |
| * @param {Function} cancelCallback The cancel callback in |
| * <code>shindig.paymentprocessor</code>. |
| */ |
| function openEvent() { |
| // Set the UI. |
| document.getElementById('loading-tab').style.display = 'none'; |
| |
| document.getElementById('payment-appname').innerHTML = processor.getParam('appTitle'); |
| document.getElementById('payment-appspec').innerHTML = processor.getParam('appSpec'); |
| |
| document.getElementById('payment-type').innerHTML = processor.getParam('payment.paymentType'); |
| document.getElementById('payment-amount').innerHTML = processor.getParam('payment.amount'); |
| document.getElementById('payment-message').innerHTML = processor.getParam('payment.message'); |
| |
| var items = processor.getParam('payment.items'); |
| if (items) { |
| var html = '<table border=1><tbody><tr class=head><td>SKU_ID</td><td>Price</td>' + |
| '<td>Count</td><td>Description</td></tr>'; |
| for (var i = 0; i < items.length; i++) { |
| html += '<tr>' + |
| '<td>' + items[i]['skuId'] + '</td>' + |
| '<td>' + items[i]['price'] + '</td>' + |
| '<td>' + items[i]['count'] + '</td>' + |
| '<td>' + items[i]['description'] + '</td>' + |
| '</tr>'; |
| } |
| html += '</tbody></table>'; |
| document.getElementById('payment-items').innerHTML = html; |
| } else { |
| document.getElementById('payment-items').innerHTML = 'No detail items'; |
| } |
| |
| document.getElementById('payment-orderedtime').innerHTML = |
| new Date(processor.getParam('payment.orderedTime')).toLocaleString(); |
| |
| if (processor.getParam('payment.paymentType') == 'credit') { |
| // If the payment type is 'credit', skip the confirm panel UI and |
| // call the submitEvent directly. |
| window.setTimeout(submitHandler, 500); |
| } else { |
| // If the payment type is normal 'payment', add click listeners and |
| // wait for user confirmation. |
| document.getElementById('button-tab').style.display = 'block'; |
| document.getElementById('payment-submit').onclick = submitHandler; |
| document.getElementById('payment-cancel').onclick = cancelHandler; |
| } |
| |
| // Set the div in the parent window to visible. |
| parentDiv.style.display = 'block'; |
| }; |
| |
| /** |
| * Called by submit button clicked by the user. |
| * |
| * This function should send the pay request to container virtual currency |
| * api with Ajax POST. |
| * |
| * Then usually an acknowledge tab will be shown in the with a button to |
| * call the callback function. |
| */ |
| function submitHandler() { |
| document.getElementById('button-tab').style.display = 'none'; |
| document.getElementById('loading-tab').style.display = 'block'; |
| |
| |
| var requestData = processor.getParam('payment'); |
| requestData['st'] = processor.getParam('stoken'); // or other security token |
| |
| |
| |
| |
| ////////////////////////////////////////////////////////////////////////////////////// |
| // Here the logic should be on container sever with communication with app server. // |
| // See the proposal doc Rivision#4. // |
| ////////////////////////////////////////////////////////////////////////////////////// |
| var sendPaymentRequest = function(ajaxCallback) { |
| // The Server will communicate with App Backend Server then response. |
| // Here is just a fake call. You should replace these codes with actual ajax. |
| // Wait 1 second to simulate the network connection. |
| window.setTimeout(function() { |
| var responseData = {}; |
| responseData['submittedTime'] = new Date().getTime(); |
| |
| |
| // Do some fake check here. Can be any type of error during server-to-server roundtrips. |
| if (requestData['amount'] > 1000) { |
| responseData['responseCode'] = 'INSUFFICIENT_MONEY'; |
| responseData['responseMessage'] = 'Fake not enough money response!'; |
| ajaxCallback(responseData); |
| return; |
| } |
| |
| // Simulate success response. |
| responseData['orderId'] = 'ORDER_ID_FROM_APP_' + Math.round(Math.random() * 10000); |
| responseData['executedTime'] = new Date().getTime(); |
| responseData['responseCode'] = 'OK'; |
| responseData['responseMessage'] = 'Fake success response!'; |
| ajaxCallback(responseData); |
| |
| }, 1000); |
| }; |
| ////////////////////////////////////////////////////////////////////////////////////// |
| |
| |
| |
| |
| // Send Ajax Call to Container Virtual Currency API Server. |
| sendPaymentRequest(function(responseData) { |
| |
| processor.setParam('payment.responseCode', responseData['responseCode']); |
| processor.setParam('payment.responseMessage', responseData['responseMessage']); |
| |
| if (responseData['responseCode'] == 'OK') { |
| // Copy the server generated fields back to processor parameters. |
| processor.setParam('payment.submittedTime', responseData['submittedTime']); |
| processor.setParam('payment.executedTime', responseData['executedTime']); |
| processor.setParam('payment.orderId', responseData['orderId']); |
| } |
| |
| // Close the processor panel and return to app. |
| processor.closePayment(); |
| }); |
| }; |
| |
| |
| /** |
| * Invoked when cancel button clicked by user. |
| */ |
| function cancelHandler() { |
| // You can also show a message to say the order is canceled. |
| // Here just call the callback and return. |
| processor.setParam('payment.responseCode', 'USER_CANCELLED'); |
| processor.closePayment(); |
| }; |
| |
| |
| |
| return { |
| /** |
| * Initializes the counter module. It can be called by this page's <code>body.onload()</code> |
| * function or in other initializing steps. |
| * Note the <code>shindig.paymentprocessor</code> object is passed from the parent window. |
| */ |
| init: function() { |
| // Store the parent node in which there is an iframe holding this page. |
| parentDiv = window.frameElement.parentNode; |
| |
| processor = parent.shindig.paymentprocessor; |
| |
| // Initialize the paymentprocessor module with four events. |
| // The container need to fully implement these event functions for |
| // UI/Backend interaction. |
| processor.initPayment(openEvent, closeEvent); |
| } |
| }; |
| |
| })(); |
| |
| </script> |
| </head> |
| <body onload="myProcessorPanel.init();"> |
| <!-- Customize the UI --> |
| <div class="payment-processor-shadow"></div> |
| <div class="payment-processor-border1"> |
| <div class="payment-processor-border2"> |
| <div class="payment-processor-content"> |
| <p class="desc"> |
| This panel is in an iframe from another page in the same container domain:<br> |
| <b><script>document.write(window.location.href);</script></b> |
| </p> |
| <div class="caption">App Name: </div><span id="payment-appname"></span><br> |
| <div class="caption">App Spec: </div><span id="payment-appspec"></span><br> |
| <br> |
| <div class="caption">Payment Type: </div><span id="payment-type"></span><br> |
| <div class="caption">Amount: </div><span id="payment-amount"></span><br> |
| <div class="caption">Message: </div><span id="payment-message"></span><br> |
| <div class="caption">Items: </div><br><div id="payment-items"></div> |
| <div class="caption">Ordered Time: </div><span id="payment-orderedtime"></span><br> |
| <br> |
| <div id="button-tab" style="display:none;"> |
| <button id="payment-submit">Submit</button> |
| <button id="payment-cancel">Cancel</button> |
| </div> |
| <div id="loading-tab" style="display:none"> |
| Please wait... |
| </div> |
| </div> |
| </div> |
| </div> |
| </body> |
| </html> |
| |