微信常用接口

微信常用接口

一、公众号

1、准备工作

  1. 公众号的帐号及密码

  2. 公众号的AppID,AppSecret

    AppID:

    ​ 开发者ID是公众号开发识别码,配合开发者密码可调用公众号的接口能力。

    AppSecret:

    ​ 开发者密码是校验公众号开发者身份的密码,具有极高的安全性。切记勿把密码直接交给第三方开发者或直接存储在代码中。如需第三方代开发公众号,请使用授权方式接入

  3. 在公众号设置中选择功能设置,下载TXT文件放到web服务器的目录下,将域名填写至白名单等

    业务域名:

    ​ 设置业务域名后,在微信内访问该域名下页面时,不会被重新排版。用户在该域名上进行输入时,不出现安全提示。

    JS接口安全域名:

    ​ 因为微信的安全做得比较好,我们根据 微信的js sdk写的函数、方法,只有在指定的安全域名下才能被微信唤起。

    网页授权域名:

    ​ 用户在网页授权页同意授权给公众号后,微信会将授权数据传给一个回调页面,回调页面需在此域名下,以确保安全可靠。

    例如:微信公众号登录后的回调

  4. 微信官方文档:https://developers.weixin.qq.com/doc/ 有你想知道的一切信息

2、获取access_token

​ access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。access_token的有效期目前为2个小时,需定时刷新.

https请求方式: GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

参数说明

参数是否必须说明
grant_type获取access_token填写client_credential
appid第三方用户唯一凭证
secret第三方用户唯一凭证密钥,即appsecret

返回说明

正常情况下,微信会返回下述JSON数据包给公众号:

{"access_token":"ACCESS_TOKEN","expires_in":7200}

代码演示

(1) 获取Token,建议采用懒加载策略,用的时候再发请求,全局共享。

//拼接连接
String accessToken="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+"你的appId"+"&secret="+"你的appsecret";

String tokenResult = req.sendGet(accessToken);//进行网络的请求获取token
String tokenObj= JSON.parseObject(tokenResult);//在上面的基础上获取信息 
//返回:{"access_token":"ACCESS_TOKEN","expires_in":7200}

String accesstoken = tokenObj.getString("access_token");//获取access_token 
String expiresin = tokenObj.getString("expires_in");//获取expires_in
String errcode=tokenObj.getString("errcode");//获取错误代码
String errmsg=tokenObj.getString("errmsg");//获取错误信息
//判断是否为空
if(StringUtils.isNotBlank(accesstoken)){
    //写入redis缓存,设置2小时过期
	SecurityCommonUtils.putRedis("GLOBAL_ACCESS_TOKEN", accesstoken, 7200);
}else{
    logger.error("错误代码=========="+errcode);
    logger.error("错误信息=========="+errmsg);
    throw new NullPointerException("token获取异常!");
}

至此只要不出问题,SecurityCommonUtils.gutRedis(“GLOBAL_ACCESS_TOKEN”) 咱们就可以拿到的全局token了

3、用户管理

(1)OpenID 与 UnionID

OpenID :

​ 在关注者与公众号产生消息交互后,公众号可获得关注者的OpenID(加密后的微信号,每个用户对每个公众号的OpenID是唯一的。对于不同公众号,同一用户的OpenID不同)

​ 简单的说就是,用户去逛各大商场,商场给你对应了商场的会员卡(OpenID),可以根据这个会员卡进行改商城的消费。

​ 那么问题来了,如果想在不同的维多利商城做到会员卡通用,就需要增加一个公用的会员卡(UnionID ),方便同一个集团在不同的产品中识别到同一个用户

UnionID :

​ 请注意,如果开发者有在多个公众号,或在公众号、移动应用之间统一用户帐号的需求,需要前往微信开放平台(open.weixin.qq.com)绑定公众号后,才可利用UnionID机制来满足上述需求。

(2)网页授权(用户登录)

具体而言,网页授权流程分为四步:

  1. 引导用户进入授权页面同意授权,获取code
  2. 通过code换取网页授权access_token(与基础支持中的access_token不同)
  3. 如果需要,开发者可以刷新网页授权access_token,避免过期
  4. 通过网页授权access_token和openid获取用户基本信息(支持UnionID机制)

