溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

java微信公眾號支付開發(fā)之如何實(shí)現(xiàn)現(xiàn)金紅包

發(fā)布時間:2021-09-09 10:41:55 來源:億速云 閱讀:171 作者:小新 欄目:編程語言

這篇文章主要為大家展示了“java微信公眾號支付開發(fā)之如何實(shí)現(xiàn)現(xiàn)金紅包”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“java微信公眾號支付開發(fā)之如何實(shí)現(xiàn)現(xiàn)金紅包”這篇文章吧。

我們先來看看公眾號發(fā)放現(xiàn)金紅包的效果:

java微信公眾號支付開發(fā)之如何實(shí)現(xiàn)現(xiàn)金紅包

需要調(diào)用商戶平臺的接口,接口發(fā)放規(guī)則如下:

1.發(fā)送頻率限制——默認(rèn)1800/min
2.發(fā)送個數(shù)上限——按照默認(rèn)1800/min算
3.金額上限——根據(jù)傳入場景id不同默認(rèn)上限不同,可以在商戶平臺產(chǎn)品設(shè)置進(jìn)行設(shè)置和申請,最大不大于4999元/個
4.其他的“量”上的限制還有哪些?——用戶當(dāng)天的領(lǐng)取上限次數(shù),默認(rèn)是10
5.如果量上滿足不了我們的需求,如何提高各個上限?——金額上限和用戶當(dāng)天領(lǐng)取次數(shù)上限可以在商戶平臺進(jìn)行設(shè)置
注意-紅包金額大于200時,請求參數(shù)scene_id必傳,參數(shù)說明見下文。
注意2-根據(jù)監(jiān)管要求,新申請商戶號使用現(xiàn)金紅包需要滿足兩個條件:1、入駐時間超過90天 2、連續(xù)正常交易30天。

請求Url https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack
是否需要證書 是(證書及使用說明詳見商戶證書)
請求方式 POST

請求數(shù)據(jù)示例:

<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[恭喜發(fā)財]]></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>

接口需要調(diào)用商戶平臺的證書,證書需要去商戶平臺下載:

java微信公眾號支付開發(fā)之如何實(shí)現(xiàn)現(xiàn)金紅包

然后在接口中使用證書,首先我們新建一個WeixinSSL 類

@Component
public 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 類實(shí)現(xiàn) https 請求加證書:

@Component
public class HttpClientSSL {

  @Autowired
  private WeiXinSSL weiXinSSL;

  // 請求超時時間(毫秒) 5秒
  public static RequestConfig requestConfig;

  // 響應(yīng)超時時間(毫秒) 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());
      // 設(shè)置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();
  }

  /**
   * 封裝發(fā)送請求的方法
   * @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());// 設(shè)置超時時間
    CloseableHttpResponse response = null;

    // 參數(shù)放入
    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請求加證書的實(shí)體類,接下來我們生成請求微信紅包接口:
https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack 的參數(shù)簽名:

/**
* 紅包參數(shù)實(shí)體類
 * @throws UnsupportedEncodingException
 */
@Component
public class SendRedPack implements Serializable{

  /**
   * 
   */
  private static final long serialVersionUID = -1000489228099916099L;

  private String nonce_str;// 隨機(jī)字符串
  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;// 紅包發(fā)放總?cè)藬?shù)
  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;
  }
}

接下來是發(fā)送紅包的控制器:

/**
 * 領(lǐng)紅包控制器
 * @author zengliang
 */
@Controller
@RequestMapping(value="/redenveLopesReceive")
public class RedEnvelopesReceiveController {

  //微信唯一標(biāo)識
  @Value("${weixin.appid}")
  private String appid;

  //微信開發(fā)者密碼標(biāo)識
  @Value("${weixin.appsecret}")
  public String appsecret;

  @Autowired
  private SendRedPack sendredpack;

  @Autowired
  private HttpClientSSL httpclientssl;

  /**
   * 發(fā)送XML參數(shù)
   * @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());
    //擴(kuò)展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的工具類實(shí)現(xiàn)解析微信返回的XML

/**
 * 解析XML工具類
 * @author zengliang
 */
@Component
public 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); // 將字符串轉(zhuǎn)為XML 
      Element rootElt = doc.getRootElement(); // 獲取根節(jié)點(diǎn) 
      List<Element> list = rootElt.elements();//獲取根節(jié)點(diǎn)下所有節(jié)點(diǎn) 
      for (Element element : list) { //遍歷節(jié)點(diǎn) 
        map.put(element.getName(), element.getText()); //節(jié)點(diǎn)的name為map的key,text為map的value 
      } 
    } catch (DocumentException e) { 
      e.printStackTrace(); 
    } catch (Exception e) { 
      e.printStackTrace(); 
    }
    return map; 
  }

  /**
   * 擴(kuò)展xstream,使其支持CDATA塊
   */
   private XStream xstream = new XStream(new XppDriver(new NoNameCoder()) {
      @Override
      public HierarchicalStreamWriter createWriter(Writer out) {
          return new PrettyPrintWriter(out) {
          // 對所有xml節(jié)點(diǎn)的轉(zhuǎn)換都增加CDATA標(biāo)記
          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;
   }

   /**
   * 生成隨機(jī)數(shù)
   * @return
   */
  public String random(){
    String random = UUID.randomUUID().toString().replace("-", "");
    return random;
  }
}

然后我們調(diào)用 sendXML 方法公眾號就能向用戶發(fā)送紅包了。

以上是“java微信公眾號支付開發(fā)之如何實(shí)現(xiàn)現(xiàn)金紅包”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI