java微信公众号发送现金红包源码,包括查询红包记录(子商户模式)

概述

本demo,实现通过调用微信api接口发送公众号现金红包以及查询红包状态功能,应用场景是服务商替子商户发送现金红包(子商户模式)。普通商户模式也能使用,接口一致,参数调整一下就可以。所有功能代码都已封装好,替换完参数就可以直接运行。代码下载: http://www.demodashi.com/demo/15390.html

一、前言

微信红包分为普通红包和裂变红包,发放方式分为普通商户模式以及子商户模式,下面代码是以子商户模式发放普通红包写的。具体怎么选择看业务场景,代码原理是一样的,只是接口不一致,传参不同。

微信红包默认为1到200元,场景下为1-499元(调接口时参数必须传场景id),这些只需要平台设置,不需要申请。

其最小额度为0.3元,最大额度为4999元,这些需要向微信申请。(不一定能申请下来)

读代码之前最好对服务商,普通商户,特约商户等有个基本概念。最好先研究一遍文档,微信的文档写的还是很详细的。实在不明白可以打客服电话。

 

二、先看效果图

      1558080844676079745.jpg            1558081042149001839.jpg

三、准备工作

 

开始前一定要准备好测试条件:

1、已有服务商账号,必须已经开通了服务商现金红包功能。产品中心--特约商户授权产品--运营工具--服务商现金红包

image.png

2、已申请特约商户,必须已经开通了现金红包功能。产品中心--我的产品--运营工具--现金红包

image.png

3、服务商和特约商户完成绑定授权

详细流程见开发文档: https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon_sl.php?chapter=13_3&index=2

4、获取重要参数

包括:服务商id、服务商对应公众号appid、api密钥(服务商平台--账户中心--api安全--api密钥)、

api证书、特约商户号(子商户号)、子商户绑定的公众号appid、用户openid(子商户公众号下的)

1558077560606087518.png

1558077671674044105.png

关于准备工作的注意事项:

1、特约商户的申请以及授权绑定都需要审核,大概一到三天。

2、特约商户开通现金红包功能是有要求的,T+7账户能立即开通,其余的需要有90天的入驻以及30天的连续流水交易才能开通

3、特约商户绑定公众号时,两者主体必须一致,如果公众号绑定过其他商户,则特约商户的费率必须和这个商户一致

4、用户必须关注特约商户绑定的公众号,红包也是从这个公众号发出,钱是从特约商户账户出,红包发送记录是在服务商后台查

四、程序实现

项目代码截图:

1558078599730006502.png

以下摘部分重要代码说明过程:

1、服务商相关配置 application.yml

1

2

3

4

5

6

7

8

9

10

11

wx:

  # 服务商id

  mch_id: "153xxx9191"

  # 服务商appid(公众号id)

  wxappid: "wx3bcxxxxxx9d4163b"

  #调用接口的机器IP地址(真实ip  百度搜出来的ip)

  client_ip: "61.xxx.xxx.178"

  # api秘钥 微信商户平台-->账户设置-->API安全-->密钥设置

api-key: "zxcvbnmasdfghjklqwertyuiop123456"

# API证书

certFile: "wx_153xxx9191_cert.p12"

2、服务商对应的配置类

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

package com.sylujia.wxpay;

 

import lombok.Data;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.stereotype.Component;

 

/**

 * @Author jia

 * @Date 2019/5/17 12:20

 * @Description

 */

@Data

@Component

public class WxConfig {

 

    /**

     * 服务商id

     */

    @Value("${wx.mch_id}")

    private String mchId;

 

    /**

     * 服务商appid

     */

    @Value("${wx.wxappid}")

    private String wxappid;

 

    /**

     * 调用接口的机器IP地址

     */

    @Value("${wx.client_ip}")

    private String clientIp;

 

    /**

     * api秘钥 微信商户平台-->账户设置-->API安全-->密钥设置

     */

