<!--微信支付-->
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>0.0.3</version>
</dependency>
<!-- http请求工具包依赖 -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>
/**
* 微信登录
* @return
*/
@RequestMapping("/wxLogin")
@ResponseBody
public Result user_login(@RequestParam(value = "code", required = false) String code,
@RequestParam(value = "rawData", required = false) String rawData,
@RequestParam(value = "signature", required = false) String signature,
@RequestParam(value = "encrypteData", required = false) String encrypteData,
@RequestParam(value = "iv", required = false) String iv) {
// 用户非敏感信息:rawData
// 签名:signature
JSONObject rawDataJson = JSON.parseObject(rawData);
// 1.接收小程序发送的code
// 2.开发者服务器 登录凭证校验接口 appi + appsecret + code
JSONObject SessionKeyOpenId = WeChatUtil.getSessionKeyOrOpenId(code);
// 3.接收微信接口服务 获取返回的参数
String openid = SessionKeyOpenId.getString("openid");
String sessionKey = SessionKeyOpenId.getString("session_key");
// 4.校验签名 小程序发送的签名signature与服务器端生成的签名signature2 = sha1(rawData + sessionKey)
String signature2 = DigestUtils.sha1Hex(rawData + sessionKey);
if (!signature.equals(signature2)) {
return Result.build(500, "签名校验失败", null);
}
// 5.根据返回的User实体类,判断用户是否是新用户,是的话,将用户信息存到数据库;不是的话,更新最新登录时间
User user = this.userMapper.selectById(openid);
// uuid生成唯一key,用于维护微信小程序用户与服务端的会话
String skey = UUID.randomUUID().toString();
String nickName = rawDataJson.getString("nickName");
Boolean status = rawDataJson.getBoolean("status");
if (user == null) {
// 用户信息入库
user = new User();
user.setOpenId(openid);
user.setSessionKey(sessionKey);
user.setUserName(nickName);
user.setPayStatus(status);
//this.userMapper.insert(user);
Result result = userService.addUser(user);
Map<String ,Object> map = new HashMap<>();
map.put("skey",skey);
map.put("userResult",result);
return Result.build(200,"succ",map);
} else {
user.setPayStatus(status);
this.userMapper.updateById(user);
}
//encrypteData比rowData多了appid和openid
//JSONObject userInfo = WechatUtil.getUserInfo(encrypteData, sessionKey, iv);
//6. 把新的skey返回给小程序
return Result.build(200,"succ",skey);
}
接口实现类:
//常量配置
public static final String SPBILL_CREATE_IP = "IP地址";
public static final String NOTIFY_URL = "https://域名和端口/notify";
public static final String TRADE_TYPE_APP = "JSAPI";
//微信回调访问的接口
@Override
public String payBack(String resXml) {
WXConfigUtil config = null;
try {
config = new WXConfigUtil ();
} catch (Exception e) {
e.printStackTrace();
}
WXPay wxpay = new WXPay(config);
String xmlBack = "";
Map<String, String> notifyMap = null;
try {
notifyMap = WXPayUtil.xmlToMap(resXml); // 调用官方SDK转换成map类型数据
if (wxpay.isPayResultNotifySignatureValid(notifyMap)) {//验证签名是否有效,有效则进一步处理
String return_code = notifyMap.get("return_code");//状态
String out_trade_no = notifyMap.get("out_trade_no");//商户订单号
String openid = notifyMap.get("openid");//openid
if (return_code.equals("SUCCESS")) {
if (out_trade_no != null) {
// 注意特殊情况:订单已经退款,但收到了支付结果成功的通知,不应把商户的订单状态从退款改成支付成功
// 注意特殊情况:微信服务端同样的通知可能会多次发送给商户系统,所以数据持久化之前需要检查是否已经处理过了,处理了直接返回成功标志
//业务数据持久化
xmlBack = "" + " " + " " + " ";
/**
* 用户状态更新
*/
User user = userMapper.selectByOpenid(openid);
user.setPayStatus(true);
userMapper.updateById(user);
/**
* 新增流水信息
*/
PriceStream priceStream = new PriceStream();
priceStream.setUserName(user.getUserName());
priceStream.setPayPrice(systemConfigService.getBookPrice()/100);
priceStream.setOutTradeNo(out_trade_no);
priceStreamService.addStream(priceStream);
} else {
xmlBack = "" + " " + " " + " ";
}
}
return xmlBack;
} else {
// 签名错误,如果数据里没有sign字段,也认为是签名错误
//失败的数据要不要存储?
log.error("手机支付回调通知签名错误");
xmlBack = "" + " " + " " + " ";
return xmlBack;
}
} catch (Exception e) {
log.error("手机支付回调通知失败", e);
xmlBack = "" + " " + " " + " ";
}
return xmlBack;
}
//微信支付时前端调用的接口
@Override
public Map doUnifiedOrder(Integer id) throws Exception {
try {
User user = userMapper.selectById(id);
WXConfigUtil config = new WXConfigUtil ();
WXPay wxpay = new WXPay(config);
Map<String, String> data = new HashMap<>();
//生成商户订单号,不可重复
data.put("appid", config.getAppID());
data.put("openid", user.getOpenId());
data.put("mch_id", config.getMchID());
data.put("nonce_str", WXPayUtil.generateNonceStr());
String body = "订单支付";
data.put("body", body);
data.put("out_trade_no", UUID.randomUUID().toString().replaceAll("-",""));
data.put("total_fee", systemConfigService.getBookPrice().toString());
//data.put("total_fee", "1");
//自己的服务器IP地址
data.put("spbill_create_ip", SPBILL_CREATE_IP);
//异步通知地址(请注意必须是外网)
data.put("notify_url", NOTIFY_URL);
//交易类型
data.put("trade_type", TRADE_TYPE_APP);
//附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据
data.put("attach", "");
data.put("sign", WXPayUtil.generateSignature(data, config.getKey(),
WXPayConstants.SignType.MD5));
//使用官方API请求预付订单
Map<String, String> response = wxpay.unifiedOrder(data);
if ("SUCCESS".equals(response.get("return_code"))) {//主要返回以下5个参数
Map<String, String> param = new HashMap<>();
param.put("appId",config.getAppID());
param.put("timeStamp",System.currentTimeMillis()/1000+"");
param.put("nonceStr",WXPayUtil.generateNonceStr());
param.put("signType",WXPayUtil.generateNonceStr());
param.put("package","prepay_id=" + response.get("prepay_id"));
param.put("paySign",WXPayUtil.generateSignature(param, config.getKey(),
WXPayConstants.SignType.MD5));
return param;
}
} catch (Exception e) {
e.printStackTrace();
throw new Exception("下单失败");
}
throw new Exception("下单失败");
}
微信支付控制器:
/**
* 微信支付
*/
@RequestMapping("/wx")
public Map wxAdd(@RequestBody User user) throws Exception {
return userService.doUnifiedOrder(user.getId());
}
@PostMapping("/notify")
@ApiOperation("微信回调")
public String wxPayNotify(HttpServletRequest request) {
String resXml = "";
try {
InputStream inputStream = request.getInputStream();
//将InputStream转换成xmlString
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
System.out.println(e.getMessage());
} finally {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
resXml = sb.toString();
String result = userService.payBack(resXml);
return result;
} catch (Exception e) {
System.out.println("微信手机支付失败:" + e.getMessage());
String result = "" + " " + " " + " ";
return result;
}
}