美文网首页
2019-03-28 java 调用微信红包接口

2019-03-28 java 调用微信红包接口

作者: 阿饼不是炳 | 来源:发表于2019-03-28 14:28 被阅读0次

java 调用微信红包接口

之前写的一个微信红包接口,用于公众号自动发送红包给用户,调用微信接口思路都是相同的,其他接口也可以使用这个方法。

  • jar包

方法涉及的java包过多,需要自行查询下载

  • 方法

    public final static int SEND_FAILED = 0; // 发放失败
    public final static int SEND_SENDING = 1; // 发放中
    public final static int SEND_SENT = 2; // 已发放
    public final static int SEND_RECEIVED = 3; // 已领取

    @Autowired
    private ConfigMgrService configMgrService;

    @Autowired
    private WXpayorderService wXpayorderService;
// 红包接口
    public String do_pay(String openid, int price ,String act_name) {
        logger.info("WechatPay::do_pay called");

        if (openid == null) {
            logger.error("WechatPay::openid  is null");
            return "fail";
        }
        Map wx_pay_config = configMgrService.queryWxConfigByGameid(1);//数据库获取商户平台配置,根据项目更改
        if (wx_pay_config == null) {
            logger.error("WechatPay::wx_pay_config  is null");
            return "fail";
        }

        String ip = wx_pay_config.get("client_ip").toString();
        int game_id = Integer.parseInt(wx_pay_config.get("game_id").toString());

        // 拼接请求参数
        Map<String, String> paramap = new HashMap<String, String>();

        // 随机字符串
        String nonce_str = create_nonce_str();
        paramap.put("nonce_str", nonce_str);
        // 商户订单号
        String orderid = createOrderId();

        paramap.put("mch_billno", orderid);
        // 商户号
        paramap.put("mch_id", wx_pay_config.get("mch_id").toString());
        // appid
        paramap.put("wxappid", wx_pay_config.get("app_id").toString());
        // 商户名称
        paramap.put("send_name", wx_pay_config.get("send_name").toString());
        // 用户openid
        paramap.put("re_openid", openid);
        // 付款金额
        paramap.put("total_amount", String.valueOf(price));
        // 红包发放总人数
        paramap.put("total_num", String.valueOf(1));
        // 红包祝福语
        paramap.put("wishing", "恭喜中奖");
        // ip地址
        paramap.put("client_ip", ip);
        // 活动名称
        paramap.put("act_name", act_name);
        // 备注
        paramap.put("remark", "红包");
        // 场景id
        paramap.put("scene_id", "PRODUCT_5");//查看微信开发者文档自行修改

        // 签名
        try {
            String paysign = getPayCustomSign(paramap, wx_pay_config.get("key")
                    .toString()); // todo get sign
            // key
            paramap.put("sign", paysign);
        } catch (Exception e) {
            logger.error(e.toString());
            return "fail";
        }

        String xml = ArrayToXml(paramap);

        // 向微信接口发起请求
        String url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack";

        String xmlresponse = "";
        try {
            xmlresponse = sendRedEnvelope(url, xml);
        } catch (Exception e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
            logger.error("WechatPay::" + e1);
        }

        // String xmlresponse = dopost(url, xml);
        if (xmlresponse.isEmpty()) {
            logger.error("ActivityWechatPay::dopost failed");
            return "fail";
        }

        // 解析返回数据
        try {
            logger.info("ActivityWechatPay::xml response:" + xmlresponse);
            Map<String, String> responsemap = doXMLParse(xmlresponse);
            // 通信标识
            String returncode = responsemap.get("return_code");
            if (!returncode.equals("SUCCESS")) {
                logger.error("WechatPay::wechat return err:" + returncode
                        + ",return_msg:" + responsemap.get("return_msg"));

                return "fail";
            }

            // 业务结果
            returncode = responsemap.get("result_code");
            if (!returncode.equals("SUCCESS")) {
                logger.error("WechatPay::wechat return err:"
                        + responsemap.get("err_code") + ",err_code_des:"
                        + responsemap.get("err_code_des"));
                return "fail";
            }

        } catch (XmlPullParserException e) {
            logger.error(e.toString());
        } catch (IOException ioe) {
            logger.error(ioe.toString());
        }
        return "success";
    }

// 生成签名
    private String getPayCustomSign(Map<String, String> bizObj, String key)
            throws Exception {

        String bizString = FormatBizQueryParaMap(bizObj, false);
        // logger.info(bizString);
        return sign(bizString, key);
    }
private String FormatBizQueryParaMap(Map<String, String> paraMap,
            boolean urlencode) throws Exception {
        String buff = "";
        try {
            List<Map.Entry<String, String>> infoIds = new ArrayList<Entry<String, String>>(
                    paraMap.entrySet());

            Collections.sort(infoIds,
                    new Comparator<Map.Entry<String, String>>() {
                        public int compare(Map.Entry<String, String> o1,
                                Map.Entry<String, String> o2) {
                            return (o1.getKey()).toString().compareTo(
                                    o2.getKey());
                        }
                    });

            for (int i = 0; i < infoIds.size(); i++) {
                Map.Entry<String, String> item = infoIds.get(i);
                // System.out.println(item.getKey());
                if (item.getKey() != "") {

                    String key = item.getKey();
                    String val = item.getValue();
                    if (urlencode) {
                        val = URLEncoder.encode(val, "utf-8");

                    }
                    buff += key + "=" + val + "&";

                }
            }

            if (buff.isEmpty() == false) {
                buff = buff.substring(0, buff.length() - 1);
            }
        } catch (Exception e) {
            throw new Exception(e.getMessage());
        }
        return buff;
    }