获取用户授权 请使用https协议。

/**
 * 微信登录请求这个方法获取code
 * @param response
 * @Date 2020年10月29日
 * @author zy
 */
@RequestMapping("/wxlogin")
public void wxloginvenue(HttpServletResponse response,String isLogin, String orderId){
    try {
        String appId = "你的appId";
        String url = "你的回调地址";
        String redirectUri = URLEncoder.encode(url,"utf-8");//回调的方法转成UTF-8
        String requestUrl = "";
        if (StringUtils.isNotBlank(isLogin)){// 登录操作
            requestUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" +appId +
                "&redirect_uri=" + redirectUri + "&response_type=code&scope=snsapi_userinfo&state=-0#wechat_redirect";
        } else { // 授权,静默方式授权
            requestUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + appId +
                "&redirect_uri=" + redirectUri + "&response_type=code&scope=snsapi_base&state=-0#wechat_redirect";
        }
        response.sendRedirect(requestUrl);//进行网络的请求
    } catch (Exception e) {
        e.printStackTrace();
        logger.error("微信登录出现异常出现异常!",e);
    }
}

以上代码有几个比较重要的参数:

  1. snsapi_userinfo :非静默授权。这种授权方式需要用户手动同意,授权后获取该用户的基本信息
  2. snsapi_base :静默授权。这种授权方式可以让用户无感知,授权后获取该用户的OpenID
  3. redirect_uri : 回调地址,微信登录成功后需要通知的地址,返回数据
  4. state:重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节

回调地址

获取code后,请求以下链接获取access_token: https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

@RequestMapping("/logingetaccesstoken")
    public String loginGetAccessToken(HttpRequest req, HttpServletRequest request) {
        String tokenResult = null;
        String redirecturl = null;
        try {
            String code = request.getParameter("code");
            String state = request.getParameter("state");
            String appId = "你的appId";;
            String secret = "你的appsecret";
            //通过code获取access_token的url
            String wxAccessUrl = "https://api.weixin.qq.com/sns/oauth2/access_token";
            String accessTokenUrl = wxAccessUrl + "?appid=" + appId + "&secret=" + secret + "&code=" + code + "&grant_type=authorization_code";//Url的拼接
            tokenResult = req.sendGet(accessTokenUrl);//进行网络的请求获取token
            JSONObject tokenObj = JSON.parseObject(tokenResult);//在上面的基础上获取信息

            //获取用户信息url
            //获取access_token网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
            String accessToken = tokenObj.getString("access_token");
            String openId = tokenObj.getString("openid");//获取openid
            String unionid = tokenObj.getString("unionid");
            String wxUserinfoUrl = "https://api.weixin.qq.com/sns/userinfo";
            String userUrl = wxUserinfoUrl + "?access_token=" + accessToken + "&openid=" + openId;//url的拼接
            String wxUserInfo = req.sendGet(userUrl);//进行网络请求获取用户的信息

            request.getSession().setAttribute("openId", openId);
            //用户统一标识。针对一个微信开放平台帐号下的应用,同一用户的unionid是唯一的。
            request.getSession().setAttribute("unionid", unionid);
            request.getSession().setAttribute("wxUserInfo", wxUserInfo);

            if ("-0".equals(state)) {// 登录操作需要更新数据库中信息,授权操作只记录openId
                SecurityCommonUtils.putRedis("THIRD_PARTY_LOGIN_" + user.getLogin_name(), "true", 7200);
                SecurityCommonUtils.putRedis(user.getUser_id().toString() + REDIS_USER_OPENID_SUFFIX, openId);
                SecurityCommonUtils.login(user, false);
                SavedRequest savedRequest = WebUtils.getSavedRequest(request);
                String url = "";
                if (null != savedRequest) {
                    url = savedRequest.getRequestUrl();
                    redirecturl = "redirect:" + url;//上一次访问的页面
                }else {
                    redirecturl = "redirect:" + HOME_URL;
            	}
            } else{
                redirecturl = "redirect:/pay/orders.shtml?orderId"+ state+"&code="+code;// 微付支付页面;*/
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("微信登录绑定出现异常出现异常!", e);
        }
        return redirecturl;
    }

获取到的用户信息为JSON数据,进行处理

{   
  "openid":" OPENID",
  "nickname": "用户昵称",
  "sex":"用户的性别",//,值为1时是男性,值为2时是女性,值为0时是未知
  "province":"省市",
  "city":"城市信息",
  "country":"国家地区",
  "headimgurl":"https://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46",//用户头像地址
  "privilege":[ "PRIVILEGE1" "PRIVILEGE2"     ],//用户特权信息
  "unionid": "unionid"
}

4、 模板消息

(1)准备工作

进入公众号,找到功能-模板消息-我的末班-从模板库中添加,进行新增模板库(需要审核)

进入模板详情查看对应参数,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bkUvTKcy-1604884542866)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201105114327432.png)]

