package shop.alien.store.strategy.payment.impl;


import com.google.gson.annotations.SerializedName;
import com.wechat.pay.java.service.refund.model.QueryByOutRefundNoRequest;
import com.wechat.pay.java.service.refund.model.Refund;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;
import shop.alien.entity.result.R;
import shop.alien.entity.store.RefundRecord;
import shop.alien.store.service.RefundRecordService;
import shop.alien.store.strategy.payment.PaymentStrategy;
import shop.alien.store.util.WXPayUtility;
import shop.alien.util.common.UniqueRandomNumGenerator;
import shop.alien.util.common.constant.PaymentEnum;
import shop.alien.util.system.OSUtil;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.util.*;


/**
 * 微信支付小程序策略
 *
 * @author lyx
 * @date 2025/11/20
 */

@Slf4j
@Component
@RequiredArgsConstructor
@RefreshScope
public class WeChatPaymentMininProgramStrategyImpl implements PaymentStrategy {
    /**
     * 微信支付api主机地址
     */
    @Value("${payment.wechatPay.host}")
    private String wechatPayApiHost;
    /**
     * 微信支付商户id
     */
    @Value("${payment.wechatPay.business.mchId}")
    private String mchId;
    // TODO:小程序未注册-> 把下面的所有默认的去掉然后从配置文件中读取
    /**
     * 微信支付小程序应用id
     */
    @Value("${payment.wechatPay.business.mininprogram.appId:没有}")
    private String appId;
    /**
     * 微信支付商户证书序列号
     */
    @Value("${payment.wechatPay.business.merchantSerialNumber}")
    private String certificateSerialNo;
    /**
     * 微信支付公钥id
     */
    @Value("${payment.wechatPay.business.wechatPayPublicKeyId}")
    private String wechatPayPublicKeyId;
    /**
     * 微信支付商户私钥路径
     */
    @Value("${payment.wechatPay.business.win.privateKeyPath}")
    private String privateWinKeyPath;

    /**
     * 微信支付商户私钥路径（Linux环境）
     */
    @Value("${payment.wechatPay.business.linux.privateKeyPath}")
    private String privateLinuxKeyPath;

    /**
     * 微信支付公钥路径
     */
    @Value("${payment.wechatPay.business.win.wechatPayPublicKeyFilePath}")
    private String wechatWinPayPublicKeyFilePath;

    /**
     * 微信支付公钥路径（Linux环境）
     */
    @Value("${payment.wechatPay.business.linux.wechatPayPublicKeyFilePath}")
    private String wechatLinuxPayPublicKeyFilePath;
    /**
     * 微信支付预支付路径
     */
    @Value("${payment.wechatPay.miniProgram.prePayPath:/v3/pay/transactions/jsapi}")
    private String prePayPath;
    /**
     * 微信支付预支付通知路径
     */
    @Value("${payment.wechatPay.miniProgram.prePayNotifyUrl:https://www.weixin.qq.com/wxpay/pay.php}")
    private String prePayNotifyUrl;
    /**
     * 微信支付退款通知路径
     */
    @Value("${payment.wechatPay.business.miniProgram.refundNotifyUrl:https://www.weixin.qq.com/wxpay/pay.php}")
    private String refundNotifyUrl;
    /**
     * 微信支付查询退款状态路径
     */
    @Value("${payment.wechatPay.searchRefundStatusByOutRefundNoPath:/v3/refund/domestic/refunds/{out_refund_no}}")
    private String searchRefundStatusByOutRefundNoPath;

    private static String POSTMETHOD = "POST";
    private static String GETMETHOD = "GET";

    private PrivateKey privateKey;
    private PublicKey wechatPayPublicKey;

    private final WeChatPaymentStrategyImpl weChatPaymentStrategy;
    private final RefundRecordService refundRecordService;

    @PostConstruct
    public void setWeChatPaymentConfig() {
        String privateKeyPath;
        String wechatPayPublicKeyFilePath;
        if ("windows".equals(OSUtil.getOsName())) {
            privateKeyPath = privateWinKeyPath;
            wechatPayPublicKeyFilePath = wechatWinPayPublicKeyFilePath;
        } else {
            privateKeyPath = privateLinuxKeyPath;
            wechatPayPublicKeyFilePath = wechatLinuxPayPublicKeyFilePath;
        }
        this.privateKey = WXPayUtility.loadPrivateKeyFromPath(privateKeyPath);
        this.wechatPayPublicKey = WXPayUtility.loadPublicKeyFromPath(wechatPayPublicKeyFilePath);
    }

