2017-07-07 14:47:26 byc233518 阅读数 2966
  • 微信支付开发-微信公众号开发12-微信开发php

    微信公众平台开发之微信支付开发是子恒老师《微信公众平台开发》视频教程的第12部。详细讲解了用php进行微信支付的开发。内容包含获取支付密钥,微信公众号支付开发,扫码支付,微信刷卡支付,异步处理支付结果等等。欢迎反馈,微信/QQ:68183131

    27772 人正在学习 去看看 秦子恒

上次是重装了解决了卡顿的问题;

总不能过几天就重装一次啊!

更不能忍受现在这样一点一卡, 一键一卡!

找遍菜单也没找到任何有用的选项!

开始解决:

0. 关闭微信web开发者工具;

1. 打开 finder, 按下 shift + command + G , 输入 ~/资源库


2. 找到 下面几个文件夹, 删掉这几个东西:

    Application Support --> 微信web开发者工具
   Preferences -->com.tencent.wechat.devtools.plist
   Caches -->微信web开发者工具

3. 重新打开吧

2017-07-10 16:46:34 byc233518 阅读数 3315
  • 微信支付开发-微信公众号开发12-微信开发php

    微信公众平台开发之微信支付开发是子恒老师《微信公众平台开发》视频教程的第12部。详细讲解了用php进行微信支付的开发。内容包含获取支付密钥,微信公众号支付开发,扫码支付,微信刷卡支付,异步处理支付结果等等。欢迎反馈,微信/QQ:68183131

    27772 人正在学习 去看看 秦子恒

还记得之前用微信的 web开发者工具是长这个样子的, 打开后直接就有移动开发的选项,然而现在却没有了, 调试不了, 摸黑写代码, 不爽!

以前↓


现在↓


这样可不行呀, 随便改个东西都要 alert(JSON.stringify(xxx)), 才能看得到到底返回了啥内容

于是就找到了另外一个腾讯的移动调试工具 TBS Studio

官方介绍: http://bbs.mb.qq.com/thread-1416936-1-1.html

打开后就是长这个样子的↓


具体使用步骤: 

感觉自己再怎么写也赶不上官方的详细, 直接看官方的好了啦

 https://x5.tencent.com/tbs/guide/debug/season1.html


下面这个单独贴出来, 因为我是华为 P10手机, 之前用 chrome 的调试工具一直识别不出来, 更别说调试微信了, 使用下面官方的方法, 终于连接成功了, 供参考!
4. 电脑死活adb连接不成功?

解决方案:

方案一: 确保USB与PC的连接

1) 请确保USB连线能正常连通PC和手机(非常重要呀!)

简单确认方法:手机状态栏显示为充电状态。

2) 请确保PC的USB驱动已正常安装,可以在控制面板“设备管理器” “通用串行总线控制器”中确认无异常USB设备显示。

3) 点击重置,再次“启动检测”。

方案二: 使用adb启动

1) 使用内置adb包( win下载mac下载),手动启动adb

运行 adb devices

2) 找到设备,点击重置,再次“启动检测”

3) 未找到设备,或者offline

  ① 运行命令 adb kill-server -> adb start-server -> adb devices

  ② 重拔usb链接调试设备

  ③ 重启调试设备

  ④ 重启电脑...

方案三: 安装PC应用宝

方案四: 安装android SDK




2018-04-09 19:34:35 GrahamACER 阅读数 3263
  • 微信支付开发-微信公众号开发12-微信开发php

    微信公众平台开发之微信支付开发是子恒老师《微信公众平台开发》视频教程的第12部。详细讲解了用php进行微信支付的开发。内容包含获取支付密钥,微信公众号支付开发,扫码支付,微信刷卡支付,异步处理支付结果等等。欢迎反馈,微信/QQ:68183131

    27772 人正在学习 去看看 秦子恒

坑1,首先是一定要用微信开发者工具调试你的页面,虽然它就是一个Chrome内核包裹的玩意,但如果不用它的工具直接用Chrome你是收不到任何API返回的提示的

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

坑2,使用we.addCard一定要放在wx.ready里面,同时所有你使用的方法(例如wx.addCard)一定要放在wx.config的jsApiList里

