微信小程序> java实现微信企业付款到个人零钱(微信红包)

java实现微信企业付款到个人零钱(微信红包)

浏览量:4576 时间: 来源:梦寻千古-nsh

        今天公司打算做一个活动,就是可以让用户领取平台发送的红包,根据微信官方文档实现微信企业付款到零钱(因为商户号不满足一些条件无法使用红包,红包跟零钱实现方法基本一样),然后又加入了一些简单的红包算法。微信官方文档地址:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_1

        红包发送的规则:总共有100个红包,总金额100元,最小红包0.05,最大红包3,也就是说100元,发100次基本上能领完。红包领取的规则:在移动端页面上展示红包,用户领取的时候,调用后台接口领取红包(一些领取规则可以自己添加)。

        零钱(红包)发放接口如下

    @ResponseBody    @RequestMapping("wxSendWallet")    public void wxSendWallet(String openid) {        //微信金额的单位是分 所以这里要*100         float money = getRedPack();        BigDecimal df = new BigDecimal(money+"");     df = df.multiply(new BigDecimal("100"));     int fee = df.intValue();     //创建一个唯一订单号        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");        String time = sdf.format(new Date());     String orderId = time + (int)(Math.random()*1000000);        String xml = WeixinCore.wxSendWallet(orderId,openid,String.valueOf(fee));        try {            //指定读取证书格式为PKCS12            KeyStore keyStore = KeyStore.getInstance("PKCS12");            //windows系统            //FileInputStream instream = new FileInputStream(new File("D:\cert\apiclient_cert.p12"));            //linux系统,读取本机存放的PKCS12证书文件            FileInputStream instream = new FileInputStream(new File("/alidata/opt/paycert/apiclient_cert.p12"));            try {            //指定PKCS12的密码(商户ID)                //keyStore.load(instream, accountUtil.getWxPartnerId().toCharArray());            keyStore.load(instream, "微信商户号".toCharArray());            }finally {                instream.close();            }            // Trust own CA and all self-signed certs            SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, "微信商户号".toCharArray()).build();        //指定TLS版本, Allow TLSv1 protocol only            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(                    sslcontext, new String[] { "TLSv1" }, null, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);            //设置httpclient的SSLSocketFactory            CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();            HttpPost httppost = new HttpPost("https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers");        //这里要设置编码,不然xml中有中文的话会提示签名失败或者展示乱码            httppost.addHeader("Content-Type", "text/xml");            StringEntity se = new StringEntity(xml,"UTF-8");            httppost.setEntity(se);            CloseableHttpResponse responseEntry = httpclient.execute(httppost);            try {                HttpEntity entity = responseEntry.getEntity();                if (entity != null) {                    System.out.println("响应内容长度 : "+ entity.getContentLength());                    SAXReader saxReader = new SAXReader();                    Document document = saxReader.read(entity.getContent());                    Element rootElt = document.getRootElement();                    String resultCode = rootElt.elementText("result_code");                    if(resultCode.equals("SUCCESS")){                    //保存红包信息到数据库                        //保存用户领取记录                    }else{                    System.out.println(rootElt.elementText("err_code_des"));                    }                }                EntityUtils.consume(entity);            }catch(Exception e){            System.out.println("请求失败");            }            finally {                responseEntry.close();            }        }catch(Exception e){        System.out.println("请求失败");        }    }

       getRedPack方法如下, 假如第一次领取(后台获取表示从后台查询所得)

    public float getRedPack(){//红包数   (后台获取)        int number = 100;            //剩余红包总额    (后台获取)        float total = 100;  float money = 0f;            //最小红包    (后台获取)        double min = 0.05;            //系统最大红包(后台获取)        float systemMax = 3;        //最大红包        double max;        //剩余领取次数(后台获取)        int surplusNumber = 100;                //本次领取之后,剩余领取次数减一        surplusNumber--;                DecimalFormat df = new DecimalFormat("###.##");            if (surplusNumber  0) {                 //保证即使一个红包是最大的了,后面剩下的红包,每个红包也不会小于最小值                  max = total - min * surplusNumber;                  int k = (int)surplusNumber / 2;                  //保证最后两个人拿的红包不超出剩余红包                 if (surplusNumber = 2) {                      k = surplusNumber;                  }                 //最大的红包限定的平均线上下                  max = max / k;                 //保证每个红包大于最小值,又不会大于最大值                  money = (int) (min * 100 + Math.random() * (max * 100 - min * 100 + 1));                money = (float)money / 100;                 //保留两位小数                  money = Float.parseFloat(df.format(money));                //如果红包大于默认最大值,将红包职位默认最大值            if(money  systemMax){            money = systemMax;            }            total=(int)(total*100 - money*100);                 total = total/100;            System.out.println("第" + (number - surplusNumber) + "个人拿到" + money + "剩下" + total);             } else if(surplusNumber == 0){//如果是最后一次,不需要计算        //如果最后一次红包超过系统最大红包,设置为系统默认最大红包        if(total  systemMax){        money = systemMax;        total=(int)(total*100 - money*100);        total = total/100;        System.out.println("最后一个人拿到" + money + "剩下"+total);          }else{        money = total;        System.out.println("最后一个人拿到" + money + "剩下0");          }        }else{        System.out.println("红包已发放完毕");        }        return money;    }

        进行签名,将参数排序并拼接成xml

    public static String wxSendWallet(String partner_trade_no, String openid,String total_amount) {        String data = null;        try {            String nonceStr = genNonceStr();            //SortedMap接口主要提供有序的Map实现,默认的排序是根据key值进行升序排序            SortedMapString,String parameters = new TreeMapString,String();            parameters.put("mch_appid", "商户appid");            parameters.put("mchid", "商户号");            parameters.put("nonce_str", nonceStr);            parameters.put("partner_trade_no", partner_trade_no);            parameters.put("openid", openid);            parameters.put("check_name", "NO_CHECK");            parameters.put("amount", total_amount);            parameters.put("spbill_create_ip", WeChatPayUtil.getLocalIP());            parameters.put("desc", "福利红包");            //签名            parameters.put("sign", createSign(parameters, "商户的key"));            data =SortedMaptoXml(parameters);        } catch (Exception e) {            e.printStackTrace();        }        return data;    }

getLocalIp() 获取ip地址

    public static String getLocalIP() {           InetAddress addr = null;           try {            addr = InetAddress.getLocalHost();        } catch (UnknownHostException e) {            e.printStackTrace();        }                 byte[] ipAddr = addr.getAddress();           String ipAddrStr = "";           for (int i = 0; i  ipAddr.length; i++) {               if (i  0) {                   ipAddrStr += ".";               }               ipAddrStr += ipAddr[i] & 0xFF;           }           return ipAddrStr;       } 

createSign() 签名算法

    /**     * @Title: createSign     * @Description: 签名算法,创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。     * 参照:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=4_3     */    public static String createSign(SortedMapString, String packageParams, String AppKey) {        StringBuffer sb = new StringBuffer();        Set es = packageParams.entrySet();        Iterator it = es.iterator();        while (it.hasNext()) {            Map.Entry entry = (Map.Entry) it.next();            String k = (String) entry.getKey();            String v = (String) entry.getValue();            if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {                sb.append(k + "=" + v + "&");            }        }        sb.append("key=" + AppKey);        String sign = MD5Util.MD5Encode(sb.toString(), "UTF-8").toUpperCase();        return sign;    }

MD5Encode() 常见md5摘要

    public static String MD5Encode(String origin, String charsetname) {             String resultString = null;          try {              resultString = new String(origin);              MessageDigest md = MessageDigest.getInstance("MD5");              if (charsetname == null || "".equals(charsetname))                  resultString = byteArrayToHexString(md.digest(resultString                          .getBytes()));              else                  resultString = byteArrayToHexString(md.digest(resultString                          .getBytes(charsetname)));          } catch (Exception exception) {          }          return resultString;      }

上面的就是整个的逻辑,需要的方法都在这里了,配置好了运行肯定是没问题的,测试的效果如下:

随笔记录一下,如果有问题请留言

版权声明

即速应用倡导尊重与保护知识产权。如发现本站文章存在版权问题,烦请提供版权疑问、身份证明、版权证明、联系方式等发邮件至197452366@qq.com ,我们将及时处理。本站文章仅作分享交流用途,作者观点不等同于即速应用观点。用户与作者的任何交易与本站无关,请知悉。

产品经理

手机 : 13312967497

擅长 : 小程序流量变现

扫码领取礼包

热门模板

  • 头条
  • 搜狐
  • 微博
  • 百家
  • 一点资讯
  • 知乎