    @Value("${wx.api-key}")

    private String apiKey;

 

    /**

     * API证书

     */

    @Value("${wx.certFile}")

    private String certFile;

 

}

3、调用测试类

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

package com.sylujia.wxpay;

 

import com.sylujia.wxpay.entity.WxPayReqBO;

import com.sylujia.wxpay.service.WxPayService;

import lombok.extern.slf4j.Slf4j;

import org.junit.Test;

import org.junit.runner.RunWith;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.test.context.SpringBootTest;

import org.springframework.test.context.junit4.SpringRunner;

 

@Slf4j

@RunWith(SpringRunner.class)

@SpringBootTest

public class WxpayRedpackageApplicationTests {

 

    @Autowired

    private WxPayService wxPayService;

 

    @Test

    public void sendRedPackTest() {

 

        WxPayReqBO wxPayReqBO = new WxPayReqBO();

 

        //微信公众号下的用户唯一标示(msgAppid公众号下对应的用户openid)

        wxPayReqBO.setReOpenid("osuL9szZugvO1vkwJGKNYGb9cNT8");

        //子商户号(特约商户)

        wxPayReqBO.setSubMchId("153xxx651");

        //子商户绑定的公众号APPID

        wxPayReqBO.setMsgAppid("wx3d9xxxxxx5741bf4");

        //发送方名字

        wxPayReqBO.setSendName("返现测试");

        //红包金额 单位分

        wxPayReqBO.setTotalAmount(100);

        //红包总数

        wxPayReqBO.setTotalNum(1);

        //红包祝福语

        wxPayReqBO.setWishing("红包祝福语");

        //活动名称

        wxPayReqBO.setActName("活动");

        //备注

        wxPayReqBO.setRemark("红包备注");

        //使用原订单号重发

//        wxPayReqBO.setMchBillNo("1557727546317cfysmet0xptt9sp");

 

        String res = wxPayService.sendRedPack(wxPayReqBO);

        log.info("红包发送返回:{}",res);

    }

 

 

 

    @Test

    public void queryRedPackInfoTest(){

        String resXml = wxPayService.queryRedPackInfo("1558073129334pqbc9nki4tvr9jl");

        log.info("查询红包记录返回:{}", resXml);

    }

 

 

 

}

4、服务实现类,包含发送红包服务、以及红包状态查询服务

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

package com.sylujia.wxpay.service.impl;

 

import com.sylujia.wxpay.WxConfig;

import com.sylujia.wxpay.entity.RedPackQueryEntity;

import com.sylujia.wxpay.entity.RedPackSendEntity;

import com.sylujia.wxpay.entity.WxPayReqBO;

import com.sylujia.wxpay.service.WxPayService;

import com.sylujia.wxpay.utils.HttpClientSSL;

import com.sylujia.wxpay.utils.WeiXinUtil;

import com.sylujia.wxpay.utils.XmlUtils;

import lombok.extern.slf4j.Slf4j;

import org.apache.commons.lang3.StringUtils;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

 

/**

 * @author jia

 * @createTime 2019-05-09

 * @description 微信支付服务实现

 */

@Slf4j

@Service

public class WxPayServiceImpl implements WxPayService {

 

    @Autowired

    private HttpClientSSL httpClientSSL;

 

    @Autowired

    private WxConfig wxConfig;

 

    /**

     * 红包发送url

     */

    private final String SEND_URL = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack";

    /**

     * 查询红包记录url

     */

    private final String QUERY_URL = "https://api.mch.weixin.qq.com/mmpaymkttransfers/gethbinfo";

 

    @Override

