Springboot——对接支付宝实现扫码支付

前言

最近项目中需要对接支付模块,需要考虑到微信支付与支付宝支付的实现。

由于微信支付的还在审核中,先预研demo做一个支付宝支付码获取的实现。

官方文档以及说明

本次开发环境中编写demo实现,采用的是支付宝的沙箱方式,后续上线会重新申请正式的appid等信息。

支付宝开发平台链接:https://open.alipay.com/

1、申请沙箱

进入支付宝的开发平台,用支付宝登录后,在控制台面板中找到沙箱,并创建第一个沙箱。

https://open.alipay.com/develop/manage

在这里插入图片描述

2、进入沙箱获取对应的关键信息

在这里插入图片描述
对于像授权回调地址应用网关地址这些暂时不设置。

3、拿到系统生成的公钥和密钥

在这里插入图片描述
在这里插入图片描述
这里会有应用公钥支付宝公钥应用私钥。但这里通过个人实践,只需要支付宝公钥应用私钥

应用公钥在某些特定的场景中并不会生效还会出现各种奇怪的报错。

注意事项

沙箱并不是所有的操作都能够在其中进行开发操作,详情参考官方文档说明。

https://opendocs.alipay.com/common/097jyi?pathHash=9fcbe0d0&highlight_field=%E6%B2%99%E7%AE%B1%E7%8E%AF%E5%A2%83

在这里插入图片描述

创建springboot项目

1、引入依赖

选用的是springboot 2.x 的版本,并且引用的依赖在官方文档中有版本说明。

<dependency>
    <groupId>com.alipay.sdk</groupId>
    <artifactId>alipay-sdk-java</artifactId>
    <version>4.34.47.ALL</version>
</dependency>

<dependency>
    <groupId>com.alipay.sdk</groupId>
    <artifactId>alipay-easysdk</artifactId>
    <version>2.0.0</version>
</dependency>

参考官方文档依赖版本规定:

https://opendocs.alipay.com/common/02n6z6?pathHash=f5e2a056

其中,针对通用版的版本要求,官方文档中有做说明:

https://opendocs.alipay.com/common/02kkv2?pathHash=358ff034

在这里插入图片描述

2、配置连接参数

src/main/resources中新建一个application.yml文件,如果是nacos项目,可以在对应的配置中心中新增配置项。

# 支付宝支付
alipay:
    # 应用ID,标识你的应用
    appId: 
    # 应用私钥,用于签名请求
    appPrivateKey:
    # 应用公钥,用于验证支付宝的响应
    #alipayPublicKey: 沙箱页面中的应用公钥
    # 支付宝公钥(推荐使用这个)
    alipayPublicKey: 支付宝公钥
    # 支付通知的回调地址,支付宝会在支付完成后通知这个地址
    notifyUrl: 支付成功后的回调地址,必须要求公网能够访问
    # 页面跳转地址,支付完成后跳转到此URL
    returnUrl: 场景一中登录成功后的重定向页面
    # 签名类型,通常为RSA2
    signType: RSA2
    # 字符编码,通常为utf-8
    charset: utf-8
    # 支付宝网关地址,用于发送请求
    gatewayUrl: https://openapi-sandbox.dl.alipaydev.com/gateway.do

3、创建配置类,用于接收这些参数

package cn.alipay.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * 支付宝 支付参数配置类
 */
@Data
@Component
@ConfigurationProperties(prefix = "alipay")
public class AlipayProperties {

    /**
     * APPID
     */
    private String appId;

    /**
     * 应用私钥,就是工具生成的应用私钥
     */
    public String appPrivateKey;

    /**
     * 支付宝公钥,对应APPID下的支付宝公钥
     */
    public String alipayPublicKey;

    /**
     * 支付宝会悄悄的给我们发送一个请求,告诉我们支付成功的信息
     */
    public String notifyUrl;

    /**
     * 同步通知,支付成功,一般跳转到成功页
     */
    public String returnUrl;

    /**
     * 签名方式
     */
    private String signType;

    /**
     * 字符编码格式
     */
    private String charset;

    /**
     * 支付宝网关;https://openapi-sandbox.dl.alipaydev.com/gateway.do
     */
    public String gatewayUrl;

    /**
     * 订单超时时间
     */
    private String timeout = "5m";
}

新建配置类,获取对应的配置参数,并构建连接对象