    @Override
    public R createPrePayOrder(String price, String subject) throws Exception {


        DirectAPIv3JsapiPrepayRequest request = new DirectAPIv3JsapiPrepayRequest();
        request.appid = appId;
        request.mchid = mchId;
        request.description = subject;
        request.outTradeNo = UniqueRandomNumGenerator.generateUniqueCode(19);
//        request.timeExpire = "2018-06-08T10:34:56+08:00";
//        request.attach = "自定义数据说明";
        request.notifyUrl = prePayNotifyUrl;
        request.goodsTag = "WXG";
        request.supportFapiao = false;
        request.amount = new CommonAmountInfo();
        request.amount.total = 100L;
        request.amount.currency = "CNY";
        request.payer = new JsapiReqPayerInfo();
        request.payer.openid = "oUpF8uMuAJO_M2pxb1Q9zNjWeS6o";
        request.detail = new CouponInfo();
        request.detail.costPrice = 608800L;
        request.detail.invoiceId = "微信123";
        request.detail.goodsDetail = new ArrayList<>();
        {
            GoodsDetail goodsDetailItem = new GoodsDetail();
            goodsDetailItem.merchantGoodsId = "1246464644";
            goodsDetailItem.wechatpayGoodsId = "1001";
            goodsDetailItem.goodsName = "iPhoneX 256G";
            goodsDetailItem.quantity = 1L;
            goodsDetailItem.unitPrice = 528800L;
            request.detail.goodsDetail.add(goodsDetailItem);
        };
        request.sceneInfo = new CommonSceneInfo();
        request.sceneInfo.payerClientIp = "14.23.150.211";
        request.sceneInfo.deviceId = "013467007045764";
        request.sceneInfo.storeInfo = new StoreInfo();
        request.sceneInfo.storeInfo.id = "0001";
        request.sceneInfo.storeInfo.name = "腾讯大厦分店";
        request.sceneInfo.storeInfo.areaCode = "440305";
        request.sceneInfo.storeInfo.address = "广东省深圳市南山区科技中一道10000号";
        request.settleInfo = new SettleInfo();
        request.settleInfo.profitSharing = false;
        try {
            DirectAPIv3JsapiPrepayResponse response = doCreatePrePayOrder(request);
            // TODO: 请求成功，继续业务逻辑
            log.info("微信预支付订单创建成功，预支付ID：{}", response.prepayId);
            Map<String,String> result = new HashMap<>();
            result.put("prepayId", response.prepayId);
            result.put("appId", appId);
            result.put("mchId", mchId);
            result.put("orderNo", request.outTradeNo);
            long timestamp = System.currentTimeMillis() / 1000; // 时间戳
            String nonce = WXPayUtility.createNonce(32); // 随机字符串
            String prepayId = response.prepayId;
            String message = String.format("%s\n%s\n%s\n%s\n", appId, timestamp, nonce, prepayId);
//            String sign = WXPayUtility.sign(message, sha256withRSA, privateKey);

            Signature sign = Signature.getInstance("SHA256withRSA");
            sign.initSign(privateKey);
            sign.update(message.getBytes(StandardCharsets.UTF_8));
            result.put("signType","RSA");
            result.put("sign", Base64.getEncoder().encodeToString(sign.sign()));
            result.put("timestamp", String.valueOf(timestamp));
            result.put("nonce", nonce);
            return R.data(result);
        } catch (WXPayUtility.ApiException e) {
            log.error("微信支付预支付失败，状态码：{}，错误信息：{}", e.getErrorCode(), e.getMessage());
            return R.fail(e.getMessage());
        }
    }

    @Override
    public R createPreAliPayOrder(String orderId, String amount, String subject, String smid) throws Exception {
        return null;
    }

    @Override
    public R handleNotify(String notifyData) throws Exception {
        return null;
    }

    @Override
    public R searchOrderByOutTradeNoPath(String transactionId) throws Exception {
        return weChatPaymentStrategy.searchOrderByOutTradeNoPath(transactionId);
    }

