米德

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

有个H5支付的业务需要随机数字的键盘

参考了下文:https://blog.csdn.net/Mr_Smile2014/article/details/52473351

做了一些小修改:

  在原有的基础上,增加了一些按键反馈的效果。

  每个按键加上边框。

最终效果:

  

下面是所有代码:

1.HTML页面+JS

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>

<head>

<meta name="viewport"

    content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0" />

<meta http-equiv="Cache-Control" CONTENT="private,must-revalidate">

<link href="../media/css/bootstrap.min.css" rel="stylesheet" type="text/css"/>

<!-- 引入js脚本文件  begin -->

<!--[if lt IE 9]>

  <script src="http://cdn.bootcss.com/html5shiv/3.7.2/html5shiv.min.js"></script>

  <script src="http://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>

<![endif]-->

<title>H5付款</title>

<style type="text/css">

.input-out {

    padding-top: 14px;

}

.btn-out {

    margin:30px 10px;

}

.btn-out button {

    width: 100%;

    background: #5CACEE;

    border: #5CACEE;

    color: #fff;

    height: 50px;

    border-radius: 3px;

    font-size: 18px;

    font-family: "Microsoft Yahei", "??????", SimHei, Tahoma, Arial, Helvetica, STHeiti;

}

.keyboard {

    background: #fff;

}

.keyboard table {

    width:100%;

    text-align:center;

}

.keyboard table td {

    padding: 15px;

}

.keyboard table a,

.keyboard table a:hover,

.keyboard table a:focus {

    color: #333;

    text-decoration: none;

}

.input-out label {

    color:#D2D1D1;

    font-weight: normal;

    font-size: 16px;

}

.bottom {

    color:#888888;

    margin-bottom: 15px;

    text-align:center;

    margin-top:100px;

}

.bottom a {

    color:#888888;

}

.bottom img {

    vertical-align: middle;

    width: 18px;

}
/*.inputText { 
    font-size: 16px;
    border-left: medium none; 
    border-right: medium none; 
    border-top: medium none; 
    border-bottom: 1px solid rgb(192,192,192); 
    border-bottom: 1px solid #ddd;
       padding-left: 12px; 
       width:100%;
    font-weight: normal;
    padding-top: 20px;
    height: 50px;
}*/
input[type="password"],input[type="text"]{ 
    font-size: 30px;
    border-left: medium none; 
    border-right: medium none; 
    border-top: medium none; 
    /*border-bottom: 1px solid rgb(192,192,192);*/ 
    border-bottom: 1px solid #ddd;
       padding-left: 12px; 
       width:100%;
    font-weight: normal;
    padding-top: 10px;
    height: 40px;
}
</style>

</head>

<body>

    <div style="height: 20px;">
    </div>

    <form action="../pay" method="post" id="from">

        <div class="content">

            
                <div>
                    <label  style="font-size: 20px;padding-left: 12px; ">账户</label>
                    <input type="text" id="loginName"  placeholder="" />

                </div>
                
                <!--<div>
                    <label  style="font-size: 20px;padding-left: 12px; ">密码</label>
                    <input type="password"  id="pwd" placeholder="" />

                </div>
                
                --><label  style="font-size: 20px;padding-left: 12px; ">支付密码</label>
                <div id="tradePwd" class="input-out pass-label" style="border-bottom: 1px solid #ddd;padding-left: 12px;" random="2321321321" path="../" >
                    
                    <label id="pin" style="color: #8C8C8C;height: 20px;"></label>

                </div>

        </div>

         

        <div class="btn-out">

            <button type="button" class="btn btn-default" ontouchstart="check();" id="pay">支付</button>

        </div>

    </form>

    <div class="bottom" id="bottom-out">

        <!--<img src="<c:url value="/images/phone.png"/>" />

        --><!--<span>客服电话:4000-xxx-xxx</span>

    --></div>

    <!-- jianpan-->

    <div class="keyboard" style="display:none;" id="keyboard">

        <table class="table-bordered" id="key_table">

        </table>

    </div>

