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

网友投稿 278 2023-02-08


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

请求数据示例:

<![CDATA[E1EE61A91C8E90F299DE6AE075D60A2D]]>

<![CDATA[0010010404201411170000046545]]>

<![CDATA[888]]>

<![CDATA[wxcbda96de0b165486]]>

<![CDATA[send_name]]>

<![CDATA[onqOjjmM1tad-3ROpncN-yUfa6uI]]>

<![CDATA[200]]>

<![CDATA[1]]>

<![CDATA[恭喜发财]]>

<![CDATA[127.0.0.1]]>

<![CDATA[新年红包]]>

<![CDATA[新年红包]]>

<![CDATA[PRODUCT_2]]>

<![CDATA[10000097]]>

<![CDATA[50780e0cca98c8c8e814883e5caa672e]]>

posttime%3d123123412%26clientversion%3d234134%26mobile%3d122344545%26deviceid%3dIOS

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

然后在接口中使用证书,首先我们新建一个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 类实现 https 请求加证书:

@Component

public class HttpClientSSL {

@Autowired

private WeiXinSSL weiXinSSL;

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

public static RequestConfig requestConfig;http://

// 响应超时时间(毫秒) 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 | http://KeyManagementException e) {

e.printStackTrace();

}

SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(sslContext, new String[] { "TLSv1" }, null,

SSLConnectionSocketFactory.BROWSER_COMPhttp://ATIBLE_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

*/

@Component

public 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

*/

@Component

public class XMLUtil {

/**

* 解析微信返回的XML

* @param xml

* @return

* @throws Exception

*/

@SuppressWarnings("unchecked")

public Map parseXml(String xml)throws Exception {

Map map = new HashMap();

Document doc = null;

try {

doc = DocumentHelper.parseText(xml); // 将字符串转为XML

Element rootElt = doc.getRootElement(); // 获取根节点

List 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 getXstreamInhttp://clueUnderline() {

return inclueUnderlineXstream;

}

public XStream xstream() {

return xstream;

}

/**

* 生成随机数

* @return

*/

public String random(){

String random = UUID.randomUUID().toString().replace("-", "");

return random;

}

}


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Jedis操作Redis数据库的方法
下一篇:redux中间件之redux
相关文章

 发表评论

暂时没有评论,来抢沙发吧~