    @Override
    public String handleRefund(Map<String, String> params) throws Exception {

        WeChatPaymentStrategyImpl.CreateRequest request = new WeChatPaymentStrategyImpl.CreateRequest();
        // 微信支付订单号和商户订单号必须二选一，不能同时为空，查询的时候使用的是商户订单号
        //request.transactionId = "1217752501201407033233368018";
        request.outTradeNo = params.get("outTradeNo");
        // 退款订单号
        request.outRefundNo = UniqueRandomNumGenerator.generateUniqueCode(19);
        // 退款原因
        request.reason = params.get("reason");
        // 退款回调通知地址
        request.notifyUrl = refundNotifyUrl;
        // 退款资金来源选填
        //request.fundsAccount = ReqFundsAccount.AVAILABLE;
        // 金额信息
        request.amount = new WeChatPaymentStrategyImpl.AmountReq();
        request.amount.refund = new BigDecimal(params.get("refundAmount")).longValue();
        // 退款出资账户及金额 目前不需要，需要的时候再看
        /*
        request.amount.from = new ArrayList<>();
        {
            FundsFromItem fromItem = new FundsFromItem();
            fromItem.account = Account.AVAILABLE;
            fromItem.amount = 444L;
            request.amount.from.add(fromItem);
        };*/
        // 订单总金额
        request.amount.total = new BigDecimal(params.get("totalAmount")).longValue();
        // 退款币种 目前默认人民币 CNY
        request.amount.currency = "CNY";
        // 退款商品信息 目前不需要，需要的时候再看
        /*
        request.goodsDetail = new ArrayList<>();
        {
            GoodsDetail goodsDetailItem = new GoodsDetail();
            goodsDetailItem.merchantGoodsId = "1217752501201407033233368018";
            goodsDetailItem.wechatpayGoodsId = "1001";
            goodsDetailItem.goodsName = "iPhone6s 16G";
            goodsDetailItem.unitPrice = 528800L;
            goodsDetailItem.refundAmount = 528800L;
            goodsDetailItem.refundQuantity = 1L;
            request.goodsDetail.add(goodsDetailItem);
        };*/
        // 记录退款请求信息
        log.info("开始处理微信支付退款，商户订单号：{}，商户退款单号：{}，退款金额：{}分，订单总金额：{}分，退款原因：{}",
                request.outTradeNo, request.outRefundNo, request.amount.refund, request.amount.total, request.reason);
        String refundResult = "";
        try {
            WeChatPaymentStrategyImpl.Refund response = weChatPaymentStrategy.refundRun(request);
            // 退款状态
            String status = response.status != null ? response.status.name() : "UNKNOWN";
            if ("SUCCESS".equals(status) || "PROCESSING".equals(status)) {
                // refund_id 申请退款受理成功时，该笔退款单在微信支付侧生成的唯一标识。
                String refundId = response.refundId;
                // 商户申请退款时传的商户系统内部退款单号。
                String outRefundNo = response.outRefundNo != null ? response.outRefundNo : request.outRefundNo;
                // 微信支付订单号
                String transactionId = response.transactionId;

                // 退款金额信息
                String refundAmount = response.amount != null && response.amount.refund != null
                        ? String.valueOf(response.amount.refund) : String.valueOf(request.amount.refund);
                String totalAmount = response.amount != null && response.amount.total != null
                        ? String.valueOf(response.amount.total) : String.valueOf(request.amount.total);
                // 退款成功时间
                String successTime = response.successTime;
                // 退款创建时间
                String createTime = response.createTime;
                // 退款渠道
                String channel = response.channel != null ? response.channel.name() : "UNKNOWN";

                // 记录退款成功详细信息
                log.info("微信支付退款成功 - 商户订单号：{}，微信支付订单号：{}，商户退款单号：{}，微信退款单号：{}，" +
                                "退款状态：{}，退款金额：{}分，订单总金额：{}分，退款渠道：{}，创建时间：{}，成功时间：{}",
                        request.outTradeNo, transactionId, outRefundNo, refundId, status, refundAmount,
                        totalAmount, channel, createTime, successTime != null ? successTime : "未完成");

                // 保存到通用退款记录表
                try {
                    RefundRecord refundRecord = weChatPaymentStrategy.buildRefundRecordFromWeChatResponse(response, request, params);
                    refundRecord.setPayType(PaymentEnum.WECHAT_PAY_MININ_PROGRAM.getType());
                    if (refundRecord != null) {
                        // 检查是否已存在，避免重复插入
                        long count = refundRecordService.lambdaQuery()
                                .eq(RefundRecord::getOutRefundNo, refundRecord.getOutRefundNo())
                                .count();
                        if (count == 0) {
                            refundRecordService.save(refundRecord);
                            log.info("微信支付退款记录已保存到RefundRecord表，商户退款单号：{}", refundRecord.getOutRefundNo());
                        } else {
                            log.info("微信支付退款记录已存在，跳过插入，商户退款单号：{}", refundRecord.getOutRefundNo());
                        }
                    }
                } catch (Exception e) {
                    log.error("保存微信支付退款记录到RefundRecord表失败", e);
                    // 不抛出异常，避免影响原有逻辑
                }

                refundResult = "调用成功";
                return refundResult;
            } else {
                log.error("微信支付退款失败 - 商户订单号：{}，商户退款单号：{}，退款金额：{}分，订单总金额：{}分，" +
                                "退款状态：{}",
                        request.outTradeNo, request.outRefundNo, request.amount.refund,
                        request.amount.total, status);

                // 保存失败记录到通用退款记录表
                try {
                    RefundRecord refundRecord = weChatPaymentStrategy.buildRefundRecordFromWeChatError(response, request, params, status);
                    refundRecord.setPayType(PaymentEnum.WECHAT_PAY_MININ_PROGRAM.getType());
                    if (refundRecord != null) {
                        // 检查是否已存在，避免重复插入
                        long count = refundRecordService.lambdaQuery()
                                .eq(RefundRecord::getOutRefundNo, refundRecord.getOutRefundNo())
                                .count();
                        if (count == 0) {
                            refundRecordService.save(refundRecord);
                            log.info("微信支付退款失败记录已保存到RefundRecord表，商户退款单号：{}", refundRecord.getOutRefundNo());
                        } else {
                            log.info("微信支付退款失败记录已存在，跳过插入，商户退款单号：{}", refundRecord.getOutRefundNo());
                        }
                    }
                } catch (Exception e) {
                    log.error("保存微信支付退款失败记录到RefundRecord表失败", e);
                }

                return "退款失败";
            }
        }
        catch (Exception e) {
            // 记录其他异常
            log.error("微信支付退款异常 - 商户订单号：{}，商户退款单号：{}，退款金额：{}分，订单总金额：{}分，" +
                            "退款原因：{}，异常信息：{}",
                    request.outTradeNo, request.outRefundNo, request.amount.refund,
                    request.amount.total, request.reason, e.getMessage(), e);

            // 保存异常记录到通用退款记录表
            try {
                RefundRecord refundRecord = weChatPaymentStrategy.buildRefundRecordFromWeChatException(request, params, e);
                refundRecord.setPayType(PaymentEnum.WECHAT_PAY_MININ_PROGRAM.getType());
                if (refundRecord != null) {
                    // 检查是否已存在，避免重复插入
                    long count = refundRecordService.lambdaQuery()
                            .eq(RefundRecord::getOutRefundNo, refundRecord.getOutRefundNo())
                            .count();
                    if (count == 0) {
                        refundRecordService.save(refundRecord);
                        log.info("微信支付退款异常记录已保存到RefundRecord表，商户退款单号：{}", refundRecord.getOutRefundNo());
                    } else {
                        log.info("微信支付退款异常记录已存在，跳过插入，商户退款单号：{}", refundRecord.getOutRefundNo());
                    }
                }
            } catch (Exception ex) {
                log.error("保存微信支付退款异常记录到RefundRecord表失败", ex);
            }

            refundResult = "退款处理异常：" + e.getMessage();
            return refundResult;
        }
    }