</body>
<script src="../media/js/jquery-1.10.1.min.js" type="text/javascript"></script>
<script src="../media/js/bootstrap.min.js" type="text/javascript"></script>
<script type="text/javascript">
    $(document).ready(

        function() {
            $("#pay").removeAttr("disabled");
            $("input").click(function() {
                hideKey();
            });
            $("button").click(function() {
                hideKey();
            });
            $(".pass-label").click(function() {
                
                var rangdom = $(this).attr("random");
                var path = $(this).attr("path");
                pwdkey(this, rangdom, path);
            });
            window.addEventListener(
                    "onorientationchange" in window ? "orientationchange"
                            : "resize", hengshuping, false);
        });
        
        //横竖屏
        function hengshuping() {
         
            if (window.orientation == 180 || window.orientation == 0) {
                $("div#keyboard td").each(function() {
                    $(this).css("padding", "15px");
                });
            }
            if (window.orientation == 90 || window.orientation == -90) {
                $("div#keyboard td").each(function() {
                    $(this).css("padding", "8px");
                });
         
            }
            window.scrollTo(0, $(".pass-label").offset().top);
        }
        
        //加载密码键盘
        function pwdkey(obj, rangdom, path) {
            $('.keyboard').addClass("navbar-fixed-bottom");
            $('.keyboard').css({
                "z-index" : "9999"
            });
            if (rangdom == null || rangdom == "") {
                alert("无法加载密码键盘,请刷新后重试!");
                return false;
            }
            if ($("#pkey").val() == null || $("#pkey").val() == "undefined") {
                $(obj)
                        .html(
                                $(obj).html()
                                        + '<input type="hidden" name="pkey" id="pkey" />');
            }
            //$("#pin").html("支付密码");
            $("#pin").html("");
            setCssNomal();
            $("#pkey").val("");
            $.ajax({
                type : 'post',
                url : "../h5Pay/pkey",
                cache : false,
                async : false,
                data : {
                    rangdom : rangdom
                },
                success : function(data) {
                    if (data == null || data == "" || data == "undefined"
                            || data.length != 10) {
                        alert("无法加载密码键盘,请刷新后重试!");
                        return false;
                    } else {
                        var key_table = $("#key_table");
                        key_table.html("");
                        var content = '<tr>';
                        for (var i = 0; i < 12; i++) {
                            if ((i + 1) % 3 == 0 && i != 0 && i <= 5) {
                                content = content
                                        + '<td class="table-bordered" style="width:33%;"  key="'
                                        + data[i]
                                        + '"ontouchstart="ontouchreturn(this);" ontouchend="return ontouch(this);"><img src="'
                                        + '../h5Pay/getKey?key='
                                        + data[i]
                                        + '&rangdom='
                                        + rangdom
                                        + '" style="height:20px;" id="key_img"/></td></tr><tr>';
                            } else if (i <= 7) {
                                content = content
                                        + '<td class="table-bordered" style="width:33%;" key="'
                                        + data[i]
                                        + '"ontouchstart="ontouchreturn(this);" ontouchend="return ontouch(this);"><img src="'
                                        + '../h5Pay/getKey?key='
                                        + data[i]
                                        + '&rangdom='
                                        + rangdom
                                        + '" style="height:20px;" id="key_img"/></td>';
                            } else if (i == 8) {
                                content = content
                                        + '<td class="table-bordered" style="width:33%;" ontouchstart="ontouchreturn(this);"  ontouchend="return deleteOne(this);"><img src="'
                                        + '../media/image/keys/delete.png" style="height:20px;"  id="key_img"/></td>'
                                        + '</tr><tr>';
                            } else if (i < 11) {
                                content = content
                                        + '<td class="table-bordered" style="width:33%;" key="'
                                        + data[i - 1]
                                        + '" ontouchstart="ontouchreturn(this);" ontouchend="return ontouch(this);"><img src="'
                                        + '../h5Pay/getKey?key='
                                        + data[i - 1]
                                        + '&rangdom='
                                        + rangdom
                                        + '" style="height:20px;" id="key_img"/></td>';
                            } else {
                                content = content
                                        + '<td class="table-bordered" style="width:33%;" ontouchstart="ontouchreturn(this);" ontouchend="return _ok(this);"><img src="'
                                        + '../media/image/keys/ok.png" style="height:20px;" id="key_img"/></td>'
                                        + '</tr>';
                            }
 
                        }
                        key_table.html(content);
 
                        setTimeout(function() {
                            $("#keyboard").show();
                        }, 600);
                        hengshuping();
                    }
 
                },
                error : function() {
                    alert("无法加载键盘,请刷新后重试!");
                }
            });
        }
        function ontouchreturn(obj) {
            $(obj).attr("bgcolor","#c5c5c5");
        }
        //数字按钮映射input
        function ontouch(obj) {
            $(obj).removeAttr("bgcolor");
            var pkey = $("#pkey").val();
            var key = $(obj).attr("key");
            if (pkey == "") {
                $("#pin").html("");
            }
            var content = $("#pin").html();
            if (content != "" && content.length >= 6) {
                return false;
            }
            if (pkey != "") {
                key = "," + key;
            }
            pkey = pkey + key;
            $("#pkey").val(pkey);
            $("#pin").append("");
            setCssKey();
         
        }
        
        //删除按钮
        function deleteOne(obj) {
            $(obj).removeAttr("bgcolor");
            var pkey = $("#pkey").val() + "";
            if (pkey == "") {
                return false;
            }
            var local = pkey.lastIndexOf(",");
            if (local == -1) {
         
                $("#pkey").val("");
                $("#pin").html("");
                //$("#pin").html("支付密码");
                setCssNomal();
            } else {
                pkey = pkey.substring(0, local - 1);
                var content = $("#pin").html();
                content = content.substring(0, content.length - 1);
                $("#pkey").val(pkey);
                $("#pin").html(content);
            }
         
        }
        
        //确认按钮
        function _ok(obj) {
            $(obj).removeAttr("bgcolor");
            $("#key_table").html("");
            $("#keyboard").hide();
        }
        function showkey() {
            $("#keyboard").show();
        }
        function hideKey() {
            $("#key_table").html("");
            $("#keyboard").hide();
        }
        function setCssKey() {
            $("#pin").css({
                "font-size" : "18px",
                "color" : "#030303",
                "font-weight" : "normal",
                "letter-spacing" : "1px"
            });
        }
        function setCssNomal() {
            $("#pin").css({
                "font-size" : "16px",
                "color" : "#8C8C8C",
                "font-weight" : "normal"
            });
        }
        
        //支付按钮
        function check()
        {
            hideKey();
            var pin="";
    
            pin=$("#pkey").val();
            if(pin==""||pin==undefined)
            {
                bool=false;
                alert("请输入支付密码");
                
                return false;
            }else
            {
                var keys=pin.split(",");
                if(keys.length!=6)
                {
                    alert("请输入6位支付密码");
                    
                    return false;
                }
            }
            $.ajax({
                type : 'post',
                url : "../h5Pay/pay",
                data : {
                    random:"2321321321",
                    pin:pin
                },
                cache : false,
                success : function(data) { 
                    if(data.success)
                        {
                          alert(data.message);
                        }else{
                            
                        }
                    
                },
                error : function(){
                    
                    alert("系统异常,请重试!");
                }
            });
        }

