From 39a6658b155a1104aa1cd3d3151c896414652e6e Mon Sep 17 00:00:00 2001 From: kira <164851225@qq.com> Date: Tue, 11 Sep 2018 13:57:48 +0800 Subject: [PATCH 1/5] app style --- .../payment/manage/appclient/core/RetailAppService.java | 2 ++ .../manage/appclient/core/impls/RetailAppServiceImp.java | 5 +++++ .../payment/manage/appclient/web/RetailAppController.java | 5 +++++ 3 files changed, 12 insertions(+) diff --git a/src/main/java/au/com/royalpay/payment/manage/appclient/core/RetailAppService.java b/src/main/java/au/com/royalpay/payment/manage/appclient/core/RetailAppService.java index b0138c63c..1706ade3a 100644 --- a/src/main/java/au/com/royalpay/payment/manage/appclient/core/RetailAppService.java +++ b/src/main/java/au/com/royalpay/payment/manage/appclient/core/RetailAppService.java @@ -163,4 +163,6 @@ public interface RetailAppService { JSONObject getCouponCusCouponLog(String client_moniker, AppQueryBean appQueryBean); void saveCouponAccuessLog(int client_id, String coupon_id); + + JSONObject getStyle(); } diff --git a/src/main/java/au/com/royalpay/payment/manage/appclient/core/impls/RetailAppServiceImp.java b/src/main/java/au/com/royalpay/payment/manage/appclient/core/impls/RetailAppServiceImp.java index f8f3a01a9..c441fcd24 100644 --- a/src/main/java/au/com/royalpay/payment/manage/appclient/core/impls/RetailAppServiceImp.java +++ b/src/main/java/au/com/royalpay/payment/manage/appclient/core/impls/RetailAppServiceImp.java @@ -498,6 +498,11 @@ public class RetailAppServiceImp implements RetailAppService { couponAccuessLogMapper.save(couponAccuessLog); } + @Override + public JSONObject getStyle() { + return royalPayCMSSupport.getStyle(); + } + @Override public void updateClient(JSONObject device, AppClientBean appClientBean) { String clientType = device.getString("client_type"); diff --git a/src/main/java/au/com/royalpay/payment/manage/appclient/web/RetailAppController.java b/src/main/java/au/com/royalpay/payment/manage/appclient/web/RetailAppController.java index 003e7b8ca..00f5b7ce9 100644 --- a/src/main/java/au/com/royalpay/payment/manage/appclient/web/RetailAppController.java +++ b/src/main/java/au/com/royalpay/payment/manage/appclient/web/RetailAppController.java @@ -574,4 +574,9 @@ public class RetailAppController { retailAppService.saveCouponAccuessLog(client_id, coupon_id); } + @RequestMapping(value = "/style", method = RequestMethod.GET) + public JSONObject getStyle() { + return retailAppService.getStyle(); + } + } From 14e130316ecbfc1a7d8d54ee186659f3cc1e2ee0 Mon Sep 17 00:00:00 2001 From: kira <164851225@qq.com> Date: Wed, 12 Sep 2018 14:22:39 +0800 Subject: [PATCH 2/5] update --- src/main/ui/static/lib/rpay/app_pay_2.js | 394 ++++++++++++++++++++++ src/main/ui/static/lib/rpay/rpay_jssdk.js | 58 ++++ 2 files changed, 452 insertions(+) create mode 100644 src/main/ui/static/lib/rpay/app_pay_2.js create mode 100644 src/main/ui/static/lib/rpay/rpay_jssdk.js diff --git a/src/main/ui/static/lib/rpay/app_pay_2.js b/src/main/ui/static/lib/rpay/app_pay_2.js new file mode 100644 index 000000000..076527393 --- /dev/null +++ b/src/main/ui/static/lib/rpay/app_pay_2.js @@ -0,0 +1,394 @@ +/** + * Created by yixian on 2017-05-08 + */ + +$(function () { + 'use strict'; + var dataCache = {price: '0', coupons: [], coupon_groups:{}}; + var exchangeRate = parseFloat(window.exchange_rate); + + dataCache.paying = false; + var ctrl = {}; + + $('.weui_grid.key').bind('touchstart', function () { + if (dataCache.paying) { + return; + } + var char = $(this).attr('data-char'); + appendChar(char); + }); + + $('.coupons .use-check').click(function () { + if ($(this).hasClass('disabled')) { + return; + } + var couponId = $(this).attr('data-coupon-id'); + var couponGroup = $(this).attr('data-coupon-group'); + if (couponGroup) { + var prevCouponId = dataCache.coupon_groups[couponGroup]; + if (prevCouponId) { + var prevIdx = dataCache.coupons.indexOf(prevCouponId); + if (prevIdx >= 0) { + dataCache.coupons.splice(prevIdx, 1); + } + if (prevCouponId!=couponId) { + $('.coupons .use-check[data-coupon-id="' + prevCouponId + '"]').removeClass('checked').addClass('unchecked'); + dataCache.coupon_groups[couponGroup] = couponId; + }else { + dataCache.coupon_groups[couponGroup]= null; + } + }else { + dataCache.coupon_groups[couponGroup] = couponId; + } + + } + + if ($(this).is('.checked')) { + $(this).removeClass('checked').addClass('unchecked'); + } else { + $(this).removeClass('unchecked').addClass('checked'); + } + var checked = $(this).is('.checked'); + if (checked) { + dataCache.coupons.push(couponId); + updatePrice(); + } else { + var idx = dataCache.coupons.indexOf(couponId); + dataCache.coupons.splice(idx, 1); + updatePrice(); + } + }); + + $('#key_B').bind('touchstart', function () { + backspace(); + }); + + function updatePoundage(price) { + if (window.extensions.indexOf('customerrate') >= 0 && window.rateValue != null) { + if (window.use_customised_rate) { + var rate = new Decimal(100).plus(window.rateValue).div(100); + var poundageValue = new Decimal(dataCache.price).mul(rate).sub(dataCache.price); + } else { + var rateRemain = new Decimal(100).sub(window.rateValue).div(100); + poundageValue = new Decimal(dataCache.price).div(rateRemain).sub(dataCache.price); + } + dataCache.poundageValue = poundageValue.toFixed(2, Decimal.ROUND_HALF_UP); + return poundageValue.plus(price).toFixed(2, Decimal.ROUND_HALF_UP); + } + return price; + } + + function updatePrice() { + $('#audVal').html(dataCache.price); + var realPrice = dataCache.price; + $('#audValReal').html(realPrice); + var surchargeData = calculateSurcharge(realPrice); + + dataCache.tax = surchargeData.tax; + dataCache.surcharge = surchargeData.surcharge; + var price = surchargeData.newPrice || realPrice; + var priceBeforeDiscount = price; + dataCache.discounts = []; + $(window.coupons).each(function () { + price = this.handleDiscount(price, dataCache.price, dataCache.discounts, dataCache.coupons); + }); + dataCache.customSurcharge = new Decimal(price).sub(realPrice).toFixed(2,Decimal.ROUND_HALF_UP); + dataCache.finalPrice = new Decimal(price).toFixed(2, Decimal.ROUND_FLOOR); + var rate = 'CNY' == window.currency ? 1 : exchangeRate; + var cnyVal = Decimal.mul(price, rate).toFixed(2, Decimal.ROUND_HALF_UP); + $('#cnyVal').html(cnyVal); + dataCache.currencyPrice = 'CNY' == window.currency ? Decimal.div(priceBeforeDiscount, exchangeRate).toFixed(2, Decimal.ROUND_FLOOR) : priceBeforeDiscount; + } + + function updatePoundageStatus() { + $(window.coupons).each(function () { + var coupon = this; + var couponId = coupon.couponId(); + if (coupon.isEnable(dataCache.currencyPrice||0)) { + $('.coupons .use-check[data-coupon-id=' + couponId + ']').removeClass('disabled'); + } else { + var dom = $('.coupons .use-check[data-coupon-id=' + couponId + ']').addClass('disabled'); + var couponGroup = dom.attr('data-coupon-group'); + if (couponGroup) { + if (dataCache.coupon_groups[couponGroup] == couponId) { + dataCache.coupon_groups[couponGroup] = null; + } + } + var idx = dataCache.coupons.indexOf(couponId); + if (idx >= 0) { + dataCache.coupons.splice(idx, 1); + } + dom.removeClass('checked').addClass('unchecked'); + } + }) + } + updatePoundageStatus(); + + function backspace() { + dataCache.price = dataCache.price.substring(0, dataCache.price.length - 1); + if (dataCache.price.length == 0) { + dataCache.price = '0'; + } + updatePrice(); + updatePoundageStatus(); + } + + function appendChar(char) { + var pointLocation = dataCache.price.indexOf('.'); + if (pointLocation >= 0 || char == '.' || dataCache.price.length < 5) { + if (pointLocation >= 0 && char == '.') { + return; + } + if (pointLocation >= 0 && pointLocation <= dataCache.price.length - 3) { + return; + } + if (dataCache.price == '0' && char != '.') { + dataCache.price = ''; + } + dataCache.price += char; + updatePrice(); + updatePoundageStatus(); + } + } + + $('#coupon-box-toggle').click(function () { + $('.coupons-container').addClass('show') + }); + $('.coupons-container>.coupons-mask,.coupons-container #close-coupon-box').click(function () { + $(this).parents('.coupons-container').removeClass('show'); + }); + + + + $('.remark-btn').click(function () { + var cfg = { + title: '备注 Remark', + template: '', + initialize: function (dialog) { + $('').addClass('remark-input').attr('name', 'remark').val(dataCache.remark || '').appendTo($('.weui_dialog_bd', dialog)); + }, + confirm: function (dialog, chosen) { + if (chosen) { + var remark = $('textarea[name="remark"]', dialog).val(); + if (remark) { + $('#remark-box').text('备注:' + remark).show() + } else { + $('#remark-box').text('').hide(); + } + dataCache.remark = remark; + } + + } + }; + showWeuiDialog(cfg); + }); + + $('.paydetail').click(function () { + var config = { + title: 'Payment Detail', + template: '', + initialize: function (dialog) { + var bd = $('.weui_dialog_bd', dialog); + var currencySymbol = window.currency == 'AUD' ? '$' : '¥'; + $('

').html('Input Price 输入金额:' + currencySymbol + dataCache.price).appendTo(bd); + if (parseFloat(dataCache.customSurcharge) > 0) { + $('

').html('Surcharge 手续费(' + window.rateValue + '%):+' + currencySymbol + dataCache.customSurcharge).appendTo(bd); + } + $(dataCache.discounts).each(function () { + $('

').html(this.title + ':-' + currencySymbol + this.amount).appendTo(bd); + }); + $('

').addClass('final').html('Final 支付金额:' + currencySymbol + (dataCache.finalPrice || 0)).appendTo(bd); + } + }; + showWeuiDialog(config); + }); + + $('#key_P').bind('touchstart', function () { + + pay(); + + // $('#key_P').addClass('hidden'); + // $('#key_Loading').removeClass('hidden'); + // if (dataCache.paying) { + // return; + // } + // dataCache.paying = true; + // var data = {price: dataCache.price + '', original_number: true, currency: window.currency}; + // if (dataCache.remark) { + // data.description = dataCache.remark; + // } + // if (window.extensions.indexOf('preauthorize') >= 0) { + // data.preauthorize = true; + // } + // if (window.extensions.indexOf('qrcodemode') >= 0) { + // data.qrmode = true; + // } + // if (window.extensions.indexOf('customerrate') >= 0) { + // data.customerrate = true; + // } + // data.coupons = dataCache.coupons; + // dataCache.remark = ''; + // data.account_id = User.getProduct(); + // data.qrcodeVersion = window.qrcodeVersion; + // $.ajax({ + // url: '/api/v1.0/bestpay/partners/' + window.client_moniker + '/app_order', + // method: 'POST', + // data: JSON.stringify(data), + // dataType: 'json', + // contentType: 'application/json', + // success: function (pay) { + // if (pay.direct_paid) { + // window.location = '/api/v1.0/bestpay/partners/' + window.client_moniker + '/orders/' + pay.order_id; + // return; + // } + // var paydata = pay.params; + // try { + // Payment.onPay(paydata, function () { + // window.location = '/api/v1.0/bestpay/partners/' + window.client_moniker + '/orders/' + pay.order_id; + // dataCache.paying = false; + // $('#key_P').removeClass('hidden'); + // $('#key_Loading').addClass('hidden'); + // }, function (rescode) { + // dataCache.paying = false; + // if (rescode === "cancel") { + // Dialog.alert("支付取消" + rescode) + // } else { + // Dialog.alert("支付失败" + rescode) + // } + // $('#key_P').removeClass('hidden'); + // $('#key_Loading').addClass('hidden'); + // }) + // } catch (e) { + // Dialog.alert(e); + // dataCache.paying = false; + // $('#key_P').removeClass('hidden'); + // $('#key_Loading').addClass('hidden'); + // } + // Dialog.dismissDialog(dataCache.process); + // }, + // error: function (jqXhr) { + // Dialog.alert(jqXhr.responseJSON.message); + // Dialog.dismissDialog(dataCache.process); + // dataCache.paying = false; + // $('#key_P').removeClass('hidden'); + // $('#key_Loading').addClass('hidden'); + // } + // }); + }); + + function showWeuiDialog(config) { + if (config.templateUrl) { + $.ajax({ + url: config.templateUrl, + dataType: 'html', + success: function (template) { + buildDialog(template); + } + }); + } else { + buildDialog(config.template); + } + + + function buildDialog(template) { + var defaultConfig = {backdrop: true}; + config = $.extend({}, defaultConfig, config); + var dialog = $("
", {class: 'weui_dialog_confirm'}); + var mask = $('
', {class: 'weui_mask'}).appendTo(dialog); + if (config.backdrop) { + mask.click(function () { + dialog.remove(); + if ($.isFunction(config.dismiss)) { + config.dismiss(); + } + }) + } + var dialogBox = $("
", {class: 'weui_dialog'}).appendTo(dialog); + if (config.title) { + $('
', {class: 'weui_dialog_hd'}).append($('', {class: 'weui_dialog_title'}).html(config.title)).appendTo(dialogBox); + } + var dialogBody = $("
", {class: 'weui_dialog_bd'}).appendTo(dialogBox); + if (template) { + dialogBody.append(template); + } + if ($.isFunction(config.initialize)) { + config.initialize(dialog); + } + var ft = $('
').appendTo(dialogBox); + if ($.isFunction(config.confirm)) { + var yes = $('', {class: 'weui_btn_dialog primary', text: 'OK'}).appendTo(ft); + yes.click(function () { + config.confirm(dialog, true); + dialog.remove(); + }); + var no = $('', {class: 'weui_btn_dialog default', text: 'Cancel'}).appendTo(ft); + no.click(function () { + config.confirm(dialog, false); + dialog.remove(); + }) + } else { + var ok = $('', {class: 'weui_btn_dialog primary', text: 'OK'}).appendTo(ft); + ok.click(function () { + dialog.remove(); + }) + } + dialog.appendTo($('body')); + } + + } + + + function getUserId(){ + window.RPayPlus.send("getUserId", null, function(data){ + alert(data); + }); + } + + function pay(){ + var order={ + orderId:'00002', + amount:'$100.07', + title:'Gift card purchase' + }; + window.RPayPlus.send('pay', order, function(data){ + alert('this is callback from native and data='+JSON.stringify(data)); + }); + } + + function back(){ + window.RPayPlus.send("back", null, null); + } + + function jsInvoke(){ + window.RPayPlus.send("jsInvoke", 'Native Test', null); + } + + function createOrder(msg){ + alert('create order information='+JSON.stringify(msg)); + } + + function queryOrder(msg){ + alert('query order information='+JSON.stringify(msg)); + + var order={ + orderId:'00001', + amount:'$10.98', + title:'Balance Top-UP' + }; + setTimeout("window.RPayPlus.onResult("+JSON.stringify(order)+");", 1500); + } + + function registerJs(){ + window.RPayPlus.register('createOrder', function(data){ + createOrder(data); + }); + window.RPayPlus.register('queryOrder', function(data){ + queryOrder(data); + }); + } + + function init() { + registerJs(); + getUserId(); + } +}); \ No newline at end of file diff --git a/src/main/ui/static/lib/rpay/rpay_jssdk.js b/src/main/ui/static/lib/rpay/rpay_jssdk.js new file mode 100644 index 000000000..39aa6afe9 --- /dev/null +++ b/src/main/ui/static/lib/rpay/rpay_jssdk.js @@ -0,0 +1,58 @@ +(function (){ + var callbacks = {}; + var functions = {}; + + window.RPayPlus = { + // 向Native端发送消息,用于实现:JS->Native + send: function(methodName, param, callback) { + var thisId = 0; + if(callback){ + thisId = new Date().getTime();; // 获取唯一id + callbacks[thisId] = callback; // 存储Callback + } + var json = { + method: methodName, + data: param || {}, + callbackId: thisId // 传到 Native 端 + }; + var msg = JSON.stringify(json); + + var u = navigator.userAgent; + var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); + if(isiOS){ + window.webkit.messageHandlers.rpayplus.postMessage(msg); + } else{ + rpayplus.send(msg); + } + }, + + // 接收来自Native发送的消息,用于实现Native->JS + receive: function(msg) { + var method = msg.methodName, + data = msg.data || {}, + callbackId = msg.callbackId; // JS->Native的回调函数ID + + // 具体逻辑 bridgeName 和 callbackId 不会同时存在; + // callbackId有效,表示此接收信息源自JS->Native的回调 + // callbackId无效,且method有效,表示是Native->JS的直接调用 + if (callbackId && callbacks[callbackId]) { + callbacks[callbackId](msg.data); // 执行调用 + return; + } + if (method && functions[method]) { + functions[method](msg); + } + }, + // 注册JS方法,供Native调用,未被注册的方法,Native无法调用 + register: function(methodName, callback) { + if (!functions[methodName]) { + functions[methodName] = callback; + } + }, + + // JS端逻辑处理完成后,回调给Native的数据 + onResult: function(data){ + window.RPayPlus.send("jsCallback", data, null); + } + }; + })(); \ No newline at end of file From 32aad0f13c6af1b0ef2e1645d0fb62640fda2e7b Mon Sep 17 00:00:00 2001 From: kira <164851225@qq.com> Date: Wed, 12 Sep 2018 14:32:02 +0800 Subject: [PATCH 3/5] update --- src/main/ui/static/lib/rpay/app_pay_2.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/main/ui/static/lib/rpay/app_pay_2.js b/src/main/ui/static/lib/rpay/app_pay_2.js index 076527393..c9b29ed8a 100644 --- a/src/main/ui/static/lib/rpay/app_pay_2.js +++ b/src/main/ui/static/lib/rpay/app_pay_2.js @@ -386,9 +386,6 @@ $(function () { queryOrder(data); }); } - - function init() { - registerJs(); - getUserId(); - } + registerJs(); + getUserId(); }); \ No newline at end of file From 9ba1500808718b8571ae5a8c0d85572c167ae8b4 Mon Sep 17 00:00:00 2001 From: kira <164851225@qq.com> Date: Wed, 12 Sep 2018 14:46:24 +0800 Subject: [PATCH 4/5] update --- src/main/ui/static/lib/rpay/app_pay_2.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/ui/static/lib/rpay/app_pay_2.js b/src/main/ui/static/lib/rpay/app_pay_2.js index c9b29ed8a..5126e7f98 100644 --- a/src/main/ui/static/lib/rpay/app_pay_2.js +++ b/src/main/ui/static/lib/rpay/app_pay_2.js @@ -386,6 +386,5 @@ $(function () { queryOrder(data); }); } - registerJs(); getUserId(); }); \ No newline at end of file From 999df149c05dee556a30bef7a9e28e3dc1f118da Mon Sep 17 00:00:00 2001 From: kira <164851225@qq.com> Date: Wed, 12 Sep 2018 14:57:38 +0800 Subject: [PATCH 5/5] fixbug parent client invalid --- src/main/ui/static/lib/rpay/rrlogo.png | Bin 0 -> 2719 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/main/ui/static/lib/rpay/rrlogo.png diff --git a/src/main/ui/static/lib/rpay/rrlogo.png b/src/main/ui/static/lib/rpay/rrlogo.png new file mode 100644 index 0000000000000000000000000000000000000000..bd87d97d2710e80eec1a217f9943a03736e9ebb6 GIT binary patch literal 2719 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 Z{tG~iZ)UX-1w#M;002ovPDHLkV1g