package cn.alipay.config;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradePagePayModel;
import com.alipay.api.domain.AlipayTradePayModel;
import com.alipay.api.domain.AlipayTradePrecreateModel;
import com.alipay.api.domain.BusinessParams;
import com.alipay.api.domain.ExtendParams;
import com.alipay.api.domain.GoodsDetail;
import com.alipay.api.domain.SettleDetailInfo;
import com.alipay.api.domain.SettleInfo;
import com.alipay.api.internal.util.WebUtils;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradePayRequest;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.response.AlipayTradePagePayResponse;
import com.alipay.api.response.AlipayTradePayResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;

/**
 * 支付宝支付 模板
 */
@Slf4j
@Data
@Component
public class AliPayTemplate {
    
    @Autowired
    private AlipayProperties alipayProperties;

    private AlipayClient alipayClient;

    @PostConstruct
    public void init() {
        log.info("APPID:" + alipayProperties.getAppId());
        log.info("应用私钥:" + alipayProperties.getAppPrivateKey());
        log.info("支付宝公钥:" + alipayProperties.getAlipayPublicKey());
        log.info("支付宝会悄悄的给我们发送一个请求,告诉我们支付成功的信息:" + alipayProperties.getNotifyUrl());
        log.info("同步通知,支付成功,一般跳转到成功页:" + alipayProperties.getReturnUrl());
        log.info("签名方式:" + alipayProperties.getSignType());
        log.info("字符编码格式:" + alipayProperties.getCharset());
        log.info("订单超时时间:" + alipayProperties.getTimeout());
        log.info("支付宝网关:" + alipayProperties.getGatewayUrl());
        // 1. 根据支付宝的配置生成一个支付客户端
        alipayClient = new DefaultAlipayClient(
                alipayProperties.getGatewayUrl(),
                alipayProperties.getAppId(),
                alipayProperties.getAppPrivateKey(),
                "json",
                alipayProperties.getCharset(),
                alipayProperties.getAlipayPublicKey(),
                alipayProperties.getSignType()
        );
    }
}

4、中间类的定义(订单类)

创建一个订单类,主要用于一些基本信息的传参处理。

package cn.alipay.config;

import lombok.Data;

import java.io.Serializable;
import java.util.Date;

/**
 * 订单表
 */
@Data
public class Order implements Serializable {
    /**
     * 订单Id
     */
    private Long id;
 
    /**
     * 用户Id
     */
    private Long userId;
 
    /**
     * 接口Id
     */
    private Long interfaceInfoId;
 
    /**
     * 支付金额
     */
    private Double money;
 
    /**
     * 支付方式
     */
    private String paymentMethod;
 
    /**
     * 0 - 未支付 1 - 已支付
     */
    private Integer status;
 
    /**
     * 创建时间
     */
    private Date createTime;
 
    /**
     * 更新时间
     */
    private Date updateTime;
 
    /**
     * 是否删除
     */
    private Integer isDelete;

    private static final long serialVersionUID = 1L;
}

5、编写测试接口

场景一、pc端请求后端后,生成支付宝的特制页面(AlipayTradePagePayRequest)

在支付宝的PC端案例文档中,有一个注意事项。

https://opendocs.alipay.com/open/00dn7o?pathHash=c1e36251

在这里插入图片描述

像这种传递订单信息至后台,后台调用支付宝的对应接口后,返回前端页面样式或者地址,前端再进行渲染实现。可以参照以下的方式。

定义接口

package cn.alipay.controller;

import cn.alipay.config.AliPayTemplate;
import cn.alipay.config.Order;
import com.alipay.api.AlipayApiException;
import com.alipay.easysdk.factory.Factory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.MimeTypeUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * 阿里支付宝支付与回调接口
 */
@Slf4j
@RestController
@RequestMapping("/alipay")
public class AliPayController {

    @Autowired
    private AliPayTemplate aliPayTemplate;

    /**
     * 获取支付宝
     * post 请求 生成 frame 页面
     * get 请求生成 页面url
     * @param id
     * @return
     * @throws AlipayApiException
     */
    @GetMapping(value = "/pay", produces = MimeTypeUtils.TEXT_HTML_VALUE)
    @ResponseBody
    public String pay(@RequestParam long id) throws AlipayApiException {
        // 创建订单对象并设置属性
        Order order = createOrder(id);

        // 调用支付宝支付模板进行支付
        return aliPayTemplate.pay(order);
    }