坑3,jsapi签名拿回的sign,一定要是你当前访问程序的URL计算出来的api,不然会判断违法。也就是说出于安全考虑,开发者一定要在服务器端完成签名逻辑,并且建议使用者也在线上环境拿到signature

坑4,之前遇到一个问题,现象大概是:打开config中的debug:true是可以调用的,console返回的信息也是正确。但是一单关闭debug,addCard又不能用了,实在令人头大

最后尝试了下,一旦加入alert事件让页面暂停,就能顺利运行。所以认为这是config请求和addCard的同步问题

官网API解释过congfig可以放在MVVM框架中的mounted中执行,这样再调用addCard是不需要再次带上config的,问题得到解决

2017-04-17 09:51:30 hjucook1988 阅读数 1518
  • 微信支付开发-微信公众号开发12-微信开发php

    微信公众平台开发之微信支付开发是子恒老师《微信公众平台开发》视频教程的第12部。详细讲解了用php进行微信支付的开发。内容包含获取支付密钥,微信公众号支付开发,扫码支付,微信刷卡支付,异步处理支付结果等等。欢迎反馈,微信/QQ:68183131

    27772 人正在学习 去看看 秦子恒

上一章讲了redis工具类的封装,今天我们来讲讲微信工具类的封装。这个可没有想象的那么简单,说实话,我就因为没看仔细微信企业号开发者接口文档,在参数上碰到过很多坑。这个在没有人指导的情况下,整个人心情好几天都是不好的。为什么不好呢,下面听我详细说来:
像什么主动调用啊,成员登录什么的目前还用不到,我到后面再讲,现在就先讲讲JSSDK的调用,首先

步骤一:引入JS文件

在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.2.0.js
备注:我也懒得下载了。反正使用手机端都是有联网的,去服务器下载JS和去微信下载js耗费的流量也基本没差。如果没网也没法测,所以我就考虑直接引入联网的js文件。

步骤二:通过config接口注入权限验证配置

所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用(同一个url仅需调用一次,对于变化url的SPA的web app可在每次url变化时进行调用,目前Android微信客户端不支持pushState的H5新特性,所以使用pushState来实现web app的页面会导致签名失败,此问题会在Android6.2中修复)。

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

上面是我抄微信API的,其他都是没啥问题,就是这个签名害苦了我。这是调用的JSSDK是否能调用的验证的,下面调用JSSDK具体方法的时候,还要另外生成一次不同的签名。我就不废话了,直接开始讲生成签名的方法封装好了。

/**
     * @param group_ticket 格式如jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg
     * @param url 当前页面的url路径
     * @return String
     * @throws DigestException
     */
    public static String getSignature(String ticket,String url) throws DigestException{
        JSONObject jres = new JSONObject();
        String signature = "";
        String sign = "";
        String noncestr = getRandomString(16);
        String timestamp = Long.toString(System.currentTimeMillis()).substring(0,10);
        sign = sign + ticket 
                + "&noncestr=" + noncestr
                + "&timestamp=" + timestamp
                + "&url=" + url;
        try {
            //指定sha1算法  
            MessageDigest digest = MessageDigest.getInstance("SHA-1");  
            digest.update(sign.getBytes());  
            //获取字节数组  
            byte messageDigest[] = digest.digest();  
            // Create Hex String  
            StringBuffer hexString = new StringBuffer();  
            // 字节数组转换为 十六进制 数  
            for (int i = 0; i < messageDigest.length; i++) {  
                String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);  
                if (shaHex.length() < 2) {  
                    hexString.append(0);  
                }  
                hexString.append(shaHex);  
            }  
            signature =  hexString.toString();  

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();  
            throw new DigestException("签名错误!");  
        }
        jres.put("signature", signature);
        jres.put("noncestr", noncestr);
        jres.put("timestamp", timestamp);
        return jres.toJSONString();
    }
    //获取指定位数的随机字符串(包含小写字母、大写字母、数字,0<length)
    private static String getRandomString(int length) {
        //随机字符串的随机字符库
        String KeyString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        StringBuffer sb = new StringBuffer();
        int len = KeyString.length();
        for (int i = 0; i < length; i++) {
           sb.append(KeyString.charAt((int) Math.round(Math.random() * (len - 1))));
        }
        return sb.toString();
    }

