zoukankan      html  css  js  c++  java
  • h5对接微信支付分jssdk支付分并调用开启支付分页面

    1、ws.config签名   调用ticket等获取ws.config的签名,下面会调用方法再调用方法时需要再次按照调用方法的签名

    wx.config({
    debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
    appId: '', // 必填,公众号的唯一标识
    timestamp: , // 必填,生成签名的时间戳
    nonceStr: '', // 必填,生成签名的随机串
    signature: '',// 必填,签名
    jsApiList: [] // 必填,需要使用的JS接口列表
    });

    jsapi_ticket

    生成签名之前必须先了解一下jsapi_ticket,jsapi_ticket是公众号用于调用微信JS接口的临时票据。正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。由于获取jsapi_ticket的api调用次数非常有限,频繁刷新jsapi_ticket会导致api调用受限,影响自身业务,开发者必须在自己的服务全局缓存jsapi_ticket 。

    1、获取access_token(有效期7200秒,开发者必须在自己的服务全局缓存access_token):
    http请求方式: GET
    https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=appID&secret=appsecret

    2、用第一步拿到的access_token 采用http GET方式请求获得jsapi_ticket(有效期7200秒,api 调用次数非常有限,频繁刷新api_ticket 会导致api调用受限,影响自身业务,开发者必须在自己的服务全局缓存jsapi_ticket):https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi

    成功返回如下JSON:

    {
    "errcode":0,
    "errmsg":"ok",
    "ticket":"bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA",
    "expires_in":7200
    }
    1
    2
    3
    4
    5
    6


    https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=27_1JoR00pdKD26t0IbR_kPzC5FbCChBLVmoRTkJPQ6b3SbHO2D-IfeaCe1-iBI-kFCjZ58QCSffv9IEVhv0PfmfCsT4ZAEDNcwfO8zYEtB05SOM-mY8pspfKJsz_V8LJnqhMWJO-R9ymZhBj00UWRdACAIKF&type=jsapi


    获得jsapi_ticket之后,就可以生成JS-SDK权限验证的签名了。
    https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx954f1899ef15d2ea&secret=9af198bddb8db015e9113ed7379cbcdf

    微信 JS 接口签名校验工具:

    https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign

    微信支付接口签名校验工具

    https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=20_

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="https://res.wx.qq.com/open/js/jweixin-1.5.0.js"></script>
        <script src="jquery-3.4.1.min.js"></script>
        <script src="vconsole.min.js"></script>
        <script type="text/javascript">
            var vConsole = new VConsole();
            window.vConsole = new window.VConsole();
            var appidG = "";
            var timestampG = "";
            var nonceStrG = "";
            var signatureG = "";
    
            $(function () {
                var signUrl = window.location.href.split('#')[0];
                console.log("signUrl:" + signUrl);
                $.ajax({
                    url: "/index/test",
                    method: "post",
                    data: {
                        signUrl: signUrl
                    },
                    success: function (data) {
                        console.log("data:" + data);
                        var dataJson = JSON.parse(data);
                        // console.log("dataJson.appid:"+dataJson.appid);
                        console.log("wx.config() ---> 接收后台返回的参数");
                        appidG = dataJson.appid;
                        timestampG = dataJson.timestamp;
                        nonceStrG = dataJson.nonceStr;
                        signatureG = dataJson.signature;
                        wx.config({
                            debug: true,
                            appId: dataJson.appid,
                            timestamp: dataJson.timestamp,
                            nonceStr: dataJson.nonceStr,
                            signature: dataJson.signature,
                            jsApiList: ['onMenuShareAppMessage', 'openBusinessView']
                        })
                    }
                });
            });
    
    
            function getLocation() {
                wx.ready(function () {
                    wx.getLocation({
                        type: 'gcj02', // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02'
                        success: function (res) {
                            var latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90
                            var longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。
                            var speed = res.speed; // 速度,以米/每秒计
                            var accuracy = res.accuracy; // 位置精度
                            alert('纬度:' + latitude + '------经度:' + longitude)
                        },
                        fail: function (res) {
                            console.log('未开启定位功能');
                        },
                        cancel: function (res) {
                            console.log('用户拒绝授权获取地理位置');
                        }
                    });
                });
            }
    
    
            /**
             * 跳转微信支付分
             */
            function goToWXScore() {
                console.log("appidG:" + appidG);
                console.log("timestampG:" + timestampG);
                console.log("nonceStrG:" + nonceStrG);
                console.log("signatureG:" + signatureG);
                $.ajax({
                    url: "/index/generateSignature",
                    method: "post",
                    data: {
                        timestamp: timestampG,
                        nonce_str:nonceStrG
                    },
                    success: function (sign) {
                        console.log("sign:" + sign);
                        wx.ready(function () {
                            wx.checkJsApi({
                                jsApiList: ['openBusinessView'], // 需要检测的JS接口列表
                                success: function (res) {
                                    // 以键值对的形式返回,可用的api值true,不可用为false
                                    // 如:{"checkResult":{"openBusinessView":true},"errMsg":"checkJsApi:ok"}
                                    if (res.checkResult.openBusinessView) {
                                        wx.invoke(
                                            'openBusinessView', {
                                                businessType: 'wxpayScoreEnable',
                                                queryString: "mch_id=1518750531&service_id=00004000000000704283351234894845&out_request_no=1234323JKHDFE1243259&timestamp=" + timestampG + "" +
                                                    "&nonce_str=" + nonceStrG + "&sign_type=HMAC-SHA256&sign=" + sign + ""
                                            },
                                            function (res) {
                                                // 从微信侧小程序返回时会执行这个回调函数
                                                if (parseInt(res.err_code) === 0) {
                                                    s
                                                    // 返回成功
                                                } else {
                                                    // 返回失败
                                                }
                                            });
                                    }
                                }
                            });
                        });
                    }
                });
    
    
            }
    
        </script>
    </head>
    <body>
    <div>
        <!--<button id="snap1" onclick="goToWXScore()">goToWXScore</button>-->
        <button id="pay" onclick="goToWXScore()" value="跳转支付分">跳转支付分</button>
        <button id="snap2" onclick="getLocation()" value="获取地区">获取地区</button>
    
        <!--<button id="snap3" onclick="onBridgeReady()">支付</button>-->
    </div>
    </body>
    </html>

    后端接口

    @ResponseBody
        @RequestMapping("/test")
        @Login(required = false)
        public String test(String signUrl) {
            System.out.println("signUrl:"+signUrl);
            //String res = HttpGetMethod.doGet("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx954f1899ef15d2ea&secret=acb8ad2a46765766c7881ea37237c1c7", "utf8", null);
            String jsapi_ticket = "HoagFKDcsGMVCIY2vOjf9kjcHCRqLoF8k77O2dyyZiMTaOwxLTQ9nHU3fa4jfiEj2XW4NsvQG53gZZgVMkQdJA";
            //String url = "http://localhost/h5/weixinexer.html";
            Map<String, String> ret = com.jd.mrd.m.nc.web.utils.Sign.sign(jsapi_ticket, signUrl);
            ret.put("appid","wx954f1899ef15d2ea");
            for (Map.Entry entry : ret.entrySet()) {
                System.out.println(entry.getKey() + ", " + entry.getValue());
            }
            return JSON.toJSONString(ret);
        }
    
        /**
         * 获取签名
         * @param timestamp
         * @param nonce_str
         * @return
         * @throws Exception
         */
        @ResponseBody
        @RequestMapping("/generateSignature")
        @Login(required = false)
        public String generateSignature(String timestamp,String nonce_str) throws Exception {
            HashMap<String, String> stringStringHashMap = new HashMap<String, String>();
            stringStringHashMap.put("mch_id","1518750531");
            stringStringHashMap.put("service_id","00004000000000704283351234894845");
            stringStringHashMap.put("out_request_no","1234323JKHDFE1243259");
            stringStringHashMap.put("timestamp",timestamp);
            stringStringHashMap.put("nonce_str",nonce_str);
            stringStringHashMap.put("sign_type","HMAC-SHA256");
            String signature = WeChatUtils.generateSignature(stringStringHashMap, "acb8ad2a46765766c7881ea37237c1c7", WeChatConstant.SignType.HMACSHA256);
            return signature;
        }
    
    
        @RequestMapping(value = "generateImage")
        @ResponseBody
        @Login(required = false)
        public String generateImage(HttpServletRequest request, String base64) throws IOException {
    
            //String base64=request.getParameter("base64");;
            File directory = new File("");//设定为当前文件夹
            URL resource = IndexController.class.getResource("/");
            String clasFilePath = resource.getPath();
            System.out.println(clasFilePath);//获取标准的路径
            File file = new File(clasFilePath);
            String strParentDirectory = file.getParent();
            System.out.println(strParentDirectory);
            file = new File(strParentDirectory);
            strParentDirectory = file.getParent();
            System.out.println(strParentDirectory);
            strParentDirectory = strParentDirectory + "/h5/img";
            System.out.println(strParentDirectory);
    
            String fileName = CommonUtils.generateUUID() + ".jpg";
            String fileUrl = strParentDirectory + "/" + fileName;
            String imgStr = base64.split(",")[1];
            Base64Utils.GenerateImage(imgStr, fileUrl);
            System.out.println(fileUrl);
            System.out.println(request.getServerName() + "/h5/img/" + fileName);
            return request.getServerName() + "/h5/img/" + fileName;
    
    //        JSONObject json =new JSONObject();
    //        json.put("result",fileUrl);
    //        response.setCharacterEncoding("utf-8");
    //        response.setContentType("application/json;charset=utf-8");
    //        PrintWriter out = null;
    //        out = response.getWriter();
    //        out.write(json.toString());
    //        return json.toJSONString();
        }
    
    
        @RequestMapping(value = "testPost")
        @ResponseBody
        @Login(required = false)
        public String testPost(HttpServletRequest request, String base64) {
    
    
    
            return "";
    
        }
    package com.jd.lestore.payment.common.utils;
    
    import com.jd.lestore.payment.common.constant.WeChatConstant;
    import com.jd.lestore.payment.common.constant.WeChatConstant.SignType;
    import org.w3c.dom.Node;
    import org.w3c.dom.NodeList;
    
    import javax.crypto.Mac;
    import javax.crypto.spec.SecretKeySpec;
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.transform.OutputKeys;
    import javax.xml.transform.Transformer;
    import javax.xml.transform.TransformerFactory;
    import javax.xml.transform.dom.DOMSource;
    import javax.xml.transform.stream.StreamResult;
    import java.io.ByteArrayInputStream;
    import java.io.InputStream;
    import java.io.StringWriter;
    import java.security.MessageDigest;
    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Set;
    
    public class WeChatUtils {
    
        /**
         * 生成新的请求序列号
         *
         * @return
         */
        public static Integer getNewRequestSerial() {
            String timestamp = String.valueOf( System.currentTimeMillis()/1000 );
            return Integer.valueOf(timestamp).intValue();
        }
    
        public static String generateSignature(final Map<String, String> data, String key) throws Exception {
            return generateSignature(data, key, SignType.MD5);
        }
    
        public static String generateHMACSHA256Signature(final Map<String, String> data, String key) throws Exception {
            return generateSignature(data, key, SignType.HMACSHA256);
        }
    
    
        /**
         * 生成签名
         *
         * @param data
         * @param key
         * @return
         * @throws Exception 规则
         *                   第一步,设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA。
         *                   <p>
         *                   特别注意以下重要规则:
         *                   <p>
         *                   ◆ 参数名ASCII码从小到大排序(字典序);
         *                   ◆ 如果参数的值为空不参与签名;
         *                   ◆ 参数名区分大小写;
         *                   ◆ 验证调用返回或微信主动通知签名时,传送的sign参数不参与签名,将生成的签名与该sign值作校验。
         *                   ◆ 微信接口可能增加字段,验证签名时必须支持增加的扩展字段
         *                   <p>
         *                   第二步,在stringA最后拼接上key得到stringSignTemp字符串,并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值signValue。
         */
        public static String generateSignature(final Map<String, String> data, String key, SignType signType) throws Exception {
    
            Set<String> keySet = data.keySet();
            String[] keyArray = keySet.toArray(new String[keySet.size()]);
            Arrays.sort(keyArray);
            StringBuilder sb = new StringBuilder();
            for (String k : keyArray) {
                if (k.equals(WeChatConstant.FIELD_SIGN)) {
                    continue;
                }
                if (data.get(k).trim().length() > 0) // 参数值为空,则不参与签名
                    sb.append(k).append("=").append(data.get(k).trim()).append("&");
            }
            sb.append("key=").append(key);
    
            if (SignType.MD5.equals(signType)) {
                return MD5(sb.toString()).toUpperCase();
            } else if (SignType.HMACSHA256.equals(signType)) {
                System.out.println("HMACSHA256 original text: " + sb.toString());
                return HMACSHA256(sb.toString(), key);
            } else {
                throw new Exception(String.format("Invalid sign_type: %s", signType));
            }
        }
    
        /**
         * 生成 MD5
         *
         * @param data 待处理数据
         * @return MD5结果
         */
        public static String MD5(String data) throws Exception {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] array = md.digest(data.getBytes("UTF-8"));
            StringBuilder sb = new StringBuilder();
            for (byte item : array) {
                sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
            }
            return sb.toString().toUpperCase();
        }
    
        /**
         * 生成 HMACSHA256
         *
         * @param data 待处理数据
         * @param key  密钥
         * @return 加密结果
         * @throws Exception
         */
        public static String HMACSHA256(String data, String key) throws Exception {
            Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
            SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
            sha256_HMAC.init(secret_key);
            byte[] array = sha256_HMAC.doFinal(data.getBytes("UTF-8"));
            StringBuilder sb = new StringBuilder();
            for (byte item : array) {
                sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
            }
            return sb.toString().toUpperCase();
        }
    
        /**
         * 获取当前时间戳,单位秒
         *
         * @return
         */
        public static long getCurrentTimestamp() {
            return System.currentTimeMillis() / 1000;
        }
    
        /**
         * 获取当前时间戳,单位毫秒
         *
         * @return
         */
        public static long getCurrentTimestampMs() {
            return System.currentTimeMillis();
        }
    
        /**
         * XML格式字符串转换为Map
         *
         * @param strXML XML字符串
         * @return XML数据转换后的Map
         * @throws Exception
         */
        public static Map<String, String> xmlToMap(String strXML) throws Exception {
            InputStream stream = null;
            try {
                Map<String, String> data = new HashMap<String, String>();
                DocumentBuilderFactory documentBuilderFactory = setWechatPaySafeCode();
                DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
                stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));
                org.w3c.dom.Document doc = documentBuilder.parse(stream);
                doc.getDocumentElement().normalize();
                NodeList nodeList = doc.getDocumentElement().getChildNodes();
                for (int idx = 0; idx < nodeList.getLength(); ++idx) {
                    Node node = nodeList.item(idx);
                    if (node.getNodeType() == Node.ELEMENT_NODE) {
                        org.w3c.dom.Element element = (org.w3c.dom.Element) node;
                        data.put(element.getNodeName(), element.getTextContent());
                    }
                }
                return data;
            } finally {
                try {
                    stream.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
    
        }
    
        private static DocumentBuilderFactory setWechatPaySafeCode( ) {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            // 禁 用 DOCTYPE
            try{
                dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
                //该 feature 的作用是配置是否包含外部的参数,包括外部 DTD 子集,设置false 禁用参数实体
                dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
                //该 feature 的功能指是否包含外部生成的实体,设置 false 禁用外部实体
                dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
                dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
                dbf.setXIncludeAware(false);
                dbf.setExpandEntityReferences(false);
            }catch ( Exception e ){
                e.printStackTrace();
            }
            return dbf;
        }
    
        /**
         * XML格式字符串转换为Map
         *
         * @param strXML XML字符串
         * @return XML数据转换后的Map
         * @throws Exception
         */
        public static Map<String, String> xmlClildToMap(String strXML) throws Exception {
            InputStream stream = null;
            try {
                Map<String, String> data = new HashMap<String, String>();
                DocumentBuilderFactory documentBuilderFactory = setWechatPaySafeCode();
                DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
                stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));
                org.w3c.dom.Document doc = documentBuilder.parse(stream);
                doc.getDocumentElement().normalize();
                NodeList nodeList = doc.getDocumentElement().getChildNodes();
                for (int idx = 0; idx < nodeList.getLength(); ++idx) {
                    Node node = nodeList.item(idx);
                    if (node.getNodeType() == Node.ELEMENT_NODE) {
                        org.w3c.dom.Element element = (org.w3c.dom.Element) node;
                        if(element.hasChildNodes()){//对于三级子项处理
                            for(int i = 0 ; i < element.getChildNodes().getLength();i++){
                                Node nodeChild = element.getChildNodes().item(i);
                                data.put(nodeChild.getNodeName(),nodeChild.getTextContent());
                            }
                        }else {
                            data.put(element.getNodeName(), element.getTextContent());
                        }
                    }
                }
                return data;
            } finally {
                try {
                    stream.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
    
        }
    
        /**
         * 将Map转换为XML格式的字符串
         *
         * @param data Map类型数据
         * @return XML格式的字符串
         * @throws Exception
         */
        public static String mapToXml(Map<String, String> data) throws Exception {
            DocumentBuilderFactory documentBuilderFactory = setWechatPaySafeCode();
            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
            org.w3c.dom.Document document = documentBuilder.newDocument();
            org.w3c.dom.Element root = document.createElement("xml");
            document.appendChild(root);
            for (String key : data.keySet()) {
                String value = data.get(key);
                if (value == null) {
                    value = "";
                }
                value = value.trim();
                org.w3c.dom.Element filed = document.createElement(key);
                filed.appendChild(document.createTextNode(value));
                root.appendChild(filed);
            }
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer transformer = tf.newTransformer();
            DOMSource source = new DOMSource(document);
            transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            StringWriter writer = new StringWriter();
            StreamResult result = new StreamResult(writer);
            transformer.transform(source, result);
            String output = writer.getBuffer().toString(); //.replaceAll("
    |
    ", "");
            try {
                writer.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            return output;
        }
    
        /**
         * 将Map转换为XML格式的字符串
         *
         * @param data Map类型数据
         * @return XML格式的字符串
         * @throws Exception
         */
        public static String mapToXmlROOT(Map<String, String> data,String xmlRoot) throws Exception {
            DocumentBuilderFactory documentBuilderFactory = setWechatPaySafeCode();
            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
            org.w3c.dom.Document document = documentBuilder.newDocument();
            document.setXmlStandalone(true);
            org.w3c.dom.Element root = document.createElement(xmlRoot);
            document.appendChild(root);
            for (String key : data.keySet()) {
                String value = data.get(key);
                if (value == null) {
                    value = "";
                }
                value = value.trim();
                org.w3c.dom.Element filed = document.createElement(key);
                filed.appendChild(document.createTextNode(value));
                root.appendChild(filed);
            }
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer transformer = tf.newTransformer();
            DOMSource source = new DOMSource(document);
            transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            StringWriter writer = new StringWriter();
            StreamResult result = new StreamResult(writer);
            transformer.transform(source, result);
            String output = writer.getBuffer().toString(); //.replaceAll("
    |
    ", "");
            try {
                writer.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            return output;
        }
    
    }
  • 相关阅读:
    iOS----------上传遇到的问题
    iOS----------面试常问
    iOS----------Mac维修预约-如何找到电脑维修单
    iOS----------has copy command from(bug修复)
    关于powershell的个人总结
    关于powershell 的一些练习
    域控制总结
    Windows 常用命令
    注册表安全配置
    注册表危险操作
  • 原文地址:https://www.cnblogs.com/honghong75042/p/11805683.html
Copyright © 2011-2022 走看看