{{first.DATA}}
{{keyword1.DATA}}
{{keyword2.DATA}}
{keyword3.DATA}}

{{keyword.DATA}}
{{remark.DATA}}

记录上方的的字段,传输模板消息时会用

(2)代码实现

发送请求

public boolean sendMessage(WxMsg wxMsg,String openid){
    HttpRequest req=new HttpRequest();
    if(StringUtils.isBlank(SecurityCommonUtils.getRedis("GLOBAL_ACCESS_TOKEN"))){//判断access token是否失效
        GetAccessToken.getasstoken(req);//获取accesstoken
    }
    
    //拼接连接 传入TOKEN
    String sendurl="https://api.weixin.qq.com/cgi-bin/message/template/send?						access_token="+SecurityCommonUtils.getRedis("GLOBAL_ACCESS_TOKEN");
    
    JSONObject map=spellMsg(wxMsg, openid);//拼接消息
    
    String results=req.sendPost(sendurl, map.toString());
    JSONObject tokenObj=JSON.parseObject(results);
    String errcode = tokenObj.getString("errcode");//获取返回值
    if(StringUtils.isNotBlank(errcode)&&errcode.equals("0")){
        logger.info("发送消息成功,返回代码————————"+errcode);
        return true;
    }else{
        logger.error("发送失败,返回错误代码————————"+errcode);
        return false;
    }
}

**消息拼接 **

public JSONObject spellMsg(WxEasyMsg wxEasyMsg,String openid){
	JSONObject result=new JSONObject(); 
	JSONObject data=new JSONObject(); 

    //{{first.DATA}}
	JSONObject first=new JSONObject(); 
    first.put("value","恭喜你购买成功");
    first.put("color","#173177");
    data.put("first",first);

  
    //{{keyword1.DATA}}
    JSONObject keyword1=new JSONObject();
    keyword1.put("value","巧克力");
    data.put("keyword1",keyword1);
    
	//{{keyword2.DATA}}
    JSONObject keyword2=new JSONObject();
    keyword2.put("value","39.8元");
    data.put("keyword2",keyword2);

    //{{keyword3.DATA}}
    JSONObject keyword3=new JSONObject();
    keyword3.put("value","2014年9月22日");
    data.put("keyword3",keyword3);

    //{{remark.DATA}}
    JSONObject remark=new JSONObject();
    remark.put("value","欢迎再次购买!");
    remark.put("color","#0000FF");
    data.put("remark",remark);
			
    result.put("touser","用户的OpenID");
    result.put("template_id","对应的模板ID");
    
    //详情页的回调地址
    result.put("url","你的详情地址");
    result.put("topcolor","#FF0000");
    result.put("data",data);
    return result;
}

拼接结果

