首页 > 开发 > Java > 正文

java微信公众号支付开发之现金红包

2024-07-14 08:40:21
字体:
来源:转载
供稿:网友

我们先来看看公众号发放现金红包的效果:

java,微信公众号,支付开发,java微信公众号开发,java微信现金红包,微信公众号现金红包

需要调用商户平台的接口,接口发放规则如下:

1.发送频率限制——默认1800/min
2.发送个数上限——按照默认1800/min算
3.金额上限——根据传入场景id不同默认上限不同,可以在商户平台产品设置进行设置和申请,最大不大于4999元/个
4.其他的“量”上的限制还有哪些?——用户当天的领取上限次数,默认是10
5.如果量上满足不了我们的需求,如何提高各个上限?——金额上限和用户当天领取次数上限可以在商户平台进行设置
注意-红包金额大于200时,请求参数scene_id必传,参数说明见下文。
注意2-根据监管要求,新申请商户号使用现金红包需要满足两个条件:1、入驻时间超过90天 2、连续正常交易30天。

请求Url https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack
是否需要证书 是(证书及使用说明详见商户证书)
请求方式 POST

请求数据示例:

 

<xml><sign><![CDATA[E1EE61A91C8E90F299DE6AE075D60A2D]]></sign><mch_billno><![CDATA[0010010404201411170000046545]]></mch_billno><mch_id><![CDATA[888]]></mch_id><wxappid><![CDATA[wxcbda96de0b165486]]></wxappid><send_name><![CDATA[send_name]]></send_name><re_openid><![CDATA[onqOjjmM1tad-3ROpncN-yUfa6uI]]></re_openid><total_amount><![CDATA[200]]></total_amount><total_num><![CDATA[1]]></total_num><wishing><![CDATA[恭喜发财]]></wishing><client_ip><![CDATA[127.0.0.1]]></client_ip><act_name><![CDATA[新年红包]]></act_name><remark><![CDATA[新年红包]]></remark><scene_id><![CDATA[PRODUCT_2]]></scene_id><consume_mch_id><![CDATA[10000097]]></consume_mch_id><nonce_str><![CDATA[50780e0cca98c8c8e814883e5caa672e]]></nonce_str><risk_info>posttime%3d123123412%26clientversion%3d234134%26mobile%3d122344545%26deviceid%3dIOS</risk_info></xml>

接口需要调用商户平台的证书,证书需要去商户平台下载:

java,微信公众号,支付开发,java微信公众号开发,java微信现金红包,微信公众号现金红包

然后在接口中使用证书,首先我们新建一个WeixinSSL 类

@Componentpublic class WeiXinSSL {  /**   * 证书类型   */  @Value("${werchant.storekey}")  private String storekey;  /**   * 文件路径   */  @Value("${werchant.ssLfile}")  private String ssLfile;  /**   * 商户号   */  @Value("${werchant.merchantNumber}")  private String merchantNumber;  public String getStorekey() {    return storekey;  }  public void setStorekey(String storekey) {    this.storekey = storekey;  }  public String getSsLfile() {    return ssLfile;  }  public void setSsLfile(String ssLfile) {    this.ssLfile = ssLfile;  }  public String getMerchantNumber() {    return merchantNumber;  }  public void setMerchantNumber(String merchantNumber) {    this.merchantNumber = merchantNumber;  }  }

封装HttpClientSSL 类实现 https 请求加证书:

 

@Componentpublic class HttpClientSSL {  @Autowired  private WeiXinSSL weiXinSSL;  // 请求超时时间(毫秒) 5秒  public static RequestConfig requestConfig;  // 响应超时时间(毫秒) 60秒  public static int HTTP_RESPONSE_TIMEOUT = 60 * 1000;  // httpClient字符编码  public static String encoding = "UTF-8";  public static RequestConfig getRequestConfig() {    return RequestConfig.custom().setConnectTimeout(5 * 1000)        .setConnectionRequestTimeout(HTTP_RESPONSE_TIMEOUT).build();  }  public static void setRequestConfig(RequestConfig requestConfig) {    HttpClientSSL.requestConfig = requestConfig;  }  /**   * https请求伪造证书   * @return   */  public CloseableHttpClient defaultSSLClient() {    SSLContext sslContext = null;    try {      new SSLContextBuilder().loadTrustMaterial(null,new TrustStrategy(){        @Override        public boolean isTrusted(X509Certificate[] chain, String authType)            throws java.security.cert.CertificateException {          return false;        }      });    } catch (NoSuchAlgorithmException | KeyStoreException e) {      e.printStackTrace();    }    SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(sslContext);    return HttpClients.custom().setSSLSocketFactory(factory).build();  }  /**   * https请求加证书   * @return   */  public CloseableHttpClient defaultSSLClientFile() {    if (this.weiXinSSL == null){      return this.defaultSSLClient();    }    FileInputStream inputStream = null;    KeyStore keyStore = null;    try {      // ssl类型      keyStore = KeyStore.getInstance(weiXinSSL.getStorekey());      // ssl文件      inputStream = new FileInputStream(weiXinSSL.getSsLfile());      // 设置ssl密码      keyStore.load(inputStream,weiXinSSL.getMerchantNumber().toCharArray());    } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e1) {      e1.printStackTrace();    } finally {      try {        inputStream.close();      } catch (IOException e) {        e.printStackTrace();      }    }    SSLContext sslContext = null;    try {      sslContext = SSLContexts.custom().loadKeyMaterial(keyStore,weiXinSSL.getMerchantNumber().toCharArray()).build();    } catch (UnrecoverableKeyException | NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) {      e.printStackTrace();    }    SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(sslContext, new String[] { "TLSv1" }, null,        SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);    return HttpClients.custom().setSSLSocketFactory(factory).build();  }  /**   * 封装发送请求的方法   * @throws UnsupportedEncodingException   */  public String send(String url, String data, CloseableHttpClient closeableHttpClient)      throws UnsupportedEncodingException {    CloseableHttpClient client = closeableHttpClient;    HttpPost httpPost = new HttpPost(URLDecoder.decode(url, encoding));    httpPost.addHeader("Connection", "keep-alive");    httpPost.addHeader("Accept", "*/*");    httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");    httpPost.addHeader("Host", "api.mch.weixin.qq.com");    httpPost.addHeader("X-Requested-With", "XMLHttpRequest");    httpPost.addHeader("Cache-Control", "max-age=0");    httpPost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");    httpPost.setConfig(this.getRequestConfig());// 设置超时时间    CloseableHttpResponse response = null;    // 参数放入    StringEntity entity = new StringEntity(data, encoding);    entity.setContentEncoding(encoding);    entity.setContentType("application/xml");    httpPost.setEntity(entity);    try {      response = client.execute(httpPost);      if (response.getStatusLine().getStatusCode() == 200) {        HttpEntity httpEntity = (HttpEntity) response.getEntity();        if (response != null) {          return EntityUtils.toString(httpEntity,encoding);        }      }    } catch (IOException e) {      e.printStackTrace();    }    return null;  }}  

这样我们就封装了一个https请求加证书的实体类,接下来我们生成请求微信红包接口:
https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack 的参数签名:

/*** 红包参数实体类 * @throws UnsupportedEncodingException */@Componentpublic class SendRedPack implements Serializable{  /**   *    */  private static final long serialVersionUID = -1000489228099916099L;  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 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 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 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;  }}

