SpringBoot开发微信公众号现金红包

简介:

主要流程为按照微信要求的格式准备xml发送数据,然后发送请求,微信响应后再解析返回的数据,根据返回数据再进行自己的业务操作。

注意代码中需要自己填写的部分以及证书位置要用绝对路径;

依赖:

<!-- 解析xml -->
<dependency>
    <groupId>com.thoughtworks.xstream</groupId>
    <artifactId>xstream</artifactId>
    <version>1.4.10</version>
</dependency>

实体类:

package com.ruoyi.project.wxuserhb.domain;

import java.io.Serializable;

/**
 * 微信发放红包接口 sdkVo
 *
 * @author Qiu
 * @date 2022-11-24 10:24
 */
public class WxRedpackSdkVo implements Serializable {
    private String nonce_str;// 随机字符串
    private String sign;// 签名
    private String mch_billno;// 商户订单号
    private String mch_id;// 商户号
    private String wxappid;// 公众账号
    private String send_name;// 商户名称
    private String re_openid;// 用户
    private int total_amount;// 付款金额
    private int total_num;// 红包发放总人数
    private String wishing;// 红包祝福语
    private String client_ip;// Ip地址
    private String act_name;// 活动名称
    private String remark;// 备注

    public int getTotal_amount() {
        return total_amount;
    }

    public void setTotal_amount(int total_amount) {
        this.total_amount = total_amount;
    }

    public int getTotal_num() {
        return total_num;
    }

    public void setTotal_num(int total_num) {
        this.total_num = total_num;
    }

    public String getNonce_str() {
        return nonce_str;
    }

    public void setNonce_str(String nonce_str) {
        this.nonce_str = nonce_str;
    }

    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 mch_billno) {
        this.mch_billno = mch_billno;
    }

    public String getMch_id() {
        return mch_id;
    }

    public void setMch_id(String mch_id) {
        this.mch_id = mch_id;
    }

    public String getWxappid() {
        return wxappid;
    }

    public void setWxappid(String wxappid) {
        this.wxappid = wxappid;
    }

    public String getSend_name() {
        return send_name;
    }

    public void setSend_name(String send_name) {
        this.send_name = send_name;
    }

    public String getRe_openid() {
        return re_openid;
    }

    public void setRe_openid(String re_openid) {
        this.re_openid = re_openid;
    }

    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 client_ip) {
        this.client_ip = client_ip;
    }

    public String getAct_name() {
        return act_name;
    }

    public void setAct_name(String act_name) {
        this.act_name = act_name;
    }

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }
}

工具类:

package com.ruoyi.project.wxuserhb.Utils;

import com.ruoyi.project.wxuserhb.domain.WxRedpackSdkVo;
import com.ruoyi.project.wxuserhb.service.impl.OWechatuserHongbaoServiceImpl;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.naming.NoNameCoder;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;
import javax.net.ssl.SSLContext;
import java.io.*;
import java.security.KeyStore;
import java.text.SimpleDateFormat;
import java.util.*;


@Service
public class HongBaoUtil {

