当你需要进行微信支付的时候,你需要将自己appid,mchid,key以及数字证书给读取进来,那么就需要一个工具类来加载你自己的这些信息。
我写了一个工具类,工具类用到的其他类均为微信官方的SDK,大家可以自行在下载。
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
/**
* @Author:LION
* @Date
* @Version 1.0
**/
@Component
@Slf4j
public class MyConfig extends WXPayConfig {
@Value("${wxpay.appid}")
private String appid;
@Value("${wxpay.mchid}")
private String mchid;
@Value("${wxpay.key}")
private String key;
/**
* 加载证书 这里证书需要到微信商户平台进行下载
*/
private byte[] certData;
public MyConfig() throws Exception {
InputStream certStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("apiclient_cert.p12");
this.certData = IOUtils.toByteArray(certStream);
certStream.close();
}
@Override
String getAppID() {
return this.appid;
}
@Override
String getMchID() {
return this.mchid;
}
@Override
String getKey() {
return this.key;
}
void setKey(String key){this.key = key;}
@Override
InputStream getCertStream() {
return new ByteArrayInputStream(this.certData);
}
@Override
public IWXPayDomain getWXPayDomain() { // 这个方法需要这样实现, 否则无法正常初始化WXPay
IWXPayDomain iwxPayDomain = new IWXPayDomain() {
@Override
public void report(String domain, long elapsedTimeMillis, Exception ex) {
}
@Override
public DomainInfo getDomain(WXPayConfig config) {
return new DomainInfo(WXPayConstants.DOMAIN_API, true);
}
};
return iwxPayDomain;
}
/**
* 获取沙箱密钥
* @return
*/
public String getSandboxSignKey() {
try {
WXPay wxPay = new WXPay(this);
Map<String, String> params = new HashMap<String, String>();
params.put("mch_id", this.getMchID());
params.put("nonce_str", WXPayUtil.generateNonceStr());
params.put("sign", WXPayUtil.generateSignature(params, this.getKey()));
String strXML = wxPay.requestWithoutCert("https://api.mch.weixin.qq.com/sandboxnew/pay/getsignkey",
params, this.getHttpConnectTimeoutMs(), this.getHttpReadTimeoutMs());
Map<String, String> result = WXPayUtil.xmlToMap(strXML);
log.info("retrieveSandboxSignKey:" + result);
if ("SUCCESS".equals(result.get("return_code"))) {
return result.get("sandbox_signkey");
}
return null;
} catch (Exception e) {
log.error("获取sandbox_signkey异常" + e.getMessage());
return null;
}
}
}
把上面写的MyConfig加载到WXPay类中(微信官方提供了)
@Component
@Slf4j
public class WxConfig {
@Autowired
private MyConfig config;
@Bean
public WXPay getWXPay() {
WXPay wxpay = null;
try {
wxpay = new WXPay(config);
} catch (Exception e) {
log.info("获取wxpay失败");
e.printStackTrace();
}
return wxpay;
}
}
这边儿在写一个付款码支付的程序供大家参考(其他支付以及订单查询、退款等与之类似)
@Autowired
private WXPay wxPay;
public Map<String, String> pay(PayParam payParam) {
Map<String, String> data = new HashMap(8);
//公众账号ID (微信分配的公众账号ID(企业号corpid即为此appId))
data.put("appid", appid);
//商户号 (微信支付分配的商户号)
data.put("mch_id", mchid);
//终端设备号(商户自定义,如门店编号),非必传
String deviceInfo = payParam.getDeviceInfo();
if (StringUtils.isNotBlank(deviceInfo)){
data.put("device_info", deviceInfo);
}
//随机字符串,不长于32位
data.put("nonce_str", RandomStringUtils.randomAlphanumeric(32));
//商品描述 (商品简单描述,该字段须严格按照规范传递) 店名-销售商品类目 例 小张南山店-超市
data.put("body", payParam.getBody());
//商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*且在同一个商户号下唯一
data.put("out_trade_no", payParam.getOutTradeNo());
//订单总金额,单位为分,只能为整数
data.put("total_fee", payParam.getTotalFee());
//付款码 (扫码支付付款码,设备读取用户微信中的条码或者二维码信息(注:用户付款码条形码规则:18位纯数字,以10、11、12、13、14、15开头))
data.put("auth_code", payParam.getAutoCode());
try {
//终端IP (支持IPV4和IPV6两种格式的IP地址。调用微信支付API的机器IP)
data.put("spbill_create_ip", InetAddress.getLocalHost().getHostAddress());
} catch (UnknownHostException e) {
log.error("终端IP获取失败",e);
Assert.isTrue(false,"终端IP获取失败");
}
//非必填参数 订单优惠标记,代金券或立减优惠功能的参数
if(StringUtils.isNotEmpty(payParam.getGoodsTag())){
data.put("goods_tag", payParam.getGoodsTag());
}
try {
data.put("sign", WXPayUtil.generateSignature(data, key));
} catch (Exception e) {
log.error("微信签名失败",e);
Assert.isTrue(false,e.getMessage());
}
try {
Map<String, String> responseMap = wxPay.microPay(data);
log.info("微信支付返回 : {}", JSON.toJSONString(responseMap));
//判断是否成功
String returnCode = responseMap.get("return_code");
if (WXEnums.WXReturnCode.SUCCESS.getCode().equals(returnCode)) {
return responseMap;
} else {
Assert.isTrue(false,"与微信通讯失败");
}
} catch (Exception e) {
log.error("调用支付失败",e);
Assert.isTrue(false,e.getMessage());
}
return null;
}