feat 分账接收方管理

This commit is contained in:
xxm1995
2024-03-27 22:04:49 +08:00
parent d306486e08
commit 9532f6366b
20 changed files with 402 additions and 69 deletions

View File

@@ -33,6 +33,9 @@ public class PayParam extends DaxPayRequest<PayOrderModel> {
/** 过期时间, 多次传输以第一次为准 */
private Long expiredTime;
/** 是否开启分账 */
private boolean allocation;
/** 用户付款中途退出返回商户网站的地址(部分支付场景中可用) */
private String quitUrl;

View File

@@ -0,0 +1,9 @@
package cn.bootx.platform.daxpay.code;
/**
* 分账关系类型
* @author xxm
* @since 2024/3/27
*/
public enum AllocationRelationTypeEnum {
}

View File

@@ -35,6 +35,9 @@ public class PayParam extends PaymentCommonParam {
@Schema(description = "支付描述")
private String description;
@Schema(description = "是否开启分账")
private boolean allocation;
@Schema(description = "过期时间, 多次传输以第一次为准")
@JsonDeserialize(using = TimestampToLocalDateTimeDeserializer.class)
private LocalDateTime expiredTime;
@@ -55,6 +58,7 @@ public class PayParam extends PaymentCommonParam {
@Schema(description = "同步跳转URL")
private String returnUrl;
/** 是否不启用异步通知 */
@Schema(description = "是否不启用异步通知")
private boolean notNotify;

View File

@@ -7,7 +7,6 @@ import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
import cn.bootx.platform.daxpay.param.pay.PayChannelParam;
import cn.bootx.platform.daxpay.param.pay.PayParam;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.util.IdUtil;
import lombok.experimental.UtilityClass;
import java.time.LocalDateTime;
@@ -21,6 +20,34 @@ import java.util.List;
*/
@UtilityClass
public class PayUtil {
/**
* 校验参数
*/
public void validation(PayParam payParam) {
// 验证支付金额
validationAmount(payParam.getPayChannels());
// 验证异步支付方式
validationAsyncPay(payParam);
// 验证是否可以分账
validationAllocation(payParam);
}
/**
* 验证是否可以分账
*/
private void validationAllocation(PayParam payParam) {
// 如果分账不启用, 不需要校验
if (!payParam.isAllocation()) {
return;
}
// 只有异步支付方式支持分账
if (!isNotSync(payParam.getPayChannels())) {
throw new PayFailureException("分账只支持包含异步支付通道的订单");
}
}
/**
* 检查异步支付方式
*/
@@ -36,8 +63,8 @@ public class PayUtil {
if (asyncPayCount > 1) {
throw new PayFailureException("组合支付时只允许有一个异步支付方式");
}
}
}
/**
* 检查支付金额
@@ -52,13 +79,6 @@ public class PayUtil {
}
}
/**
* 获取支付宝的过期时间
*/
public String getAliExpiredTime(int minute) {
return minute + "m";
}
/**
* 获取支付宝的过期时间 yyyy-MM-dd HH:mm:ss
*/
@@ -96,11 +116,4 @@ public class PayUtil {
.noneMatch(PayChannelEnum.ASYNC_TYPE_CODE::contains);
}
/**
* 生成退款号
*/
public String getRefundNo(){
// return "R" + IdUtil.getSnowflakeNextIdStr();
return IdUtil.getSnowflakeNextIdStr();
}
}

View File

@@ -109,6 +109,12 @@ public class AliPayService {
model.setProductCode(AliPayCode.QUICK_WAP_PAY);
// 中途退出地址
model.setQuitUrl(noticeInfo.getQuitUrl());
// 是否分账
if (payOrder.isAllocation()){
ExtendParams extendParams = new ExtendParams();
extendParams.setRoyaltyFreeze("true");
model.setExtendParams(extendParams);
}
AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
request.setBizModel(model);
@@ -140,6 +146,12 @@ public class AliPayService {
// 过期时间
model.setTimeExpire(PayUtil.getAliTimeExpire(payOrder.getExpiredTime()));
model.setTotalAmount(String.valueOf(amount*0.01));
// 是否分账
if (payOrder.isAllocation()){
ExtendParams extendParams = new ExtendParams();
extendParams.setRoyaltyFreeze("true");
model.setExtendParams(extendParams);
}
try {
// 异步回调必须到当前系统中
@@ -156,7 +168,6 @@ public class AliPayService {
* PC支付
*/
public String webPay(int amount, PayOrder payOrder, AliPayConfig alipayConfig) {
NoticeLocal noticeInfo = PaymentContextLocal.get().getNoticeInfo();
AlipayTradePagePayModel model = new AlipayTradePagePayModel();
model.setSubject(payOrder.getTitle());
@@ -167,6 +178,13 @@ public class AliPayService {
// 目前仅支持FAST_INSTANT_TRADE_PAY
model.setProductCode(AliPayCode.FAST_INSTANT_TRADE_PAY);
// 是否分账
if (payOrder.isAllocation()){
ExtendParams extendParams = new ExtendParams();
extendParams.setRoyaltyFreeze("true");
model.setExtendParams(extendParams);
}
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
request.setBizModel(model);
// 异步回调必须到当前系统中
@@ -192,7 +210,12 @@ public class AliPayService {
model.setSubject(payOrder.getTitle());
model.setOutTradeNo(String.valueOf(payOrder.getId()));
model.setTotalAmount(String.valueOf(amount*0.01));
// 是否分账
if (payOrder.isAllocation()){
ExtendParams extendParams = new ExtendParams();
extendParams.setRoyaltyFreeze("true");
model.setExtendParams(extendParams);
}
// 过期时间
model.setTimeExpire(PayUtil.getAliTimeExpire(payOrder.getExpiredTime()));
@@ -218,7 +241,12 @@ public class AliPayService {
model.setOutTradeNo(String.valueOf(payOrder.getId()));
model.setScene(AliPayCode.BAR_CODE);
model.setAuthCode(aliPayParam.getAuthCode());
// 是否分账
if (payOrder.isAllocation()){
ExtendParams extendParams = new ExtendParams();
extendParams.setRoyaltyFreeze("true");
model.setExtendParams(extendParams);
}
// 过期时间
model.setTimeExpire(PayUtil.getAliTimeExpire(payOrder.getExpiredTime()));
model.setTotalAmount(String.valueOf(amount*0.01));

View File

@@ -16,6 +16,7 @@ import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WeChatPayConf
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
import cn.bootx.platform.daxpay.service.core.payment.sync.service.PaySyncService;
import cn.bootx.platform.daxpay.service.param.channel.wechat.WeChatPayParam;
import cn.bootx.platform.daxpay.service.sdk.wechat.BarPayModel;
import cn.bootx.platform.daxpay.util.PayUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.net.NetUtil;
@@ -25,7 +26,6 @@ import com.ijpay.core.enums.SignType;
import com.ijpay.core.enums.TradeType;
import com.ijpay.core.kit.WxPayKit;
import com.ijpay.wxpay.WxPayApi;
import com.ijpay.wxpay.model.MicroPayModel;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.retry.annotation.Backoff;
@@ -66,7 +66,7 @@ public class WeChatPayService {
}
PayWayEnum payWayEnum = Optional.ofNullable(WeChatPayWay.findByCode(payChannelParam.getWay()))
.orElseThrow(() -> new PayFailureException("非法的微信支付类型"));
.orElseThrow(() -> new PayFailureException("非法的微信支付类型"));
if (!payWays.contains(payWayEnum.getCode())) {
throw new PayFailureException("该微信支付方式不可用");
}
@@ -105,7 +105,7 @@ public class WeChatPayService {
}
// 付款码支付
else if (payWayEnum == PayWayEnum.BARCODE) {
this.barCodePay(totalFee, payOrder, weChatPayParam.getAuthCode(), weChatPayConfig);
this.barCodePay(totalFee, payOrder, weChatPayParam.getAuthCode(), weChatPayConfig);
}
asyncPayInfo.setPayBody(payBody);
}
@@ -113,10 +113,10 @@ public class WeChatPayService {
/**
* wap支付
*/
private String wapPay(String amount, PayOrder payment, WeChatPayConfig weChatPayConfig) {
Map<String, String> params = this.buildParams(amount, payment, weChatPayConfig, TradeType.MWEB.getTradeType())
.build()
.createSign(weChatPayConfig.getApiKeyV2(), SignType.HMACSHA256);
private String wapPay(String amount, PayOrder payOrder, WeChatPayConfig weChatPayConfig) {
Map<String, String> params = this.buildParams(amount, payOrder, weChatPayConfig, TradeType.MWEB.getTradeType())
.build()
.createSign(weChatPayConfig.getApiKeyV2(), SignType.HMACSHA256);
String xmlResult = WxPayApi.pushOrder(false, params);
Map<String, String> result = WxPayKit.xmlToMap(xmlResult);
@@ -127,10 +127,10 @@ public class WeChatPayService {
/**
* 程序支付
*/
private String appPay(String amount, PayOrder payment, WeChatPayConfig weChatPayConfig) {
Map<String, String> params = this.buildParams(amount, payment, weChatPayConfig, TradeType.APP.getTradeType())
.build()
.createSign(weChatPayConfig.getApiKeyV2(), SignType.HMACSHA256);
private String appPay(String amount, PayOrder payOrder, WeChatPayConfig weChatPayConfig) {
Map<String, String> params = this.buildParams(amount, payOrder, weChatPayConfig, TradeType.APP.getTradeType())
.build()
.createSign(weChatPayConfig.getApiKeyV2(), SignType.HMACSHA256);
String xmlResult = WxPayApi.pushOrder(false, params);
Map<String, String> result = WxPayKit.xmlToMap(xmlResult);
@@ -141,11 +141,11 @@ public class WeChatPayService {
/**
* 微信公众号支付或者小程序支付
*/
private String jsPay(String amount, PayOrder payment, String openId, WeChatPayConfig weChatPayConfig) {
Map<String, String> params = this.buildParams(amount, payment, weChatPayConfig, TradeType.JSAPI.getTradeType())
.openid(openId)
.build()
.createSign(weChatPayConfig.getApiKeyV2(), SignType.HMACSHA256);
private String jsPay(String amount, PayOrder payOrder, String openId, WeChatPayConfig weChatPayConfig) {
Map<String, String> params = this.buildParams(amount, payOrder, weChatPayConfig, TradeType.JSAPI.getTradeType())
.openid(openId)
.build()
.createSign(weChatPayConfig.getApiKeyV2(), SignType.HMACSHA256);
String xmlResult = WxPayApi.pushOrder(false, params);
Map<String, String> result = WxPayKit.xmlToMap(xmlResult);
@@ -161,11 +161,11 @@ public class WeChatPayService {
/**
* 二维码支付
*/
private String qrCodePay(String amount, PayOrder payment, WeChatPayConfig weChatPayConfig) {
private String qrCodePay(String amount, PayOrder payOrder, WeChatPayConfig weChatPayConfig) {
Map<String, String> params = this.buildParams(amount, payment, weChatPayConfig, TradeType.NATIVE.getTradeType())
.build()
.createSign(weChatPayConfig.getApiKeyV2(), SignType.HMACSHA256);
Map<String, String> params = this.buildParams(amount, payOrder, weChatPayConfig, TradeType.NATIVE.getTradeType())
.build()
.createSign(weChatPayConfig.getApiKeyV2(), SignType.HMACSHA256);
String xmlResult = WxPayApi.pushOrder(false, params);
Map<String, String> result = WxPayKit.xmlToMap(xmlResult);
@@ -176,20 +176,21 @@ public class WeChatPayService {
/**
* 付款码支付
*/
private void barCodePay(String amount, PayOrder payment, String authCode, WeChatPayConfig weChatPayConfig) {
private void barCodePay(String amount, PayOrder payOrder, String authCode, WeChatPayConfig weChatPayConfig) {
PayLocal asyncPayInfo = PaymentContextLocal.get().getPayInfo();
Map<String, String> params = MicroPayModel.builder()
.appid(weChatPayConfig.getWxAppId())
.mch_id(weChatPayConfig.getWxMchId())
.nonce_str(WxPayKit.generateStr())
.body(payment.getTitle())
.auth_code(authCode)
.out_trade_no(String.valueOf(payment.getId()))
.total_fee(amount)
.spbill_create_ip(NetUtil.getLocalhostStr())
.build()
.createSign(weChatPayConfig.getApiKeyV2(), SignType.HMACSHA256);
Map<String, String> params = BarPayModel.builder()
.appid(weChatPayConfig.getWxAppId())
.mch_id(weChatPayConfig.getWxMchId())
.nonce_str(WxPayKit.generateStr())
.profit_sharing(payOrder.isAllocation()?"Y":"N")
.body(payOrder.getTitle())
.auth_code(authCode)
.out_trade_no(String.valueOf(payOrder.getId()))
.total_fee(amount)
.spbill_create_ip(NetUtil.getLocalhostStr())
.build()
.createSign(weChatPayConfig.getApiKeyV2(), SignType.HMACSHA256);
String xmlResult = WxPayApi.microPay(false, params);
Map<String, String> result = WxPayKit.xmlToMap(xmlResult);
@@ -211,7 +212,7 @@ public class WeChatPayService {
// 支付中, 发起轮训同步
if (Objects.equals(resultCode, WeChatPayCode.PAY_FAIL)
&& Objects.equals(errCode, WeChatPayCode.PAY_USERPAYING)) {
SpringUtil.getBean(this.getClass()).rotationSync(payment);
SpringUtil.getBean(this.getClass()).rotationSync(payOrder);
asyncPayInfo.setGatewayOrderNo(result.get(WeChatPayCode.TRANSACTION_ID));
return;
}
@@ -233,18 +234,19 @@ public class WeChatPayService {
private UnifiedOrderModelBuilder buildParams(String amount, PayOrder payOrder, WeChatPayConfig weChatPayConfig, String tradeType) {
return builder()
.appid(weChatPayConfig.getWxAppId())
.mch_id(weChatPayConfig.getWxMchId())
.nonce_str(WxPayKit.generateStr())
.time_start(LocalDateTimeUtil.format(LocalDateTime.now(), DatePattern.PURE_DATETIME_PATTERN))
// 反正v2版本的超时时间无效
.time_expire(PayUtil.getWxExpiredTime(payOrder.getExpiredTime()))
.body(payOrder.getTitle())
.out_trade_no(String.valueOf(payOrder.getId()))
.total_fee(amount)
.spbill_create_ip(NetUtil.getLocalhostStr())
.notify_url(weChatPayConfig.getNotifyUrl())
.trade_type(tradeType);
.appid(weChatPayConfig.getWxAppId())
.mch_id(weChatPayConfig.getWxMchId())
.nonce_str(WxPayKit.generateStr())
.time_start(LocalDateTimeUtil.format(LocalDateTime.now(), DatePattern.PURE_DATETIME_PATTERN))
// 反正v2版本的超时时间无效
.time_expire(PayUtil.getWxExpiredTime(payOrder.getExpiredTime()))
.body(payOrder.getTitle())
.profit_sharing(payOrder.isAllocation()?"Y":"N")
.out_trade_no(String.valueOf(payOrder.getId()))
.total_fee(amount)
.spbill_create_ip(NetUtil.getLocalhostStr())
.notify_url(weChatPayConfig.getNotifyUrl())
.trade_type(tradeType);
}
/**

View File

@@ -48,6 +48,10 @@ public class PayOrder extends MpBaseEntity implements EntityBaseFunction<PayOrde
@DbColumn(comment = "是否是异步支付")
private boolean asyncPay;
/** 是否需要分账 */
@DbColumn(comment = "是否需要分账")
private boolean allocation;
/**
* 异步支付通道
* @see PayChannelEnum#ASYNC_TYPE_CODE

View File

@@ -0,0 +1,18 @@
package cn.bootx.platform.daxpay.service.core.payment.allocation.dao;
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
import cn.bootx.platform.daxpay.service.core.payment.allocation.entity.AllocationGroup;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;
/**
*
* @author xxm
* @since 2024/3/27
*/
@Slf4j
@Repository
@RequiredArgsConstructor
public class AllocationGroupManager extends BaseManager<AllocationGroupMapper,AllocationGroup> {
}

View File

@@ -0,0 +1,15 @@
package cn.bootx.platform.daxpay.service.core.payment.allocation.dao;
import cn.bootx.platform.daxpay.service.core.payment.allocation.entity.AllocationGroup;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
*
* @author xxm
* @since 2024/3/27
*/
@Mapper
public interface AllocationGroupMapper extends BaseMapper<AllocationGroup> {
}

View File

@@ -0,0 +1,18 @@
package cn.bootx.platform.daxpay.service.core.payment.allocation.dao;
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
import cn.bootx.platform.daxpay.service.core.payment.allocation.entity.AllocationReceiverGroup;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;
/**
*
* @author xxm
* @since 2024/3/27
*/
@Slf4j
@Repository
@RequiredArgsConstructor
public class AllocationReceiverGroupManager extends BaseManager<AllocationReceiverGroupMapper, AllocationReceiverGroup> {
}

View File

@@ -0,0 +1,14 @@
package cn.bootx.platform.daxpay.service.core.payment.allocation.dao;
import cn.bootx.platform.daxpay.service.core.payment.allocation.entity.AllocationReceiverGroup;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
*
* @author xxm
* @since 2024/3/27
*/
@Mapper
public interface AllocationReceiverGroupMapper extends BaseMapper<AllocationReceiverGroup> {
}

View File

@@ -0,0 +1,18 @@
package cn.bootx.platform.daxpay.service.core.payment.allocation.dao;
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
import cn.bootx.platform.daxpay.service.core.payment.allocation.entity.AllocationReceiver;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;
/**
*
* @author xxm
* @since 2024/3/27
*/
@Slf4j
@Repository
@RequiredArgsConstructor
public class AllocationReceiverManager extends BaseManager<AllocationReceiverMapper,AllocationReceiver> {
}

View File

@@ -0,0 +1,14 @@
package cn.bootx.platform.daxpay.service.core.payment.allocation.dao;
import cn.bootx.platform.daxpay.service.core.payment.allocation.entity.AllocationReceiver;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
*
* @author xxm
* @since 2024/3/27
*/
@Mapper
public interface AllocationReceiverMapper extends BaseMapper<AllocationReceiver> {
}

View File

@@ -0,0 +1,30 @@
package cn.bootx.platform.daxpay.service.core.payment.allocation.entity;
import cn.bootx.platform.common.mybatisplus.base.MpBaseEntity;
import cn.bootx.table.modify.annotation.DbColumn;
import cn.bootx.table.modify.annotation.DbComment;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 分账组
* @author xxm
* @since 2024/3/27
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
@TableName("pay_allocation_receiver_group")
public class AllocationGroup extends MpBaseEntity {
@DbComment("名称")
private String name;
@DbColumn("通道")
private String channel;
@DbColumn("备注")
private String remark;
}

View File

@@ -0,0 +1,50 @@
package cn.bootx.platform.daxpay.service.core.payment.allocation.entity;
import cn.bootx.platform.common.mybatisplus.base.MpBaseEntity;
import cn.bootx.platform.daxpay.code.AllocationRelationTypeEnum;
import cn.bootx.table.modify.annotation.DbColumn;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 分账接收方
* @author xxm
* @since 2024/3/27
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
public class AllocationReceiver extends MpBaseEntity {
@DbColumn(name = "账号别名")
private String name;
@DbColumn(name = "所属通道")
private String channel;
/**
* 分账接收方类型 个人/商户
*/
@DbColumn(name = "分账接收方类型")
private String receiverType;
@DbColumn(name = "接收方账号")
private String receiverAccount;
/** 接收方姓名 */
@DbColumn(name = "接收方姓名")
private String receiverName;
/**
* 分账关系类型
* @see AllocationRelationTypeEnum
*/
@DbColumn(name = "分账关系类型")
private String relationType;
@DbColumn(name = "关系名称")
private String relationName;
}

View File

@@ -0,0 +1,24 @@
package cn.bootx.platform.daxpay.service.core.payment.allocation.entity;
import cn.bootx.platform.common.mybatisplus.base.MpCreateEntity;
import cn.bootx.table.modify.annotation.DbColumn;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 分账接收组关系
* @author xxm
* @since 2024/3/27
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
public class AllocationReceiverGroup extends MpCreateEntity {
@DbColumn("分账ID")
private Long groupId;
@DbColumn("接收者ID")
private Long receiverId;
}

View File

@@ -0,0 +1,16 @@
package cn.bootx.platform.daxpay.service.core.payment.allocation.service;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* 分账接收方服务类
* @author xxm
* @since 2024/3/27
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class AllocationReceiverService {
}

View File

@@ -93,14 +93,12 @@ public class PayService {
* 执行异步通道支付的逻辑与上面异步支付的逻辑一致
* 4. 同步支付一次支付完成,不允许重复发起支付
* 5. 重复支付时不允许中途将异步支付换为同步支付也不允许更改出支付通道和支付方式之外的支付参数请求时间、IP、签名等可以更改
*
* 6. 如果要进行分账, 请求时就需要将分账标识字段穿true
*/
public PayResult pay(PayParam payParam){
// 异步支付方式检查
PayUtil.validationAsyncPay(payParam);
// 检查支付金额
PayUtil.validationAmount(payParam.getPayChannels());
// 支付参数检查
PayUtil.validation(payParam);
// 校验支付限额
payAssistService.validationLimitAmount(payParam);

View File

@@ -36,6 +36,10 @@ public class PayOrderDto extends BaseDto {
@Schema(description = "是否是组合支付")
private boolean combinationPay;
/** 是否需要分账 */
@Schema(description = "是否需要分账")
private boolean allocation;
/**
* 异步支付通道
* @see PayChannelEnum#ASYNC_TYPE_CODE

View File

@@ -0,0 +1,51 @@
package cn.bootx.platform.daxpay.service.sdk.wechat;
import com.ijpay.wxpay.model.MicroPayModel;
import lombok.*;
import lombok.experimental.Accessors;
/**
* 付款码支付, 增加分账字段
* @author xxm
* @since 2024/3/27
*/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class BarPayModel extends MicroPayModel {
/**
* 是否押金支付
*/
private String deposit;
private String appid;
private String sub_appid;
private String mch_id;
private String sub_mch_id;
private String device_info;
private String nonce_str;
private String sign;
private String sign_type;
private String body;
private String detail;
private String attach;
private String out_trade_no;
private String total_fee;
private String fee_type;
private String spbill_create_ip;
private String goods_tag;
private String limit_pay;
private String time_start;
private String time_expire;
private String auth_code;
private String receipt;
private String scene_info;
private String openid;
/**
* 人脸凭证,用于人脸支付
*/
private String face_code;
private String profit_sharing;
}