    /**
     * 伪造订单数据
     * @param id
     * @return
     */
    private Order createOrder(long id) {
        Order order = new Order();
        order.setId(id);  
        order.setUserId(1111111L);  
        order.setInterfaceInfoId(294389472934L); 
        order.setMoney(1000.0);  
        order.setPaymentMethod("支付宝"); 
        return order;
    }
}

定义请求逻辑代码

package cn.alipay.config;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradePagePayModel;
import com.alipay.api.domain.AlipayTradePayModel;
import com.alipay.api.domain.AlipayTradePrecreateModel;
import com.alipay.api.domain.BusinessParams;
import com.alipay.api.domain.ExtendParams;
import com.alipay.api.domain.GoodsDetail;
import com.alipay.api.domain.SettleDetailInfo;
import com.alipay.api.domain.SettleInfo;
import com.alipay.api.internal.util.WebUtils;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradePayRequest;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.response.AlipayTradePagePayResponse;
import com.alipay.api.response.AlipayTradePayResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;

/**
 * 支付宝支付 模板
 */
@Slf4j
@Data
@Component
public class AliPayTemplate {
    
    @Autowired
    private AlipayProperties alipayProperties;

    private AlipayClient alipayClient;

    @PostConstruct
    public void init() {
        log.info("APPID:" + alipayProperties.getAppId());
        log.info("应用私钥:" + alipayProperties.getAppPrivateKey());
        log.info("支付宝公钥:" + alipayProperties.getAlipayPublicKey());
        log.info("支付宝会悄悄的给我们发送一个请求,告诉我们支付成功的信息:" + alipayProperties.getNotifyUrl());
        log.info("同步通知,支付成功,一般跳转到成功页:" + alipayProperties.getReturnUrl());
        log.info("签名方式:" + alipayProperties.getSignType());
        log.info("字符编码格式:" + alipayProperties.getCharset());
        log.info("订单超时时间:" + alipayProperties.getTimeout());
        log.info("支付宝网关:" + alipayProperties.getGatewayUrl());
        // 1. 根据支付宝的配置生成一个支付客户端
        alipayClient = new DefaultAlipayClient(
                alipayProperties.getGatewayUrl(),
                alipayProperties.getAppId(),
                alipayProperties.getAppPrivateKey(),
                "json",
                alipayProperties.getCharset(),
                alipayProperties.getAlipayPublicKey(),
                alipayProperties.getSignType()
        );
    }

    /**
     * 调用支付接口
     * @param order
     * @return
     * @throws AlipayApiException
     */
    public String pay(Order order) throws AlipayApiException {
        //2、创建一个支付请求,并设置请求参数
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        alipayRequest.setReturnUrl(alipayProperties.getReturnUrl());
        alipayRequest.setNotifyUrl(alipayProperties.getNotifyUrl());

        Long id = order.getId();
        Long interfaceInfoId = order.getInterfaceInfoId();
        Double money = order.getMoney();
        String paymentMethod = order.getPaymentMethod();

        // 设置业务内容,包含必要的支付参数
        AlipayTradePagePayModel pagePayModel = new AlipayTradePagePayModel();
        pagePayModel.setOutTradeNo(String.valueOf(id));
        pagePayModel.setTotalAmount(String.valueOf(money));
        pagePayModel.setSubject(String.valueOf(interfaceInfoId));
        pagePayModel.setBody(paymentMethod);
        pagePayModel.setTimeoutExpress(alipayProperties.getTimeout());
        // 电脑支付场景下仅支持FAST_INSTANT_TRADE_PAY
        pagePayModel.setProductCode("FAST_INSTANT_TRADE_PAY");
        alipayRequest.setBizModel(pagePayModel);
		
		// post 请求返回 frame 前端样式
        AlipayTradePagePayResponse response = alipayClient.pageExecute(alipayRequest, "POST");
        // get 请求返回一个页面地址url
        AlipayTradePagePayResponse response2 = alipayClient.pageExecute(alipayRequest, "GET");
        String result = response.getBody();
        //返回支付宝响应的结果
        return result;
    }
}

启动服务,请求后的效果如下:

localhost:8080/alipay/pay?id=123456

post 请求生成的样式如下所示:

<form  name="punchout_form" method="post" action="会有对应的信息">
    <input  type="hidden" name="biz_content" value="{&quot;body&quot;:&quot;支付宝&quot;,&quot;out_trade_no&quot;:&quot;125477&quot;,&quot;product_code&quot;:&quot;FAST_INSTANT_TRADE_PAY&quot;,&quot;subject&quot;:&quot;294389472934&quot;,&quot;timeout_express&quot;:&quot;5m&quot;,&quot;total_amount&quot;:&quot;1000.0&quot;}">
        <input  type="submit" value="立即支付" style="display:none" >
        </form>
        <script>document.forms[0].submit();</script>

