微信支持哪几种支付方式
登录微信公众平台–>开发>基本配置>ip白名单
支付授权目录说明:
1、商户最后请求拉起微信支付收银台的页面地址我们称之为“支付目录”,例如:https://www.weixin.com/pay.php。
2、商户实际的支付目录必须和在微信支付商户平台设置的一致,否则会报错“当前页面的URL未注册:”
支付授权目录设置说明:
登录微信支付商户平台(pay.weixin.qq.com)–>产品中心–>开发配置,设置后一般5分钟内生效。
支付授权目录校验规则说明:
1、如果支付授权目录设置为顶级域名(例如:https://www.weixin.com/ ),那么只校验顶级域名,不校验后缀;
2、如果支付授权目录设置为多级目录,就会进行全匹配,例如设置支付授权目录为https://www.weixin.com/abc/123/,则实际请求页面目录不能为https://www.weixin.com/abc/,也不能为https://www.weixin.com/abc/123/pay/,必须为https://www.weixin.com/abc/123/
微信开发,都得先了解微信的access_token获取及过期机制,获取access_token之后存到本地数据库,然后不要频繁去调用微信接口获取access_token,每天调用获取access_token接口的次数微信有限制,只需要判断过期时再去获取access_token。
获取access_token接口地址:
https://api.weixin.qq.com/cgi-bin/token?&grant_type=client_credential&appid=" + appId + "&secret="+ secret
更新数据库access_token和过期时间:
wc.setAccessToken(json.getString("access_token"));
Date expiresTime = new Date(new Date().getTime() + json.getIntValue("expires_in")*1000);
wc.setExpiresTime(expiresTime);
wxAccessConfMapper.updateWxAccessConf(wc);
判断过期时调用获取access_token接口:
if(wc.getExpiresTime() == null || StringUtils.isBlank(wc.getAccessToken()) || new Date().getTime() > wc.getExpiresTime().getTime()){
//调用获取access_token接口,更新数据库access_token和过期时间
}
微信开发,还得了解微信的jsapi的ticket获取及过期时间,和access_token类似但作用于微信前端页面的jsapi调用,access_token是作用于后端接口。
获取ticket接口地址:
https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + accessToken+ "&type=jsapi
更新数据库ticket和过期时间:
wc.setJsapiTicket(json.getString("ticket"));
Date expiresTime = new Date(new Date().getTime() + json.getIntValue("expires_in")*1000);
wc.setJsapExpiresTime(expiresTime);
wxAccessConfMapper.updateWxAccessConf(wc);
判断过期时调用获取ticket接口:
if (wc.getJsapExpiresTime() == null || StringUtils.isBlank(wc.getJsapiTicket()) || new Date().getTime() > wc.getJsapExpiresTime().getTime()) {
//调用获取ticket接口,更新数据库ticket和过期时间
}
这个链接建议是一个接口地址,不能直接是html这种静态页面,因为我们需要在这个接口里获取微信openid等微信用户基本数据。
示例二维码链接:
http://www.xuexibisai.com/weixin/enter.do?productId=ss1000223000
// 用户通过微信内置浏览器访问此接口
// 如果用户在微信客户端中访问第三方网页,公众号可以通过微信网页授权机制,来获取用户基本信息(目前我们只需要openid),进而实现业务逻辑。
@RequestMapping(value = "/enter.do", method = RequestMethod.GET)
public void enter(HttpServletRequest request, HttpServletResponse response, String productId) {
try {
WxAccessConf wc= weixinService.getSelfWxAccessConfAndUp();//获取本地数据库的微信基本数据,并判断access_token和ticket是否过期,如果过期就更新access_token和ticket
String url = "http://www.xuexibisai.com" + request.getContextPath() + "/weixin/pay.view?productId=" + productId;
// scope参数只有两种应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且, 即使在未关注的情况下,只要用户授权,也能获取其信息 )
// state参数是开发者自定义的参数,重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节
response.sendRedirect("https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + wc.getAppId() + "&redirect_uri=" + URLEncoder.encode(url, "utf-8")
+ "&response_type=code&scope=snsapi_base&state=1#wechat_redirect");
// 如果用户同意授权,页面将跳转至 redirect_uri/?code=CODE&state=STATE。
} catch (Exception e) {
e.printStackTrace();
}
}
// 经过微信重定向后,会返回code,然后根据code获取openid,并将openid返回给页面
@RequestMapping(value = "/pay.view", method = RequestMethod.GET)
public ModelAndView payView(HttpServletRequest request, HttpServletResponse response, String code, String productId) throws IOException {
WxAccessConf wxAccessConf = weixinService.getSelfWxAccessConf();
// 通过code拿openid
String openId = weiXinAuthManager.getOpenId(wxAccessConf, code);
// 通过openid查用户信息
JSONObject jsonObject = weiXinAuthManager.getUserInfo(wxAccessConf, openId);
LOG.debug(logPrefix + "最新的微信用户信息:" + jsonObject.toJSONString());
// 查数据库用户信息
WxUserInfo wxUserInfo = wxUserInfoMapper.selectByOpenId(openId);
if (!Utils.isEmpty(jsonObject, "openid")) {
if (wxUserInfo == null) {// 如果数据库没有就插入用户信息
wxUserInfo = new WxUserInfo();
wxUserInfo.setAppId(wxAccessConf.getAppId());
wxUserInfo.setOpenid(openId);
wxUserInfo.setCreateTime(new Date());
}
wxUserInfo.setNickname(jsonObject.getString("nickname"));
wxUserInfo.setHeadimgurl(jsonObject.getString("headimgurl"));
wxUserInfo.setSex(jsonObject.getInteger("sex"));
wxUserInfo.setCity(jsonObject.getString("city"));
wxUserInfo.setProvince(jsonObject.getString("province"));
wxUserInfo.setCountry(jsonObject.getString("country"));
wxUserInfo.setSubscribe(jsonObject.getInteger("subscribe"));
wxUserInfo.setSubscribeTime(jsonObject.getLong("subscribe_time"));
wxUserInfo.setGroupid(jsonObject.getInteger("groupid"));
wxUserInfo.setRemark(jsonObject.getString("remark"));
if (!Utils.isEmpty(jsonObject.getString("unionid"))) {
wxUserInfo.setUnionid(jsonObject.getString("unionid"));
}
wxUserInfo.setUpdateTime(new Date());
if (Utils.isEmpty(wxUserInfo.getUserId())) {
wxUserInfoMapper.insertSelective(wxUserInfo);
} else {
wxUserInfoMapper.updateByPrimaryKeySelective(wxUserInfo);
}
}
Product product = productMapper.selectByPrimaryKey(Long.parseLong(productId));
if (info == null) {
return WebUtil.getErrorPage("查询支付信息失败", LOG, logPrefix);
}
Map<String, Object> model = new HashMap<>(2);
model.put("openId", openId);
model.put("product", product);
return new ModelAndView("pay", model);// 跳到支付页面
}
<html>
展示商品信息
<input id="productId" name="productId" value="${(product.productId)!''}" type="hidden"/>
<input id="openId" name="openId" value="${openId!''}" type="hidden"/>
<input type="button" id="payBtn" value="支付" onclick="pay(this)"/>
html>
微信要求调用微信jsapi前需调用wx.config,声明你要调用哪些js接口。
<html>
<script type="text/javascript">
$.ajax({
url : '${ctx}/weixin/getJsConfig.ajax',
async : false,
data : {
'url' : window.location.href
},
dataType : 'json',
type : 'post',
success : function(result) {
var data = result.data;
if (data.appid == null || data.appid == "") {
return;
}
wx.config({
debug : false,
appId : data.appid,
timestamp : data.timestamp,
nonceStr : data.nonceStr,
signature : data.signature,
jsApiList : [ "chooseWXPay" ]
});
}
});
wx.error(function(res) {
alert("页面鉴权失败:"+res);
});
wx.ready(function() {
});
script>
展示商品信息
<input id="productId" name="productId" value="${(product.productId)!''}" type="hidden"/>
<input id="openId" name="openId" value="${openId!''}" type="hidden"/>
<input type="button" id="payBtn" value="支付" onclick="pay(this)"/>
html>
private static String byteToHex(final byte[] hash) {
Formatter formatter = new Formatter();
for (byte b : hash) {
formatter.format("%02x", b);
}
String result = formatter.toString();
formatter.close();
return result;
}
@RequestMapping(value = "/getJsConfig.ajax")
@ResponseBody
public Map<String, Object> getJsConfig(HttpServletRequest request, HttpServletResponse response, String url) {
WxAccessConf wxAccessConf = weixinService.getSelfWxAccessConf();
if (StringUtils.isBlank(url)) {
LOG.info("url传递失败");
return fail("传递失败");
}
Map<String, String> ret = new HashMap<String, String>();
String nonceStr =UUID.randomUUID().toString();
String timestamp = Long.toString(System.currentTimeMillis() / 1000);
String string1;
String signature = "";
// 注意这里参数名必须全部小写,且必须有序
string1 = "jsapi_ticket=" + wxAccessConf.getJsapiTicket() + "&noncestr=" + nonceStr + "×tamp=" + timestamp + "&url=" + url;
try {
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(string1.getBytes("UTF-8"));
signature = byteToHex(crypt.digest());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
ret.put("url", url);
ret.put("nonceStr", nonceStr);
ret.put("timestamp", timestamp);
ret.put("signature", signature);
LOG.debug("ret:=" + ret);
ret.put("appid", wxAccessConf.getAppId());
return success(ret);
}
var flag = false;
function pay(btn) {
if (flag == true) {
alert("您已经支付过了,请不要重复支付哦!");
return;
}
$.ajax({
url : '${ctx}/weixin/pay.ajax',//后端提供wx.chooseWXPay的参数
type : 'post',
'data' : {
"productId" : $("#productId").val(),
"openId" : $("#openId").val()
},
dataType : 'json',
aysnc : false,
success : function(res) {
if (res && res.code) {
if(res.code == "200"){
var data = res.data;
wx.chooseWXPay({
'debug' : true,
'timestamp': data.timeStamp,
'nonceStr': data.nonceStr,
'package': 'prepay_id=' + data.prepayId,
'signType': 'MD5',
'paySign': data.sign,
success : function(res) {
flag = true;
alert("支付成功");
$(btn).prop("disabled", "disabled");
},
fail:function(err) {
alert("系统错误:"+err);
}
});
}else{
alert("系统错误:"+res.msg);
}
} else {
alert("系统错误:"+res);
}
}
});
}
wx.chooseWXPay({
timeStamp: 0, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
nonceStr: '', // 支付签名随机串,不长于 32 位
package: '', // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=***)
signType: '', // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
paySign: '', // 支付签名
success: function (res) {
// 支付成功后的回调函数
}
});
wx.chooseWXPay有一个替代品:
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId" : "wx2421b1c4370ec43b", //公众号名称,由商户传入
"timeStamp":" 1395712654", //时间戳,自1970年以来的秒数
"nonceStr" : "e61463f8efa94090b1f366cccfbbb444", //随机串
"package" : "prepay_id=u802345jgfjsdfgsdg888",
"signType" : "MD5", //微信签名方式:
"paySign" : "70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信签名
},
function(res){
if(res.err_msg == "get_brand_wcpay_request:ok" ) {} // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回 ok,但并不保证它绝对可靠。
}
);
public String getSign(Map<String, String> map, String apiKey) {
StringBuffer sb = new StringBuffer();
Set es = map.entrySet();// 所有参与传参的参数按照accsii排序(升序)
Iterator it = es.iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
String k = (String) entry.getKey();
Object v = entry.getValue();
if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {
sb.append(k + "=" + v + "&");
}
}
sb.append("key=" + apiKey);
String sign = MD5Util.MD5(sb.toString(),"UTF-8").toUpperCase();
return sign;
}
/**
* 返回微信支付前端参数对象
*/
public WxResp getPayConfig(WeixinOrderDTO weixinOrder, WxAccessConf accessConf, WeixinResponseDTO weixinResponse) {
// 返回对象值
LOG.debug("进入返回界面的wxRsp");
WxResp wxResp = new WxResp();
wxResp.setAppId(weixinResponse.getAppid());
wxResp.setPartnerId(weixinResponse.getMch_id());
wxResp.setNonceStr(weixinOrder.getNonceStr());
wxResp.setPrepayId(weixinResponse.getPrepay_id());
wxResp.setPackageValue("Sign=WXPay");
String timeStamp = String.valueOf(System.currentTimeMillis() / 1000);
wxResp.setTimeStamp(timeStamp);
Map<String, String> map = new TreeMap<String, String>();
map.put("appId", weixinResponse.getAppid());
map.put("timeStamp", timeStamp);
map.put("nonceStr", weixinOrder.getNonceStr());
map.put("package", "prepay_id=" + weixinResponse.getPrepay_id());
map.put("signType", "MD5");
StringBuffer sb = new StringBuffer();
String sign = getSign(map,accessConf.getApiKey());
wxResp.setSign(sign);
LOG.debug("进入返回界面的wxRsp下面" + wxResp.toString());
return wxResp;
}
// 下单,生成prepay_id给前端H5,然后通过jsapi调用wx.chooseWXPay
@RequestMapping(value = "/wxPayMonthBalancePay.ajax", method = RequestMethod.POST)
@ResponseBody
public Object wxPayMonthBalancePay(HttpServletRequest request, HttpServletResponse response, String openId, Long infoId) throws IOException {
String logPrefix = "月账单结算支付>>>";
LOG.debug(logPrefix + "参数,openId=" + openId + ",infoId=" + infoId);
if (Utils.isEmpty(openId)) {
return JsonResult.getFailResultAndLog("openId为空", LOG, logPrefix);
}
WxUserInfo wxUser = wxUserInfoMapper.selectByOpenId(openId);
if (wxUser == null) {
return JsonResult.getFailResultAndLog("微信用户未录入", LOG, logPrefix);
}
if (Utils.isEmpty(infoId)) {
return JsonResult.getFailResultAndLog("infoId为空", LOG, logPrefix);
}
WxPayMonthBalanceInfo info = wxPayMonthBalanceInfoMapper.selectByPrimaryKey(infoId);
if (info == null) {
return JsonResult.getFailResultAndLog("未找到支付信息", LOG, logPrefix);
}
WxAccessConf wxAccessConf = weixinService.getSelfWxAccessConf();
TempBean tempBean = weixinService.wxPayMonthBalancePay(request, info, openId);
if (tempBean.weixinResponse == null) {
return JsonResult.getFailResultAndLog("发起支付失败", LOG, logPrefix);
}
// Map config = weixinService.getPayConfig(wxAccessConf, tempBean.weixinResponse.getPrepay_id());
// LOG.debug(logPrefix + "前端需要的支付参数config=" + config);
WxResp wxResp = getPayConfig(tempBean.weixinOrder, wxAccessConf, tempBean.weixinResponse);
return JsonResult.getSuccessResultByData(wxResp);
}
public static class TempBean {
public WeixinOrderDTO weixinOrder;
public WeixinResponseDTO weixinResponse;
}
/**
* 微信支付下单
*/
public String sendOrder(WeixinOrderDTO weixinOrder, String key) {
String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
Map<String, String> map = new TreeMap<String, String>();
StringBuffer sb = new StringBuffer();
sb.append("" );
sb.append(" + weixinOrder.getAppId() + "]]> ");
if (StringUtils.isNotBlank(weixinOrder.getBody())) {
sb.append(" + weixinOrder.getBody() + "]]>");
map.put("body", weixinOrder.getBody());
}
sb.append(" + weixinOrder.getMachId() + "]]> ");
sb.append(" + weixinOrder.getNonceStr() + "]]> ");
sb.append(" + weixinOrder.getNotifyUrl() + "]]> ");
if(!StringUtils.isEmpty(weixinOrder.getOpenId())){
sb.append(" + weixinOrder.getOpenId() + "]]> ");
}
sb.append(" + weixinOrder.getOutTradeNo() + "]]> ");
sb.append(" + weixinOrder.getSpbillCreateIp() + "]]> ");
sb.append(" + weixinOrder.getTotalFee() + "]]> ");
sb.append(" + weixinOrder.getTradeType() + "]]> ");
map.put("appid", weixinOrder.getAppId());
map.put("mch_id", weixinOrder.getMachId());
map.put("nonce_str", weixinOrder.getNonceStr());
map.put("notify_url", weixinOrder.getNotifyUrl());
if(!StringUtils.isEmpty(weixinOrder.getOpenId())){
map.put("openid", weixinOrder.getOpenId());
}
map.put("out_trade_no", weixinOrder.getOutTradeNo());
map.put("spbill_create_ip", weixinOrder.getSpbillCreateIp() + "");
map.put("total_fee", weixinOrder.getTotalFee() + "");
map.put("trade_type", weixinOrder.getTradeType());
String sign = getSign(map, key);
sb.append(" + sign + "]]> ");
sb.append("");
String str = null;
log.debug("url:" + url + "xml:" + sb.toString());
try {
str = HttpClientUtil.postByBody(url, sb.toString(), "text/xml;charset=utf-8");
} catch (HttpException e) {
log.error(e.getMessage(), e);
e.printStackTrace();
} catch (IOException e) {
log.error(e.getMessage(), e);
e.printStackTrace();
}
return str;
}
/**
* 下单返回结果是否合法
*
* @param weixinResponse
* @param apiKey
* @return
*/
public boolean validateResponseSign(WeixinResponseDTO weixinResponse, String apiKey) {
Map<String, String> map = new TreeMap<String, String>();
if (StringUtils.isNotBlank(weixinResponse.getAppid())) {
map.put("appid", weixinResponse.getAppid());
}
if (StringUtils.isNotBlank(weixinResponse.getMch_id())) {
map.put("mch_id", weixinResponse.getMch_id());
}
if (StringUtils.isNotBlank(weixinResponse.getNonce_str())) {
map.put("nonce_str", weixinResponse.getNonce_str());
}
if (StringUtils.isNotBlank(weixinResponse.getPrepay_id())) {
map.put("prepay_id", weixinResponse.getPrepay_id());
}
if (StringUtils.isNotBlank(weixinResponse.getResult_code())) {
map.put("result_code", weixinResponse.getResult_code());
}
if (StringUtils.isNotBlank(weixinResponse.getReturn_code())) {
map.put("return_code", weixinResponse.getReturn_code());
}
if (StringUtils.isNotBlank(weixinResponse.getTrade_type())) {
map.put("trade_type", weixinResponse.getTrade_type());
}
if (StringUtils.isNotBlank(weixinResponse.getReturn_msg())) {
map.put("return_msg", weixinResponse.getReturn_msg());
}
if (StringUtils.isNotBlank(weixinResponse.getCode_url())) {
map.put("code_url", weixinResponse.getCode_url());
}
if (StringUtils.isNotBlank(weixinResponse.getMweb_url())) {
map.put("mweb_url", weixinResponse.getMweb_url());
}
if (StringUtils.isBlank(weixinResponse.getSign())) {
return false;
}
String sign = getSign(map, apiKey);
log.debug("-----------对比后的sign1111" + sign);
return sign.equals(weixinResponse.getSign());
}
/**
* 账单结算微信二维码支付-微信统一下单
* @param partnerId,合作伙伴id,整数,必填
* @param month 结算月份,yyyy-mm,必填
* @param payMoney 交易金额,单位元,必填
* @param remark 备注,非必填
* @return 二维码图片base64数据
* @author tangzhichao 20200922 新增
*/
public TempBean pay(HttpServletRequest request, WxPayMonthBalanceInfo info, String openId) {
TempBean tempBean = new TempBean();
WxAccessConf wxConfInfo = getSelfWxAccessConf();
String outTradeNo = WxPayMonthBalanceOrder.genOutTradeNo(info.getType());
LOG.debug("微信统一下单>>微信支付流水单号:" + outTradeNo + ",InfoId:" + info.getInfoId());
WxPayMonthBalanceOrder o = insertWxPayMonthBalanceOrder(request, wxConfInfo, info, openId, outTradeNo);
WeixinOrderDTO order = new WeixinOrderDTO();
order.setAppId(o.getAppId());
order.setBody(getOrderName(info));
order.setOutTradeNo(o.getOutTradeNo());
// 商户号 必填
order.setMachId(wxConfInfo.getWxMerchantNo());
order.setNonceStr(UUID.randomUUID().toString().replaceAll("-", ""));
String notifyUrl = wxConfInfo.getAuthDomain() + "/fmp-app/weixin/balancePayNotify.ws";
order.setNotifyUrl(notifyUrl);
order.setOpenId(o.getOpenId());
order.setTotalFee(new BigDecimal(o.getTotalFee()).intValue());
order.setTradeType(o.getTradeType());
order.setSpbillCreateIp(o.getSpbillCreateIp());
tempBean.weixinOrder = order;
String str = sendOrder(order, wxConfInfo.getApiKey());
LOG.debug("微信统一下单>>微信返回数据:" + str);
if (StringUtils.isBlank(str)) {
LOG.error("微信统一下单>>微信统一下单失败,微信未返回数据");
return tempBean;
}
XStream xs = new XStream(new DomDriver());
xs.alias("xml", WeixinResponseDTO.class);
WeixinResponseDTO weixinResponse = (WeixinResponseDTO) xs.fromXML(str);
if (weixinResponse == null) {
LOG.error("微信统一下单>>解析微信返回数据失败");
return tempBean;
}
if (StringUtils.isBlank(weixinResponse.getResult_code()) || StringUtils.isBlank(weixinResponse.getReturn_code()) || !weixinResponse.getResult_code().equals("SUCCESS")
|| !weixinResponse.getReturn_code().equals("SUCCESS")) {
LOG.error("微信统一下单>>微信返回数据return_code为失败");
return tempBean;
}
boolean flag = validateResponseSign(weixinResponse, wxConfInfo.getApiKey());
if (!flag) {
LOG.error("微信统一下单>>微信返回数据apikey校验失败");
return tempBean;
}
String prepay_id = weixinResponse.getPrepay_id();
LOG.debug("微信统一下单>>prepay_id:" + prepay_id);
if (!Utils.isEmptyTrim(prepay_id)) {
tempBean.weixinResponse = weixinResponse;
updateWxPayOrderStatus(o.getOrderId(), WxPayMonthBalanceOrder.status_2);
}
return tempBean;
}
/**
* 账单结算微信支付-支付回调
* @param body 微信传递的消息体
* @author tangzhichao 20200922 新增
*/
@RequestMapping(value = "/balancePayNotify.ws")
public void balancePayNotify(HttpServletRequest request, HttpServletResponse resp) throws IOException {
LOG.debug("账单结算微信二维码支付---支付回调...");
try {
String param = WebUtil.getParams(request);
if (StringUtils.isBlank(param)) {
LOG.error("支付回调>>>回调信息为空");
failByCallback(resp);
return;
}
XStream xs = new XStream(new DomDriver());
xs.alias("xml", WeChatBuyPostDTO.class);
WeChatBuyPostDTO weChatBuyPost = (WeChatBuyPostDTO) xs.fromXML(param);
if (weChatBuyPost == null) {
LOG.error("支付回调>>>回调信息解析失败");
failByCallback(resp);
return;
}
String outTradeNo = weChatBuyPost.getOut_trade_no();
if (Utils.isEmptyTrim(outTradeNo)) {
LOG.error("支付回调>>>回调信息out_trade_no为空");
failByCallback(resp);
return;
}
LOG.debug("支付回调>>>订单Id:{}", outTradeNo);
WxPayMonthBalanceOrder wxPayMonthBalanceOrder = wxPayMonthBalanceOrderMapper.selectByOutTradeNo(outTradeNo);
if (wxPayMonthBalanceOrder == null) {
LOG.error("支付回调>>>未找到订单号" + outTradeNo);
failByCallback(resp);
return;
}
if (StringUtils.isBlank(weChatBuyPost.getResult_code()) || StringUtils.isBlank(weChatBuyPost.getReturn_code()) || !weChatBuyPost.getResult_code().equals("SUCCESS")) {
LOG.error("支付回调>>>回调信息result_code返回失败,具体信息:{}", JSONObject.toJSONString(weChatBuyPost));
failAndUp(resp,wxPayMonthBalanceOrder, weChatBuyPost);
return;
}
WxAccessConf wxConfInfo = weixinService.getSelfWxAccessConf();
if (!weiXinAuthManager.verifySign(param, wxConfInfo.getApiKey())) {
LOG.error("支付回调>>>回调信息apikey校验失败");
failAndUp(resp,wxPayMonthBalanceOrder, weChatBuyPost);
return;
}
if (wxPayMonthBalanceOrder.getInfoId() == null) {
LOG.error("支付回调>>>未找到订单所属信息" + outTradeNo);
failAndUp(resp,wxPayMonthBalanceOrder, weChatBuyPost);
return;
}
LOG.debug("支付回调>>>debug-准备查询info>>>"+wxPayMonthBalanceOrder.getInfoId());
WxPayMonthBalanceInfo wxPayMonthBalanceInfo = wxPayMonthBalanceInfoMapper.selectByPrimaryKey(wxPayMonthBalanceOrder.getInfoId());
if (wxPayMonthBalanceInfo == null) {
LOG.error("支付回调>>>未找到所属信息" + wxPayMonthBalanceOrder.getInfoId());
failAndUp(resp,wxPayMonthBalanceOrder, weChatBuyPost);
return;
}
LOG.debug("支付回调>>>debug-判断status>>>"+wxPayMonthBalanceOrder.getStatus());
if (WxPayMonthBalanceOrder.status_2.equals(wxPayMonthBalanceOrder.getStatus())) {
LOG.debug("支付回调>>>debug-判断type>>>"+wxPayMonthBalanceInfo.getType());
if (WxPayMonthBalanceInfo.type_10.equals(wxPayMonthBalanceInfo.getType())||WxPayMonthBalanceInfo.type_11.equals(wxPayMonthBalanceInfo.getType())) {
LOG.debug("支付回调>>>debug-准备更新合作伙伴账户余额>>>"+weChatBuyPost.getTransaction_id());
weixinService.updatePartnerInfo(wxPayMonthBalanceOrder, wxPayMonthBalanceInfo, weChatBuyPost.getTransaction_id());
} else if (WxPayMonthBalanceInfo.type_20.equals(wxPayMonthBalanceInfo.getType())||WxPayMonthBalanceInfo.type_21.equals(wxPayMonthBalanceInfo.getType())) {
LOG.debug("支付回调>>>debug-准备更新客户账户余额>>>"+weChatBuyPost.getTransaction_id());
weixinService.updateCustomerInfo(wxPayMonthBalanceOrder, wxPayMonthBalanceInfo, weChatBuyPost.getTransaction_id());
} else {
LOG.error("支付回调>>>微信支付流水记录类型不匹配");
failAndUp(resp,wxPayMonthBalanceOrder, weChatBuyPost);
return;
}
} else {
LOG.debug("支付回调>>>重复回调...");
}
LOG.debug("支付回调>>>微信回调成功");
} catch (Exception e) {
LOG.error("支付回调>>>异常", e);
failByCallback(resp);
return;
}
LOG.debug("支付回调>>>debug-响应微信文件流>>>");
super.output(resp, "text/xml", "utf-8", " ");
}
private void failByCallback(HttpServletResponse resp) throws IOException {
super.output(resp, "text/xml", "utf-8", " ");
}
private void failAndUp(HttpServletResponse resp,WxPayMonthBalanceOrder wxPayMonthBalanceOrder,WeChatBuyPostDTO weChatBuyPost) throws IOException {
weixinService.updateWxPayOrderStatusByCallback(wxPayMonthBalanceOrder.getOrderId(), WxPayMonthBalanceOrder.status_4, weChatBuyPost.getTransaction_id());
failByCallback(resp);
}