| @@ -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<WxRefundOrder> 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)); | |||||
| } | |||||
| } | |||||
| @@ -96,8 +96,14 @@ public enum ErrorCode{ | |||||
| * 支付 | * 支付 | ||||
| */ | */ | ||||
| PAY_ORDER_EXIST(12001, "支付订单已存在"), | 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, "退款验签失败"); | |||||
| @@ -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<Long> 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<Long> getIds() { | |||||
| return ids; | |||||
| } | |||||
| public void setIds(List<Long> 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<Field> 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)); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -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; | |||||
| } | |||||
| } | |||||
| @@ -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<WxRefundOrder, Long> { | |||||
| List<WxRefundOrder> findList(WxRefundOrder wxRefundOrder); | |||||
| } | |||||
| @@ -243,6 +243,35 @@ public class WxPayment { | |||||
| return buildSignAfterParasMap(params, paternerKey); | return buildSignAfterParasMap(params, paternerKey); | ||||
| } | } | ||||
| /** | |||||
| * 查询退款 | |||||
| * | |||||
| * @param appid | |||||
| * @param mch_id | |||||
| * @param out_trade_no | |||||
| * @param paternerKey | |||||
| * @return | |||||
| */ | |||||
| public static Map<String, String> buildWeappRefundQueryMap(String appid, String mch_id, | |||||
| String transaction_id, String out_trade_no, String out_refund_no, String refund_id, | |||||
| String paternerKey) { | |||||
| Map<String, String> params = new HashMap<String, String>(); | |||||
| 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); | |||||
| } | |||||
| /** | /** | ||||
| * 组装签名的字段 | * 组装签名的字段 | ||||
| * | * | ||||
| @@ -3,11 +3,12 @@ package com.simple.pay; | |||||
| /** | /** | ||||
| * Created by Stormeye on 2018/8/10. | * Created by Stormeye on 2018/8/10. | ||||
| */ | */ | ||||
| public class WxRefundOrder { | |||||
| public class WxRefundOrderP { | |||||
| private String appid; // 公众账号ID | private String appid; // 公众账号ID | ||||
| private String mch_id; // 商户号 | private String mch_id; // 商户号 | ||||
| private String nonce_str; // 随机字符串 | private String nonce_str; // 随机字符串 | ||||
| private String sign; // 签名 | private String sign; // 签名 | ||||
| private String transaction_id; // 微信订单号 | |||||
| private String out_trade_no; // 商户订单号 | private String out_trade_no; // 商户订单号 | ||||
| private String out_refund_no; // 商户退款单号 | private String out_refund_no; // 商户退款单号 | ||||
| private Integer total_fee; // 支付金额 | private Integer total_fee; // 支付金额 | ||||
| @@ -45,6 +46,14 @@ public class WxRefundOrder { | |||||
| this.sign = sign; | 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() { | public String getOut_trade_no() { | ||||
| return out_trade_no; | return out_trade_no; | ||||
| } | } | ||||
| @@ -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<WxRefundOrder> 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); | |||||
| } | |||||
| @@ -103,7 +103,7 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { | |||||
| record.setPayOrderStatus(EnumPayStatus.PAY_WAY_WAIT.getCode()); | record.setPayOrderStatus(EnumPayStatus.PAY_WAY_WAIT.getCode()); | ||||
| int sqlRow = wxPayOrderMapper.insertSelective(record); | int sqlRow = wxPayOrderMapper.insertSelective(record); | ||||
| if(sqlRow == 1) { | |||||
| if(sqlRow != 1) { | |||||
| throw new MallinkException(ErrorCode.DB_FAIL); | throw new MallinkException(ErrorCode.DB_FAIL); | ||||
| } | } | ||||
| WxPayAccount payAccount = wxPayAccountMapper.selectByPrimaryKey(appInfo.getPayId()); | WxPayAccount payAccount = wxPayAccountMapper.selectByPrimaryKey(appInfo.getPayId()); | ||||
| @@ -122,7 +122,7 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { | |||||
| wxPayOrderP.setTrade_type(WxPay.TradeType.APP.name()); // 终端类型 | wxPayOrderP.setTrade_type(WxPay.TradeType.APP.name()); // 终端类型 | ||||
| wxPayOrderP.setProduct_id(String.valueOf(order.getId())); // 订单ID | wxPayOrderP.setProduct_id(String.valueOf(order.getId())); // 订单ID | ||||
| wxPayOrderP.setTime_start(Utility.getDataFormatStringYYYYMMDDHHmmss(currentTime)); | 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())); | wxPayOrderP.setSign(WxPayment.createSign(BeanUtils.toStringMap(wxPayOrderP), payAccount.getApiKey())); | ||||
| String response = WxPay.pushOrder(BeanUtils.toStringMap(wxPayOrderP)); | String response = WxPay.pushOrder(BeanUtils.toStringMap(wxPayOrderP)); | ||||
| logger.info("pay order, wechat pushOrder, wxPayOrder:" + wxPayOrderP.toString() + ", response: " + response.toString()); | logger.info("pay order, wechat pushOrder, wxPayOrder:" + wxPayOrderP.toString() + ", response: " + response.toString()); | ||||
| @@ -154,6 +154,10 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { | |||||
| } | } | ||||
| } | } | ||||
| // TODO | |||||
| // 微信订单查询 | |||||
| // 微信关闭订单 | |||||
| @Override | @Override | ||||
| public String notify(Map<String, String> paramMap, EnumPayWay payWay) { | public String notify(Map<String, String> paramMap, EnumPayWay payWay) { | ||||
| // how to get wechatAppId, wechatMchId, partnerKey | // how to get wechatAppId, wechatMchId, partnerKey | ||||
| @@ -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<WxRefundOrder> 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<String, String> 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<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); | |||||
| Map<String, String> 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<WxRefundOrder> 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); | |||||
| } | |||||
| } | |||||
| @@ -30,4 +30,9 @@ public class RandomUtils { | |||||
| return str.toString(); | return str.toString(); | ||||
| } | } | ||||
| public static void main(String[] args) { | |||||
| System.out.println(getStr(32)); | |||||
| } | |||||
| } | } | ||||
| @@ -0,0 +1,128 @@ | |||||
| <?xml version="1.0" encoding="UTF-8"?> | |||||
| <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |||||
| <mapper namespace="com.simple.mapper.WxRefundOrderMapper"> | |||||
| <resultMap id="BaseResultMap" type="com.simple.domain.po.WxRefundOrder"> | |||||
| <id column="id" jdbcType="BIGINT" property="id" /> | |||||
| <result column="tenant_id" jdbcType="VARCHAR" property="tenantId" /> | |||||
| <result column="create_time" jdbcType="TIMESTAMP" property="createTime" /> | |||||
| <result column="update_time" jdbcType="TIMESTAMP" property="updateTime" /> | |||||
| <result column="transaction_id" jdbcType="VARCHAR" property="transactionId" /> | |||||
| <result column="order_id" jdbcType="BIGINT" property="orderId" /> | |||||
| <result column="pay_order_no" jdbcType="VARCHAR" property="payOrderNo" /> | |||||
| <result column="c_user_id" jdbcType="BIGINT" property="cUserId" /> | |||||
| <result column="total_fee" jdbcType="INTEGER" property="totalFee" /> | |||||
| <result column="refund_fee" jdbcType="INTEGER" property="refundFee" /> | |||||
| <result column="refund_time_start" jdbcType="INTEGER" property="refundTimeStart" /> | |||||
| <result column="refund_time_end" jdbcType="INTEGER" property="refundTimeEnd" /> | |||||
| <result column="refund_vendor" jdbcType="INTEGER" property="refundVendor" /> | |||||
| <result column="refund_order_status" jdbcType="INTEGER" property="refundOrderStatus" /> | |||||
| <result column="refund_id" jdbcType="VARCHAR" property="refundId" /> | |||||
| <result column="fail_reason" jdbcType="VARCHAR" property="failReason" /> | |||||
| </resultMap> | |||||
| <sql id="allColumns"> | |||||
| `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` | |||||
| </sql> | |||||
| <sql id="dynamicWhereConditions"> | |||||
| where 1 = 1 | |||||
| <if test=" null != id "> | |||||
| and `id` = #{id} | |||||
| </if> | |||||
| <if test=" null != tenantId "> | |||||
| and `tenant_id` like concat('%', #{tenantId},'%') | |||||
| </if> | |||||
| <if test=" null != createTime "> | |||||
| and `create_time` = #{createTime} | |||||
| </if> | |||||
| <if test=" null != updateTime "> | |||||
| and `update_time` = #{updateTime} | |||||
| </if> | |||||
| <if test=" null != transactionId "> | |||||
| and `transaction_id` like concat('%', #{transactionId},'%') | |||||
| </if> | |||||
| <if test=" null != orderId "> | |||||
| and `order_id` = #{orderId} | |||||
| </if> | |||||
| <if test=" null != payOrderNo "> | |||||
| and `pay_order_no` like concat('%', #{payOrderNo},'%') | |||||
| </if> | |||||
| <if test=" null != cUserId "> | |||||
| and `c_user_id` = #{cUserId} | |||||
| </if> | |||||
| <if test=" null != totalFee "> | |||||
| and `total_fee` = #{totalFee} | |||||
| </if> | |||||
| <if test=" null != refundFee "> | |||||
| and `refund_fee` = #{refundFee} | |||||
| </if> | |||||
| <if test=" null != refundTimeStart "> | |||||
| and `refund_time_start` = #{refundTimeStart} | |||||
| </if> | |||||
| <if test=" null != refundTimeEnd "> | |||||
| and `refund_time_end` = #{refundTimeEnd} | |||||
| </if> | |||||
| <if test=" null != refundVendor "> | |||||
| and `refund_vendor` = #{refundVendor} | |||||
| </if> | |||||
| <if test=" null != refundOrderStatus "> | |||||
| and `refund_order_status` = #{refundOrderStatus} | |||||
| </if> | |||||
| <if test=" null != refundId "> | |||||
| and `refund_id` like concat('%', #{refundId},'%') | |||||
| </if> | |||||
| <if test=" null != failReason "> | |||||
| and `fail_reason` like concat('%', #{failReason},'%') | |||||
| </if> | |||||
| <if test=" null != ids "> | |||||
| and id in | |||||
| <foreach collection="ids" index="index" item="idItem" open="(" separator="," close=")"> | |||||
| #{idItem} | |||||
| </foreach> | |||||
| </if> | |||||
| <if test=" null != sortColumns"> order by ${sortColumns} </if> | |||||
| </sql> | |||||
| <select id="findList" parameterType="com.simple.domain.po.WxRefundOrder" resultMap="BaseResultMap"> | |||||
| select <include refid="allColumns" /> from wx_refund_order | |||||
| <include refid="dynamicWhereConditions" /> | |||||
| </select> | |||||
| </mapper> | |||||