如果是GET请求,则只会是上面action的地址。

场景二、前端请求后端,只返回对应的二维码地址(AlipayTradePrecreateRequest)

参照官方文档中的案例实现

https://opendocs.alipay.com/open/8ad49e4a_alipay.trade.precreate?scene=2ae8516856f24a5592194d237f3f235d&pathHash=d18bff53

编写对应的接口和实现类

@GetMapping(value = "/pay3")
@ResponseBody
public String pay3(@RequestParam long id) throws AlipayApiException {
    // 创建订单对象并设置属性
    Order order = createOrder(id);

    // 调用支付宝支付模板进行支付
    return aliPayTemplate.pay3(order);
}
package cn.alipay.config;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradePagePayModel;
import com.alipay.api.domain.AlipayTradePayModel;
import com.alipay.api.domain.AlipayTradePrecreateModel;
import com.alipay.api.domain.BusinessParams;
import com.alipay.api.domain.ExtendParams;
import com.alipay.api.domain.GoodsDetail;
import com.alipay.api.domain.SettleDetailInfo;
import com.alipay.api.domain.SettleInfo;
import com.alipay.api.internal.util.WebUtils;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradePayRequest;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.response.AlipayTradePagePayResponse;
import com.alipay.api.response.AlipayTradePayResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;

/**
 * 支付宝支付 模板
 */
@Slf4j
@Data
@Component
public class AliPayTemplate {
    
    @Autowired
    private AlipayProperties alipayProperties;

    private AlipayClient alipayClient;

    @PostConstruct
    public void init() {
        log.info("APPID:" + alipayProperties.getAppId());
        log.info("应用私钥:" + alipayProperties.getAppPrivateKey());
        log.info("支付宝公钥:" + alipayProperties.getAlipayPublicKey());
        log.info("支付宝会悄悄的给我们发送一个请求,告诉我们支付成功的信息:" + alipayProperties.getNotifyUrl());
        log.info("同步通知,支付成功,一般跳转到成功页:" + alipayProperties.getReturnUrl());
        log.info("签名方式:" + alipayProperties.getSignType());
        log.info("字符编码格式:" + alipayProperties.getCharset());
        log.info("订单超时时间:" + alipayProperties.getTimeout());
        log.info("支付宝网关:" + alipayProperties.getGatewayUrl());
        // 1. 根据支付宝的配置生成一个支付客户端
        alipayClient = new DefaultAlipayClient(
                alipayProperties.getGatewayUrl(),
                alipayProperties.getAppId(),
                alipayProperties.getAppPrivateKey(),
                "json",
                alipayProperties.getCharset(),
                alipayProperties.getAlipayPublicKey(),
                alipayProperties.getSignType()
        );
    }
    
    public String pay3(Order order) throws AlipayApiException {
        AlipayTradePrecreateRequest alipayRequest = new AlipayTradePrecreateRequest();
        // 强制关闭 ssl 证书校验
        WebUtils.setNeedCheckServerTrusted(false);
        alipayRequest.setNotifyUrl(alipayProperties.getNotifyUrl());
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("out_trade_no",order.getId());// 商户订单号
        jsonObject.put("total_amount",order.getMoney());// 商品价格
        jsonObject.put("subject","这只是个商品标题");// 商品标题
        jsonObject.put("store_id","香蕉集团");//组织或公司名
//            jsonObject.put("timeout_express","5m");// 订单有效时间
        alipayRequest.setBizContent(jsonObject.toString());
        AlipayTradePrecreateResponse response = alipayClient.execute(alipayRequest);
        System.out.println("创建订单结果:"+response.getBody());
        System.out.println("订单编号是"+response.getOutTradeNo());
        String qrCode = response.getQrCode();
//            AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
        return qrCode;
    }
}

请求后会得到一个支付的地址,使用ZXing框架,将其转换为二维码。

场景三、沙箱APP扫码支付后回调处理

在每次请求AliPay的接口时,都会传递一个回调接口参数。

alipayRequest.setNotifyUrl(alipayProperties.getNotifyUrl());

这个参数主要是用于告知AliPay在支付操作中,各项信息的回调信息,是个异步的操作。

针对回调,判断是否是支付成功,可以参照如下逻辑:

