diff --git a/mallinkAdmin/src/main/java/com/simple/controller/WxRefundOrderController.java b/mallinkAdmin/src/main/java/com/simple/controller/WxRefundOrderController.java new file mode 100644 index 000000000..d426b9126 --- /dev/null +++ b/mallinkAdmin/src/main/java/com/simple/controller/WxRefundOrderController.java @@ -0,0 +1,71 @@ +package com.simple.controller; + +import org.apache.log4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.Assert; +import org.springframework.web.bind.annotation.*; + +import com.github.pagehelper.PageInfo; +import com.simple.common.Result; +import com.simple.common.ResultData; + +import com.simple.domain.po.WxRefundOrder; +import com.simple.service.WxRefundOrderService; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; + +@RestController +@RequestMapping("wxRefundOrder") +public class WxRefundOrderController extends BaseController +{ + @Autowired + private WxRefundOrderService wxRefundOrderService; + + private Logger logger = Logger.getLogger(WxRefundOrderController.class); + + @ApiOperation("分页列表接口") + @GetMapping("list") + @ApiImplicitParams({ + @ApiImplicitParam(name="pageNum",value="页数",dataType="int", paramType = "query",required=true), + @ApiImplicitParam(name="pageSize",value="每页条数",dataType="int", paramType = "query",required=true)}) + public ResultData list(@ModelAttribute WxRefundOrder wxRefundOrder,Integer pageNum, Integer pageSize) { + if (null == wxRefundOrder) wxRefundOrder = new WxRefundOrder(); + final PageInfo page = wxRefundOrderService.listAsPage(wxRefundOrder, pageNum, pageSize); + return new ResultData(page); + } + + @ApiOperation("新增接口") + @PostMapping("add") + public ResultData add(@RequestBody WxRefundOrder wxRefundOrder) { + //Assert.notNull(wxRefundOrder.getName(), "角色名不能为空"); + //Assert.isTrue(!checkUnique(sysRole.getName(), null), "重复的角色名"); + wxRefundOrderService.saveOrUpdate(wxRefundOrder); + return new ResultData(); + } + + @ApiOperation("根据id更新接口") + @PostMapping("update") + public ResultData update(@RequestBody WxRefundOrder wxRefundOrder) { + wxRefundOrderService.saveOrUpdate(wxRefundOrder); + return new ResultData(); + } + + @ApiOperation("根据id删除接口") + @GetMapping("/del") + @ApiImplicitParam(name="id",value="id",dataType="Long", paramType = "query",required=true) + public ResultData delete(Long id) { + wxRefundOrderService.deleteById(id); + return new ResultData(Result.SUCCESS, "删除成功", null); + } + + @ApiOperation("根据id查询接口") + @GetMapping("/findById") + @ApiImplicitParam(name="id",value="id",dataType="Long", paramType = "query",required=true) + public ResultData findById(Long id) { + return new ResultData(Result.SUCCESS,"查询成功",wxRefundOrderService.getById(id)); + } + + + +} diff --git a/mallinkService/src/main/java/com/simple/common/ErrorCode.java b/mallinkService/src/main/java/com/simple/common/ErrorCode.java index 9822b0b11..110c8ddc9 100644 --- a/mallinkService/src/main/java/com/simple/common/ErrorCode.java +++ b/mallinkService/src/main/java/com/simple/common/ErrorCode.java @@ -96,8 +96,14 @@ public enum ErrorCode{ * 支付 */ PAY_ORDER_EXIST(12001, "支付订单已存在"), - PAY_ORDER_ERROR(12004, "支付订单异常"), - PAY_ORDER_NOTIFY_CHECK_SIGN_ERROR(12005 , "验签失败"); + PAY_ORDER_ERROR(12002, "支付订单异常"), + PAY_ORDER_NOTIFY_CHECK_SIGN_ERROR(12003 , "支付验签失败"), + + REFUND_ORDER_EXIST(12004, "退款订单已存在"), + REFUND_PAY_ORDER_IS_NOT_EXIST(12005, "退款支付订单不存在"), + REFUND_PAY_ORDER_IS_ZERO(12006, "退款支付订单金额为0"), + REFUND_ORDER_ERROR(12007, "退款订单异常"), + REFUND_ORDER_NOTIFY_CHECK_SIGN_ERROR(12008, "退款验签失败"); diff --git a/mallinkService/src/main/java/com/simple/domain/po/WxRefundOrder.java b/mallinkService/src/main/java/com/simple/domain/po/WxRefundOrder.java new file mode 100644 index 000000000..27f5a1e4d --- /dev/null +++ b/mallinkService/src/main/java/com/simple/domain/po/WxRefundOrder.java @@ -0,0 +1,252 @@ +package com.simple.domain.po; + +import javax.persistence.*; +import java.util.*; +import java.math.*; +import javax.persistence.Transient; +import java.util.List; +import javax.persistence.Id; +import java.io.Serializable; + +@Table(name = "wx_refund_order") +public class WxRefundOrder implements Serializable { + private static final long serialVersionUID = 1L; + + @Id + protected Long id; + + @Transient + protected List ids; + @Transient + protected String sortColumns; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getSortColumns() { + return sortColumns; + } + + public List getIds() { + return ids; + } + + public void setIds(List ids) { + this.ids = ids; + } + + + + /*租户ID**/ + @io.swagger.annotations.ApiModelProperty(value="租户ID",name="tenantId") + private String tenantId; + /*创建时间**/ + @io.swagger.annotations.ApiModelProperty(value="创建时间",name="createTime") + private Date createTime; + /*更新时间**/ + @io.swagger.annotations.ApiModelProperty(value="更新时间",name="updateTime") + private Date updateTime; + /*微信生成的订单号**/ + @io.swagger.annotations.ApiModelProperty(value="微信生成的订单号",name="transactionId") + private String transactionId; + /*订单ID-out_trade_no**/ + @io.swagger.annotations.ApiModelProperty(value="订单ID-out_trade_no",name="orderId") + private Long orderId; + /*支付订单号**/ + @io.swagger.annotations.ApiModelProperty(value="支付订单号",name="payOrderNo") + private String payOrderNo; + /*用户ID**/ + @io.swagger.annotations.ApiModelProperty(value="用户ID",name="cUserId") + private Long cUserId; + /*订单总金额(分)**/ + @io.swagger.annotations.ApiModelProperty(value="订单总金额(分)",name="totalFee") + private Integer totalFee; + /*退款总金额**/ + @io.swagger.annotations.ApiModelProperty(value="退款总金额",name="refundFee") + private Integer refundFee; + /*退款发起时间(秒)**/ + @io.swagger.annotations.ApiModelProperty(value="退款发起时间(秒)",name="refundTimeStart") + private Integer refundTimeStart; + /*退款结束时间(秒)**/ + @io.swagger.annotations.ApiModelProperty(value="退款结束时间(秒)",name="refundTimeEnd") + private Integer refundTimeEnd; + /*支付渠道: 0-微信 1-支付宝 2-银联 **/ + @io.swagger.annotations.ApiModelProperty(value="支付渠道: 0-微信 1-支付宝 2-银联 ",name="refundVendor") + private Integer refundVendor; + /*支付状态: 0-退款中;1-退款成功;2-退款失败**/ + @io.swagger.annotations.ApiModelProperty(value="支付状态: 0-退款中;1-退款成功;2-退款失败",name="refundOrderStatus") + private Integer refundOrderStatus; + /*微信退款单号**/ + @io.swagger.annotations.ApiModelProperty(value="微信退款单号",name="refundId") + private String refundId; + /*支付失败原因**/ + @io.swagger.annotations.ApiModelProperty(value="支付失败原因",name="failReason") + private String failReason; + public String getTenantId() { + return tenantId; + } + public void setTenantId(String _tenantId) { + tenantId = _tenantId; + } + public Date getCreateTime() { + return createTime; + } + public void setCreateTime(Date _createTime) { + createTime = _createTime; + } + public Date getUpdateTime() { + return updateTime; + } + public void setUpdateTime(Date _updateTime) { + updateTime = _updateTime; + } + public String getTransactionId() { + return transactionId; + } + public void setTransactionId(String _transactionId) { + transactionId = _transactionId; + } + public Long getOrderId() { + return orderId; + } + public void setOrderId(Long _orderId) { + orderId = _orderId; + } + public String getPayOrderNo() { + return payOrderNo; + } + public void setPayOrderNo(String _payOrderNo) { + payOrderNo = _payOrderNo; + } + public Long getCUserId() { + return cUserId; + } + public void setCUserId(Long _cUserId) { + cUserId = _cUserId; + } + public Integer getTotalFee() { + return totalFee; + } + public void setTotalFee(Integer _totalFee) { + totalFee = _totalFee; + } + public Integer getRefundFee() { + return refundFee; + } + public void setRefundFee(Integer _refundFee) { + refundFee = _refundFee; + } + public Integer getRefundTimeStart() { + return refundTimeStart; + } + public void setRefundTimeStart(Integer _refundTimeStart) { + refundTimeStart = _refundTimeStart; + } + public Integer getRefundTimeEnd() { + return refundTimeEnd; + } + public void setRefundTimeEnd(Integer _refundTimeEnd) { + refundTimeEnd = _refundTimeEnd; + } + public Integer getRefundVendor() { + return refundVendor; + } + public void setRefundVendor(Integer _refundVendor) { + refundVendor = _refundVendor; + } + public Integer getRefundOrderStatus() { + return refundOrderStatus; + } + public void setRefundOrderStatus(Integer _refundOrderStatus) { + refundOrderStatus = _refundOrderStatus; + } + public String getRefundId() { + return refundId; + } + public void setRefundId(String _refundId) { + refundId = _refundId; + } + public String getFailReason() { + return failReason; + } + public void setFailReason(String _failReason) { + failReason = _failReason; + } + + + + public static enum Field + { + Id_ASC("`id` ASC"),Id_DESC("`id` DESC") + ,TenantId_ASC("`tenantId` ASC"),TenantId_DESC("`tenantId` DESC") + ,CreateTime_ASC("`createTime` ASC"),CreateTime_DESC("`createTime` DESC") + ,UpdateTime_ASC("`updateTime` ASC"),UpdateTime_DESC("`updateTime` DESC") + ,TransactionId_ASC("`transactionId` ASC"),TransactionId_DESC("`transactionId` DESC") + ,OrderId_ASC("`orderId` ASC"),OrderId_DESC("`orderId` DESC") + ,PayOrderNo_ASC("`payOrderNo` ASC"),PayOrderNo_DESC("`payOrderNo` DESC") + ,CUserId_ASC("`cUserId` ASC"),CUserId_DESC("`cUserId` DESC") + ,TotalFee_ASC("`totalFee` ASC"),TotalFee_DESC("`totalFee` DESC") + ,RefundFee_ASC("`refundFee` ASC"),RefundFee_DESC("`refundFee` DESC") + ,RefundTimeStart_ASC("`refundTimeStart` ASC"),RefundTimeStart_DESC("`refundTimeStart` DESC") + ,RefundTimeEnd_ASC("`refundTimeEnd` ASC"),RefundTimeEnd_DESC("`refundTimeEnd` DESC") + ,RefundVendor_ASC("`refundVendor` ASC"),RefundVendor_DESC("`refundVendor` DESC") + ,RefundOrderStatus_ASC("`refundOrderStatus` ASC"),RefundOrderStatus_DESC("`refundOrderStatus` DESC") + ,RefundId_ASC("`refundId` ASC"),RefundId_DESC("`refundId` DESC") + ,FailReason_ASC("`failReason` ASC"),FailReason_DESC("`failReason` DESC") + ; + private String value; + Field(String value){ + this.value = value; + } + public String getValue() { + return value; + } + public void setCol(String value) { + this.value = value; + } + @Override + public String toString() { + return this.getValue(); + } + } + + public void setSortColumns(WxRefundOrder.Field... fields) + { + if (fields == null || fields.length == 0) { + return; + } + for (int k = 0; k < fields.length; k++) { + if (fields[k] == null) { + return; + } + } + StringBuilder sb = new StringBuilder(fields[0].toString()); + for (int k = 1; k < fields.length; k++) { + sb.append(","); + sb.append(fields[k].toString()); + } + + } + + public void setSortColumns(String sortColumns) + { + if (sortColumns == null || "".equals(sortColumns.trim())) { + return; + } + if (sortColumns.contains(",")) { + String[] cols = sortColumns.split(","); + java.util.List fList = new java.util.ArrayList(); + for (int k = 0; k < cols.length; k++) { + fList.add(Field.valueOf(cols[k])); + } + this.setSortColumns(fList.toArray(new Field[fList.size()])); + } else { + this.setSortColumns(Field.valueOf(sortColumns)); + } + } +} diff --git a/mallinkService/src/main/java/com/simple/enums/EnumRefundStatus.java b/mallinkService/src/main/java/com/simple/enums/EnumRefundStatus.java new file mode 100644 index 000000000..4ac8d4981 --- /dev/null +++ b/mallinkService/src/main/java/com/simple/enums/EnumRefundStatus.java @@ -0,0 +1,39 @@ +package com.simple.enums; + +/** + * Created by Stormeye on 2018/08/09. + */ +public enum EnumRefundStatus { + REFUND_UNKNOWN(-1, "未知"), + REFUND_WAIT(0, "退款中"), + REFUND_REQ_SUCCESS(1, "退款申请成功"), + REFUND_REQ_FAIL(2, "退款申请失败"), + REFUND_SUCCESS(3, "退款成功"), + REFUND_FAIL(4, "退款失败"), + ; + + public static EnumRefundStatus getEnum(Integer code) { + for (EnumRefundStatus value : values()) { + if (value.getCode().equals(code)) { + return value; + } + } + return null; + } + + private Integer code; + private String message; + + EnumRefundStatus(Integer code, String message) { + this.code = code; + this.message = message; + } + + public Integer getCode() { + return code; + } + + public String getMessage() { + return message; + } +} diff --git a/mallinkService/src/main/java/com/simple/mapper/WxRefundOrderMapper.java b/mallinkService/src/main/java/com/simple/mapper/WxRefundOrderMapper.java new file mode 100644 index 000000000..8e7e5d9ca --- /dev/null +++ b/mallinkService/src/main/java/com/simple/mapper/WxRefundOrderMapper.java @@ -0,0 +1,17 @@ +package com.simple.mapper; + +import java.util.*; +import com.simple.common.CommonMapper; +import org.apache.ibatis.annotations.Param; +import com.simple.domain.po.WxRefundOrder; + +public interface WxRefundOrderMapper extends CommonMapper { + + List findList(WxRefundOrder wxRefundOrder); + + + + + + +} diff --git a/mallinkService/src/main/java/com/simple/pay/WxPayment.java b/mallinkService/src/main/java/com/simple/pay/WxPayment.java index 2398ebb4e..f44d1231d 100644 --- a/mallinkService/src/main/java/com/simple/pay/WxPayment.java +++ b/mallinkService/src/main/java/com/simple/pay/WxPayment.java @@ -243,6 +243,35 @@ public class WxPayment { return buildSignAfterParasMap(params, paternerKey); } + /** + * 查询退款 + * + * @param appid + * @param mch_id + * @param out_trade_no + * @param paternerKey + * @return + */ + public static Map buildWeappRefundQueryMap(String appid, String mch_id, + String transaction_id, String out_trade_no, String out_refund_no, String refund_id, + String paternerKey) { + Map params = new HashMap(); + + params.put("appid", appid); + params.put("mch_id", mch_id); + if(!StringUtils.isBlank(refund_id)) { + params.put("refund_id", refund_id); + } else if (!StringUtils.isBlank(out_refund_no)) { + params.put("out_refund_no", out_refund_no); + } else if (!StringUtils.isBlank(transaction_id)) { + params.put("transaction_id", transaction_id); + } else if (!StringUtils.isBlank(out_trade_no)) { + params.put("out_trade_no", out_trade_no); + } + + return buildSignAfterParasMap(params, paternerKey); + } + /** * 组装签名的字段 * diff --git a/mallinkService/src/main/java/com/simple/pay/WxRefundOrder.java b/mallinkService/src/main/java/com/simple/pay/WxRefundOrderP.java similarity index 89% rename from mallinkService/src/main/java/com/simple/pay/WxRefundOrder.java rename to mallinkService/src/main/java/com/simple/pay/WxRefundOrderP.java index 521b02090..d83000ac1 100644 --- a/mallinkService/src/main/java/com/simple/pay/WxRefundOrder.java +++ b/mallinkService/src/main/java/com/simple/pay/WxRefundOrderP.java @@ -3,11 +3,12 @@ package com.simple.pay; /** * Created by Stormeye on 2018/8/10. */ -public class WxRefundOrder { +public class WxRefundOrderP { private String appid; // 公众账号ID private String mch_id; // 商户号 private String nonce_str; // 随机字符串 private String sign; // 签名 + private String transaction_id; // 微信订单号 private String out_trade_no; // 商户订单号 private String out_refund_no; // 商户退款单号 private Integer total_fee; // 支付金额 @@ -45,6 +46,14 @@ public class WxRefundOrder { this.sign = sign; } + public String getTransaction_id() { + return transaction_id; + } + + public void setTransaction_id(String transaction_id) { + this.transaction_id = transaction_id; + } + public String getOut_trade_no() { return out_trade_no; } diff --git a/mallinkService/src/main/java/com/simple/service/WxRefundOrderService.java b/mallinkService/src/main/java/com/simple/service/WxRefundOrderService.java new file mode 100644 index 000000000..e9ea7c813 --- /dev/null +++ b/mallinkService/src/main/java/com/simple/service/WxRefundOrderService.java @@ -0,0 +1,68 @@ +package com.simple.service; + +import java.util.*; +import com.github.pagehelper.PageInfo; +import com.simple.common.ResultData; +import com.simple.domain.po.WxAppinfo; +import com.simple.domain.po.WxCUser; +import com.simple.domain.po.WxRefundOrder; +import com.simple.enums.EnumPayWay; + +public interface WxRefundOrderService { + + /** + * 创建退款订单 + * @param appInfo + * @param record 退款订单请求 + * @param payWay + * @return + */ + ResultData createRefundOrder(WxAppinfo appInfo, WxRefundOrder record, EnumPayWay payWay); + + /** + * 退款订单查询 + * @param appInfo + * @param record + * @return + */ + ResultData queryRefundOrder(WxAppinfo appInfo, WxRefundOrder record); + /** + * 根据实体查询分页列表 + * + * @param record + * @param pageIndex + * @param pageSize + * @return + */ + PageInfo listAsPage(WxRefundOrder record, Integer pageIndex, Integer pageSize); + + /** + * 根据Id获得实体 + * + * @param id + * @return + */ + WxRefundOrder getById(Long id); + + /** + * 保存或更新实体 + * + * @param record + */ + void saveOrUpdate(WxRefundOrder record); + + /** + * 根据Id删除实体 + * + * @param id + */ + void deleteById(Long id); + + + + + + + + +} diff --git a/mallinkService/src/main/java/com/simple/service/impl/WxPayOrderServiceImpl.java b/mallinkService/src/main/java/com/simple/service/impl/WxPayOrderServiceImpl.java index cb041308e..90afccc0c 100644 --- a/mallinkService/src/main/java/com/simple/service/impl/WxPayOrderServiceImpl.java +++ b/mallinkService/src/main/java/com/simple/service/impl/WxPayOrderServiceImpl.java @@ -103,7 +103,7 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { record.setPayOrderStatus(EnumPayStatus.PAY_WAY_WAIT.getCode()); int sqlRow = wxPayOrderMapper.insertSelective(record); - if(sqlRow == 1) { + if(sqlRow != 1) { throw new MallinkException(ErrorCode.DB_FAIL); } WxPayAccount payAccount = wxPayAccountMapper.selectByPrimaryKey(appInfo.getPayId()); @@ -122,7 +122,7 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { wxPayOrderP.setTrade_type(WxPay.TradeType.APP.name()); // 终端类型 wxPayOrderP.setProduct_id(String.valueOf(order.getId())); // 订单ID wxPayOrderP.setTime_start(Utility.getDataFormatStringYYYYMMDDHHmmss(currentTime)); - wxPayOrderP.setTime_start(Utility.getDataFormatStringYYYYMMDDHHmmss(currentTime + 15 * 60)); // 15分钟结束 + wxPayOrderP.setTime_expire(Utility.getDataFormatStringYYYYMMDDHHmmss(currentTime + 15 * 60)); // 15分钟结束 wxPayOrderP.setSign(WxPayment.createSign(BeanUtils.toStringMap(wxPayOrderP), payAccount.getApiKey())); String response = WxPay.pushOrder(BeanUtils.toStringMap(wxPayOrderP)); logger.info("pay order, wechat pushOrder, wxPayOrder:" + wxPayOrderP.toString() + ", response: " + response.toString()); @@ -154,6 +154,10 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { } } + // TODO + // 微信订单查询 + // 微信关闭订单 + @Override public String notify(Map paramMap, EnumPayWay payWay) { // how to get wechatAppId, wechatMchId, partnerKey diff --git a/mallinkService/src/main/java/com/simple/service/impl/WxRefundOrderServiceImpl.java b/mallinkService/src/main/java/com/simple/service/impl/WxRefundOrderServiceImpl.java new file mode 100644 index 000000000..a7c8604e3 --- /dev/null +++ b/mallinkService/src/main/java/com/simple/service/impl/WxRefundOrderServiceImpl.java @@ -0,0 +1,222 @@ +package com.simple.service.impl; + +import java.util.*; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import com.simple.common.ErrorCode; +import com.simple.common.ResultData; +import com.simple.domain.po.*; +import com.simple.enums.EnumPayStatus; +import com.simple.enums.EnumPayWay; +import com.simple.enums.EnumRefundStatus; +import com.simple.exception.MallinkException; +import com.simple.mapper.WxPayAccountMapper; +import com.simple.mapper.WxPayOrderMapper; +import com.simple.mapper.WxRefundOrderMapper; +import com.simple.pay.WxPay; +import com.simple.pay.WxPayment; +import com.simple.pay.WxRefundOrderP; +import com.simple.service.WxRefundOrderService; +import com.simple.utils.BeanUtils; +import com.simple.utils.Utility; +import org.apache.log4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.simple.common.IdWorker; + +@Service +public class WxRefundOrderServiceImpl implements WxRefundOrderService { + private Logger logger = Logger.getLogger(getClass()); + + @Autowired + WxRefundOrderMapper wxRefundOrderMapper; + + @Autowired + WxPayOrderMapper wxPayOrderMapper; + + @Autowired + WxPayAccountMapper wxPayAccountMapper; + + JSONObject errorRefundReqMap = JSON.parseObject("{\"SYSTEMERROR\":{\"detail\":\"接口返回错误\",\"reason\":\"系统超时等\",\"resolution\":\"请不要更换商户退款单号,请使用相同参数再次调用API。\"},\n" + + "{\"BIZERR_NEED_RETRY\":{\"detail\":\"退款业务流程错误,需要商户触发重试来解决\",\"reason\":\"并发情况下,业务被拒绝,商户重试即可解决\",\"resolution\":\"请不要更换商户退款单号,请使用相同参数再次调用API。\"},\n" + + "{\"TRADE_OVERDUE\":{\"detail\":\"订单已经超过退款期限\",\"reason\":\"订单已经超过可退款的最大期限(支付后一年内可退款)\t\",\"resolution\":\"请选择其他方式自行退款\"},\n" + + "{\"ERROR\":{\"detail\":\"业务错误\",\"reason\":\"申请退款业务发生错误\",\"resolution\":\"该错误都会返回具体的错误原因,请根据实际返回做相应处理。\"},\n" + + "{\"USER_ACCOUNT_ABNORMAL\":{\"detail\":\"退款请求失败\",\"reason\":\"用户帐号注销\",\"resolution\":\"此状态代表退款申请失败,商户可自行处理退款。\"},\n" + + "{\"INVALID_REQ_TOO_MUCH\":{\"detail\":\"无效请求过多\",\"reason\":\"连续错误请求数过多被系统短暂屏蔽\t\",\"resolution\":\"请检查业务是否正常,确认业务正常后请在1分钟后再来重试\"},\n" + + "{\"NOTENOUGH\":{\"detail\":\"余额不足\",\"reason\":\"商户可用退款余额不足\",\"resolution\":\"此状态代表退款申请失败,商户可根据具体的错误提示做相应的处理。\"},\n" + + "{\"INVALID_TRANSACTIONID\":{\"detail\":\"无效transaction_id\",\"reason\":\"请求参数未按指引进行填写\",\"resolution\":\"请求参数错误,检查原交易号是否存在或发起支付交易接口返回失败\"},\n" + + "{\"PARAM_ERROR\":{\"detail\":\"参数错误\",\"reason\":\"请求参数未按指引进行填写\",\"resolution\":\"请求参数错误,请重新检查再调用退款申请\"},\n" + + "{\"APPID_NOT_EXIST\":{\"detail\":\"APPID不存在\",\"reason\":\"参数中缺少APPID\",\"resolution\":\"请检查APPID是否正确\"},\n" + + "{\"MCHID_NOT_EXIST\":{\"detail\":\"MCHID不存在\",\"reason\":\"参数中缺少MCHID\",\"resolution\":\"请检查MCHID是否正确\"},\n" + + "{\"REQUIRE_POST_METHOD\":{\"detail\":\"请使用post方法\",\"reason\":\"未使用post传递参数\",\"resolution\":\"请检查请求参数是否通过post方法提交\"},\n" + + "{\"SIGNERROR\":{\"detail\":\"签名错误\",\"reason\":\"参数签名结果不正确\",\"resolution\":\"请检查签名参数和方法是否都符合签名算法要求\"},\n" + + "{\"XML_FORMAT_ERROR\":{\"detail\":\"XML格式错误\",\"reason\":\"XML格式错误\",\"resolution\":\"请检查XML参数格式是否正确\"},\n" + + "{\"FREQUENCY_LIMITED\":{\"detail\":\"频率限制\",\"reason\":\"2个月之前的订单申请退款有频率限制\",\"resolution\":\"该笔退款未受理,请降低频率后重试\"}"); + + JSONObject errorRefundQueryMap = JSON.parseObject("{\"SYSTEMERROR\":{\"detail\":\"接口返回错误\",\"reason\":\"系统超时等\",\"resolution\":\"请不要更换商户退款单号,请使用相同参数再次调用API。\"},\n" + + "{\"BIZERR_NEED_RETRY\":{\"detail\":\"退款业务流程错误,需要商户触发重试来解决\",\"reason\":\"并发情况下,业务被拒绝,商户重试即可解决\",\"resolution\":\"请不要更换商户退款单号,请使用相同参数再次调用API。\"},\n" + + "{\"TRADE_OVERDUE\":{\"detail\":\"订单已经超过退款期限\",\"reason\":\"订单已经超过可退款的最大期限(支付后一年内可退款)\t\",\"resolution\":\"请选择其他方式自行退款\"},\n" + + "{\"ERROR\":{\"detail\":\"业务错误\",\"reason\":\"申请退款业务发生错误\",\"resolution\":\"该错误都会返回具体的错误原因,请根据实际返回做相应处理。\"},\n" + + "{\"USER_ACCOUNT_ABNORMAL\":{\"detail\":\"退款请求失败\",\"reason\":\"用户帐号注销\",\"resolution\":\"此状态代表退款申请失败,商户可自行处理退款。\"},\n" + + "{\"INVALID_REQ_TOO_MUCH\":{\"detail\":\"无效请求过多\",\"reason\":\"连续错误请求数过多被系统短暂屏蔽\t\",\"resolution\":\"请检查业务是否正常,确认业务正常后请在1分钟后再来重试\"},\n" + + "{\"NOTENOUGH\":{\"detail\":\"余额不足\",\"reason\":\"商户可用退款余额不足\",\"resolution\":\"此状态代表退款申请失败,商户可根据具体的错误提示做相应的处理。\"},\n" + + "{\"INVALID_TRANSACTIONID\":{\"detail\":\"无效transaction_id\",\"reason\":\"请求参数未按指引进行填写\",\"resolution\":\"请求参数错误,检查原交易号是否存在或发起支付交易接口返回失败\"},\n" + + "{\"PARAM_ERROR\":{\"detail\":\"参数错误\",\"reason\":\"请求参数未按指引进行填写\",\"resolution\":\"请求参数错误,请重新检查再调用退款申请\"},\n" + + "{\"APPID_NOT_EXIST\":{\"detail\":\"APPID不存在\",\"reason\":\"参数中缺少APPID\",\"resolution\":\"请检查APPID是否正确\"},\n" + + "{\"MCHID_NOT_EXIST\":{\"detail\":\"MCHID不存在\",\"reason\":\"参数中缺少MCHID\",\"resolution\":\"请检查MCHID是否正确\"},\n" + + "{\"REQUIRE_POST_METHOD\":{\"detail\":\"请使用post方法\",\"reason\":\"未使用post传递参数\",\"resolution\":\"请检查请求参数是否通过post方法提交\"},\n" + + "{\"SIGNERROR\":{\"detail\":\"签名错误\",\"reason\":\"参数签名结果不正确\",\"resolution\":\"请检查签名参数和方法是否都符合签名算法要求\"},\n" + + "{\"XML_FORMAT_ERROR\":{\"detail\":\"XML格式错误\",\"reason\":\"XML格式错误\",\"resolution\":\"请检查XML参数格式是否正确\"},\n" + + "{\"FREQUENCY_LIMITED\":{\"detail\":\"频率限制\",\"reason\":\"2个月之前的订单申请退款有频率限制\",\"resolution\":\"该笔退款未受理,请降低频率后重试\"}"); + + @Override + public ResultData createRefundOrder(WxAppinfo appInfo, WxRefundOrder record, EnumPayWay payWay) { + // check 是否有退款订单 + List list = wxRefundOrderMapper.findList(record); + if (list.size() > 0) { + throw new MallinkException(ErrorCode.REFUND_ORDER_EXIST); + } + // check 支付 订单 + WxPayOrder payOrder = null; + try { + WxPayOrder payOrderQ = new WxPayOrder(); + payOrderQ.setOrderId(record.getOrderId()); + payOrderQ.setId(Long.valueOf(record.getPayOrderNo())); + payOrderQ.setPayOrderNo(record.getPayOrderNo()); + payOrderQ.setPayOrderStatus(EnumPayStatus.PAY_WAY_SUCCESS.getCode()); + payOrder = wxPayOrderMapper.selectOne(payOrderQ); + } catch (Exception e) { + throw new MallinkException(ErrorCode.DB_FAIL); + } + + if (payOrder == null) { + throw new MallinkException(ErrorCode.REFUND_PAY_ORDER_IS_NOT_EXIST); + } + if (payOrder.getPayAmount() <= 0) { + throw new MallinkException(ErrorCode.REFUND_PAY_ORDER_IS_NOT_EXIST); + } + + // TODO check 可退券???? + + // 创建退款订单 + final IdWorker idWorker = IdWorker.get(); + Long id = idWorker.nextId(); + Date currentDate = new Date(); + + try { + record.setId(id); + record.setTenantId(appInfo.getTenantId()); + record.setCreateTime(currentDate); + record.setUpdateTime(currentDate); + record.setTransactionId(payOrder.getTransactionId()); + record.setCUserId(payOrder.getCUserId()); + record.setTotalFee(payOrder.getPayAmount()); + record.setRefundFee(payOrder.getPayAmount()); + record.setRefundTimeStart((int)(currentDate.getTime()/1000)); + record.setRefundOrderStatus(EnumRefundStatus.REFUND_WAIT.getCode()); + int sqlRow = wxRefundOrderMapper.insertSelective(record); + if(sqlRow != 1) { + throw new MallinkException(ErrorCode.DB_FAIL); + } + } catch (Exception e) { + throw new MallinkException(ErrorCode.DB_FAIL); + } + + WxPayAccount payAccount = wxPayAccountMapper.selectByPrimaryKey(appInfo.getPayId()); + + // 退款申请 + try { + String noncestr = Utility.generate32UUID(); + WxRefundOrderP wxRefundOrderP = new WxRefundOrderP(); + wxRefundOrderP.setAppid(appInfo.getAppId()); + wxRefundOrderP.setMch_id(payAccount.getMchId()); + wxRefundOrderP.setNonce_str(noncestr); + wxRefundOrderP.setTransaction_id(record.getTransactionId()); + wxRefundOrderP.setOut_trade_no(record.getPayOrderNo()); + wxRefundOrderP.setTotal_fee(record.getTotalFee()); + wxRefundOrderP.setRefund_fee(record.getRefundFee()); + wxRefundOrderP.setSign(WxPayment.createSign(BeanUtils.toStringMap(wxRefundOrderP), payAccount.getApiKey())); + String response = WxPay.orderRefund(BeanUtils.toStringMap(wxRefundOrderP), payAccount.getCertPath(), payAccount.getApiKey()); + logger.info("微信退款订单:" + wxRefundOrderP.toString() + ", response: " + response.toString()); + Map returnMap = WxPayment.xmlToMap(response); + String result_no = returnMap.get("result_code"); + if ("SUCCESS".equals(result_no)) { + String refund_id = returnMap.get("refund_id"); + record.setRefundId(refund_id); + record.setRefundOrderStatus(EnumRefundStatus.REFUND_REQ_SUCCESS.getCode()); + wxRefundOrderMapper.updateByPrimaryKey(record); + return new ResultData(200, "退款订单申请成功", returnMap); + } else { + String refund_id = returnMap.get("refund_id"); + record.setRefundId(refund_id); + record.setRefundOrderStatus(EnumRefundStatus.REFUND_REQ_FAIL.getCode()); + wxRefundOrderMapper.updateByPrimaryKey(record); + JSONObject errObj = errorRefundReqMap.getJSONObject(result_no); + return new ResultData(ErrorCode.PAY_ORDER_ERROR.getCode(), errObj.toJSONString(), returnMap); + } + } catch(Exception e) { + throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR); + } + } + + // TODO + // 微信退款查询 + @Override + public ResultData queryRefundOrder(WxAppinfo appInfo, WxRefundOrder record) { + WxPayAccount payAccount = wxPayAccountMapper.selectByPrimaryKey(appInfo.getPayId()); + + Map paramMap = WxPayment.buildWeappRefundQueryMap(appInfo.getAppId(), payAccount.getMchId(), + record.getTransactionId(), record.getPayOrderNo(), String.valueOf(record.getId()), record.getRefundId(), payAccount.getApiKey()); + String response = WxPay.orderRefundQuery(paramMap); + Map returnMap = WxPayment.xmlToMap(response); + String result_no = returnMap.get("result_code"); + if ("SUCCESS".equals(result_no)) { + String refund_id = returnMap.get("refund_id"); + return new ResultData(200, "退款", returnMap); + } else { + wxRefundOrderMapper.updateByPrimaryKey(record); + JSONObject errObj = errorRefundReqMap.getJSONObject(result_no); + return new ResultData(ErrorCode.REFUND_ORDER_ERROR.getCode(), errObj.toJSONString(), returnMap); + } + } + // 微信退款结果通知 + + + @Override + public PageInfo listAsPage(WxRefundOrder record, Integer pageIndex, Integer pageSize) { + return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxRefundOrderMapper.findList(record)); + } + + @Override + public WxRefundOrder getById(Long id) { + return wxRefundOrderMapper.selectByPrimaryKey(id); + } + + @Override + public void saveOrUpdate(WxRefundOrder record) { + if (record.getId() == null) { + //record.setId(UUID.randomUUID().toString().replaceAll("-", "")); + final IdWorker idWorker = IdWorker.get(); + record.setId(idWorker.nextId()); + wxRefundOrderMapper.insertSelective(record); + } else { + wxRefundOrderMapper.updateByPrimaryKeySelective(record); + } + } + + @Override + public void deleteById(Long id) { + wxRefundOrderMapper.deleteByPrimaryKey(id); + } + + + + + + + + +} diff --git a/mallinkService/src/main/java/com/simple/utils/RandomUtils.java b/mallinkService/src/main/java/com/simple/utils/RandomUtils.java index 5ef79a95e..940438061 100644 --- a/mallinkService/src/main/java/com/simple/utils/RandomUtils.java +++ b/mallinkService/src/main/java/com/simple/utils/RandomUtils.java @@ -30,4 +30,9 @@ public class RandomUtils { return str.toString(); } + + public static void main(String[] args) { + System.out.println(getStr(32)); + } + } \ No newline at end of file diff --git a/mallinkService/src/main/resources/mapper/WxRefundOrderMapper.xml b/mallinkService/src/main/resources/mapper/WxRefundOrderMapper.xml new file mode 100644 index 000000000..7f86d8a5f --- /dev/null +++ b/mallinkService/src/main/resources/mapper/WxRefundOrderMapper.xml @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + `id`,`tenant_id`,`create_time`,`update_time`,`transaction_id`,`order_id`,`pay_order_no`,`c_user_id`,`total_fee`,`refund_fee`,`refund_time_start`,`refund_time_end`,`refund_vendor`,`refund_order_status`,`refund_id`,`fail_reason` + + + + where 1 = 1 + + + and `id` = #{id} + + + + + and `tenant_id` like concat('%', #{tenantId},'%') + + + + + and `create_time` = #{createTime} + + + + + and `update_time` = #{updateTime} + + + + + and `transaction_id` like concat('%', #{transactionId},'%') + + + + + and `order_id` = #{orderId} + + + + + and `pay_order_no` like concat('%', #{payOrderNo},'%') + + + + + and `c_user_id` = #{cUserId} + + + + + and `total_fee` = #{totalFee} + + + + + and `refund_fee` = #{refundFee} + + + + + and `refund_time_start` = #{refundTimeStart} + + + + + and `refund_time_end` = #{refundTimeEnd} + + + + + and `refund_vendor` = #{refundVendor} + + + + + and `refund_order_status` = #{refundOrderStatus} + + + + + and `refund_id` like concat('%', #{refundId},'%') + + + + + and `fail_reason` like concat('%', #{failReason},'%') + + + + and id in + + #{idItem} + + + order by ${sortColumns} + + + + + + + + + +