    @Override
    public R searchRefundRecordByOutRefundNo(String outRefundNo) throws Exception {
        // 1. 初始化日志（推荐使用SLF4J，替代System.out.println）
        Logger logger = LoggerFactory.getLogger(this.getClass());

        // 2. 参数校验（前置防御，避免无效请求）
        if (outRefundNo == null || outRefundNo.trim().isEmpty()) {
            logger.error("微信退款查询失败：外部退款单号为空");
            return R.fail("外部退款单号不能为空");
        }

        QueryByOutRefundNoRequest request = new QueryByOutRefundNoRequest();
        request.setOutRefundNo(outRefundNo);

        try {
            Refund response = doSearchRefundRecordByOutRefundNo(request);

            // 3. 空值校验（避免response为空导致空指针）
            if (response == null) {
                logger.error("微信退款查询失败：外部退款单号{}，返回结果为空", outRefundNo);
                return R.fail("微信支付查询退款记录失败：返回结果为空");
            }

            logger.info("微信退款查询结果：外部退款单号{}，退款状态{}",
                    outRefundNo, response.getStatus());

            // 4. 细化退款状态判断（覆盖微信支付核心退款状态）
            String refundStatus = String.valueOf(response.getStatus());
            switch (refundStatus) {
                case "SUCCESS":
                    // 退款成功：执行成功业务逻辑（如更新订单状态、通知用户等）
                    logger.info("退款成功：外部退款单号{}", outRefundNo);
                    // TODO: 补充你的成功业务逻辑（例：updateOrderRefundStatus(outRefundNo, "SUCCESS");）
                    return R.data(response);

                case "REFUNDCLOSE":
                    // 退款关闭：执行关闭逻辑（如记录关闭原因、人工介入等）
                    logger.warn("退款关闭：外部退款单号{}，原因{}", outRefundNo);
                    return R.fail("微信支付退款已关闭");

                case "PROCESSING":
                    // 退款处理中：执行等待逻辑（如提示用户等待、定时任务重试等）
                    logger.info("退款处理中：外部退款单号{}", outRefundNo);
                    return R.fail("微信支付退款处理中，请稍后再查");

                case "CHANGE":
                    // 退款异常：执行异常处理（如记录异常、人工核查等）
                    logger.error("退款异常：外部退款单号{}", outRefundNo);
                    return R.fail("微信支付退款异常");

                default:
                    // 未知状态：兜底处理
                    logger.error("退款状态未知：外部退款单号{}，状态码{}", outRefundNo, refundStatus);
                    return R.fail("微信支付查询退款记录失败：未知状态码" + refundStatus);
            }

        } catch (WXPayUtility.ApiException e) {
            // 5. 异常处理：细化异常日志，便于排查
            logger.error("微信退款查询API异常：外部退款单号{}，错误码{}，错误信息{}",
                    outRefundNo, e.getErrorCode(), e.getMessage(), e);
            return R.fail("微信支付查询退款记录失败：" + e.getMessage() + "（错误码：" + e.getErrorCode() + "）");
        } catch (Exception e) {
            // 6. 兜底异常：捕获非API异常（如空指针、网络异常等）
            logger.error("微信退款查询系统异常：外部退款单号{}", outRefundNo, e);
            return R.fail("微信支付查询退款记录失败：系统异常，请联系管理员");
        }
    }