    public String sendRedPack(WxPayReqBO wxPayReqBO) {

        log.info("红包发送实体,wxPayReqBO:{}", wxPayReqBO);

        try {

            /** 封装发送红包实体**/

            RedPackSendEntity redPackageEntity = transferRedPackSendEntity(wxPayReqBO);

 

            /**获取xml格式请求体**/

            XmlUtils.xstream().autodetectAnnotations(true);

            XmlUtils.xstream().alias("xml", redPackageEntity.getClass());

            String xmlData = XmlUtils.xstream().toXML(redPackageEntity);

            /**http请求加证书 发送请求**/

            String resXml = httpClientSSL.sendWX(SEND_URL, xmlData, httpClientSSL.defaultSSLClientFile());

            log.info("sendRedPack() 红包发送结果:{}", resXml);

            return resXml;

        catch (Exception e) {

            log.error("sendRedPack() 红包发送异常", e);

            throw new RuntimeException("红包发送异常");

        }

    }

 

    /**

     * 获取红包实体

     * @param wxPayReqBO

     * @return

     */

    private RedPackSendEntity transferRedPackSendEntity(WxPayReqBO wxPayReqBO){

        //封装发送红包实体

        RedPackSendEntity redPackEntity = new RedPackSendEntity();

        redPackEntity.setReOpenid(wxPayReqBO.getReOpenid());

        redPackEntity.setSubMchId(wxPayReqBO.getSubMchId());

        redPackEntity.setMsgAppid(wxPayReqBO.getMsgAppid());

        redPackEntity.setSendName(wxPayReqBO.getSendName());

        redPackEntity.setTotalAmount(wxPayReqBO.getTotalAmount());

        redPackEntity.setTotalNum(wxPayReqBO.getTotalNum());

        redPackEntity.setWishing(wxPayReqBO.getWishing());

        redPackEntity.setActName(wxPayReqBO.getActName());

        redPackEntity.setRemark(wxPayReqBO.getRemark());

 

        redPackEntity.setMchId(wxConfig.getMchId());

        redPackEntity.setWxAppid(wxConfig.getWxappid());

        redPackEntity.setClientIp(wxConfig.getClientIp());

 

        String nonceStr = WeiXinUtil.getUUID32Str();

        redPackEntity.setNonceStr(nonceStr);

 

        //不为空即使用原订单号重发

        String mchBillNo = wxPayReqBO.getMchBillNo();

        if(StringUtils.isBlank(mchBillNo)){

            mchBillNo = WeiXinUtil.getMchBillNo();

        }

        redPackEntity.setMchBillNo(mchBillNo);

        //签名

        String sign = WeiXinUtil.createRedPackOrderSign(redPackEntity , wxConfig.getApiKey());

        redPackEntity.setSign(sign);

        return redPackEntity;

    }

 

 

    @Override

    public String queryRedPackInfo(String mchBillNo) {

        log.info("查询红包发送记录 入参 mchBillNo:{}", mchBillNo);

 

        /**封装查询红包记录的实体**/

        RedPackQueryEntity redInfoEntity = new RedPackQueryEntity();

        redInfoEntity.setMchBillNo(mchBillNo);

        redInfoEntity.setMchId(wxConfig.getMchId());

        redInfoEntity.setAppid(wxConfig.getWxappid());

        redInfoEntity.setBillType("MCHT");

        String nonceStr = WeiXinUtil.getUUID32Str();

        redInfoEntity.setNonceStr(nonceStr);

        //签名

        String sign = WeiXinUtil.createQueryRedPackInfoSign(redInfoEntity , wxConfig.getApiKey());

        redInfoEntity.setSign(sign);

        //转换为xml格式请求体

        XmlUtils.xstream().autodetectAnnotations(true);

        XmlUtils.xstream().alias("xml", redInfoEntity.getClass());

        String xmlData = XmlUtils.xstream().toXML(redInfoEntity);

 

        /**http请求加证书 发送请求**/

        String resXml = httpClientSSL.sendWX(QUERY_URL, xmlData, httpClientSSL.defaultSSLClientFile());

 

        return resXml;

 

    }

 

}

上面代码涉及到几个工具类:

HttpClientSSL.java  http请求加微信证书,封装请求用的

WeiXinUtil.java     微信通用工具方法,生成订单号,拼接参数,生成签名等

XmlUtils.java        重写Xstream添加支持<![CDATA[]]>,封装接口的请求体使用

HttpClientSSL.java如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

package com.sylujia.wxpay.utils;

 

import lombok.extern.slf4j.Slf4j;

import org.apache.commons.codec.Charsets;

import org.apache.http.HttpEntity;

import org.apache.http.HttpStatus;

import org.apache.http.client.config.RequestConfig;

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.springframework.beans.factory.annotation.Value;

import org.springframework.stereotype.Component;

 

import javax.net.ssl.SSLContext;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.security.*;

import java.security.cert.CertificateException;

 

/**

 * @Author jia

 * @Date 2019/5/7 17:12

 * @Description   http请求带证书

 */

@Slf4j

@Component

public class HttpClientSSL {

 

