精华内容
下载资源
问答
  • 微信公众号支付是指在微信内嵌浏览器进入到公众号之后,点击电商页面的支付接口,他使用了微信内嵌浏览器的支持,开发步骤如下: (1)首先开通企业公众号账户并且开通支付接口,详细步骤可以参考相关文档,这里...

    微信公众号支付是指在微信内嵌浏览器进入到公众号之后,点击电商页面的支付接口,他使用了微信内嵌浏览器的支持,开发步骤如下:

    (1)首先开通企业公众号账户并且开通支付接口,详细步骤可以参考相关文档,这里不再细数,这一步问题不大,主要是企业账号等信息要设置准确,除了公众号还有企业商户号要设置。

    (2)将用户openid传递到支付链接的参数中,例如:

    <a href="/product/buy?id=productid&openid=user_openid">支付     </a>

    (3)先写好支付成功后的微信回调函数处理程序,成功的话微信会访问配置好的通知url(notify_url),会尝试8次直到我们写回去success或者fail,示例代码如下:

    @RequestMapping(value = "/wxpaycallback", method = { RequestMethod.POST,
                RequestMethod.GET }, produces = { "application/json;charset=utf-8" })
        public String weixinNotify(HttpServletRequest request,
                HttpServletResponse response) {
            try {
                response.setCharacterEncoding("UTF-8");
                InputStream inStream = request.getInputStream();
                ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
                byte[] buffer = new byte[1024];
                int len = 0;
                while ((len = inStream.read(buffer)) != -1) {
                    outSteam.write(buffer, 0, len);
                }
                outSteam.close();
                inStream.close();
                String resultStr = new String(outSteam.toByteArray(), "utf-8");
                 Map<String, String> resultMap =MessageUtil.parseXml(resultStr);
                 String out_trade_no = resultMap.get("out_trade_no");//订单号
                 String return_code = resultMap.get("return_code");
                 String mch_id=resultMap.get("mch_id");        
                if (return_code.contains("SUCCESS")) {
                    // 此处就是你的逻辑代码
                    if (mch_id.equals(WeixinUtil.MCH_ID)){
                        OrderLogic.finishOrder(out_trade_no);//处理该订单的状态
                    }
                }
                //返回消息给微信服务器
                String retXml = "<xml>  <return_code><![CDATA[SUCCESS]]></return_code>  <return_msg><![CDATA[OK]]></return_msg></xml>";
                PrintWriter out = response.getWriter();
                out.print(retXml);
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return "success";//这句话可以不用吧?
        }

     

    (4)Js端代码:

    商品页面增加以下代码就会调用支付流程:

        function onBridgeReady() {        
            var appId = $('#appId').val();// getUrlParam('appId');        
            var timeStamp = $('#timeStamp').val();//  getUrlParam('timeStamp');
            var nonceStr = $('#nonceStr').val();//  getUrlParam('nonceStr');
            var Package = $('#packageid').val();//  getUrlParam('package');
            var signType =  $('#signType').val();// getUrlParam('signType');
            var paySign =  $('#paySign').val();// getUrlParam('paySign');
            WeixinJSBridge.invoke('getBrandWCPayRequest', {
                "appId" : appId, //公众号名称,由商户传入
                "timeStamp" : timeStamp,// "1395712654", //时间戳,自1970年以来的秒数
                "nonceStr" : nonceStr,// "e61463f8efa94090b1f366cccfbbb444", //随机串
                "package" : Package,// "prepay_id=u802345jgfjsdfgsdg888",
                "signType" : signType,// "MD5", //微信签名方式:
                "paySign" : paySign,// "70EA570631E4BB79628FBCA90534C63FF7FADD89"
                                    // //微信签名
            }, function(res) { // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回
                                // ok,但并不保证它绝对可靠。
                // alert(res.err_msg);
                if (res.err_msg == "get_brand_wcpay_request:ok") {
                    alert("success");
                }
                if (res.err_msg == "get_brand_wcpay_request:cancel") {
                    alert("cancel");
                }
                if (res.err_msg == "get_brand_wcpay_request:fail") {
                    alert("fail");
                }
            });
        }

        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();
            }
        }

     

    (5)还需要预先调用预下单接口才行,这部分代码暂时找不到了,后面补充。

    写的不是很流畅,第一次写,感觉微信支付接口挺绕的,不如支付宝来的简洁。

    附件:

    微信用户在不同的公众号里时候openid值是不一样的,因此在支付的时候要先将用户的openid获取到传递给支付页面。获取openid一个方式是通过Oauth链接,就是说先进入Oauth地址,将H5页面url作为参数传递给Oauth链接,微信会回调这个url并将随机的code传给这个H5,通过code来查询微信api获取openid值。

    public class WeixinLogic {
        private static final Logger logger = LoggerFactory
                .getLogger(WeixinLogic.class);
        private static Gson gson = MyGlobal.gson();

        /*
         * 生成并记录短信验证码到数据库
         */
        private static String genBindSmsCode(String mobile) {
            String code = "";
            DB db = MyMongo.getDB();
            if (db != null) {
                code = UserLogic.createRandom(true, 4);
                DBCollection collection = db.getCollection("wxsmscode");
                BasicDBObject cond = new BasicDBObject("mobile", mobile);
                DBObject obj = collection.findOne(cond);
                if (obj != null) {
                    DBObject doc = new BasicDBObject("$set", new BasicDBObject(
                            "code", code));
                    collection.update(cond, doc);
                } else {
                    DBObject doc = new BasicDBObject().append("mobile", mobile)
                            .append("code", code);
                    collection.insert(doc);
                }
            }
            return code;
        }

        /*
         * 发送短信验证码
         */
        public static void SendSmsCode(String mobile) {
            String code = genBindSmsCode(mobile);
            UserLogic.sendSmsCode(mobile, code);
        }

        /*
         * 绑定公众号和手机号 成功返回true
         */
        public static boolean bindwx(String openid, String mobile, String code) {
            boolean ret = false;
            if (!isMobileExist(mobile)) {
                return false;
            }
            if (!checkSmsCode(mobile, code)) {
                return false;
            }
            String old = getbindmobile(openid);
            DB db = MyMongo.getDB();
            if (db != null) {
                DBCollection collection = db.getCollection("bindweixin");
                if (!old.equals("")) {
                    collection.remove(new BasicDBObject("openid", openid));
                }
                try {
                    BindWeixin info = new BindWeixin();
                    DBObject doc = (DBObject) JSON.parse(gson.toJson(info));
                    collection.insert(doc);
                    return true;
                } catch (Exception e) {
                    logger.error("bindwx" + e.getMessage());
                    return false;
                }
            }
            return ret;
        }

        private static boolean isMobileExist(String mobile) {
            boolean ret = true;

            return ret;
        }

        /*
         * 短信码是否正确
         */
        private static boolean checkSmsCode(String mobile, String code) {
            boolean ret = false;
            DB db = MyMongo.getDB();
            if (db != null) {
                DBCollection collection = db.getCollection("wxsmscode");
                BasicDBObject cond = new BasicDBObject("mobile", mobile).append(
                        "code", code);
                DBObject obj = collection.findOne(cond);
                if (obj != null) {
                    ret = true;
                }
            }
            return ret;
        }

        /*
         * 返回微信用户绑定的手机号
         */
        public static String getbindmobile(String openid) {
            String mobile = "";
            DB db = MyMongo.getDB();
            if (db != null) {
                DBCollection collection = db.getCollection("bindweixin");
                try {
                    DBObject obj = collection.findOne(new BasicDBObject("openid",
                            openid));
                    if (obj != null) {
                        BindWeixin info = gson.fromJson(obj.toString(),
                                BindWeixin.class);
                        mobile = info.mobile;
                    }
                } catch (Exception e) {
                    logger.error("getbindmobile:" + e.getMessage());
                }
            }
            return mobile;
        }

        
        public static void sendWXMonny(String re_openId, int money) {
            String URL = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack";
            String mch_id =WeixinUtil.MCH_ID;
            SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
            parameters.put("wxappid",WeixinUtil.APPID);
            parameters.put("mch_id", mch_id);
            String nonscr = UUID.randomUUID().toString().toUpperCase()
                    .replace("-", "");
            parameters.put("nonce_str", nonscr);// 随机字符串
            parameters.put("send_name", "中医管家");
            String billno = createBillNo(mch_id, "01");
            parameters.put("mch_billno",billno);        
            parameters.put("re_openid", re_openId);//我的微信openid: "oW9-5s8Aecs_teXlIuwTwNbLQyHk"        
            parameters.put("total_amount",money+"");
            parameters.put("total_num", "1");
            parameters.put("wishing", "中医管家");
            parameters.put("client_ip", "127.0.0.1");
            parameters.put("act_name", "测试红包用例");
            parameters.put("remark", "中医管家");
        
            // String sign = createSign("UTF-8", parameters);
            // parameters.put("sign", sign);
            sign(parameters);
            String requestXML = getRequestXml(parameters);
            String result = httpsRequest(URL, "POST", requestXML);
            System.out.println("result:" + result);
        }
        
        
        public static String unifiedOrder(String openid,String trade_no,int fee,String doctorName){
            //统一下单支付
            String unified_url="https://api.mch.weixin.qq.com/pay/unifiedorder";
            String notify_url="http://123.56.140.11/health/wxpaycallback";
    //        trade_no=UUID.randomUUID().toString().replace("-","");    
            try {
              //生成sign签名
              SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();
              parameters.put("appid",WeixinUtil.APPID); 
              parameters.put("attach", "中医管家");
              parameters.put("body",doctorName);
              parameters.put("mch_id",WeixinUtil.MCH_ID);
              String nonscr =trade_no;// UUID.randomUUID().toString().toUpperCase().replace("-", "");
              parameters.put("nonce_str", nonscr);
              parameters.put("notify_url",notify_url);
              parameters.put("out_trade_no", trade_no);
              parameters.put("total_fee",fee+"");
              parameters.put("trade_type", "JSAPI");
              parameters.put("spbill_create_ip","127.0.0.1");
              parameters.put("openid", openid);
              parameters.put("device_info", "WEB");
              sign(parameters);
                String requestXML = getRequestXml(parameters);
                String result =WeixinUtil. httpsRequest(unified_url, "POST", requestXML);
                System.out.println("result:" + result);
                return result;
            } catch (Exception e) {
              e.printStackTrace();
            } 
            return "";
          }
        
        private static String getRandomNum(int length) {
            String val = "";
            Random random = new Random();
            for (int i = 0; i < length; i++) {
                val += String.valueOf(random.nextInt(10));
            }
            return val;
        }

        public static String createBillNo(String mch_id, String userId) {
            // 组成: mch_id+yyyymmdd+10位一天内不能重复的数字
            // 10位一天内不能重复的数字实现方法如下:
            // 因为每个用户绑定了userId,他们的userId不同,加上随机生成的(10-length(userId))可保证这10位数字不一样
            Date dt = new Date();
            SimpleDateFormat df = new SimpleDateFormat("yyyymmdd");
            String nowTime = df.format(dt);
            int length = 10 - userId.length();
            return mch_id + nowTime + userId + getRandomNum(length);
        }

        
        public static void sign(SortedMap<Object, Object> params) {
             String KEY =WeixinUtil.APIKEY;
            Set<Entry<Object, Object>> entrys = params.entrySet();
            Iterator<Entry<Object, Object>> it = entrys.iterator();
            StringBuffer result = new StringBuffer();
            while (it.hasNext()) {
                Entry<Object, Object> entry = it.next();
                result.append(entry.getKey()).append("=").append(entry.getValue())
                        .append("&");
            }
            result.append("key=").append(KEY);
            params.put("sign", MD5Util.MD5Encode(result.toString(), "UTF-8")
                    .toUpperCase());
        }
        /*
         * 发送红包接口示例
         */
        
        
        

        public static String getRequestXml(SortedMap<Object, Object> parameters) {
            StringBuffer sb = new StringBuffer();
            sb.append("<xml>");
            Set<Entry<Object, Object>> es = parameters.entrySet();
            Iterator<Entry<Object, Object>> it = es.iterator();
            while (it.hasNext()) {
                @SuppressWarnings("rawtypes")
                Map.Entry entry = (Map.Entry) it.next();
                String k = (String) entry.getKey();
                String v = String.valueOf(entry.getValue());
                if ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k)
                        || "sign".equalsIgnoreCase(k)) {
                    sb.append("<" + k + ">" + "<![CDATA[" + v + "]]></" + k + ">");
                } else {
                    sb.append("<" + k + ">" + v + "</" + k + ">");
                }
            }
            sb.append("</xml>");
            return sb.toString();
        }

        /**
         * 发送https请求
         * 
         * @param requestUrl
         *            请求地址
         * @param requestMethod
         *            请求方式(GET、POST)
         * @param outputStr
         *            提交的数据
         * @return 返回微信服务器响应的信息
         */
        public static String httpsRequest(String requestUrl, String requestMethod,
                String outputStr) {
            try {
                String result = "";
                // // 创建SSLContext对象,并使用我们指定的信任管理器初始化
                // TrustManager[] tm = { new MyX509TrustManager() };
                // SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
                // sslContext.init(null, tm, new java.security.SecureRandom());
                // // 从上述SSLContext对象中得到SSLSocketFactory对象
                // SSLSocketFactory ssf = sslContext.getSocketFactory();

                // 指定读取证书格式为PKCS12
                KeyStore keyStore = KeyStore.getInstance("PKCS12");
                // 读取本机存放的PKCS12证书文件
                FileInputStream instream = new FileInputStream(new File(
                        "/root/apiclient_cert.p12"));
                try {
                    // 指定PKCS12的密码(商户ID)
                    keyStore.load(instream,WeixinUtil.MCH_ID.toCharArray());
                } finally {
                    instream.close();
                }
                SSLContext sslcontext = SSLContexts.custom()
                        .loadKeyMaterial(keyStore, WeixinUtil.MCH_ID.toCharArray())
                        .build();
                // 指定TLS版本
                SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                        sslcontext,
                        new String[] { "TLSv1" },
                        null,
                        SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);

                CloseableHttpClient httpclient = HttpClients.custom()
                        .setSSLSocketFactory(sslsf).build();

                //URL url = new URL(requestUrl);
                HttpPost httpPost = new HttpPost(requestUrl);
                StringEntity reqEntity = new StringEntity(outputStr, "utf-8"); // 如果此处编码不对,可能导致客户端签名跟微信的签名不一致
                reqEntity.setContentType("application/x-www-form-urlencoded");
                httpPost.setEntity(reqEntity);
                CloseableHttpResponse response = httpclient.execute(httpPost);
                try {
                    HttpEntity entity = response.getEntity();
                    if (entity != null) {
                        BufferedReader bufferedReader = new BufferedReader(
                                new InputStreamReader(entity.getContent(), "UTF-8"));
                        String text;
                        while ((text = bufferedReader.readLine()) != null) {
                            result += text;
                        }
                    }
                    EntityUtils.consume(entity);
                } finally {
                    response.close();
                }
                return result;
                // HttpsURLConnection conn =
                // (HttpsURLConnection)httpclient.execute(httpPost);//
                // url.openConnection();
                // conn.setSSLSocketFactory(sslsf);
                // conn.setDoOutput(true);
                // conn.setDoInput(true);
                // conn.setUseCaches(false);
                // // 设置请求方式(GET/POST)
                // conn.setRequestMethod(requestMethod);
                // conn.setRequestProperty("content-type",
                // "application/x-www-form-urlencoded");
                // // 当outputStr不为null时向输出流写数据
                // if (null != outputStr) {
                // OutputStream outputStream = conn.getOutputStream();
                // // 注意编码格式
                // outputStream.write(outputStr.getBytes("UTF-8"));
                // outputStream.close();
                // }
                // // 从输入流读取返回内容
                // InputStream inputStream = conn.getInputStream();
                // InputStreamReader inputStreamReader = new InputStreamReader(
                // inputStream, "utf-8");
                // BufferedReader bufferedReader = new BufferedReader(
                // inputStreamReader);
                // String str = null;
                // StringBuffer buffer = new StringBuffer();
                // while ((str = bufferedReader.readLine()) != null) {
                // buffer.append(str);
                // }
                // // 释放资源
                // bufferedReader.close();
                // inputStreamReader.close();
                // inputStream.close();
                // inputStream = null;
                // conn.disconnect();
                // return buffer.toString();
            } catch (ConnectException ce) {
                logger.error("连接超时:{}", ce);
            } catch (Exception e) {
                logger.error("https请求异常:{}", e);
            }
            return null;
        }
    }

    转载于:https://my.oschina.net/u/778683/blog/829006

    展开全文
  • 微信外部浏览器或短信链接唤起微信公众号的解决方案背景利用天天外链实现微信外部浏览器或短信链接唤起微信公众号 背景 目前想实现微信外部浏览器或短信链接唤起微信公众号,即微信外部环境下,直接唤起微信并进入到...

    微信外部浏览器或短信链接唤起微信公众号的解决方案

    背景

    目前想实现微信外部浏览器或短信链接唤起微信公众号,即微信外部环境下,直接唤起微信并进入到微信公众号内,引导用户去关注微信公众号。但是目前微信官方并未提供这样的api接口,不过仍然有可实现的途径,即借助第三方平台可实现该功能

    利用第三方平台实现微信外部浏览器或短信链接唤起微信公众号

    第三方平台如天天外链明确提供了将公众号生成链接,在微信外部环境下可直接跳转关注公众号这样的功能
    在这里插入图片描述

    具体参考:https://developers.weixin.qq.com/community/develop/doc/000c80fa13c490f845394a0a151c00

    展开全文
  • 本教程的学习条件:了解微信公众号开发的基本知识。已经申请了微信公众号并设置了开发模式等。如果不了解,请先到微信官方平台学习需要服务器端开发的基本技能,本文主要讲解流程,基本不涉及具体开发语言。首先我们...

    本教程的学习条件:

    了解微信公众号开发的基本知识。已经申请了微信公众号并设置了开发模式等。如果不了解,请先到微信官方平台学习

    需要服务器端开发的基本技能,本文主要讲解流程,基本不涉及具体开发语言。

    首先我们要明确绑定微信用户和系统用户,其目的是为了用户在一次绑定以后,再次通过微信访问系统时可以由系统自动为其登录,避免用户反复登录操作,使用户操作体验更流畅。

    微信绑定用户的核心逻辑其实就是把微信用户的 OpenID 和本系统的用户 UserId 建立关联关系。目前可以获得微信用户的 OpenID 的方法有 2 种:

    1 从用户交互的 xml 中获取:

    获取不需要授权页面,但是需要用户主动和公众号互动,常见的方式是使用公众号菜单,设置为回复消息,在用户点击菜单事件推送到服务器接口的 XML 中获取 OpenId ,然后组织一个与 OpenId 相关的链接放到回复内容里,用户点击此链接再跳转到绑定页面。

    2 使用网页授权获取用户基本信息

    这是利用微信提供的 OAuth2.0 接口,不需要用户额外点击菜单项和回复消息中的,可以直接从微信公众号里的移动站点任何页面发起。尤其是绑定用户时只需要知道 OpenId,不需要完善的用户信息,还可以使用微信提供的静默授权模式,这时连用户授权的页面都不用出现,获取 OpenId 的过程对用户几乎是透明的,这种流程更流畅。

    本文重点介绍第 2 种方式。对应的微信官方文档在 网页授权获取用户基本信息

    先看一下整体流程图。

    用户已登录的判断是通过本系统自行判断的。检测出用户未登录时,程序跳转到微信 OAuth 授权页,比如

    %3A%2F%2Fchong.qq.com%2Fphp%2Findex.php%3Fd%3D%26c%3DwxAdapter%26m%3DmobileDeal%26showwxpaytitle%3D1%26vb2ctag%3D4_2030_5_1194_60&response_type=code&scope=snsapi_base&state=123#wechat_redirect

    注意我们使用的静默授权方式,scope 参数要取值 snsapi_base。redirect_uri 参数值是要跳回我系统的 URL 地址,这里要进行 URL 编码。

    跳转到微信授权页时,不需要用户点击授权,所以不会停,直接跳回到本系统的 URI,并且在其后再加上 code 参数,如上例中的

    而这个跳回的页面,就是获取 OpenId 的程序所在。这页程序里使用跳回时得到的 code 参数值,再去调用微信服务器 access_token 接口即可得到 OpenId,即这个接口在返回 access_token 的同时也会返回 OpenId:

    注意这个接口的 URL 前边是 ,和其它微信接口 是不同的!

    到此我们已经得到了微信用户的 OpenId,此时再输出一个登录表单给用户,让用户填写用户名/密码,或者使用现在更流利的用户登录方式,填写手机号获取短信验证码,POST 提交后,即可查到用户在本系统的 UserId,我们在服务器端记录关联关系,整个绑定过程就完成了。

    OpenId 作为微信用户标识字符串,出于完全考虑,原则上不能以明文方式出现在表单里以及在表单中提交上来。OpenId 防伪造防重复等等,网上已有不少研讨。我在实际开发中,发现比较简明的方式是直接使用有效期 5 分钟的 session 存储 OpenId,此 session 使用时立即失效,然后把 session 的 key 作为参数输出给用户端。

    展开全文
  • 微信公众号-给指定用户发送信息 文章目录微信公众号-给指定用户发送信息前言一、开通模板消息二、项目使用步骤1.引入库2.直接上代码controllerservice其他一些封装的类总结 前言 本篇主要讲解微信公众号中,根据...

    微信公众号-给指定用户发送信息


    前言

    本篇主要讲解微信公众号中,根据openID向指定用户发送消息。
    前置条件是:
    ①微信公众号已经被认证。
    ②微信公众号自定义菜单已设置。
    ③公众号设置->功能设置->JS接口安全域名、网页授权域名。
    ④已获取到AppId,AppSecret(开发->基本配置->公众号开发信息 中查看)。
    ⑤ip白名单已设置好(开发->基本配置->公众号开发信息->白名单 中设置)。
    ⑥服务器配置(开发/基本配置/ 填写服务器配置。本次章中未使用,因为功能简单,采用了链接的方式)
    ⑦至于根据code换token,加密签名这一些玩意就更多了,还有支付一些坑,mmp不说了

    微信的这些东西,做了八百遍每次都有踩不完的坑,官方文档,emm,官方文档算了吧,mmp
    鉴于找资料这么费劲, 准备写一下系列文章,从微信配置开始,包括以上全部前置条件、到使用,到服务器配置发布。 因懒取消原计划。
    如果有需要的说一下,反正我也不一定写。


    一、开通模板消息

    看剑,不看箭头,点击开通
    在这里插入图片描述

    可以从模板库中选择合适的模板,也可以自己添加,我用【工单消息提醒】模板做例子。

    {{first.DATA}}
    工单编号:{{keyword1.DATA}}
    工单标题:{{keyword2.DATA}}
    时间:{{keyword3.DATA}}
    {{remark.DATA}}
    在发送时,需要将内容中的参数({{.DATA}}内为参数)赋值替换为需要的信息
    

    二、项目使用步骤

    1.引入库

    1. hutool工具包。
    2. lombok插件自己装。
    3. 阿里巴巴的fastjson。
      代码如下(示例):
    <dependency>
       <groupId>cn.hutool</groupId>
        <artifactId>hutool-all</artifactId>
        <version>4.5.1</version>
    </dependency>
    
    <dependency>
       <groupId>com.alibaba</groupId>
       <artifactId>fastjson</artifactId>
       <version>1.2.54</version>
    </dependency>
    

    2.直接上代码

    controller

    	@Autowired
    	private WeChatMessageImpl weChatMessage;
    
    	@RequestMapping("/sendMessage")
        public R sendMessage() {
            try {
    
               WeChatConfig weChatConfig = new WeChatConfig();
    
                TemplateConfig first =  new TemplateConfig();
                first.setValue("first");
                TemplateConfig k1 =  new TemplateConfig();
                k1.setValue("k1");
                TemplateConfig k2 =  new TemplateConfig();
                k2.setValue("k2");
                TemplateConfig k3 =  new TemplateConfig();
                k3.setValue("k3");
                k3.setColor("#ff3800");//颜色可以不设置,为默认
                TemplateConfig remark =  new TemplateConfig();
                remark.setValue("remarksadfasdf");
                remark.setColor("#ff3800");
    
                WeChatOrderNoticeVo data = new WeChatOrderNoticeVo();
                data.setFirst(first);
                data.setKeyword1(k1);
                data.setKeyword2(k2);
                data.setKeyword3(k3);
                data.setRemark(remark);
    
    
                MessageTemplate<WeChatOrderNoticeVo> template = new MessageTemplate<>();
                template.setTemplate_id("消息模板id");
                template.setTopcolor("#808080");
                template.setTouser("要发送对象的openID");
                template.setUrl("#");
                template.setData(data);
    
                return weChatMessage.sendMessage(weChatConfig,template);
            } catch (Exception e) {
                e.printStackTrace();
                return R.fail("发送失败");
    
            }
        }
    

    service

    
    import cn.hutool.core.util.StrUtil;
    import com.alibaba.fastjson.JSONObject;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Service;
    
    
    @Service
    public class WeChatMessageImpl {
        private static Logger log = LoggerFactory.getLogger(WeChatMessageImpl.class);
        /**
         *  * 发送模板消息
         *  * weChatConfig 微信配置
         *  * MessageTemplate 消息模板
         * @return
         */
        public R sendMessage(WeChatConfig weChatConfig, MessageTemplate<WeChatOrderNoticeVo> wechatOrderNoticeTemplate ) {
            Token token = WeChatUtils.getToken(weChatConfig.getAppId(), weChatConfig.getAppSecret());
            if(null == token || StrUtil.isBlank(token.getAccessToken())){
                return R.fail("获取token失败");
            }
            String access_token = token.getAccessToken();
            String url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + access_token;
    
            String jsonString = JSONObject.toJSONString(wechatOrderNoticeTemplate).replace("day", "Day");
            log.info(jsonString);
    
            JSONObject jsonObject = WeChatUtils.httpsRequest(url, "POST", jsonString);
    
            System.out.println(jsonObject);
    
            if (null != jsonObject) {
                if (StrUtil.isBlank(jsonObject.getString("errcode"))
                        || !StrUtil.equals(jsonObject.getString("errcode"),"0")){
                    log.error("错误 errcode:{} errmsg:{}", jsonObject.getInteger("errcode"), jsonObject.getString("errmsg"));
                    return R.fail(jsonObject.toString());
                }
            }
            return R.ok(jsonObject);
        }
    }
    

    其他一些封装的类

    BaseTemplateField

    import lombok.Data;
    
    /**
     * @author :socilents
     * @date :Created in 2020/11/4 16:41
     * @description:微信模板基础字段(必填项),这些字段变量的名字不可改变,变了微信接口不认
     */
    @Data
    public class BaseTemplateField {
        //用户OpenID
        private String touser;
        //模板消息ID
        private String template_id;
        //点击详情后要进入的页面,可为空
        private String url;
        //标题颜色,根据官方文档写的,好像没啥卵用
        private String topcolor;
    }
    

    MessageTemplate

    import lombok.Data;
    
    /**
     * @author :socilents
     * @date :Created in 2020/11/4 16:39
     * @description:微信发送消息模板封装,
     * 同BaseTemplateField中的字段名称一样,不可以更改字段名称,否则不认
     */
    @Data
    public class MessageTemplate<T> extends BaseTemplateField {
    
        private T data;
    
    }
    

    MyX509TrustManager

    import javax.net.ssl.X509TrustManager;
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    
    /**
     * 信任管理器
     *
     */
    public class MyX509TrustManager implements X509TrustManager {
    
        @Override
        public void checkClientTrusted(X509Certificate[] arg0, String arg1)
                throws CertificateException {
    
        }
    
        @Override
        public void checkServerTrusted(X509Certificate[] arg0, String arg1)
                throws CertificateException {
    
        }
    
        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
    
    }
    
    

    TemplateConfig

    import lombok.Data;
    
    /**
     * @author :magangming
     * @date :Created in 2020/11/4 16:40
     * @description:微信模板字段设置
     */
    @Data
    public class TemplateConfig {
        //字段值
        private String value;
        //字体颜色
        private String color;
    }
    
    

    WeChatConfig

    import lombok.Data;
    
    /**
     * @author :magangming
     * @date :Created in 2020/11/4 17:07
     * @description:微信公众号的基本配置
     * 根据实际情况使用,这么写是为了方便展示
     */
    @Data
    public class WeChatConfig {
        private String appId="你的APPID";
        private String appSecret="你的appsecret";
    
        //为了方便展示写在这里,根据实际情况使用
        private String openId;
        private String templeId;
    }
    

    WeChatOrderNoticeVo

    import lombok.Data;
    
    /**
     * @author :socilents
     * @date :Created in 2020/11/4 16:51
     * @description:发送消息的封装类,
     * 工单模板内容 微信公众号通知模板
     * 这里我引用了工单消息提醒的模板,记得要在消息模板中添加
     */
    @Data
    public class WeChatOrderNoticeVo {
    
        private TemplateConfig first;
    
        private TemplateConfig keyword1;
    
        private TemplateConfig keyword2;
    
        private TemplateConfig keyword3;
    
        private TemplateConfig remark;
    }
    

    WeChatUtils

    
    import cn.hutool.core.util.StrUtil;
    import com.alibaba.fastjson.JSONException;
    import com.alibaba.fastjson.JSONObject;
    import com.kalvin.kvf.modules.web.entity.Token;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import javax.net.ssl.HttpsURLConnection;
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLSocketFactory;
    import javax.net.ssl.TrustManager;
    import java.io.BufferedReader;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.net.ConnectException;
    import java.net.URL;
    
    /**
     * @author :socilents
     * @date :2020/11/2 17:20
     * @description: 微信公众号指定openID发送消息工具类
     */
    public class WeChatUtils {
    
        private static Logger log = LoggerFactory.getLogger(WeChatUtils.class);
    
        // 凭证获取(GET)
        public final static String token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
    
        /**
         * @param requestUrl    请求地址
         * @param requestMethod 请求方式(GET、POST)
         * @param outputStr     提交的数据
         * @return JSONObject(通过 JSONObject.get(key) 的方式获取 JSON 对象的属性值)
         * @description: 发送 https 请求,方法有多种
         */
        public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {
    
            JSONObject jsonObject = null;
    
            try {
                // 创建 SSLContext 对象,并使用我们指定的信任管理器初始化
                TrustManager[] tm = {new MyX509TrustManager()};
                SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
                sslContext.init(null, tm, new java.security.SecureRandom());
                // 从上述 SSLContext 对象中得到 SSLSocketFactory 对象
                SSLSocketFactory ssf = sslContext.getSocketFactory();
    
                URL url = new URL(requestUrl);
                HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
                conn.setSSLSocketFactory(ssf);
    
                conn.setDoOutput(true);
                conn.setDoInput(true);
                conn.setUseCaches(false);
    
                // 设置请求方式(GET/POST)
                conn.setRequestMethod(requestMethod);
    
                // 当 outputStr 不为 null 时,向输出流写数据
                if (null != outputStr) {
                    OutputStream outputStream = conn.getOutputStream();
    
                    // 注意编码格式
                    outputStream.write(outputStr.getBytes("UTF-8"));
                    outputStream.close();
                }
    
                // 从输入流读取返回内容
                InputStream inputStream = conn.getInputStream();
                InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
                BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
                String str = null;
                StringBuffer buffer = new StringBuffer();
    
                while ((str = bufferedReader.readLine()) != null) {
                    buffer.append(str);
                }
    
                // 释放资源
                bufferedReader.close();
                inputStreamReader.close();
                inputStream.close();
                inputStream = null;
                conn.disconnect();
                jsonObject = JSONObject.parseObject(buffer.toString());
            } catch (ConnectException ce) {
                log.error(" 连接超时:{}", ce);
            } catch (Exception e) {
                log.error("https 请求异常:{}", e);
            }
    
            return jsonObject;
        }
    
        /**
         * @author :socilents
         * @date :2020/11/5 7:59
         * @param appId 凭证
         * @param secret 密钥
         * @description: 获取接口访问凭证
         */
        public static Token getToken(String appId, String secret) {
            Token token = null;
            String requestUrl = token_url.replace("APPID", appId).replace("APPSECRET", secret);
            // 发起GET请求获取凭证
            JSONObject jsonObject = httpsRequest(requestUrl, "GET", null);
    
            if (null != jsonObject) {
                if (StrUtil.isBlank(jsonObject.getString("errcode"))) {
                    try {
                        token = new Token();
                        token.setAccessToken(jsonObject.getString("access_token"));
                        token.setExpiresIn(jsonObject.getInteger("expires_in"));
                        log.info(jsonObject.getString("access_token"));
                    } catch (JSONException e) {
                        token = null;
                        // 获取token失败
                        log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInteger("errcode"), jsonObject.getString("errmsg"));
                    }
                }else {
                    log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInteger("errcode"), jsonObject.getString("errmsg"));
                    token = null;
                }
    
            }
            return token;
        }
    
    }
    

    返回结果R的封装

    
    import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
    import ****************************************.Constants;
    
    import java.io.Serializable;
    
    /**
     * 返回前端 数据封闭类
     */
    public class R implements Serializable {
    
        private static final long serialVersionUID = 1L;
    
        private Integer code;
        private String msg;
        private Object data;
        private Long total; // 分页信息:总条数
    
        public R() { }
    
        private R(int code, String msg, Object data) {
            this.code = code;
            this.msg = msg;
            if (data instanceof Page<?>) {
                Page<?> page = (Page<?>) data;
                this.total = page.getTotal();
                this.data = page.getRecords();
            } else {
                this.data = data;
            }
        }
    
        public static R ok() {
            return new R(Constants.OK_CODE, Constants.OK_MSG, null);
        }
    
        public static R ok(Object data) {
            return new R(Constants.OK_CODE, Constants.OK_MSG, data);
        }
    
        public static R ok(String msg, Object data) {
            return new R(Constants.OK_CODE, msg, data);
        }
    
        public static R fail(String msg) {
            return new R(Constants.FAIL_CODE, msg, null);
        }
    
        public static R invalidToken(String msg) {
            return new R(Constants.INVALID_TOKEN_CODE, msg, null);
        }
    
        public static R fail(int errorCode, String msg) {
            return new R(errorCode, msg, null);
        }
    
        public int getCode() {
            return code;
        }
    
        public String getMsg() {
            return msg;
        }
    
        public Object getData() {
            return data;
        }
    
        public Long getTotal() {
            return total;
        }
    
        public R setTotal(Long total) {
            this.total = total;
            return this;
        }
    }
    
    
    

    Constants

    /**
     * 常量类
     */
    public class Constants {
    
        public final static int OK_CODE = 200;
        public final static int FAIL_CODE = 400;
        public final static int OTHER_FAIL_CODE = 333;    // 其它错误
        public final static int INVALID_TOKEN_CODE = 10000;    // 其它错误
        public final static String OK_MSG = "请求成功";
        public final static String FAIL_MSG = "请求失败";
        public final static int STATUS_0 = 0;   // 可用状态
        public final static int STATUS_1 = 1;   // 禁用状态
    }
    
    

    发送成功之后的展示:
    在这里插入图片描述

    微信官方文档:
    https://mp.weixin.qq.com/advanced/tmplmsg?action=faq&token=505847577&lang=zh_CN


    总结

    wxsb。

    展开全文
  • C# 微信公众号开发

    2021-03-27 10:16:02
    微信公众号开发c# 下载项目》运行项目出现异常》点击加载全部文件,出现没有包含在项目中的文件请包含在项目中.包含bin 楼主QQ369841603 如有疑问请加好友,备注说明 一. ** 项目介绍 这个微信功能类,目前还未...
  • 关于微信公众号短链接数量和时效说明 经过测试 微信公众号.短链接 的时效是 经过三天后仍然可以访问 判定是永久类型,根据短链接实现原理判定 经过测试 微信公众号.短链接 在 微信公众平台.接口权限 上面显示的数字...
  • Java开发微信公众号

    2017-12-11 23:10:08
    1.首先需要注册,https://mp.weixin.qq.com/,然后设置公众号信息什么的,默认是使用的微信公众号自己的后台,如果只是需要做一些简单了的操作,比如固定的关键字自动回复等,没有复杂的需求,就可以直接使用微信...
  • 微信公众号平台: https://mp.weixin.qq.com/cgi-bin/home?t=home/index&lang=zh_CN&token=795093844w 微信公众号测试平台: https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login 账号密码...
  • 微信公众号支付总结

    2018-11-27 14:14:58
    公众号支付就尼玛是个天坑   首先场景介绍 ... 看完场景介绍后脑子里会觉得这个东西也太简单了8?...需要在微信公众号平台开通认证(开发者配置迁移到了商户平台),商户平台获取一些必要的参数; 微信公众...
  • 微信公众号相关 微信公众号相关,来源微信公众号开发 AccessToken 获取jsapi_ticket 推送的问题: 短信 《无限制》 模板消息(支付【7天内只能推送3条】 或者 提交form表单【7天内一次提交只能发一条】)模板消息 ...
  • delphi XE关于微信公众号支付及微信零钱支付的便捷解决方案
  • 看了下微信公众号的信息推送开发文档,发现不难,就是一个个借口对估计有点郁闷。然后看到了Wx-JAVA系列。看了下,感觉很香。开源、生态齐全,好就盘它。 二、依赖导入 <!-- 微信公众号 --> <dependency>...
  • phpWeChat PC+微信公众号开发核心框架v1.0.3针对v1.0.2版本出现的问题,主要修复了和增加了以下功能: 1、优化自定义模块操作; 2、优化安装过程; 3、修复一处在线支付的PHP版本兼容问题; 4、修复一处自定义模块的...
  • 本教程的学习条件: 了解微信公众号开发的基本知识。已经申请了微信公众号并设置了开发模式等。如果不了解,请先到微信官方平台学习 http://mp.weixin.qq.com/wiki。 需要服...
  • 微信公众号

    2018-09-15 20:44:31
    1. 公众号类型 订阅号 普通订阅号 认证订阅号 服务号 普通服务号 认证服务号 2. 订阅号 主要偏向于为用户传达资讯,(功能类似报纸杂志,为用户提供新闻信息或娱乐趣事),每天可群发1条消息; 适用...
  • 微信公众号发送手机号返回验证码

    千次阅读 2020-01-12 20:09:54
    微信公众号发送手机号返回验证码 MsgHandler中判断传递参数时候为手机号,如果为手机号则生成验证码返回 @Component public class MsgHandler extends AbstractHandler { @Override public ...
  • 微信公众号主要面向名人、政府、媒体、企业等机构推出的合作推广业务。在这里可以通过微信渠道将品牌推广给上亿的微信用户,减少宣传成本,提高品牌知名度,打造更具影响力的品牌形象。在推广微信公众号的时候大家...
  • 微信公众号模板消息

    2021-08-17 10:58:29
    目前项目中需要有一个除短信外其他方式通知或提醒用户业务操作的功能,故采用了微信的模板消息,把自己使用模板消息的过程和要点简要的记录一下。 一 、运营规则及使用规则 1.关于运营规则,注意: 解释一下:...
  • 微信门户开发框架源码 微信公众号平台开发框架源码 微信门户应用管理系统,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技术路线,界面层采用Boostrap + Metronic组合的前端框架,数据访问层支持Oracle...
  • 当下微信公众号几乎已经是每个公司必备的,但是大部分微信公众账号用户体验都欠佳,特别是涉及到用户绑定等,需要用户进行复杂的操作才可以和网站绑定,或者很多公司直接不绑定,而是每次都让用户填写账号密码。...
  • 关注微信公众号使其自动发送欢迎你关注消息 一般我们关注微信公众号时。他都会自动推送一条消息。欢迎您关注了某公众号。而今天我们所做的就是这个功能。 关注公众号时我们需要获取到用户的一些个人基本信息。 而...
  • 微信公众号平台也有自定义回复消息,比如我在公众号里发送关注你,我们在微信公众号平台设置关键字关注你(就是 有人发送这个关键字就要回复什么内容)设置成回复:你好,java!适用于这种固定信息,如果我发送...
  • 微信公众号安全测试

    千次阅读 2020-03-16 09:12:20
    微信公众平台,简称公众号,是腾讯公司于2012年月推出的,曾命名为“官号平台”和“媒体平台”,后改为公众平台,形成了一种独有的移动互联生态系统。 “利用公众账号平台进行自媒体活动,简单来说就是进行一对多的...
  • 终端用户关注客户微信公众号后,在公众号上可以接收到服务端发来的关联设备的报警信息 2、使用到的Javabean 2.1授权凭证 package cn.ibiandan.cloud.swimming.api.vo; import lombok.Data; import java.io....
  • 搭建企业级微信公众号 微信公众平台: https://mp.weixin.qq.com/cgi-bin/home?t=home/index&lang=zh_CN&token=795093844 微信公众号测试平台 ...
  • Flask 微信公众号开发

    2018-10-04 02:00:00
    公众号接口 1. 公众号消息会话 目前公众号内主要有这样几类消息服务的类型,分别用于不同的场景。 群发消息 公众号可以以一定频次(订阅号为每天1次,服务号为每月4次),向用户群发消息,包括文字消息、图文...
  • 因为要做网页的微信分享,分享的时候想自定义 分享标题 分享摘要 和分享缩略图,所以要用到微信公众号的jssdk,必然就牵扯到微信签名。 以thinkphp5为例,展示整个生成和使用的过程。 步骤: 1、获取微信access_...
  • 微信公众号申请页面获取验证码BUG

    千次阅读 2016-01-26 12:29:01
    1.注册成功后,进入微信公众号 2.选择订阅号,下面的[选择并继续],点击确认3.选择[个人]后,会让你填写个人信息4.填写完姓名和身份证号码后,填写手机号后,[获取验证码]的按钮应该由灰色转为高亮,但是却没有,...
  • 外部H5页面内实现关注公众号微信JSSDK没有相关接口开放,第三方浏览器打开微信接口微信只给部分合作平台开放了接口权限,任何第三方想调用只能是通过一些技术手段来请求接口,获取秘钥(ticket)。那么如果我们...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,630
精华内容 1,852
关键字:

微信公众号短信接口