有微信支付的需求,先是自己看了几天博客和微信的官方文档,然后选择使用官方sdk去写,问题总结如下:
1.官方sdk的加密方式需要改成MD5,这是一个官方的大坑
public WXPay(final WXPayConfig config, final String notifyUrl, final boolean autoReport, final boolean useSandbox) throws Exception {
this.config = config;
this.notifyUrl = notifyUrl;
this.autoReport = autoReport;
this.useSandbox = useSandbox;
if (useSandbox) {
this.signType = SignType.MD5; // 沙箱环境
}
else {
this.signType = SignType.MD5;
}
this.wxPayRequest = new WXPayRequest(config);
}
2.下单之后最好有能收到微信返回结果的接口,微信返回来的结果不是json格式,接收方式也需要注意
具体看代码
获取openid
@PostMapping("/getOpenid") public JsonResult getOpenid(@RequestBody Map request){ MyConfig config = null; try { config = new MyConfig(); } catch (Exception e) { e.printStackTrace(); } initMyConf(config, (String) request.get("schId")); //先获取四个必要参数, 拼接获取微信openid的api String key = "appid=" + config.getAppID() + "&secret=" + config.getSecret() + "&grant_type=" + "authorization_code" + "&js_code=" + request.get("code"); String url = "https://api.weixin.qq.com/sns/jscode2session" + "?" + key; String result = connectUrl(url);//这里我是使用了网络代理,没要求使用正常的http请求就行 Map map = JSON.parseObject(result,Map.class); assert map != null; if (map.get("openid") == null) { return JsonResultBuilder.errorMessage(map.get("errmsg").toString()); } return JsonResultBuilder.successMessage(map.get("openid").toString()); }
统一下单
@PostMapping("/unifiedOrder")
public JsonResult unifiedOrder(@RequestBody Map request){
MyConfig config = null;
WXPay wxpay = null;
try {
config = new MyConfig();
wxpay = new WXPay(config);
} catch (Exception e) {
e.printStackTrace();
}
Map<String, String> data = new HashMap<String, String>();
data.put("body", (String) request.get("body"));
//生成商户订单号
String out_trade_no = String.valueOf(SequenceFactory.getInstance().getSeqence(ShanyuanDonor.class.getSimpleName()).nextId());
data.put("out_trade_no", out_trade_no);
data.put("device_info", (String) request.get("device_info"));
data.put("fee_type", (String) request.get("fee_type"));
data.put("total_fee", (String) request.get("total_fee"));
//获取本机的ip地址
InetAddress addr = null;
try {
addr = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
e.printStackTrace();
}
String spbill_create_ip = addr.getHostAddress();
data.put("spbill_create_ip", spbill_create_ip);
data.put("notify_url", "https://schoolfellowtest.edu-scene.com/xyh/WXPayController/returnPayResult/");
data.put("trade_type", "JSAPI"); // 此处指定为JS支付
data.put("openid", (String) request.get("openid"));
//返回5个参数和sign
Map resultMap = new HashMap();
try {
Map<String, String> resp = wxpay.unifiedOrder(data);
System.out.println("统一下单返回:" + resp);
String return_code = (String) resp.get("return_code");
String result_code = (String) resp.get("result_code");
Long timeStamp = System.currentTimeMillis() / 1000;
String nonceStr = WXPayUtil.generateNonceStr();
resultMap.put("nonceStr", nonceStr);
if ("SUCCESS".equals(return_code) && return_code.equals(result_code)) {
String prepayid = resp.get("prepay_id");
resultMap.put("package", "prepay_id="+prepayid);
resultMap.put("signType", "MD5");
//这边要将返回的时间戳转化成字符串,不然小程序端调用wx.requestPayment方法会报签名错误
resultMap.put("timeStamp", String.valueOf(timeStamp));
//再次签名,这个签名用于小程序端调用wx.requesetPayment方法
resultMap.put("appId", config.getAppID());
String sign = WXPayUtil.generateSignature(resultMap, config.getKey());
resultMap.put("paySign", sign);
System.out.println("生成的签名paySign : "+ sign);
}
} catch (Exception e) {
e.printStackTrace();
}
return JsonResultBuilder.success(resultMap);
}
微信返回接受
@RequestMapping(value = "/returnPayResult" , produces = "text/xml; charset=utf-8")
@ResponseBody
public String returnPayResult(@RequestBody String notifyData){
MyConfig config = null;
WXPay wxpay = null;
Map result = new HashMap();
try {
config = new MyConfig();
wxpay = new WXPay(config);
Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyData); // 转换成map
if (wxpay.isPayResultNotifySignatureValid(notifyMap)) {
//根据自己需求写
result.put("code", "SUCCESS");
result.put("message", "成功");
} else {
result.put("message", "失败");
}
} catch (Exception e) {
e.printStackTrace();
}
return JSON.toJSONString(result);
}