Selaa lähdekoodia

add pay v3

release_toaliyun_real
zhengfangyuan 3 vuotta sitten
vanhempi
commit
20033f9e03
24 muutettua tiedostoa jossa 2618 lisäystä ja 104 poistoa
  1. +2
    -0
      mallinkAdmin/src/main/resources/db/migration/V2022080800001_pay_v3.sql
  2. +1
    -1
      mallinkCallback/src/main/java/com/iformall/controller/callback/TtPayController.java
  3. +1
    -1
      mallinkSchedule/src/main/java/com/iformall/schedule/CashOutSchedule.java
  4. +1
    -1
      mallinkSchedule/src/main/java/com/iformall/schedule/OrderExpiringSchedule.java
  5. +3
    -1
      mallinkService/src/main/java/com/iformall/domain/po/WxPayAccount.java
  6. +37
    -0
      mallinkService/src/main/java/com/iformall/enums/EnumPayVersion.java
  7. +11
    -11
      mallinkService/src/main/java/com/iformall/service/impl/WxPayOrderServiceImpl.java
  8. +6
    -8
      mallinkService/src/main/java/com/iformall/service/impl/WxProfitSharingOrderServiceImpl.java
  9. +2
    -2
      mallinkService/src/main/java/com/iformall/service/impl/WxProfitSharingReceiverServiceImpl.java
  10. +6
    -6
      mallinkService/src/main/java/com/iformall/service/impl/WxRefundOrderServiceImpl.java
  11. +104
    -63
      mallinkService/src/main/java/com/iformall/service/pay/PayServiceFactory.java
  12. +1
    -1
      mallinkService/src/main/java/com/iformall/service/pay/service/cashout/wx/v2/WxCashOutAdapterService.java
  13. +500
    -0
      mallinkService/src/main/java/com/iformall/service/pay/service/cashout/wx/v3/WxCashOutV3AdapterService.java
  14. +1
    -1
      mallinkService/src/main/java/com/iformall/service/pay/service/pay/wx/v2/BaseWxPayAdapterService.java
  15. +2
    -2
      mallinkService/src/main/java/com/iformall/service/pay/service/pay/wx/v2/h5/WxH5PayService.java
  16. +2
    -2
      mallinkService/src/main/java/com/iformall/service/pay/service/pay/wx/v2/miniApp/appPay/WxMiniAppPayAdapterService.java
  17. +2
    -2
      mallinkService/src/main/java/com/iformall/service/pay/service/pay/wx/v2/miniApp/maPay/WxMiniMaPayAdapterService.java
  18. +81
    -0
      mallinkService/src/main/java/com/iformall/service/pay/service/pay/wx/v3/h5/WxH5PayV3Service.java
  19. +291
    -0
      mallinkService/src/main/java/com/iformall/service/pay/service/pay/wx/v3/miniApp/appPay/WxMiniAppPayV3AdapterService.java
  20. +275
    -0
      mallinkService/src/main/java/com/iformall/service/pay/service/pay/wx/v3/miniApp/maPay/WxMiniMaPayV3AdapterService.java
  21. +1
    -1
      mallinkService/src/main/java/com/iformall/service/pay/service/refund/wx/v2/WxRefundAdapterService.java
  22. +685
    -0
      mallinkService/src/main/java/com/iformall/service/pay/service/refund/wx/v3/WxRefundV3AdapterService.java
  23. +1
    -1
      mallinkService/src/main/java/com/iformall/service/pay/service/share/wx/v2/WxPayShareService.java
  24. +602
    -0
      mallinkService/src/main/java/com/iformall/service/pay/service/share/wx/v3/WxPayShareV3Service.java

+ 2
- 0
mallinkAdmin/src/main/resources/db/migration/V2022080800001_pay_v3.sql Näytä tiedosto

@@ -0,0 +1,2 @@
ALTER TABLE `mallink`.`wx_pay_account`
ADD COLUMN `pay_version` smallint(1) COMMENT '支付版本' AFTER `open_pay`;

+ 1
- 1
mallinkCallback/src/main/java/com/iformall/controller/callback/TtPayController.java Näytä tiedosto

