spring boot集成微信支付
微信(坑货没有测试版)
参数可以看微信开放平台提供的api接口文档 ---------话不多说、开始干
1. 在项目中加入jar包
<!--微信支付 SDk-->
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>0.0.3</version>
</dependency>
2.原理与支付宝差不多,配置微信支付环境 这里我的公共参数写在impl实现类中
//应用id
private String app_id ="+++++++++++++++";
//商户号id
private String mch_id ="++++++++++++++";
//密钥
private String key ="+++++++++++++++++++++";
//#APP和网页支付提交用户端ip, Native支付填调用微信支付API的机器IP, 即:服务器ip地址
private String spbtll_create_ip ="127.0.0.1";
//支付回调地址
//private String notify_url ="https://++++++++++++++++";
//测试使用的支付回调地址
private String notify_url ="http://+++++++++++++++++++++++++";
//支付方式,取值如下:JSAPI,NATIVE,APP
private String trade_type ="NATIVE";
//微信支付 - 统一下单地址
private String placeanoroer_url ="https://api.mch.weixin.qq.com/pay/unifiedorder";
3、开始写service接口吧
//请求微信api
Map<String,String> createNative(Integer id);
//微信api回调
String notifyUrl(HttpServletRequest request, HttpServletResponse response) throws Exception;
//查询支付状态
Map<String,String> queryStatus(Integer id);
4、实现service提供的createNative()方法<<注意金额 、微信是以分为单位>><<这里是用的变动订单号、不然当扫码未支付、那么这个订单再次扫码时便支付不了了、死坑>>>
这里请求需要与前端沟通,是否需要进行转码、如果不需要就直接将接收到的微信二维码连接返回给前端处理/如果需要就进行Base64的转码处理
//请求微信api
@Override
public Map<String,String> createNative(Integer id) {
try {
QueryWrapper<SOrder> wrapper = new QueryWrapper<>();
wrapper.eq("id",id);
SOrder order = orderMapper.selectList(wrapper).get(0);
String num = order.getTotalPrice().multiply(BigDecimal.valueOf(100)).setScale(0).toString();
Map<String, String> paramMap = new HashMap<>();
paramMap.put("appid",app_id);
paramMap.put("mch_id",mch_id);
paramMap.put("nonce_str", WXPayUtil.generateNonceStr());
paramMap.put("body","++++++");
String tradeNumber = order.getOId().substring(0,16);
StringBuffer sb = new StringBuffer();
int random=(int)((Math.random()*9+1)*100000);
sb.append(tradeNumber);
sb.append(random);
SOrder sOrder = new SOrder();
sOrder.setOId(sb.toString());
QueryWrapper<SOrder> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("id",id);
orderMapper.update(sOrder,queryWrapper);
SOrdertype orderType = new SOrdertype();
orderType.setOId(sb.toString());
QueryWrapper<SOrdertype> objectQueryWrapper = new QueryWrapper<>();
objectQueryWrapper.eq("o_id",order.getOId());
orderTypeMapper.update(orderType,objectQueryWrapper);
paramMap.put("out_trade_no", sb.toString());
paramMap.put("total_fee",num);
paramMap.put("spbill_create_ip",spbtll_create_ip);
paramMap.put("notify_url",notify_url);
paramMap.put("trade_type",trade_type);
String xmlparameters = WXPayUtil.generateSignedXml(paramMap,key);//签名
String ulr = placeanoroer_url;
HttpClientUtil httpClient = new HttpClientUtil(ulr);
httpClient.setHttps(true);
log.info("++我的请求信息:++\n"+xmlparameters);
httpClient.setXmlParam(xmlparameters);
httpClient.post();
String result = httpClient.getContent();
log.info("++返回的xml数据++\n"+result);
Map<String, String> resultMap = WXPayUtil.xmlToMap(result);
log.info("++返回的xml转成map数据++"+resultMap);
//生成微信二维码
String codeUrl = resultMap.get("code_url"); // 二维码内容
int width = 200; // 二维码图片宽度
int height = 200; // 二维码图片高度
Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();
hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); // 内容所使用字符集编码
BitMatrix bitMatrix = new MultiFormatWriter().encode(codeUrl,BarcodeFormat.QR_CODE, width, height, hints);
BufferedImage bufferedImage = MatrixToImageWriter.toBufferedImage(bitMatrix);
String base64 = QrCodeUtils.getBase64(bufferedImage);
HashMap<String , String> map = new HashMap<>();
map.put("base64",base64);
map.put("totalFee", String.valueOf(order.getTotalPrice()));
return map;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
5.实现notifyUrl回调方法(处理完业务一定要返回微信<<
<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>
>>)否则微信会一直调用改接口
//微信api回调
@Override
public String notifyUrl(HttpServletRequest request, HttpServletResponse response) throws Exception {
//获取网络输入流
ServletInputStream inputStream = request.getInputStream();
//定义缓存
byte[] buffer = new byte[1024];
//创建OutputStream输入文件
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//定义数组长度
int len = 0;
while ((len = inputStream.read(buffer)) != -1){
baos.write(buffer,0,len);
}
//取得微信回调结果
byte[] bytes = baos.toByteArray();
String xmlResult = new String(bytes,"utf-8");
//将取得的微信回调结果转成map
Map<String, String> resultMap = WXPayUtil.xmlToMap(xmlResult);
log.info("微信回调结果转成map"+resultMap);
//获取通信标识
String returnCode = resultMap.get("return_code");
//判断是否支付是否回调
if (returnCode.equals("SUCCESS")){
//获取业务结果
String resultCode = resultMap.get("result_code");
//获取订单号
String tradeNumber = resultMap.get("out_trade_no");
//获取微信流水号
String transactionId = resultMap.get("transaction_id");
//获取交易完成时间
String timeEnd = resultMap.get("time_end");
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
Date date = format.parse(timeEnd);
if (resultCode.equals("SUCCESS")){//SUCCESS 支付成功
SOrder order = new SOrder();
order.setTradeNumber(transactionId); //微信流水号
order.setOId(tradeNumber);//订单号
order.setOrderStatus(1);//订单状态标识 (0:待支付;1:已支付;2:已取消;3:已退款)
order.setPaymentTime(date);
order.setPaymentMethod("微信");
QueryWrapper<SOrder> wrapper = new QueryWrapper<>();
wrapper.eq("o_id",tradeNumber);
orderMapper.update(order,wrapper);
SOrdertype sOrdertype = new SOrdertype();
sOrdertype.setTradeNumber(transactionId);
QueryWrapper<SOrdertype> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("o_id",order.getOId());
orderTypeMapper.update(sOrdertype,queryWrapper);
QueryWrapper<SOrder> wrapper1 = new QueryWrapper<>();
wrapper1.eq("o_id",tradeNumber);
wrapper1.last("offset 0 rows fetch next 1 rows only");
wrapper1.orderByDesc("id");
SOrder sOrder = orderMapper.selectOne(wrapper1);
HashMap<Object, Object> map = new HashMap<>();
map.put("type","OrderPaymentSuccess");//{ type =”SubmitOrder", value = order.o_ id,
map.put("value",sOrder.getOId());
map.put("uid",order.getUid());
String result = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
response.setContentType("text/xml");
BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
out.write(result.getBytes());
out.flush();
out.close();
return result;
}else {//交易失败
String result = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[交易失败!!]]></return_msg></xml>";
response.setContentType("text/xml");
BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
out.write(result.getBytes());
out.flush();
out.close();
return result;
}
}else {//回调信息错误
String result = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[回调信息错误!!]]></return_msg></xml>";
response.setContentType("text/xml");
BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
out.write(result.getBytes());
out.flush();
out.close();
return result;
}
}
6.实现查询支付状态queryStatus接口
/**
* 查询支付状态
* */
@Override
public Map<String,String> queryStatus(Integer id) {
Map<String,String> map = new HashMap<>();
try {
QueryWrapper<SOrder> wrapper = new QueryWrapper<>();
wrapper.eq("id",id);
SOrder order = orderMapper.selectList(wrapper).get(0);
Map<String, String> paramMap = new HashMap<>();
paramMap.put("appid",app_id);
paramMap.put("mch_id",mch_id);
paramMap.put("nonce_str", WXPayUtil.generateNonceStr());
paramMap.put("out_trade_no",order.getOId());
String xmlparameters = WXPayUtil.generateSignedXml(paramMap,key);//签名
String ulr = "https://api.mch.weixin.qq.com/pay/orderquery";
HttpClientUtil httpClient = new HttpClientUtil(ulr);
httpClient.setHttps(true);
log.info("++查询支付状态的请求信息:++\n"+xmlparameters);
httpClient.setXmlParam(xmlparameters);
httpClient.post();
String result = httpClient.getContent();
log.info("++查询支付状态的返回的xml数据++\n"+result);
Map<String, String> resultMap = WXPayUtil.xmlToMap(result);
log.info("++查询支付状态的返回的xml转成map数据++"+resultMap);
if (resultMap.get("trade_state").equals("SUCCESS")){
int sum = Integer.parseInt(resultMap.get("total_fee"));
BigDecimal price = BigDecimal.valueOf(sum).divide(BigDecimal.valueOf(100));
map.put("price", String.valueOf(price));
map.put("tradeNumber",resultMap.get("out_trade_no"));
map.put("time_end",resultMap.get("time_end"));
map.put("trade_state",resultMap.get("trade_state"));
map.put("trade_state_desc",resultMap.get("trade_state_desc"));
return map;
}
map.put("tradeNumber",resultMap.get("out_trade_no"));
map.put("trade_state",resultMap.get("trade_state"));
map.put("trade_state_desc",resultMap.get("trade_state_desc"));
return map;
} catch (Exception e) {
e.printStackTrace();
}
return map;
}
7.controller层
@Autowired
private WeiXinPayService weiXinPayService;
//支付
@RequiresAuthentication
@RequestMapping(value = "/pay",method = RequestMethod.POST)
public ResultVo createNative(Integer id){
Map<String,String> result= weiXinPayService.createNative(id);
System.out.println("result="+result);
log.info("{=========================》》》》》》》微信支付请求信息}"+result);
return ResultVoUtil.success(result);
}
//微信api回调
@RequestMapping("/notifyUrl")
public String notifyUrl(HttpServletRequest request, HttpServletResponse response)throws Exception{
//log.info("{====================================》》》》》微信支付回调信息}"+weiXinPayService.notifyUrl(request,response));
return weiXinPayService.notifyUrl(request,response);
}
//查询支付状态
@RequestMapping(value = "/status/query",method = RequestMethod.GET)
public ResultVo queryStatus(Integer id){
Map<String,String> result= weiXinPayService.queryStatus(id);
log.info("{==========================》》》》》》微信支付状态查询}"+result);
if (result.get("trade_state_desc").equals("支付成功")){ //支付成功
return ResultVoUtil.success(result,"true");
}else if (result.get("trade_state_desc").equals("未支付")){//未支付
return ResultVoUtil.success(result,"false");
}else if (result.get("trade_state_desc").equals("用户支付中")){//用户支付中
return ResultVoUtil.success(result,"false");
}
return ResultVoUtil.success(null,"false");
}