{
    "touser":"OPENID",
    "template_id":"ngqIpbwh8bUfcSsECmogfXcV14J0tQlEpBO27izEYtY",
    "url":"http://weixin.qq.com/download",  
    "miniprogram":{
        "appid":"xiaochengxuappid12345",
        "pagepath":"index?foo=bar"
    },          
    "data":{
        "first": {
            "value":"恭喜你购买成功!",
            "color":"#173177"
        },
        "keyword1":{
            "value":"巧克力",
            "color":"#173177"
        },
        "keyword2": {
            "value":"39.8元",
            "color":"#173177"
        },
        "keyword3": {
            "value":"2014年9月22日",
            "color":"#173177"
        },
        "remark":{
            "value":"欢迎再次购买!",
            "color":"#173177"
        }
    }
}

**发送完毕 **

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l2ERXf7r-1604884542869)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201105120403950.png)]

二、 微信支付

1、准备工作

傻瓜式准备文档 : https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pages/ico-guide/chapter1_2.shtml

  1. 微信支付的帐号密码

  2. 商户号(mch_id):

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5N3jhI7x-1604884542870)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201105121630887.png)]

  1. 证书(cert):

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9ACSbhJg-1604884542873)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201105121800805.png)]

  2. 密码(password)

  3. API秘钥(key):API密钥属于敏感信息,请妥善保管不要泄露,如果怀疑信息泄露,请重设密钥。

  4. 选择并且开通对应的支付渠道

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PWZOw4CW-1604884542873)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201105122048517.png)]

场景介绍文档 : https://pay.weixin.qq.com/static/product/product_intro.shtml?name=jsapi

2、代码实现

​ 下订单前,需要获取用户的OPENID(使用静默授权即可,除非业务需要)

接口文档 : https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_10&index=1

JSAPI : https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_1

业务流程

微信内网页支付时序图

代码演示

sdk 工具,以及demo:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1

订单生成

function submit(){
    var name=$("#name").val();
    var phone=$("#phone").val();
    var sex=$("input[name='sex']:checked") .val();
    var contributionTypeId=$("#contributionTypeId").val();
    var price=$("#price").val();

    if(name==null || name==''){
        layer.msg("请填写姓名!");
        return false;
    }
    if(phone==null || phone==''){
        layer.msg("请填写手机号!");
        return false;
    }
    if(!(/^[1][0-9]{10}$/.test(phone))){
        layer.msg("请填写正确手机号!");
        return false;
    }
    if(sex==null || sex==''){
        layer.msg("请选择性别!");
        return false;
    }
    if(contributionTypeId==null || contributionTypeId==''){
        layer.msg("请选择捐款用途!");
        return false;
    }
    if(price==null || price=='' || price<=0){
        layer.msg("请填写正确的金额!");
        return false;
    }
    var data={
        name:name,
        phone:phone,
        sex:sex,
        contributionTypeId:contributionTypeId,
        price:price
    };

    $.post(ctx+"/wechat/savecontribution.shtml",data,function(data){//创建订单
        if(data.flag){
           $("#orderCode").val(data.orderCode);
            goPay();
        }else if(data.isNotLogin){
            window.location.href = ctx + "/wechat/wxlogin.shtml?isLogin=true";
        }else{
            layer.msg(data.msg);
        }
    });
}

支付js

function goPay(){
    var load = parent.layer.load(1, {
        shade : [ 0.3, '#393D49' ]
    });

    $.ajax({
        url : ctx + "/pay/orders.shtml",
        type : 'post',
        async:false,
        data : {
            orderCode : $("#orderCode").val()
        },
        success : function(data) {
            parent.layer.close(load);
            if (data.flag) {
                //固定写法开始 
                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(data.json);
                }
                //固定写法结束 
            }else if(data.status){
                parent.layer.msg(data.msg);
            }else if(data.wxlogin){
                parent.layer.msg(data.wxlogin);
                setTimeout(function(){
                    window.location.href = ctx + "/wechat/wxlogin.shtml?isLogin=true&orderId="+orderId;
                },3000);
            }
        }
    });
}

onBridgeReady

function onBridgeReady(data){
    WeixinJSBridge.invoke(
        'getBrandWCPayRequest', {
            "appId":data.appId,//公众号名称,由商户传入
            "timeStamp":data.timeStamp,//时间戳,自1970年以来的秒数
            "nonceStr":data.nonceStr, //随机串
            "package":data['package'],
            "signType":data.signType,//微信签名方式:
            "paySign":data.paySign //微信签名
        },
        function(res){
            if (res.err_msg == "get_brand_wcpay_request:ok" ) {
                setCodeTimer();
            } else {
                layer.msg("支付失败");
            }
        }
    );
}