慢慢理解代码吧,有我封装的代码一切API的误解都能迎刃而解。特别注意的是url这个。就是输入你手机当前页面的地址。这个可真坑死我了,我默认以为输入API上提供的那个url。一直忽略了它。
这里面有调用其他的方法,比如getToken(),ticket。怎么来的呢,看下面:

public static String getToken(){
        String access_token = RedisUtil.getString("access_token");
        if(access_token==null||access_token.length()<1){
            String url = CommonConst.WECHAT_URL_GETTOKEN;
            String param = "corpid="+CommonConst.WECHAT_CORPID+"&corpsecret="+CommonConst.WECHAT_CORPSECRET;
            String result = HttpRequest.httpClientSendGet(url, param);
            JSONObject obj = JSONObject.parseObject(result);
            access_token = obj.getString("access_token");
            RedisUtil.setStringByTime("access_token", access_token,CommonConst.WECHAT_TOKEN_TIME,TimeUnit.SECONDS);
        }
        return access_token;
    }

这里我先去redis缓存拿,如果没有,就去微信获取再存入缓存,API说这个access_token有限制次数,慌死,赶紧弄个缓存来存存,还有它的保质期只有7200秒,一算就两个小时,不得不设置了缓存的保留时间。

/**
     * 微信权限认证config的jsapi_ticket获取
     * @return
     */
    public static String getUseTicket(){
        String ticket = RedisUtil.getString("jsapi_ticket");
        if(ticket==null||ticket.length()<0){
            String url = CommonConst.WECHAT_URL_USETICKET;
            String param = "access_token=" + getToken();
            String result = HttpRequest.httpClientSendGet(url, param);
            JSONObject obj = JSONObject.parseObject(result);
            ticket = obj.getString("ticket");
            RedisUtil.setStringByTime("jsapi_ticket", ticket,CommonConst.WECHAT_TOKEN_TIME,TimeUnit.SECONDS);
        }
        return ticket;
    }

特别提醒,这个是config验证的时候的ticket获取。也是有保质期的,如上

/**
     * 获取打开通讯录签名条件 结果为  ticket,group_id
     * @return  
     */
    public static String getManageTicketAndId(){
        JSONObject jres = new JSONObject();
        String ticket = RedisUtil.getString("group_ticket");
        String group_id = RedisUtil.getString("group_id");
        if(ticket==null||ticket.length()<0){
            String url = CommonConst.WECHAT_URL_MANAGETICKET;
            String param = "access_token=" + getToken() + "&type=contact";
            String result = HttpRequest.httpClientSendGet(url, param);
            JSONObject obj = JSONObject.parseObject(result);
            ticket = obj.getString("ticket");
            group_id = obj.getString("group_id");
            RedisUtil.setStringByTime("group_ticket", ticket,CommonConst.WECHAT_TOKEN_TIME,TimeUnit.SECONDS);
            RedisUtil.setStringByTime("group_id", group_id,CommonConst.WECHAT_TOKEN_TIME,TimeUnit.SECONDS);
        }
        jres.put("ticket", ticket);
        jres.put("group_id", group_id);
        return jres.toJSONString();
    }

这个如注释,不解释了。可能有人会问 CommonConst.WECHAT_URL_MANAGETICKET。这玩意是干嘛的,这个我就是把一些微信固定的一些参数存入一个类里,统一管理。如

public class CommonConst {
    /**
     * 微信各类参数
     */
    public final static long WECHAT_TOKEN_TIME = 7200;
    public final static String WECHAT_URL_GETTOKEN = "https://qyapi.weixin.qq.com/cgi-bin/gettoken";
    public final static String WECHAT_URL_USETICKET = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket";
    public final static String WECHAT_URL_MANAGETICKET = "https://qyapi.weixin.qq.com/cgi-bin/ticket/get";
    public final static String WECHAT_URL_GETUSERBYID = "https://qyapi.weixin.qq.com/cgi-bin/user/get";
    public final static String WECHAT_URL_GETUSERINFO = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo";


    public final static String WECHAT_CORPID = "wxa9312c3105f7438e";
    public final static String WECHAT_CORPSECRET = "ic-ZUEkqTu9Mk3TkfSZ_qg0JbvKxAsfCashXWIqrYyw8b3S_tr5VdnTdfeIQoXvl";