接下来是发送红包的控制器:

/** * 领红包控制器 * @author zengliang */@Controller@RequestMapping(value="/redenveLopesReceive")public class RedEnvelopesReceiveController {  //微信唯一标识  @Value("${weixin.appid}")  private String appid;  //微信开发者密码标识  @Value("${weixin.appsecret}")  public String appsecret;  @Autowired  private SendRedPack sendredpack;  @Autowired  private HttpClientSSL httpclientssl;  /**   * 发送XML参数   * @author zengliang   */  @ResponseBody  @RequestMapping(value="/sendXml")  public String sendXml(String openid,Long redenveLopes_id      ,String mch_billno){    RedenveLopes redenve = redenveLopesService.findOne(redenveLopes_id);    XMLUtil xmlUtil= new XMLUtil();    sendredpack.setAct_name(redenve.getAct_name());    sendredpack.setNonce_str(xmlUtil.random());    sendredpack.setRe_openid(openid);    sendredpack.setClient_ip(redenve.getClient_ip());    sendredpack.setMch_billno(mch_billno);    sendredpack.setMch_id(redenve.getMch_id());    String xx = redenve.getRemark();    sendredpack.setRemark(StringUtils.isEmpty(xx) == false?xx:"空");    sendredpack.setSend_name(redenve.getSend_name());    sendredpack.setTotal_amount(redenve.getTotal_amount());    sendredpack.setTotal_num(redenve.getTotal_num());    sendredpack.setWishing(redenve.getWishing());    sendredpack.setWxappid(redenve.getWxappidxx());    //生成签名    String params = this.createSendRedPackOrderSign(sendredpack,redenve.getStore_key());    sendredpack.setSign(params);    xmlUtil.xstream().alias("xml",sendredpack.getClass());    //扩展xstream,使其支持CDATA块    String requestXml = xmlUtil.xstream().toXML(sendredpack);    String result;    try {      result = httpclientssl.send("https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack",requestXml,httpclientssl.defaultSSLClientFile());      System.out.println("成功返回值"+result);      return result;    } catch (UnsupportedEncodingException e) {      e.printStackTrace();    }    return null;  }/**   * 生成签名   * @param redPack   * @return   */  public String createSendRedPackOrderSign(SendRedPack redPack,String storekey){    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(storekey);    return DigestUtils.md5Hex(sign.toString()).toUpperCase();  }}

然后我们需要用一个解析XML的工具类实现解析微信返回的XML

 

/** * 解析XML工具类 * @author zengliang */@Componentpublic class XMLUtil {  /**   * 解析微信返回的XML   * @param xml   * @return   * @throws Exception   */  @SuppressWarnings("unchecked")  public Map<String, String> parseXml(String xml)throws Exception {    Map<String,String> map = new HashMap<String,String>();     Document doc = null;     try {       doc = DocumentHelper.parseText(xml); // 将字符串转为XML       Element rootElt = doc.getRootElement(); // 获取根节点       List<Element> list = rootElt.elements();//获取根节点下所有节点       for (Element element : list) { //遍历节点         map.put(element.getName(), element.getText()); //节点的name为map的key,text为map的value       }     } catch (DocumentException e) {       e.printStackTrace();     } catch (Exception e) {       e.printStackTrace();     }    return map;   }  /**   * 扩展xstream,使其支持CDATA块   */   private 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);            }          }          };      }   });   private XStream inclueUnderlineXstream = new XStream(new DomDriver(null,new XmlFriendlyNameCoder("_-", "_")));   public XStream getXstreamInclueUnderline() {     return inclueUnderlineXstream;   }   public XStream xstream() {     return xstream;   }   /**   * 生成随机数   * @return   */  public String random(){    String random = UUID.randomUUID().toString().replace("-", "");    return random;  }}

然后我们调用 sendXML 方法公众号就能向用户发送红包了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持VeVb武林网。


注:相关教程知识阅读请移步到JAVA教程频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表