</script>

</html>

2.密码键盘的MODEL类

import java.io.Serializable;
import java.util.List;
import java.util.Map;

public class PwdKeyDto implements Serializable{

    private static final long serialVersionUID = 1L;
    private List<String> rundomKeys;// 随机Keys
    private Map<String, String> valueKeyMaps;// 密文和明文映射
    private Map<String, String> imgKeyMaps;// 密文和明文映射
 
    public PwdKeyDto() {
        super();
        // TODO Auto-generated constructor stub
    }
 
    public List<String> getRundomKeys() {
        return rundomKeys;
    }
 
    public void setRundomKeys(List<String> rundomKeys) {
        this.rundomKeys = rundomKeys;
    }
 
    public PwdKeyDto(List<String> rundomKeys, Map<String, String> valueKeyMaps,
            Map<String, String> imgKeyMaps) {
        super();
        this.rundomKeys = rundomKeys;
        this.valueKeyMaps = valueKeyMaps;
        this.imgKeyMaps = imgKeyMaps;
    }
 
    public Map<String, String> getValueKeyMaps() {
        return valueKeyMaps;
    }
 
    public void setValueKeyMaps(Map<String, String> valueKeyMaps) {
        this.valueKeyMaps = valueKeyMaps;
    }
 
    public Map<String, String> getImgKeyMaps() {
        return imgKeyMaps;
    }
 
    public void setImgKeyMaps(Map<String, String> imgKeyMaps) {
        this.imgKeyMaps = imgKeyMaps;
    }
    
}

3.后台Action

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import com.sanwing.spi.model.PwdKeyDto;
import com.sanwing.spi.utils.PwdKeyUtils;


@Controller
@RequestMapping("/h5Pay")
public class H5Pay {
    
    private static final Logger logger = Logger.getLogger(H5Pay.class);

    @RequestMapping("/jumpH5Pay")
    public String jumpH5Pay(HttpServletRequest request,HttpServletResponse response){    
        return "/h5Pay";
    }
    