@@ -169,7 +169,7 @@ public class TtPayController extends BaseController {
logger.error("未找到订单"+orderId);
resultMap.put("err_tips","未找到订单");
}else{
PayQueryAdapterResult queryResult = payServiceFactory.getPayAdapterService(wxpayOrder.getPayVendor()).queryPayStatus(wxpayOrder, appinfo, payAccount);
PayQueryAdapterResult queryResult = payServiceFactory.getPayAdapterService(wxpayOrder.getPayVendor(),payAccount.getPayVersion()).queryPayStatus(wxpayOrder, appinfo, payAccount);
if (EnumPayStatus.PAY_STATUS_SUCCESS.getCode() == queryResult.getCode()) {
WxComposeOrder composeOrder = orderFactory.getOrderAdapterService(wxpayOrder.getComposeOrder()).getComposeOrder(wxpayOrder.getOrderId(), wxpayOrder.getTenantId());
wxPayOrderService.handleSuccessOrder(wxpayOrder, composeOrder, queryResult, true,false);


+ 1
- 1
mallinkSchedule/src/main/java/com/iformall/schedule/CashOutSchedule.java Näytä tiedosto

@@ -124,7 +124,7 @@ public class CashOutSchedule {
if (null == payAccount) {
return;
}
CashOutAdapterResult result = payServiceFactory.getCashOutAdapterService(payWay.getCode()).queryCashOut(appInfo, payAccount, cashout);
CashOutAdapterResult result = payServiceFactory.getCashOutAdapterService(payWay.getCode(),payAccount.getPayVersion()).queryCashOut(appInfo, payAccount, cashout);
cashout.setUpdateDate(new Date());
if (result.isSuccess()) {
cashout.setStatus(EnumCashOutStatus.SUCCESS.getCode());


+ 1
- 1
mallinkSchedule/src/main/java/com/iformall/schedule/OrderExpiringSchedule.java Näytä tiedosto

@@ -316,7 +316,7 @@ public class OrderExpiringSchedule {
}
//Map<String, String> retMap = WxPayOrderServiceHelper.wxOrderPayStatusMap(wxpayOrder, order, appInfo, payAccount);
//int status = WxPayOrderServiceHelper.getPayStatusFromMap(retMap, wxpayOrder.getPayOrderNo());
PayQueryAdapterResult payResult = payServiceFactory.getPayAdapterService(wxpayOrder.getPayVendor()).queryPayStatus(wxpayOrder, appInfo, payAccount);
PayQueryAdapterResult payResult = payServiceFactory.getPayAdapterService(wxpayOrder.getPayVendor(),payAccount.getPayVersion()).queryPayStatus(wxpayOrder, appInfo, payAccount);
//如果是支付成功,并且需要重试成功流程,
if (EnumPayStatus.PAY_STATUS_SUCCESS.getCode().intValue() == payResult.getCode()) {
if (autoReHandle) {


+ 3
- 1
mallinkService/src/main/java/com/iformall/domain/po/WxPayAccount.java Näytä tiedosto

@@ -45,8 +45,10 @@ public class WxPayAccount extends TenantEntity {
private Integer type;
@io.swagger.annotations.ApiModelProperty(value="EnumPayMchType 0:总分1:直连",name="mchType")
private Integer mchType;
@io.swagger.annotations.ApiModelProperty(value="抖音用 ",name="openPay")
@io.swagger.annotations.ApiModelProperty(value="开通的支付方式。抖音用 ",name="openPay")
private String openPay;
@io.swagger.annotations.ApiModelProperty(value="支付版本 EnumPayVersion",name="payVersion")
private Integer payVersion;
@io.swagger.annotations.ApiModelProperty(value="是否开启分账(0:未开启分账1:开启分账)",name="type")
private Integer share;
@io.swagger.annotations.ApiModelProperty(value="手续费(万分之几,默认60)",name="rate")


+ 37
- 0
mallinkService/src/main/java/com/iformall/enums/EnumPayVersion.java Näytä tiedosto

@@ -0,0 +1,37 @@
package com.iformall.enums;

/**
* Created by Stormeye on 2018/08/09.
*/
public enum EnumPayVersion {

WX_PAY_V2(1, "微信支付2.0,老版本"),
WX_PAY_V3(2, "微信支付3.0,对接电商收付通"),
DY_PAY_V2(3,"抖音支付2.0,对接商品库")
;

public static EnumPayVersion getEnum(Integer code) {
for (EnumPayVersion value : values()) {
if (value.getCode().equals(code)) {
return value;
}
}
return null;
}

private Integer code;
private String name;

EnumPayVersion(Integer code, String name) {
this.code = code;
this.name = name;
}

public Integer getCode() {
return code;
}

public String getName() {
return name;
}
}

+ 11
- 11
mallinkService/src/main/java/com/iformall/service/impl/WxPayOrderServiceImpl.java Näytä tiedosto

@@ -204,8 +204,8 @@ public class WxPayOrderServiceImpl implements WxPayOrderService {
PayQueryAdapterResult queryResult = null;
int wxpaystatus = 0;
try {
queryResult = payServiceFactory.getPayAdapterService(oldRecord.getPayVendor()).queryPayStatus(oldRecord, appInfo, payAccount);
wxpaystatus = payServiceFactory.getPayAdapterService(oldRecord.getPayVendor()).queryPayStatus(queryResult, oldRecord.getPayOrderNo());
queryResult = payServiceFactory.getPayAdapterService(oldRecord.getPayVendor(),payAccount.getPayVersion()).queryPayStatus(oldRecord, appInfo, payAccount);
wxpaystatus = payServiceFactory.getPayAdapterService(oldRecord.getPayVendor(),payAccount.getPayVersion()).queryPayStatus(queryResult, oldRecord.getPayOrderNo());
} catch (Exception e) {
logger.error("pay order service handleWxOrderQuery error: " ,e);
throw new MallinkException(ErrorCode.PAY_ORDER_ERROR);
@@ -433,7 +433,7 @@ public class WxPayOrderServiceImpl implements WxPayOrderService {
record.setShare(isShare.getCode());
record.setComposeOrder(composeOrder.getComposeOrderType());
// if (isShare == EnumPayShare.YES) {
PayShareAdapterService payShareServie = payServiceFactory.getPayShareAdapterService(payWay.getCode());
PayShareAdapterService payShareServie = payServiceFactory.getPayShareAdapterService(payWay.getCode(),payAccount.getPayVersion());
// PayShareCalculateAmount recordShareAmount = payShareServie.calculateAmount(record.getPayAmount(), payAccount);
// // 分账金额
@@ -481,7 +481,7 @@ public class WxPayOrderServiceImpl implements WxPayOrderService {
}
}

PayAdapterService payAdapterService = payServiceFactory.getPayAdapterService(payWay.getCode());
PayAdapterService payAdapterService = payServiceFactory.getPayAdapterService(payWay.getCode(),payAccount.getPayVersion());

if(!isCreatePay){
PayAdapterResult payResult = payAdapterService.noCreatePay(record,composeOrder,childOrders);
@@ -613,7 +613,7 @@ public class WxPayOrderServiceImpl implements WxPayOrderService {

logger.debug("wxPayRecord md5 before:"+record.toString());
String beforemd5 = HashUtil.md5(record.toString());
PayAdapterResult payResult = payServiceFactory.getPayAdapterService(payWay.getCode()).pay(payAccount, record,composeOrder,"付款码支付",isShare,appInfo, currentDate, params);
PayAdapterResult payResult = payServiceFactory.getPayAdapterService(payWay.getCode(),payAccount.getPayVersion()).pay(payAccount, record,composeOrder,"付款码支付",isShare,appInfo, currentDate, params);
String aftermd5 = HashUtil.md5(record.toString());
if (beforemd5.equals(aftermd5)) {
logger.error("支付方式["+payWay.getCode()+"]支付接口【pay】过程中 WxPayOrder 未做更新.record:"+record.toString());
@@ -675,10 +675,10 @@ public class WxPayOrderServiceImpl implements WxPayOrderService {
}

WxAppinfo appInfo = wxAppinfoService.getCAppInfo(record,payWay.getPlat());
PayAdapterService payService = payServiceFactory.getPayAdapterService(payWay.getCode());
WxPayAccount payAccount = wxPayAccountMapper.selectById(appInfo.getPayId());
PayAdapterService payService = payServiceFactory.getPayAdapterService(payWay.getCode(),payAccount.getPayVersion());
PayQueryAdapterResult apiResult = payService.queryPayStatus(record, appInfo, payAccount);
int status = payServiceFactory.getPayAdapterService(payWay.getCode()).queryPayStatus(apiResult, record.getPayOrderNo());
int status = payServiceFactory.getPayAdapterService(payWay.getCode(),payAccount.getPayVersion()).queryPayStatus(apiResult, record.getPayOrderNo());
boolean isSuccess = true;
String msg = "";
if (status == EnumPayStatus.PAY_STATUS_REFUND.getCode().intValue()) {
@@ -747,7 +747,7 @@ public class WxPayOrderServiceImpl implements WxPayOrderService {
public ResultData payOrderClose(WxAppinfo appInfo, WxPayOrder record) {
WxPayAccount payAccount = wxPayAccountMapper.selectById(appInfo.getPayId());
try {
PayAdapterResult result = payServiceFactory.getPayAdapterService(record.getPayVendor()).payOrderClose(appInfo, record, payAccount);
PayAdapterResult result = payServiceFactory.getPayAdapterService(record.getPayVendor(),payAccount.getPayVersion()).payOrderClose(appInfo, record, payAccount);
if (result.isSuccess()) {
record.setPayOrderStatus(EnumPayStatus.PAY_STATUS_CANCEL.getCode());
}else {
@@ -784,7 +784,7 @@ public class WxPayOrderServiceImpl implements WxPayOrderService {
WxAppinfo appInfo = wxAppinfoService.getCAppInfo(record,EnumPayWay.getEnum(record.getPayVendor()).getPlat());
WxPayAccount payAccount = wxPayAccountMapper.selectById(appInfo.getPayId());
try {
PayAdapterResult result = payServiceFactory.getPayAdapterService(record.getPayVendor()).payOrderReverse(appInfo, record, payAccount);
PayAdapterResult result = payServiceFactory.getPayAdapterService(record.getPayVendor(),payAccount.getPayVersion()).payOrderReverse(appInfo, record, payAccount);
if (result.isSuccess()) {
record.setPayOrderStatus(EnumPayStatus.PAY_STATUS_REVERSE.getCode());
record.setUpdateTime(new Date());
@@ -1059,7 +1059,7 @@ public class WxPayOrderServiceImpl implements WxPayOrderService {
WxPayOrder payOrder = new WxPayOrder();
payOrder.setPayOrderNo(id.toString());
try {
return payServiceFactory.getPayAdapterService(EnumPayWay.PAY_WAY_TT.getCode()).queryPayStatus(payOrder, appInfo, payAccount);
return payServiceFactory.getPayAdapterService(EnumPayWay.PAY_WAY_TT.getCode(),payAccount.getPayVersion()).queryPayStatus(payOrder, appInfo, payAccount);
} catch (Exception e) {
return new PayQueryAdapterResult(ErrorCode.SYS_SERVER_ERROR.getCode(), e.getMessage(),null,null,null,null);
}
@@ -1350,7 +1350,7 @@ public class WxPayOrderServiceImpl implements WxPayOrderService {
// 回调未返回,主动检查支付订单状态
try {
WxPayAccount payAccount = wxPayAccountMapper.selectById(appInfo.getPayId());
int payStatus = payServiceFactory.getPayAdapterService(record.getPayVendor()).queryPayStatusCode(record, appInfo, payAccount);
int payStatus = payServiceFactory.getPayAdapterService(record.getPayVendor(),payAccount.getPayVersion()).queryPayStatusCode(record, appInfo, payAccount);
if (payStatus!=EnumPayStatus.PAY_STATUS_SUCCESS.getCode().intValue() && payStatus!=EnumPayStatus.PAY_STATUS_WAIT.getCode().intValue()) {
// 支付订单未成功,返回异常
record.setPayOrderStatus(EnumPayStatus.PAY_STATUS_FAIL.getCode());


+ 6
- 8
mallinkService/src/main/java/com/iformall/service/impl/WxProfitSharingOrderServiceImpl.java Näytä tiedosto

@@ -204,7 +204,7 @@ public class WxProfitSharingOrderServiceImpl implements WxProfitSharingOrderServ
}

PayShareResult shareResult = payServiceFactory.getPayShareAdapterService(dto.getPayWay()).haveReciversShare(appInfo, payAccount, frecord,
PayShareResult shareResult = payServiceFactory.getPayShareAdapterService(dto.getPayWay(),payAccount.getPayVersion()).haveReciversShare(appInfo, payAccount, frecord,
sharingOrder.getTransactionId(), JSONArray.parseArray(JSON.toJSONString(receivers)), EnumProfitSharingOrderType.getEnum(sharingOrder.getType()));
WxProfitSharingOrder updSharingOrder = new WxProfitSharingOrder();
updSharingOrder.updateTenantInfo(sharingOrder);
@@ -237,7 +237,7 @@ public class WxProfitSharingOrderServiceImpl implements WxProfitSharingOrderServ
WxAppinfo appInfo = dto.getAppinfo();
WxPayAccount payAccount = wxPayAccountMapper.selectById(appInfo.getPayId());

PayShareResult shareResult = payServiceFactory.getPayShareAdapterService(dto.getPayWay()).noReciverShare(appInfo,payAccount,sharingOrder,sharingOrder.getTransactionId(),sharingOrder.getPayAmount());
PayShareResult shareResult = payServiceFactory.getPayShareAdapterService(dto.getPayWay(),payAccount.getPayVersion()).noReciverShare(appInfo,payAccount,sharingOrder,sharingOrder.getTransactionId(),sharingOrder.getPayAmount());

WxProfitSharingOrder updSharingOrder = new WxProfitSharingOrder();
updSharingOrder.updateTenantInfo(sharingOrder);
@@ -346,7 +346,7 @@ public class WxProfitSharingOrderServiceImpl implements WxProfitSharingOrderServ
if (record == null)
return new ResultData(ErrorCode.ORDER_IS_NOT_FIND);

PayShareQueryResult shareResult = payServiceFactory.getPayShareAdapterService(dto.getPayWay()).shareQuery(appInfo, payAccount, record);
PayShareQueryResult shareResult = payServiceFactory.getPayShareAdapterService(dto.getPayWay(),payAccount.getPayVersion()).shareQuery(appInfo, payAccount, record);
if (!shareResult.isSuccess()) {
throw new MallinkException(shareResult.getCode(),shareResult.getMsg());
}
@@ -447,11 +447,9 @@ public class WxProfitSharingOrderServiceImpl implements WxProfitSharingOrderServ
return new ResultData(ErrorCode.SYS_PARAMETER_ERROR);
}

PayShareAdapterService payShareAdapterService = payServiceFactory.getPayShareAdapterService(payWay);

WxAppinfo appInfo = getAppinfo(sharingOrderDto.getTenantId(),payWay);
WxPayAccount payAccount = wxPayAccountMapper.selectById(appInfo.getPayId());
PayShareAdapterService payShareAdapterService = payServiceFactory.getPayShareAdapterService(payWay,payAccount.getPayVersion());

//分账检查是否已创建分账订单
WxProfitSharingOrder record = new WxProfitSharingOrder();
@@ -667,7 +665,7 @@ public class WxProfitSharingOrderServiceImpl implements WxProfitSharingOrderServ
WxProfitSharingReceiver psReceiverQ = new WxProfitSharingReceiver();
psReceiverQ.updateTenantInfo(payAccount);
psReceiverQ.setMerchantId(sharingOrder.getMerchantId());
psReceiverQ.setSharingType(payServiceFactory.getPayShareAdapterService(dto.getPayWay()).getProfitSharingType());
psReceiverQ.setSharingType(payServiceFactory.getPayShareAdapterService(dto.getPayWay(),payAccount.getPayVersion()).getProfitSharingType());
psReceiverQ.setStatus(EnumProfitSharingReceiverStatus.PROFIT_SHARING_RECEIVER_STATUS_VALID.getCode());
List<WxProfitSharingReceiver> psReceiverList = wxProfitSharingReceiverMapper.findList(psReceiverQ);
if (null == psReceiverList || psReceiverList.size() !=1 ) {
@@ -677,7 +675,7 @@ public class WxProfitSharingOrderServiceImpl implements WxProfitSharingOrderServ
JSONArray realReceivers = new JSONArray();
psReceiverList.stream().forEach(receiver->{
JSONObject jo = new JSONObject();
jo.put("type",payServiceFactory.getPayShareAdapterService(dto.getPayWay()).getShareAccount(receiver.getReceiverType()).getMessage());
jo.put("type",payServiceFactory.getPayShareAdapterService(dto.getPayWay(),payAccount.getPayVersion()).getShareAccount(receiver.getReceiverType()).getMessage());
jo.put("account",receiver.getReceiverAccount());
jo.put("amount", amount);
//jo.put("description",receiver.getReceiverComments()); //改为存ID,


+ 2
- 2
mallinkService/src/main/java/com/iformall/service/impl/WxProfitSharingReceiverServiceImpl.java Näytä tiedosto

@@ -157,7 +157,7 @@ public class WxProfitSharingReceiverServiceImpl implements WxProfitSharingReceiv
//receiver.setTrueName(receiverParam.getTrueName());

//添加分账账户
ShareAccountResult createResult = payServiceFactory.getPayShareAdapterService(payWay.getCode()).createShareAccount(appInfo, payAccount, receiver);
ShareAccountResult createResult = payServiceFactory.getPayShareAdapterService(payWay.getCode(),payAccount.getPayVersion()).createShareAccount(appInfo, payAccount, receiver);
if (!createResult.isSuccess()) {
return new ResultData(createResult.getCode(), createResult.getMsg());
}
@@ -395,7 +395,7 @@ public class WxProfitSharingReceiverServiceImpl implements WxProfitSharingReceiv
))) {
//还有别的商户使用这个账号,不从微信服务器申请删除
} else {
ShareAccountResult shareResult = payServiceFactory.getPayShareAdapterService(receiver.getPlat()).deleteShareAccount(appInfo, payAccount, receiver);
ShareAccountResult shareResult = payServiceFactory.getPayShareAdapterService(receiver.getPlat(),payAccount.getPayVersion()).deleteShareAccount(appInfo, payAccount, receiver);
if (!shareResult.isSuccess()) {
return new ResultData(shareResult.getCode(), shareResult.getMsg());
}


+ 6
- 6
mallinkService/src/main/java/com/iformall/service/impl/WxRefundOrderServiceImpl.java Näytä tiedosto

@@ -229,7 +229,7 @@ public class WxRefundOrderServiceImpl implements WxRefundOrderService {
throw new MallinkException(ErrorCode.PAY_ORDER_QUERY_ERROR.getCode(), "payAccount为空[payId:"+appInfo.getPayId()+"]");
}
try {
PayQueryAdapterResult queryResult = payServiceFactory.getPayAdapterService(payOrder.getPayVendor()).queryPayStatus(payOrder, appInfo, payAccount);
PayQueryAdapterResult queryResult = payServiceFactory.getPayAdapterService(payOrder.getPayVendor(),payAccount.getPayVersion()).queryPayStatus(payOrder, appInfo, payAccount);
if(EnumPayStatus.PAY_STATUS_SUCCESS.getCode() != queryResult.getCode()){
return new ResultData(ErrorCode.PAY_ORDER_ERROR.getCode(),"该订单查询支付状态为未支付成功,无法退款。");
}
@@ -350,7 +350,7 @@ public class WxRefundOrderServiceImpl implements WxRefundOrderService {
throw new MallinkException(ErrorCode.DB_FAIL);
}
RefundAdapterResult refundResult = payServiceFactory.getRefundPayAdapterService(payOrder.getPayVendor()).refund(payAccount, appInfo, record, payOrder, payType);
RefundAdapterResult refundResult = payServiceFactory.getRefundPayAdapterService(payOrder.getPayVendor(),payAccount.getPayVersion()).refund(payAccount, appInfo, record, payOrder, payType);
if (refundResult.isSuccess()) {
record.setRefundOrderStatus(EnumRefundStatus.REFUND_REQ_SUCCESS.getCode());
wxRefundOrderMapper.updateById(record);
@@ -554,7 +554,7 @@ public class WxRefundOrderServiceImpl implements WxRefundOrderService {
if (null == payAccount) {
throw new MallinkException(ErrorCode.PAY_ORDER_QUERY_ERROR.getCode(), "payAccount为空[payId:"+appInfo.getPayId()+"]");
}
RefundAdapterResult refundResult = payServiceFactory.getRefundPayAdapterService(payOrder.getPayVendor()).refund(payAccount, appInfo, record, payOrder, payType);
RefundAdapterResult refundResult = payServiceFactory.getRefundPayAdapterService(payOrder.getPayVendor(),payAccount.getPayVersion()).refund(payAccount, appInfo, record, payOrder, payType);
if (refundResult.isSuccess()) {
record.setRefundOrderStatus(EnumRefundStatus.REFUND_REQ_SUCCESS.getCode());
wxRefundOrderMapper.updateById(record);
@@ -573,7 +573,7 @@ public class WxRefundOrderServiceImpl implements WxRefundOrderService {
@Override
public ResultData queryRefundOrder(WxAppinfo appInfo, WxRefundOrder record) {
WxPayAccount payAccount = wxPayAccountMapper.selectById(appInfo.getPayId());
RefundAdapterResult result = payServiceFactory.getRefundPayAdapterService(record.getRefundVendor()).queryRefund(appInfo, payAccount, record);
RefundAdapterResult result = payServiceFactory.getRefundPayAdapterService(record.getRefundVendor(),payAccount.getPayVersion()).queryRefund(appInfo, payAccount, record);
if (result.isSuccess()) {
return new ResultData(Result.SUCCESS, "退款", result.getData());
}else {
@@ -776,7 +776,7 @@ public class WxRefundOrderServiceImpl implements WxRefundOrderService {
logger.error("退款订单已存在, 无法再提交退款申请");
throw new MallinkException(ErrorCode.REFUND_ORDER_EXIST.getCode(), "退款订单已存在, 无法再提交退款申请");
}
RefundAdapterResult refundResult = payServiceFactory.getRefundPayAdapterService(payOrder.getPayVendor()).refund(payAccount, appInfo, record, payOrder, null);
RefundAdapterResult refundResult = payServiceFactory.getRefundPayAdapterService(payOrder.getPayVendor(),payAccount.getPayVersion()).refund(payAccount, appInfo, record, payOrder, null);
if (refundResult.isSuccess()) {
record.setRefundOrderStatus(EnumRefundStatus.REFUND_REQ_SUCCESS.getCode());
wxRefundOrderMapper.updateById(record);
@@ -1022,7 +1022,7 @@ public class WxRefundOrderServiceImpl implements WxRefundOrderService {
@Override
@Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class})
public ResultData syncRefundOrder(WxAppinfo appinfo, WxPayAccount payAccount, WxRefundOrder order) {
RefundAdapterResult refundAdapterResult = payServiceFactory.getRefundPayAdapterService(order.getRefundVendor()).queryRefund(appinfo, payAccount, order);
RefundAdapterResult refundAdapterResult = payServiceFactory.getRefundPayAdapterService(order.getRefundVendor(),payAccount.getPayVersion()).queryRefund(appinfo, payAccount, order);

if(EnumRefundStatus.REFUND_REQ_SUCCESS.getCode().equals(refundAdapterResult.getCode())){//退款中 退款申请成功
if(EnumRefundStatus.REFUND_WAIT.getCode().equals(order.getRefundOrderStatus())){


+ 104
- 63
mallinkService/src/main/java/com/iformall/service/pay/PayServiceFactory.java Näytä tiedosto

@@ -2,28 +2,34 @@ package com.iformall.service.pay;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.iformall.enums.EnumAppPlat;
import com.iformall.enums.EnumPayVersion;
import com.iformall.service.pay.service.pay.douyin.miniApp.TtMiniAppPayAdapterService;
import com.iformall.service.pay.service.refund.douyin.TtRefundAdapterService;
import com.iformall.service.pay.service.refund.wx.v2.WxRefundAdapterService;
import com.iformall.service.pay.service.refund.wx.v3.WxRefundV3AdapterService;
import com.iformall.service.pay.service.share.douyin.TtPayShareService;
import com.iformall.service.pay.service.share.wx.v2.WxPayShareService;
import com.iformall.service.pay.service.share.wx.v3.WxPayShareV3Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.iformall.common.ErrorCode;
import com.iformall.enums.EnumPayWay;
import com.iformall.exception.MallinkException;
import com.iformall.service.pay.service.cashout.CashOutAdapterService;
import com.iformall.service.pay.service.cashout.wx.WxCashOutAdapterService;
import com.iformall.service.pay.service.cashout.wx.v2.WxCashOutAdapterService;
import com.iformall.service.pay.service.cashout.wx.v3.WxCashOutV3AdapterService;
import com.iformall.service.pay.service.pay.CDrivingPayService;
import com.iformall.service.pay.service.pay.CPassivePayService;
import com.iformall.service.pay.service.pay.PayAdapterService;
import com.iformall.service.pay.service.pay.wx.h5.WxH5PayService;
import com.iformall.service.pay.service.pay.wx.miniApp.appPay.WxMiniAppPayAdapterService;
import com.iformall.service.pay.service.pay.wx.miniApp.maPay.WxMiniMaPayAdapterService;
import com.iformall.service.pay.service.pay.wx.v2.h5.WxH5PayService;
import com.iformall.service.pay.service.pay.wx.v2.miniApp.appPay.WxMiniAppPayAdapterService;
import com.iformall.service.pay.service.pay.wx.v2.miniApp.maPay.WxMiniMaPayAdapterService;
import com.iformall.service.pay.service.pay.wx.v3.h5.WxH5PayV3Service;
import com.iformall.service.pay.service.pay.wx.v3.miniApp.appPay.WxMiniAppPayV3AdapterService;
import com.iformall.service.pay.service.pay.wx.v3.miniApp.maPay.WxMiniMaPayV3AdapterService;
import com.iformall.service.pay.service.refund.RefundPayAdapterService;
import com.iformall.service.pay.service.refund.wx.WxRefundAdapterService;
import com.iformall.service.pay.service.share.PayShareAdapterService;
import com.iformall.service.pay.service.share.wx.WxPayShareService;

/**
* 支付方式工厂
@@ -32,119 +38,154 @@ import com.iformall.service.pay.service.share.wx.WxPayShareService;
@Service
public class PayServiceFactory {

private Map<Integer,PayAdapterService> serviceMap = null;
private Map<Integer,PayAdapterService> qrcodeMap = null;
private Map<Integer,PayShareAdapterService> shareMap = null;
private Map<Integer,RefundPayAdapterService> refundMap = null;
private Map<Integer,CashOutAdapterService> cashoutMap = null;
private Map<String,PayAdapterService> serviceMap = null;
private Map<String,PayAdapterService> qrcodeMap = null;
private Map<String,PayShareAdapterService> shareMap = null;
private Map<String,RefundPayAdapterService> refundMap = null;
private Map<String,CashOutAdapterService> cashoutMap = null;
@Autowired
WxMiniAppPayAdapterService wxMiniAppPayService;
@Autowired
WxMiniAppPayV3AdapterService wxMiniAppPayV3AdapterService;
@Autowired
WxMiniMaPayAdapterService wxMiniAppMaPayService;
@Autowired
WxMiniMaPayV3AdapterService wxMiniMaPayV3AdapterService;
@Autowired
WxH5PayService wxH5PayService;
@Autowired
WxH5PayV3Service wxH5PayV3Service;

@Autowired
TtMiniAppPayAdapterService ttMiniAppPayService;

@Autowired
WxPayShareService wxShareService;
@Autowired
WxPayShareV3Service wxPayShareV3Service;

@Autowired
TtPayShareService ttShareService;
@Autowired
WxRefundAdapterService wxRefundService;
@Autowired
WxRefundV3AdapterService wxRefundV3AdapterService;

@Autowired
TtRefundAdapterService ttRefundService;
@Autowired
WxCashOutAdapterService wxCashOutService;
@Autowired
WxCashOutV3AdapterService wxCashOutV3AdapterService;

private Map<Integer,PayAdapterService> getServiceMap() {
private Map<String,PayAdapterService> getServiceMap() {
if (null == serviceMap) {
serviceMap = new ConcurrentHashMap<Integer,PayAdapterService>();
serviceMap.put(EnumPayWay.PAY_WAY_WECHAT.getCode(), wxMiniAppPayService);
serviceMap.put(EnumPayWay.PAY_WAY_WECHAT_MA.getCode(), wxMiniAppMaPayService);
serviceMap.put(EnumPayWay.PAY_WAY_WECHAT_WAP.getCode(), wxH5PayService);
serviceMap.put(EnumPayWay.PAY_WAY_TT.getCode(),ttMiniAppPayService);
serviceMap = new ConcurrentHashMap<String,PayAdapterService>();
serviceMap.put(EnumPayWay.PAY_WAY_WECHAT.getCode()+"_"+EnumPayVersion.WX_PAY_V2.getCode(), wxMiniAppPayService);
serviceMap.put(EnumPayWay.PAY_WAY_WECHAT.getCode()+"_"+EnumPayVersion.WX_PAY_V3.getCode(), wxMiniAppPayV3AdapterService);
serviceMap.put(EnumPayWay.PAY_WAY_WECHAT_MA.getCode()+"_"+EnumPayVersion.WX_PAY_V2.getCode(), wxMiniAppMaPayService);
serviceMap.put(EnumPayWay.PAY_WAY_WECHAT_MA.getCode()+"_"+EnumPayVersion.WX_PAY_V3.getCode(), wxMiniMaPayV3AdapterService);
serviceMap.put(EnumPayWay.PAY_WAY_WECHAT_WAP.getCode()+"_"+EnumPayVersion.WX_PAY_V2.getCode(), wxH5PayService);
serviceMap.put(EnumPayWay.PAY_WAY_WECHAT_WAP.getCode()+"_"+EnumPayVersion.WX_PAY_V3.getCode(), wxH5PayV3Service);
serviceMap.put(EnumPayWay.PAY_WAY_TT.getCode()+"_"+EnumPayVersion.DY_PAY_V2.getCode(),ttMiniAppPayService);
}
return serviceMap;
}

private Map<Integer,PayAdapterService> getQrcodeMap() {
private Map<String,PayAdapterService> getQrcodeMap() {
if (null == qrcodeMap) {
qrcodeMap = new ConcurrentHashMap<Integer,PayAdapterService>();
qrcodeMap.put(EnumAppPlat.WX.getCode(), wxMiniAppPayService);
qrcodeMap.put(EnumAppPlat.TOUTIAO.getCode(),ttMiniAppPayService);
qrcodeMap = new ConcurrentHashMap<String,PayAdapterService>();
qrcodeMap.put(EnumAppPlat.WX.getCode()+"_"+EnumPayVersion.WX_PAY_V2.getCode(), wxMiniAppPayService);
qrcodeMap.put(EnumAppPlat.WX.getCode()+"_"+EnumPayVersion.WX_PAY_V3.getCode(), wxMiniAppPayService);
qrcodeMap.put(EnumAppPlat.TOUTIAO.getCode()+"_"+EnumPayVersion.DY_PAY_V2.getCode(),ttMiniAppPayService);
}
return qrcodeMap;
}
private Map<Integer,PayShareAdapterService> getShareMap(){
private Map<String,PayShareAdapterService> getShareMap(){
if (null == shareMap ) {
shareMap = new ConcurrentHashMap<Integer, PayShareAdapterService>();
shareMap.put(EnumPayWay.PAY_WAY_WECHAT.getCode(), wxShareService);
shareMap.put(EnumPayWay.PAY_WAY_WECHAT_MA.getCode(), wxShareService);
shareMap.put(EnumPayWay.PAY_WAY_TT.getCode(), ttShareService);
shareMap.put(EnumPayWay.PAY_WAY_POS_NEU.getCode(), wxShareService);
shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_MERCHANT.getCode(), wxShareService);
shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_VERRIFY.getCode(), wxShareService);
shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_B_MA.getCode(), wxShareService);
shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_CAR_STOP.getCode(), wxShareService);
shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_SYSTEM_SEND.getCode(), wxShareService);
shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_INJECT_SEND.getCode(), ttShareService);
shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_BATCH_SEND.getCode(), wxShareService);
shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_TRADE.getCode(), wxShareService);
shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_PASSWD.getCode(), wxShareService);
shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_CREDIT.getCode(), wxShareService);
shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_GIFTLIST.getCode(), wxShareService);
shareMap = new ConcurrentHashMap<String, PayShareAdapterService>();
shareMap.put(EnumPayWay.PAY_WAY_WECHAT.getCode()+"_"+EnumPayVersion.WX_PAY_V2.getCode(), wxShareService);
shareMap.put(EnumPayWay.PAY_WAY_WECHAT_MA.getCode()+"_"+EnumPayVersion.WX_PAY_V2.getCode(), wxShareService);
shareMap.put(EnumPayWay.PAY_WAY_TT.getCode()+"_"+EnumPayVersion.DY_PAY_V2.getCode(), ttShareService);
shareMap.put(EnumPayWay.PAY_WAY_POS_NEU.getCode()+"_"+EnumPayVersion.WX_PAY_V2.getCode(), wxShareService);
shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_MERCHANT.getCode()+"_"+EnumPayVersion.WX_PAY_V2.getCode(), wxShareService);
shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_VERRIFY.getCode()+"_"+EnumPayVersion.WX_PAY_V2.getCode(), wxShareService);
shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_B_MA.getCode()+"_"+EnumPayVersion.WX_PAY_V2.getCode(), wxShareService);
shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_CAR_STOP.getCode()+"_"+EnumPayVersion.WX_PAY_V2.getCode(), wxShareService);
shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_SYSTEM_SEND.getCode()+"_"+EnumPayVersion.WX_PAY_V2.getCode(), wxShareService);
shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_INJECT_SEND.getCode()+"_"+EnumPayVersion.DY_PAY_V2.getCode(), ttShareService);
shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_BATCH_SEND.getCode()+"_"+EnumPayVersion.WX_PAY_V2.getCode(), wxShareService);
shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_TRADE.getCode()+"_"+EnumPayVersion.WX_PAY_V2.getCode(), wxShareService);
shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_PASSWD.getCode()+"_"+EnumPayVersion.WX_PAY_V2.getCode(), wxShareService);
shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_CREDIT.getCode()+"_"+EnumPayVersion.WX_PAY_V2.getCode(), wxShareService);
shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_GIFTLIST.getCode()+"_"+EnumPayVersion.WX_PAY_V2.getCode(), wxShareService);
shareMap.put(EnumPayWay.PAY_WAY_WECHAT.getCode()+"_"+EnumPayVersion.WX_PAY_V3.getCode(), wxPayShareV3Service);
shareMap.put(EnumPayWay.PAY_WAY_WECHAT_MA.getCode()+"_"+EnumPayVersion.WX_PAY_V3.getCode(), wxPayShareV3Service);
shareMap.put(EnumPayWay.PAY_WAY_POS_NEU.getCode()+"_"+EnumPayVersion.WX_PAY_V3.getCode(), wxPayShareV3Service);
shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_MERCHANT.getCode()+"_"+EnumPayVersion.WX_PAY_V3.getCode(), wxPayShareV3Service);
shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_VERRIFY.getCode()+"_"+EnumPayVersion.WX_PAY_V3.getCode(), wxPayShareV3Service);
shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_B_MA.getCode()+"_"+EnumPayVersion.WX_PAY_V3.getCode(), wxPayShareV3Service);
shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_CAR_STOP.getCode()+"_"+EnumPayVersion.WX_PAY_V3.getCode(), wxPayShareV3Service);
shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_SYSTEM_SEND.getCode()+"_"+EnumPayVersion.WX_PAY_V3.getCode(), wxPayShareV3Service);
shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_BATCH_SEND.getCode()+"_"+EnumPayVersion.WX_PAY_V3.getCode(), wxPayShareV3Service);
shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_TRADE.getCode()+"_"+EnumPayVersion.WX_PAY_V3.getCode(), wxPayShareV3Service);
shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_PASSWD.getCode()+"_"+EnumPayVersion.WX_PAY_V3.getCode(), wxPayShareV3Service);
shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_CREDIT.getCode()+"_"+EnumPayVersion.WX_PAY_V3.getCode(), wxPayShareV3Service);
shareMap.put(EnumPayWay.PAY_WAY_NOT_UNPAY_GIFTLIST.getCode()+"_"+EnumPayVersion.WX_PAY_V3.getCode(), wxPayShareV3Service);
}
return shareMap;
}
private Map<Integer,RefundPayAdapterService> getRefundMap(){
private Map<String,RefundPayAdapterService> getRefundMap(){
if (null == refundMap ) {
refundMap = new ConcurrentHashMap<Integer, RefundPayAdapterService>();
refundMap.put(EnumPayWay.PAY_WAY_WECHAT.getCode(), wxRefundService);
refundMap.put(EnumPayWay.PAY_WAY_WECHAT_MA.getCode(), wxRefundService);
refundMap.put(EnumPayWay.PAY_WAY_TT.getCode(), ttRefundService);
refundMap = new ConcurrentHashMap<String, RefundPayAdapterService>();
refundMap.put(EnumPayWay.PAY_WAY_WECHAT.getCode()+"_"+EnumPayVersion.WX_PAY_V2.getCode(), wxRefundService);
refundMap.put(EnumPayWay.PAY_WAY_WECHAT_MA.getCode()+"_"+EnumPayVersion.WX_PAY_V2.getCode(), wxRefundService);
refundMap.put(EnumPayWay.PAY_WAY_WECHAT.getCode()+"_"+EnumPayVersion.WX_PAY_V3.getCode(), wxRefundV3AdapterService);
refundMap.put(EnumPayWay.PAY_WAY_WECHAT_MA.getCode()+"_"+EnumPayVersion.WX_PAY_V3.getCode(), wxRefundV3AdapterService);
refundMap.put(EnumPayWay.PAY_WAY_TT.getCode()+"_"+EnumPayVersion.DY_PAY_V2.getCode(), ttRefundService);
}
return refundMap;
}
private Map<Integer,CashOutAdapterService> getCashOutMap() {
private Map<String,CashOutAdapterService> getCashOutMap() {
if (null == cashoutMap ) {
cashoutMap = new ConcurrentHashMap<Integer, CashOutAdapterService>();
cashoutMap.put(EnumPayWay.PAY_WAY_WECHAT.getCode(), wxCashOutService);
cashoutMap.put(EnumPayWay.PAY_WAY_WECHAT_MA.getCode(), wxCashOutService);
cashoutMap = new ConcurrentHashMap<String, CashOutAdapterService>();
cashoutMap.put(EnumPayWay.PAY_WAY_WECHAT.getCode()+"_"+EnumPayVersion.WX_PAY_V2.getCode(), wxCashOutService);
cashoutMap.put(EnumPayWay.PAY_WAY_WECHAT_MA.getCode()+"_"+EnumPayVersion.WX_PAY_V2.getCode(), wxCashOutService);
cashoutMap.put(EnumPayWay.PAY_WAY_WECHAT.getCode()+"_"+EnumPayVersion.WX_PAY_V3.getCode(), wxCashOutV3AdapterService);
cashoutMap.put(EnumPayWay.PAY_WAY_WECHAT_MA.getCode()+"_"+EnumPayVersion.WX_PAY_V3.getCode(), wxCashOutV3AdapterService);
}
return cashoutMap;
}
public PayAdapterService getPayAdapterService(Integer type) throws MallinkException{
PayAdapterService service = getServiceMap().get(type);
public PayAdapterService getPayAdapterService(Integer type,Integer payVersion) throws MallinkException{
PayAdapterService service = getServiceMap().get(type+"_"+payVersion);
if (null == service) {
throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(),"payWay["+type+"] 支付service未找到");
}
return service;
}

public PayAdapterService getQrcodeService(Integer type) throws MallinkException{
PayAdapterService service = getQrcodeMap().get(type);
public PayAdapterService getQrcodeService(Integer type,Integer payVersion) throws MallinkException{
PayAdapterService service = getQrcodeMap().get(type+"_"+payVersion);
if (null == service) {
throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(),"payWay["+type+"] 支付service未找到");
}
return service;
}
public CDrivingPayService getCDrivingPayService(Integer type) throws MallinkException{
PayAdapterService service = getServiceMap().get(type);
public CDrivingPayService getCDrivingPayService(Integer type,Integer payVersion) throws MallinkException{
PayAdapterService service = getServiceMap().get(type+"_"+payVersion);
if (null == service) {
throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(),"payWay["+type+"] 支付service未找到");
}
@@ -155,8 +196,8 @@ public class PayServiceFactory {
}
}
public CPassivePayService getCPassivePayService(Integer type) throws MallinkException{
PayAdapterService service = getServiceMap().get(type);
public CPassivePayService getCPassivePayService(Integer type,Integer payVersion) throws MallinkException{
PayAdapterService service = getServiceMap().get(type+"_"+payVersion);
if (null == service) {
throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(),"payWay["+type+"] 支付service未找到");
}
@@ -167,24 +208,24 @@ public class PayServiceFactory {
}
}
public PayShareAdapterService getPayShareAdapterService(Integer type) throws MallinkException{
PayShareAdapterService shareService = getShareMap().get(type);
public PayShareAdapterService getPayShareAdapterService(Integer type,Integer payVersion) throws MallinkException{
PayShareAdapterService shareService = getShareMap().get(type+"_"+payVersion);
if (null == shareService) {
throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(),"payWay["+type+"] 分账service未找到");
}
return shareService;
}
public RefundPayAdapterService getRefundPayAdapterService(Integer type) throws MallinkException{
RefundPayAdapterService refundService = getRefundMap().get(type);
public RefundPayAdapterService getRefundPayAdapterService(Integer type,Integer payVersion) throws MallinkException{
RefundPayAdapterService refundService = getRefundMap().get(type+"_"+payVersion);
if (null == refundService) {
throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(),"payWay["+type+"] 退款service未找到");
}
return refundService;
}
public CashOutAdapterService getCashOutAdapterService(Integer type)throws MallinkException {
CashOutAdapterService cashOutService = getCashOutMap().get(type);
public CashOutAdapterService getCashOutAdapterService(Integer type,Integer payVersion)throws MallinkException {
CashOutAdapterService cashOutService = getCashOutMap().get(type+"_"+payVersion);
if (null == cashOutService) {
throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(),"payWay["+type+"] 零钱service未找到");
}


mallinkService/src/main/java/com/iformall/service/pay/service/cashout/wx/WxCashOutAdapterService.java → mallinkService/src/main/java/com/iformall/service/pay/service/cashout/wx/v2/WxCashOutAdapterService.java Näytä tiedosto

@@ -1,4 +1,4 @@
package com.iformall.service.pay.service.cashout.wx;
package com.iformall.service.pay.service.cashout.wx.v2;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;

+ 500
- 0
mallinkService/src/main/java/com/iformall/service/pay/service/cashout/wx/v3/WxCashOutV3AdapterService.java Näytä tiedosto

@@ -0,0 +1,500 @@
package com.iformall.service.pay.service.cashout.wx.v3;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.binarywang.wxpay.service.WxPayService;
import com.iformall.common.ErrorCode;
import com.iformall.common.Result;
import com.iformall.common.ResultData;
import com.iformall.domain.po.WxAppinfo;
import com.iformall.domain.po.WxCashOut;
import com.iformall.domain.po.WxPayAccount;
import com.iformall.domain.po.WxPayOrder;
import com.iformall.domain.po.WxRefundOrder;
import com.iformall.domain.po.base.TenantEntity;
import com.iformall.enums.EnumAppPlat;
import com.iformall.enums.EnumCashOutStatus;
import com.iformall.enums.EnumPayMode;
import com.iformall.enums.EnumPayType;
import com.iformall.enums.EnumPayWay;
import com.iformall.enums.EnumRefundStatus;
import com.iformall.exception.MallinkException;
import com.iformall.mapper.WxAppinfoMapper;
import com.iformall.mapper.WxPayAccountMapper;
import com.iformall.mapper.WxPayOrderMapper;
import com.iformall.mapper.WxRefundOrderMapper;
import com.iformall.pay.WxCashOutP;
import com.iformall.pay.WxCashOutPV3;
import com.iformall.pay.WxCashOutPV3Item;
import com.iformall.pay.WxCashOutQueryP;
import com.iformall.pay.WxPay;
import com.iformall.pay.WxPayment;
import com.iformall.pay.WxRefundOrderP;
import com.iformall.pay.WxRefundOrderSP;
import com.iformall.service.WxAppinfoService;
import com.iformall.service.pay.service.cashout.CashOutAdapterService;
import com.iformall.service.pay.service.cashout.entity.CashOutAdapterResult;
import com.iformall.service.pay.service.refund.RefundPayAdapterService;
import com.iformall.service.pay.service.refund.entity.RefundAdapterResult;
import com.iformall.service.pay.service.refund.entity.RefundNotifyAdapterResult;
import com.iformall.utils.BeanUtils;
import com.iformall.utils.CipherUtil;
import com.iformall.utils.DateUtils;
import com.iformall.utils.MaUtil;
import com.iformall.utils.Utility;
import com.iformall.utils.XmlUtil;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class WxCashOutV3AdapterService implements CashOutAdapterService{
@Autowired
WxAppinfoService wxAppinfoService;
@Autowired
MaUtil maUtil;

JSONObject errorRefundReqMap = JSON.parseObject("{\n" +
" \"NO_AUTH\": {\n" +
" \"detail\": \"没有该接口权限\",\n" +
" \"reason\": \"1. 用户账号被冻结,无法付款;2. 产品权限没有开通或者被风控冻结;3. 此IP地址不允许调用接口,如有需要请登录微信支付商户平台更改配置\",\n" +
" \"resolution\": \"请根据具体的错误返回描述做对应处理,如返回描述不够明确,请参考此处的错误原因做排查。\"\n" +
" },\n" +
" \"AMOUNT_LIMIT\": {\n" +
" \"detail\": \"金额超限\",\n" +
" \"reason\": \"1. 被微信风控拦截,最低单笔付款限额调整为5元。2. 低于最低单笔付款限额或者高于最高单笔付款限额\",\n" +
" \"resolution\": \"目前最低付款金额为1元,最高10万元,请确认是否付款金额超限。\"\n" +
" },\n" +
" \"PARAM_ERROR\": {\n" +
" \"detail\": \"参数错误\",\n" +
" \"reason\": \"1. 请求参数校验错误 2. 字符中包含非utf8字符 3. 商户号和appid没有绑定关系\\t\",\n" +
" \"resolution\": \"请参照原因检查您的请求参数是否正确\"\n" +
" },\n" +
" \"OPENID_ERROR\": {\n" +
" \"detail\": \"Openid错误\",\n" +
" \"reason\": \"Openid格式错误或者不属于商家公众账号\",\n" +
" \"resolution\": \"Openid与appid是有一一映射关系的,请确保正确使用。\"\n" +
" },\n" +
" \"SEND_FAILED\": {\n" +
" \"detail\": \"付款错误\",\n" +
" \"reason\": \"付款错误,请查单确认付款结果\",\n" +
" \"resolution\": \"请查单确认付款结果,以查单结果为准。\"\n" +
" },\n" +
" \"NOTENOUGH\": {\n" +
" \"detail\": \"余额不足\",\n" +
" \"reason\": \"您的付款帐号余额不足或资金未到账\\t\",\n" +
" \"resolution\": \"如果要继续付款必须使用原商户订单号重试\"\n" +
" },\n" +
" \"SYSTEMERROR\": {\n" +
" \"detail\": \"系统繁忙,请稍后再试\",\n" +
" \"reason\": \"微信内部接口调用发生错误\",\n" +
" \"resolution\": \"请先调用查询接口,查看此次付款结果,如结果为不明确状态(如订单号不存在),请务必使用原商户订单号进行重试。\"\n" +
" },\n" +
" \"NAME_MISMATCH\": {\n" +
" \"detail\": \"姓名校验出错\",\n" +
" \"reason\": \"收款人身份校验不通过\",\n" +
" \"resolution\": \"如果要继续付款必须使用原商户订单号重试\"\n" +
" },\n" +
" \"SIGN_ERROR\": {\n" +
" \"detail\": \"签名错误\",\n" +
" \"reason\": \"校验签名错误\",\n" +
" \"resolution\": \"请检查您的请求参数和签名密钥KEY是否正确,如果要继续付款必须使用原商户订单号重试\"\n" +
" },\n" +
" \"XML_ERROR\": {\n" +
" \"detail\": \"Post内容出错\",\n" +
" \"reason\": \"Post请求数据不是合法的xml格式内容\",\n" +
" \"resolution\": \"格式问题,请检查请求格式是否正确。\"\n" +
" },\n" +
" \"FATAL_ERROR\": {\n" +
" \"detail\": \"两次请求参数不一致\",\n" +
" \"reason\": \"两次请求商户单号一样,但是参数不一致\",\n" +
" \"resolution\": \"重入必须保证所有参数值都不变\"\n" +
" },\n" +
" \"FREQ_LIMIT\": {\n" +
" \"detail\": \"超过频率限制,请稍后再试\",\n" +
" \"reason\": \"接口请求频率超时接口限制\",\n" +
" \"resolution\": \"调用接口过于频繁,请稍后再试,如果要继续付款必须使用原商户订单号重试\"\n" +
" },\n" +
" \"MONEY_LIMIT\": {\n" +
" \"detail\": \"已经达到今日付款总额上限/已达到付款给此用户额度上限\",\n" +
" \"reason\": \"请关注接口的付款限额条件\",\n" +
" \"resolution\": \"付款额度已经超限,请参考接口使用条件,如果要继续付款必须使用原商户订单号重试\"\n" +
" },\n" +
" \"CA_ERROR\": {\n" +
" \"detail\": \"商户API证书校验出错\",\n" +
" \"reason\": \"请求没带商户API证书或者带上了错误的商户API证书\",\n" +
" \"resolution\": \"您使用的调用证书有误,请确认是否使用了正确的证书,可以前往商户平台重新下载,证书需与商户号对应,如果要继续付款必须使用原商户订单号重试\"\n" +
" },\n" +
" \"V2_ACCOUNT_SIMPLE_BAN\": {\n" +
" \"detail\": \"无法给未实名用户付款\",\n" +
" \"reason\": \"用户微信支付账户未实名,无法付款\",\n" +
" \"resolution\": \"不支持给未实名用户付款,如果要继续付款必须使用原商户订单号重试\"\n" +
" },\n" +
" \"PARAM_IS_NOT_UTF8\": {\n" +
" \"detail\": \"请求参数中包含非utf8编码字符\",\n" +
" \"reason\": \"接口规范要求所有请求参数都必须为utf8编码\",\n" +
" \"resolution\": \"微信接口使用编码是UTF-8,请确认,如果要继续付款必须使用原商户订单号重试\"\n" +
" },\n" +
" \"SENDNUM_LIMIT\": {\n" +
" \"detail\": \"该用户今日付款次数超过限制,如有需要请进入【微信支付商户平台-产品中心-企业付款到零钱-产品设置】进行修改\",\n" +
" \"reason\": \"该用户今日付款次数超过限制,如有需要请进入【微信支付商户平台-产品中心-企业付款到零钱-产品设置】进行修改\",\n" +
" \"resolution\": \"向用户付款的次数超限了,请参考接口使用条件,如果要继续付款必须使用原商户订单号重试\"\n" +
" },\n" +
" \"RECV_ACCOUNT_NOT_ALLOWED\": {\n" +
" \"detail\": \"收款账户不在收款账户列表\",\n" +
" \"reason\": \"收款账户不在收款账户列表\",\n" +
" \"resolution\": \"请登陆商户平台,查看产品中心企业付款到零钱的产品配置\"\n" +
" },\n" +
" \"PAY_CHANNEL_NOT_ALLOWED\": {\n" +
" \"detail\": \"本商户号未配置API发起能力\",\n" +
" \"reason\": \"本商户号未配置API发起能力\",\n" +
" \"resolution\": \"请登陆商户平台,查看产品中心企业付款到零钱的产品配置\"\n" +
" }\n" +
"}");
JSONObject errorQueryReqMap = JSON.parseObject("{\n" +
" \"CA_ERROR\": {\n" +
" \"detail\": \"请求未携带证书,或请求携带的证书出错\",\n" +
" \"reason\": \"请求未携带证书,或请求携带的证书出错\",\n" +
" \"resolution\": \"到商户平台下载证书,请求带上证书后重试。\"\n" +
" },\n" +
" \"SIGN_ERROR\": {\n" +
" \"detail\": \"商户签名错误\",\n" +
" \"reason\": \"商户签名错误\",\n" +
" \"resolution\": \"按文档要求重新生成签名后再重试。\"\n" +
" },\n" +
" \"FREQ_LIMIT\": {\n" +
" \"detail\": \"受频率限制\",\n" +
" \"reason\": \"受频率限制\\t\",\n" +
" \"resolution\": \"请对请求做频率控制\"\n" +
" },\n" +
" \"XML_ERROR\": {\n" +
" \"detail\": \"请求的xml格式错误,或者post的数据为空\",\n" +
" \"reason\": \"请求的xml格式错误,或者post的数据为空\",\n" +
" \"resolution\": \"检查请求串,确认无误后重试。\"\n" +
" },\n" +
" \"PARAM_ERROR\": {\n" +
" \"detail\": \"参数错误\",\n" +
" \"reason\": \"参数错误\",\n" +
" \"resolution\": \"请查看err_code_des,修改设置错误的参数。\"\n" +
" },\n" +
" \"SYSTEMERROR\": {\n" +
" \"detail\": \"系统繁忙,请再试\",\n" +
" \"reason\": \"系统繁忙,请再试\\t\",\n" +
" \"resolution\": \"系统繁忙\"\n" +
" },\n" +
" \"NOT_FOUND\": {\n" +
" \"detail\": \"1、指定单号数据不存在 2、指定单号数据不存在,单据查询超过有效期\",\n" +
" \"reason\": \"1、指定单号数据不存在 2、指定单号数据不存在,单据查询超过有效期\",\n" +
" \"resolution\": \"1、查询单号对应的数据不存在,请使用正确的商户订单号查询2、如需查询超过有效期的单据,请登录到商户平台进行查询。\"\n" +
" }\n" +
"}");
@Override
public CashOutAdapterResult cashOut(WxAppinfo appInfo, WxPayAccount payAccount, WxCashOut cashOut) {
if (StringUtils.isBlank(payAccount.getMerchantCertPath())) {
return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), "零钱支付失败。商户证书为空。请联系管理员配置。", null);
}
if (StringUtils.isBlank(payAccount.getMerchantKeyPath())) {
return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), "零钱支付失败。商户密钥为空。请联系管理员配置。", null);
}
if (StringUtils.isBlank(payAccount.getMerchantApiv3Key())) {
return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), "零钱支付失败。商户密钥ApiV3为空。请联系管理员配置。", null);
}
WxPayService payService = maUtil.getWxPayServiceBySelfModel(appInfo,payAccount);
if (null == payService) {
return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), "零钱支付失败。当前小程序未查询到payService。", null);
}
String response = null;
try {
response = WxPay.merchantTranferChange(payService,generateWxCashOutPV3(payAccount, appInfo, cashOut));
} catch (Exception e) {
log.error("零钱支付异常: " + e.getMessage(),e);
return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), "微信零钱支付接口调用异常:"+e.getMessage(), null);
}
log.info("微信零钱支付:, response: " + response.toString());
return generateResult(response,cashOut);
// if (payAccount.getType() == EnumPayMode.MCH.getCode()) {
// 普通商户模式
// }
}
private WxCashOutPV3 generateWxCashOutPV3(WxPayAccount payAccount,WxAppinfo appInfo,WxCashOut cashOut) {
WxCashOutPV3 wxCashOutPv3 = new WxCashOutPV3();
wxCashOutPv3.setAppid(appInfo.getAppId());
wxCashOutPv3.setOut_batch_no(String.valueOf(cashOut.getId()));
StringBuffer bn = new StringBuffer(cashOut.getMerchantName()).append("提现");
try {
wxCashOutPv3.setBatch_name(new String(bn.toString().getBytes("ISO-8859-1"), "UTF-8"));
} catch (UnsupportedEncodingException e) {
wxCashOutPv3.setBatch_name("tixian");
}
wxCashOutPv3.setBatch_remark("From FM WxMiniApp");
wxCashOutPv3.setTotal_amount(cashOut.getTotalFee());
wxCashOutPv3.setTotal_num(1);
List<WxCashOutPV3Item> itemList = new ArrayList<WxCashOutPV3Item>();
WxCashOutPV3Item item = new WxCashOutPV3Item();
item.setOut_detail_no(Utility.generate32UUID());
item.setOpenid(cashOut.getReciveOpenId());
item.setTransfer_amount(cashOut.getTotalFee());
item.setTransfer_remark("From FM WxMiniApp Tranfer.");
item.setUser_name(cashOut.getRealName());
itemList.add(item);
wxCashOutPv3.setTransfer_detail_list(itemList);
return wxCashOutPv3;
}
private CashOutAdapterResult generateResult(String response,WxCashOut cashOut) {
JSONObject result = JSON.parseObject(response);
String batchId = result.getString("batch_id");
if (!StringUtils.isBlank(batchId)) {
cashOut.setWxPayNo(batchId);
String payTime = result.getString("create_time");
cashOut.setWxPayTime(payTime);
return new CashOutAdapterResult(true,EnumCashOutStatus.SUCCESS.getCode(),"微信零钱支付申请成功",result);
}else {
//log.error("微信零钱支付申请失败: " + response);
return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), "微信零钱支付申请失败:微信接口未返回值", result);
}
}
@Override
public CashOutAdapterResult queryCashOut(WxAppinfo appInfo, WxPayAccount payAccount, WxCashOut cashOut) {
if (StringUtils.isBlank(payAccount.getMerchantCertPath())) {
return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), "零钱支付失败。商户证书为空。请联系管理员配置。", null);
}
if (StringUtils.isBlank(payAccount.getMerchantKeyPath())) {
return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), "零钱支付失败。商户密钥为空。请联系管理员配置。", null);
}
if (StringUtils.isBlank(payAccount.getMerchantApiv3Key())) {
return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), "零钱支付失败。商户密钥ApiV3为空。请联系管理员配置。", null);
}
WxPayService payService = maUtil.getWxPayServiceBySelfModel(appInfo,payAccount);
if (null == payService) {
return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), "零钱支付失败。当前小程序未查询到payService。", null);
}
String response = null;
try {
response = WxPay.merchantTransferInfo(String.valueOf(cashOut.getId()), payService);
} catch (Exception e) {
log.error("零钱支付查询异常: " + e.getMessage(),e);
throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR.getCode(), "微信零钱支付查询接口异常:"+e.getMessage());
}
log.info("微信零钱支付查询:"+ response.toString());
return getReusltFromQuery(response,cashOut);
}
private CashOutAdapterResult getReusltFromQuery(String response,WxCashOut cashOut) throws MallinkException{
JSONObject result = JSON.parseObject(response);
JSONObject transferBatch = result.getJSONObject("transfer_batch");
if (null != transferBatch) {
/**
* WAIT_PAY:待付款,商户员工确认付款阶段
* ACCEPTED:已受理。批次已受理成功,若发起批量转账的30分钟后,转账批次单仍处于该状态,可能原因是商户账户余额不足等
* PROCESSING:转账中。已开始处理批次内的转账明细单
* FINISHED:已完成。批次内的所有转账明细单都已处理完成
* CLOSED:已关闭。可查询具体的批次关闭原因确认
*/
String batchStatus = transferBatch.getString("batch_status");
if ("WAIT_PAY".equals(batchStatus)) {
throw new MallinkException(EnumCashOutStatus.FAIL.getCode(), "待商户付款:");
}else if ("ACCEPTED".equals(batchStatus)) {
throw new MallinkException(EnumCashOutStatus.FAIL.getCode(), "已受理,待转账:");
}else if ("PROCESSING".equals(batchStatus)) {
throw new MallinkException(EnumCashOutStatus.FAIL.getCode(), "待转账中");
}else if ("CLOSED".equals(batchStatus)) {
/**
* MERCHANT_REVOCATION:商户主动撤销 OVERDUE_CLOSE:系统超时关闭
*/
String close_reason = transferBatch.getString("close_reason");
if ("MERCHANT_REVOCATION".equals(close_reason)) {
close_reason = "商户主动撤销";
}else if ("OVERDUE_CLOSE".equals(close_reason)) {
close_reason = "系统超时关闭";
}
return new CashOutAdapterResult(false,EnumCashOutStatus.FAIL.getCode(),"转账已关闭:"+close_reason,result);
}else if ("FINISHED".equals(batchStatus)) {
String detailId = transferBatch.getString("out_batch_no");
cashOut.setWxPayNo(detailId);
String wxPayTime = transferBatch.getString("create_time");
cashOut.setWxPayTime(wxPayTime);
return new CashOutAdapterResult(true,EnumCashOutStatus.SUCCESS.getCode(),"转账已完成",result);
}else {
log.error("微信零钱支付查询失败,微信返回未知状态: " + response);
throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), "微信零钱支付查询失败, 微信返回未知状态:"+batchStatus);
}
}else {
log.error("微信零钱支付查询失败,微信未返回值: " + response);
throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), "微信零钱支付查询失败,微信未返回值:");
}
}
// /**
// * https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2
// *
// * 在wx_pay_account里面要设置merchant_cert_path,登陆特约商户的商户后台,账号中心-API安全。
// */
// @Deprecated
// @Override
// public CashOutAdapterResult cashOut(WxAppinfo appInfo, WxPayAccount payAccount, WxCashOut cashOut) {
// if (StringUtils.isBlank(payAccount.getMerchantCertPath())) {
// return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), "零钱支付失败。商户证书为空。请联系管理员配置。", null);
// }
// if (StringUtils.isBlank(payAccount.getMerchantApiKey())) {
// return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), "零钱支付失败。商户密钥为空。请联系管理员配置。", null);
// }
// WxCashOutP wxCashOutP = generateWxCashOutP(payAccount, appInfo, cashOut);
// Map signMap = null;
// try {
// signMap = BeanUtils.toStringMap(wxCashOutP);
// } catch (Exception e) {
// log.error("零钱支付命令生辰: " + e.getMessage(),e);
// return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), "零钱支付签名异常", null);
// }
//
// String signAgent = WxPayment.createSign(signMap, payAccount.getMerchantApiKey());
// signMap.put("sign", signAgent);
// String response = null;
// try {
// response = WxPay.merchantTranferChange(signMap, payAccount.getMerchantCertPath(), payAccount.getSubMchId());
// } catch (Exception e) {
// log.error("零钱支付异常: " + e.getMessage(),e);
// return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), "微信零钱支付接口调用异常", null);
// }
// log.info("微信零钱支付:" + wxCashOutP.toString() +", response: " + response.toString());
// return getReusltFromp(response,cashOut);
//
//// if (payAccount.getType() == EnumPayMode.MCH.getCode()) {
// // 普通商户模式
//// }
// }
//
// private WxCashOutP generateWxCashOutP(WxPayAccount payAccount,WxAppinfo appInfo,WxCashOut cashOut) {
// String noncestr = Utility.generate32UUID();
// WxCashOutP wxCashOutP = new WxCashOutP();
// wxCashOutP.setMch_appid(appInfo.getAppId());
// wxCashOutP.setMchid(payAccount.getSubMchId());
// wxCashOutP.setNonce_str(noncestr);
// wxCashOutP.setAmount(cashOut.getTotalFee());
// wxCashOutP.setCheck_name("NO_CHECK");
// wxCashOutP.setDesc("客户结算");
// wxCashOutP.setOpenid(cashOut.getReciveOpenId());
// wxCashOutP.setPartner_trade_no(String.valueOf(cashOut.getId()));
// return wxCashOutP;
// }
//
// private CashOutAdapterResult getReusltFromp(String response,WxCashOut cashOut) throws MallinkException{
// Map<String, String> returnMap = WxPayment.xmlToMap(response);
// String result_no = returnMap.get("result_code");
// if ("SUCCESS".equals(result_no)) {
// log.info("微信零钱支付申请成功: " + returnMap.toString());
// String wxPayNo = returnMap.get("payment_no");
// String payTime = returnMap.get("payment_time");
// cashOut.setWxPayNo(wxPayNo);
// cashOut.setWxPayTime(payTime);
// return new CashOutAdapterResult(true,EnumCashOutStatus.SUCCESS.getCode(),"微信零钱支付申请成功",returnMap);
// } else {
// log.error("微信零钱支付申请失败: " + response);
// String errMsg = "";
// JSONObject errObj = errorRefundReqMap.getJSONObject(result_no);
// if (errObj != null) {
// errMsg = errObj.toJSONString();
// } else {
// errMsg = returnMap.get("err_code_des");
// }
// return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), errMsg, returnMap);
// }
// }
//
// @Override
// public CashOutAdapterResult queryCashOut(WxAppinfo appInfo, WxPayAccount payAccount, WxCashOut cashOut) {
// if (StringUtils.isBlank(payAccount.getMerchantCertPath())) {
// return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), "零钱支付失败。商户证书为空。请联系管理员配置。", null);
// }
// WxCashOutQueryP wxCashOutP = generateQueryWxCashOutP(payAccount, appInfo, cashOut);
// Map signMap = null;
// try {
// signMap = BeanUtils.toStringMap(wxCashOutP);
// } catch (Exception e) {
// log.error("零钱支付命令生辰: " + e.getMessage(),e);
// throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), "零钱支付签名异常");
// }
//
// String signAgent = WxPayment.createSign(signMap, payAccount.getMerchantApiKey());
// signMap.put("sign", signAgent);
// String response = null;
// try {
// response = WxPay.getTransferInfo(signMap, payAccount.getMerchantCertPath(), payAccount.getSubMchId());
// } catch (Exception e) {
// log.error("零钱支付查询异常: " + e.getMessage(),e);
// throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR.getCode(), "微信零钱支付查询接口异常");
// }
// log.info("微信零钱支付查询:" + wxCashOutP.toString() + ", response: " + response.toString());
// return getReusltFromQueryp(response,cashOut);
// }
//
// private WxCashOutQueryP generateQueryWxCashOutP(WxPayAccount payAccount,WxAppinfo appInfo,WxCashOut cashOut) {
// String noncestr = Utility.generate32UUID();
// WxCashOutQueryP wxCashOutQueryP = new WxCashOutQueryP();
// wxCashOutQueryP.setAppid(appInfo.getAppId());
// wxCashOutQueryP.setMch_id(payAccount.getSubMchId());
// wxCashOutQueryP.setNonce_str(noncestr);
// wxCashOutQueryP.setPartner_trade_no(String.valueOf(cashOut.getId()));
// return wxCashOutQueryP;
// }
//
// private CashOutAdapterResult getReusltFromQueryp(String response,WxCashOut cashOut) throws MallinkException{
// Map<String, String> returnMap = WxPayment.xmlToMap(response);
// String result_no = returnMap.get("result_code");
// if ("SUCCESS".equals(result_no)) {
// String realStatus = returnMap.get("status");
// if ("SUCCESS".equals(realStatus) || "PROCESSING".equals(realStatus)) {
// String detailId = returnMap.get("detail_id");
// cashOut.setWxPayNo(detailId);
// String wxPayTime = returnMap.get("transfer_time");
// cashOut.setWxPayTime(wxPayTime);
// return new CashOutAdapterResult(true,EnumCashOutStatus.SUCCESS.getCode(),"微信零钱支付查询成功",returnMap);
// }else if("FAILED".equals(realStatus)) {
// String msg = returnMap.get("reason");
// return new CashOutAdapterResult(false,EnumCashOutStatus.FAIL.getCode(),msg,returnMap);
// }else {
// log.error("微信零钱支付查询失败,微信返回未知状态: " + response);
// throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), "微信零钱支付查询失败, 微信返回未知状态:"+realStatus);
// }
// } else {
// log.error("微信零钱支付查询失败: " + response);
// String errMsg = returnMap.get("err_code_des");
// String errCode = returnMap.get("err_code");
// if ("NOT_FOUND".equals(errCode)) {
// return new CashOutAdapterResult(false,EnumCashOutStatus.FAIL.getCode(),errMsg,returnMap);
// }
//// JSONObject errObj = errorQueryReqMap.getJSONObject(result_no);
//// if (errObj != null) {
//// errMsg = errObj.toJSONString();
//// } else {
//// errMsg = returnMap.get("err_code_des");
//// }
// throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), "微信零钱支付查询失败:"+errMsg);
// }
// }
}

mallinkService/src/main/java/com/iformall/service/pay/service/pay/wx/BaseWxPayAdapterService.java → mallinkService/src/main/java/com/iformall/service/pay/service/pay/wx/v2/BaseWxPayAdapterService.java Näytä tiedosto

@@ -1,4 +1,4 @@
package com.iformall.service.pay.service.pay.wx;
package com.iformall.service.pay.service.pay.wx.v2;

import java.io.File;
import java.util.Date;

mallinkService/src/main/java/com/iformall/service/pay/service/pay/wx/h5/WxH5PayService.java → mallinkService/src/main/java/com/iformall/service/pay/service/pay/wx/v2/h5/WxH5PayService.java Näytä tiedosto

@@ -1,4 +1,4 @@
package com.iformall.service.pay.service.pay.wx.h5;
package com.iformall.service.pay.service.pay.wx.v2.h5;

import java.io.File;
import java.util.Date;
@@ -16,7 +16,7 @@ import com.iformall.service.pay.entity.PayExtraParam;
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.BaseWxPayAdapterService;
import com.iformall.service.pay.service.pay.wx.v2.BaseWxPayAdapterService;

@Service
public class WxH5PayService extends BaseWxPayAdapterService implements CDrivingPayService{

mallinkService/src/main/java/com/iformall/service/pay/service/pay/wx/miniApp/appPay/WxMiniAppPayAdapterService.java → mallinkService/src/main/java/com/iformall/service/pay/service/pay/wx/v2/miniApp/appPay/WxMiniAppPayAdapterService.java Näytä tiedosto

@@ -1,4 +1,4 @@
package com.iformall.service.pay.service.pay.wx.miniApp.appPay;
package com.iformall.service.pay.service.pay.wx.v2.miniApp.appPay;

import java.io.File;
import java.util.Date;
@@ -28,7 +28,7 @@ import com.iformall.service.pay.entity.PayExtraParam;
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.BaseWxPayAdapterService;
import com.iformall.service.pay.service.pay.wx.v2.BaseWxPayAdapterService;
import com.iformall.utils.BeanUtils;
import com.iformall.utils.MapUtil;
import com.iformall.utils.Utility;

mallinkService/src/main/java/com/iformall/service/pay/service/pay/wx/miniApp/maPay/WxMiniMaPayAdapterService.java → mallinkService/src/main/java/com/iformall/service/pay/service/pay/wx/v2/miniApp/maPay/WxMiniMaPayAdapterService.java Näytä tiedosto

@@ -1,4 +1,4 @@
package com.iformall.service.pay.service.pay.wx.miniApp.maPay;
package com.iformall.service.pay.service.pay.wx.v2.miniApp.maPay;

import java.io.File;
import java.util.Date;
@@ -31,7 +31,7 @@ import com.iformall.service.pay.service.pay.CPassivePayService;
import com.iformall.service.pay.service.pay.entity.CreateUser;
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.BaseWxPayAdapterService;
import com.iformall.service.pay.service.pay.wx.v2.BaseWxPayAdapterService;
import com.iformall.utils.BeanUtils;
import com.iformall.utils.Utility;
import lombok.extern.slf4j.Slf4j;

+ 81
- 0
mallinkService/src/main/java/com/iformall/service/pay/service/pay/wx/v3/h5/WxH5PayV3Service.java Näytä tiedosto

@@ -0,0 +1,81 @@
package com.iformall.service.pay.service.pay.wx.v3.h5;

import java.io.File;
import java.util.Date;
import java.util.List;
import java.util.Map;

import com.iformall.common.ErrorCode;
import com.iformall.domain.po.*;
import com.iformall.exception.MallinkException;
import org.springframework.stereotype.Service;

import com.iformall.enums.EnumPayShare;
import com.iformall.service.order.entity.WxComposeOrder;
import com.iformall.service.pay.entity.PayExtraParam;
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;

@Service
public class WxH5PayV3Service implements CDrivingPayService{

@Override
public PayAdapterResult pay(WxPayAccount payAccount, WxPayOrder record,WxComposeOrder composeOrder,String productName, EnumPayShare isShare,
WxAppinfo appInfo, Date currentDate, PayExtraParam params) throws Exception {
// TODO Auto-generated method stub
return null;
}

@Override
public PayQueryAdapterResult queryPayStatus(WxPayOrder oldRecord, WxAppinfo appInfo,
WxPayAccount payAccount) throws Exception {
//return super.queryPayStatus(oldRecord, appInfo, payAccount);
return null;
}

@Override
public int queryPayStatus(PayQueryAdapterResult statusObject, String orderOutNo) throws Exception {
//return super.queryPayStatus(statusObject, orderOutNo);
return 0;
}

@Override
public int queryPayStatusCode(WxPayOrder oldRecord, WxAppinfo appInfo, WxPayAccount payAccount)
throws Exception {
//return super.queryPayStatusCode(oldRecord, appInfo, payAccount);
return 0;
}

@Override
public PayAdapterResult payOrderClose(WxAppinfo appInfo, WxPayOrder record, WxPayAccount payAccount)
throws Exception {
// TODO Auto-generated method stub
return null;
}

@Override
public PayAdapterResult payOrderReverse(WxAppinfo appInfo, WxPayOrder record, WxPayAccount payAccount)
throws Exception {
// TODO Auto-generated method stub
return null;
}

@Override
public PayAdapterResult payOrderPush(String openId,WxAppinfo appInfo, WxBatchOrder batchOrder,WxPayOrder payOrder) throws Exception {
return null;
}

@Override
public File getQrcode(WxAppinfo appinfo,String pageUrl,int type,String sceneParam) throws Exception{
// TODO Auto-generated method stub
return null;
}

@Override
public PayAdapterResult noCreatePay(WxPayOrder record, WxComposeOrder composeOrder, List<WxOrder> childOrders) {
throw new MallinkException(ErrorCode.SYS_PARAMETER_ERROR);
}

}

+ 291
- 0
mallinkService/src/main/java/com/iformall/service/pay/service/pay/wx/v3/miniApp/appPay/WxMiniAppPayV3AdapterService.java Näytä tiedosto

@@ -0,0 +1,291 @@
package com.iformall.service.pay.service.pay.wx.v3.miniApp.appPay;

import java.io.File;
import java.util.Date;
import java.util.List;
import java.util.Map;

import com.iformall.domain.po.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.iformall.common.ErrorCode;
import com.iformall.common.Result;
import com.iformall.common.ResultData;
import com.iformall.enums.EnumOrderStatus;
import com.iformall.enums.EnumPayMode;
import com.iformall.enums.EnumPayShare;
import com.iformall.enums.EnumPayStatus;
import com.iformall.exception.MallinkException;
import com.iformall.pay.WxPay;
import com.iformall.pay.WxPayOrderP;
import com.iformall.pay.WxPayOrderSP;
import com.iformall.pay.WxPayment;
import com.iformall.service.order.entity.WxComposeOrder;
import com.iformall.service.pay.entity.PayExtraParam;
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.utils.BeanUtils;
import com.iformall.utils.MapUtil;
import com.iformall.utils.Utility;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class WxMiniAppPayV3AdapterService implements CDrivingPayService{

JSONObject errorMap = JSON.parseObject("{" +
"\"NOAUTH\":{\"detail\":\"商户无此接口权限\",\"reason\":\"商户未开通此接口权限\",\"resolution\":\"请商户前往申请此接口权限\"}," +
"\"NOTENOUGH\":{\"detail\":\"余额不足\",\"reason\":\"用户帐号余额不足\",\"resolution\":\"用户帐号余额不足,请用户充值或更换支付卡后再支付\"}," +
"\"ORDERPAID\":{\"detail\":\"商户订单已支付\",\"reason\":\"商户订单已支付,无需重复操作\",\"resolution\":\"商户订单已支付,无需更多操作\"}," +
"\"ORDERCLOSED\":{\"detail\":\"订单已关闭\",\"reason\":\"当前订单已关闭,无法支付\",\"resolution\":\"当前订单已关闭,请重新下单\"}," +
"\"SYSTEMERROR\":{\"detail\":\"系统错误\t\",\"reason\":\"系统超时\",\"resolution\":\"系统异常,请用相同参数重新调用\"}," +
"\"APPID_NOT_EXIST\":{\"detail\":\"APPID不存在\",\"reason\":\"参数中缺少APPID\",\"resolution\":\"请检查APPID是否正确\"}," +
"\"MCHID_NOT_EXIST\":{\"detail\":\"MCHID不存在\",\"reason\":\"参数中缺少MCHID\",\"resolution\":\"请检查MCHID是否正确\"}," +
"\"APPID_MCHID_NOT_MATCH\":{\"detail\":\"appid和mch_id不匹配\",\"reason\":\"appid和mch_id不匹配\",\"resolution\":\"请确认appid和mch_id是否匹配\"}," +
"\"LACK_PARAMS\":{\"detail\":\"缺少参数\t\",\"reason\":\"缺少必要的请求参数\",\"resolution\":\"请检查参数是否齐全\"}," +
"\"OUT_TRADE_NO_USED\":{\"detail\":\"商户订单号重复\",\"reason\":\"同一笔交易不能多次提交\",\"resolution\":\"请核实商户订单号是否重复提交\"}," +
"\"SIGNERROR\":{\"detail\":\"签名错误\",\"reason\":\"参数签名结果不正确\",\"resolution\":\"请检查签名参数和方法是否都符合签名算法要求\"}," +
"\"XML_FORMAT_ERROR\":{\"detail\":\"XML格式错误\t\",\"reason\":\"XML格式错误\",\"resolution\":\"请检查XML参数格式是否正确\"}," +
"\"REQUIRE_POST_METHOD\":{\"detail\":\"请使用post方法\",\"reason\":\"未使用post传递参数\",\"resolution\":\"请检查请求参数是否通过post方法提交\"}," +
"\"POST_DATA_EMPTY\":{\"detail\":\"post数据为空\",\"reason\":\"post数据不能为空\",\"resolution\":\"请检查post数据是否为空\"}," +
"\"NOT_UTF8\":{\"detail\":\"编码格式错误\",\"reason\":\"未使用指定编码格式\",\"resolution\":\"请使用UTF-8编码格式\"}}");
private WxPayOrderP generateWxPayOrderP(WxPayAccount payAccount,WxComposeOrder composeOrder,String productName, WxPayOrder record,String openId,String appId,Date currentDate) throws Exception {
// 统一下单 普通商户模式
String noncestr = Utility.generate32UUID();
WxPayOrderP wxPayOrderP = new WxPayOrderP();
wxPayOrderP.setOpenid(openId);
wxPayOrderP.setAppid(appId);
wxPayOrderP.setMch_id(payAccount.getMchId());
wxPayOrderP.setNonce_str(noncestr);
wxPayOrderP.setBody(productName);
wxPayOrderP.setOut_trade_no(record.getPayOrderNo());
wxPayOrderP.setTotal_fee(composeOrder.getPayment());
wxPayOrderP.setSpbill_create_ip(record.getIp()); // 终端IP
wxPayOrderP.setGoods_tag(productName);
wxPayOrderP.setNotify_url(payAccount.getPayNotifyUrl());
wxPayOrderP.setTrade_type(WxPay.TradeType.JSAPI.name()); // 终端类型
wxPayOrderP.setProduct_id(String.valueOf(composeOrder.getMainOrderId())); // 订单ID
wxPayOrderP.setTime_start(Utility.getDataFormatStringYYYYMMDDHHmmss(currentDate));
Date futureDate = new Date();
futureDate.setTime(currentDate.getTime() + 15 * 60 * 1000);
wxPayOrderP.setTime_expire(Utility.getDataFormatStringYYYYMMDDHHmmss(futureDate)); // 15分钟后结束
Map<String, String> payOrderMap = BeanUtils.toStringMap(wxPayOrderP);
wxPayOrderP.setSign(WxPayment.createSign(payOrderMap, payAccount.getApiKey()));
return wxPayOrderP;
}
private PayAdapterResult getOrderPResult(Map<String, String> returnMap,WxPayOrder record,WxPayAccount payAccount,String noncestr) {
PayAdapterResult par = new PayAdapterResult();
returnMap.put("payOrderId", String.valueOf(record.getId()));
String result_code = returnMap.get("result_code");
if ("SUCCESS".equals(result_code)) {
par.setSuccess(true);
par.setMsg("success.");
par.setData(returnMap);
String prepay_id = returnMap.get("prepay_id");
// update payOrder with prepay_id
record.setPrepayId(prepay_id);
record.setUpdateTime(new Date());
record.setPayOrderStatus(EnumPayStatus.PAY_STATUS_SUCCESS.getCode());

String timestamp = String.valueOf(Utility.getCurrentTimeStamp());
Map<String, String> sighMap = MapUtil.getOrderMap();
sighMap.put("appId", returnMap.get("appid"));
sighMap.put("timeStamp", timestamp);
sighMap.put("nonceStr", noncestr);
sighMap.put("package", "prepay_id=" + prepay_id);
sighMap.put("signType", "MD5");
String signAgent = WxPayment.createSign(sighMap, payAccount.getApiKey());
returnMap.put("timeStamp", timestamp);
returnMap.put("nonceStr", noncestr);
returnMap.put("package", "prepay_id=" + prepay_id);
returnMap.put("paySign", signAgent);
log.info("back to UI: " + returnMap.toString());
} else {
String errMsg = "";
JSONObject errObj = errorMap.getJSONObject(result_code);
if (errObj != null) {
errMsg = errObj.toJSONString();
record.setFailReason(errMsg);
} else {
errMsg = returnMap.get("return_msg");
record.setFailReason(errMsg);
}
record.setUpdateTime(new Date());
par.setSuccess(false);
par.setMsg(errMsg);
par.setData(returnMap);
}
return par;
}
private WxPayOrderSP generateWxPayOrderSP(WxPayAccount payAccount, WxComposeOrder composeOrder,String productName,WxPayOrder record,WxAppinfo appInfo,String openId,String appId,Date currentDate,EnumPayShare isShare) throws Exception {
String noncestr = Utility.generate32UUID();
WxPayOrderSP wxPayOrderSP = new WxPayOrderSP();
wxPayOrderSP.setSub_openid(openId);
wxPayOrderSP.setAppid(appInfo.getParentAppId());
wxPayOrderSP.setMch_id(payAccount.getMchId());
wxPayOrderSP.setSub_appid(appId);
wxPayOrderSP.setSub_mch_id(payAccount.getSubMchId());
wxPayOrderSP.setNonce_str(noncestr);
wxPayOrderSP.setBody(productName);
wxPayOrderSP.setOut_trade_no(record.getPayOrderNo());
wxPayOrderSP.setTotal_fee(composeOrder.getPayment().toString());
wxPayOrderSP.setSpbill_create_ip(record.getIp()); // 终端IP
wxPayOrderSP.setGoods_tag(productName); // 券ID
wxPayOrderSP.setNotify_url(payAccount.getPayNotifyUrl());
wxPayOrderSP.setTrade_type(WxPay.TradeType.JSAPI.name()); // 终端类型
wxPayOrderSP.setProduct_id(String.valueOf(composeOrder.getMainOrderId())); //
wxPayOrderSP.setTime_start(Utility.getDataFormatStringYYYYMMDDHHmmss(currentDate));
Date futureDate = new Date();
futureDate.setTime(currentDate.getTime() + 15 * 60 * 1000);
wxPayOrderSP.setTime_expire(Utility.getDataFormatStringYYYYMMDDHHmmss(futureDate)); // 15分钟后结束
wxPayOrderSP.setSign_type("HMAC-SHA256");
wxPayOrderSP.setProfit_sharing(null);
if (isShare == EnumPayShare.YES) {
wxPayOrderSP.setProfit_sharing("Y");
}
Map<String, String> payOrderMap = BeanUtils.toStringMap(wxPayOrderSP);
wxPayOrderSP.setSign(WxPayment.createSignHMAC(payOrderMap, payAccount.getApiKey()));
return wxPayOrderSP;
}
private PayAdapterResult getOrderSPResult(Map<String, String> returnMap,WxPayOrder record,WxPayAccount payAccount,WxAppinfo appInfo,String noncestr) {
PayAdapterResult par = new PayAdapterResult();
returnMap.put("payOrderId", String.valueOf(record.getId()));
String result_code = returnMap.get("result_code");
if ("SUCCESS".equals(result_code)) {
par.setSuccess(true);
par.setMsg("success.");
par.setData(returnMap);
String prepay_id = returnMap.get("prepay_id");
// update payOrder with prepay_id
record.setPrepayId(prepay_id);
record.setUpdateTime(new Date());

String timestamp = String.valueOf(Utility.getCurrentTimeStamp());
Map<String, String> sighMap = MapUtil.getOrderMap();
sighMap.put("appId", appInfo.getAppId());
sighMap.put("timeStamp", timestamp);
sighMap.put("nonceStr", noncestr);
sighMap.put("package", "prepay_id=" + prepay_id);
sighMap.put("signType", "HMAC-SHA256");
String signAgent = WxPayment.createSignHMAC(sighMap, payAccount.getApiKey());
returnMap.put("timeStamp", timestamp);
returnMap.put("nonceStr", noncestr);
returnMap.put("package", "prepay_id=" + prepay_id);
returnMap.put("paySign", signAgent);
returnMap.put("signType", "HMAC-SHA256");
log.info("back to UI: " + returnMap.toString());
} else {
String errMsg = "";
JSONObject errObj = errorMap.getJSONObject(result_code);
if (errObj != null) {
errMsg = errObj.toJSONString();
record.setFailReason(errMsg);
} else {
errMsg = returnMap.get("return_msg");
record.setFailReason(errMsg);
}
record.setUpdateTime(new Date());
par.setSuccess(false);
par.setMsg(errMsg);
par.setData(returnMap);
}
return par;
}
/**
* https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_8_2.shtml
*/
@Override
public PayAdapterResult pay(WxPayAccount payAccount, WxPayOrder record,WxComposeOrder composeOrder,String productName,EnumPayShare isShare,WxAppinfo appInfo,Date currentDate, PayExtraParam params) throws Exception {
if (null == params ) {
throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(),"openId为空");
}
String openId = (String) params.getValue("openId");
if (StringUtils.isBlank(openId) ) {
throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(),"openId为空");
}
//普通商户模式
if (payAccount.getType() == EnumPayMode.MCH.getCode()) {
WxPayOrderP wxPayOrderP = generateWxPayOrderP(payAccount,composeOrder,productName,record,openId,appInfo.getAppId(),currentDate);
String response = WxPay.pushOrder(BeanUtils.toStringMap(wxPayOrderP));
log.info("pay order, wechat pushOrder, " + wxPayOrderP.toString() + ", response: " + response.toString());
Map<String, String> returnMap = WxPayment.xmlToMap(response);
return getOrderPResult(returnMap,record,payAccount,wxPayOrderP.getNonce_str());
} else {
// 统一下单 // 服务商模式
WxPayOrderSP wxPayOrderSP = generateWxPayOrderSP(payAccount,composeOrder,productName,record,appInfo,openId,appInfo.getAppId(),currentDate,isShare);
String response = WxPay.pushOrder(BeanUtils.toStringMap(wxPayOrderSP));
log.info("pay order, wechat pushOrder, " + wxPayOrderSP.toString() + ", response: " + response.toString());
Map<String, String> returnMap = WxPayment.xmlToMap(response);
return getOrderSPResult(returnMap,record,payAccount,appInfo,wxPayOrderSP.getNonce_str());
}
}

@Override
public PayQueryAdapterResult queryPayStatus(WxPayOrder oldRecord, WxAppinfo appInfo,
WxPayAccount payAccount) throws Exception {
//return super.queryPayStatus(oldRecord,appInfo, payAccount);
return null;
}

@Override
public int queryPayStatus(PayQueryAdapterResult statusObject, String orderOutNo) throws Exception {
//return super.queryPayStatus(statusObject, orderOutNo);
return 0;
}

@Override
public int queryPayStatusCode(WxPayOrder oldRecord, WxAppinfo appInfo, WxPayAccount payAccount)
throws Exception {
//return super.queryPayStatusCode(oldRecord, appInfo, payAccount);
return 0;
}

@Override
public PayAdapterResult payOrderClose(WxAppinfo appInfo, WxPayOrder record,WxPayAccount payAccount) throws Exception {
//return super.closeOrder(appInfo, record, payAccount);
return null;
}

@Override
public PayAdapterResult payOrderReverse(WxAppinfo appInfo, WxPayOrder record, WxPayAccount payAccount)
throws Exception {
//return super.payOrderReverse(appInfo, record, payAccount);
return null;
}

@Override
public PayAdapterResult payOrderPush(String openId,WxAppinfo appInfo, WxBatchOrder batchOrder,WxPayOrder payOrder) throws Exception {
return null;
}

@Override
public File getQrcode(WxAppinfo appinfo,String pageUrl,int type,String sceneParam) throws Exception{
//return super.getQrCode(appinfo, pageUrl, type, sceneParam);
return null;
}

@Override
public PayAdapterResult noCreatePay(WxPayOrder record, WxComposeOrder composeOrder, List<WxOrder> childOrders) {
throw new MallinkException(ErrorCode.SYS_PARAMETER_ERROR);
}

}

+ 275
- 0
mallinkService/src/main/java/com/iformall/service/pay/service/pay/wx/v3/miniApp/maPay/WxMiniMaPayV3AdapterService.java Näytä tiedosto

@@ -0,0 +1,275 @@
package com.iformall.service.pay.service.pay.wx.v3.miniApp.maPay;

import java.io.File;
import java.util.Date;
import java.util.List;
import java.util.Map;

import com.iformall.domain.po.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.iformall.common.ErrorCode;
import com.iformall.common.IdWorker;
import com.iformall.domain.po.base.TenantEntity;
import com.iformall.enums.EnumPayMode;
import com.iformall.enums.EnumPayShare;
import com.iformall.enums.EnumUserIsSubscribe;
import com.iformall.exception.MallinkException;
import com.iformall.mapper.WxCUserBasicInfoMapper;
import com.iformall.mapper.WxCUserMapper;
import com.iformall.mapper.WxMallMapper;
import com.iformall.pay.WxMicroPayOrderP;
import com.iformall.pay.WxMicroPayOrderSP;
import com.iformall.pay.WxPay;
import com.iformall.pay.WxPayment;
import com.iformall.service.WxCUserService;
import com.iformall.service.order.entity.WxComposeOrder;
import com.iformall.service.pay.entity.PayExtraParam;
import com.iformall.service.pay.service.pay.CPassivePayService;
import com.iformall.service.pay.service.pay.entity.CreateUser;
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.utils.BeanUtils;
import com.iformall.utils.Utility;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;


@Slf4j
@Service
public class WxMiniMaPayV3AdapterService implements CPassivePayService{

private WxMicroPayOrderP generateWxMicroPayOrderP(WxPayAccount payAccount, WxComposeOrder composeOrder, String productName,WxPayOrder record, EnumPayShare isShare,
WxAppinfo appInfo, Date currentDate,String bAppId,String bUserPhone) throws Exception {
String noncestr = Utility.generate32UUID();
WxMicroPayOrderP wxPayOrderP = new WxMicroPayOrderP();
wxPayOrderP.setAppid(bAppId);
wxPayOrderP.setMch_id(payAccount.getMchId());
wxPayOrderP.setDevice_info(bUserPhone);
wxPayOrderP.setNonce_str(noncestr);
wxPayOrderP.setBody(productName);
wxPayOrderP.setOut_trade_no(record.getPayOrderNo());
wxPayOrderP.setTotal_fee(record.getPayAmount());
wxPayOrderP.setSpbill_create_ip(record.getIp()); // 终端IP
wxPayOrderP.setAuth_code(record.getAuthCode());
wxPayOrderP.setTime_start(Utility.getDataFormatStringYYYYMMDDHHmmss(currentDate));
Date futureDate = new Date();
futureDate.setTime(currentDate.getTime() + 15 * 60 * 1000);
wxPayOrderP.setTime_expire(Utility.getDataFormatStringYYYYMMDDHHmmss(futureDate)); // 15分钟后结束
Map<String, String> payOrderMap = BeanUtils.toStringMap(wxPayOrderP);
wxPayOrderP.setSign(WxPayment.createSign(payOrderMap, payAccount.getApiKey()));
return wxPayOrderP;
}
private PayAdapterResult getWxMicroPayOrderPResult(Map<String, String> returnMap,WxPayOrder record,WxPayAccount payAccount) {
String return_code = returnMap.get("return_code");
String result_code = returnMap.get("result_code");
PayAdapterResult pr = null;
if ("SUCCESS".equalsIgnoreCase(return_code)) {
if ("SUCCESS".equals(result_code)) {
String openId = returnMap.get("openid");
String isSubscribe = returnMap.get("is_subscribe");
String transactionId = returnMap.get("transaction_id");
record.setTransactionId(transactionId);
record.setUpdateTime(new Date());
pr = new PayAdapterResult(true, "success", returnMap,transactionId);
} else {
String err_code = returnMap.get("err_code");
String errMsg = returnMap.get("err_code_des");
if (errMsg.length() <= 0) {
errMsg = returnMap.get("return_msg");
}
record.setFailReason(errMsg);
record.setUpdateTime(new Date());
pr = new PayAdapterResult(false, errMsg, returnMap,null);
}
} else {
String errMsg = returnMap.get("return_msg");
record.setFailReason(errMsg);
record.setUpdateTime(new Date());
pr = new PayAdapterResult(false, errMsg, returnMap,null);
}
return pr;
}
private WxMicroPayOrderSP generateWxMicroPayOrderSP(WxPayAccount payAccount, WxComposeOrder composeOrder, String productName,WxPayOrder record, EnumPayShare isShare,
WxAppinfo appInfo, Date currentDate,String bUserPhone) throws Exception {
String noncestr = Utility.generate32UUID();
WxMicroPayOrderSP wxPayOrderSP = new WxMicroPayOrderSP();
wxPayOrderSP.setAppid(appInfo.getParentAppId());
wxPayOrderSP.setMch_id(payAccount.getMchId());
wxPayOrderSP.setSub_appid(appInfo.getAppId());
wxPayOrderSP.setSub_mch_id(payAccount.getSubMchId());
wxPayOrderSP.setDevice_info(bUserPhone);
wxPayOrderSP.setNonce_str(noncestr);
wxPayOrderSP.setBody(productName);
wxPayOrderSP.setOut_trade_no(record.getPayOrderNo());
wxPayOrderSP.setTotal_fee(record.getPayAmount());
wxPayOrderSP.setSpbill_create_ip(record.getIp());
wxPayOrderSP.setAuth_code(record.getAuthCode());
wxPayOrderSP.setTime_start(Utility.getDataFormatStringYYYYMMDDHHmmss(currentDate));
Date futureDate = new Date();
futureDate.setTime(currentDate.getTime() + 15 * 60 * 1000);
wxPayOrderSP.setTime_expire(Utility.getDataFormatStringYYYYMMDDHHmmss(futureDate)); // 15分钟后结束
wxPayOrderSP.setSign_type("HMAC-SHA256");
wxPayOrderSP.setProfit_sharing(null);
if (isShare == EnumPayShare.YES) {
wxPayOrderSP.setProfit_sharing("Y");
}
Map<String, String> payOrderMap = BeanUtils.toStringMap(wxPayOrderSP);
wxPayOrderSP.setSign(WxPayment.createSignHMAC(payOrderMap, payAccount.getApiKey()));
return wxPayOrderSP;
}
private PayAdapterResult getWxMicroPayOrderSPResutl(Map<String, String> returnMap,WxPayOrder record,WxPayAccount payAccount) {
PayAdapterResult pr = null;
String return_code = returnMap.get("return_code");
String result_code = returnMap.get("result_code");
if ("SUCCESS".equalsIgnoreCase(return_code)) {
if ("SUCCESS".equals(result_code)) {
String openId = returnMap.get("sub_openid");
String isSubscribe = returnMap.get("sub_is_subscribe");
String transactionId = returnMap.get("transaction_id");
record.setTransactionId(transactionId);
record.setUpdateTime(new Date());
pr = new PayAdapterResult(true, "success", returnMap,transactionId);
} else {
String err_code = returnMap.get("err_code");
String errMsg = returnMap.get("err_code_des");
if (errMsg.length() <= 0) {
errMsg = returnMap.get("return_msg");
}
record.setFailReason(errMsg);
record.setUpdateTime(new Date());
pr = new PayAdapterResult(false, errMsg, returnMap,null);
}
} else {
String errMsg = returnMap.get("return_msg");
record.setFailReason(errMsg);
record.setUpdateTime(new Date());
pr = new PayAdapterResult(false, errMsg, returnMap,null);
}
return pr;
}
@Override
public PayAdapterResult pay(WxPayAccount payAccount, WxPayOrder record, WxComposeOrder composeOrder,String productName, EnumPayShare isShare,
WxAppinfo appInfo, Date currentDate, PayExtraParam params) throws Exception {
if (payAccount.getType() == EnumPayMode.MCH.getCode()) {
// 扫码支付 普通商户模式
String bAppId = (String) params.getValue("bAppId");
if (StringUtils.isBlank(bAppId)) {
throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(),"bAppId 不能为空");
}
String bUserPhone = (String) params.getValue("bUserPhone");
if (StringUtils.isBlank(bUserPhone)) {
throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(),"bUserPhone 不能为空");
}
WxMicroPayOrderP wxPayOrderP = generateWxMicroPayOrderP(payAccount, composeOrder,productName,record, isShare, appInfo, currentDate, bAppId, bUserPhone);
String response = WxPay.micropay(BeanUtils.toStringMap(wxPayOrderP));
log.info("pay order, wechat micropay, " + wxPayOrderP.toString() + ", response: " + response.toString());
Map<String, String> returnMap = WxPayment.xmlToMap(response);
returnMap.put("payOrderId", record.getPayOrderNo());
returnMap.put("orderId", String.valueOf(composeOrder.getMainOrderId()));
return getWxMicroPayOrderPResult(returnMap, record, payAccount);
} else {
// 统一下单 // 服务商模式
String bUserPhone = (String) params.getValue("bUserPhone");
if (StringUtils.isBlank(bUserPhone)) {
throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(),"bUserPhone 不能为空");
}
WxMicroPayOrderSP wxPayOrderSP = generateWxMicroPayOrderSP(payAccount, composeOrder,productName,record, isShare, appInfo, currentDate, bUserPhone);
String response = WxPay.micropay(BeanUtils.toStringMap(wxPayOrderSP));
log.info("pay order, wechat micropay, " + wxPayOrderSP.toString() + ", response: " + response.toString());
Map<String, String> returnMap = WxPayment.xmlToMap(response);
returnMap.put("payOrderId", record.getPayOrderNo());
returnMap.put("orderId", String.valueOf(composeOrder.getMainOrderId()));
return getWxMicroPayOrderSPResutl(returnMap, record, payAccount);
}
}

@Autowired
WxCUserMapper wxCUserMapper;
@Autowired
WxCUserService wxCUserService;
@Autowired
WxCUserBasicInfoMapper wxCUserBasicInfoMapper;
@Autowired
WxMallMapper wxMallMapper;
@Override
public CreateUser getCUserAfterPay(Object result,WxAppinfo appInfo) throws Exception {
// add c_user, 收银台支付和券支付可能不是同一个人
WxCUser userQ = new WxCUser();
Map<String, String> returnMap = (Map<String, String>) result;
String openId = returnMap.get("sub_openid");
//String isSubscribe = returnMap.get("sub_is_subscribe");
userQ.setOpenId(openId);
userQ.setAppId(appInfo.getAppId());
userQ.updateTenantInfo(appInfo);
WxCUser user1 = wxCUserMapper.findByOpenId(userQ);
if (user1 == null) {
return null;
}else {
return new CreateUser(user1.getId(),user1.getUserId());
}
}

@Override
public PayQueryAdapterResult queryPayStatus(WxPayOrder oldRecord, WxAppinfo appInfo,
WxPayAccount payAccount) throws Exception {
//return super.queryPayStatus(oldRecord,appInfo, payAccount);
return null;
}

@Override
public int queryPayStatus(PayQueryAdapterResult statusObject, String orderOutNo) throws Exception {
//return super.queryPayStatus(statusObject, orderOutNo);
return 0;
}

@Override
public int queryPayStatusCode(WxPayOrder oldRecord, WxAppinfo appInfo, WxPayAccount payAccount)
throws Exception {
//return super.queryPayStatusCode(oldRecord, appInfo, payAccount);
return 0;
}

@Override
public PayAdapterResult payOrderClose(WxAppinfo appInfo, WxPayOrder record,WxPayAccount payAccount) throws Exception {
//return super.closeOrder(appInfo, record, payAccount);
return null;
}

@Override
public PayAdapterResult payOrderReverse(WxAppinfo appInfo, WxPayOrder record, WxPayAccount payAccount)
throws Exception {
//return super.payOrderReverse(appInfo, record, payAccount);
return null;
}

@Override
public PayAdapterResult payOrderPush(String openId,WxAppinfo appInfo, WxBatchOrder batchOrder,WxPayOrder payOrder) throws Exception {
return null;
}

@Override
public File getQrcode(WxAppinfo appinfo,String pageUrl,int type,String sceneParam) throws Exception {
//return super.getQrCode(appinfo, pageUrl, type, sceneParam);
return null;
}

@Override
public PayAdapterResult noCreatePay(WxPayOrder record, WxComposeOrder composeOrder, List<WxOrder> childOrders) {
throw new MallinkException(ErrorCode.SYS_PARAMETER_ERROR);
}


}

mallinkService/src/main/java/com/iformall/service/pay/service/refund/wx/WxRefundAdapterService.java → mallinkService/src/main/java/com/iformall/service/pay/service/refund/wx/v2/WxRefundAdapterService.java Näytä tiedosto

@@ -1,4 +1,4 @@
package com.iformall.service.pay.service.refund.wx;
package com.iformall.service.pay.service.refund.wx.v2;

import java.util.List;
import java.util.Map;

+ 685
- 0
mallinkService/src/main/java/com/iformall/service/pay/service/refund/wx/v3/WxRefundV3AdapterService.java Näytä tiedosto

@@ -0,0 +1,685 @@
package com.iformall.service.pay.service.refund.wx.v3;

import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.iformall.common.ErrorCode;
import com.iformall.common.Result;
import com.iformall.common.ResultData;
import com.iformall.domain.po.WxAppinfo;
import com.iformall.domain.po.WxPayAccount;
import com.iformall.domain.po.WxPayOrder;
import com.iformall.domain.po.WxRefundOrder;
import com.iformall.enums.EnumPayMode;
import com.iformall.enums.EnumPayType;
import com.iformall.enums.EnumPayWay;
import com.iformall.enums.EnumRefundStatus;
import com.iformall.exception.MallinkException;
import com.iformall.mapper.WxAppinfoMapper;
import com.iformall.mapper.WxPayAccountMapper;
import com.iformall.mapper.WxPayOrderMapper;
import com.iformall.mapper.WxRefundOrderMapper;
import com.iformall.pay.WxPay;
import com.iformall.pay.WxPayment;
import com.iformall.pay.WxRefundOrderP;
import com.iformall.pay.WxRefundOrderSP;
import com.iformall.service.pay.service.refund.RefundPayAdapterService;
import com.iformall.service.pay.service.refund.entity.RefundAdapterResult;
import com.iformall.service.pay.service.refund.entity.RefundNotifyAdapterResult;
import com.iformall.utils.BeanUtils;
import com.iformall.utils.CipherUtil;
import com.iformall.utils.Utility;
import com.iformall.utils.XmlUtil;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class WxRefundV3AdapterService implements RefundPayAdapterService{

JSONObject errorRefundReqMap = JSON.parseObject("{\n" +
" \"SYSTEMERROR\": {\n" +
" \"detail\": \"接口返回错误\",\n" +
" \"reason\": \"系统超时等\",\n" +
" \"resolution\": \"请不要更换商户退款单号,请使用相同参数再次调用API。\"\n" +
" },\n" +
" \"BIZERR_NEED_RETRY\": {\n" +
" \"detail\": \"退款业务流程错误,需要商户触发重试来解决\",\n" +
" \"reason\": \"并发情况下,业务被拒绝,商户重试即可解决\",\n" +
" \"resolution\": \"请不要更换商户退款单号,请使用相同参数再次调用API。\"\n" +
" },\n" +
" \"TRADE_OVERDUE\": {\n" +
" \"detail\": \"订单已经超过退款期限\",\n" +
" \"reason\": \"订单已经超过可退款的最大期限(支付后一年内可退款)\\t\",\n" +
" \"resolution\": \"请选择其他方式自行退款\"\n" +
" },\n" +
" \"ERROR\": {\n" +
" \"detail\": \"业务错误\",\n" +
" \"reason\": \"申请退款业务发生错误\",\n" +
" \"resolution\": \"该错误都会返回具体的错误原因,请根据实际返回做相应处理。\"\n" +
" },\n" +
" \"USER_ACCOUNT_ABNORMAL\": {\n" +
" \"detail\": \"退款请求失败\",\n" +
" \"reason\": \"用户帐号注销\",\n" +
" \"resolution\": \"此状态代表退款申请失败,商户可自行处理退款。\"\n" +
" },\n" +
" \"INVALID_REQ_TOO_MUCH\": {\n" +
" \"detail\": \"无效请求过多\",\n" +
" \"reason\": \"连续错误请求数过多被系统短暂屏蔽\\t\",\n" +
" \"resolution\": \"请检查业务是否正常,确认业务正常后请在1分钟后再来重试\"\n" +
" },\n" +
" \"NOTENOUGH\": {\n" +
" \"detail\": \"余额不足\",\n" +
" \"reason\": \"商户可用退款余额不足\",\n" +
" \"resolution\": \"此状态代表退款申请失败,商户可根据具体的错误提示做相应的处理。\"\n" +
" },\n" +
" \"INVALID_TRANSACTIONID\": {\n" +
" \"detail\": \"无效transaction_id\",\n" +
" \"reason\": \"请求参数未按指引进行填写\",\n" +
" \"resolution\": \"请求参数错误,检查原交易号是否存在或发起支付交易接口返回失败\"\n" +
" },\n" +
" \"PARAM_ERROR\": {\n" +
" \"detail\": \"参数错误\",\n" +
" \"reason\": \"请求参数未按指引进行填写\",\n" +
" \"resolution\": \"请求参数错误,请重新检查再调用退款申请\"\n" +
" },\n" +
" \"APPID_NOT_EXIST\": {\n" +
" \"detail\": \"APPID不存在\",\n" +
" \"reason\": \"参数中缺少APPID\",\n" +
" \"resolution\": \"请检查APPID是否正确\"\n" +
" },\n" +
" \"MCHID_NOT_EXIST\": {\n" +
" \"detail\": \"MCHID不存在\",\n" +
" \"reason\": \"参数中缺少MCHID\",\n" +
" \"resolution\": \"请检查MCHID是否正确\"\n" +
" },\n" +
" \"REQUIRE_POST_METHOD\": {\n" +
" \"detail\": \"请使用post方法\",\n" +
" \"reason\": \"未使用post传递参数\",\n" +
" \"resolution\": \"请检查请求参数是否通过post方法提交\"\n" +
" },\n" +
" \"SIGNERROR\": {\n" +
" \"detail\": \"签名错误\",\n" +
" \"reason\": \"参数签名结果不正确\",\n" +
" \"resolution\": \"请检查签名参数和方法是否都符合签名算法要求\"\n" +
" },\n" +
" \"XML_FORMAT_ERROR\": {\n" +
" \"detail\": \"XML格式错误\",\n" +
" \"reason\": \"XML格式错误\",\n" +
" \"resolution\": \"请检查XML参数格式是否正确\"\n" +
" },\n" +
" \"FREQUENCY_LIMITED\": {\n" +
" \"detail\": \"频率限制\",\n" +
" \"reason\": \"2个月之前的订单申请退款有频率限制\",\n" +
" \"resolution\": \"该笔退款未受理,请降低频率后重试\"\n" +
" }\n" +
"}");
JSONObject errorRefundQueryMap = JSON.parseObject("{\n" +
" \"SYSTEMERROR\": {\n" +
" \"detail\": \"接口返回错误\",\n" +
" \"reason\": \"系统超时等\",\n" +
" \"resolution\": \"请不要更换商户退款单号,请使用相同参数再次调用API。\"\n" +
" },\n" +
" \"BIZERR_NEED_RETRY\": {\n" +
" \"detail\": \"退款业务流程错误,需要商户触发重试来解决\",\n" +
" \"reason\": \"并发情况下,业务被拒绝,商户重试即可解决\",\n" +
" \"resolution\": \"请不要更换商户退款单号,请使用相同参数再次调用API。\"\n" +
" },\n" +
" \"TRADE_OVERDUE\": {\n" +
" \"detail\": \"订单已经超过退款期限\",\n" +
" \"reason\": \"订单已经超过可退款的最大期限(支付后一年内可退款)\\t\",\n" +
" \"resolution\": \"请选择其他方式自行退款\"\n" +
" },\n" +
" \"ERROR\": {\n" +
" \"detail\": \"业务错误\",\n" +
" \"reason\": \"申请退款业务发生错误\",\n" +
" \"resolution\": \"该错误都会返回具体的错误原因,请根据实际返回做相应处理。\"\n" +
" },\n" +
" \"USER_ACCOUNT_ABNORMAL\": {\n" +
" \"detail\": \"退款请求失败\",\n" +
" \"reason\": \"用户帐号注销\",\n" +
" \"resolution\": \"此状态代表退款申请失败,商户可自行处理退款。\"\n" +
" },\n" +
" \"INVALID_REQ_TOO_MUCH\": {\n" +
" \"detail\": \"无效请求过多\",\n" +
" \"reason\": \"连续错误请求数过多被系统短暂屏蔽\\t\",\n" +
" \"resolution\": \"请检查业务是否正常,确认业务正常后请在1分钟后再来重试\"\n" +
" },\n" +
" \"NOTENOUGH\": {\n" +
" \"detail\": \"余额不足\",\n" +
" \"reason\": \"商户可用退款余额不足\",\n" +
" \"resolution\": \"此状态代表退款申请失败,商户可根据具体的错误提示做相应的处理。\"\n" +
" },\n" +
" \"INVALID_TRANSACTIONID\": {\n" +
" \"detail\": \"无效transaction_id\",\n" +
" \"reason\": \"请求参数未按指引进行填写\",\n" +
" \"resolution\": \"请求参数错误,检查原交易号是否存在或发起支付交易接口返回失败\"\n" +
" },\n" +
" \"PARAM_ERROR\": {\n" +
" \"detail\": \"参数错误\",\n" +
" \"reason\": \"请求参数未按指引进行填写\",\n" +
" \"resolution\": \"请求参数错误,请重新检查再调用退款申请\"\n" +
" },\n" +
" \"APPID_NOT_EXIST\": {\n" +
" \"detail\": \"APPID不存在\",\n" +
" \"reason\": \"参数中缺少APPID\",\n" +
" \"resolution\": \"请检查APPID是否正确\"\n" +
" },\n" +
" \"MCHID_NOT_EXIST\": {\n" +
" \"detail\": \"MCHID不存在\",\n" +
" \"reason\": \"参数中缺少MCHID\",\n" +
" \"resolution\": \"请检查MCHID是否正确\"\n" +
" },\n" +
" \"REQUIRE_POST_METHOD\": {\n" +
" \"detail\": \"请使用post方法\",\n" +
" \"reason\": \"未使用post传递参数\",\n" +
" \"resolution\": \"请检查请求参数是否通过post方法提交\"\n" +
" },\n" +
" \"SIGNERROR\": {\n" +
" \"detail\": \"签名错误\",\n" +
" \"reason\": \"参数签名结果不正确\",\n" +
" \"resolution\": \"请检查签名参数和方法是否都符合签名算法要求\"\n" +
" },\n" +
" \"XML_FORMAT_ERROR\": {\n" +
" \"detail\": \"XML格式错误\",\n" +
" \"reason\": \"XML格式错误\",\n" +
" \"resolution\": \"请检查XML参数格式是否正确\"\n" +
" },\n" +
" \"FREQUENCY_LIMITED\": {\n" +
" \"detail\": \"频率限制\",\n" +
" \"reason\": \"2个月之前的订单申请退款有频率限制\",\n" +
" \"resolution\": \"该笔退款未受理,请降低频率后重试\"\n" +
" }\n" +
"}");
private WxRefundOrderP generateWxRefundOrderP(WxPayAccount payAccount,WxAppinfo appInfo,WxRefundOrder record,WxPayOrder payOrder,EnumPayType payType) {
String noncestr = Utility.generate32UUID();
WxRefundOrderP wxRefundOrderP = new WxRefundOrderP();
wxRefundOrderP.setAppid(appInfo.getAppId());
wxRefundOrderP.setMch_id(payAccount.getMchId());
wxRefundOrderP.setNonce_str(noncestr);
// 微信内部订单号
if (record.getTransactionId() != null)
wxRefundOrderP.setTransaction_id(record.getTransactionId());
// 支付订单号
wxRefundOrderP.setOut_trade_no(payOrder.getPayOrderNo());
// 退款支付订单号
wxRefundOrderP.setOut_refund_no(String.valueOf(record.getId()));
wxRefundOrderP.setTotal_fee(record.getTotalFee());
wxRefundOrderP.setRefund_fee(record.getRefundFee());
if(null != payType) {
if (payType == EnumPayType.PAY_B_REFUND) {
wxRefundOrderP.setRefund_desc("B端商户退款");
} else if (payType == EnumPayType.PAY_ADMIN_REFUND) {
wxRefundOrderP.setRefund_desc("管理端商户退款");
} else if (payType == EnumPayType.PAY_AUTO_REFUND) {
wxRefundOrderP.setRefund_desc("超期自动退款");
} else {
wxRefundOrderP.setRefund_desc("用户自己退款");
}
}
wxRefundOrderP.setNotify_url(payAccount.getRefundNotifyUrl());
return wxRefundOrderP;
}
private RefundAdapterResult getReusltFromp(String response,WxRefundOrder record,WxPayOrder payOrder) throws MallinkException{
Map<String, String> returnMap = WxPayment.xmlToMap(response);
String result_no = returnMap.get("result_code");
String refund_id = returnMap.get("refund_id");
// 设置 微信退款订单号
record.setRefundId(refund_id);
record.setRefundVendor(payOrder.getPayVendor());
if ("SUCCESS".equals(result_no)) {
log.info("微信退款订单申请成功: " + returnMap.toString());
try {
return new RefundAdapterResult(true,EnumRefundStatus.REFUND_REQ_SUCCESS.getCode(),"退款订单申请成功",returnMap);
} catch (Exception e) {
log.error("微信退款订单更新入库出错: " + e.getMessage() + ", record: " + record.toString());
throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR);
}
} else {
String errDesc = returnMap.get("err_code_des");
if (errDesc.equalsIgnoreCase("订单已全额退款")) {
return new RefundAdapterResult(true,EnumRefundStatus.REFUND_REQ_SUCCESS.getCode(),"退款订单申请成功",returnMap);
}
log.error("微信退款订单申请失败: " + response);
String errMsg = "";
JSONObject errObj = errorRefundReqMap.getJSONObject(result_no);
if (errObj != null) {
errMsg = errObj.toJSONString();
record.setFailReason(errMsg);
} else {
errMsg = returnMap.get("return_msg");
record.setFailReason(errMsg);
}
if (errDesc.equalsIgnoreCase("超期订单不允许退款")) {
// 更新券状态
throw new MallinkException(ErrorCode.REFUND_NOT_ALLOW);
}
return new RefundAdapterResult(false, EnumRefundStatus.REFUND_REQ_FAIL.getCode(), errMsg, returnMap);
}
}
private WxRefundOrderSP generateWxRefundOrderSP(WxPayAccount payAccount,WxAppinfo appInfo,WxRefundOrder record,WxPayOrder payOrder,EnumPayType payType) {
String noncestr = Utility.generate32UUID();
WxRefundOrderSP wxRefundOrderSP = new WxRefundOrderSP();
wxRefundOrderSP.setAppid(appInfo.getParentAppId());
wxRefundOrderSP.setSub_appid(appInfo.getAppId());
wxRefundOrderSP.setMch_id(payAccount.getMchId());
wxRefundOrderSP.setSub_mch_id(payAccount.getSubMchId());
wxRefundOrderSP.setNonce_str(noncestr);
// 微信内部订单号
if (record.getTransactionId() != null)
wxRefundOrderSP.setTransaction_id(record.getTransactionId());
// 支付订单号
wxRefundOrderSP.setOut_trade_no(payOrder.getPayOrderNo());
// 退款支付订单号
wxRefundOrderSP.setOut_refund_no(String.valueOf(record.getId()));
wxRefundOrderSP.setTotal_fee(record.getTotalFee());
wxRefundOrderSP.setRefund_fee(record.getRefundFee());
if(null != payType) {
if (payType == EnumPayType.PAY_B_REFUND) {
wxRefundOrderSP.setRefund_desc("B端商户退款");
} else if (payType == EnumPayType.PAY_ADMIN_REFUND) {
wxRefundOrderSP.setRefund_desc("管理端商户退款");
} else if (payType == EnumPayType.PAY_AUTO_REFUND) {
wxRefundOrderSP.setRefund_desc("超期自动退款");
} else {
wxRefundOrderSP.setRefund_desc("用户自己退款");
}
}
wxRefundOrderSP.setNotify_url(payAccount.getRefundNotifyUrl());
wxRefundOrderSP.setSign_type("HMAC-SHA256");
return wxRefundOrderSP;
}
private RefundAdapterResult getResultFromSp(String response,WxRefundOrder record,WxPayOrder payOrder) {
Map<String, String> returnMap = WxPayment.xmlToMap(response);
String result_no = returnMap.get("result_code");
String refund_id = returnMap.get("refund_id");
// 设置 微信退款订单号
record.setRefundId(refund_id);
record.setRefundVendor(payOrder.getPayVendor());
if ("SUCCESS".equals(result_no)) {
log.info("微信退款订单申请成功: " + returnMap.toString());
try {
return new RefundAdapterResult(true, EnumRefundStatus.REFUND_REQ_SUCCESS.getCode(), "退款订单申请成功", returnMap);
} catch (Exception e) {
log.error("微信退款订单更新入库出错: " + e.getMessage() + ", record: " + record.toString());
throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR.getCode(), "订单状态更新失败");
}
} else {
// 特殊处理
String errDesc = returnMap.get("err_code_des");
if (errDesc.equalsIgnoreCase("订单已全额退款")) {
return new RefundAdapterResult(true, EnumRefundStatus.REFUND_REQ_SUCCESS.getCode(), "退款订单申请成功", returnMap);
}
log.error("微信退款订单申请失败: " + response);
String errMsg = "";
JSONObject errObj = errorRefundReqMap.getJSONObject(result_no);
if (errObj != null) {
errMsg = errObj.toJSONString();
record.setFailReason(errMsg);
} else {
errMsg = returnMap.get("err_code_des");
record.setFailReason(errMsg);
}
if (errDesc.equalsIgnoreCase("超期订单不允许退款")) {
// 更新券状态
throw new MallinkException(ErrorCode.REFUND_NOT_ALLOW);
}
return new RefundAdapterResult(false,EnumRefundStatus.REFUND_REQ_FAIL.getCode(),errMsg,returnMap);
}
}
@Override
public RefundAdapterResult refund(WxPayAccount payAccount,WxAppinfo appInfo,WxRefundOrder record,WxPayOrder payOrder,EnumPayType payType) {
if (StringUtils.isBlank(payAccount.getApiKey())) {
log.error("支付密钥为空");
throw new MallinkException(ErrorCode.API_KEY_NOT_FOUND.getCode(), "支付密钥为空,请联系商城管理员");
}
if (StringUtils.isBlank(payAccount.getCertPath())) {
log.error("证书路径为空");
throw new MallinkException(ErrorCode.CERT_PATH_NOT_FOUND.getCode(), "证书路径为空,请联系商城管理员");
}
if (!Utility.isFileExist(payAccount.getCertPath())) {
log.error("证书文件不存在");
throw new MallinkException(ErrorCode.CERT_PATH_NOT_FOUND.getCode(), "证书文件不存在,请联系商城管理员");
}

// 实际支付
// 向微信提交退款申请
if (payAccount.getType() == EnumPayMode.MCH.getCode()) {
// 普通商户模式
WxRefundOrderP wxRefundOrderP = generateWxRefundOrderP(payAccount, appInfo, record, payOrder, payType);

Map signMap = null;
try {
signMap = BeanUtils.toStringMap(wxRefundOrderP);
} catch (Exception e) {
log.error("退款命令生辰: " + e.getMessage());
throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), "退款签名异常");
}

String signAgent = WxPayment.createSign(signMap, payAccount.getApiKey());
signMap.put("sign", signAgent);
String response = null;
try {
response = WxPay.orderRefund(signMap, payAccount.getCertPath(), payAccount.getMchId());
} catch (Exception e) {
log.error("退款异常: " + e.getMessage());
throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR.getCode(), "退款异常");
}
log.info("微信退款订单:" + wxRefundOrderP.toString() + ", response: " + response.toString());
return getReusltFromp(response, record, payOrder);
} else {
// 服务商模式
WxRefundOrderSP wxRefundOrderSP = generateWxRefundOrderSP(payAccount, appInfo, record, payOrder, payType);

Map signMap = null;
try {
signMap = BeanUtils.toStringMap(wxRefundOrderSP);
} catch (Exception e) {
log.error("退款命令生成: " + e.getMessage());
throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), "退款签名异常");
}

String signAgent = WxPayment.createSignHMAC(signMap, payAccount.getApiKey());
signMap.put("sign", signAgent);
String response = null;
try {
response = WxPay.orderRefund(signMap, payAccount.getCertPath(), payAccount.getMchId());
} catch (Exception e) {
log.error("退款异常: " + e.getMessage());
throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR.getCode(), "退款异常");
}
log.info("微信退款订单:" + wxRefundOrderSP.toString() + ", response: " + response.toString());
return getResultFromSp(response, record, payOrder);
}
}

@Override
public RefundAdapterResult queryRefund(WxAppinfo appInfo,WxPayAccount payAccount, WxRefundOrder record) {
if (payAccount.getType() == EnumPayMode.MCH.getCode()) {
Map<String, String> paramMap = WxPayment.buildWeappRefundQueryMap(
appInfo.getAppId(), payAccount.getMchId(),
record.getTransactionId(), record.getPayOrderNo(), String.valueOf(record.getId()),
record.getRefundId(), payAccount.getApiKey());
String response = WxPay.orderRefundQuery(paramMap);
log.info("微信退款订单:" + record.toString() + ", response: " + response.toString());
Map<String, String> returnMap = WxPayment.xmlToMap(response);
String return_code = returnMap.get("return_code");
if("SUCCESS".equals(return_code)){
String result_code = returnMap.get("result_code");
if("SUCCESS".equals(result_code)){
String refund_status_0 = returnMap.get("refund_status_0");
if("SUCCESS".equals(refund_status_0)){
return new RefundAdapterResult(true,EnumRefundStatus.REFUND_SUCCESS.getCode(),"退款成功",returnMap);
}else if("REFUNDCLOSE".equals(refund_status_0)){
return new RefundAdapterResult(true,EnumRefundStatus.REFUND_FAIL.getCode(),"退款关闭,指商户发起退款失败的情况",returnMap);
}else if("PROCESSING".equals(refund_status_0)){
return new RefundAdapterResult(true,EnumRefundStatus.REFUND_REQ_SUCCESS.getCode(),"退款中",returnMap);
}else if("CHANGE".equals(refund_status_0)){
return new RefundAdapterResult(true,EnumRefundStatus.REFUND_FAIL.getCode(),
"退款异常,退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败。",returnMap);
}else{
throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR.getCode(),"查询状态异常 非法状态");
}
}else{
throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR.getCode(),"查询状态异常 "+returnMap.get("err_code_des"));
}
}else{
throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR.getCode(),"查询状态异常 "+returnMap.get("return_msg"));
}

// String result_no = returnMap.get("result_code");
// if ("SUCCESS".equals(result_no)) {
// String refund_id = returnMap.get("refund_id");
// return new RefundAdapterResult(true,0,"退款",returnMap);
// } else {
// String errMsg = "";
// JSONObject errObj = errorRefundReqMap.getJSONObject(result_no);
// if (errObj != null) {
// errMsg = errObj.toJSONString();
// } else {
// errMsg = returnMap.get("return_msg");
// }
// return new RefundAdapterResult(false,ErrorCode.REFUND_ORDER_ERROR.getCode(),errMsg,returnMap);
// }
} else {
Map<String, String> paramMap = WxPayment.buildSWeappRefundQueryMap(
appInfo.getParentAppId(), appInfo.getAppId(), payAccount.getMchId(), payAccount.getSubMchId(),
record.getTransactionId(), record.getPayOrderNo(), String.valueOf(record.getId()), record.getRefundId(), payAccount.getApiKey());
String response = WxPay.orderRefundQuery(paramMap);
log.info("微信退款订单:" + record.toString() + ", response: " + response.toString());
Map<String, String> returnMap = WxPayment.xmlToMap(response);
String return_code = returnMap.get("return_code");
if("SUCCESS".equals(return_code)){
String result_code = returnMap.get("result_code");
if("SUCCESS".equals(result_code)){
String refund_status_0 = returnMap.get("refund_status_0");
if("SUCCESS".equals(refund_status_0)){
return new RefundAdapterResult(true,EnumRefundStatus.REFUND_SUCCESS.getCode(),"退款成功",returnMap);
}else if("REFUNDCLOSE".equals(refund_status_0)){
return new RefundAdapterResult(true,EnumRefundStatus.REFUND_FAIL.getCode(),"退款关闭,指商户发起退款失败的情况",returnMap);
}else if("PROCESSING".equals(refund_status_0)){
return new RefundAdapterResult(true,EnumRefundStatus.REFUND_REQ_SUCCESS.getCode(),"退款中",returnMap);
}else if("CHANGE".equals(refund_status_0)){
return new RefundAdapterResult(true,EnumRefundStatus.REFUND_FAIL.getCode(),"退款异常",returnMap);
}else{
throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR.getCode(),"查询状态异常 非法状态");
}
}else{
throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR.getCode(),"查询状态异常 "+returnMap.get("err_code_des"));
}
}else{
throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR.getCode(),"查询状态异常 "+returnMap.get("return_msg"));
}
// String result_no = returnMap.get("result_code");
// if ("SUCCESS".equals(result_no)) {
// String refund_id = returnMap.get("refund_id");
// return new RefundAdapterResult(true,0,"退款",returnMap);
// } else {
// String errMsg = "";
// JSONObject errObj = errorRefundQueryMap.getJSONObject(result_no);
// if (errObj != null) {
// errMsg = errObj.toJSONString();
// } else {
// errMsg = returnMap.get("return_msg");
// }
// return new RefundAdapterResult(false,ErrorCode.REFUND_ORDER_ERROR.getCode(),errMsg,returnMap);
// }
}
}

@Autowired
WxAppinfoMapper wxAppinfoMapper;
@Autowired
WxPayAccountMapper wxPayAccountMapper;
@Autowired
WxPayOrderMapper wxPayOrderMapper;
@Autowired
WxRefundOrderMapper wxRefundOrderMapper;
private RefundNotifyAdapterResult notifyErrorResult(String msg) {
SortedMap resultMap = new TreeMap();
resultMap.put("return_code", "FAIL");
resultMap.put("return_msg", msg);
return new RefundNotifyAdapterResult(false,ErrorCode.REFUND_ORDER_ERROR.getCode(),msg,XmlUtil.getRequestXml(resultMap));
}
private RefundNotifyAdapterResult notifySuccessResult(String transactionId,String refundId,WxRefundOrder refundOrder) {
SortedMap resultMap = new TreeMap();
resultMap.put("return_code", "SUCCESS");
resultMap.put("return_msg", "OK");
return new RefundNotifyAdapterResult(transactionId, refundId,refundOrder,XmlUtil.getRequestXml(resultMap));
}
@Override
public RefundNotifyAdapterResult notify(Map<String, String> paramMap, EnumPayWay payWay) {
// how to get wechatAppId, wechatMchId, partnerKey
String appId = paramMap.get("appid");
String subAppId = paramMap.get("sub_appid");
String mchId = paramMap.get("mch_id");
String subMchId = paramMap.get("sub_mch_id");
if (StringUtils.isBlank(subAppId) && StringUtils.isBlank(subMchId)) {
// 普通商户号
WxAppinfo appinfo = wxAppinfoMapper.findByAppId(appId);
if (appinfo == null) {
log.error("未找到appid信息:" + appId);
throw new MallinkException(ErrorCode.APP_ID_NOT_FOUND);
}
WxPayAccount payAccount = wxPayAccountMapper.selectById(appinfo.getPayId());
if (payAccount == null) {
log.error("未找到mch_id信息:" + mchId);
throw new MallinkException(ErrorCode.MCH_INFO_NOT_FOUND);
}
if (!mchId.equalsIgnoreCase(payAccount.getMchId())) {
log.error("mch_id不对应:" + mchId + ",account:" + payAccount.getMchId());
throw new MallinkException(ErrorCode.MCH_INFO_NOT_EQUAL);
}
String partnerKey = payAccount.getApiKey();
try {
if (payWay.getType() == EnumPayWay.EnumPayWayType.WX_MINIPAY) {
if (!"SUCCESS".equals(paramMap.get("return_code"))) {
log.warn("notify refund, wxpay status not success, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString());
return notifyErrorResult("订单状态码非SUCCESS");
}

// 解密req_info
String req_info = CipherUtil.decryptReqInfo(paramMap.get("req_info"), partnerKey);
Map<String, String> reqMap = WxPayment.xmlToMap(req_info);

String payOrderNo = reqMap.get("out_trade_no");
Long payOrderId = Long.valueOf(payOrderNo);
WxPayOrder payOrder = wxPayOrderMapper.selectById(payOrderId,payAccount.getTenantId());
if (payOrder == null) {
log.warn("notify refund, wxpay check pay order not exists, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString());
return notifyErrorResult("支付订单不存在");
}
// 验证支付金额
if (!reqMap.get("total_fee").equals(payOrder.getPayAmount().toString())) {
log.warn("notify refund, wxpay check total_fee is invalid, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString());
return notifyErrorResult("支付订单总金额不一致");
}
String refundIdStr = reqMap.get("out_refund_no");
Long refundOrderId = Long.valueOf(refundIdStr);
WxRefundOrder refundOrder = wxRefundOrderMapper.selectById(refundOrderId);
if (refundOrder == null) {
log.warn("notify refund, wxpay check pay order not exists, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString());
return notifyErrorResult("退款订单不存在");
}
// 验证支付金额
if (!reqMap.get("total_fee").equals(refundOrder.getTotalFee().toString())) {
log.warn("notify refund, wxpay check total_fee is invalid, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString());
return notifyErrorResult("订单总金额不一致");
}
// 验证退款金额
if (!reqMap.get("refund_fee").equals(refundOrder.getRefundFee().toString())) {
log.warn("notify refund, wxpay check refund_fee is invalid, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString());
return notifyErrorResult("退款总金额不一致");
}
// 处理支付成功
//handleRefundSuccess(refundOrder, reqMap.get("transaction_id"), reqMap.get("refund_id"));
log.info("notify refund, wxpay checksign success, paramMap:{}, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString());
return notifySuccessResult(reqMap.get("transaction_id"), reqMap.get("refund_id"), refundOrder);
}
} catch (RuntimeException e) {
log.warn("notify refund paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString() + ", e:" + e.getMessage());
throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR.getCode(), e.getMessage());
} catch (Exception e) {
log.warn("notify refund, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString() + ", e:" + e.getMessage());
throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR.getCode(), e.getMessage());
}
} else {
// 服务号回调
WxAppinfo appinfo = wxAppinfoMapper.findByAppId(subAppId);
if (appinfo == null) {
log.error("未找到appid信息:" + appId);
throw new MallinkException(ErrorCode.APP_ID_NOT_FOUND);
}
WxPayAccount payAccount = wxPayAccountMapper.selectById(appinfo.getPayId());
if (payAccount == null) {
log.error("未找到mch_id信息:" + mchId);
throw new MallinkException(ErrorCode.MCH_INFO_NOT_FOUND);
}
if (!mchId.equalsIgnoreCase(payAccount.getMchId())) {
log.error("mch_id不对应:" + mchId + ",account:" + payAccount.getMchId());
throw new MallinkException(ErrorCode.MCH_INFO_NOT_EQUAL);
}
String partnerKey = payAccount.getApiKey();
try {
if (payWay.getType() == EnumPayWay.EnumPayWayType.WX_MINIPAY) {
if (!"SUCCESS".equals(paramMap.get("return_code"))) {
log.warn("notify order, wxpay status not success, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString());
return notifyErrorResult("订单状态码非SUCCESS");
}

// 解密req_info
String req_info = CipherUtil.decryptReqInfo(paramMap.get("req_info"), partnerKey);
log.info(req_info);
Map<String, String> reqMap = WxPayment.xmlToMap(req_info);

String payOrderNo = reqMap.get("out_trade_no");
if (payOrderNo == null) {
return notifySuccessResult(reqMap.get("transaction_id"), reqMap.get("refund_id"), null);
}
Long payOrderId = Long.valueOf(payOrderNo);
WxPayOrder payOrder = wxPayOrderMapper.selectById(payOrderId,payAccount.getTenantId());
if (payOrder == null) {
log.warn("notify refund, wxpay check pay order not exists, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString());
return notifyErrorResult("支付订单不存在");
}
// 验证支付金额
if (!reqMap.get("total_fee").equals(payOrder.getPayAmount().toString())) {
log.warn("notify refund, wxpay check total_fee is invalid, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString());
return notifyErrorResult("支付订单总金额不一致");
}
String refundIdStr = reqMap.get("out_refund_no");
Long refundOrderId = Long.valueOf(refundIdStr);
WxRefundOrder refundOrder = wxRefundOrderMapper.selectById(refundOrderId);
if (refundOrder == null) {
log.warn("notify refund, wxpay check pay order not exists, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString());
return notifyErrorResult("退款订单不存在");
}
// 验证支付金额
if (!reqMap.get("total_fee").equals(refundOrder.getTotalFee().toString())) {
log.warn("notify refund, wxpay check total_fee is invalid, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString());
return notifyErrorResult("订单总金额不一致");
}
// 验证退款金额
if (!reqMap.get("refund_fee").equals(refundOrder.getRefundFee().toString())) {
log.warn("notify refund, wxpay check refund_fee is invalid, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString());
return notifyErrorResult("退款总金额不一致");
}

log.info("notify refund, wxpay checksign success, paramMap:{}, paramMap: " + reqMap.toString() + ", payWay:" + payWay.toString());
return notifySuccessResult(reqMap.get("transaction_id"), reqMap.get("refund_id"), refundOrder);
}
} catch (RuntimeException e) {
log.warn("notify refund, wepay checksign error, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString() + ", e:" + e.getMessage());
throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR);
} catch (Exception e) {
log.warn("notify refund, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString() + ", e:" + e.getMessage());
throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR.getCode(), e.getMessage());
}
}

return notifyErrorResult("FAILED");
}

}

mallinkService/src/main/java/com/iformall/service/pay/service/share/wx/WxPayShareService.java → mallinkService/src/main/java/com/iformall/service/pay/service/share/wx/v2/WxPayShareService.java Näytä tiedosto

@@ -1,4 +1,4 @@
package com.iformall.service.pay.service.share.wx;
package com.iformall.service.pay.service.share.wx.v2;

import java.text.ParseException;
import java.util.*;

+ 602
- 0
mallinkService/src/main/java/com/iformall/service/pay/service/share/wx/v3/WxPayShareV3Service.java Näytä tiedosto

@@ -0,0 +1,602 @@
package com.iformall.service.pay.service.share.wx.v3;

import java.text.ParseException;
import java.util.*;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.iformall.common.IdWorker;
import com.iformall.domain.dto.WxSharingOrderDto;
import com.iformall.domain.po.*;
import com.iformall.domain.po.base.TenantEntity;
import com.iformall.douyin.pay.enums.MerchantImportStatus;
import com.iformall.enums.*;
import com.iformall.mapper.*;
import com.iformall.service.pay.service.pay.douyin.miniApp.EnumTtPayChannel;
import net.sf.saxon.trans.Err;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.iformall.common.ErrorCode;
import com.iformall.common.ResultData;
import com.iformall.exception.MallinkException;
import com.iformall.pay.WxPayment;
import com.iformall.pay.WxProfitSharing;
import com.iformall.pay.WxProfitSharingFinishP;
import com.iformall.pay.WxProfitSharingP;
import com.iformall.pay.WxProfitSharingQueryP;
import com.iformall.pay.WxProfitSharingReceiverP;
import com.iformall.service.order.util.OrderHelper;
import com.iformall.service.pay.service.share.PayShareAdapterService;
import com.iformall.service.pay.service.share.PayShareBaseAdapterService;
import com.iformall.service.pay.service.share.entity.ShareAccountResult;
import com.iformall.service.pay.service.share.entity.PayShareCalculateAmount;
import com.iformall.service.pay.service.share.entity.PayShareQueryResult;
import com.iformall.service.pay.service.share.entity.PayShareResult;
import com.iformall.service.pay.service.share.entity.ShareNotifyAdapterResult;
import com.iformall.utils.BeanUtils;
import com.iformall.utils.Utility;
import com.iformall.utils.XmlUtil;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class WxPayShareV3Service extends PayShareBaseAdapterService{

@Autowired
WxProfitSharingOrderMapper wxProfitSharingOrderMapper;

final JSONObject statusMap = JSON.parseObject(
"{\"ACCEPTED\":3," +
"\"PROCESSING\": 4," +
"\"FINISHED\": 5," +
"\"CLOSED\": 6}");
@Override
public Integer getSubsidyType() {
return EnumMerchantSubsidyType.WECHAT.getCode();
}

@Override
public Integer getProfitSharingType() {
return EnumProfitSharingType.PROFIT_SHARING_TYPE_WECHAT.getCode();
}

@Override
public Integer getSharingOrderInitialStatus() {
return EnumProfitSharingOrderStatus.PROFIT_SHARING_READY.getCode();
}

@Override
public PayShareCalculateAmount calculateAmount(Integer payAmount,Integer officialCommissionRate, WxPayAccount payAccount) {
int mallCharge = OrderHelper.getMallCharge(payAmount, payAccount);
Integer realRateAmount = OrderHelper.getRealRateAmount(payAmount, payAccount);
return new PayShareCalculateAmount(payAmount,mallCharge,realRateAmount,0);
}

@Override
public PayShareResult noReciverShare(WxAppinfo appInfo,WxPayAccount payAccount,WxProfitSharingOrder record,String transcationId,Integer amount) {
WxProfitSharingFinishP psFCmd = new WxProfitSharingFinishP();
psFCmd.setMch_id(payAccount.getMchId());
psFCmd.setSub_mch_id(payAccount.getSubMchId());
psFCmd.setAppid(appInfo.getParentAppId());
psFCmd.setNonce_str(Utility.generate32UUID());
psFCmd.setTransaction_id(transcationId);
psFCmd.setOut_order_no(record.getId().toString());
//psFCmd.setAmount(amount);
psFCmd.setDescription("分账已完结");
psFCmd.setSign_type("HMAC-SHA256");

String response;
try {
psFCmd.setSign(WxPayment.createSignHMAC(BeanUtils.toStringMap(psFCmd), payAccount.getApiKey()));
log.info("request:" + psFCmd.toString());
response = WxProfitSharing.finishOrder(BeanUtils.toStringMap(psFCmd), payAccount.getCertPath(), payAccount.getMchId());
} catch (Exception e) {
log.error("wx noreciver share error:",e);
return new PayShareResult(false, EnumProfitSharingOrderStatus.PROFIT_SHARING_REQ_FAILED.getCode(),ErrorCode.PROFIT_SHARING_REQUEST_FAILED.getMessage()+":"+e.getMessage(), null,null);
}

log.info("response: " + response);
Map<String, String> returnMap = WxPayment.xmlToMap(response);
String return_code = returnMap.get("return_code");

if (!"SUCCESS".equals(return_code)) {
return new PayShareResult(false, EnumProfitSharingOrderStatus.PROFIT_SHARING_REQ_FAILED.getCode(),returnMap.get("return_msg"), null,null);
}
if (!WxPayment.verifyNotifyHMAC(returnMap,payAccount.getApiKey())){
return new PayShareResult(false, EnumProfitSharingOrderStatus.PROFIT_SHARING_REQ_FAILED.getCode(),ErrorCode.PROFIT_SHARING_RETURN_INVALID.getMessage(), null,null);
}
String result_code = returnMap.get("result_code");
if (!"SUCCESS".equals(result_code)) {
return new PayShareResult(false, EnumProfitSharingOrderStatus.PROFIT_SHARING_APPLY_FAILED.getCode(),returnMap.get("err_code_des"), null,null);
}
return new PayShareResult(true, null,"success", returnMap,returnMap.get("order_id"));
}

@Override
public PayShareResult haveReciversShare(WxAppinfo appInfo,WxPayAccount payAccount,WxProfitSharingOrder record,String transcationId,JSONArray receivers,EnumProfitSharingOrderType shareType ) throws MallinkException {
//分账提交
WxProfitSharingP psCmd = new WxProfitSharingP();
psCmd.setMch_id(payAccount.getMchId());
psCmd.setSub_mch_id(payAccount.getSubMchId());
psCmd.setAppid(appInfo.getParentAppId());
psCmd.setSub_appid(appInfo.getAppId());
psCmd.setNonce_str(Utility.generate32UUID());
psCmd.setTransaction_id(transcationId);
psCmd.setOut_order_no(record.getId().toString());
psCmd.setSign_type("HMAC-SHA256");
psCmd.setReceivers(receivers.toJSONString());
String response;
try {
psCmd.setSign(WxPayment.createSignHMAC(BeanUtils.toStringMap(psCmd), payAccount.getApiKey()));
log.info("request:" + psCmd.toString());
if(shareType.getCode().intValue()==EnumProfitSharingOrderType.PROFIT_SHARING_SINGLE.getCode().intValue()) {
response = WxProfitSharing.pushOrder(BeanUtils.toStringMap(psCmd), payAccount.getCertPath(), payAccount.getMchId());
} else if(shareType.getCode().intValue()==EnumProfitSharingOrderType.PROFIT_SHARING_MULTI.getCode().intValue()) {
response = WxProfitSharing.pushMultiOrder(BeanUtils.toStringMap(psCmd), payAccount.getCertPath(), payAccount.getMchId());
} else {
throw new MallinkException(ErrorCode.SYS_PARAMETER_ERROR);
}
} catch (Exception e) {
log.error("wx recivers share error:",e);
return new PayShareResult(false, EnumProfitSharingOrderStatus.PROFIT_SHARING_REQ_FAILED.getCode(), ErrorCode.PROFIT_SHARING_REQUEST_FAILED.getMessage()+":"+e.getMessage(), null, null);
}

log.info("response: " + response);
Map<String, String> returnMap = WxPayment.xmlToMap(response);
String return_code = returnMap.get("return_code");

if (!"SUCCESS".equals(return_code)) {
return new PayShareResult(false, EnumProfitSharingOrderStatus.PROFIT_SHARING_REQ_FAILED.getCode(), returnMap.get("return_msg"), null, null);
}

if (!WxPayment.verifyNotifyHMAC(returnMap,payAccount.getApiKey())){
return new PayShareResult(false, EnumProfitSharingOrderStatus.PROFIT_SHARING_REQ_FAILED.getCode(), ErrorCode.PROFIT_SHARING_RETURN_INVALID.getMessage(), null, null);
}

String result_code = returnMap.get("result_code");
if (!"SUCCESS".equals(result_code)) {
return new PayShareResult(false, EnumProfitSharingOrderStatus.PROFIT_SHARING_APPLY_FAILED.getCode(), returnMap.get("err_code_des"), null, null);
}
return new PayShareResult(true, null, "success",returnMap, returnMap.get("order_id"));
}

@Override
public PayShareQueryResult shareQuery(WxAppinfo appInfo, WxPayAccount payAccount, WxProfitSharingOrder record) throws MallinkException {
WxProfitSharingQueryP wxProfitSharingQueryP = new WxProfitSharingQueryP();;
wxProfitSharingQueryP.setMch_id(payAccount.getMchId());
wxProfitSharingQueryP.setSub_mch_id(payAccount.getSubMchId());
wxProfitSharingQueryP.setNonce_str(Utility.generate32UUID());
wxProfitSharingQueryP.setTransaction_id(record.getTransactionId());
wxProfitSharingQueryP.setOut_order_no(record.getId().toString());
wxProfitSharingQueryP.setSign_type("HMAC-SHA256");
String response;
try {
wxProfitSharingQueryP.setSign(WxPayment.createSignHMAC(BeanUtils.toStringMap(wxProfitSharingQueryP),payAccount.getApiKey()));
response = WxProfitSharing.queryOrder(BeanUtils.toStringMap(wxProfitSharingQueryP), payAccount.getCertPath(), payAccount.getMchId());
}catch (Exception e){
throw new MallinkException(ErrorCode.PROFIT_SHARING_QUERY_REQUEST_FAILED.getCode(), ErrorCode.PROFIT_SHARING_QUERY_REQUEST_FAILED.getMessage()+e.getMessage());
}
Map<String, String> returnMap = WxPayment.xmlToMap(response);
String return_code = returnMap.get("return_code");
if (!"SUCCESS".equals(return_code)) {
throw new MallinkException(ErrorCode.PROFIT_SHARING_QUERY_REQUEST_FAILED.getCode(), returnMap.get("return_msg"));
}

if (!WxPayment.verifyNotifyHMAC(returnMap,payAccount.getApiKey())){
throw new MallinkException(ErrorCode.PROFIT_SHARING_QUERY_RETURN_INVALID);
}

String result_code = returnMap.get("result_code");
if (!"SUCCESS".equals(result_code)) {
throw new MallinkException(ErrorCode.PROFIT_SHARING_QUERY_APPLY_FAILED.getCode(), returnMap.get("err_code_des"));
}

String out_order_no = returnMap.get("out_order_no");
if (StringUtils.isBlank(out_order_no) || !out_order_no.equals(record.getId().toString())){
throw new MallinkException(ErrorCode.PROFIT_SHARING_QUERY_RETURN_INVALID.getCode(),"out_order_no:["+out_order_no+"] WxProfitSharingOrder:["+record.getId()+"]");
}
Integer code = (Integer) statusMap.get(returnMap.get("status"));
return new PayShareQueryResult(true, code, "success",returnMap, returnMap.get("receivers"));
}
@Autowired
WxAppinfoMapper wxAppinfoMapper;
@Autowired
WxPayAccountMapper wxPayAccountMapper;
@Autowired
WxPayOrderMapper wxPayOrderMapper;
private ShareNotifyAdapterResult getErrorResult(String msg) {
SortedMap resultMap = new TreeMap();
resultMap.put("return_code", "FAIL");
resultMap.put("return_msg", msg);
return new ShareNotifyAdapterResult(false,ErrorCode.PAY_ORDER_NOTIFY_CHECK_SIGN_ERROR.getCode(),msg,XmlUtil.getRequestXml(resultMap));
}
private ShareNotifyAdapterResult getSuccessResult(WxPayOrder payOrder, String transcationId){
SortedMap resultMap = new TreeMap();
resultMap.put("return_code", "SUCCESS");
resultMap.put("return_msg", "OK");
return new ShareNotifyAdapterResult(transcationId, payOrder, XmlUtil.getRequestXml(resultMap));
}
@Override
public ShareNotifyAdapterResult notify(Map<String, String> paramMap,EnumPayWay payWay) {
// how to get wechatAppId, wechatMchId, partnerKey
String appId = paramMap.get("appid");
String subAppId = paramMap.get("sub_appid");
String mchId = paramMap.get("mch_id");
String subMchId = paramMap.get("sub_mch_id");
WxAppinfo appinfo = null;
boolean isNormal = true;
if (StringUtils.isBlank(subAppId) && StringUtils.isBlank(subMchId)) {
// 普通商户号
appinfo = wxAppinfoMapper.findByAppId(appId);
if (appinfo == null) {
log.error("appid not found: " + appId);
throw new MallinkException(ErrorCode.APP_ID_NOT_FOUND);
}
isNormal = true;
} else {
// 服务号 现在用hmac-sha256
appinfo = wxAppinfoMapper.findByAppId(subAppId);
if (appinfo == null) {
log.error("subappid not found: " + subAppId);
throw new MallinkException(ErrorCode.APP_ID_NOT_FOUND);
}
isNormal = false;
}

WxPayAccount payAccount = wxPayAccountMapper.selectById(appinfo.getPayId());
if (payAccount == null) {
throw new MallinkException(ErrorCode.MCH_INFO_NOT_FOUND);
}
String partnerKey = payAccount.getApiKey();
try {
if (payWay == EnumPayWay.PAY_WAY_WECHAT) {
boolean signVerified = false;
if (isNormal) {
// 普通商户号支付
signVerified = WxPayment.verifyNotify(paramMap, partnerKey);
if (!signVerified) {
log.warn("notify order, wxpay checksign error, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString());
throw new MallinkException(ErrorCode.PAY_ORDER_NOTIFY_CHECK_SIGN_ERROR);
}
} else {
// 服务号 现在用hmac-sha256
signVerified = WxPayment.verifyNotifyHMAC(paramMap, partnerKey);
if (!signVerified) {
log.warn("notify order, wxpay checksign error, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString());
throw new MallinkException(ErrorCode.PAY_ORDER_NOTIFY_CHECK_SIGN_ERROR);
}
}

if (!"SUCCESS".equals(paramMap.get("return_code"))) {
log.warn("notify order, wxpay status not success, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString());
return getErrorResult("订单状态码非SUCCESS");
}

String payOrderNo = paramMap.get("out_trade_no");
String timEndStr = paramMap.get("time_end");
Long payOrderId = Long.valueOf(payOrderNo);
WxPayOrder payOrder = wxPayOrderMapper.selectById(payOrderId,payAccount.getTenantId());
if (payOrder == null) {
log.warn("notify order, wxpay check pay order not exists, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString());
return getErrorResult("订单不存在");
}
// 验证支付金额
if (!paramMap.get("total_fee").equals(payOrder.getPayAmount().toString())) {
log.warn("notify order, wxpay check total_fee is invalid, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString());
return getErrorResult("订单总金额不一致");
}

Date timeEnd = null;

try {
timeEnd = Utility.getDateFromString(timEndStr);
} catch (ParseException e) {
log.error("解析timeEnd失败");
timeEnd = new Date();
}
payOrder.setPayTimeEnd(timeEnd);

log.info("notify order, wxpay checksign success, paramMap:{}, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString());
return getSuccessResult(payOrder, paramMap.get("transaction_id"));
}
} catch (RuntimeException e) {
log.warn("notify order, checksign error, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString() + ", e:" + e.getMessage());
throw new MallinkException(ErrorCode.PAY_ORDER_ERROR);
}

return getErrorResult("FAILED");
}

@Override
public ShareAccountResult createShareAccount(WxAppinfo appInfo,WxPayAccount payAccount,WxProfitSharingReceiver receiver) {
WxProfitSharingReceiverP wxProfitSharingReceiverP = new WxProfitSharingReceiverP();
if (StringUtils.isNotBlank(appInfo.getParentAppId())) {
wxProfitSharingReceiverP.setAppid(appInfo.getParentAppId());
wxProfitSharingReceiverP.setMch_id(payAccount.getMchId());
wxProfitSharingReceiverP.setSub_appid(appInfo.getAppId());
wxProfitSharingReceiverP.setSub_mch_id(payAccount.getSubMchId());
} else {
wxProfitSharingReceiverP.setAppid(appInfo.getAppId());
wxProfitSharingReceiverP.setMch_id(payAccount.getMchId());
}
wxProfitSharingReceiverP.setNonce_str(Utility.generate32UUID());
wxProfitSharingReceiverP.setSign_type("HMAC-SHA256");


JSONObject receiverJSON = new JSONObject();
receiverJSON.put("type", EnumProfitSharingReceiverType.getEnum(receiver.getReceiverType()).getMessage());
receiverJSON.put("account", receiver.getReceiverAccount());
receiverJSON.put("name", receiver.getTrueName());

wxProfitSharingReceiverP.setReceiver(receiverJSON.toJSONString());
String response;
try {
wxProfitSharingReceiverP.setSign(WxPayment.createSignHMAC(BeanUtils.toStringMap(wxProfitSharingReceiverP), payAccount.getApiKey()));
response = WxProfitSharing.addReceiver(BeanUtils.toStringMap(wxProfitSharingReceiverP));
log.info(response);
} catch (Exception e) {
log.error(ErrorCode.PROFIT_SHARING_RECEIVER_ADD_FAILED.getMessage() + e.getMessage());
return new ShareAccountResult(false, ErrorCode.PROFIT_SHARING_RECEIVER_ADD_FAILED.getCode(), e.getMessage(), null);
}
Map<String, String> returnMap = WxPayment.xmlToMap(response);
String return_code = returnMap.get("return_code");
if (!"SUCCESS".equals(return_code)) {
log.error(ErrorCode.PROFIT_SHARING_RECEIVER_ADD_FAILED.getMessage() + returnMap.get("return_msg")+":"+JSON.toJSONString(returnMap));
return new ShareAccountResult(false, ErrorCode.PROFIT_SHARING_RECEIVER_ADD_FAILED.getCode(), returnMap.get("return_msg"), null);
}

String result_code = returnMap.get("result_code");
if (!"SUCCESS".equals(result_code)) {
log.error(ErrorCode.PROFIT_SHARING_RECEIVER_ADD_FAILED.getMessage() + returnMap.get("err_code_des")+":"+JSON.toJSONString(returnMap));
return new ShareAccountResult(false, ErrorCode.PROFIT_SHARING_RECEIVER_ADD_FAILED.getCode(), returnMap.get("err_code_des"), null);
}

if (!WxPayment.verifyNotifyHMAC(returnMap, payAccount.getApiKey())) {
log.error(ErrorCode.PROFIT_SHARING_RECEIVER_ADD_FAILED.getMessage() + "verifyNotifyHMAC"+":"+JSON.toJSONString(returnMap));
return new ShareAccountResult(false, ErrorCode.PROFIT_SHARING_RECEIVER_ADD_FAILED.getCode(), ErrorCode.PROFIT_SHARING_RECEIVER_ADD_FAILED.getMessage(), null);
}

return new ShareAccountResult(true, null, "success", returnMap);
}

@Autowired
WxProfitSharingReceiverMapper wxProfitSharingReceiverMapper;
@Override
public ShareAccountResult deleteShareAccount(WxAppinfo appInfo, WxPayAccount payAccount,
WxProfitSharingReceiver receiver) {
//删除分账账户从微信服务器
WxProfitSharingReceiverP wxProfitSharingReceiverP = new WxProfitSharingReceiverP();
if (StringUtils.isNotBlank(appInfo.getParentAppId())) {
wxProfitSharingReceiverP.setAppid(appInfo.getParentAppId());
wxProfitSharingReceiverP.setMch_id(payAccount.getMchId());
wxProfitSharingReceiverP.setSub_appid(appInfo.getAppId());
wxProfitSharingReceiverP.setSub_mch_id(payAccount.getSubMchId());
} else {
wxProfitSharingReceiverP.setAppid(appInfo.getAppId());
wxProfitSharingReceiverP.setMch_id(payAccount.getMchId());
}
wxProfitSharingReceiverP.setNonce_str(Utility.generate32UUID());
wxProfitSharingReceiverP.setSign_type("HMAC-SHA256");

JSONObject receiverJSON = new JSONObject();
receiverJSON.put("type", EnumProfitSharingReceiverType.getEnum(receiver.getReceiverType()).getMessage());
receiverJSON.put("account", receiver.getReceiverAccount());

wxProfitSharingReceiverP.setReceiver(receiverJSON.toJSONString());
String response;
try {
wxProfitSharingReceiverP.setSign(WxPayment.createSignHMAC(BeanUtils.toStringMap(wxProfitSharingReceiverP), payAccount.getApiKey()));
response = WxProfitSharing.delReceiver(BeanUtils.toStringMap(wxProfitSharingReceiverP));
} catch (Exception e) {
log.error(ErrorCode.PROFIT_SHARING_RECEIVER_DEL_FAILED.getMessage() + e.getMessage());
return new ShareAccountResult(false, ErrorCode.PROFIT_SHARING_RECEIVER_DEL_FAILED.getCode(), e.getMessage(), null);
}
Map<String, String> returnMap = WxPayment.xmlToMap(response);
String return_code = returnMap.get("return_code");
if (!"SUCCESS".equals(return_code)) {
log.error(ErrorCode.PROFIT_SHARING_RECEIVER_DEL_FAILED.getMessage() + returnMap.get("return_msg")+":"+JSON.toJSONString(returnMap));
return new ShareAccountResult(false, ErrorCode.PROFIT_SHARING_RECEIVER_DEL_FAILED.getCode(), returnMap.get("return_msg"), null);
}

String result_code = returnMap.get("result_code");
if (!"SUCCESS".equals(result_code)) {

if (returnMap.get("err_code").contains("USER_NOT_EXIST")) {
receiver.setStatus(EnumProfitSharingReceiverStatus.PROFIT_SHARING_RECEIVER_STATUS_INVALID.getCode());
receiver.setUpdateTime(new Date());
wxProfitSharingReceiverMapper.updateById(receiver);
}
log.error(ErrorCode.PROFIT_SHARING_RECEIVER_DEL_FAILED.getMessage() + returnMap.get("err_code_des")+":"+JSON.toJSONString(returnMap));
return new ShareAccountResult(false, ErrorCode.PROFIT_SHARING_RECEIVER_DEL_FAILED.getCode(), returnMap.get("err_code_des"), null);
}

if (!WxPayment.verifyNotifyHMAC(returnMap, payAccount.getApiKey())) {
log.error(ErrorCode.PROFIT_SHARING_RECEIVER_DEL_FAILED.getMessage()+":"+JSON.toJSONString(returnMap));
return new ShareAccountResult(false, ErrorCode.PROFIT_SHARING_RECEIVER_DEL_FAILED.getCode(), "verifyNotifyHMAC", null);
}
return new ShareAccountResult(true, null, "success", returnMap);
}

@Override
public int getOfficialCommission(WxOrder o, WxPayAccount payAccount) {
return 0;
}

@Override
public ResultData handerSharingOrder(WxPayOrder payOrder, WxProfitSharingOrder sharingOrder) {
return new ResultData(ErrorCode.SYS_PARAMETER_TYPE_ERROR.getCode(),"微信分账无需处理");
}

@Override
public WxProfitSharingOrder createSharingOrder(WxSharingOrderDto sharingOrderDto, Integer mchType,Integer share) {
if(EnumPayMchType.DIRECT.getCode().equals(mchType)){
throw new MallinkException(ErrorCode.SYS_PARAMETER_TYPE_ERROR.getCode(),"微信直连模式待开发");
}
if(EnumYesOrNo.NO.getCode().equals(share)){
throw new MallinkException(ErrorCode.SYS_PARAMETER_TYPE_ERROR.getCode(),"微信不分账");
}
//是否已创建分账订单
WxProfitSharingOrder record = new WxProfitSharingOrder();
record.updateTenantInfo(sharingOrderDto);
record.setOrderId(sharingOrderDto.getOrderId());
record = wxProfitSharingOrderMapper.selectOne(new QueryWrapper(record));
if (record == null) {
//创建分账订单
Date currentDate = new Date();
record = new WxProfitSharingOrder();
final IdWorker idworker = IdWorker.get();
record.setId(idworker.nextId());
record.updateTenantInfo(sharingOrderDto);
record.setTransactionId(sharingOrderDto.getTransactionId());
record.setOrderId(sharingOrderDto.getOrderId());
record.setPayAmount(sharingOrderDto.getPayAmount());
record.setMerchantId(sharingOrderDto.getMerchantId());
record.setSharingStatus(this.getSharingOrderInitialStatus());
record.setCreateTime(currentDate);
record.setUpdateTime(currentDate);
record.setPayTimeStart(sharingOrderDto.getPayTimeStart());
record.setPayTimeEnd(sharingOrderDto.getPayTimeEnd());
record.setType(sharingOrderDto.getType());
wxProfitSharingOrderMapper.insert(record);
}

List<WxProfitSharingReceiver> psReceiverList = getReceiverList(sharingOrderDto, sharingOrderDto.getMerchantId(), null);

if (psReceiverList != null && psReceiverList.size() > 50) {
throw new MallinkException(ErrorCode.PROFIT_SHARING_RECEIVER_INVALID);
}

if (psReceiverList == null || psReceiverList.size() == 0) { //没有分账账户,
throw new MallinkException(ErrorCode.PROFIT_SHARING_RECEIVER_UNKNOWN);
}

if (psReceiverList.size() > 1 &&//计算分账账户合法性
psReceiverList.stream().filter(r->(r.getParameter() == null)).count() > 0) {
throw new MallinkException(ErrorCode.PROFIT_SHARING_RECEIVER_INVALID);
}

//计算分账金额合法性
psReceiverList.stream().forEach(r->
{
if (r.getParameter() == null){
r.setSharingAmount(sharingOrderDto.getShareAmount());
r.setRateAmount(sharingOrderDto.getRateAmount());
r.setRealRateAmount(sharingOrderDto.getRealRateAmount());
r.setCommissionAmount(sharingOrderDto.getCommissionAmount());
} else {
r.setSharingAmount(sharingOrderDto.getShareAmount()*Integer.valueOf(r.getParameter())/10000);
}
});
if (psReceiverList.stream().mapToInt(r->r.getSharingAmount()).sum() > sharingOrderDto.getShareAmount()){
throw new MallinkException(ErrorCode.PROFIT_SHARING_RECEIVER_UNKNOWN);
}

// 添加分账接收方
JSONArray receivers = new JSONArray();
psReceiverList.stream().forEach(receiver->{
JSONObject jo = new JSONObject();
jo.put("type",this.getShareAccount(receiver.getReceiverType()).getMessage());
jo.put("account",receiver.getReceiverAccount());
jo.put("amount", receiver.getSharingAmount());
jo.put("rateAmount", receiver.getRateAmount());
jo.put("realRateAmount", receiver.getRateAmount());
jo.put("commissionAmount", receiver.getCommissionAmount());
//jo.put("description",receiver.getReceiverComments()); //改为存ID,
jo.put("description",receiver.getId().toString()); //为重试做准备
receivers.add(jo);
});

record.setReceivers(receivers.toJSONString());
wxProfitSharingOrderMapper.updateById(record);

return record;
}

@Override
public List<WxProfitSharingReceiver> getReceiverList(TenantEntity tenantEntity, Long merchantId, Integer ttPayWay) {
WxProfitSharingReceiver psReceiverQ = new WxProfitSharingReceiver();
psReceiverQ.updateTenantInfo(tenantEntity);
psReceiverQ.setMerchantId(merchantId);
psReceiverQ.setSharingType(getProfitSharingType());
psReceiverQ.setStatus(EnumProfitSharingReceiverStatus.PROFIT_SHARING_RECEIVER_STATUS_VALID.getCode());
psReceiverQ.setPlat(EnumAppPlat.WX.getCode());
List<WxProfitSharingReceiver> psReceiverList = wxProfitSharingReceiverMapper.findList(psReceiverQ);
if (null == psReceiverList || psReceiverList.size() == 0) {
throw new MallinkException(ErrorCode.PROFIT_SHARING_RECEIVER_INVALID.getCode(),"该商户未设置分账账号.");
}else {
for (WxProfitSharingReceiver receiver:psReceiverList) {
if (EnumProfitSharingReceiverType.PROFIT_SHARING_RECEIVER_PERSONAL_WECHATID.getCode().intValue()
== receiver.getReceiverType().intValue()) {
throw new MallinkException(ErrorCode.PROFIT_SHARING_RECEIVER_INVALID.getCode(),"该商户收款账号存在个人微信号方式,微信已停止支持,请重新设置.");
}
}
}
return psReceiverList;
}

private static String queryOrderShareAmount(String mchId,String transcationId,String apiKey) {
WxProfitSharingP psCmd = new WxProfitSharingP();
psCmd.setMch_id(mchId);//服务商商户id
psCmd.setNonce_str(Utility.generate32UUID());
psCmd.setTransaction_id(transcationId);
psCmd.setSign_type("HMAC-SHA256");
try {
psCmd.setSign(WxPayment.createSignHMAC(BeanUtils.toStringMap(psCmd), apiKey));
return WxProfitSharing.queryOrderShareAmount(BeanUtils.toStringMap(psCmd));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

// public static void main(String[] args) {
// System.out.println(queryOrderShareAmount("1511925291","4200001516202205010431149938","XHZfpVA0NzoXgLEjsujctUTcyj8Zur2C"));
// //System.out.println(test("1511925291", "1604439800", "wxed2f44705544b892", "4200001455202205127949391954", "XHZfpVA0NzoXgLEjsujctUTcyj8Zur2C", "684670745960046592", "D:\\apiclient_cert.p12"));
// }
//
// private static String test(String mchId,String subMchId,String parentAppId,String transcationId,String apiKey,String orderNo,String certPaht) {
// WxProfitSharingFinishP psFCmd = new WxProfitSharingFinishP();
// psFCmd.setMch_id(mchId);
// psFCmd.setSub_mch_id(subMchId);
// psFCmd.setAppid(parentAppId);
// psFCmd.setNonce_str(Utility.generate32UUID());
// psFCmd.setTransaction_id(transcationId);
// psFCmd.setOut_order_no(orderNo);
// //psFCmd.setAmount(amount);
// psFCmd.setDescription("分账已完结");
// psFCmd.setSign_type("HMAC-SHA256");
//
// String response;
// try {
// psFCmd.setSign(WxPayment.createSignHMAC(BeanUtils.toStringMap(psFCmd), apiKey));
// log.info("request:" + psFCmd.toString());
// response = WxProfitSharing.finishOrder(BeanUtils.toStringMap(psFCmd), certPaht, mchId);
// return response;
// } catch (Exception e) {
// e.printStackTrace();
// }
// return null;
//
// }
}

Ladataan…
Peruuta
Tallenna