| @@ -24,6 +24,8 @@ import org.springframework.web.bind.annotation.ResponseBody; | |||
| import org.springframework.web.bind.annotation.RestController; | |||
| import javax.servlet.http.HttpServletRequest; | |||
| import javax.servlet.http.HttpServletResponse; | |||
| import java.io.ByteArrayOutputStream; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| @@ -117,18 +119,16 @@ public class WxPayController extends BaseController { | |||
| /** | |||
| * 微信支付3.0版本 | |||
| * 微信支付3.0版本 | |||
| * 普通支付 https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_2_11.shtml | |||
| * 合单支付 https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_3_13.shtml | |||
| * @return 接收微信异步通知 | |||
| * @throws Exception 可能产生的任何异常 | |||
| */ | |||
| @RequestMapping(value = "/pay/v3", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) | |||
| @ResponseBody | |||
| public String _payV3Notify(HttpServletRequest request) throws IOException, JDOMException { | |||
| logger.info("[" +getIpAddr() + "]微信支付回调"); | |||
| SortedMap resultMap = new TreeMap(); | |||
| resultMap.put("return_code", "SUCCESS"); | |||
| resultMap.put("return_msg", "OK"); | |||
| return XmlUtil.getRequestXml(resultMap); | |||
| public void _payV3Notify(HttpServletRequest request,HttpServletResponse response) throws IOException, JDOMException { | |||
| response.setStatus(200); | |||
| } | |||
| /** | |||
| @@ -75,33 +75,78 @@ public class WxPayOrder extends TenantEntity { | |||
| // private String storeId; | |||
| @io.swagger.annotations.ApiModelProperty(value="子订单分账金额json",name="childOrderShare") | |||
| private String childOrderShare; | |||
| @io.swagger.annotations.ApiModelProperty(value="支付失败原因",name="failReason") | |||
| private String failReason; | |||
| @io.swagger.annotations.ApiModelProperty(value="支付后结果来源(0:callback, 1:query)",name="payEndFrom") | |||
| private Integer payEndFrom; | |||
| @io.swagger.annotations.ApiModelProperty(value="是否为组合订单,1-是 0-不是",name="composeOrder") | |||
| private Integer composeOrder; | |||
| @io.swagger.annotations.ApiModelProperty(value="支付后结果来源(0:inside, 1:POS支付)",name="payFrom") | |||
| private Integer payFrom; | |||
| @io.swagger.annotations.ApiModelProperty(value="抖音支付实际支付方式--1-微信支付,2-支付宝支付,10-抖音支付",name="ttPayWay") | |||
| private Integer ttPayWay; | |||
| @io.swagger.annotations.ApiModelProperty(value="支付订单号,来源于POS, inside时,填写couponOrderId",name="posPayOrderId") | |||
| private Long posPayOrderId; | |||
| @io.swagger.annotations.ApiModelProperty(value="支付订单创建时间,来源于POS",name="posPayOrderTime") | |||
| private Long posPayOrderTime; | |||
| @io.swagger.annotations.ApiModelProperty(value="支付方式: 0微信;1支付宝;2现金;3会员折扣;4优惠券;5预付卡;6银行卡,来源于POS",name="posPaymentType") | |||
| private Integer posPaymentType; | |||
| @io.swagger.annotations.ApiModelProperty(value="支付订单流水号, 来源于POS, 第三方(微信、支付宝、富茂预付卡)支付订单流水号,富茂优惠券ID,现金和富茂会员折扣时为空",name="posPayOrderNo") | |||
| private String posPayOrderNo; | |||
| @io.swagger.annotations.ApiModelProperty(value="POS支付描述",name="posPayDes") | |||
| private String posPayDes; | |||
| public WxComposeChildOrderShare getChildOrderShare(Long wxOrderId) { | |||
| if (StringUtils.isBlank(this.childOrderShare)) { | |||
| return new WxComposeChildOrderShare(this.payAmount, this.shareAmount, this.rateAmount,null,null,null,null); | |||
| return new WxComposeChildOrderShare(this.payAmount, this.shareAmount, this.rateAmount,null,null,null,null,null); | |||
| } | |||
| Map childs = JSON.parseObject(this.childOrderShare, Map.class); | |||
| JSONObject childOrderShare = (JSONObject) childs.get(String.valueOf(wxOrderId)); | |||
| if (null != childOrderShare) { | |||
| return new WxComposeChildOrderShare(childOrderShare.getInteger("realPayMent"), childOrderShare.getInteger("shareAmount"), childOrderShare.getInteger("rateAmount"), | |||
| childOrderShare.getInteger("realRateAmount"), childOrderShare.getInteger("commissionAmount"), | |||
| childOrderShare.getLong("merchantId"),childOrderShare.getString("merchantUid")); | |||
| childOrderShare.getLong("merchantId"),childOrderShare.getString("merchantUid"),childOrderShare.getLong("orderId")); | |||
| } | |||
| return null; | |||
| } | |||
| public WxComposeChildOrderShare getSingleChildOrderShare() { | |||
| private List<WxComposeChildOrderShare> getAllChilds(Integer index) { | |||
| if (StringUtils.isBlank(this.childOrderShare)) { | |||
| return new WxComposeChildOrderShare(this.payAmount, this.shareAmount, this.rateAmount,null,null,null,null); | |||
| return null; | |||
| } | |||
| Map childs = JSON.parseObject(this.childOrderShare, Map.class); | |||
| List<WxComposeChildOrderShare> childList = new ArrayList<WxComposeChildOrderShare>(); | |||
| int _index = 0; | |||
| for (Iterator<String> it = childs.keySet().iterator();it.hasNext();) { | |||
| JSONObject childOrderShare = (JSONObject) childs.get(it.hasNext()); | |||
| return new WxComposeChildOrderShare(childOrderShare.getInteger("realPayMent"), childOrderShare.getInteger("shareAmount"), childOrderShare.getInteger("rateAmount"), | |||
| WxComposeChildOrderShare child = new WxComposeChildOrderShare(childOrderShare.getInteger("realPayMent"), childOrderShare.getInteger("shareAmount"), childOrderShare.getInteger("rateAmount"), | |||
| childOrderShare.getInteger("realRateAmount"), childOrderShare.getInteger("commissionAmount"), | |||
| childOrderShare.getLong("merchantId"),childOrderShare.getString("merchantUid")); | |||
| childOrderShare.getLong("merchantId"),childOrderShare.getString("merchantUid"),childOrderShare.getLong("orderId")); | |||
| childList.add(child); | |||
| if (null != index && index.intValue() == _index) { | |||
| return childList; | |||
| } | |||
| _index ++; | |||
| } | |||
| return null; | |||
| if (childList.size() <= 0 ) { | |||
| return null; | |||
| } | |||
| return childList; | |||
| } | |||
| public WxComposeChildOrderShare getSingleChildOrderShare() { | |||
| List<WxComposeChildOrderShare> childs = getAllChilds(0); | |||
| if (null == childs) { | |||
| return null; | |||
| } | |||
| return childs.get(0); | |||
| } | |||
| public List<WxComposeChildOrderShare> getAllChilds() { | |||
| return getAllChilds(null); | |||
| } | |||
| public boolean isMulity() { | |||
| @@ -115,30 +160,6 @@ public class WxPayOrder extends TenantEntity { | |||
| } | |||
| return false; | |||
| } | |||
| @io.swagger.annotations.ApiModelProperty(value="支付失败原因",name="failReason") | |||
| private String failReason; | |||
| @io.swagger.annotations.ApiModelProperty(value="支付后结果来源(0:callback, 1:query)",name="payEndFrom") | |||
| private Integer payEndFrom; | |||
| @io.swagger.annotations.ApiModelProperty(value="是否为组合订单,1-是 0-不是",name="composeOrder") | |||
| private Integer composeOrder; | |||
| @io.swagger.annotations.ApiModelProperty(value="支付后结果来源(0:inside, 1:POS支付)",name="payFrom") | |||
| private Integer payFrom; | |||
| @io.swagger.annotations.ApiModelProperty(value="抖音支付实际支付方式--1-微信支付,2-支付宝支付,10-抖音支付",name="ttPayWay") | |||
| private Integer ttPayWay; | |||
| @io.swagger.annotations.ApiModelProperty(value="支付订单号,来源于POS, inside时,填写couponOrderId",name="posPayOrderId") | |||
| private Long posPayOrderId; | |||
| @io.swagger.annotations.ApiModelProperty(value="支付订单创建时间,来源于POS",name="posPayOrderTime") | |||
| private Long posPayOrderTime; | |||
| @io.swagger.annotations.ApiModelProperty(value="支付方式: 0微信;1支付宝;2现金;3会员折扣;4优惠券;5预付卡;6银行卡,来源于POS",name="posPaymentType") | |||
| private Integer posPaymentType; | |||
| @io.swagger.annotations.ApiModelProperty(value="支付订单流水号, 来源于POS, 第三方(微信、支付宝、富茂预付卡)支付订单流水号,富茂优惠券ID,现金和富茂会员折扣时为空",name="posPayOrderNo") | |||
| private String posPayOrderNo; | |||
| @io.swagger.annotations.ApiModelProperty(value="POS支付描述",name="posPayDes") | |||
| private String posPayDes; | |||
| } | |||
| @@ -10,6 +10,7 @@ import com.aliyun.openservices.shade.org.apache.commons.lang3.StringUtils; | |||
| import com.github.binarywang.wxpay.exception.WxPayException; | |||
| import com.github.binarywang.wxpay.service.WxPayService; | |||
| import com.github.binarywang.wxpay.v3.util.RsaCryptoUtil; | |||
| import com.iformall.service.pay.service.pay.wx.v3.entity.CombineCloseReq; | |||
| import com.iformall.service.pay.service.pay.wx.v3.entity.CombinePayCommonMiniAppReq; | |||
| import com.iformall.service.pay.service.pay.wx.v3.entity.PayCommonMiniAppReq; | |||
| import com.iformall.service.pay.service.pay.wx.v3.entity.PayQueryReq; | |||
| @@ -28,11 +29,14 @@ public class WxPayV3 { | |||
| private static final String PAY_COMMON_MINIAPP_URL = "https://api.mch.weixin.qq.com/v3/pay/partner/transactions/jsapi"; | |||
| //电商收付通-普通支付-查询 | |||
| private static final String PAY_COMMON_QUERY_URL = "https://api.mch.weixin.qq.com/v3/pay/partner/transactions/out-trade-no/%s"; | |||
| //电商收付通-普合单支付-小程序下单 | |||
| //电商收付通-合单支付-小程序下单 | |||
| private static final String PAY_COMBINE_MINIAPP_URL = "https://api.mch.weixin.qq.com/v3/combine-transactions/jsapi"; | |||
| //电商收付通-合单支付-查询 | |||
| private static final String PAY_COMBINE_QUERY_URL = "https://api.mch.weixin.qq.com/v3/combine-transactions/out-trade-no/%s"; | |||
| //电商收付通-普通支付-关闭订单 | |||
| private static final String PAY_COMMON_CLOSE_ORDER_URL = "https://api.mch.weixin.qq.com/v3/pay/partner/transactions/out-trade-no/%s/close"; | |||
| //电商收付通-合单支付-关闭订单 | |||
| private static final String PAY_COMBINE_CLOSE_ORDER_URL = "https://api.mch.weixin.qq.com/v3/combine-transactions/out-trade-no/%s/close"; | |||
| private WxPayV3() { | |||
| } | |||
| @@ -114,4 +118,21 @@ public class WxPayV3 { | |||
| } | |||
| /** | |||
| * 电商收付通-普通支付-关闭 https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_3_11.shtml | |||
| * @throws WxPayException | |||
| */ | |||
| public static String payCommonClose(WxPayService payService,PayQueryReq payQuery) throws WxPayException { | |||
| return payService.postV3WithWechatpaySerial(String.format(PAY_COMMON_CLOSE_ORDER_URL, payQuery.getOut_trade_no()), JSON.toJSONString(payQuery)); | |||
| } | |||
| /** | |||
| * 电商收付通-合单支付-关闭 https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_3_12.shtml | |||
| * @throws WxPayException | |||
| */ | |||
| public static String payCombineClose(WxPayService payService,CombineCloseReq closeOrder) throws WxPayException { | |||
| return payService.postV3WithWechatpaySerial(String.format(PAY_COMBINE_CLOSE_ORDER_URL, closeOrder.getCombine_out_trade_no()), JSON.toJSONString(closeOrder)); | |||
| } | |||
| } | |||
| @@ -466,7 +466,7 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { | |||
| logger.info("佣金明细"+ JSON.toJSONString(oShareAmount)); | |||
| share_amount += oShareAmount.getShareAmount(); | |||
| rate_amount += oShareAmount.getRateAmount(); | |||
| childShares.put(String.valueOf(o.getId()), new WxComposeChildOrderShare(oShareAmount,merchant_id,merchant_uid)); | |||
| childShares.put(String.valueOf(o.getId()), new WxComposeChildOrderShare(oShareAmount,merchant_id,merchant_uid,o.getId())); | |||
| } | |||
| record.setShareAmount(share_amount); | |||
| record.setRateAmount(rate_amount); | |||
| @@ -12,7 +12,7 @@ import lombok.Data; | |||
| public class WxComposeChildOrderShare { | |||
| public WxComposeChildOrderShare(Integer realPayMent,Integer shareAmount,Integer rateAmount,Integer realRateAmount,Integer commissionAmount, | |||
| Long merchantId,String merchantUid) { | |||
| Long merchantId,String merchantUid,Long orderId) { | |||
| this.realPayMent = realPayMent; | |||
| this.shareAmount = shareAmount; | |||
| this.rateAmount = rateAmount; | |||
| @@ -20,9 +20,10 @@ public class WxComposeChildOrderShare { | |||
| this.commissionAmount = commissionAmount; | |||
| this.merchantId = merchantId; | |||
| this.merchantUid = merchantUid; | |||
| this.orderId = orderId; | |||
| } | |||
| public WxComposeChildOrderShare(PayShareCalculateAmount shareCalculateAmount,Long merchantId,String merchantUid) { | |||
| public WxComposeChildOrderShare(PayShareCalculateAmount shareCalculateAmount,Long merchantId,String merchantUid,Long orderId) { | |||
| this.realPayMent = shareCalculateAmount.getPayAmount(); | |||
| this.shareAmount = shareCalculateAmount.getShareAmount(); | |||
| this.rateAmount = shareCalculateAmount.getRateAmount(); | |||
| @@ -30,8 +31,10 @@ public class WxComposeChildOrderShare { | |||
| this.commissionAmount = shareCalculateAmount.getCommissionAmount(); | |||
| this.merchantId = merchantId; | |||
| this.merchantUid = merchantUid; | |||
| this.orderId = orderId; | |||
| } | |||
| private Long orderId;//订单编号,v3要用 | |||
| private Integer realPayMent;//付款金额 | |||
| private Integer shareAmount;//分账的钱(分给商户的) | |||
| @@ -0,0 +1,11 @@ | |||
| package com.iformall.service.pay.service.pay.wx.v3.entity; | |||
| import lombok.Data; | |||
| @Data | |||
| public class CombineCloseItemOrder { | |||
| private String mchid;//子单发起方商户号,必须与发起方appid有绑定关系 | |||
| private String out_trade_no;//子单商户订单号 | |||
| private String sub_mchid;//二级商户号,服务商子商户的商户号,被合单方。直连商户不用传二级商户号 | |||
| } | |||
| @@ -0,0 +1,39 @@ | |||
| package com.iformall.service.pay.service.pay.wx.v3.entity; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| import com.alibaba.fastjson.annotation.JSONField; | |||
| import com.iformall.domain.po.WxPayAccount; | |||
| import com.iformall.domain.po.WxPayOrder; | |||
| import com.iformall.service.order.entity.WxComposeChildOrderShare; | |||
| import lombok.Data; | |||
| @Data | |||
| public class CombineCloseReq { | |||
| private String combine_appid;//合单发起方的appid | |||
| @JSONField(serialize = false) | |||
| private String combine_out_trade_no;//不放到body | |||
| private List<CombineCloseItemOrder> sub_orders; | |||
| public void initSubOrders(WxPayAccount payAccount,WxPayOrder payOrder) { | |||
| List<WxComposeChildOrderShare> childs = payOrder.getAllChilds(); | |||
| if (null != childs) { | |||
| List<CombineCloseItemOrder> suborders = new ArrayList<CombineCloseItemOrder>(); | |||
| for (WxComposeChildOrderShare child : childs) { | |||
| CombineCloseItemOrder ccio = new CombineCloseItemOrder(); | |||
| ccio.setMchid(payAccount.getMchId()); | |||
| ccio.setSub_mchid(child.getMerchantUid()); | |||
| ccio.setOut_trade_no(String.valueOf(child.getOrderId())); | |||
| suborders.add(ccio); | |||
| } | |||
| if (suborders.size() > 0) { | |||
| this.setSub_orders(suborders); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -1,5 +1,7 @@ | |||
| package com.iformall.service.pay.service.pay.wx.v3.entity; | |||
| import com.alibaba.fastjson.annotation.JSONField; | |||
| import lombok.Data; | |||
| @Data | |||
| @@ -7,6 +9,8 @@ public class PayQueryReq { | |||
| private String sp_mchid;//服务商户号。 | |||
| private String sub_mchid;//二级商户号 | |||
| @JSONField(serialize = false) | |||
| private String out_trade_no;//商户订单号 | |||
| } | |||
| @@ -38,6 +38,7 @@ import com.iformall.service.pay.service.pay.CDrivingPayService; | |||
| import com.iformall.service.pay.service.pay.entity.PayAdapterResult; | |||
| import com.iformall.service.pay.service.pay.entity.PayQueryAdapterResult; | |||
| import com.iformall.service.pay.service.pay.wx.v2.BaseWxPayAdapterService; | |||
| import com.iformall.service.pay.service.pay.wx.v3.entity.CombineCloseReq; | |||
| import com.iformall.service.pay.service.pay.wx.v3.entity.CombineItemOrder; | |||
| import com.iformall.service.pay.service.pay.wx.v3.entity.CombinePayCommonMiniAppReq; | |||
| import com.iformall.service.pay.service.pay.wx.v3.entity.CombinePayerReq; | |||
| @@ -200,8 +201,10 @@ public class WxMiniAppPayV3AdapterService implements CDrivingPayService{ | |||
| private PayQueryAdapterResult getPayCombineQueryResult(String response) { | |||
| JSONObject result = JSON.parseObject(response); | |||
| //只有各子订单的状态,没有统一的状态,暂时无法处理 | |||
| //TODO 只有各子订单的状态,没有统一的状态,暂时无法处理 | |||
| JSONArray subOrders = result.getJSONArray("sub_orders"); | |||
| ///######待处理 | |||
| String transtionId = result.getString("transaction_id"); | |||
| String tradeState = result.getString("trade_state"); | |||
| String tradeStateDesc = result.getString("trade_state_desc"); | |||
| @@ -254,8 +257,25 @@ public class WxMiniAppPayV3AdapterService implements CDrivingPayService{ | |||
| @Override | |||
| public PayAdapterResult payOrderClose(WxAppinfo appInfo, WxPayOrder record,WxPayAccount payAccount) throws Exception { | |||
| //return super.closeOrder(appInfo, record, payAccount); | |||
| return null; | |||
| WxPayService payService = maUtil.getWxPayService(appInfo, payAccount); | |||
| if (!record.isMulity()) { | |||
| PayQueryReq req = new PayQueryReq(); | |||
| req.setSp_mchid(payAccount.getMchId()); | |||
| req.setSub_mchid(record.getSingleChildOrderShare().getMerchantUid()); | |||
| req.setOut_trade_no(String.valueOf(record.getId())); | |||
| WxPayV3.payCommonClose(payService, req); | |||
| return new PayAdapterResult(true, "close success", req, null); | |||
| }else { | |||
| throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(),"因电商收付通合单查询无法处理,暂时不支持合单支付关闭"); | |||
| // CombineCloseReq req = new CombineCloseReq(); | |||
| // req.setCombine_appid(appInfo.getAppId()); | |||
| // req.setCombine_out_trade_no(String.valueOf(record.getId())); | |||
| // req.initSubOrders(payAccount, record); | |||
| // | |||
| // String response = WxPayV3.payCombineClose(payService, req); | |||
| // return new PayAdapterResult(true, "close success", req, null); | |||
| } | |||
| } | |||
| @Override | |||