/**
 * 支付宝 支付 异步回调接口  必须是 Post
 * @param request
 * @return
 * @throws Exception
 */
@PostMapping("/notify")  
public String payNotify(HttpServletRequest request) throws Exception {
    // 检查交易状态是否为成功
    if (!"TRADE_SUCCESS".equalsIgnoreCase(request.getParameter("trade_status"))) {
        // 如果状态不是成功,则返回失败
        return "failure"; 
    }
    log.info("=========支付宝异步回调========");
    // .... 此处省略部分业务逻辑
    aliPayServide.payNotify(request);
    return "success";
}

业务层中的代码片段如下:

public void payNotify(HttpServletRequest request) throws AlipayApiException {
    // 创建一个存储请求参数的Map
    Map<String, String> params = getRequestParams(request);

    String tradeNo = params.get("out_trade_no");

    // 验证支付宝返回的签名
    if (!verifySignature(params)) {
        log.info("----验签失败----");
       return;
    }
    // 记录交易详情
    logTransactionDetails(params);
    // 其他业务逻辑
}

/**
 * 记录交易详情的方法
 * @param params
 */
private void logTransactionDetails(Map<String, String> params) {
    log.info("交易名称: " + params.get("subject"));
    log.info("交易状态: " + params.get("trade_status"));
    log.info("支付宝交易凭证号: " + params.get("trade_no"));
    log.info("商户订单号: " + params.get("out_trade_no"));
    log.info("交易金额: " + params.get("total_amount"));
    log.info("买家在支付宝唯一id: " + params.get("buyer_id"));
    log.info("买家付款时间: " + params.get("gmt_payment"));
    log.info("买家付款金额: " + params.get("buyer_pay_amount"));

    // 记录日志
    ChatAliPayDetailLog chatAliPayDetailLog = ChatAliPayDetailLog.builder()
            .id(IdUtil.getSnowflakeNextIdStr())
            .subject(params.get("subject"))
            .tradeStatus(params.get("trade_status"))
            .tradeNo(params.get("trade_no"))
            .outTradeNo(params.get("out_trade_no"))
            .totalAmount(new BigDecimal(params.get("total_amount")))
            .buyerId(params.get("buyer_id"))
            .gmtPayment(DateUtil.parseDate(params.get("gmt_payment")))
            .buyerPayAmount(new BigDecimal(params.get("buyer_pay_amount")))
            .createdTime(new Date())
            .build();
    chatAliPayDetailLogMapper.insert(chatAliPayDetailLog);
}

/**
 * 验证签名
 * @param params
 * @return
 */
private boolean verifySignature(Map<String, String> params) throws AlipayApiException {
    String sign = params.get("sign");
    String content = AlipaySignature.getSignCheckContentV1(params);
    return AlipaySignature.rsa256CheckContent(content, sign, alipayProperties.getAlipayPublicKey(), "UTF-8");
}

/**
 * 提取请求参数的方法
 * @param request
 * @return
 */
private Map<String, String> getRequestParams(HttpServletRequest request) {
    Map<String, String> params = new HashMap<>();
    Map<String, String[]> requestParams = request.getParameterMap();
    for (String name : requestParams.keySet()) {
        params.put(name, request.getParameter(name));
    }
    return params;
}

但回调处理是一个异步,如果前端界面中需要实时获取支付成功状态,可以使用轮训的方式,定时去查询支付结果。

场景四、定时查询支付结果

在官方文档中,其中提供有一个alipay.trade.query(统一收单交易查询),专门提供查询操作。

https://opendocs.alipay.com/open/217dd591_alipay.trade.query?scene=common&pathHash=62ae74aa

代码片段如下所示:

AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
AlipayTradeQueryModel model = new AlipayTradeQueryModel();
model.setOutTradeNo(chatUserPayOrder.getOrderNo());
request.setBizModel(model);
try {
    AlipayTradeQueryResponse response = alipayClient.execute(request);
    if ("TRADE_SUCCESS".equalsIgnoreCase(response.getTradeStatus())) {
        // 成功支付  则进行后续处理
        insertLog(response);
        // 根据 response.getOutTradeNo() 修改对应的支付信息
        updatePayOrderStatus(response);
    }
} catch (AlipayApiException e) {
    throw new RuntimeException(e);
}

也可以考虑定时任务xxl-job定时去获取所有未收到支付状态的数据,请求获取最终结果。或者超过限定时间表示失效等逻辑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值