微信开发h5页面_微信公众号开发,写好的h5页面怎么和微信对接 - CSDN
  • 微信H5开发(一)

    2018-06-16 09:17:59
    H5开发,一般是指移动端的页面开发。移动端可分为app和普通浏览页面。从嵌入的环境来归类:可以分为app、微信H5及手机浏览器里面打开的页面。 以前粗略的涉略过h5开发的一些知识,感觉H5并不是很难。在这半年内,...

    H5开发,一般是指移动端的页面开发。移动端可分为app和普通浏览页面。从嵌入的环境来归类:可以分为app、微信H5及手机浏览器里面打开的页面。
    以前粗略的涉略过h5开发的一些知识,感觉H5并不是很难。在这半年内,接手并完成了两个微信H5项目(一期)的过程中,发觉h5开发过程中需要注意的细节有很多,碰到的兼容问题也有一些。在这里我先总结下,H5项目的一些思路及碰到的难点和解决方法。
    在刚接到H5项目时,因为前端有很多框架,所有需要先确定使用什么技术。对于用vue和还是react,考虑到项目的规划时间和对框架的熟练度。这两个H5的项目我都用react来完成。
    webpack+react+react-dom+react-route+redux+axios +Java+mysql ,一个完整的技术栈。
    比较基础的前端开发环境搭建(webpack+react…),各位可以参考我前面写的文章。由于webpack的技术更新及部分代码优化,基础配置里面有些东西需要稍微调整下。
    比如:
    1. nodeJs 的指令更改
    以前安装一个模块的指令:

    npm install url-loader file-loader --save-dev

    现在更改为:

    npm install url-loader file-loader -S -D
    1. Happypack 插件将不再支持cache
    new Happypack({
        id:"happybabel",
        loaders:['babel-loader'],
        threadPool:happypackThreadPool,
        cache:true,   **//需要删除这句cache的配置**
        verbose:true
    })
    1. 在webpack plugins 里面添加配置使用(生产)环境的插件
    new webpack.DefinePlugin({
      "process.env": { 
         NODE_ENV: JSON.stringify("production") 
       }
    })

    4.为了降低最后打包的压缩体积,把devtool:’eval-soure-map’ 改成 devtool:false。
    配置css-loader将css文件进行压缩:

     {
        test:/\.css$/,        
        use:ExtractTextPlugin.extract({//使用ExtractTextPlugin 插件
            fallback:"style-loader",//用于开发环境
            use:[{loader:"css-loader",options:{minimize:true}},"postcss-loader"]
        }),
    
    }

    5.简化redux 和action的代码
    以前旧代码请参考:https://blog.csdn.net/cbboke31/article/details/77046839

      redux 以前的代码:
       const reducer = (state = defaultState, action) => {     
        switch (action.type) {//通过action的返回值来选择更新哪个state的状态
            case 'AlterMain':
                return  Object.assign({},state,{ mainText:action.payload});
            case 'AlterTopic':
                return  Object.assign({},state,{ topicText:action.payload});
            default:
                return state;
        }
    };
    精简为:
    const reducer = (state = defaultState, action) => {
        if (action.type.indexOf("@@redux") != -1) {
            return state;
        } else {
            var ob = {};
            ob[action.type] = action.payload;
            return Object.assign({}, state, ob);
        }
    };
    action 旧代码:
    const actions = {
     changeText:function(num){
         console.log("调用actions");
          switch(num){
          case 1:
          return {type:'AlterMain',payload:"mainContainer had been changed"};
          case 2:
           return {type:'AlterTopic',payload:"topicContainer had been changed"};
           default:
           return action;
       }
    }
    };
    export default actions;
    
    优化为:
    const actions = {
     changeInfo:(infotype,string)=>{   
        if(infotype == ""){
          return action;
        }else{
          return {type:infotype,payload:string};
        }
    },
    };
    export default actions;

    现在转入主要内容。
    h5 开发,第一个面临的难题是像素问题,移动端的像素有物理像素及逻辑像素的说法,同一个像素在不同的手机,显示的大小都不一致。而且PC端浏览器的最小像素为1px,但手机端却可以显示出0.5px甚至可能更小。
    一、这个像素问题要怎么解决?
    h5 里面有个视口(viewport)这个标签。这个视口标签就设定逻辑像素和物理像素的比值。initial-scale=1表示1倍的关系。user-scalabe=no,表示不允许用户更改当前页面的比例。

    根据网上推荐的方案,通过 docEl.clientWidth 获取移动端网页的可见区域的宽度,把可见区域分成320小分,然后规定根字体占10(pc端默认字号为10px)小分,单位取px。

    (function (doc, win) {
        var docEl = doc.documentElement,
            resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
        recalc = function () {
            var clientWidth = docEl.clientWidth;
            if (!clientWidth) return;
            docEl.style.fontSize = 10 * (clientWidth / 320) + 'px';       
        }; 
        if (!doc.addEventListener) return;
        win.addEventListener(resizeEvt, recalc, false);
        doc.addEventListener('DOMContentLoaded', recalc, false);
    })(document, window);

    上面这个js,在react的app..js 引入。当代码成功运行,可以看到根字体的大小。
    这里写图片描述

    当根字体确定下来之后,后面所有设计到尺寸的地方都以跟父元素的百分比或者用以根字体的比例关系设定(以rem)。如果用rem做单位,需要所有指定尺寸的地方都需要 用UI图纸标注的尺寸除以根字体大小。如果每次尺寸都用人工转换,这个将会是个很浪费时间一件事。为了解决这个费力不讨好的问题,我启用了less。less只需要在整个文档前面设定一个根字体大小的变量(比如:@rootFontSize:23.4375),后面所有涉及到尺寸的地方直接除以这个变量就好。例子:设置div 的高度 height:44rem/@rootFontSize。 这样div设定的高度就等同于图纸(设计尺寸比例1:1的关系)上的44px。

    二、 Object.assign() 兼容问题
    以前碰到一个这样的现象:引入redux成功后,项目在pc端谷歌 浏览器上调试页面可以正常渲染。但如果在安卓模拟机和实体手机的环境下,页面就变成了空白。后来经过排查,发现object.assign 存在移动端兼容性问题。
    这个兼容问题怎么解决?
    网上有现成的方案:引入polyfill 文件,重新定义object.assign。

     if (typeof Object.assign != 'function') {
        // Must be writable: true, enumerable: false, configurable: true
        Object.defineProperty(Object, "assign", {
          value: function assign(target, varArgs) { // .length of function is 2
            'use strict';
            if (target == null) { // TypeError if undefined or null
              throw new TypeError('Cannot convert undefined or null to object');
            }
    
            var to = Object(target);
    
            for (var index = 1; index < arguments.length; index++) {
              var nextSource = arguments[index];
    
              if (nextSource != null) { // Skip over if undefined or null
                for (var nextKey in nextSource) {
                  // Avoid bugs when hasOwnProperty is shadowed
                  if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
                    to[nextKey] = nextSource[nextKey];
                  }
                }
              }
            }
            return to;
          },
          writable: true,
          configurable: true
        });
      }

    这篇就先到这。解决了移动端刚开始碰到的两个问题,处理好这个两个问题,移动端页面和pc页面开发的区别就不会很大了。
    下一篇讲微信相关的知识及使用微信模块碰到的一些棘手的问题。

    展开全文
  • 利用H5开发微信公众号 一、 首先授权配置 公众号设置 --》功能设置 设置业务域名! 1 2 3   这里的MP_verify_w7tdZrafqhkK9Mcj.txt文件,需要放到你项目的根目录下,例子:你的项目war包叫 test.war ,里面...

    来源:https://blog.csdn.net/chou342175867/article/details/62429354

    利用H5开发微信公众号

    一、 首先授权配置

     公众号设置 --》功能设置
     设置业务域名!
    
    • 1
    • 2
    • 3

    自定义菜单 
    这里的MP_verify_w7tdZrafqhkK9Mcj.txt文件,需要放到你项目的根目录下,例子:你的项目war包叫 test.war ,里面包含了src,WEB-INFO两个文件夹,则把MP_verify_w7tdZrafqhkK9Mcj.txt放到这两个文件夹的同级目录下;即现在test.war下有两个文件夹一个txt文件:src,WEB-INFO,MP_verify_w7tdZrafqhkK9Mcj.txt. 
    后面就需要配置JS接口安全域名和网页授权域名了,最好和业务域名配置为一样就好了。 
    二、开发中的配置 
    在开发目录下的基本配置中进行配置。 
    基本配置–》开发者ID–》AppID(应用ID),AppSecret(应用密钥); 
    基本配置–》微信开放平台账号绑定 
    这里需要绑定微信开放平台,若不绑定,在获取用户信息的时候就只能获取到用户的openId,不能获取到unionId. 
    自定义菜单
    注意:定义菜单的时候有讲究了, 
    如果你想在用户点这个菜单的时候就拿到用户的微信基本信息(性别,昵称,openId,unionId),这里直接可以配置成为授权链接,授权链接回调url直接写成你后台的一个接口地址,然后由这个接口来跳转到其它页面. 
    例子:H5授权的链接: 
    http://open.weixin.qq.com/connect/oauth2/authorize?appid=xxxxxxxxx&redirect_uri=http://xxxx.com/test/login&response_type=code&scope=snsapi_userinfo&state=xxx&connect_redirect=1#wechat_redirect 
    微信回调的url是一个接口地址:http://xxxx.com/test/login,不能回调网页,因为存在跨域错误。 
    state的值是可以自定义的。 
    这里的scope是用的snsapi_userinfo,这样可以直接在后台拿到用户信息。 
    微信回调这个接口的时候会把code和state的值返回,接口就可以通过code去拿用户的信息了。 
    若要用code去拿用户的信息,又会去做一堆事情,这些事情确实麻烦;推荐直接使用第三方的jar包,一步就拿到了。 
    推荐的jar包:weixin-java-mp-2.5.0.jar,weixin-java-common-2.5.0.jar; 
    maven地址

        <dependency>
          <groupId>com.github.binarywang</groupId>
          <artifactId>weixin-java-mp</artifactId>
          <version>2.5.0</version>
        </dependency>
    • 1
    • 2
    • 3
    • 4
    • 5
     在做微信支付的时候有可能会用到xstream的包,有需要也拿去
     xstream-1.4.7.jar,xxp3_min-1.1.4.jar,xmlpull-1.1.3.1.jar
     maven地址 
    
    • 1
    • 2
    • 3
    • 4
        <dependency>
            <groupId>com.thoughtworks.xstream</groupId>
            <artifactId>xstream</artifactId>
            <version>1.4.7</version>
        </dependency>
        <dependency>
            <groupId>xpp3</groupId>
            <artifactId>xpp3</artifactId>
            <version>1.1.4c</version>
        </dependency>
        <dependency>
            <groupId>xmlpull</groupId>
            <artifactId>xmlpull</artifactId>
            <version>1.1.3.1</version>
        </dependency>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    这里说下weixin-java-mp-2.5.0.jar的使用方法, 
    1.weixin-java-mp-2.5.0.jar里面最重要的类是 
    WxMpInMemoryConfigStorage和WxMpService; 
    WxMpInMemoryConfigStorage是用来存微信公众号的基本信息的, 
    在Spring+SpringMvc中的使用方法例子:

    @Configuration
    @PropertySource(
            value={"classpath:wxProperties.properties"},
            ignoreResourceNotFound = true)
    //@DependsOn("propertyPlaceholderConfigurer")
    public class WeixinConfig {
        //直接获取资源文件中的配置的值
        @Value("${wxProperties.appid}")
        private String appid;//appId
    
        @Value("${wxProperties.appsecret}")
        private String appsecret;//Appsecret
    
        @Value("${wxProperties.token}")
        private String token;//Token
    
        @Value("${wxProperties.aeskey}")
        private String aesKey;//aeskey,有就填,没有就不填
    
        @Value("${wxProperties.partener_id}")
        private String partenerId;//商户号
    
        @Value("${wxProperties.partener_key}")
        private String partenerKey;//商户秘钥
    
        @Value("${wxProperties.notify_url}")
        private String notifyUrl;//支付后台通知接口地址
    
        @Bean
        public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
           PropertySourcesPlaceholderConfigurer ppc = new PropertySourcesPlaceholderConfigurer();
           ppc.setIgnoreUnresolvablePlaceholders(true);
           return ppc;
        }
    
        @Bean
        public WxMpConfigStorage wxMpConfigStorage() {
            WxMpInMemoryConfigStorage configStorage = new WxMpInMemoryConfigStorage();
            configStorage.setAppId(this.appid);
            configStorage.setSecret(this.appsecret);
            configStorage.setToken(this.token);
            configStorage.setAesKey(this.aesKey);
            configStorage.setPartnerId(this.partenerId);
            configStorage.setPartnerKey(this.partenerKey);
            configStorage.setNotifyURL(this.notifyUrl);
            return configStorage;
        }
    
        @Bean
        public WxMpService wxMpService() {
            WxMpService wxMpService = new WxMpServiceImpl();
            wxMpService.setWxMpConfigStorage(wxMpConfigStorage());
            return wxMpService;
        }
    
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    这里是配置微信公众号的基本信息,其它地方要使用就直接使用:

        @Autowired
        protected WxMpService wxMpService;
    • 1
    • 2

    2.获取微信用户基本信息示例代码:

    WxMpOAuth2AccessToken accessToken;
    WxMpUser wxMpUser = null;
    accessToken = this.wxMpService.oauth2getAccessToken(code);
    wxMpUser = this.wxMpService.getUserService().userInfo(accessToken.getOpenId(), null);
    //用户的基本信息就在wxMpUser中了,需要的就拿去用了。(注意:微信用户的性别:0:未知,1:男 2:女)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3.H5若要使用微信封装好的js,则需要一些基本的配置信息,完全可以从后天台获取然后返回,示例代码:

     public StatusResult<Map<String, Object>> createJsapiSignature(String url) {
            Map<String, Object> result = new HashMap<String, Object>();
            try {
                WxJsapiSignature  wxJsapiSignature = wxMpService.createJsapiSignature(url);
                String getJsapiTicket = wxMpService.getJsapiTicket();
                result.put("wxJsapiSignature", wxJsapiSignature);
                return StatusResult.success(result, "");
            } catch (WxErrorException e) {
                return StatusResult.failed("未知错误出现", result);
            }
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    这里的url是H5用js代码获取的:

    var url = location.href.split('#')[0];
    • 1

    4.公众号支付 
    流程: 
    页面发起–>后台下单后返回前端所需要的参数–>页面发起支付–>用户输入密码付款成功–>微信回调后台通知接口–>业务处理完成 
    H5页面发起支付: 
    微信公众号的页面支付首先要配置微信公众号: 
    微信支付–>开发配置–>支付授权目录(正式、测试的目录必须要不一样,否则有你好看的,) 
    注意:设置授权目录的时候必须要精确到需要支付页面的目录文件夹; 
    例子:需要支付的H5页面 http://xxxxx.com/test/html/pay/pay.html 
    则授权目录配置为 http://xxxxx.com/test/html/pay/ 
    配置完成后就可以发起下单了, 
    后台下单代码示例:

    public StatusResult<Map<String, String>> getJSSDKPayInfo(HttpServletResponse response,
                                    HttpServletRequest request) {
            StatusResult<Map<String, String>> result = null;
            String spbill_create_ip = request.getRemoteAddr();//订单生成的机器 IP
            Map<String, String> map = new HashMap<String, String>();    
            WxMpConfigStorage wx= wxMpService.getWxMpConfigStorage();
            WxPayUnifiedOrderRequest prepayInfo = new WxPayUnifiedOrderRequest();
            //TODO change all request parameters to a VO class
            prepayInfo.setOpenid("openId");        
            prepayInfo.setOutTradeNo("out_trade_no");//设置订单商户号
            int total_fee = 0.01 * 100;
            total_fee = 1;
            prepayInfo.setTotalFee(Integer.valueOf(total_fee));//设置支付金额 单位为分 
            prepayInfo.setBody("xxxxx");//支付的内容简介
            prepayInfo.setTradeType("JSAPI");//渠道:公众号支付
            prepayInfo.setSpbillCreateIp(spbill_create_ip);//终端ip 
            //TODO(user) 填写通知回调地址
            prepayInfo.setNotifyURL(wx.getNotifyURL());
            try {
                两种下单方式,如果报错请先仔细检查微信配置的各种参数
                //WxPayUnifiedOrderResult  wxPayUnifiedOrderResult= wxMpService.getPayService().unifiedOrder(prepayInfo);
                Map<String, String> payInfo = this.wxMpService.getPayService().getPayInfo(prepayInfo);
                if(payInfo != null){
                    //业务代码
                }
                result = StatusResult.success(payInfo);
                return result;
            } catch (WxErrorException e) {
                log.error(e.getError().toString());
                map.put("error", e.getError().toString());
                return StatusResult.failed("微信下单失败",map);
            }
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    H5页面支付js代码(需要引入微信js哈):

    function callPay(){
                if (typeof WeixinJSBridge == "undefined"){
                   if( document.addEventListener ){
                       document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
                   }else if (document.attachEvent){
                       document.attachEvent('WeixinJSBridgeReady', onBridgeReady); 
                       document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
                   }
                }else{
                   onBridgeReady();
                }       
            }
            function onBridgeReady(){
                   WeixinJSBridge.invoke(
                       'getBrandWCPayRequest', {
                           "appId":appId,     //公众号名称,由商户传入     
                           "timeStamp":timeStamp,         //时间戳,自1970年以来的秒数     
                           "nonceStr":nonceStr, //随机串     
                           "package":package,     
                           "signType":"MD5",         //微信签名方式:     
                           "paySign":paySign //微信签名 
                       },
                       function(res){     
                           if (res.err_msg == "get_brand_wcpay_request:ok") {    
                                alert("微信支付成功!");
                            } else if (res.err_msg == "get_brand_wcpay_request:cancel") {    
                                alert("用户取消支付!");
                            } else {  
                                 alert("支付失败!");
                            }     // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回    ok,但并不保证它绝对可靠。 
                       }
                   ); 
            }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    微信回调后台通知接口代码示例:

     public void getJSSDKCallbackData(HttpServletRequest request,
                HttpServletResponse response) {
            try {
                synchronized (this) {
                    Map<String, String> kvm = XMLUtil.parseRequestXmlToMap(request);
                    System.out.println("微信通知返回结果:\t"+kvm.toString());
                    WxPayOrderQueryResult  wxPayOrderQueryResult = wxMpService.getPayService().queryOrder("", kvm.get("out_trade_no"));//用订单号去查询订单状态,冗余代码可看可删
    //                if (this.wxMpService.getPayService().checkSign(kvm,  kvm.get("sign"))) {
                    System.out.println("查询订单返回结果:\t"+wxPayOrderQueryResult.getTradeState());
                    if ("SUCCESS".equals(wxPayOrderQueryResult.getTradeState())) {
                        if (kvm.get("result_code").equals("SUCCESS")) {
                            //TODO(user) 微信服务器通知此回调接口支付成功后,通知给业务系统做处理
                            log.info("out_trade_no: " + kvm.get("out_trade_no") + " pay SUCCESS!");
                            String out_trade_no = kvm.get("out_trade_no"); //支付订单号,接下来写业务代码                       
                                    }
                                }
                            } 
                            log.info("已经支付的订单详情\t"+aleadyPayOrder);
                            response.getWriter().write("<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[ok]]></return_msg></xml>");
                        } else {
                            log.error("out_trade_no: "
                                + kvm.get("out_trade_no") + " result_code is FAIL");
                            response.getWriter().write(
                                "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[result_code is FAIL]]></return_msg></xml>");
                        }
                    } else {
                        response.getWriter().write(
                            "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[check signature FAIL]]></return_msg></xml>");
                        log.error("out_trade_no: " + kvm.get("out_trade_no")
                            + " check signature FAIL");
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    到此为止公众号支付完成。

    三、微信js中接口使用 
    分享等很常见的,需要初始化微信的js,需要利用到上面写的createJsapiSignature后台接口。 
    公众号的分享给朋友、朋友圈、QQ空间等方法在微信js中是可以直接调用的,分享的内容可以自己改变的,但是分享出去的按钮只能是微信右上角的分享,开发者不能自定义分享按钮。。。这一点让人非常不爽。 
    H5页面js的代码示例:

    引入微信的js,然后初始化,然后微信会自动执行wx.ready中的方法

    wx.config({
        debug: false,   //开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。  
        appId: appId,   //必填,公众号的唯一标识
        timestamp: timestamp,   // 必填,生成签名的时间戳 
        nonceStr: nonceStr,   //必填,生成签名的随机串 
        signature: signature,   // 必填,签名
        jsApiList: [//需要多少接口就写多少接口
            'checkJsApi',//判断当前客户端是否支持指定JS接口
            'onMenuShareAppMessage'//获取“分享给朋友”按钮点击状态及自定义分享内容接口
        ] //必填,需要使用的JS接口列表,所有JS接口列表 
    }); 
    wx.ready(function () {  
        var title = "xxxx";
        var desc = "xxxx";
        var imgUrl = "http://xxx.com/test/picture/xxxxx.png";
        wx.onMenuShareAppMessage({
            title: title, // 分享标题
            desc: desc, // 分享描述
            link: url, // 分享链接,h5网页的地址或者其它
            imgUrl: imgUrl,
            trigger: function(res) {
                alert('用户点击发送给朋友');
            },
            success: function(res) {
                alert('已分享');
            },
            cancel: function(res) {
                alert('已取消');
            },
            fail: function(res) {
                alert(JSON.stringify(res));
            }
        });
    }); 
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    调用微信js中的方法流程: 
    初始化config–>执行wx.ready 
    开发者需要更多的功能就依照葫芦画瓢了,或者去微信js sdk文档去copy方法了。

    让人不愉快的事情又发生了,微信在4月29日开始限制自定义分享的链接啦,必须要是安全域名下的链接才可以分享。 
    详情请看: 
    JSSDK自定义分享接口的策略调整 
    这样导致不能直接分享自己想要的链接了,但是解决方法还是有的: 
    在你的域名下新建一个H5页面,在这个H5页面的js代码中做一个跳转就好啦(但是如果你分享出去的是支付页面,那多半是支付不了地)!

    四、处理微信直接可以分享页面问题 
    有时候业务需要不能把当前的页面分享出去,但是微信自带的分享、复制链接按钮是可以在任何页面拿到当前页面的地址,如果别人点击就会进入。为了避免这个情况发生,有几种处理方法: 
    1.后端足够强大,页面跳转完全由后端完成,在加入了权限验证的情况下就不怕这个的,后端会拦截请求验证,验证不过就跳指定的error页面就好。 
    2.前端做验证 
    jsp可以用session,判断session中的一个全局参数即可。 
    H5可以使用cookie,在项目的开始页写入cookie,在js中写一个验证方法,每个页面都调用这个验证方法进行验证,虽然有冗余代码,但是这个是可以实现地,简单粗暴,速度快。 
    设置cookie的方法:

    jquery(function() {
        var expiresDate= new Date();
        expiresDate.setTime(expiresDate.getTime() + (30 * 60 * 1000));//半小时
        jquery.cookie("openId",'${openId}', {
              path : '/',//cookie的作用域为根目录,任何页面都是有效的
              expires : expiresDate
             });//cookie里面保存openId
    });
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    然后在js中写一个方法每个页面都调用判断。

    展开全文
  • 刚入门前端的时候写过很多的微信H5页面,时隔多年感觉应该是手到擒来,不曾想竟很是费了一些功夫。现在把本次开发过程中遇到的问题以及我是如何解决的,做个记录。防止自己以后再去解决解决过的问题。 一、微信网页...

    写在前面

    刚入门前端的时候写过很多的微信H5页面,时隔多年感觉应该是手到擒来,不曾想竟很是费了一些功夫。现在把本次开发过程中遇到的问题以及我是如何解决的,做个记录。防止自己以后再去解决解决过的问题。

    一、微信网页授权

     

    网页授权流程分为四步,这里只说前端需要做的,其中的第一步:跳转授权页面获取code。 这里分享下我的授权逻辑(下图),它有两个优点:

     

    1. 授权跳转在dom渲染之前,体验会好一些;

       

    2. 本地存储了openId,前后端均不用频繁的与微信服务器交互。

       

     

     

     

    二、微信jssdk授权

     

    如果你页面中有用到分享、上传图片、微信支付等功能,那么需要先进行js-sdk授权。我这边封装成了2个方法:initConfig和setShare,方便在路由/页面切换的时候重复调用。

    /main.js
    import wxsdk from './config/wxsdk.js' //该模块提供initConfig和setShare方法,具体代码太长见github
    Vue.prototype.wxsdk = wxsdk;//挂载到全局
    
    //使用
    created() {
      this.wxsdk.initConfig(location.href.split("#")[0], () => {
        this.wxsdk.setShare(this.user.openId);
       });
    }

    三、webpack-dev-server解决跨域

    讲真的所有跨域解决方案都必须有服务端的参与,诚然这个问题是浏览器抛出的,但让前端去解决真的很冤。下面两个配置让你永远告别跨域烦恼。本地开发用webpack-dev-server,测试生产环境用nginx。

    //接口根路径http://47.105.59.***:9090/zt-wx
    //以vue-cli搭建的项目config举例 config/index.js
     dev: {
       proxyTable: {
         '/zt-wx': {
           target: 'http://47.105.59.***:9090',  //目标接口域名
           changeOrigin: true  //是否跨域
         }
       },
     }
    //实际发起请求时的url
    this.http.get(`/zt-wx/api/wx/info`).then(); //http是我自己对axios的再封装  
    
    //nginx代理配置
    server {
       location /zt-wx {
       proxy_pass http://47.105.59.***:9090;
       }
    }

    四、ios初次加载白屏、跳转白屏

     

    问题现象: ios页面初次加载白屏,刷新后正常,但切换到其他页面再后退,又会白屏。
    问题原因:在ios机器上使用webview开发Vue项目时候,go history(-1),无法将body的高度拉掉,使得内容被遮住了。
    解决办法:html,body都是100%,#app撑起了父元素的告诉,但是浏览器默认的滚动scroll并不是#app,而是body,某些因素,造成返回history 后,无法复原(ios 的锅),为此,我们将#app进行了绝对定位,并让它重新成为 scroll 的对象,从而解决问题。

    #app {
     position: absolute;
     top: 0;
     left: 0;
     width: 100%;
     height: 100%;
     overflow: scroll;
     -webkit-overflow-scrolling: touch;
    }

    五、ios路由/跳转页面后分享失效

     

    问题现象:ios微信路由到另一个页面选择图片OK,但分享失效,刷新这个页面分享就正常了。
    已累计尝试解决超过8小时,至今未果。

     

    六、上传图片报错:处理异常

     

    这个报错甚是诡异,因为前端和后端代码均没有“处理异常”这4个字。本来想甩锅给微信不管了的,但随后在做限制上传图片大小功能的时候阴差阳错的给解决了。
    问题原因:后端tomcat服务默认设置表单提交数据大小上限为2M,大于2M就会报错。
    解决办法:后端大神把server.xml中maxPostSize的值改为-1后解决。

     

    七、正确导出图片格式

     

    这个项目首页基本是由图片堆砌成的,一开始切出来的图(默认.png)压缩后在400k-1.3M之间。一开始还以为PSD素材有问题。直到项目最后才闪回,想起图片格式的知识点,改导出成.jpg格式后压缩出来的图片基本控制在100K以内了。具体的.png.jpg这些图片格式的知识有兴趣的自己查。

     

    八、vuex使用之同步用户信息

     

    讲道理小项目是不应该用vuex的,但是用着确实爽,即简单又省心省力。由于我总是忘记它的方法名,所以在这里贴下代码,方便以后随时cv。

    /config/store.js
    const store = new Vuex.Store({
       state: {
           user: {}
       },
       mutations:{
           updateUser(state, data){
               state.user = data;
           }
       }
    })
    //在组件中使用
    computed: {
       user() {
           return this.$store.state.user;
       }
    }
    //在需要的时候更新数据
    this.$store.commit("updateUser", user);

    九、使用html2canvas生成的海报不显示图片

    问题原因:引入的图片资源路径跨域造成的。
    解决办法:我先是按照官方给的那个php的方案弄的,未能解决。最后舔着脸让后端大佬把图片资源目录挪到我web服务目录下给解决的。

    十、css黑科技之放置指定比例的图片

    就是把不定宽图片按指定比例显示,直接上码(1:1.25)。

    //html
    <div class="poster-img-wrap">
       <div class="poster-img-place"></div>
       <img class="poster-img" :src="user.picAddress" alt="">
    </div>
    //less
    .poster-img-wrap {
       position: absolute;
       top: 28%;
       left: 0;
       right: 0;
       width: 80%;
       margin: 0 auto;
       .poster-img-place {
           width: 100%;
           padding-top: 125%;
       }
       .poster-img {
           position: absolute;
           top: 0;
           left: 0;
           width: 100%;
           height: 100%;
       }
    }

    十一、ios页面加载不全不能滚动

    问题描述 :ios从首页进入,跳转其他页面再后退到首页,首页只显示一屏内容且无法滚动。问题原因:在于ios浏览器内核的别致渲染逻辑:它会预先找到相应的overflow: scroll元素,如果子元素高度高于父元素,则建立原生的scrollView实现滚动。问题就出现在这个“预先”上,它预先获取的高度并不是子元素渲染后的真实高度。解决办法:给设置了滚动的#app元素下的子元素p-index设置min-height: calc(100% + 1px);

    #app {
     position: absolute;
     top: 0;
     left: 0;
     width: 100%;
     height: 100%;
     overflow: scroll;
     -webkit-overflow-scrolling: touch;
    }
    .p-index{
      min-height: calc(100% + 1px);
    }

     

    一些忠告

    1.能小程序就别网页开发;

    2.不意淫不揣摩待定的需求;

    3.坚持看图作业的优良传统;

    4.迷茫的时候就看书,焦虑的时候去学习;

    展开全文
  • 微信公众号H5页面开发微信JS-SDK引用 微信提供了微信公众号开发者手册,官方地址:https://mp.weixin.qq.com/ 公众号内许多复杂的业务场景,都是通过网页形式来提供服务,这时需要用到: 微信JS-SDK。以地理位置...

    微信公众号H5页面开发–微信JS-SDK引用

    微信提供了微信公众号开发者手册,官方地址:https://mp.weixin.qq.com/

    公众号内许多复杂的业务场景,都是通过网页形式来提供服务,这时需要用到: 微信JS-SDK。以地理位置接口为例进行阐述。

    写在前面 非常重要!
    • 微信公众号接口必须以http://或https://开头,分别支持80端口和443端口。
    • 由于微信7.0版本升级了对https的安全限制,在微信7.0版本及以上版本使用http协议访问定位组件会导致定位失败。尤其是安卓,所以必须升级https。

    1. 域名绑定

    微信公众号请求网页授权之前,开发者需要先登记授权回调域名。
    注意:这里填写的是域名,且为全域名。授权后该域名下的其他页面都可以授权,例如:www.qq.com为回调域名,配置以后此域名下面的页面http://www.qq.com/music.html 、 http://www.qq.com/login.html 都可以进行OAuth2.0鉴权。
    官方:微信公众平台 >> 微信网页开发 >> 微信网页授权

    2.js文件引入

    官方:
    在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.4.0.js
    如需进一步提升服务稳定性,当上述资源不可访问时,可改访问:http://res2.wx.qq.com/open/js/jweixin-1.4.0.js (支持https)。
    备注:支持使用 AMD/CMD 标准模块加载方法加载

    3.通过config接口注入权限验证配置信息

    所有引用微信JS-SDK的页面都需要提供权限验证信息,否则无法调用。同样的URL只需要配置一次即可,URL发生变化时需要重新调用配置信息进行验证。

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

    这里涉及到两类配置信息的获取,一类是appId所属的公众号标识类配置信息,另一类是签名。JS接口列表可以根据需求在微信公众平台附录中获取。这里所写的是两个地理接口的相关js接口:
    jsApiList: ['openLocation','getLocation'] // 必填,需要使用的JS接口列表

    1. 公众号标识
      微信提供了微信公众帐号测试号,绑定个人微信号即可使用。申请地址:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login
      进入后,第一行就提供了appID和appsecret。不同微信号绑定的微信公众测试号提供的appID和appsecret不同,如果多人参与开发,要注意区分。

    在这里插入图片描述

    接口配置信息主要用于消息接口的配置。公众号是以微信用户的一个联系人形式存在的,消息会话是公众号与用户交互的基础。在这里填写的URL主要用于接收用户信息,进行业务操作后返回信息,没有单独的页面链接。如果不是H5开发的话这里可以空着不写。

    在这里插入图片描述

    这里填写的域名就是上面1点提到的回调域名绑定授权,具体请看上面1. 域名绑定
    在这里插入图片描述

    1. 签名配置信息获取

    生成签名之前,我们要先获取两个参数:access_token 和 jsapi_ticket 。这两个参数的有效期为7200秒,所以一般是放在全局变量中。
    官方:微信公众平台 >> 开始开发 >> 获取access_token

    接口调用请求说明:

    https请求方式: GET
    https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
    在这里插入图片描述

     public static String getAccessToken(String appId, String secret, String accessTokenUrl) {
            HttpClient client = HttpClients.createDefault();	
    	// 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的)
            HttpGet get = new HttpGet(MessageFormat.format(accessTokenUrl,appId,secret));
            // 创建Get请求
            try {
                String accessToken = (String) CacheUtil.get("wxCache", "accessToken");
        	    //这里把accessToken放在全局变量中,通过CacheUtil缓存工具类判断accessToken是否失效
                if (StringUtils.isBlank(accessToken) || StringUtils.isEmpty(accessToken)) {
                    HttpResponse response = client.execute(get);
        		// 由客户端执行(发送)Get请求
                    HttpEntity entity = response.getEntity();
        		// 从响应模型中获取响应实体
                    String result = EntityUtils.toString(entity, "UTF-8");
                    Map<String, Object> accessTokenMap = JSON.parseObject(result);
                    accessToken = (String)accessTokenMap.get("access_token");
        		//将响应实体进行编码转换
                    CacheUtil.put("wxCache", "accessToken", accessToken);
        		//将accessToken存入缓存变量中
                }
                return accessToken;
            } catch (ClientProtocolException e) {
                log.error(e.getMessage());
            } catch (IOException e) {
                log.error(e.getMessage());
            }
            return  null;
        }
    
    

    用同样的get请求方法,获得jsapi_ticket。与access_token性质相似,有效期为7200秒,建议放在全局变量中,便于下次请求的时候判断是否仍在有效期内。

    public static String getTicket(String accessToken,String ticketUrl) {
        HttpClient client = HttpClients.createDefault();
        HttpGet get = new HttpGet(MessageFormat.format(ticketUrl,accessToken));
        try {
            String ticket = (String) CacheUtil.get("wxCache", "jsapi_ticket");
            if (StringUtils.isBlank(ticket) || StringUtils.isEmpty(ticket)) {
                HttpResponse response = client.execute(get);
                HttpEntity entity = response.getEntity();
                String result = EntityUtils.toString(entity, "UTF-8");
    	    Map<String, Object> jsApiTicketMap = JSON.parseObject(result);
                ticket = (String)jsApiTicketMap.get("ticket");
    
                CacheUtil.put("wxCache", "jsapi_ticket", ticket);
            }
            return ticket;
        } catch (ClientProtocolException e) {
            log.error(e.getMessage());
        } catch (IOException e) {
            log.error(e.getMessage());
        }
        return null;
    }
    

    获得jsapi_ticket之后,就可以生成JS-SDK权限验证的签名了。
    签名生成规则如下:
    参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分) 。

    //生成时间戳和随机字符串
            String noncestr = UUID.randomUUID().toString().replace("-", "").substring(0, 16);
            String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
    

    时间戳和随机字符串都是随机生成的,但是随机生成规则不同,注意区分。

     //获取url
            String url = pathUrl;
    

    url必须与用户进入页面的url相同,从前台传入,防止因为参数不同而引起的url不同,从而获取签名失败。
    对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1:

     //将参数排序并拼接字符串
         String sortString = WeChatCommonUtil.sort(url, timestamp, ticket, noncestr);
      
     /**
         * @Param [signature, timestamp, ticket, echostr]
         * @Return java.lang.String
         * @Description: 对所有待签名参数按照字段名的ASCII 码从小到大排序
         */
        public static String sort(String url, String timestamp, String ticket, String noncestr) {
            return "jsapi_ticket=" + ticket + "&noncestr=" + noncestr + "&timestamp=" + timestamp + "&url=" + url;
        }
    

    对string1进行sha1签名,得到signature:
    在这里插入图片描述
    至此,得到权限验证配置所有信息。

    4.通过ready接口处理成功验证

    以下步骤官网都有参考:

    wx.ready(function(){
    // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作.
    // 所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。
    // 对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
    });

    这里没有写到error接口,不够严谨。

    wx.error(function(res){
    // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
    });

    5.判断当前客户端版本是否支持指定JS接口

    wx.checkJsApi({
    jsApiList: [‘chooseImage’], // 需要检测的JS接口列表
    success: function(res) {
    // 以键值对的形式返回,可用的api值true,不可用为false
    // 如:{“checkResult”:{“chooseImage”:true},“errMsg”:“checkJsApi:ok”}
    }
    });

    需要检测的JS接口与config中填写的 jsApiList 基本一致。
    config信息验证后,才会调用ready方法,所以将checkJsApi放在ready方法中执行。

    6.参考官方文档调用所需接口

    使用微信内置地图查看位置接口:用于打开导航地图,获取目的地坐标定位。

    wx.openLocation({
    latitude: , // 纬度,浮点数,范围为90 ~ -90
    longitude: , // 经度,浮点数,范围为180 ~ -180。
    name: ’ ', // 位置名
    address: ’ ', // 地址详情说明
    scale: 1, // 地图缩放级别,整形值,范围从1~28。默认为最大
    infoUrl: ‘’ // 在查看位置界面底部显示的超链接,可点击跳转
    });

    获取地理位置接口:主要用于获取自身坐标定位。

    wx.getLocation({
    type: ‘wgs84’, // 默认为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; // 位置精度
    }
    });

    注意:两个接口的经纬度都是浮点数类型,否则无法调用。

    总结:获取微信配置信息验证的步骤比较复杂,必须没有误差,同时要考虑配置信息具有时效性,重复获取以及放在全局变量中。调用接口的代码文档官方都有提供,可以参考。

    wx.ready(function () {
        // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作.
        // 所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。
        // 对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
       
        wx.checkJsApi({
            jsApiList: ['checkJsApi', 'openLocation', 'getLocation'], // 需要检测的JS接口列表,所有JS接口列表见附录2,
            success: function (res) {
                // 以键值对的形式返回,可用的api值true,不可用为false
                // 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"}
            }
        });
    
        wx.getLocation({
            type: 'gcj02', // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02'
            dataType: "json",
            success: function (res) {
                var latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90
                var longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。
                var speed = res.speed; // 速度,以米/每秒计
                var accuracy = res.accuracy; // 位置精度
            }
        });
    
        $(".nav-to").on ('click','a',function () {
            wx.openLocation({
                latitude: parseFloat($(".nav-to").attr("lat")), // 纬度,浮点数,范围为90 ~ -90
                longitude:parseFloat($(".nav-to").attr("lng")), // 经度,浮点数,范围为180 ~ -180。
                name: $(".nav-to").attr("name"), // 位置名
                address: '', // 地址详情说明
                scale: 10, // 地图缩放级别,整形值,范围从1~28。默认为最大
                infoUrl: '' // 在查看位置界面底部显示的超链接,可点击跳转
            });
        });
    });
    

    后续补充:
    事实证明我真是too young too native = =

    背景交代 与真正的公众号进行对接(以上都是用微信提供的测试公众号)时,除了以上步骤还有其他验证是在测试公众号上所不需要的,在此remark一下。

    7.设置IP白名单

    在这里插入图片描述
    根据要求把服务器的IP加入到IP白名单中,这样就不会被拦截了。

    8.设置JS接口安全域名

    在这里插入图片描述
    注意:确保可以访问!!!
    不管是根目录还是路径目录,都要确保通过所填写的域名都可以访问到这个文件。同时微信所访问的其他路径也需要在这个路径目录下。
    踩坑记录:如果程序设置了权限认证,则要记得放开认证,否则永远也无法访问到。

    展开全文
  • 最近在项目中接手微信环境h5页面开发,主要的是使用微信 JS-SDK 做原有项目部分功能在微信环境下的适配。 目前项目暂时告一段落,希望可以用几篇文章记录并分享这些天来学习、开发微信h5页面的心得、体会~ 由于...
  • 微信公众号H5页面

    2020-07-29 14:20:07
    模仿微信公众平台做的简单静态页面,里面包含了用户列表,标签设计,关注回复等功能
  • 微信h5页面缓存

    2019-05-07 18:42:51
    微信h5页面缓存问题前言先说说之前开发的问题来看看现在的效果:因为我的分享页面是在一整个项目中的,默认就是采用的第一种方案,所以我直接修改了图片的名称,打包编译后上传js文件到服务器,得到的效果是: ...
  • 前端微信h5开发

    2019-02-11 15:28:40
    首先确定的是,这是一个H5页面,是在微信端展示的一个H5页面 需要获取微信用户头像、性别、昵称需要获取微信用户头像、性别、昵称 测试结果需要生成图片,用户可直接长按保存图片 分享 首先说下前两点: ...
  • 一、首先是ios对时间date()的支持不一样: var date =new Date("2016-05-31 00:00:00"); ...这种写法在安卓和pc上都不正常的,唯独在ios手机上会显示Nan,查阅一些资料,经过一番调试发现: ...
  • 微信H5开发(三)

    2018-06-03 14:36:36
    微信H5开发在使用微信SDK,会碰到很多问题,特别是由于微信文档的介绍不够细致或者某些功能被限制但在文档上没有提及。我这篇文不提微信上的这些小小的坑,只讲H5和iOS 、安卓 的一些兼容问题。 微信H5页面项目...
  • 微信公众号的H5页面,在新版本上线后部分用户无法获取最新的页面文件 二、无法获取新版本页面的用户特征 在上线前某段时间内,访问过该H5页面,手机本地存有该H5页面的缓存 三、解决方案【亲测可行】 对于JS和CSS...
  • 一、微信网页授权 网页授权流程分为四步,这里只说前端需要做的,其中的第一步:跳转授权页面获取code。...如果你页面中有用到分享、上传图片、微信支付等功能,那么需要先进行js-sdk授权。我...
  • 会员免费看,...微信h5支付开发是子恒老师《子恒说微信开发》视频教程的第17部。详细讲解了微信H5支付开发,内容包含开通H5支付,实现微信h5支付,订单查询,关闭订单等等。欢迎反馈,微信号:QQ68183131
  • 微信H5开发(二)

    2018-07-15 10:45:14
    第一次使用微信开发文档的时候,感觉文档里面写的内容不算太难,但在实际开发中会碰到很多预想不到的问题。 微信开放平台、微信商务平台 有什么用?都在哪里用? 首先从微信公众号讲起,期间用到微信商务平台和...
  • 微信H5支付功能开发

    2019-06-28 10:44:03
    本文介绍的是微信H5支付功能开发,也就是在微信之外的H5页面支付。 首先我们需要先看微信的官方文档https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=15_1,这里面几乎介绍了全部流程了。等你了解大概流程...
  • 一看就明白的微信H5页面制作教程 H5页面微场景制作 入门教程入门了,一切都变得很简单!
  • 不过,有一处更新颇使H5开发者感到困扰,就是在iPhone上H5页面最底部多了一个白色的前进后退控制栏,即下图底部的那个白条, 分析 在微信里只要发生页面跳转,这个控制浏览器前进后退的白色条就会出现。...
  • H5这个由HTML5简化而来的词汇,正通过微信广泛传播。H5是集文字、图片、音乐、视频、链接等多种形式的展示页面,丰富的控件、灵活的动画特效、强大的...下面就给大家介绍如何通过应用之星网站轻松制作微信H5页面,简
  • 箭头指向是微信自行决定是显示"返回(ios,返回上一步)"还是"x(安卓,直接返回公众号)",开发者不能做任何的控制。![图片说明](https://img-ask.csdn.net/upload/201611/09/1478671161_13433.jpg)
1 2 3 4 5 ... 20
收藏数 17,664
精华内容 7,065
关键字:

微信开发h5页面