    /**
     * 获取微信部门下人员参数
     */
    public final static String WECHAT_URL_USER_SIMPLELIST = "https://qyapi.weixin.qq.com/cgi-bin/user/simplelist";
}

再讲一个获取通讯录部门下的人员API的封装就不讲了,如下:

/**
     * 
     * @param id 部门ID
     * @param flag 是否递归部门下所有人
     * @param code 0获取全部成员,1获取已关注成员列表,2获取禁用成员列表,4获取未关注成员列表。status可叠加,未填写则默认为4
     * @return JSONString
     */
    public static List<String> getPersonByDepartId(int id,boolean flag,String code){
        List<String> list = new ArrayList<String>();
        String access_token = WeChatUtil.getToken();
        String param = "access_token="+ access_token 
                + "&department_id=" + id
                + "&fetch_child=" + (flag?"1":"0")
                + "&status=" + code;
        String result = HttpRequest.httpClientSendGet(CommonConst.WECHAT_URL_USER_SIMPLELIST,param);
        JSONObject obj = JSONObject.parseObject(result);
        String errmsg = obj.getString("errmsg");
        if("ok".equals(errmsg)){
            JSONArray objs = obj.getJSONArray("userlist");
            for(int i=0;i<objs.size();i++){
                JSONObject a = objs.getJSONObject(i);
                list.add(a.getString("userid")+","+a.getString("name"));
            }
        }
        return list;
    }

这些可都是我深思熟虑写的,可不是哪里乱复制来的,希望能给大家很多的帮助,不过很多微信API更新了就不关我事了,一切还是要以API为准,我这个为辅助。

2019-08-30 15:56:14 weixin_41552521 阅读数 38
  • 微信支付开发-微信公众号开发12-微信开发php

    微信公众平台开发之微信支付开发是子恒老师《微信公众平台开发》视频教程的第12部。详细讲解了用php进行微信支付的开发。内容包含获取支付密钥,微信公众号支付开发,扫码支付,微信刷卡支付,异步处理支付结果等等。欢迎反馈,微信/QQ:68183131

    27772 人正在学习 去看看 秦子恒

一、绑定微信公众号JS接口安全域名

二、为开发者设置web开发者权限(方便调试)

三、引入JS文件

http://res2.wx.qq.com/open/js/jweixin-1.4.0.js (支持https)。

四、通过config接口注入权限验证配置

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

React项目中使用JSSDK

  • 自行封装wxsdk
import wx from 'weixin-js-sdk';
import { getWxSignature } from './../../api/member/commonApi';