轮询查询支付结果

function setCodeTimer() {
    var time=120;
    var codeTimer = window.setInterval(function() {
        time=time--;
        $.ajax({
            url : ctx+"/pay/getnotify.shtml",
            type : 'post',
            data:{
                orderCode:$("#orderCode").val()
            },
            success : function(data) {
                if(data.flag){
                    window.clearInterval(codeTimer);
                    layer.msg("捐赠成功,感谢您的捐赠!");
                    setTimeout(function(){
                        location.href = ctx + "/wechat/home.shtml";
                    },2000);

                }
            }
        });
        if (time == 0) {
            window.clearInterval(codeTimer);
            layer.msg("订单已过期");
            setTimeout(function(){
                location.href =location.href = ctx + "/wechat/home.shtml";
            },2000);
        }
    },1500);
}

微信预下单操作

/**
    * @Description 微信浏览器内微信支付/公众号支付(JSAPI)
    * @param request
    * @param code
    * @return Map
    */
@RequestMapping(value="orders", method = RequestMethod.POST)
@ResponseBody
public Map orders(HttpServletRequest request,String orderCode) {
   Map<String, Object> payMap = new HashMap<String, Object>();
   boolean resultBool = false;
   payMap.put("flag",false);
   if(StringUtils.isBlank(orderCode)){
       payMap.put("msg","订单号为空!");
       return payMap;
   }
   Map<String, String> map = new HashMap<String, String>();
   try {
       ContributionOrder contributionOrder=contributionOrderService.getContributionOrderByOrderCode(orderCode);
       if(contributionOrder!=null){
           if(contributionOrder.getStatus()!=0){
               payMap.put("status",true);
               payMap.put("msg","捐赠订单状态异常,请重新下单!");
               return payMap;
           }
           if(request.getSession().getAttribute("openId")==null){
               payMap.put("wxlogin",true);
               payMap.put("msg","暂未登录,请登录后重新捐赠!");
               return payMap;
           }

           //页面获取openId接口
           String nonceStr = getRandomStringByLength(32);
           String appid = SysConfigManager.getInstance().getText("/config/wx/appid");
           String key = SysConfigManager.getInstance().getText("/config/wxpay/key");
           String mchId =SysConfigManager.getInstance().getText("/config/wx/wxpay");
           String notifyUrl = SysConfigManager.getInstance().getText("/config/wxpay/notify_url");
           String unifiedorderUrl = SysConfigManager.getInstance().getText("/config/pay/unifiedorder");
           String openId=request.getSession().getAttribute("openId").toString();
           String sign = Signature.getSign(map, key);
           String ip = CommonUtils.getIpAddr(request);
           if(ip.contains(",")){
               ip = ip.split(",")[0];
           }

           map.put("appid", appid);//公众账号ID
           map.put("mch_id", mchId);//商户号ID
           map.put("nonce_str", nonceStr);//随机字符串
           map.put("sign", sign);//签名
           map.put("body", "爱心捐赠:[" + contributionOrder.getPrice() + "] 费用");//商品描述
           map.put("out_trade_no", contributionOrder.getOrderCode());//订单号

           //交易金额默认为人民币交易,接口中参数支付金额单位为【分】,参数值不能带小数。对账单中的交易金额单位为【元】
           map.put("total_fee",""+(new Double(contributionOrder.getPrice() * 100)).intValue());//标价金额
           map.put("spbill_create_ip", ip);//IP地址
           map.put("notify_url",notifyUrl);// 此路径是微信服务器调用支付结果
           map.put("trade_type", "JSAPI");
           map.put("openid",openId);
           String xml = WXPayUtil.mapToXml(map);//将所有参数(map)转xml格式
           String result = PayUtils.invokeHttpsMethod(unifiedorderUrl, xml);
           Map resultMap = PayUtils.getMapFromXML(result);

           String returnCode = resultMap.get("return_code").toString();//返回状态码
           String resultCode = resultMap.get("result_code").toString();//业务结果
           String timeStamp = String.valueOf(System.currentTimeMillis());
           String nonceStr2 = getRandomStringByLength(32);

           payMap.put("appId", appid);
           payMap.put("timeStamp", timeStamp);
           payMap.put("nonceStr", nonceStr2);
           payMap.put("orderCode", contributionOrder.getOrderCode());
           payMap.put("price", contributionOrder.getPrice());
           String prepayId = "";
           if ("SUCCESS".equals(returnCode.toUpperCase()) && "SUCCESS".equals(resultCode.toUpperCase())) {//SUCCESS/FAIL
               prepayId = resultMap.get("prepay_id").toString();
               resultBool = true;
           }
           if (!resultBool) {
               logger.error("微信下单失败,订单号:" + contributionOrder.getOrderCode() + " 返回信息:" + result);
           }
           String returnSign = createSign(appid, timeStamp, nonceStr, prepayId, key);

           payMap.put("prepay_id", prepayId);
           payMap.put("paySign", returnSign);
           payMap.put("flag",true);
       }

   } catch (Exception e) {
       e.printStackTrace();
   }
   return payMap;
}

