最近有弄服务号的现金红包和企业付款,和微信支付 弄完之后发现其实这些基本都差不多.
所有我这里就把微信企业付款记录一样
首先 还是先看一下文档 https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2 点击打开链接
在文档中我们可以看到,企业付款需要调用的url和所有参数的说明,这里的话就需要自己去看去理解了。
如果要使用 现金红包和企业付款 要先去开通在产品中心里面 就要 点击进去开通就行了 ,顺便填写一下机器ip地址
之后我要提一下的是机器ip是外网ip,如果是在本地测试的就要注意一下 然后保持一致就行了
这里的话还有个最主要的证书需要下载,我们可以下载到D盘cert目录下 D:/cert 这个证书的下载 只要登陆微信商户平台 API安全 就可以了 看自己是什么语言就下载什么证书,这里文档有说明
一些微信的基本配置我都写在了 #weixin mp config
appID=xxxx
appsecret=xxxx
token=xxxx
#商户号
partnerId=xxx
#商户支付密钥
partnerKey=xxxx
#微信统一支付接口
payUrl=https://api.mch.weixin.qq.com/pay/unifiedorder
#支付结果通知的回调地址
payCallBack= http://域名/wechatPay/wechat_notify
queryOrderUrl=https://api.mch.weixin.qq.com/pay/orderquery
前面的准备工作都ok 之后就是写代码了
建一个微信需要的企业付款参数 transfers 类
public class Transfers {
private String mch_appid;// 公众账号
private String mchid;// 商户号
private String nonce_str;// 随机字符串
private String sign;// 签名
private String partner_trade_no;// 商户订单号
private String openid;// 用户openid
//校验用户姓名选项 NO_CHECK:不校验真实姓名
private String check_name;
private int amount;// 付款金额
private String desc;// 企业付款描述信息
private String spbill_create_ip;// 调用接口的机器Ip地址
public String getMch_appid() {
return mch_appid;
}
public void setMch_appid(String mch_appid) {
this.mch_appid = mch_appid;
}
public String getMchid() {
return mchid;
}
public void setMchid(String mchid) {
this.mchid = mchid;
}
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 getPartner_trade_no() {
return partner_trade_no;
}
public void setPartner_trade_no(String partner_trade_no) {
this.partner_trade_no = partner_trade_no;
}
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public String getCheck_name() {
return check_name;
}
public void setCheck_name(String check_name) {
this.check_name = check_name;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getSpbill_create_ip() {
return spbill_create_ip;
}
public void setSpbill_create_ip(String spbill_create_ip) {
this.spbill_create_ip = spbill_create_ip;
}
}
之后就是给 这些参数赋值
@Autowired
private XMLUtil xmlUtil;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.security.KeyStore;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
import javax.net.ssl.SSLContext;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
上面是导入的包 下面就是给参数配值了
private void redPackets(Integer withdrawId, String openId) throws Exception {
int total=100;
int amount = (int) (total*100);
Transfers transfers=new Transfers();
String nonce = UUID.randomUUID().toString().substring(0, 30);
SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
String time = df.format(new Date());
Random ne=new Random();
int guid=ne.nextInt(9999-1000+1)+1000;
transfers.setMch_appid(APPID);// 自己的公众账号
transfers.setMchid(partnerId);//自己的 商户号
transfers.setNonce_str(nonce);// 随机字符串
transfers.setOpenid(openId);// 用户openId
transfers.setCheck_name("NO_CHECK");// 校验用户姓名选项
transfers.setAmount(amount);// 付款金额
transfers.setDesc("微信企业付款");// 企业付款描述信息
transfers.setSpbill_create_ip("120.236.82.202");// 调用接口的机器Ip地址
transfers.setPartner_trade_no(WxConfig.partnerId+time+guid);// 商户订单号
String sign = createSendRedPackOrderSign(transfers);
transfers.setSign(sign);// 签名
xmlUtil.xstream().alias("xml", transfers.getClass());
String xml = xmlUtil.xstream().toXML(transfers);
String sendEedPackUrl="https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";
String response = ssl(sendEedPackUrl,xml);
Map<String, String> responseMap = xmlUtil.parseXml(response);
String return_msg = responseMap.get("return_msg");
System.out.println(return_msg);
}
这里就是根据上面的内容生成签名 sign 这里文档有说明 这里要注意的是去,签名要按照 ASCII码从小到大排序(字典序)
public String createSendRedPackOrderSign(Transfers transfers){
StringBuffer sign = new StringBuffer();
sign.append("mch_appid=").append(transfers.getMch_appid());
sign.append("&mchid=").append(transfers.getMchid());
sign.append("&nonce_str=").append(transfers.getNonce_str());
sign.append("&partner_trade_no=").append(transfers.getPartner_trade_no());
sign.append("&openid=").append(transfers.getOpenid());
sign.append("&check_name=").append(transfers.getCheck_name());
sign.append("&amount=").append(transfers.getAmount());
sign.append("&desc=").append(transfers.getDesc());
sign.append("&spbill_create_ip=").append(transfers.getSpbill_create_ip());
sign.append("&key=").append(WxConfig.partnerKey);
return DigestUtils.md5Hex(sign.toString()).toUpperCase();
}
然后就是xmlutil类了 我是在网上大神博客找的
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.stereotype.Component;
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.DomDriver;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder;
import com.thoughtworks.xstream.io.xml.XppDriver;
/**
* XML工具包
*
* XMLUtil
*
* @author zdl
* @version 1.0.0
*
*/
@Component
public class XMLUtil {
/**
* 解析字符串(XML)
*
* @param request
* @return
* @throws Exception
*/
@SuppressWarnings("unchecked")
public Map<String, String> parseXml(String msg) throws Exception {
// 将解析结果存储在HashMap中
Map<String, String> map = new HashMap<String, String>();
// 从request中取得输入流
InputStream inputStream = new ByteArrayInputStream(
msg.getBytes("UTF-8"));
// 读取输入流
SAXReader reader = new SAXReader();
Document document = reader.read(inputStream);
// 得到xml根元素
Element root = document.getRootElement();
// 得到根元素的所有子节点
List<Element> elementList = root.elements();
// 遍历所有子节点
for (Element e : elementList)
map.put(e.getName(), e.getText());
// 释放资源
inputStream.close();
inputStream = null;
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;
}
}
private String ssl(String url,String data){
StringBuffer message = new StringBuffer();
try {
KeyStore keyStore = KeyStore.getInstance("PKCS12");
FileInputStream instream = new FileInputStream(new File("D:/cert/apiclient_cert.p12"));
keyStore.load(instream, WxConfig.partnerId.toCharArray());
// Trust own CA and all self-signed certs
SSLContext sslcontext = SSLContexts.custom()
.loadKeyMaterial(keyStore, WxConfig.partnerId.toCharArray())
.build();
// Allow TLSv1 protocol only
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();
}
如果还有什么不懂的可以去看 这位大师的博客,我也是根据他的来写的 ,顺便说一下是java微信红包的!
http://blog.csdn.net/jrainbow/article/details/50266391