const wxsdk = {
  /**
   * @description 微信分享
   * @author Seven_G
   * @param {*} content 分享参数
   * @param {*} callback 回调函数
   */
  share(shareInfo, callback) {
    wx.checkJsApi({
      jsApiList: [
        'updateAppMessageShareData',
        'updateTimelineShareData',
        'onMenuShareAppMessage',
        'onMenuShareTimeline',
      ], // 需要检测的JS接口列表,所有JS接口列表见附录2,
      success: function(res) {
        // 以键值对的形式返回,可用的api值true,不可用为false
        // 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"}
        let link = window.location.href;
        // 在这里设置默认分享的内容
        let content = {
          title: '庆团圆时刻,赢双重好礼。',
          desc: '庆团圆时刻,赢双重好礼。',
          link: link,
          imgUrl:
            'http://cdn-dmp.swellfun.com/image/a9be9c8a141349a69718093d06c07397',
        };
        if (shareInfo instanceof Object) {
          content = shareInfo;
        }

        if (res.checkResult.updateAppMessageShareData) {
          wx.updateAppMessageShareData({
            title: content.title, // 分享标题
            desc: content.desc, // 分享描述
            link: content.link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
            imgUrl: content.imgUrl, // 分享图标
            success: function() {
              // 设置成功
              if (typeof callback == 'function') {
                callback();
              }
            },
          });
        }
        if (res.checkResult.updateTimelineShareData) {
          wx.updateTimelineShareData({
            title: content.title, // 分享标题
            link: content.link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
            imgUrl: content.imgUrl, // 分享图标
            success: function() {
              // 设置成功
              if (typeof callback == 'function') {
                callback();
              }
            },
          });
        }
        if (res.checkResult.onMenuShareAppMessage) {
          wx.onMenuShareAppMessage(
            {
              title: content.title, // 分享标题
              desc: content.desc, // 分享描述
              link: content.link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
              imgUrl: content.imgUrl, // 分享图标
            },
            function() {
              //这里是回调函数
              if (typeof callback == 'function') {
                callback();
              }
            }
          );
        }
        if (res.checkResult.onMenuShareTimeline) {
          wx.onMenuShareTimeline(
            {
              title: content.title, // 分享标题
              link: content.link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
              imgUrl: content.imgUrl, // 分享图标
            },
            function() {
              //这里是回调函数
              if (typeof callback == 'function') {
                callback();
              }
            }
          );
        }
      },
    });
  },
  init(content, callback) {
    let url = window.location.href;
    let appid = '';
    if (window.location.origin.indexOf('sjfuat.xiaoshu.biz') > -1) {
      appid = 'wxf7d4f8be8d6261a0';
    } else if (window.location.origin.indexOf('sjfapp.xiaoshu.biz') > -1) {
      appid = 'wxd1c7c714de4a462a';
    } else if (window.location.origin.indexOf('a.convertwork.cn') > -1) {
      appid = 'wxd1c7c714de4a462a';
    } else if (window.location.origin.indexOf('membertest.swellfun.com') > -1) {
      appid = 'wxf7d4f8be8d6261a0';
    } else if (window.location.origin.indexOf('member.swellfun.com') > -1) {
      appid = 'wxe7d0e0c40c0f6191';
    } else {
      appid = 'wxd1c7c714de4a462a';
    }
    let link = window.location.href;
    // 注意在hash模式下,链接带有#,不进行切割时可能会导致签名错误(前端后端进行切割都可以),因为微信签名算法默认是不会将#号和井号之后的链接加入到算法当中
    link = window.location.href.split('#')[0];
    let params = {
      url: link,
    };
    getWxSignature(params).then(res => {
      if (res && res.data && !res.data.error) {
        wx.config({
          debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
          appId: appid, // 必填,公众号的唯一标识
          timestamp: res.data.timestamp, // 必填,生成签名的时间戳
          nonceStr: res.data.nonceStr, // 必填,生成签名的随机串
          signature: res.data.signature, // 必填,签名
          jsApiList: [
            'updateAppMessageShareData',
            'updateTimelineShareData',
            'onMenuShareAppMessage',
            'onMenuShareTimeline',
          ], // 必填,需要使用的JS接口列表
        });
        wx.ready(function() {
          wxsdk.share(content, callback);
        });
        wx.error(function() {});
      }
    });
  },
};
export default wxsdk;

  • 引入当前单页文件内
import wxsdk from './../common/js/wxsdk';


// 在componentDidMount钩子函数中调用init方法,初始化JSSDK,并自定义分享内容以覆盖默认分享
componentDidMount() {
    document.title = '活动说明页';
    let link = window.location.href;
    let shareContent = {
      title: '庆团圆时刻,赢双重好礼。', // 分享标题
      desc: '庆团圆时刻,赢双重好礼。', // 分享描述
      link: link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
      imgUrl:
        'http://cdn-dmp.swellfun.com/image/a9be9c8a141349a69718093d06c07397', // 分享图标
    };
    wxsdk.init(shareContent);
    }

微信公众平台, config:invalid signature一直爆这个错误的解决办法

如果是invalid signature签名错误。建议按如下顺序检查:

1.确认签名算法正确,可用 http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign 页面工具进行校验。
在这里插入图片描述

2.确认config中nonceStr(js中驼峰标准大写S), timestamp与用以签名中的对应noncestr, timestamp一致。

3.确认url是页面完整的url(请在当前页面alert(location.href.split(’#’)[0])确认),包括’http(s)?/‘部分,以及’?‘后面的GET参数部分,但不包括’#'hash后面的部分。

4.确认 config 中的 appid 与用来获取 jsapi_ticket 的 appid 一致。

5.确保一定缓存access_token和jsapi_ticket。

没有更多推荐了,返回首页