blob: b52193a8c59d122369b7162bb0c503b165146eb8 [file] [log] [blame]
<!--
* 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>