    @Override
    public String getType() {
        return PaymentEnum.WECHAT_PAY_MININ_PROGRAM.getType();
    }

    public Refund doSearchRefundRecordByOutRefundNo(QueryByOutRefundNoRequest request) {
        String uri = searchRefundStatusByOutRefundNoPath;
        uri = uri.replace("{out_refund_no}", WXPayUtility.urlEncode(request.getOutRefundNo()));
        Request.Builder reqBuilder = new Request.Builder().url(wechatPayApiHost + uri);
        reqBuilder.addHeader("Accept", "application/json");
        reqBuilder.addHeader("Wechatpay-Serial", wechatPayPublicKeyId);
        reqBuilder.addHeader("Authorization", WXPayUtility.buildAuthorization(mchId, certificateSerialNo, privateKey, GETMETHOD, uri, null));
        reqBuilder.method(GETMETHOD, null);
        Request httpRequest = reqBuilder.build();

        // 发送HTTP请求
        OkHttpClient client = new OkHttpClient.Builder().build();
        try (Response httpResponse = client.newCall(httpRequest).execute()) {
            String respBody = WXPayUtility.extractBody(httpResponse);
            if (httpResponse.code() >= 200 && httpResponse.code() < 300) {
                // 2XX 成功，验证应答签名
                WXPayUtility.validateResponse(this.wechatPayPublicKeyId, this.wechatPayPublicKey,
                        httpResponse.headers(), respBody);

                // 从HTTP应答报文构建返回数据
                return WXPayUtility.fromJson(respBody, Refund.class);
            } else {
                throw new WXPayUtility.ApiException(httpResponse.code(), respBody, httpResponse.headers());
            }
        } catch (IOException e) {
            throw new UncheckedIOException("Sending request to " + uri + " failed.", e);
        }
    }