    /**
     * 
     * @Description: 获取密码键盘
     * @param request
     * @param rangdom 随机字符串
     * @return
     * 
     */
    @SuppressWarnings("unchecked")
    @ResponseBody
    @RequestMapping(value = "/pkey", method = RequestMethod.POST)
    public Object digitkeyboard(HttpServletRequest request, String rangdom) {
        try {
            if (isBlank(rangdom)) {
                return "";
            }
            PwdKeyDto pwdkey = PwdKeyUtils.digitkeyboard();
            HttpSession session = request.getSession();
            session.setAttribute("pwdkey_" + rangdom, pwdkey);
            /*redisUtil.set("pwdkey_" + rangdom, pwdkey,
                    redisUtil.getDigitkeyimeOut());*/
            return pwdkey.getRundomKeys();
        } catch (Exception e) {
            logger.error("[获取密码键盘digitkeyboard][error:{}",e);
        }
        return "";
    }
    
    /**
     * 获取key图片
     * 
     * @throws Exception
     */
    @RequestMapping(value = "/getKey", method = RequestMethod.GET)
    public void getKey(String key, String rangdom, HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        HttpSession session = request.getSession();
        PwdKeyDto pwdkey = (PwdKeyDto) session.getAttribute("pwdkey_" + rangdom);
        if (pwdkey == null || pwdkey.getImgKeyMaps() == null) {
            logger.error("获取图片[getKey]:未获取到对应的键盘的映射关系");
            throw new Exception();
        }
        Map<String, String> imagekeys = pwdkey.getImgKeyMaps();
        String path = imagekeys.get(key);
        String rootPath = request.getSession().getServletContext()
                .getRealPath("/");
        path = rootPath + path;
        if (path != null && path.length() != 0) {
            try {
                InputStream fis = new FileInputStream(new File(path));
                BufferedInputStream bis = new BufferedInputStream(fis);
                OutputStream fos = response.getOutputStream();
                BufferedOutputStream bos = new BufferedOutputStream(fos);
                String fileName = "image.";
                String[] strs = path.split("\\.");
                fileName = fileName + strs[strs.length - 1];
                setFileDownloadHeader(request, response, fileName);
                int byteRead = 0;
                byte[] buffer = new byte[8192];
                while ((byteRead = bis.read(buffer, 0, 8192)) != -1) {
                    bos.write(buffer, 0, byteRead);
                }
                bos.flush();
                fis.close();
                bis.close();
                fos.close();
                bos.close();
 
            } catch (Exception e) {
                logger.error("获取图片[path:" + path + "])失败:" + e.toString(), e);
            }
        }
    }
    
    /**
     * 
     * @Description: 支付
     * @param pin 交易密码密文
     * @param random 随机码
     * @return
     * 
     */
    @ResponseBody
    @RequestMapping(value = "/pay", method = RequestMethod.POST)
    public String pay(String pin,String random, HttpServletRequest request) {
        try {
            logger.info("[支付(pay)][params:pin=" + pin + ",random="+random+"]");
            if (!isBlank(pin)) {
                StringBuffer sb = new StringBuffer("");
                //PwdKeyDto pwdkey = (PwdKeyDto) redisUtil.get("pwdkey_" + random);
                HttpSession session = request.getSession();
                PwdKeyDto pwdkey = (PwdKeyDto) session.getAttribute("pwdkey_" + random);
                if (pwdkey == null || pwdkey.getValueKeyMaps() == null) {
                    return "密码键盘已失效,请重新输入密码";
                }
                Map<String, String> valuekeys = pwdkey.getValueKeyMaps();
                String[] pins = pin.split(",");
                if (pins.length != 6) {
                    return "交易密码位数不对";
                }
                for (String pinKey : pins) {
                    String val = valuekeys.get(pinKey);
                    if (isBlank(val)) {
                        return "密码键盘已失效,请重新输入密码";
                    }
                    sb.append(val);
                }
                //sb.toString()就是明文交易密码
                System.out.println(sb.toString());
                
                 
                
            }
            return "成功";
        
        } catch (Exception e) {
            logger.error("[支付(pay)][error:{}]",e);
            return "支付异常,请重试!";
        }
 
    }
    
