提交 ef099e81 authored 作者: hzh's avatar hzh

代码优化

上级 0b0c08e8
package org.dromara.common.pay.domain;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* @author hzh
* @date 2024-12-10
**/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors(chain = true)
public class Amount implements Serializable {
/**
* 订单总金额,单位为分。
*/
private Integer total;
/**
* 用户支付金额,单位为分。
*/
private Integer payer_total;
/**
* CNY:人民币,境内商户号仅支持人民币。
*/
private String currency;
/**
* 用户支付币种
*/
private String payer_currency;
}
package org.dromara.common.pay.domain;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* @author hzh
* @date 2024-12-10
**/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors(chain = true)
public class GoodsDetail implements Serializable {
/**
* 商品编码。
*/
private String goods_id;
/**
* 用户购买的数量。
*/
private Integer quantity;
/**
* 商品单价,单位为分。
*/
private Integer unit_price;
/**
* 商品优惠金额。
*/
private Integer discount_amount;
/**
* 商品备注信息。
*/
private String goods_remark;
}
...@@ -18,6 +18,7 @@ import java.io.Serializable; ...@@ -18,6 +18,7 @@ import java.io.Serializable;
@NoArgsConstructor @NoArgsConstructor
@Data @Data
@Accessors(chain = true) @Accessors(chain = true)
@SuppressWarnings("all")
public class JsapiNotifyModel implements Serializable { public class JsapiNotifyModel implements Serializable {
/** /**
...@@ -103,4 +104,160 @@ public class JsapiNotifyModel implements Serializable { ...@@ -103,4 +104,160 @@ public class JsapiNotifyModel implements Serializable {
*/ */
private PromotionDetail promotion_detail; private PromotionDetail promotion_detail;
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors(chain = true)
static class Payer implements Serializable {
/**
* 用户在直连商户AppID下的唯一标识。
*/
private String openid;
}
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors(chain = true)
static class Amount implements Serializable {
/**
* 订单总金额,单位为分。
*/
private Integer total;
/**
* 用户支付金额,单位为分。
*/
private Integer payer_total;
/**
* CNY:人民币,境内商户号仅支持人民币。
*/
private String currency;
/**
* 用户支付币种
*/
private String payer_currency;
}
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors(chain = true)
static class SceneInfo implements Serializable {
/**
* 终端设备号(门店号或收银设备ID)。
*/
private String device_id;
}
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors(chain = true)
static class PromotionDetail implements Serializable {
/**
* 券ID。
*/
private String coupon_id;
/**
* 优惠名称。
*/
private String name;
/**
* 优惠范围,枚举值:
* GLOBAL:全场代金券
* SINGLE:单品优惠。
*/
private String scope;
/**
* 优惠类型,枚举值:
* CASH:充值型代金券
* NOCASH:免充值型代金券
*/
private String type;
/**
* 优惠券面额。
*/
private Integer amount;
/**
* 活动ID。
*/
private String stock_id;
/**
* 微信出资,单位为分。
*/
private Integer wechatpay_contribute;
/**
* 商户出资,单位为分。
*/
private Integer merchant_contribute;
/**
* 其他出资,单位为分。
*/
private Integer other_contribute;
/**
* CNY:人民币,境内商户号仅支持人民币
*/
private String currency;
/**
* 单品列表信息
*/
private GoodsDetail goods_detail;
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors(chain = true)
static class GoodsDetail implements Serializable {
/**
* 商品编码。
*/
private String goods_id;
/**
* 用户购买的数量。
*/
private Integer quantity;
/**
* 商品单价,单位为分。
*/
private Integer unit_price;
/**
* 商品优惠金额。
*/
private Integer discount_amount;
/**
* 商品备注信息。
*/
private String goods_remark;
}
}
} }
package org.dromara.common.pay.domain;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* @author hzh
* @date 2024-12-10
**/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors(chain = true)
public class Payer implements Serializable {
/**
* 用户在直连商户AppID下的唯一标识。
*/
private String openid;
}
package org.dromara.common.pay.domain;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* @author hzh
* @date 2024-12-10
**/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors(chain = true)
public class PromotionDetail implements Serializable {
/**
* 券ID。
*/
private String coupon_id;
/**
* 优惠名称。
*/
private String name;
/**
* 优惠范围,枚举值:
* GLOBAL:全场代金券
* SINGLE:单品优惠。
*/
private String scope;
/**
* 优惠类型,枚举值:
* CASH:充值型代金券
* NOCASH:免充值型代金券
*/
private String type;
/**
* 优惠券面额。
*/
private Integer amount;
/**
* 活动ID。
*/
private String stock_id;
/**
* 微信出资,单位为分。
*/
private Integer wechatpay_contribute;
/**
* 商户出资,单位为分。
*/
private Integer merchant_contribute;
/**
* 其他出资,单位为分。
*/
private Integer other_contribute;
/**
* CNY:人民币,境内商户号仅支持人民币
*/
private String currency;
/**
* 单品列表信息
*/
private GoodsDetail goods_detail;
}
package org.dromara.common.pay.domain;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.List;
/**
* @author hzh
* @date 2024-12-13
* @desc 退款退款对象
**/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors(chain = true)
@SuppressWarnings("all")
public class RefundModel implements Serializable {
/**
* 【微信支付退款号】 微信支付退款号
*/
private String refund_id;
/**
* 【商户退款单号】 商户系统内部的退款单号,商户系统内部唯一,只能是数字、大小写字母_-|*@ ,同一退款单号多次请求只退一笔。
*/
private String out_refund_no;
/**
* 【微信支付订单号】 微信支付交易订单号
*/
private String transaction_id;
/**
* 【商户订单号】 原支付交易对应的商户订单号
*/
private String out_trade_no;
/**
* 【退款渠道】 退款渠道
* 可选取值:
* ORIGINAL: 原路退款
* BALANCE: 退回到余额
* OTHER_BALANCE: 原账户异常退到其他余额账户
* OTHER_BANKCARD: 原银行卡异常退到其他银行卡
*/
private String channel;
/**
* 【退款入账账户】 取当前退款单的退款入账方,有以下几种情况:
* 1)退回银行卡:{银行名称}{卡类型}{卡尾号}
* 2)退回支付用户零钱:支付用户零钱
* 3)退还商户:商户基本账户商户结算银行账户
* 4)退回支付用户零钱通:支付用户零钱通
* 5)退回支付用户银行电子账户:支付用户银行电子账户
* 6)退回支付用户零花钱:支付用户零花钱
* 7)退回用户经营账户:用户经营账户
* 8)退回支付用户来华零钱包:支付用户来华零钱包
* 9)退回企业支付商户:企业支付商户
*/
private String user_received_account;
/**
* 【退款成功时间】 退款成功时间,退款状态status为SUCCESS(退款成功)时,返回该字段。遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日13点29分35秒。
*/
private String success_time;
/**
* 【退款创建时间】 退款受理时间,遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日13点29分35秒。
*/
private String create_time;
/**
* 【退款状态】 退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败,可前往商户平台(pay.weixin.qq.com)-交易中心,手动处理此笔退款。
* 可选取值:
* SUCCESS: 退款成功
* CLOSED: 退款关闭
* PROCESSING: 退款处理中
* ABNORMAL: 退款异常
*/
private String status;
/**
* 【资金账户】 退款所使用资金对应的资金账户类型
* 可选取值:
* UNSETTLED: 未结算资金
* AVAILABLE: 可用余额
* UNAVAILABLE: 不可用余额
* OPERATION: 运营户
* BASIC: 基本账户(含可用余额和不可用余额)
* ECNY_BASIC: 数字人民币基本账户
*/
private String funds_account;
/**
* 【金额信息】 金额详细信息
*/
private RefundAmount amount;
/**
* 【优惠退款信息】 优惠退款信息
*/
private List<PromotionDetail> promotion_detail;
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors(chain = true)
static class RefundAmount implements Serializable {
/**
* 订单总金额,单位为分。
*/
private Integer total;
/**
* 【退款金额】 退款标价金额,单位为分,可以做部分退款
*/
private Integer refund;
/**
* 【退款出资账户及金额】 退款出资的账户类型及金额信息
*/
private From from;
/**
* 用户支付金额,单位为分。
*/
private Integer payer_total;
/**
* 【用户退款金额】 退款给用户的金额,单位为分,不包含所有优惠券金额
*/
private Integer payer_refund;
/**
* 【应结退款金额】 去掉非充值代金券退款金额后的退款金额,单位为分,退款金额=申请退款金额-非充值代金券退款金额,退款金额<=申请退款金额
*/
private Integer settlement_refund;
/**
* 【应结订单金额】 应结订单金额=订单金额-免充值代金券金额,应结订单金额<=订单金额,单位为分
*/
private Integer settlement_total;
/**
* 【优惠退款金额】 优惠退款金额<=退款金额,退款金额-代金券或立减优惠退款金额为现金,说明详见代金券或立减优惠,单位为分
*/
private Integer discount_refund;
/**
* 【退款币种】 符合ISO 4217标准的三位字母代码,目前只支持人民币:CNY。
*/
private String currency;
/**
* 【手续费退款金额】 手续费退款金额,单位为分
*/
private Integer refund_fee;
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors(chain = true)
static class From implements Serializable {
/**
* 【出资账户类型】 出资账户类型
* 可选取值:
* AVAILABLE: 可用余额
* UNAVAILABLE: 不可用余额
*/
private String account;
/**
* 【出资金额】 对应账户出资金额,单位为分
*/
private Integer amount;
}
}
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors(chain = true)
static class PromotionDetail implements Serializable {
/**
* 【券ID】 券或者立减优惠id
*/
private String promotion_id;
/**
* 【优惠范围】 优惠范围
* 可选取值:
* GLOBAL: 全场优惠类型
* SINGLE: 单品优惠类型
*/
private String scope;
/**
* 【优惠类型】 优惠类型
* 可选取值:
* COUPON: 代金券类型,需要走结算资金的充值型代金券
* DISCOUNT: 优惠券类型,不走结算资金的免充值型优惠券
*/
private String type;
/**
* 【优惠券面额】 用户享受优惠的金额(优惠券面额=微信出资金额+商家出资金额+其他出资方金额 ),单位为分
*/
private Integer amount;
/**
* 【优惠退款金额】 优惠退款金额<=退款金额,退款金额-代金券或立减优惠退款金额为用户支付的现金,说明详见代金券或立减优惠,单位为分
*/
private Integer refund_amount;
/**
* 【商品列表】 优惠商品发生退款时返回商品信息
*/
private List<GoodsDetail> goods_detail;
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors(chain = true)
static class GoodsDetail implements Serializable {
/**
* 【商户侧商品编码】 商品编码,由半角的大小写字母、数字、中划线、下划线中的一种或几种组成。
*/
private String merchant_goods_id;
/**
* 【微信侧商品编码】 微信支付定义的统一商品编号(没有可不传)
*/
private String wechatpay_goods_id;
/**
* 【商品名称】 商品的实际名称
*/
private String goods_name;
/**
* 【商品单价】 商品单价金额,单位为分
*/
private Integer unit_price;
/**
* 【商品退款金额】 商品退款金额,单位为分
*/
private Integer refund_amount;
/**
* 【商品退货数量】 对应商品的退货数量
*/
private Integer refund_quantity;
}
}
}
package org.dromara.common.pay.domain;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* @author hzh
* @date 2024-12-10
**/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors(chain = true)
public class SceneInfo implements Serializable {
/**
* 终端设备号(门店号或收银设备ID)。
*/
private String device_id;
}
package org.dromara.common.pay.service; package org.dromara.common.pay.service;
import com.ijpay.wxpay.model.v3.RefundModel;
import com.ijpay.wxpay.model.v3.UnifiedOrderModel; import com.ijpay.wxpay.model.v3.UnifiedOrderModel;
import org.dromara.common.pay.domain.JsapiNotifyModel; import org.dromara.common.pay.domain.JsapiNotifyModel;
...@@ -53,5 +54,13 @@ public interface IWxPayService { ...@@ -53,5 +54,13 @@ public interface IWxPayService {
*/ */
JsapiNotifyModel notify(String timestamp, String nonce, String signature, String result); JsapiNotifyModel notify(String timestamp, String nonce, String signature, String result);
/**
* 退款
* @param model model
* @return 退款结果
* @throws Exception 异常
*/
org.dromara.common.pay.domain.RefundModel refund(RefundModel model) throws Exception;
} }
...@@ -20,10 +20,7 @@ import com.ijpay.wxpay.WxPayApi; ...@@ -20,10 +20,7 @@ import com.ijpay.wxpay.WxPayApi;
import com.ijpay.wxpay.enums.WxDomainEnum; import com.ijpay.wxpay.enums.WxDomainEnum;
import com.ijpay.wxpay.enums.v3.BasePayApiEnum; import com.ijpay.wxpay.enums.v3.BasePayApiEnum;
import com.ijpay.wxpay.enums.v3.OtherApiEnum; import com.ijpay.wxpay.enums.v3.OtherApiEnum;
import com.ijpay.wxpay.model.v3.Certificate; import com.ijpay.wxpay.model.v3.*;
import com.ijpay.wxpay.model.v3.CertificateInfo;
import com.ijpay.wxpay.model.v3.EncryptCertificate;
import com.ijpay.wxpay.model.v3.UnifiedOrderModel;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.dromara.common.pay.config.WechatPayConfiguration; import org.dromara.common.pay.config.WechatPayConfiguration;
...@@ -299,4 +296,28 @@ public class WxPayServiceImpl implements IWxPayService { ...@@ -299,4 +296,28 @@ public class WxPayServiceImpl implements IWxPayService {
throw new RuntimeException("订单:" + outTradeNo + "关闭失败!"); throw new RuntimeException("订单:" + outTradeNo + "关闭失败!");
} }
} }
@Override
public org.dromara.common.pay.domain.RefundModel refund(RefundModel model) throws Exception {
model.setNotify_url(config.getNotify());
log.info("统一退款参数 {}", JSONUtil.toJsonStr(model));
IJPayHttpResponse response = WxPayApi.v3(
RequestMethodEnum.POST,
WxDomainEnum.CHINA.toString(),
BasePayApiEnum.DOMESTIC_REFUND.toString(),
config.getMchId(),
getSerialNumber(),
null,
config.getKeyPath(),
JSONUtil.toJsonStr(model));
log.info("统一退款接口响应 {}", response);
// 根据证书序列号查询对应的证书来验证签名结果
boolean verifySignature = WxPayKit.verifySignature(response, config.getPlatformCertPath());
log.info("verifySignature: {}", verifySignature);
if (response.getStatus() == HttpStatus.HTTP_OK && verifySignature) {
String body = response.getBody();
return com.alibaba.fastjson.JSONObject.parseObject(body, org.dromara.common.pay.domain.RefundModel.class);
}
throw new RuntimeException("退款失败!");
}
} }
...@@ -9,7 +9,6 @@ import lombok.RequiredArgsConstructor; ...@@ -9,7 +9,6 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference; import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.common.pay.domain.Amount;
import org.dromara.common.pay.domain.JsapiNotifyModel; import org.dromara.common.pay.domain.JsapiNotifyModel;
import org.dromara.common.pay.service.IWxPayService; import org.dromara.common.pay.service.IWxPayService;
import org.dromara.order.api.enums.OrderStatus; import org.dromara.order.api.enums.OrderStatus;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论