// 生成订单号
    private String createOrderId() {
        int machineId = 1;// 最大支持1-9个集群机器部署
        int hashCodeV = UUID.randomUUID().toString().hashCode();
        if (hashCodeV < 0) {
            hashCodeV = -hashCodeV;
        }
        return machineId + String.format("%027d", hashCodeV);
    }

    // 将拼接的字符串转化为xml文件
    public String ArrayToXml(Map<String, String> arr) {
        String xml = "<xml>";
        Iterator<Entry<String, String>> iter = arr.entrySet().iterator();
        while (iter.hasNext()) {
            Entry<String, String> entry = iter.next();
            String key = entry.getKey();
            String val = entry.getValue();
            xml += "<" + key + ">" + val + "</" + key + ">";
        }

        xml += "</xml>";
        return xml;
    }

    /**
     * 带证书httpPost请求
     * 
     * @param url
     *            接口地址
     * @param param
     *            参数
     * @return
     * @throws Exception
     */
    public static String sendRedEnvelope(String url, String param)
            throws Exception {
        // PKCS12的密码
        String PKCS12 = "";
        // 指定读取证书格式为PKCS12
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        InputStream instream = WechatPayMgr.class
                .getResourceAsStream("apiclient_cert.p12");
        // 读取本机存放的PKCS12证书文件
        if (instream == null) {
            instream = WechatPayMgr.class.getClassLoader().getResourceAsStream(
                    "apiclient_cert.p12");
        }
        if (instream == null) {
            instream = WechatPayMgr.class.getClassLoader()
                    .getSystemResourceAsStream("apiclient_cert.p12");
        }
        try {
            // 指定PKCS12的密码
            keyStore.load(instream, PKCS12.toCharArray());
        } finally {
            instream.close();
        }
        // 指定TLS版本
        SSLContext sslcontext = SSLContexts.custom()
                .loadKeyMaterial(keyStore, PKCS12.toCharArray()).build();
        // 设置httpclient的SSLSocketFactory
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                sslcontext, new String[] { "TLSv1" }, null,
                SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
        CloseableHttpClient httpclient = HttpClients.custom()
                .setSSLSocketFactory(sslsf).build();
        StringBuffer stringBuffer = new StringBuffer();
        try {
            HttpPost httpPost = new HttpPost(url);
            InputStream is = new ByteArrayInputStream(param.getBytes("UTF-8"));
            // InputStreamEntity严格是对内容和长度相匹配的。用法和BasicHttpEntity类似
            InputStreamEntity inputStreamEntity = new InputStreamEntity(is,
                    is.available());
            httpPost.setEntity(inputStreamEntity);
            CloseableHttpResponse response = httpclient.execute(httpPost);
            try {
                HttpEntity entity = response.getEntity();
                BufferedReader reader = new BufferedReader(
                        new InputStreamReader(entity.getContent(), "UTF-8"));
                String inputLine;
                while ((inputLine = reader.readLine()) != null) {
                    stringBuffer.append(inputLine);
                }
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }
        return stringBuffer.toString();
    }
// 解析xml
    private Map<String, String> doXMLParse(String xml)
            throws XmlPullParserException, IOException {

        InputStream inputStream = new ByteArrayInputStream(xml.getBytes());

        Map<String, String> map = null;

        XmlPullParserFactory dbf = XmlPullParserFactory.newInstance();
        String FEATURE = null;
        FEATURE = "http://xml.org/sax/features/external-general-entities";
        dbf.setFeature(FEATURE, false);
        FEATURE = "http://xml.org/sax/features/external-parameter-entities";
        dbf.setFeature(FEATURE, false);
        FEATURE = "http://apache.org/xml/features/nonvalidating/load-external-dtd";
        dbf.setFeature(FEATURE, false);

        XmlPullParser pullParser = dbf.newPullParser();

        pullParser.setInput(inputStream, "UTF-8"); // 为xml设置要解析的xml数据

        int eventType = pullParser.getEventType();

        while (eventType != XmlPullParser.END_DOCUMENT) {
            switch (eventType) {
            case XmlPullParser.START_DOCUMENT:
                map = new HashMap<String, String>();
                break;

            case XmlPullParser.START_TAG:
                String key = pullParser.getName();
                if (key.equals("xml"))
                    break;

                // xml无法解析多层标签,单独加保护(红包查询时需要)
                /*if (key.equals("hblist")) {
                    pullParser.next();
                    pullParser.next();
                    key = pullParser.getName();
                }*/

                String value = pullParser.nextText();
                map.put(key, value);

                break;

            case XmlPullParser.END_TAG:
                break;

            }

            eventType = pullParser.next();

        }

        return map;
    }

以上是红包发放方法,由于发送可能被微信驳回等失败因素,建议根据各自需求写一个红包是否发送成功的查询的方法。

相关文章

网友评论

      本文标题:2019-03-28 java 调用微信红包接口

      本文链接:https://www.haomeiwen.com/subject/mkyqbqtx.html