/
Westpac Payment Gateway
Westpac Payment Gateway
// this is the default javascript for a screen layout that will appear in the screen layout javascript editor // // this file can be found at templates/scripts/dialer/defaultScreenLayout.js /** * Implements an interface to westpac's Payway CC system * * You can find a list of test cards here: * https://www.payway.com.au/docs/rest.html#test-card-numbers * * We use the 'payway.js' which essentially injects an iframe with cc UI * into our screen layout. * * We then call into an Action Script SendPaywayPayment to to do the actual * transaction. * * The action script uses this api: * https://www.payway.com.au/docs/rest.html#payway-rest-api * */ $.njDialerPlugin.getPage('${NjWizardPageName}').onPageNext = function(page,defaultNextPage) { return $.njDialerPlugin.getPage("Finished Appointment"); }; $.njDialerPlugin.getPage('${NjWizardPageName}').onPagePrev = function(page,defaultPrevPage) { // do something here debugger; // return page.getPage('Name of desired page'); // to stay on the current page: return page; return defaultPrevPage; }; $.njDialerPlugin.loadjscssfile = function(filename, filetype, callback) { jQuery.getScript(filename, callback); }; /* * this method will be invoked when the lead is displayed for previewing */ $.njDialerPlugin.onPreview = function() { // lead loaded in preview mode debugger; $.njDialerPlugin.loadCCFrame(); }; $.njDialerPlugin.loadCCFrame = function() { // lead connected $.njDialerPlugin.loadjscssfile("https://api.payway.com.au/rest/v1/payway.js", "js", $.njDialerPlugin.createFrame) //dynamically load and add this .js file } $.njDialerPlugin.validAmount = function() { debugger; var valid = false; var amount = $.njDialerPlugin.getFieldValue("CreditCardAmount"); if (amount != undefined && amount.length > 1) { // is this a currency value valid = /^\d{0,4}(\.\d{0,2})?$/.test(amount); } return valid; }; // Callback once script gets loaded. $.njDialerPlugin.createFrame = function(script, textStatus, jqXHR) { debugger; // If the form isn't already loaded then load it. var frames = jQuery.find("#payway-credit-card-iframe0"); if (frames.length == 0) { // Get our submit button var submit = document.getElementById('payway-cc-submit'); submit.disabled = true; // Wire the click handler $("#payway-cc-submit").on('click', $.njDialerPlugin.submitPayment); var testKey = 'XXXX'; var productionKey='YYYYY'; var apiKey = productionKey; payway.createCreditCardFrame({ publishableApiKey: apiKey, onValid: function() { submit.disabled = !$.njDialerPlugin.validAmount(); }, onInvalid: function() { submit.disabled = true; }, tokenMode: "callback" }, $.njDialerPlugin.ccFrameReady); // wire the submit button } } $.njDialerPlugin.ccFrameReady = function(err, frame) { if (err != null) { alert(err.message); } else { $.njDialerPlugin.ccFrame = frame; } }; $.njDialerPlugin.submitPayment = function(event) { // stop the form submission debugger; event.preventDefault(); // Fire the actoin to get the token and the callback will submit the payment. $.njDialerPlugin.ccFrame.getToken($.njDialerPlugin.receiveTokenAndSubmitPayment); }; /** * Callback to called by the above call to ccFrame.getToken * * The data object contains the singlueUseTokenId and the 'amount'.' */ $.njDialerPlugin.receiveTokenAndSubmitPayment = function(err, data) { if (err != null) { alert(err.message); } else { debugger; //var amount = $("#ccAmount").value; // Pass in the single use token. The amount should be in the CreditCardAmount field already. $.njDialerPlugin.setFieldValueByName("paywaySingleUseTokenID", data.singleUseTokenId); // alert("Amount is: " + $.njDialerPlugin.getFieldValue("CreditCardAmount") ); //$.njDialerPlugin.setFieldValueByName("CreditCardAmount", data.amount); $("#progress").text('Credit Card has been submitted please wait...'); $.njDialerPlugin.setFieldValueByName("CreditCardTransactionId", ""); $.njDialerPlugin.setFieldValueByName("CreditCardReceiptNumber", ""); $.njDialerPlugin.setFieldValueByName("CreditCardResponseCode", ""); $.njDialerPlugin.setFieldValueByName("CreditCardStatus", "Processing..."); $.njDialerPlugin.callActionScript('SendPaywayPayment', data.singleUseTokenId, function(result) { try { var allValid = true; var details = JSON.parse(result); // deserialise it. // alert("details:" + details) debugger; $.njDialerPlugin.setFieldValueByName("CreditCardTransactionId", details.transactionId); $.njDialerPlugin.setFieldValueByName("CreditCardReceiptNumber", details.receiptNumber); $.njDialerPlugin.setFieldValueByName("CreditCardResponseCode", details.responseCode); $.njDialerPlugin.setFieldValueByName("CreditCardStatus", details.status); // alert(details.responseCode + ":" + details.status + " " + details.responseText); } catch(e) { alert("something bad in callback" + e); } }); } }; $.njDialerPlugin.paymentFailed = function(xhr, status, error) { alert("failed:" + xhr.responseText); } $.njDialerPlugin.paymentSuccess = function(data) { $.njDialerPlugin.setFieldValueByName("paywaySingleUseTokenID", data.singleUseTokenId); alert("You must click 'Next' to transition to the Final Page for the appointment to be applied"); alert("success:" + data); } /* * this method is called before saving. * also for the contact hub when, hanging up and also when the 'Verify' button is clicked. * * if you return false the save or hangup will fail * * you should display any messages to the user so they know how to resolve the problem... * for example: * alert('The comments field may not be blank'); * */ $.njDialerPlugin.onVerify = function(disposition) { // validate lead and return true if ok to save return true; }; $.njDialerPlugin.onSave = function(disposition) { // lead is being saved, an opportunity to notify external services }; /* * this method will be called when the call is hung up */ $.njDialerPlugin.onHangup = function() { // do something here }; $.njDialerPlugin.getPage('${NjWizardPageName}').onPageEntry = function(page) { // do something here $.njDialerPlugin.loadCCFrame(); };
Payway Action Script
package creditcardpayment; import au.com.noojee.actionscript.api.v1.BaseScreenLayoutAction; import au.com.noojee.actionscript.api.JSCallback; import au.com.noojee.actionscript.api.v1.ScreenLayoutAction; import java.io.IOException; import java.net.URL; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import com.google.gson.Gson; import com.google.gson.GsonBuilder; public class SendPaywayPayment extends BaseScreenLayoutAction { static private String TEST_API_KEY = "TTTT"; static private String TEST_MERCHANT_ID = "TEST"; static private String PRODUCTION_API_KEY = "PPPP"; static private String PRODUCTION_MERCHANT_ID = "XXXXX"; static private boolean productionMode = true; static private String REST_END_POINT_URL = "https://api.payway.com.au/rest/v1/transactions"; // @Override public void exec(String singleUseTokenID, Map<String, String> fieldValues, JSCallback jsCallback) throws Exception { logger.warn(singleUseTokenID); //String singleUseTokenID = fieldValues.get("paywaySingleUseTokenID"); String amount = fieldValues.get("CreditCardAmount"); logger.error("Submitting CC Payment: token=" + singleUseTokenID + " amount:" + amount); PaymentTransaction.Response result = submitPayment(singleUseTokenID, amount, fieldValues.get("njLeadId")); //cancelPayment(singleUseTokenID, amount, fieldValues.get("njLeadId")); logger.error("Payment response: " + result); String jsonEntity = new Gson().toJson(result); // jsCallback.call(result); logger.error("Calling jsoncallback with: " + jsonEntity); jsCallback.call(jsonEntity); } public PaymentTransaction.Response submitPayment(String singleUseTokenID, String amount, String leadId) throws PaymentTransactionException, IOException, HTTPException { Map<String,String> args = new HashMap<>(); args.put("singleUseTokenId", singleUseTokenID); args.put("customerNumber", leadId); args.put("transactionType", "payment"); args.put("principalAmount", amount); args.put("currency", "aud"); args.put("orderNumber", leadId); args.put("merchantId", (productionMode == true ? PRODUCTION_MERCHANT_ID : TEST_MERCHANT_ID)); logger.error("args" + Arrays.toString(args.entrySet().toArray())); Map<String, String> headers = getAuthHeaders(); HTTPConnector connector = new HTTPConnector(); URL url = new URL(REST_END_POINT_URL); logger.error("URL:" + url); //PaymentTransaction transaction = new PaymentTransaction(singleUseTokenID, amount); // PaymentTransaction.Response HTTPResponse httpResponse = connector.push(HTTPMethod.POST, url, connector.buildBody(args) , headers, PaymentTransaction.Response.class); logger.error("Raw response: " + httpResponse); //String jsonEntity = new Gson().toJson(response); // return response.getResponseBody(); return httpResponse.getResponse(PaymentTransaction.Response.class); } private Map<String, String> getAuthHeaders() { Map<String,String> headers = new HashMap<>(); String apiKey = (productionMode == true ? PRODUCTION_API_KEY : TEST_API_KEY); String encodedKey = javax.xml.bind.DatatypeConverter.printBase64Binary(apiKey.getBytes()); headers.put("Authorization", "Basic " + encodedKey); return headers; } public PaymentTransaction.Response cancelPayment(String originalTransactionId, String amount, String leadId) throws PaymentTransactionException, IOException, HTTPException { Map<String,String> args = new HashMap<>(); args.put("transactionType", "refund"); args.put("principalAmount", amount); args.put("orderNumber", leadId); args.put("parentTransactionId", originalTransactionId); Map<String, String> headers = getAuthHeaders(); HTTPConnector connector = new HTTPConnector(); URL url = new URL(REST_END_POINT_URL); HTTPResponse httpResponse = connector.push(HTTPMethod.POST, url, connector.buildBody(args) , headers, PaymentTransaction.Response.class); return httpResponse.getResponse(PaymentTransaction.Response.class); } class PaymentTransactionErrors { String message; Link[] links; String getMessage() { return message; } @Override public String toString() { return "PaymentTransactionErrors [message=" + message + ", links=" + Arrays.toString(links) + "]"; } } static class PaymentTransaction { String singleUseTokenID; String principalAmount; PaymentTransaction(String singleUseTokenID, String principalAmount) { this.singleUseTokenID = singleUseTokenID; this.principalAmount = principalAmount; } static class Response { String transactionId; String receiptNumber; String status; // approved String responseCode; String responseText; String customerName; String principleAmount; String surchargeAmount; String paymentAmount; String transactionDateTime; String settlementDate; } } public PaymentTransactionErrors getError(String body) { logger.error("Body" + body); Gson gson = new GsonBuilder().create(); PaymentTransactionErrors errors = gson.fromJson(body, PaymentTransactionErrors.class); return errors; } static class Link { String rel; String href; @Override public String toString() { return "Link [rel=" + rel + ", href=" + href + "]"; } } }
Related content
05.5. Javascript Editor
05.5. Javascript Editor
More like this
Screen Layout Action Scripts
Screen Layout Action Scripts
More like this
Wizard Page Decision Making
Wizard Page Decision Making
More like this
4.0 Example
4.0 Example
More like this
Google Calendar Integration
Google Calendar Integration
More like this
Noojee Click for AJAX
Noojee Click for AJAX
More like this