|
@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject;
|
|
|
import com.zanxiang.common.constant.Constants;
|
|
|
import com.zanxiang.common.domain.ResultMap;
|
|
|
import com.zanxiang.common.enums.ResEnum;
|
|
|
+import com.zanxiang.common.utils.JsonUtil;
|
|
|
import com.zanxiang.common.utils.RandomStringUtil;
|
|
|
import com.zanxiang.sdk.common.util.*;
|
|
|
import com.zanxiang.sdk.domain.bo.ProductPayAttachParamBO;
|
|
@@ -20,15 +21,10 @@ import weixin.popular.api.SnsAPI;
|
|
|
import javax.servlet.http.HttpServletRequest;
|
|
|
import javax.servlet.http.HttpServletResponse;
|
|
|
import java.io.*;
|
|
|
-import java.net.URL;
|
|
|
-import java.net.URLConnection;
|
|
|
import java.nio.charset.StandardCharsets;
|
|
|
-import java.util.Iterator;
|
|
|
import java.util.Map;
|
|
|
import java.util.SortedMap;
|
|
|
import java.util.TreeMap;
|
|
|
-import java.util.regex.Matcher;
|
|
|
-import java.util.regex.Pattern;
|
|
|
|
|
|
/**
|
|
|
* @author xufeng
|
|
@@ -39,18 +35,34 @@ import java.util.regex.Pattern;
|
|
|
@Service("WxPayService")
|
|
|
public class WxPayServiceImpl extends PayService implements OrderPayService {
|
|
|
|
|
|
- private WxPayConfigBO config;
|
|
|
+ /**
|
|
|
+ * 二维码支付
|
|
|
+ */
|
|
|
+ private static final String WX_PAY_NATIVE = "NATIVE";
|
|
|
|
|
|
- private WxPayUtil wxPayUtil;
|
|
|
+ /**
|
|
|
+ * h5支付
|
|
|
+ */
|
|
|
+ private static final String WX_PAY_MWEB = "MWEB";
|
|
|
|
|
|
+ /**
|
|
|
+ * 服务器域名
|
|
|
+ */
|
|
|
@Value("${server.domain}")
|
|
|
private String serverUrl;
|
|
|
|
|
|
+ /**
|
|
|
+ * 微信回调接口
|
|
|
+ */
|
|
|
@Value("${payConfig.wx.notifyUrl}")
|
|
|
private String notifyUrl;
|
|
|
|
|
|
- @Value("${payConfig.wx.imgFilePath}")
|
|
|
- private String filePath;
|
|
|
+ /**
|
|
|
+ * 微信支付配置
|
|
|
+ */
|
|
|
+ private WxPayConfigBO config;
|
|
|
+
|
|
|
+ private WxPayUtil wxPayUtil;
|
|
|
|
|
|
private String body;
|
|
|
|
|
@@ -74,13 +86,15 @@ public class WxPayServiceImpl extends PayService implements OrderPayService {
|
|
|
this.configInit(getPayConfig(product.getGameId(), product.getPayWay(), product.getPayDevice()));
|
|
|
switch (product.getPayDevice()) {
|
|
|
case 1:
|
|
|
- //PC端
|
|
|
- return this.mobile(product, "NATIVE");
|
|
|
+ //PC端二维码
|
|
|
+ return this.mobile(product, WX_PAY_NATIVE);
|
|
|
case 2:
|
|
|
- return this.mobile(product, "MWEB");
|
|
|
+ //手机端H5
|
|
|
+ return this.mobile(product, WX_PAY_MWEB);
|
|
|
// case 3:
|
|
|
// return this.mobile(product, "MWEB");
|
|
|
case 4:
|
|
|
+ //微信小程序
|
|
|
return this.mp(product);
|
|
|
default:
|
|
|
throw new RuntimeException("未知支付方式");
|
|
@@ -100,7 +114,7 @@ public class WxPayServiceImpl extends PayService implements OrderPayService {
|
|
|
InputStream inputStream = request.getInputStream();
|
|
|
StringBuffer sb = new StringBuffer();
|
|
|
String s;
|
|
|
- BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, Constants.UTF8));
|
|
|
+ BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
|
|
|
while ((s = in.readLine()) != null) {
|
|
|
sb.append(s);
|
|
|
}
|
|
@@ -108,21 +122,18 @@ public class WxPayServiceImpl extends PayService implements OrderPayService {
|
|
|
inputStream.close();
|
|
|
log.info("微信支付回调 body:{}", sb);
|
|
|
// 解析xml成map
|
|
|
- Map<String, String> m = XMLUtil.doXMLParse(sb.toString());
|
|
|
+ Map m = XMLUtil.doXmlParse(sb.toString());
|
|
|
// 过滤空 设置 TreeMap
|
|
|
SortedMap<Object, Object> packageParams = new TreeMap<>();
|
|
|
- Iterator it = m.keySet().iterator();
|
|
|
- while (it.hasNext()) {
|
|
|
- String parameter = (String) it.next();
|
|
|
- String parameterValue = m.get(parameter);
|
|
|
-
|
|
|
+ for (Object parameter : m.keySet()) {
|
|
|
+ String parameterValue = (String) m.get(parameter);
|
|
|
String v = "";
|
|
|
if (null != parameterValue) {
|
|
|
v = parameterValue.trim();
|
|
|
}
|
|
|
packageParams.put(parameter, v);
|
|
|
}
|
|
|
- ProductPayAttachParamBO attachBO = this.decodeAttach(packageParams.get("attach"));
|
|
|
+ ProductPayAttachParamBO attachBO = JsonUtil.toObj(JsonUtil.toString(packageParams.get("attach")), ProductPayAttachParamBO.class);
|
|
|
configInit(getPayConfig(attachBO.getGamePayWayId()));
|
|
|
// 账号信息
|
|
|
String key = config.getApiKey();
|
|
@@ -136,7 +147,7 @@ public class WxPayServiceImpl extends PayService implements OrderPayService {
|
|
|
String orderNo = (String) packageParams.get("out_trade_no");
|
|
|
log.info("微信订单号{}付款成功", orderNo);
|
|
|
if (paySuccess(attachBO.getOrderId(), String.valueOf(Float.parseFloat(packageParams.get("total_amount").toString()) / 100), packageParams.get("trade_no").toString(), attachBO.getGamePayWayId())) {
|
|
|
- log.info("支付宝异步回调成功 request:{},商户订单号为:{}", request, outTradeNo);
|
|
|
+ log.info("微信异步回调成功 request:{},商户订单号为:{}", request, outTradeNo);
|
|
|
return ResEnum.SUCCESS.getMsg();
|
|
|
}
|
|
|
// 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了
|
|
@@ -170,42 +181,6 @@ public class WxPayServiceImpl extends PayService implements OrderPayService {
|
|
|
}
|
|
|
|
|
|
|
|
|
- /**
|
|
|
- * pc支付
|
|
|
- *
|
|
|
- * @param product
|
|
|
- * @return
|
|
|
- */
|
|
|
- public ResultMap pc(ProductPayParamBO product) {
|
|
|
- //商户支付回调URL设置指引:进入公众平台-->微信支付-->开发配置-->扫码支付-->修改 加入回调URL
|
|
|
- SortedMap<Object, Object> packageParams = new TreeMap<>();
|
|
|
- //封装通用参数
|
|
|
- wxPayUtil.commonParams(packageParams);
|
|
|
- packageParams.put("attach", JSONObject.toJSONString(this.attach));
|
|
|
- //生成签名
|
|
|
- String sign = PayCommonUtil.createSign(Constants.UTF8, packageParams, config.getApiKey());
|
|
|
- //组装二维码信息
|
|
|
- StringBuffer qrCode = new StringBuffer();
|
|
|
- qrCode.append("weixin://wxpay/bizpayurl?");
|
|
|
- qrCode.append("appid=" + config.getAppId());
|
|
|
- qrCode.append("&mch_id=" + config.getMchId());
|
|
|
- qrCode.append("&nonce_str=" + packageParams.get("nonce_str"));
|
|
|
- qrCode.append("&out_trade_no=" + this.outTradeNo);
|
|
|
- qrCode.append("&time_stamp=" + packageParams.get("time_stamp"));
|
|
|
- qrCode.append("&sign=" + sign);
|
|
|
- String imgName = this.outTradeNo + ".png";
|
|
|
- File pathFile = new File(this.filePath);
|
|
|
- if (!pathFile.exists()) {
|
|
|
- pathFile.mkdirs();
|
|
|
- }
|
|
|
- String imgPath = filePath + imgName;
|
|
|
- log.info("小程序支付调起,请求参数:qrCode:{}, imgPath:{}", qrCode, imgPath);
|
|
|
- QrCode.createQrCodeImage(qrCode.toString(), imgPath);
|
|
|
- System.out.println(imgPath);
|
|
|
- return ResultMap.ok(product.getPayDevice(), qrCode.toString());
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
/**
|
|
|
* 小程序(需要HTTPS)
|
|
|
*
|
|
@@ -227,7 +202,7 @@ public class WxPayServiceImpl extends PayService implements OrderPayService {
|
|
|
* @param product
|
|
|
* @return
|
|
|
*/
|
|
|
- public ResultMap mobile(ProductPayParamBO product, String tradeType) {
|
|
|
+ private ResultMap mobile(ProductPayParamBO product, String tradeType) {
|
|
|
//商户支付回调URL设置指引:进入公众平台-->微信支付-->开发配置-->扫码支付-->修改 加入回调URL
|
|
|
log.info("订单号:{}生成微信支付码", product.getOutTradeNo());
|
|
|
try {
|
|
@@ -251,69 +226,42 @@ public class WxPayServiceImpl extends PayService implements OrderPayService {
|
|
|
packageParams.put("attach", JSONObject.toJSONString(this.attach));
|
|
|
String sign = PayCommonUtil.createSign(Constants.UTF8, packageParams, key);
|
|
|
packageParams.put("sign", sign);
|
|
|
- log.info("订单号:{} 加密请求参数 packageParams:{}", product.getOutTradeNo(), packageParams);
|
|
|
String requestXml = PayCommonUtil.getRequestXml(packageParams);
|
|
|
String resXml = HttpUtil.postData(WxPayUrl.UNIFIED_ORDER_URL, requestXml);
|
|
|
- Map map = XMLUtil.doXMLParse(resXml);
|
|
|
- log.info("订单号:{} 微信响应 map:{}", product.getOutTradeNo(), map);
|
|
|
+ Map map = XMLUtil.doXmlParse(resXml);
|
|
|
+ if (map == null) {
|
|
|
+ log.error("微信支付通信异常, 订单号:{}", product.getOutTradeNo());
|
|
|
+ return ResultMap.error();
|
|
|
+ }
|
|
|
String returnCode = (String) map.get("return_code");
|
|
|
//返回失败
|
|
|
if (!Constants.SUCCESS.equalsIgnoreCase(returnCode)) {
|
|
|
String returnMsg = (String) map.get("return_msg");
|
|
|
- log.error("(订单号:{}生成微信支付码(通信)失败:{}", product.getOutTradeNo(), returnMsg);
|
|
|
+ log.error("微信支付通信失败, 订单号:{}, msg :{}", product.getOutTradeNo(), returnMsg);
|
|
|
return ResultMap.error(returnMsg);
|
|
|
}
|
|
|
//结果失败
|
|
|
String resultCode = (String) map.get("result_code");
|
|
|
if (!Constants.SUCCESS.equalsIgnoreCase(resultCode)) {
|
|
|
String errCodeDes = (String) map.get("err_code_des");
|
|
|
- log.error("订单号:{}生成微信支付码(系统)失败:{}", product.getOutTradeNo(), errCodeDes);
|
|
|
+ log.error("微信支付通信失败, 订单号:{}, errCodeDes :{}", product.getOutTradeNo(), errCodeDes);
|
|
|
return ResultMap.error(errCodeDes);
|
|
|
}
|
|
|
- //成功
|
|
|
- log.info("订单号:{}生成微信支付码成功", product.getOutTradeNo());
|
|
|
- String urlCode = tradeType.equals("MWEB") ? (String) map.get("mweb_url") : (String) map.get("code_url");
|
|
|
- //转成deepLink
|
|
|
- if (tradeType.equals("MWEB")) {
|
|
|
- urlCode = this.readUrl(urlCode);
|
|
|
+ if (tradeType.equals(WX_PAY_MWEB)) {
|
|
|
+ String urlCode = wxPayUtil.readUrl((String) map.get("mweb_url"), serverUrl);
|
|
|
+ return ResultMap.ok(product.getPayDevice(), urlCode);
|
|
|
}
|
|
|
- return ResultMap.ok(product.getPayDevice(), urlCode);
|
|
|
+ if (tradeType.equals(WX_PAY_NATIVE)) {
|
|
|
+ String urlCode = (String) map.get("code_url");
|
|
|
+ return ResultMap.ok(product.getPayDevice(), urlCode);
|
|
|
+ }
|
|
|
+ return ResultMap.ok(product.getPayDevice(), null);
|
|
|
} catch (Exception e) {
|
|
|
- log.error("订单号:{}生成微信支付码失败(系统异常))", product.getOutTradeNo(), e);
|
|
|
+ log.error("微信支付通信异常, 订单号:{}, e : {}", product.getOutTradeNo(), e.getMessage());
|
|
|
return ResultMap.error();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 转换deepLink
|
|
|
- *
|
|
|
- * @param url
|
|
|
- * @return
|
|
|
- * @throws Exception
|
|
|
- */
|
|
|
- private String readUrl(String url) throws Exception {
|
|
|
- // 定义好匹配规则
|
|
|
- String regex = "weixin://wap/pay?.[^\\x{4e00}-\\x{9fa5}-\"]+";
|
|
|
- Pattern pattern = Pattern.compile(regex);
|
|
|
- URL payUrl = new URL(url);
|
|
|
- URLConnection con = payUrl.openConnection();
|
|
|
- // 加referer防盗链,必须是你申请的支付白名单
|
|
|
-// con.setRequestProperty("Referer", "https://test.game.hzshengmel.com");
|
|
|
- con.setRequestProperty("Referer", serverUrl);
|
|
|
- BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), StandardCharsets.UTF_8));
|
|
|
- String result = "";
|
|
|
- String realLineStr = null;
|
|
|
- while ((realLineStr = br.readLine()) != null) {
|
|
|
- // 一行行查找
|
|
|
- Matcher matcher = pattern.matcher(realLineStr);
|
|
|
- if (matcher.find()) {
|
|
|
- result = matcher.group();
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- return result;
|
|
|
- }
|
|
|
-
|
|
|
/**
|
|
|
* 配置初始化
|
|
|
*/
|
|
@@ -322,14 +270,4 @@ public class WxPayServiceImpl extends PayService implements OrderPayService {
|
|
|
this.config = JSONObject.parseObject(obj, WxPayConfigBO.class);
|
|
|
this.wxPayUtil = new WxPayUtil(this.config);
|
|
|
}
|
|
|
-
|
|
|
- /**
|
|
|
- * 反解析自定义参数
|
|
|
- *
|
|
|
- * @param obj
|
|
|
- * @return
|
|
|
- */
|
|
|
- private ProductPayAttachParamBO decodeAttach(Object obj) {
|
|
|
- return JSONObject.parseObject(obj.toString(), ProductPayAttachParamBO.class);
|
|
|
- }
|
|
|
}
|