• Java微信公众平台开发,基于springMVC技术和xstream,json等技术。
  • 微信公众平台开发教程(含java代码)》
  • java开发微信发送消息

    2020-07-06 23:31:24
    java开发微信发送消息,内含微信发送消息的请求数据模型。
  • 微信公众号二次开发平台开发教程(JAVA版)pdf文档+视频下载
  • 微信开票上传PDF

    2018-12-23 14:28:06
    微信开票上传PDF 商户或开票平台可以通过该接口上传PDFPDF上传成功后将获得发票文件的标识,后续可以通过插卡接口将PDF关联到用户的发票卡券...这是微信开发文档的说明,谁能看懂? form-data中媒体文件标识,有f...

    微信开票上传PDF

    商户或开票平台可以通过该接口上传PDF。PDF上传成功后将获得发票文件的标识,后续可以通过插卡接口将PDF关联到用户的发票卡券上,一并插入到收票用户的卡包中。

    注意:若上传成功的PDF在三天内没有被关联到发票卡券发送到用户卡包上,将会被清理。若商户或开票平台需要在三天后再关联发票卡券的话,需要重新上传。
    这是微信开发文档的说明,谁能看懂?

    form-data中媒体文件标识,有filename、filelength、content-type等信息

    上传什么PDF?什么格式?什么要求?

    琢磨了好多天,觉得应该是上传一个 数据表单格式的pdf,扫描自己公司的空白发票,根据插入卡包的字段制作成表单,保存为pdf,,POST上传,,,靠,竟然成功了!!!

    展开全文
  • 该功能我在程自己在学习时候尝试搭建的,可能会有很多问题,在这里只是做一下记录。直接上代码。如有不懂请联系楼主或者加群725395843 这里是技术讨论群。供大家讨论。   此文档做回顾。 ...做之前建议先过遍文档,...

    该功能我在程自己在学习时候尝试搭建的,可能会有很多问题,在这里只是做一下记录。直接上代码。如有不懂请联系楼主或者加群725395843   这里是技术讨论群。供大家讨论。

     

    此文档做回顾。

    先上官方文档:http://mp.weixin.qq.com/wiki/home/index.html

    做之前建议先过遍文档,文档都说的清晰明了。

    如果已经看过文档(或者已经急不可待了),那我们一起整理下JSSDK的流程步骤:

     

    绑定域名
            登陆微信公众号,根据下列路径找到添加页面:

                微信公众号 - 公众号设置 - 功能设置 - JS接口安全域名

            添加步骤:

                1.下载txt文件(MP_verify_0HU5eN6Tzfwovxxx.txt),放到项目根目录下;

                2.添加项目访问域名地址,点击保存。

     

    在需要调用JS接口的页面引入js文件(页面不支持https的换成http://):
     

                https://res.wx.qq.com/open/js/jweixin-1.0.0.js

     

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

            将要用到的接口用引号形式写进去,逗号隔开('','');

            这里添加的js接口名称要跟下面的wx.ready()里面的接口顺序对应,当时就吃了这个亏~;

             js接口名称见官方文档。

        其他参数的值往下看...

     

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

     

            里面的js接口顺序一定要按照config()接口中的参数jsApiList中的js接口顺序排列。

     

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

    前端jsp页面  

    注意:要引入相应的文件  

    <script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>

    一定要引用

    <script>
        
         $(function(){
                var url = location.href.split('#').toString();//url不能写死
                var appId = ""; //注意这里 要填写你自己得
                var secret = "";//注意这里 要填写你自己得
                var product_id=${ap.scProduct.id}
                var activity_id=${ap.activity.id}
                $.ajax({
                    type : "get",
                    url : "/Dgsc/wechatParam",
                    dataType : "json",
                    async : true,
                    data:{url:url},
                    success : function(data) {
                    wx.config({
                            debug: false,////生产环境需要关闭debug模式
                            appId: data.appid,//appId通过微信服务号后台查看
                            timestamp: data.timestamp,//生成签名的时间戳
                            nonceStr: data.nonceStr,//生成签名的随机字符串
                            signature: data.signature,//签名
                            jsApiList: [//需要调用的JS接口列表
                                'checkJsApi',//判断当前客户端版本是否支持指定JS接口
                                'onMenuShareTimeline',//分享给好友
                                'onMenuShareAppMessage'//分享到朋友圈
                            ]
                        });
                    },
                    error: function(xhr, status, error) {
                       // alert(status);
                        //alert(xhr.responseText);
                    }
                })
                wx.ready(function () {
                    wx.onMenuShareTimeline({
                       title: '',//分享的标题
                        desc: '朋友圈都被这个刷屏了,你也来晒一晒吧~', // 分享描述
                        link:'',  //注意这里最好是http访问全路径 要不容易出问题 
                        imgUrl: '', // 分享图标 http访问全路径
                        success: function () { 
                            // 用户确认分享后执行的回调函数
                            //alert("分享成功");

                        }
                        cancel: function () { 
                            // 用户取消分享后执行的回调函数
                            //alert("取消分享");
                        }  
                    });
                  //分享给朋友
                  wx.onMenuShareAppMessage({
                         title: '',
                        desc: '朋友圈都被这个刷屏了,你也来晒一晒吧~', // 分享描述
                        link:'',
                        imgUrl: '', // 分享图标 // 分享图标
                        type: '', // 分享类型,music、video或link,不填默认为link
                        dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
                        success: function () { 
                            // 用户确认分享后执行的回调函数
                        },
                        cancel: function () { 
                            // 用户取消分享后执行的回调函数
                        }
                    });
                    wx.error(function (res) {
                       // alert(res.errMsg);
                    });
                });
            });
      </script>

     后台Controller

    package cn.com.sinosoft.controller;

    import java.io.UnsupportedEncodingException;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    import java.util.Formatter;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.UUID;

    import org.apache.commons.lang3.StringUtils;
    import org.apache.log4j.Logger;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;

    import com.alibaba.fastjson.JSONObject;

    import cn.com.sinosoft.util.CommonUtil;
    import cn.com.sinosoft.util.HttpUtil;

    @Controller
    public class WxShareController {
        private Logger log = Logger.getLogger(this.getClass());
        //获取相关的参数,在application.properties文件中
        //  @Value("${wechat.appId}")
        private String appId ="";//注意 这里必须填写   在你得公众号里面找
        // @Value("${wechat.appSecret}")
        private String appSecret ="";//注意 这里必须填写  在你得公众号里面找
        // @Value("${wechat.url.accessToken}")
        private String accessTokenUrl ="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
        // @Value("${wechat.url.apiTicket}")
        private String apiTicketUrl ="https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";

        //微信参数
        private String accessToken;
        private String jsApiTicket;
        //获取参数的时刻
        private Long getTiketTime = 0L;
        private Long getTokenTime = 0L;
        //参数的有效时间,单位是秒(s)
        private Long tokenExpireTime = 0L;
        private Long ticketExpireTime = 0L;

        //获取微信参数
        @RequestMapping("/wechatParam")
        @ResponseBody
        public Map<String, String> getWechatParam(String url) throws Exception{
            //当前时间
            long now = System.currentTimeMillis();
            log.info("currentTime====>"+now+"ms");

            //判断accessToken是否已经存在或者token是否过期
            /*if(StringUtils.isBlank(accessToken)||(now - getTokenTime > tokenExpireTime*1000)){
                JSONObject tokenInfo = getAccessToken();
                log.info("————————————————————————————————+"+tokenInfo);
                if(tokenInfo != null){
                    log.info("tokenInfo====>"+tokenInfo.toJSONString());
                    accessToken = tokenInfo.getString("access_token");
                    tokenExpireTime = tokenInfo.getLongValue("expires_in");
                    //获取token的时间
                    getTokenTime = System.currentTimeMillis();
                    log.info("accessToken====>"+accessToken);
                    log.info("tokenExpireTime====>"+tokenExpireTime+"s");
                    log.info("getTokenTime====>"+getTokenTime+"ms");
                }else{
                    log.info("====>tokenInfo is null~");
                    log.info("====>failure of getting tokenInfo,please do some check~");
                }

            }*/

            //判断jsApiTicket是否已经存在或者是否过期
            if(StringUtils.isBlank(jsApiTicket)||(now - getTiketTime > ticketExpireTime*1000)){
                JSONObject ticketInfo = getJsApiTicket();
                if(ticketInfo!=null){
                    log.info("ticketInfo====>"+ticketInfo.toJSONString());
                    jsApiTicket = ticketInfo.getString("ticket");
                    ticketExpireTime = ticketInfo.getLongValue("expires_in");
                    getTiketTime = System.currentTimeMillis();
                    log.info("jsApiTicket====>"+jsApiTicket);
                    log.info("ticketExpireTime====>"+ticketExpireTime+"s");
                    log.info("getTiketTime====>"+getTiketTime+"ms");
                }else{
                    log.info("====>ticketInfo is null~");
                    log.info("====>failure of getting tokenInfo,please do some check~");
                }
            }

            //生成微信权限验证的参数
            Map<String, String> wechatParam= makeWXTicket(jsApiTicket,url);
            return wechatParam;
        }

        //获取accessToken
        /*private JSONObject getAccessToken(){
            //String accessTokenUrl = https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
            String requestUrl = accessTokenUrl.replace("APPID",appId).replace("APPSECRET",appSecret);
            log.info("getAccessToken.requestUrl====>"+requestUrl);
            JSONObject result = HttpUtil.doGet(requestUrl);
            return result ;
        }*/

        //获取ticket
        private JSONObject getJsApiTicket() throws Exception{
            //String apiTicketUrl = https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
            accessToken = CommonUtil.getAccessToken();
            String requestUrl = apiTicketUrl.replace("ACCESS_TOKEN", accessToken);
            log.info("getJsApiTicket.requestUrl====>"+requestUrl);
            JSONObject result = HttpUtil.doGet(requestUrl);
            log.info("————————————————————"+result);
            return result;
        }

        //生成微信权限验证的参数
        public Map<String, String> makeWXTicket(String jsApiTicket, String url) {
            Map<String, String> ret = new HashMap<String, String>();
            String nonceStr = createNonceStr();
            String timestamp = createTimestamp();
            String string1;
            String signature = "";

            //注意这里参数名必须全部小写,且必须有序
            string1 = "jsapi_ticket=" + jsApiTicket +
                    "&noncestr=" + nonceStr +
                    "&timestamp=" + timestamp +
                    "&url=" + url;
            log.info("String1=====>"+string1);
            try
            {
                MessageDigest crypt = MessageDigest.getInstance("SHA-1");
                crypt.reset();
                crypt.update(string1.getBytes("UTF-8"));
                signature = byteToHex(crypt.digest());
                log.info("signature=====>"+signature);
            }
            catch (NoSuchAlgorithmException e)
            {
                log.error("WeChatController.makeWXTicket=====Start");
                log.error(e.getMessage(),e);
                log.error("WeChatController.makeWXTicket=====End");
            }
            catch (UnsupportedEncodingException e)
            {
                log.error("WeChatController.makeWXTicket=====Start");
                log.error(e.getMessage(),e);
                log.error("WeChatController.makeWXTicket=====End");
            }

            ret.put("url", url);
            ret.put("jsapi_ticket", jsApiTicket);
            ret.put("nonceStr", nonceStr);
            ret.put("timestamp", timestamp);
            ret.put("signature", signature);
            ret.put("appid", appId);

            return ret;
        }
        //字节数组转换为十六进制字符串
        private static String byteToHex(final byte[] hash) {
            Formatter formatter = new Formatter();
            for (byte b : hash)
            {
                formatter.format("%02x", b);
            }
            String result = formatter.toString();
            formatter.close();
            return result;
        }
        //生成随机字符串
        private static String createNonceStr() {
            return UUID.randomUUID().toString();
        }
        //生成时间戳
        private static String createTimestamp() {
            return Long.toString(System.currentTimeMillis() / 1000);
        }
    }

     Util  之拿需要得就可以了

     

    package cn.com.sinosoft.util;

    import java.io.BufferedReader;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.OutputStreamWriter;
    import java.net.HttpURLConnection;
    import java.net.MalformedURLException;
    import java.net.URL;
    import java.net.URLConnection;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.TreeMap;
    import java.util.regex.*;

    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import redis.clients.jedis.Jedis;

    import org.apache.http.HttpResponse;
    import org.apache.http.HttpStatus;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.entity.StringEntity;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.message.BasicHeader;
    import org.apache.http.protocol.HTTP;
    import org.apache.log4j.Logger;
    import org.junit.Test;

    import com.alibaba.fastjson.JSONObject;

    /**
     * request信息
     * @author 
     *
     */
    public class CommonUtil {
        private static Logger logger = Logger.getLogger(CommonUtil.class);
        private static String appId = "";
        private static String secret = "";
        /*private static String appId = "";
        private static String secret = "";*/
        public static JSONObject getUrlInfo(String requestURL,String method,String json) throws Exception {
            URL get_url = new URL(requestURL);
            // 将url 以 open方法返回的urlConnection 连接强转为HttpURLConnection连接
            // (标识一个url所引用的远程对象连接)
            // 此时cnnection只是为一个连接对象,待连接中
            HttpURLConnection httpURLConnection = (HttpURLConnection) get_url
                    .openConnection();
            // 设置请求方式为post
            httpURLConnection.setRequestMethod(method);
            // 设置连接输出流为true,默认false (post 请求是以流的方式隐式的传递参数)
            httpURLConnection.setDoOutput(true);
            // 设置连接输入流为true
            httpURLConnection.setDoInput(true);
            // post请求缓存设为false
            httpURLConnection.setUseCaches(false);
            // 设置请求头里面的各个属性 (以下为设置内容的类型,设置为经过urlEncoded编码过的from参数)
            // application/x-javascript text/xml->xml数据
            // application/x-javascript->json对象
            // application/x-www-form-urlencoded->表单数据
            // ;charset=utf-8 必须要,不然妙兜那边会出现乱码
            httpURLConnection.setRequestProperty("Content-type",
                    "application/json;charset=utf-8");
            // 建立连接 (请求未开始,直到connection.getInputStream()方法调用时才发起,以上各个参数设置需在此方法之前进行)
            httpURLConnection.connect();

            // 创建输入输出流,用于往连接里面输出携带的参数,(输出内容为?后面的内容)
            OutputStreamWriter out = new OutputStreamWriter(httpURLConnection.getOutputStream(), "UTF-8"); 
            if(method.equals("POST")){
                out.append(json);
            }
            out.flush();  
            out.close();

            // 连接发起请求,处理服务器响应 (从连接获取到输入流并包装为bufferedReader)
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    httpURLConnection.getInputStream(), "UTF-8"));
            // 读取数据操作
            String str = null;  
            StringBuffer buffer = new StringBuffer();  
            while((str = reader.readLine())!= null){  
                buffer.append(str);  
            }        
            //转换成json
            JSONObject jsonObj = JSONObject.parseObject(buffer.toString());
            reader.close();
            return jsonObj;

        }
        
        
        public static String getAccessToken() throws Exception{
            Jedis jedis = new Jedis("localhost");
            String access_token = null;
            Boolean conn_flag = true;
            try{
                logger.info("jedis "+jedis.ping());
                access_token = jedis.get("access_token_dg");
                if (access_token !=null && access_token.length() > 0 ){
                    return access_token;
                }
            }catch(Exception e){
                logger.info("redis连接失败");
                conn_flag = false;
            }
            String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+ appId + "&secret=" + secret;
            JSONObject access_token_json = getUrlInfo(url,"GET",null);
            access_token = access_token_json.getString("access_token");
            if (conn_flag == true){
                jedis.set("access_token_dg", access_token);
                jedis.expire("access_token_dg", 7000);
            }
            return access_token;
        }
        
        
        
        
        public static String getFreight() throws Exception{
            Jedis jedis = new Jedis("localhost");
            String freight = null;
            try{
                logger.info("jedis "+jedis.ping());
                freight = jedis.get("freight");
                if (freight !=null && freight.length() > 0 ){
                    return freight;
                }
            }catch(Exception e){
                logger.info("redis连接失败");
            }
            return null;
        }
        
        
        
        
        public static String getOpenId(String code) throws Exception{
            logger.debug("code "+code);
            String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="+ appId +"&secret="+ secret +"&code="+ code +"&grant_type=authorization_code";
            JSONObject openid_json = getUrlInfo(url,"GET",null);
            return openid_json.getString("openid");
        }
        
        public static JSONObject getUserInfo(String code) throws Exception{
            String access_token = getAccessToken();
            logger.debug("access_token "+access_token);
            String openid = getOpenId(code);
            logger.debug("openid "+openid);
            String url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token="+access_token+"&openid="+openid+"&lang=zh_CN";
            return getUrlInfo(url,"GET",null);
        }
        
        public static JSONObject getUserInfoByOpenid(String openid) throws Exception{
            String access_token = getAccessToken();
            logger.debug("access_token "+access_token);
            String url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token="+access_token+"&openid="+openid+"&lang=zh_CN";
            return getUrlInfo(url,"GET",null);
        }
        
        public static JSONObject createQRcode(String args,String qrtype) throws Exception{
            String access_token = getAccessToken();
            String url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token="+access_token;
            String jsonStr = null;
            TreeMap<String,String> tm = new TreeMap<String,String>();
            Map<String,Object> m = new HashMap<String, Object>();
            if (qrtype.equals("limit")){
                logger.debug("-----"+args);
                jsonStr = "{\"action_name\": \"QR_LIMIT_STR_SCENE\", \"action_info\":{\"scene\": {\"scene_str\":\""+ args + "\"}}}";
                //JSONObject jsonObject = getUrlInfo(url,"POST",jsonStr);  
                logger.debug("jsonStr "+jsonStr);
            }else{
            }
            
            return getUrlInfo(url,"POST",jsonStr);        
            
        }
        
        /*public static JSONObject createQRcode(int args,String qrtype) throws Exception{
            String access_token = getAccessToken();
            String url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token="+access_token;
            String jsonStr = null;
            TreeMap<String,String> tm = new TreeMap<String,String>();
            Map<String,Object> m = new HashMap<String, Object>();
            if (qrtype.equals("limit")){
                logger.debug("-----"+args);
                jsonStr = "{\"action_name\": \"QR_LIMIT_SCENE\", \"action_info\":{\"scene\": {\"scene_id\": "+args+"}}}";
                logger.debug("jsonStr "+jsonStr);
            }else{
                jsonStr = "{\"expire_seconds\": 2592000,\"action_name\": \"QR_SCENE\", \"action_info\": {\"scene\": {\"scene_id\": "+args+"}}}";
            }
            
            return getUrlInfo(url,"POST",jsonStr);        
            
        }*/
        
        public static Boolean downloadFile(String urlString, String filePath){
            // 构造URL
            URL url;
             try {
                 url = new URL(urlString);
                  // 打开连接
                 URLConnection con;
                 try {
                      con = url.openConnection();
                      // 输入流
                     InputStream is = con.getInputStream();
                     // 1K的数据缓冲
                     byte[] bs = new byte[1024];
                     // 读取到的数据长度
                     int len;
                     // 输出的文件流
                     OutputStream os = new FileOutputStream(filePath);
                     // 开始读取
                     while ((len = is.read(bs)) != -1) {
                      os.write(bs, 0, len);
                     }
                     // 完毕,关闭所有链接
                     os.close();
                     is.close();
                     return true;
                 } catch (IOException e) {
                      // TODO Auto-generated catch block
                      e.printStackTrace();
                      return false;
                 }
                
             } catch (MalformedURLException e) {
                 // TODO Auto-generated catch block
                 e.printStackTrace();
                 return false;
             }
          
        }  
        
        @Test
        public void shsh(){
            System.out.println("df "+CommonUtil.class);
            logger.info("sle");
        }
        
        @Test
        public static Boolean checkNum(String args){
            String pattern = "\\d+";
            boolean isMatch = Pattern.matches(pattern, args);
            if(isMatch == true){
                System.out.println("true");
            }else{
                System.out.println("false");
            }
            return isMatch;
        } 

        public static String PostSendMsg(JSONObject json, String url) {
            HttpPost post = new HttpPost(url);
            post.setHeader("Content-Type", "application/json");
            post.addHeader("Authorization", "Basic YWRtaW46");
            String result = "";
            try {
                StringEntity s = new StringEntity(json.toString(), "utf-8");
                s.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
                post.setEntity(s);
                // 发送请求
                HttpResponse httpResponse = HttpClients.createDefault().execute(post);
                // 获取响应输入流
                InputStream inStream = httpResponse.getEntity().getContent();
                BufferedReader reader = new BufferedReader(new InputStreamReader(inStream, "utf-8"));
                StringBuilder strber = new StringBuilder();
                String line = null;
                while ((line = reader.readLine()) != null)
                    strber.append(line + "\n");
                inStream.close();

                result = strber.toString();
                System.out.println(result);

                if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                    System.out.println("请求服务器成功,做相应处理");
                } else {
                    System.out.println("请求服务端失败");
                }
            } catch (Exception e) {
                System.out.println("请求异常");
                throw new RuntimeException(e);
            }
            return result;
        }
        
        public static void returnMsg(HttpServletResponse response,String message) throws IOException{
            response.setContentType("text/html;charset=UTF-8");
            response.getWriter().print(message);
        }
    }
     

     httpUtil

    package cn.com.sinosoft.util;

    import java.io.IOException;

    import org.apache.http.HttpEntity;
    import org.apache.http.client.methods.CloseableHttpResponse;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.util.EntityUtils;
    import org.apache.log4j.Logger;

    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.JSONObject;

    public class HttpUtil {
        
            //get请求
            public static JSONObject doGet(String requestUrl) {
                CloseableHttpClient httpClient = HttpClients.createDefault();
                CloseableHttpResponse response = null;
                String responseContent  = null;
                com.alibaba.fastjson.JSONObject result = null;
                try {
                    //创建Get请求,
                    HttpGet httpGet = new HttpGet(requestUrl);
                    //执行Get请求,
                    response = httpClient.execute(httpGet);
                    //得到响应体
                    HttpEntity entity = response.getEntity();
                    //获取响应内容
                    responseContent  = EntityUtils.toString(entity,"UTF-8");
                    //转换为map
                    result = JSON.parseObject(responseContent);
                } catch (IOException e) {
                    
                }
                return result;
            }
        
    }
     

     

    展开全文
  • 本文介绍的是基于Java语言开发微信现金红包的例子。由于个人表达能力和编程能力有限,请多多包涵。本文仅介绍拥有微信支付权限的微信公众号开发。 本文分为以下两部分: 1.开发现金红包SDK 2.构造现金红包并发送 ...

       目录(?)

    1. 功能介绍
    2. 微信红包发送规则
    3. 商户侧调用红包接口流程
    4. 用户交互流程
    5. 接口详细说明
    6. 一开发现金红包SDK
    7. 二构造现金红包并发送

    本文介绍的是基于Java语言开发微信现金红包的例子。由于个人表达能力和编程能力有限,请多多包涵。本文仅介绍拥有微信支付权限的微信公众号开发。

    本文分为以下两部分:

    1.开发现金红包SDK

    2.构造现金红包并发送

    首先看一下现金红包接口文档:http://pay.weixin.qq.com/wiki/doc/api/cash_coupon.php?chapter=13_1

    首页

    现金红包

    功能介绍

    春节期间,微信红包以其独特的魅力,优秀的用户体验和安全的支付环境,一经推出即受到了广大用户的热烈欢迎,现微信支付现金红包向微信支付商户开发,具体能力如下: 

    1、商户调用接口时,通过指定发送对象以及发送金额的方式发放红包,这样的方式,允许商户灵活的应用于各种各样丰富的活动场景

    2、领取到红包后,用户的资金直接进入微信零钱,避免繁复的领奖流程,带给用户微信支付原生的流畅体验

     

    微信红包发送规则

    1. 发送频率规则

     

     ◆ 每分钟发送红包数量不得超过1800个;

     ◆ 北京时间0:00-8:00不触发红包赠送;(如果以上规则不满足您的需求,请发邮件至wxhongbao@tencent.com获取升级指引)

    2. 红包规则

     ◆ 单个红包金额介于[1.00元,200.00元]之间;

     ◆ 同一个红包只能发送给一个用户;(如果以上规则不满足您的需求,请发邮件至wxhongbao@tencent.com获取升级指引)

    商户侧调用红包接口流程

    1. 登录微信支付商户平台下载证书以及充值

     

    在调用接口前,请商户使用微信支付商户号登录微信支付商户平台完成下述工作:

    备注:

    微信支付商户平台地址为pay.weixin.qq.com。微信支付商户号会在商户申请微信支付成功后,通过开户邮件发送给您。请不要使用微信公众平台账号或者appid登录。如果您登录时遇到问题,请联系微信支付小助手weixinpay@tencent.com

     ◆ 下载证书

    商户调用微信红包接口时,服务器会进行证书验证,请在商户平台下载证书

     ◆ 充值

     发放现金红包将扣除商户的可用余额,请注意,可用余额并不是微信支付交易额,需要预先充值,确保可用余额充足。查看可用余额、充值、提现请登录微信支付商户平台,进入“资金管理”菜单,进行操作

    2. 微信红包接口调用流程

     ◆ 后台API调用:待进入联调过程时与开发进行详细沟通;

     ◆ 告知服务器:告知服务器接收微信红包的用户openID,告知服务器该用户获得的金额;

     ◆ 从商务号扣款:服务器获取信息后从对应的商务号扣取对应的金额;

     ◆ 调用失败:因不符合发送规则,商务号余额不足等原因造成调用失败,反馈至调用方;

     ◆ 发送成功:以微信红包公众账号发送对应红包至对应用户;

     

     

     

    用户交互流程

     

    调用现金红包接口,发放成功后,用户领取红包流程如下:

    步骤(一):收到领取红包消息,根据用户微信版本不同,分为:

    • 微信版本在6.1及以上的用户收到企业自身微信号(调用接口时传入appid对应的商户号)下发领取消息;如果用户未关注微信号,那么会收到由“服务通知”下发的消息

      

     

    • 微信版本在6.1以下的用户仍按原流程收取消息:由微信红包公众号下发领取消息

     

     

    步骤(二):点击领取消息,拆红包

     

     <img src="http://pay.weixin.qq.com/wiki/doc/api/img/chapter13_5.png" "width="261" height="464" style="border: 0px none; vertical-align: top;">

    1. 接口列表

    业务

    接口

    简介

    现金红包

    发放红包

    用于企业向微信用户个人发现金红包

    目前支持向指定微信用户的openid发放指定金额红包。(获取openid参见微信公众平台开发者文档:  网页授权获取用户基本信息

     

     

     

    接口详细说明

    1.红包发放说明

     

    用于企业向微信用户个人发现金红包

    目前支持向指定微信用户的openid发放指定金额红包。(获取openid参见微信公众平台开发者文档: 网页授权获取用户基本信息

    接口参数与用户领用实际效果对应关系如下:

    如需操作请登录https://pay.weixin.qq.com/

     

    2.接口调用请求说明

    请求Url

    https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack

    是否需要证书

    是(证书及使用说明详见商户证书

    请求方式

    POST

    3.请求参数

    字段名

    字段

    必填

    示例值

    类型

    说明

    随机字符串

    nonce_str

    5K8264ILTKCH16CQ2502SI8ZNMTM67VS

    String(32)

    随机字符串,不长于32位

    签名

    sign

    C380BEC2BFD727A4B6845133519F3AD6

    String(32)

    详见签名生成算法

    商户订单号

    mch_billno

    10000098201411111234567890

    String(28)

    商户订单号(每个订单号必须唯一)

    组成: mch_id+yyyymmdd+10位一天内不能重复的数字。

    接口根据商户订单号支持重入, 如出现超时可再调用。

    商户号

    mch_id

    10000098

    String(32)

    微信支付分配的商户号

    子商户号

    sub_mch_id

    10000090

    String(32)

    微信支付分配的子商户号,受理模式下必填

    公众账号appid

    wxappid

    wx8888888888888888

    String(32)

    商户appid

    提供方名称

    nick_name

    天虹百货

    String(32)

    提供方名称

    商户名称

    send_name

    天虹百货

    String(32)

    红包发送者名称

    用户openid

    re_openid

    oxTWIuGaIt6gTKsQRLau2M0yL16E

    String(32)

    接受收红包的用户

    用户在wxappid下的openid

    付款金额

    total_amount

    1000

    int

    付款金额,单位分

    最小红包金额

    min_value

    1000

    int

    最小红包金额,单位分

    最大红包金额

    max_value

    1000

    int

    最大红包金额,单位分

    ( 最小金额等于最大金额: min_value=max_value =total_amount)

    红包发放总人数

    total_num

    1

    int

    红包发放总人数

    total_num=1

    红包祝福语

    wishing

    感谢您参加猜灯谜活动,祝您元宵节快乐!

    String(128)

    红包祝福语

    Ip地址

    client_ip

    192.168.0.1

    String(15)

    调用接口的机器Ip地址

    活动名称

    act_name

    猜灯谜抢红包活动

    String(32)

    活动名称

    备注

    remark

    猜越多得越多,快来抢!

    String(256)

    备注信息

    商户logo的url

    logo_imgurl

    https://wx.gtimg.com/mch/img/ico-logo.png

    String(128)

    商户logo的url

    分享文案

    share_content

    快来参加猜灯谜活动

    String(256)

    分享文案

    分享链接

    share_url

    http://www.qq.com

    String(128)

    分享链接

    分享的图片

    share_imgurl

    https://wx.gtimg.com/mch/img/ico-logo.png

    String(128)

    分享的图片url

    数据示例:

    <xml>

                <sign></sign>

                <mch_billno></mch_billno>

                <mch_id></mch_id>

                <wxappid></wxappid>

                <nick_name></nick_name>

                <send_name></send_name>

                <re_openid></re_openid>

                <total_amount></total_amount>

                <min_value></min_value>

                <max_value></max_value>

                <total_num></total_num>

                <wishing></wishing>

                <client_ip></client_ip>

                <act_name></act_name>

                <act_id></act_id>

                <remark></remark>

                <logo_imgurl></logo_imgurl>

                <share_content></share_content>

                <share_url></share_url>

                <share_imgurl></share_imgurl>

                <nonce_str></nonce_str>

            </xml>

    4.返回参数

    字段名

    变量名

    必填

    示例值

    类型

    说明

    返回状态码

    return_code

    SUCCESS

    String(16)

    SUCCESS/FAIL

    此字段是通信标识,非交易标识,交易是否成功需要查看result_code来判断

    返回信息

    return_msg

    签名失败

     

    String(128)

    返回信息,如非空,为错误原因

    签名失败

    参数格式校验错误

    以下字段在return_code为SUCCESS的时候有返回

    签名

    sign

    C380BEC2BFD727A4B6845133519F3AD6

    String(32)

    生成签名方式详见签名生成算法

    业务结果

    result_code

    SUCCESS

    String(16)

    SUCCESS/FAIL

    错误代码

    err_code

    SYSTEMERROR

    String(32)

    错误码信息

    错误代码描述

    err_code_des

    系统错误

    String(128)

    结果信息描述

    以下字段在return_code 和result_code都为SUCCESS的时候有返回

    商户订单号

    mch_billno

    10000098201411111234567890

    String(28)

    商户订单号(每个订单号必须唯一)

    组成: mch_id+yyyymmdd+10位一天内不能重复的数字

    商户号

    mch_id

    10000098

    String(32)

    微信支付分配的商户号

    公众账号appid

    wxappid

    wx8888888888888888

    String(32)

    商户appid

    用户openid

    re_openid

    oxTWIuGaIt6gTKsQRLau2M0yL16E

    String(32)

    接受收红包的用户

    用户在wxappid下的openid

    付款金额

    total_amount

    1000

    int

    付款金额,单位分

    发放成功时间

     

     

     

     

     

    微信单号

     

     

     

     

     

    成功示例:

    <xml>

    <return_code><![CDATA[SUCCESS]]></return_code>

    <return_msg><![CDATA[发放成功.]]></return_msg>

    <result_code><![CDATA[SUCCESS]]></result_code>

    <err_code><![CDATA[0]]></err_code>

    <err_code_des><![CDATA[发放成功.]]></err_code_des>

    <mch_billno><![CDATA[0010010404201411170000046545]]></mch_billno>

    <mch_id>10010404</mch_id>

    <wxappid><![CDATA[wx6fa7e3bab7e15415]]></wxappid>

    <re_openid><![CDATA[onqOjjmM1tad-3ROpncN-yUfa6uI]]></re_openid>

    <total_amount>1</total_amount>

    </xml>

    失败示例:

    <xml>

                     <return_code><![CDATA[FAIL]]></return_code>

    <return_msg><![CDATA[系统繁忙,请稍后再试.]]></return_msg>

    <result_code><![CDATA[FAIL]]></result_code>

    <err_code><![CDATA[268458547]]></err_code>

    <err_code_des><![CDATA[系统繁忙,请稍后再试.]]></err_code_des>

    <mch_billno><![CDATA[0010010404201411170000046542]]></mch_billno>

    <mch_id>10010404</mch_id>

    <wxappid><![CDATA[wx6fa7e3bab7e15415]]></wxappid>

    <re_openid><![CDATA[onqOjjmM1tad-3ROpncN-yUfa6uI]]></re_openid>

    <total_amount>1</total_amount>

    </xml>

     

     

    5.错误码

    错误代码

    描述

    解决方案

    NOAUTH

    无权限

    请联系微信支付开通api权限

    PARAM_ERROR

    参数错误

    请查看err_code_des,修改设置错误的参数

    OPENID_ERROR

    Openid错误

    根据用户在商家公众账号上的openid,获取用户在红包公众账号上的openid 错误。请核对商户自身公众号appid和用户在此公众号下的openid。

    NOTENOUGH

    余额不足

    商户账号余额不足,请登录微信支付商户平台充值

    SYSTEMERROR

    系统繁忙,请再试。

    可用同一商户单号再次调用,只会发放一个红包。

    TIME _LIMITED

    企业红包的发送时间受限

    请北京时间0:00-8:00时间之外触发红包赠送

    SECOND_OVER_LIMITED

    企业红包的按分钟发放受限

    每分钟发送红包数量不得超过1800个;(可联系微信支付wxhongbao@tencent.com调高额度)

    MONEY_LIMIT

    红包金额发放限制

    每个红包金额必须大于1元,小于200元(可联系微信支付wxhongbao@tencent.com调高额度至4999元)

     

    现金红包API文档:https://pay.weixin.qq.com/helper/cashredopenapi_V2.pdf这个里面是非常详细的,一定要仔细看哦。

     

    一、开发现金红包SDK

    1.创建一个红包,本文介绍的是创建一个固定金额的红包。

    2.接口调用说明

    请求Url

    https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack

    是否需要证书

    是(证书及使用说明详见商户证书

    请求方式

    POST

    证书是必须的,上面的现金红包接口文档里面有介绍。

    点击这个链接:http://pay.weixin.qq.com/wiki/doc/api/cash_coupon.php?chapter=13_3

    这一节有介绍的。

    3.请求参数。注意看下,有的参数是必填的。

    二、构造现金红包并发送

    构造现金红包实体类

    public class SendRedPackPo {
    private String nonce_str;
    private String sign;
    private String mch_billno;
    private String mch_id;
    private String sub_mch_id;
    private String wxappid;
    private String nick_name;
    private String send_name;
    private String re_openid;
    private String total_amount;
    private String min_value;
    private String max_value;
    private String total_num;
    private String wishing;
    private String client_ip;
    private String act_name;
    private String remark;
    private String logo_imgurl;
    private String share_content;
    private String share_url;
    private String share_imgurl;

    public String getNonce_str() {
    return nonce_str;
    }
    public void setNonce_str(String nonceStr) {
    nonce_str = nonceStr;
    }
    public String getSign() {
    return sign;
    }
    public void setSign(String sign) {
    this.sign = sign;
    }
    public String getMch_billno() {
    return mch_billno;
    }
    public void setMch_billno(String mchBillno) {
    mch_billno = mchBillno;
    }
    public String getMch_id() {
    return mch_id;
    }
    public void setMch_id(String mchId) {
    mch_id = mchId;
    }
    public String getSub_mch_id() {
    return sub_mch_id;
    }
    public void setSub_mch_id(String subMchId) {
    sub_mch_id = subMchId;
    }
    public String getWxappid() {
    return wxappid;
    }
    public void setWxappid(String wxappid) {
    this.wxappid = wxappid;
    }
    public String getNick_name() {
    return nick_name;
    }
    public void setNick_name(String nickName) {
    nick_name = nickName;
    }
    public String getSend_name() {
    return send_name;
    }
    public void setSend_name(String sendName) {
    send_name = sendName;
    }
    public String getRe_openid() {
    return re_openid;
    }
    public void setRe_openid(String reOpenid) {
    re_openid = reOpenid;
    }
    public String getTotal_amount() {
    return total_amount;
    }
    public void setTotal_amount(String totalAmount) {
    total_amount = totalAmount;
    }
    public String getMin_value() {
    return min_value;
    }
    public void setMin_value(String minValue) {
    min_value = minValue;
    }
    public String getMax_value() {
    return max_value;
    }
    public void setMax_value(String maxValue) {
    max_value = maxValue;
    }
    public String getTotal_num() {
    return total_num;
    }
    public void setTotal_num(String totalNum) {
    total_num = totalNum;
    }
    public String getWishing() {
    return wishing;
    }
    public void setWishing(String wishing) {
    this.wishing = wishing;
    }
    public String getClient_ip() {
    return client_ip;
    }
    public void setClient_ip(String clientIp) {
    client_ip = clientIp;
    }
    public String getAct_name() {
    return act_name;
    }
    public void setAct_name(String actName) {
    act_name = actName;
    }
    public String getRemark() {
    return remark;
    }
    public void setRemark(String remark) {
    this.remark = remark;
    }
    public String getLogo_imgurl() {
    return logo_imgurl;
    }
    public void setLogo_imgurl(String logoImgurl) {
    logo_imgurl = logoImgurl;
    }
    public String getShare_content() {
    return share_content;
    }
    public void setShare_content(String shareContent) {
    share_content = shareContent;
    }
    public String getShare_url() {
    return share_url;
    }
    public void setShare_url(String shareUrl) {
    share_url = shareUrl;
    }
    public String getShare_imgurl() {
    return share_imgurl;
    }
    public void setShare_imgurl(String shareImgurl) {
    share_imgurl = shareImgurl;
    }

    }

     

    /**
     * 生成32位字符串
     * */
    public class UUIDHexGenerator {


    private String sep = "";


    private static final int IP;


    private static short counter = (short) 0;


    private static final int JVM = (int) (System.currentTimeMillis() >>> 8);


    private static UUIDHexGenerator uuidgen = new UUIDHexGenerator();


    static {
    int ipadd;
    try {
    ipadd = toInt(InetAddress.getLocalHost().getAddress());
    } catch (Exception e) {
    ipadd = 0;
    }
    IP = ipadd;
    }


    public static UUIDHexGenerator getInstance() {
    return uuidgen;
    }


    public static int toInt(byte[] bytes) {
    int result = 0;
    for (int i = 0; i < 4; i++) {
    result = (result << 8) - Byte.MIN_VALUE + (int) bytes[i];
    }
    return result;
    }


    protected String format(int intval) {
    String formatted = Integer.toHexString(intval);
    StringBuffer buf = new StringBuffer("00000000");
    buf.replace(8 - formatted.length(), 8, formatted);
    return buf.toString();
    }


    protected String format(short shortval) {
    String formatted = Integer.toHexString(shortval);
    StringBuffer buf = new StringBuffer("0000");
    buf.replace(4 - formatted.length(), 4, formatted);
    return buf.toString();
    }


    protected int getJVM() {
    return JVM;
    }


    protected synchronized short getCount() {
    if (counter < 0) {
    counter = 0;
    }
    return counter++;
    }


    protected int getIP() {
    return IP;
    }


    protected short getHiTime() {
    return (short) (System.currentTimeMillis() >>> 32);
    }


    protected int getLoTime() {
    return (int) System.currentTimeMillis();
    }


    public String generate() {
    return new StringBuffer(36)
    .append(format(getIP()))
    .append(sep)
    .append(format(getJVM()))
    .append(sep)
    .append(format(getHiTime()))
    .append(sep)
    .append(format(getLoTime()))
    .append(sep)
    .append(format(getCount()))
    .toString();
    }


    /**
    * @param args
    */
    public static void main(String[] args) {
    String id;
    UUIDHexGenerator uuid = UUIDHexGenerator.getInstance();
     
    for(int i = 0;i<100;i++)
    {
    id = uuid.generate();
     
    }

    }
    }

     

     

    /** 
    * 功能:MD5签名处理核心文件,不需要修改
    * 说明:
    * 以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
    * */
    public class MD5 {

        /**
         * 签名字符串
         * @param text 需要签名的字符串
         * @param key 密钥
         * @param input_charset 编码格式
         * @return 签名结果
         */
        public static String sign(String text, String key, String input_charset) {
        text = text + key;
            return DigestUtils.md5Hex(getContentBytes(text, input_charset));
        }
        
        /**
         * 签名字符串
         * @param text 需要签名的字符串
         * @param sign 签名结果
         * @param key 密钥
         * @param input_charset 编码格式
         * @return 签名结果
         */
        public static boolean verify(String text, String sign, String key, String input_charset) {
        text = text + key;
        String mysign = DigestUtils.md5Hex(getContentBytes(text, input_charset));
        if(mysign.equals(sign)) {
        return true;
        }
        else {
        return false;
        }
        }


        /**
         * @param content
         * @param charset
         * @return
         * @throws SignatureException
         * @throws UnsupportedEncodingException 
         */
        private static byte[] getContentBytes(String content, String charset) {
            if (charset == null || "".equals(charset)) {
                return content.getBytes();
            }
            try {
                return content.getBytes(charset);
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);
            }
        }


    }

         

          /**
    * 生成6位或10位随机数
    * param codeLength(多少位)
    * @return
    */

    private String createCode(int codeLength) {
    String code="";
    for(int i=0; i<codeLength; i++) {
    code += (int)(Math.random() * 9);
    }
    return code;
    }
    private static boolean isValidChar(char ch) {  
            if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z')|| (ch >= 'a' && ch <= 'z'))  
                return true;  
            if ((ch >= 0x4e00 && ch <= 0x7fff) || (ch >= 0x8000 && ch <= 0x952f))  
                return true;// 简体中文汉字编码  
            return false;  
        }

     

     

    /** 
         * 除去数组中的空值和签名参数
         * @param sArray 签名参数组
         * @return 去掉空值与签名参数后的新签名参数组
         */
        public static Map<String, String> paraFilter(Map<String, String> sArray) {


            Map<String, String> result = new HashMap<String, String>();


            if (sArray == null || sArray.size() <= 0) {
                return result;
            }


            for (String key : sArray.keySet()) {
                String value = sArray.get(key);
                if (value == null || value.equals("") || key.equalsIgnoreCase("sign")
                    || key.equalsIgnoreCase("sign_type")) {
                    continue;
                }
                result.put(key, value);
            }


            return result;
        }


        /** 
         * 把数组所有元素排序,并按照“参数=参数值”的模式用“&”字符拼接成字符串
         * @param params 需要排序并参与字符拼接的参数组
         * @return 拼接后字符串
         */
        public static String createLinkString(Map<String, String> params) {


            List<String> keys = new ArrayList<String>(params.keySet());
            Collections.sort(keys);


            String prestr = "";


            for (int i = 0; i < keys.size(); i++) {
                String key = keys.get(i);
                String value = params.get(key);


                if (i == keys.size() - 1) {//拼接时,不包括最后一个&字符
                    prestr = prestr + key + "=" + value;
                } else {
                    prestr = prestr + key + "=" + value + "&";
                }
            }


            return prestr;
        }

     

    /**
    * 发送现金红包
    * @throws KeyStoreException 
    * @throws IOException 
    * @throws CertificateException 
    * @throws NoSuchAlgorithmException 
    * @throws UnrecoverableKeyException 
    * @throws KeyManagementException 
    * @throws DocumentException 
    */
    public void sendRedPack() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, KeyManagementException, UnrecoverableKeyException, DocumentException {
    // 获取uuid作为随机字符串
    String nonceStr = uuidGenerator.generate();
    String today = new SimpleDateFormat("yyyyMMdd").format(new Date());
    String code = createCode(10);
    String mch_id = "10000100";//商户号
    String appid = "wxd930ea5d5a258f4f";
    String opendid = "xxxxxxxxxxxxxxxxx"; //发送给指定微信用户的openid
    SendRedPackPo sendRedPackPo = new SendRedPackPo();
    String totalAmount = "1";

    sendRedPackPo.setNonce_str(nonceStr);
    sendRedPackPo.setMch_billno(mch_id + today + code);
    sendRedPackPo.setMch_id(mch_id);
    sendRedPackPo.setWxappid(appid);
    sendRedPackPo.setNick_name("xxx");
    sendRedPackPo.setSend_name("xxx");
    sendRedPackPo.setRe_openid(opendid);
    sendRedPackPo.setTotal_amount(totalAmount);
    sendRedPackPo.setMin_value(totalAmount);
    sendRedPackPo.setMax_value(totalAmount);
    sendRedPackPo.setTotal_num("1");
    sendRedPackPo.setWishing("祝您新年快乐!");
    sendRedPackPo.setClient_ip("192.168.1.1"); //IP
    sendRedPackPo.setAct_name("小游戏");
    sendRedPackPo.setRemark("快来抢红包!");


    //把请求参数打包成数组
    Map<String, String> sParaTemp = new HashMap<String, String>();
    sParaTemp.put("nonce_str", sendRedPackPo.getNonce_str());
            sParaTemp.put("mch_billno", sendRedPackPo.getMch_billno());
            sParaTemp.put("mch_id", sendRedPackPo.getMch_id());
    sParaTemp.put("wxappid", sendRedPackPo.getWxappid());
    sParaTemp.put("nick_name", sendRedPackPo.getNick_name());
    sParaTemp.put("send_name", sendRedPackPo.getSend_name());
    sParaTemp.put("re_openid", sendRedPackPo.getRe_openid());
    sParaTemp.put("total_amount", sendRedPackPo.getTotal_amount());
    sParaTemp.put("min_value", sendRedPackPo.getMin_value());
    sParaTemp.put("max_value", sendRedPackPo.getMax_value());
    sParaTemp.put("total_num", sendRedPackPo.getTotal_num());
    sParaTemp.put("wishing", sendRedPackPo.getWishing());
    sParaTemp.put("client_ip", sendRedPackPo.getClient_ip());
    sParaTemp.put("act_name", sendRedPackPo.getAct_name());
    sParaTemp.put("remark", sendRedPackPo.getRemark());


            //除去数组中的空值和签名参数
            Map<String, String> sPara = paraFilter(sParaTemp);
    String prestr = createLinkString(sPara); //把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
    String key = "&key=192006250b4c09247ec02edce69f6a2d"; //商户支付密钥
    String mysign = MD5.sign(prestr, key, "utf-8").toUpperCase();
            
    sendRedPackPo.setSign(mysign);

            
    String respXml = MessageUtil.messageToXml(sendRedPackPo);

    //打印respXml发现,得到的xml中有“__”不对,应该替换成“_”
    respXml = respXml.replace("__", "_");


            // 将解析结果存储在HashMap中
    Map<String, String> map = new HashMap<String, String>();


    KeyStore keyStore  = KeyStore.getInstance("PKCS12");
            FileInputStream instream = new FileInputStream(new File("/home/apiclient_cert.p12")); //此处为证书所放的绝对路径
            
            try {
                keyStore.load(instream, mch_id.toCharArray());
            } finally {
                instream.close();
            }


            // Trust own CA and all self-signed certs
            SSLContext sslcontext = SSLContexts.custom()
                    .loadKeyMaterial(keyStore, mch_id.toCharArray())
                    .build();
            // Allow TLSv1 protocol only
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                    sslcontext,
                    new String[] { "TLSv1" },
                    null,
                    SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
            CloseableHttpClient httpclient = HttpClients.custom()
                    .setSSLSocketFactory(sslsf)
                    .build();
            
            try {


                HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack");
                
                StringEntity  reqEntity  = new StringEntity(respXml, "utf-8");
                
                // 设置类型 
                reqEntity.setContentType("application/x-www-form-urlencoded"); 
                
                httpPost.setEntity(reqEntity);
                
                System.out.println("executing request" + httpPost.getRequestLine());


                CloseableHttpResponse response = httpclient.execute(httpPost);
                try {
                    HttpEntity entity = response.getEntity();
                    System.out.println(response.getStatusLine());
                    if (entity != null) {


                // 从request中取得输入流
                InputStream inputStream = entity.getContent();
                // 读取输入流
                SAXReader reader = new SAXReader();
                Document document = reader.read(inputStream);
                // 得到xml根元素
                Element root = document.getRootElement();
                // 得到根元素的所有子节点
                List<Element> elementList = root.elements();


                // 遍历所有子节点
                for (Element e : elementList)
                map.put(e.getName(), e.getText());


                // 释放资源
                inputStream.close();
                inputStream = null;


                    }
                    EntityUtils.consume(entity);
                } finally {
                    response.close();
                }
            } finally {
                httpclient.close();
            }


    // 返回状态码
    String return_code = map.get("return_code");
    // 返回信息
    String return_msg = map.get("return_msg");
    // 业务结果
    String result_code = map.get("result_code");
    // 错误代码
    String err_code = map.get("err_code");
    // 错误代码描述
    String err_code_des = map.get("err_code_des");

    /**
    * 根据以上返回码进行业务逻辑处理
    */
    .
    .
    .


    }

     

    MessageUtil工具类,在柳峰老师的博客里有的。

    代码中httpclient-4.3.4.jar没有放上去,麻烦小伙伴们自己找下吧。

    实现效果:

     

     

     

     

    如果小伙伴们觉得有什么问题,可以联系讨论。

    转载请标明出处。

    展开全文
  • ├<微信公众平台搭建与开发揭秘【PHP微信开发】> │ ├视频配套代码.zip │ ├书籍配套代码.zip │ ├微信接口10图片回复.rmvb │ ├微信接口11测距.rmvb │ ├微信接口12最近店铺.rmvb │ ├微信接口13天气预报....
  • 微信公众号的开发,这个博主写的很好,有需要的请参考:转载自:...所以下面给大家分享一下我的经验: 第一部分 介绍微信公众号的一些简单介绍以及微信扮演的一些角色,微信公众号的重...

    微信公众号的开发,这个博主写的很好,有需要的请参考:

    转载自:http://www.cnblogs.com/liuhongfeng/p/4846260.html


    相信很多人或多或少听说了微信公众平台的火热。但是开发还是有一点门槛,鉴于挺多朋友问我怎么开发,问多了,自己平时也进行以下总结。

    所以下面给大家分享一下我的经验:

     

     

    第一部分   介绍微信公众号的一些简单介绍以及微信扮演的一些角色,微信公众号的重要性。

     

    1. 微信公众号是什么?

     

       官网的介绍:再小的个体也有品牌。

      

     

     

    2. 微信已经成为人们生活中必不可少的一部分

     

    早上醒来时间:

     

              可以说人类抱着微信睡着,然后从微信中醒来;

    每天早晨,起床气少了,困意不再那么困了,因为惦记着微信里发生了什么;

             每天早晨,每个草根,每个屌丝,每个文艺青年,甚至每个大妈,都开始向古代帝王批阅奏折一样,点个赞,给个评语,然后等待那些似有可无的回复。。。

     

    起床时间:

     

             不刷牙、不洗脸、不下床、不嘿咻……而要干的第一件事,用各种各样的手机、平板……打开同一个APP:微信。

             人类上厕所,因为微信,大号的时间延长了N分钟,小号也被大号了。

     

    上班的路上:

     

             开车的碰上红灯或者堵车,也不再像过去那么焦急了,正好可以低头看看微信了。时间过得飞起!

    人类眼睛的阅读文字图文量,也重新回来不低的数字。

             人类的思想见识,突然广了起来,闷骚有了明骚的资本,孤寂的有自己的春天,清高的忽然改成清新路线了。

        全国微民,每四分钟低一下头,看微信刷朋友圈。

     

    晚上的时间:

     

       全国微信用户已达四亿,连一向爱跳广场舞的大妈大爷也开始成微民了。

     

     

    总之:微信已经在我们生活中任何地方。

     

            不论什么人,不论你是谁,都可以随便的发出声音了。

             我去去去,该刷朋友圈了!

       

     

     

    3. 微信公众号能帮助我们干些什么?

     

         具体的商业应用。不在累赘。

        

    4. 微信公众号的类别有什么?

     

       服务号和订阅号的区别。

       

     

    详细的规则:

    不同的公众号类型具备不同的接口权限,具体如下表: 请注意:

    1、微博认证视作未认证,因此微博认证的公众号不会拥有微信认证公众号特有的接口。
    2、微信认证分为资质认证和名称认证两部分,只需要资质认证通过,就可获得接口。
    

    接口名称未认证订阅号微信认证订阅号未认证服务号微信认证服务号
    基础支持-获取access_token
    基础支持-获取微信服务器IP地址
    接收消息-验证消息真实性、接收普通消息、接收事件推送、接收语音识别结果
    发送消息-被动回复消息
    发送消息-客服接口  
    发送消息-群发接口  
    发送消息-模板消息接口(发送业务通知)   
    用户管理-用户分组管理  
    用户管理-设置用户备注名  
    用户管理-获取用户基本信息  
    用户管理-获取用户列表  
    用户管理-获取用户地理位置   
    用户管理-网页授权获取用户openid/用户基本信息   
    推广支持-生成带参数二维码   
    推广支持-长链接转短链接口   
    界面丰富-自定义菜单 
    素材管理-素材管理接口  
    智能接口-语义理解接口   
    多客服-获取多客服消息记录、客服管理   
    微信支付接口   需申请
    微信小店接口   需申请
    微信卡券接口 需申请 需申请
    微信设备功能接口   需申请
    微信JS-SDK-基础接口
    微信JS-SDK-分享接口  
    微信JS-SDK-图像接口
    微信JS-SDK-音频接口
    微信JS-SDK-智能接口(网页语音识别)
    微信JS-SDK-设备信息
    微信JS-SDK-地理位置
    微信JS-SDK-界面操作
    微信JS-SDK-微信扫一扫
    微信JS-SDK-微信小店   
    微信JS-SDK-微信卡券  
    微信JS-SDK-微信支付   

     

     

     

    第二部分  微信公众号开发需要准备的一些资料以及如何搭建一个测试服务器

     

    一、服务器准备

     

    1.方式一:买的云主机。推荐 爱名网

    2.方式二:BAE(注册百度账号,然后登录 百度云开发 

    3.方式三:SAE(注册新浪微博,然后登录SAE ,点击注册「新浪云福利」现在还有1000云豆免费领!一起来用吧!)  比较推荐的方式。

    4.方式四:  购买花生壳这种本地映射外网的工具。通过这样的工具方便我们在本地进行调试。(推荐) 具体文章请参考:如何架设本地web 服务器来调试自己的微信公众号服务

    5.方式五:可以通过免费映射工具。比如:ngrok  ,natapp 等;

    大家看自己情况进行选择。

     

    二、详细介绍这几种方式。

     

    方式一:通过云服务器方式形式进行。

     

    一般需要懂一些linux相关的知识,这里不进行详细展开说明。

    如果需要了解,可以参考我的linux栏目相关文章。http://www.souvc.com/?cat=330

     

     

    方式二:通过BAE来充当服务器。(现在已经收费了,需要免费的童鞋,可能不大适合)

     

    (1)用百度账号,登录百度开发者中心。来到主界面如下图:

     

     

     (2)选择应用引擎(BAE)

     

     

     (3)创建一个自己的应用。并选择开发环境,我这里选择的是java-tomcat。以及维护代码方式,我选择的是svn方式。

     

     

    (4)确定创建成功。

     

     

     (5)查看应用信息。

     

     

     (6)访问自己的应用链接。出现以下的界面,说明了成功。

     

     

     

    方式三 : 利用sae充当服务器。

     

    (1)注册新浪sae账号。

     

    SAE官网地址:点击注册

     

    (2)创建java应用。

     

         A: 进入sae控制台:http://sae.sina.com.cn/

     

     

          B: 创建新应用。

     

     

          C:选择java环境。

     

     

       D: 填写自己的应用信息。(改为自己的应用信息)

     

         E: 把自己的应用包上传即可。

     

     

     

     

    方式四:  购买花生壳这种本地映射外网的工具。

     

    详细搭建方法,可以参考:第2章 如何架设本地web 服务器来调试自己的微信公众号服务

     

     

    方式五:通过免费的映射工具。

     

    (1)natapp  

    官网 :https://natapp.cn/

     

    (2)ngrok

     

    官网:https://www.ngrok.cc/

     

    (3)nat123

    官网:http://www.nat123.com/

     

    现在服务器配置暂时到这里。后面再说如何配置。欢留言迎大家在留言进行补充说明!

     

     

    第三部分  微信账号相关资料的准备 

     

    申请一个微信号(下载微信客户端,手机注册,或是qq注册)

    申请一个微信公众号 (去申请),申请什么样的微信公众号,请参照 微信详细注册步骤

    申请一个微信公众平台接口测试帐号 (去申请

     

     

     

    其他文章关联:

    第一篇:微信公众平台开发实战Java版之了解微信公众平台基础知识以及资料准备

    第二篇 :微信公众平台开发实战Java版之开启开发者模式,接入微信公众平台开发

    第三篇 :微信公众平台开发实战Java版之请求消息,响应消息以及事件消息类的封装

    第四篇 :微信公众平台开发实战Java版之完成消息接受与相应以及消息的处理

    第五篇 :微信公众平台开发实战Java版之如何获取公众号的access_token以及缓存access_token

    第六篇 :微信公众平台开发实战Java版之如何自定义微信公众号菜单

    第七篇 :微信公众平台开发实战Java版之如何获取微信用户基本信息

    第八篇 :微信公众平台开发实战Java版之如何网页授权获取用户基本信息

    第九篇 :微信公众平台开发实战Java版之如何实现自定义分享内容

    其他:Web开发须知:URL编码与解码

     


    ---------------------------------------------------------------------------------------------------------------------------------
    ---------------------------------------------------------------------------------------------------------------------------------------- 



    展开全文
  • 【课程内容】Java微信二次开发微信验证Java微信二次开发智能机器人java微信二次开发微信公众号平台基于java的微信订阅号自动回复接口基于java的微信二次开发必备要素基于java的微信二次开发智能机器人基于java的微信...

    【课程内容】

    Java微信二次开发微信验证
    Java微信二次开发智能机器人
    java微信二次开发微信公众号平台
    基于java的微信订阅号自动回复接口
    基于java的微信二次开发必备要素
    基于java的微信二次开发智能机器人
    基于java的微信二次开发打造中国快递实时查询APP
    基于java的微信二次大数据时代=微信时代
    基于java的微信二次开发_必备要素(穿透、映射)
    基于java的微信二次开发-打造腾讯微视频
    基于java的微信二次开发-开发淘宝智能客服
    基于java的微信二次开发-大数据时代、微信时代
    基于java的微信二次开发-微人脸识别系统
    基于java的微信二次开发-银行卡交易实时提醒系统
    基于java的微信二次开发-国家电网微营业厅
    移动互联网时代-企业级微信菜单定制开发
    基于java的微信二次开发-高考实时通知系统
    基于java的微信二次开发-LBS地理位置定位-Eric老师

     

    下载地址:百度网盘

    展开全文
  • 准备写系列博客,记录下我的微信公众平台学习记录,也为那些摸索中的开发者提供点参考。 希望与大家共同进步。 微信3.0的时候我开始做微信公众账号,那时候没时间研究开发,先用的是编辑者模式,后用开发者模式,...
  • 微信公众号平台也有自定义回复消息,比如我在公众号里发送关注你,我们在微信公众号平台设置关键字关注你(就是 有人发送这个关键字就要回复什么内容)设置成回复:你好,java!适用于这种固定信息,如果我发送...
  • 申请 通过https://mp.weixin.qq.com进入微信公众平台首页,在最下面得“开发”菜单中选择“开发者工具”。 然后在左侧页面选择“公众平台测试帐号”进入平台测试账号。 2、ngrok 可以将本地的tomcat的端口映射到...
  • 微信开发

    2020-06-03 23:32:36
    教程名称:微信开发 【】1.经典PHP微信公众号平台开发视频教程.zip 【】2.50集PHP微信接口实战开发案例教程.zip 【】3.JAVA微信全套视频教程.zip 【】4.JAVA安卓之微信项目开发实战教程 源码.zip 【】5...
  • 上一节,我们启用服务器配置的时候,填写了一个服务器地址(url),如下图,这个url就是回调url,是开发者用来接收微信消息和事件的接口URL。也就是说,用户在微信公众号中发送的消息会被推送到这个回调url,而我们...
  • 批量解析微信dat文件

    2020-06-29 14:36:32
    微信文件利用Xor加密,计算之前需要知道异或值是多少。(好像每个人电脑上面的异或值都不同,需要更换代码的地方在里面已经注明) package cn.kgw; import java.io.*; import java.util.concurrent.ExecutorService...
  • JSSDK使用步骤 步骤一:绑定域名 先登录微信公众平台...(顺便推荐做微信开发测试时,使用花生壳账号,映射出公网ip。)比如网址:http://test.wicp.net 那么它的域名就是 test.wicp.net。 步骤二:引入JS文件 ...
  • 微信小程序天气(含java后端),前端,后端都有。会弄得自己下载把。
1 2 3 4 5 ... 20
收藏数 5,803
精华内容 2,321