随机字符串

/**
     * 获取一定长度的随机字符串
     *
     * @param length
     *            指定字符串长度
     * @return 一定长度的字符串
     */
private static String getRandomStringByLength(int length) {
    String base = "abcdefghijklmnopqrstuvwxyz0123456789";
    Random random = new Random();
    StringBuffer sb = new StringBuffer();
    for (int i = 0; i < length; i++) {
        int number = random.nextInt(base.length());
        sb.append(base.charAt(number));
    }
    return sb.toString();
}

**发送请求 **

public static String invokeHttpsMethod(String url,Object xmlObj) {
    CloseableHttpClient httpClient = null;
    HttpPost httpPost = null;
    String result = null;
    try {
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        // 证书路径
        String certPath = SysConfigManager.getInstance().getText("/config/wxpay/cert");
        String certPassword = SysConfigManager.getInstance().getText("/config/wxpay/password");
        FileInputStream instream = new FileInputStream(new File(certPath));
        //FileInputStream instream = new FileInputStream(new File(SysConfigManager.getInstance().getText("/config/wechatpay/cert")));
        //String certPassword = SysConfigManager.getInstance().getText("/config/wechatpay/password");
        keyStore.load(instream, certPassword.toCharArray());
        SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore,certPassword.toCharArray()).build();
        // Allow TLSv1 protocol only
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1"}, null,SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
        httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(10000).setConnectTimeout(30000).build();
        httpPost = new HttpPost(url);
        //设置请求器的配置
        httpPost.setConfig(requestConfig);
        //解决XStream对出现双下划线的bug
        XStream xStreamForRequestPostData = new XStream(new DomDriver("UTF-8", new XmlFriendlyNameCoder("-_", "_")));
        xStreamForRequestPostData.alias("xml", OrderXml.class);
        //将要提交给API的数据对象转换成XML格式数据Post给API
        String postDataXML = xStreamForRequestPostData.toXML(xmlObj);
        System.out.println("支付xml>>>>>>>>>>>>>>>>>>"+postDataXML);
        //得指明使用UTF-8编码,否则到API服务器XML的中文不能被成功识别
        StringEntity postEntity = new StringEntity(postDataXML, "UTF-8");
        httpPost.addHeader("Content-Type", "text/xml");
        httpPost.setEntity(postEntity);
        HttpResponse response = httpClient.execute(httpPost);
        HttpEntity entity = response.getEntity();
        result = EntityUtils.toString(entity, "UTF-8");
    } catch (KeyStoreException e) {
        e.printStackTrace();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (CertificateException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (KeyManagementException e) {
        e.printStackTrace();
    } catch (UnrecoverableKeyException e) {
        e.printStackTrace();
    }finally{
        if(httpPost!=null){
            httpPost.abort();
        }
        if(httpClient!=null){
            try {
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    return result;
}

回调后台

/**
     * 微信支付回调
     *
     * @param result
     * @return
     */
@RequestMapping(value = "/notify", produces = "application/xml;charset=UTF-8")
@ResponseBody
public String wxNotify(@RequestBody String result) {
    String notifyResult = null;
    if (StringUtils.isNotBlank(result)) {
        logger.info("微信回调报文:" + result);
        try {
            Map<String, Object> resultMap = PayUtils.getMapFromXML(result);
            String returnCode = (String) resultMap.get("return_code");
            if (StringUtils.isNotBlank(returnCode) && "SUCCESS".toUpperCase().equals(returnCode)) {
                String orderCode = (String) resultMap.get("out_trade_no");
                ContributionOrder contributionOrder=contributionOrderService.getContributionOrderByOrderCode(orderCode);

                String key = SysConfigManager.getInstance().getText("/config/wxpay/key");
                if (Signature.checkIsSignValidFromResponseString(result,key)) {
                    Integer totalfFee = Integer.parseInt(resultMap.get("total_fee").toString());
                    Integer orderPrice = new Double(contributionOrder.getPrice() * 100).intValue();

                    if (contributionOrder.getStatus() == 0 && orderPrice.equals(totalfFee)) {
                        contributionOrder.setStatus(1);//已支付
                        contributionOrderService.updateOrderPayStatus(contributionOrder);
                        notifyResult = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
                        SecurityCommonUtils.putRedis(VENUE_ORDER_NOTIFY_WX + contributionOrder.getOrderCode(), "OK", 300);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    return notifyResult;
}

三、微信开放平台

1、简介

简单的说,微信公众平台是给编辑的,微信开放平台是给技术的。

接口文档 : https://developers.weixin.qq.com/doc/oplatform/Mobile_App/Resource_Center_Homepage.html?action=dir_list&t=resource%2Fres_list&verify=1&lang=zh_CN&token=a4d21a0a5d1d4c40242e1af442d2e78e76378432

微信公众平台能干什么?

  • 写文章发文章

  • 和粉丝聊天

  • 配置菜单

  • 开通各种公众号的权限(仅限自己的公众号)

  • 启用开发者模式,开发自己的公众号

  • 投放广告

  • 查看数据

微信开放平台能干什么?

  • APP想用微信登录/分享到朋友圈等
  • PC网站想用微信登录等
  • 注册公众号第三方平台(服务所有公众号)
  • 注册小程序第三方平台(提供小程序模板)
  • 绑定公众号或小程序,以形成UnionID

2、绑定操作

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m1JV6ctK-1604884542876)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201105135222459.png)]

3、接口说明

(1)app接口信息
接口名称接口介绍接口状态操作
分享到朋友圈将内容分享到微信朋友圈已获得
发送给朋友将内容发送给朋友或者群聊已获得
微信支付获得微信支付能力 [详情](javascript:void(0)😉未获得[申请开通](javascript:void(0)😉
微信登录使用微信帐号登录App或者网站 [详情](javascript:void(0)😉已获得
微信卡券移动应用内领取卡券收入微信卡包 [详情](javascript:void(0)😉未获得[申请开通](javascript:void(0)😉
智能接口获得语音识别、图像识别、语义理解等模式识别能力已获得
一次性订阅消息用户授权后,开发者将获得发送一条订阅消息的权限已获得[查看模板id](javascript:😉
APP跳转小程序获得 APP 中跳转至微信小程序,且回到原 APP 的权限 详情已获得
(2)网站接口信息
接口名称接口介绍接口状态操作
微信登录使用微信帐号登录App或者网站 [详情](javascript:void(0)😉已获得
微信支付获得微信支付能力 [详情](javascript:void(0)😉未获得[申请开通](javascript:void(0)😉
(3)公众号接口信息
接口名称接口介绍接口状态操作
网页跳转移动应用微信内打开服务号的JS接口安全域名,可以跳转至已关联的移动应用。使用前需关联移动应用和域名 详情未获得
(4)小程序接口信息
接口名称接口介绍接口状态操作
网页跳转移动应用微信内打开服务号的JS接口安全域名,可以跳转至已关联的移动应用。使用前需关联移动应用和域名 详情未获得

微信登录 | 使用微信帐号登录App或者网站 [详情](javascript:void(0)😉 | 已获得 | – |
| 微信支付 | 获得微信支付能力 [详情](javascript:void(0)😉 | 未获得 | [申请开通](javascript:void(0)😉 |

(3)公众号接口信息
接口名称接口介绍接口状态操作
网页跳转移动应用微信内打开服务号的JS接口安全域名,可以跳转至已关联的移动应用。使用前需关联移动应用和域名 详情未获得
(4)小程序接口信息
接口名称接口介绍接口状态操作
网页跳转移动应用微信内打开服务号的JS接口安全域名,可以跳转至已关联的移动应用。使用前需关联移动应用和域名 详情未获得
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
功能说明 1、可以对微信好友分类分组,比如分成客户组,员工组,可针对好友分组群发微信。 2、可以设置聊天机器人,让你的个人微信拥有自动根据预设关键字回复客户,跟据这功能可制成菜单型式的回复,使你的个人微信也具有微信公众号的功能,还不受众号那样的发信息限制。 3、集成了微信接口,具有获取好友列表及接收和发送微信功能,让你非常方便的集成到企业的OA办公系统、订单状态监控、服务器运行状态监控等。 使用说明: 1、请用手机微信扫描右边二维码登录系统(如不显示二维码,请“刷新页面”)。 2、本系统所有操作都是通过模拟控制网页实现,请不要直接操作右边的“微信网页版”,以免影响本软件的正常操作。 3、建议一个注册账号只对应一个微信账号,否则历史信息会混乱。 4、本软件免费用户信息带尾巴,批量发送每次限制10条,超过部分被忽略(用户可分多批发),使用时间不限制。 5、本软件付费会员不受以上第4条限制,会员时间到期后自动转成免费用户。 ***微信接口命令说明*** ****************************************** islogin 确定服务或微信是否登录 返内容如下几种: 1)"已登录" 表示都已经登录 2)"客服和微信都未登录" 3)"客服未登录' 4)"微信未登录" Url示例:http://127.0.0.1:8081/islogin ****************************************** logincode 取得登录二维码图片,以便远程手机扫描登录 如果返回非图片,表示出错或返回"微信已登录"这几字 网页中显示图示例: ****************************************** list 获取客户列表 以Xml文本格式返回列表 开发者可以直接转为DataTable,C#代码示例如下: WebClient webc = new WebClient(); string xmltxt=webc.DownloadString("http://127.0.0.1:8081/list"); DataTable dt=XmlTxtToDataTable(xmltxt); private DataTable XmlTxtToDataTable(string XmlTxt) {//Xml文本转DataTable XmlDocument doc = new XmlDocument(); doc.LoadXml(XmlTxt); XmlNodeReader xnr = new XmlNodeReader(doc); DataSet ds = new DataSet(); ds.ReadXml(xnr); DataTable dt = ds.Tables[0]; return dt; } ****************************************** getimg 取得客户图标 参数 uname=客户名(必选) (用list获取到的客户名) 如果返回非图片,表示出错或返回"客户名为空或找不到。"等字符 网页中显示图示例: ****************************************** send 发送信息 参数 uname=目标客户名(必选) (用list获取到的客户名) msg=信息内容(必选) time=定时发送时间(可选),格式:"yyyy-MM-dd HH:mm:ss" msid=调用者定的信息ID(可选,是大于0数字才有效),用于在sendend判断发送结果 返回以下情况 1)"ok"表示成功加入到发送队列(不是已发成功),是否成功要用sendend命令根据"信息ID"查 2)返回其它信息表示出错信息 GET提交示例:http://127.0.0.1:8081/send?uname=客户名&msg=信息内容&time=2016-03-15 15:20:00&msid=3 ****************************************** sendend 判断发送结果 参数 msid=调用者在发送时定的信息ID 返回以下情况 "ok"=发送成功 "err"=发送出错

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值