    /**
     * 现金红包
     * @Title: bindDevice
     * @return String
     * @throws
     */
    public Map<String, String> sendRedPack(@RequestBody WxRedpackSdkVo redPack) throws Exception{

        redPack.setMch_id("商户号");
        redPack.setClient_ip("服务端地址或设备地址(不大重要填自己服务器地址就行)");
        redPack.setWxappid("appId");
        redPack.setWishing("感谢您为环保做出的贡献");
        redPack.setSend_name("随手拍服务平台");
        redPack.setAct_name("随手拍举报奖励");
        redPack.setRemark("保护环境人人有责,感谢您为环境保护贡献一份力量,希望您继续保持");
        // 生成订单号
        String billno = redPack.getMch_id()+ new SimpleDateFormat("yyyyMMddHHmmssSSS") .format(new Date() ) ;
        String noncestr = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
        redPack.setNonce_str(noncestr);
        redPack.setMch_billno(billno);
        // 微信现金红包Url 地址
        String sendEedPackUrl = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack";
        // 生成签名
        String sign = createSendRedPackOrderSign(redPack);
        redPack.setSign(sign);
        XStream xstream = new XStream(new XppDriver(new NoNameCoder()) {

            @Override
            public HierarchicalStreamWriter createWriter(Writer out) {
                return new PrettyPrintWriter(out) {
                    // 对所有xml节点的转换都增加CDATA标记
                    boolean cdata = true;

                    @Override
                    @SuppressWarnings("rawtypes")
                    public void startNode(String name, Class clazz) {
                        super.startNode(name, clazz);
                    }

                    @Override
                    public String encodeNode(String name) {
                        return name;
                    }


                    @Override
                    protected void writeText(QuickWriter writer, String text) {
                        if (cdata) {
                            writer.write("<![CDATA[");
                            writer.write(text);
                            writer.write("]]>");
                        } else {
                            writer.write(text);
                        }
                    }
                };
            }
        });
        xstream.alias("xml", redPack.getClass());
        String xml = xstream.toXML(redPack);

        String response = ssl(sendEedPackUrl,xml);
        Map<String, String> mapstr = new HashMap<>();
        Document doc = null;
        try {
            doc = DocumentHelper.parseText(response);
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        Element root = doc.getRootElement();// 指向根节点
        Iterator it = root.elementIterator();

        while (it.hasNext()) {
            Element element = (Element) it.next();// 一个Item节点
            System.out.println(element.getName() + " : " + element.getTextTrim());
            mapstr.put(element.getName(),element.getTextTrim());
        }
        return mapstr;
    }

    /**
     * 生成签名
     * @param redPack
     * @return
     */
    public String createSendRedPackOrderSign(WxRedpackSdkVo redPack){
        StringBuffer sign = new StringBuffer();
        sign.append("act_name=").append(redPack.getAct_name());
        sign.append("&client_ip=").append(redPack.getClient_ip());
        sign.append("&mch_billno=").append(redPack.getMch_billno());
        sign.append("&mch_id=").append(redPack.getMch_id());
        sign.append("&nonce_str=").append(redPack.getNonce_str());
        sign.append("&re_openid=").append(redPack.getRe_openid());
        sign.append("&remark=").append(redPack.getRemark());
        sign.append("&send_name=").append(redPack.getSend_name());
        sign.append("&total_amount=").append(redPack.getTotal_amount());
        sign.append("&total_num=").append(redPack.getTotal_num());
        sign.append("&wishing=").append(redPack.getWishing());
        sign.append("&wxappid=").append(redPack.getWxappid());
        sign.append("&key=").append("xxxx生成签名用");
        return DigestUtils.md5Hex(sign.toString()).toUpperCase();
    }

    /**
     * 发送链接
     * @param url
     * @param data
     * @return
     */
    private String ssl(String url,String data){
        StringBuffer message = new StringBuffer();
        String mchId = "商户号";
        try {
            KeyStore keyStore  = KeyStore.getInstance("PKCS12");
            FileInputStream instream = new FileInputStream(new File("/home/hb/apiclient_cert.p12")); // 证书位置
            keyStore.load(instream, mchId.toCharArray());
            SSLContext sslcontext = SSLContexts.custom()
                    .loadKeyMaterial(keyStore, mchId.toCharArray())
                    .build();
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                    sslcontext,
                    new String[] { "TLSv1" },
                    null,
                    SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
            CloseableHttpClient httpclient = HttpClients.custom()
                    .setSSLSocketFactory(sslsf)
                    .build();
            HttpPost httpost = new HttpPost(url);

            httpost.addHeader("Connection", "keep-alive");
            httpost.addHeader("Accept", "*/*");
            httpost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
            httpost.addHeader("Host", "api.mch.weixin.qq.com");
            httpost.addHeader("X-Requested-With", "XMLHttpRequest");
            httpost.addHeader("Cache-Control", "max-age=0");
            httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
            httpost.setEntity(new StringEntity(data, "UTF-8"));
            System.out.println("executing request" + httpost.getRequestLine());

            CloseableHttpResponse response = httpclient.execute(httpost);
            try {
                HttpEntity entity = response.getEntity();

                System.out.println("----------------------------------------");
                System.out.println(response.getStatusLine());
                if (entity != null) {
                    System.out.println("Response content length: " + entity.getContentLength());
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent(),"UTF-8"));
                    String text;
                    while ((text = bufferedReader.readLine()) != null) {
                        message.append(text);
                    }

                }
                EntityUtils.consume(entity);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                response.close();
            }
        } catch (Exception e1) {
            e1.printStackTrace();
        }

        return message.toString();
    }
}

使用:

这个说明一下,不用按照下图所示,就是在你需要使用的地方无论是controller,还是serviceimpl中,把HongBaoUtil注册为一个service服务,然后把未赋值的参数提供一下,调用服务中的函数即可发送,返回的为map集合。

@Service
public class OWechatuserHongbaoServiceImpl implements IOWechatuserHongbaoService 
{
    @Autowired
    private HongBaoUtil hongbaoService;

    /**
     * 发红包
     * @param dto
     * @return
     */
    @Override
    public void bufaHongbao() {

        WxRedpackSdkVo wdto = new WxRedpackSdkVo();
        wdto.setTotal_amount(100); // 设置金额,分为单位
        wdto.setTotal_num(1);    // 红包数量
        wdto.setRe_openid("xxxxxx") // 用户该公众号下的openID;
        Map<String, String> mapstr = null;

        try {
            mapstr = hongbaoService.sendRedPack(wdto);
        } catch (Exception e) {
            log.error("补发红包出错"+dto.toString());
            e.printStackTrace();
        }

        System.out.println(mapstr);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值