    public DirectAPIv3JsapiPrepayResponse doCreatePrePayOrder(DirectAPIv3JsapiPrepayRequest request) {
        String uri = prePayPath;
        String reqBody = WXPayUtility.toJson(request);

        Request.Builder reqBuilder = new Request.Builder().url(wechatPayApiHost + uri);
        reqBuilder.addHeader("Accept", "application/json");
        reqBuilder.addHeader("Wechatpay-Serial", wechatPayPublicKeyId);
        reqBuilder.addHeader("Authorization", WXPayUtility.buildAuthorization(mchId, certificateSerialNo,privateKey, POSTMETHOD, uri, reqBody));
        reqBuilder.addHeader("Content-Type", "application/json");
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), reqBody);
        reqBuilder.method(POSTMETHOD, requestBody);
        Request httpRequest = reqBuilder.build();

        // 发送HTTP请求
        OkHttpClient client = new OkHttpClient.Builder().build();
        try (Response httpResponse = client.newCall(httpRequest).execute()) {
            String respBody = WXPayUtility.extractBody(httpResponse);
            if (httpResponse.code() >= 200 && httpResponse.code() < 300) {
                // 2XX 成功，验证应答签名
                WXPayUtility.validateResponse(this.wechatPayPublicKeyId, this.wechatPayPublicKey,
                        httpResponse.headers(), respBody);

                // 从HTTP应答报文构建返回数据
                return WXPayUtility.fromJson(respBody, DirectAPIv3JsapiPrepayResponse.class);
            } else {
                throw new WXPayUtility.ApiException(httpResponse.code(), respBody, httpResponse.headers());
            }
        } catch (IOException e) {
            throw new UncheckedIOException("Sending request to " + uri + " failed.", e);
        }
    }

    public static class DirectAPIv3JsapiPrepayRequest {
        @SerializedName("appid")
        public String appid;

        @SerializedName("mchid")
        public String mchid;

        @SerializedName("description")
        public String description;

        @SerializedName("out_trade_no")
        public String outTradeNo;

        @SerializedName("time_expire")
        public String timeExpire;

        @SerializedName("attach")
        public String attach;

        @SerializedName("notify_url")
        public String notifyUrl;

        @SerializedName("goods_tag")
        public String goodsTag;

        @SerializedName("support_fapiao")
        public Boolean supportFapiao;

        @SerializedName("amount")
        public CommonAmountInfo amount;

        @SerializedName("payer")
        public JsapiReqPayerInfo payer;

        @SerializedName("detail")
        public CouponInfo detail;

        @SerializedName("scene_info")
        public CommonSceneInfo sceneInfo;

        @SerializedName("settle_info")
        public SettleInfo settleInfo;
    }

    public static class DirectAPIv3JsapiPrepayResponse {
        @SerializedName("prepay_id")
        public String prepayId;
    }

    public static class CommonAmountInfo {
        @SerializedName("total")
        public Long total;

        @SerializedName("currency")
        public String currency;
    }

    public static class JsapiReqPayerInfo {
        @SerializedName("openid")
        public String openid;
    }

    public static class CouponInfo {
        @SerializedName("cost_price")
        public Long costPrice;

        @SerializedName("invoice_id")
        public String invoiceId;

        @SerializedName("goods_detail")
        public List<GoodsDetail> goodsDetail;
    }

    public static class CommonSceneInfo {
        @SerializedName("payer_client_ip")
        public String payerClientIp;

        @SerializedName("device_id")
        public String deviceId;

        @SerializedName("store_info")
        public StoreInfo storeInfo;
    }

    public static class SettleInfo {
        @SerializedName("profit_sharing")
        public Boolean profitSharing;
    }

    public static class GoodsDetail {
        @SerializedName("merchant_goods_id")
        public String merchantGoodsId;

        @SerializedName("wechatpay_goods_id")
        public String wechatpayGoodsId;

        @SerializedName("goods_name")
        public String goodsName;

        @SerializedName("quantity")
        public Long quantity;

        @SerializedName("unit_price")
        public Long unitPrice;
    }

    public static class StoreInfo {
        @SerializedName("id")
        public String id;

        @SerializedName("name")
        public String name;

        @SerializedName("area_code")
        public String areaCode;

        @SerializedName("address")
        public String address;
    }

}