    public static void setFileDownloadHeader(HttpServletRequest request,HttpServletResponse response, String fileName) {
       try {
           String encodedfileName = null;
           String agent = request.getHeader("USER-AGENT");
           
           if(null != agent && -1 != agent.indexOf("MSIE")){//IE
               encodedfileName = java.net.URLEncoder.encode(fileName,"UTF-8");
           }else if(null != agent && -1 != agent.indexOf("Mozilla")){
               encodedfileName = new String (fileName.getBytes("UTF-8"),"iso-8859-1");
           }else{
               encodedfileName = java.net.URLEncoder.encode(fileName,"UTF-8");
           }
           response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedfileName + "\"");
       } catch (UnsupportedEncodingException e) {
           e.printStackTrace();
       }
    }
    
    public static boolean isBlank(final CharSequence cs) {
        int strLen;
        if (cs == null || (strLen = cs.length()) == 0) {
            return true;
        }
        for (int i = 0; i < strLen; i++) {
            if (Character.isWhitespace(cs.charAt(i)) == false) {
                return false;
            }
        }
        return true;
    }
}

4.密码键盘工具类

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import javax.servlet.http.HttpServletRequest;

import com.sanwing.spi.model.PwdKeyDto;

public class PwdKeyUtils {
    private final static Map<String, String> imagesValueMap;
     
    /**
     * 
     * @Description: 获取密码键盘映射关系
     * @param imagesValueMap
     * @return
     * 
     */
    static {
        imagesValueMap = new HashMap<String, String>();
        imagesValueMap.put("0",
                "/media/image/keys/0.png");
        imagesValueMap.put("1",
                "/media/image/keys/1.png");
        imagesValueMap.put("2",
                "/media/image/keys/2.png");
        imagesValueMap.put("3",
                "/media/image/keys/3.png");
        imagesValueMap.put("4",
                "/media/image/keys/4.png");
        imagesValueMap.put("5",
                "/media/image/keys/5.png");
        imagesValueMap.put("6",
                "/media/image/keys/6.png");
        imagesValueMap.put("7",
                "/media/image/keys/7.png");
        imagesValueMap.put("8",
                "/media/image/keys/8.png");
        imagesValueMap.put("9",
                "/media/image/keys/9.png");
    }
 
    public static PwdKeyDto digitkeyboard() {
        List<String> rundomKeys = new ArrayList<String>();// 随机key映射
        Map<String, String> valueKeys = new HashMap<String, String>();// 密文和明文映射
        Map<String, String> imgKeyMaps = new HashMap<String, String>();// 密文和图片映射
        List<String> keys = new ArrayList<String>();
        for (int i = 0; i < 10; i++) {
            keys.add(i + "");
        }
        for (int i = 0; i < 10; i++) {
            Random r = new Random();
            int index = r.nextInt(keys.size());
            String key = keys.get(index);
            keys.remove(index);
            String randomkey = randomKey(24);
            rundomKeys.add(randomkey);
            valueKeys.put(randomkey, key);
            imgKeyMaps.put(randomkey, imagesValueMap.get(key));
        }
        PwdKeyDto dto = new PwdKeyDto(rundomKeys, valueKeys, imgKeyMaps);
        return dto;
    }
 
    /**
     * 
     * @Description:获取动态key
     * @param num
     *            key位数
     * @return
     * 
     */
    public static String randomKey(int num) {
        StringBuffer sb = new StringBuffer("");
        char[] chars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
                'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
                'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
                'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
                'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
                'x', 'y', 'z' };
        for (int i = 0; i < num; i++) {
            int id = (int) Math.ceil(Math.random() * 60);
            sb.append(chars[id]);
        }
        return sb.toString();
    }
 
    /**
     * 
     * @Description:解密pin
     * @param request
     * @param pin
     * @return
     * 
     */
    public static String decryptPinData(HttpServletRequest request,
            String ciphertextpin) throws Exception {
        if (!isBlank(ciphertextpin)) {
            Map<String, String> valuekeys = (Map<String, String>) request
                    .getSession().getAttribute("valuekeys");
            if (valuekeys == null || valuekeys.size() != 10) {
                throw new Exception();
            }
            String[] ciphertextpins = ciphertextpin.split(",");
            StringBuffer sb = new StringBuffer("");
            for (String ctpin : ciphertextpins) {
                sb.append(valuekeys.get(ctpin));
            }
        }
        return null;
    }
    public static boolean isBlank(final CharSequence cs) {
        int strLen;
        if (cs == null || (strLen = cs.length()) == 0) {
            return true;
        }
        for (int i = 0; i < strLen; i++) {
            if (Character.isWhitespace(cs.charAt(i)) == false) {
                return false;
            }
        }
        return true;
    }
}

最后,还有扣下来的按键图片。

 

posted on 2018-11-26 17:05  米德  阅读(726)  评论(1编辑  收藏  举报