    /**

     * 证书名称

     */

    @Value("${wx.certFile}")

    private String certFile;

    /**

     * 服务商id

     */

    @Value("${wx.mch_id}")

    private String mchId;

 

    /**

     * 请求超时时间(毫秒) 5秒

     * 响应超时时间(毫秒) 15秒

     */

    public static RequestConfig getRequestConfig() {

        return RequestConfig.custom().setConnectTimeout(5 1000).setConnectionRequestTimeout(15 1000).build();

    }

 

    /**

     * https请求加证书

     * @return

     */

    public CloseableHttpClient defaultSSLClientFile() {

        InputStream inputStream = null;

        KeyStore keyStore;

        try {

            // ssl证书类型

            keyStore = KeyStore.getInstance("PKCS12");

            // ssl文件

            inputStream = this.getClass().getClassLoader().getResourceAsStream(certFile);

            // 设置ssl密码

            keyStore.load(inputStream, mchId.toCharArray());

        catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e1) {

           log.error("https请求加证书,获取KeyStore错误", e1);

           throw new RuntimeException("https请求加证书,获取KeyStore错误  HttpClientSSL.defaultSSLClientFile()");

        finally {

            try {

                inputStream.close();

            catch (IOException e) {

                log.error("https请求加证书,io错误", e);

                throw new RuntimeException("https请求加证书,io错误  HttpClientSSL.defaultSSLClientFile()");

            }

        }

        SSLContext sslContext;

        try {

            //创建SSL

            sslContext = SSLContexts.custom().loadKeyMaterial(keyStore,mchId.toCharArray()).build();

        catch (UnrecoverableKeyException | NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) {

            log.error("https请求加证书,创建SSL错误", e);

            throw new RuntimeException("https请求加证书,创建SSL错误 HttpClientSSL.defaultSSLClientFile()");

        }

 

        SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(

                sslContext,

                new String[]{"TLSv1"},

                null,

                SSLConnectionSocketFactory.getDefaultHostnameVerifier());

 

        return HttpClients.custom().setSSLSocketFactory(factory).build();

    }

 

    /**

     * 封装发送请求的方法

     * @param ulr

     * @param xmlData

     * @param closeableHttpClient

     * @return

     */

    public String sendWX(String ulr, String xmlData, CloseableHttpClient closeableHttpClient) {

 

        StringBuffer message = new StringBuffer();

 

        HttpPost httpPost = new HttpPost(ulr);

        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(getRequestConfig());

 

        // 参数放入

        StringEntity entity = new StringEntity(xmlData, Charsets.UTF_8);

        entity.setContentType("application/xml");

        httpPost.setEntity(entity);

 

        try {

            //http请求加证书

            CloseableHttpClient httpClient = closeableHttpClient;

            CloseableHttpResponse response = httpClient.execute(httpPost);

 

            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {

                HttpEntity httpEntity = response.getEntity();

                if (httpEntity != null) {

                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpEntity.getContent(), Charsets.UTF_8));

                    String text;

                    while ((text = bufferedReader.readLine()) != null) {

                        message.append(text);

                    }

                }

            }

            if (message.length() == 0){

                throw new RuntimeException("network response error at HttpClientSSL sendWX()");

            }

        catch (Exception e) {

            log.error("封装发送带证书的http请求错误", e);

            throw new RuntimeException("封装发送带证书的http请求错误 HttpClientSSL sendWX()");

        }

        return message.toString();

 

    }

 

}

WeiXinUtil.java如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

package com.sylujia.wxpay.utils;

 

import com.sylujia.wxpay.entity.RedPackQueryEntity;

import com.sylujia.wxpay.entity.RedPackSendEntity;

import org.apache.commons.codec.digest.DigestUtils;

import org.apache.commons.lang3.RandomStringUtils;

import org.apache.commons.lang3.StringUtils;

 

import java.io.UnsupportedEncodingException;

import java.net.URLEncoder;

import java.nio.charset.StandardCharsets;

import java.time.LocalDateTime;

import java.time.ZoneOffset;

import java.util.*;

 

/**

 * @Author jia

 * @Date 2019/5/7 15:43

 * @Description 微信通用工具方法

 */

public class WeiXinUtil {

 

    /**

     * 获取32为的随机的字符串

     * @return 去除'-'的32为字符串

     */

    public static String getUUID32Str() {

        return UUID.randomUUID().toString().replace("-""");

    }

 

    /**

     * 生成商户订单号

     * @return String 商户订单号

     */

    public static String getMchBillNo() {

        String randomStr = RandomStringUtils.random(15"abcdefghijklmnopqrstuvwxyz1234567890");

        String mchBillno = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli() + randomStr;

        return mchBillno;

    }

 

 

    /**

     * 创建发红包签名

     *

     * @param redPack 红包实体

     * @param apiKey  api密钥

     * @return String MD5加密后的值

     */

    public static String createRedPackOrderSign(RedPackSendEntity redPack, String apiKey) {

 

        Map<String, String> params = new HashMap<>();

        params.put("act_name", redPack.getActName());

        params.put("client_ip", redPack.getClientIp());

        params.put("mch_billno", redPack.getMchBillNo());

        params.put("mch_id", redPack.getMchId());

        params.put("msgappid", redPack.getMsgAppid());

        params.put("nonce_str", redPack.getNonceStr());

        params.put("re_openid", redPack.getReOpenid());

        params.put("remark", redPack.getRemark());

        params.put("send_name", redPack.getSendName());

        params.put("total_amount", String.valueOf(redPack.getTotalAmount()));

        params.put("total_num", String.valueOf(redPack.getTotalNum()));

        params.put("wishing", redPack.getWishing());

        params.put("wxappid", redPack.getWxAppid());

        params.put("sub_mch_id", redPack.getSubMchId());

        if(StringUtils.isNotBlank(redPack.getSceneId())){

            params.put("scene_id", redPack.getSceneId());

        }

        try {

            String url = makeUrlFormMap(params, falsefalse);

            url += "&key=" + apiKey;

            return DigestUtils.md5Hex(url).toUpperCase();

        catch (UnsupportedEncodingException e) {

            throw new RuntimeException(e);

        }

    }

 

 

    /**

     * 创建查询红包记录签名

     *

     * @param redInfo 查询红包记录实体

     * @param apiKey  api密钥

     * @return String MD5加密后的值

     */

    public static String createQueryRedPackInfoSign(RedPackQueryEntity redInfo, String apiKey) {

 

        Map<String, String> params = new HashMap<>();

        params.put("nonce_str", redInfo.getNonceStr());

        params.put("mch_billno", redInfo.getMchBillNo());

        params.put("mch_id", redInfo.getMchId());

        params.put("appid", redInfo.getAppid());

        params.put("bill_type", redInfo.getBillType());

        params.put("mch_billno", redInfo.getMchBillNo());

 

        try {

            String url = makeUrlFormMap(params, falsefalse);

            url += "&key=" + apiKey;

            return DigestUtils.md5Hex(url).toUpperCase();

        catch (UnsupportedEncodingException e) {

            throw new RuntimeException(e);

        }

    }

 

 

 

    /**

     * 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序),并且生成url参数串

     *

     * @param paraMap   要排序的Map对象

     * @param urlEncode 是否需要URLENCODE

     * @return keyToLower 是否需要将Key转换为全小写  true:key转化成小写,false:不转化

     * @throws UnsupportedEncodingException 未知字符集异常

     */

    public static String makeUrlFormMap(Map<String, String> paraMap, boolean urlEncode, boolean keyToLower) throws UnsupportedEncodingException {

        StringBuffer stringBuffer = new StringBuffer();

        List<Map.Entry<String, String>> entryList = new ArrayList<>(paraMap.entrySet());

        // 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序)

        Collections.sort(entryList, Comparator.comparing(Map.Entry::getKey));

        //构造URL

        for (Map.Entry<String, String> entry: entryList) {

            if (!StringUtils.isBlank(entry.getKey())) {

                String key = entry.getKey();

                String val = entry.getValue();

                if (urlEncode) {

                    val = URLEncoder.encode(val, StandardCharsets.UTF_8.name());

                }

                if (keyToLower) {

                    stringBuffer.append(key.toLowerCase()).append("=").append(val);

                else {

                    stringBuffer.append(key).append("=").append(val);

                }

                stringBuffer.append("&");

            }

        }

        String url = stringBuffer.toString();

        if (!url.isEmpty()) {

            url = url.substring(0, url.length() - 1);

        }

        return url;

    }

 

}

五、结束语

上面只是一些简单的逻辑实现,工具类不仅适用于发红包以及查红包,其他微信api也适用。

这里只是发红包以及查红包的接口实现,具体业务情景下,这些记录都是要入库的,而且对于红包的状态要考虑清楚,例如红包是否发送成功,用户是否领取成功(24小时没领取会退回),对于发送失败的订单是否要使用原订单号重发(防止资金重复发放)等。

代码下载: http://www.demodashi.com/demo/15390.html

Java微信公众号现金红包是一种通过在Java代码中调用微信支付接口实现的支付功能,用户可以使用现金红包来给其他用户发送一定金额的红包。以下是具体实现步骤: 首先,我们需要在微信公众平台上注册一个公众号,并进行相关设置和认证。然后,通过微信支付开发文档了解相关的API接口和参数,获取到自己的AppID、商户号和商户密钥等信息。 接下来,在Java项目中引入微信支付的SDK,可以使用第三方开源的SDK如weixin-java-pay等,或者通过HTTP请求自行实现。 然后,编写Java代码调用微信支付接口实现现金红包的功能。首先需要构建请求参数,包括发送红包的接口URL、请求方式(一般为POST)、AppID、商户号、商户密钥、随机字符串、签名等信息。可以使用Java中的HttpURLConnection类发送HTTP请求,并添加请求头信息和请求体参数。其中,签名的生成需要根据微信支付的签名规则进行加密计算,确保数据的安全性。 最后,接收到微信支付接口返回的结果后,可以对返回的数据进行解析和处理,判断红包发送状态是否成功。根据业务需求,可以将红包发送结果进行持久化存储,以备后续查询记录使用。 需要注意的是,微信支付红包功能需要满足一定的条件和规则,例如红包的最低金额、发送频率等,开发者需要仔细阅读微信支付文档,并根据实际需求进行相应的调整。 总的来说,通过Java编写代码调用微信支付接口实现现金红包功能需要按照微信支付的接口规范进行开发和调试,确保支付接口的安全性和稳定性,同时可以根据具体业务需求进行功能的扩展和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值