若依(springboot)集成微信支付(native支付/jsapi支付/h5支付/支付回调),CV即用

前言:最近写了微信及支付宝支付,整理了一下,方便直接CV,遇到有支付的问题,不要犹豫,直接问微信客服,解决起来方便快捷,代码可以直接CV过去就能用,配置一下application.yml里面微信支付的所需参数就可以了.

以下是gitee项目地址,代码在dev分支

https://gitee.com/yuyuyuyulv/gjj-ry/tree/dev/

依赖

		<!-- 微信支付 -->
        <dependency>
            <groupId>com.github.wxpay</groupId>
            <artifactId>wxpay-sdk</artifactId>
            <version>0.0.3</version>
        </dependency>
        <dependency>
            <groupId>com.github.binarywang</groupId>
            <artifactId>weixin-java-miniapp</artifactId>
            <version>4.4.2.B</version>
        </dependency>
        <dependency>
            <groupId>com.github.binarywang</groupId>
            <artifactId>weixin-java-pay</artifactId>
            <version>4.2.0</version>
        </dependency>
        <dependency>
            <groupId>com.github.binarywang</groupId>
            <artifactId>weixin-java-mp</artifactId>
            <version>4.4.0</version>
        </dependency>

application.yml关于微信参数的配置

具体如何获得微信支付所需参数appid等,可以去找其他文章,或者直接找公司要

wx:
  pay:
    appId:  #微信公众号或者小程序等的appid
    secret:
    mchId:  #微信支付商户号
    mchKey:  #微信支付商户密钥
    notifyUrl: http://8.130.135.74:8053/api/order/student/pay/wxCallback #支付回调地址

微信支付配置文件

具体如何获得微信支付所需参数appid等,可以去找其他文章,或者直接找公司要,沙箱环境也需要商户账号才能使用沙箱

package com.ruoyi.common.wx;

import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author Binary Wang
 */
@Configuration
@ConditionalOnClass(WxPayService.class)
@EnableConfigurationProperties(WxPayProperties.class)
@AllArgsConstructor
public class WxPayConfiguration {

  private WxPayProperties properties;

  @Bean
  @ConditionalOnMissingBean
  public WxPayService wxService() {
    WxPayConfig payConfig = new WxPayConfig();
    payConfig.setAppId(StringUtils.trimToNull(this.properties.getAppId()));
    payConfig.setMchId(StringUtils.trimToNull(this.properties.getMchId()));
    payConfig.setMchKey(StringUtils.trimToNull(this.properties.getMchKey()));
    WxPayService wxPayService = new WxPayServiceImpl();
    wxPayService.setConfig(payConfig);
    return wxPayService;
  }

}

获取yml配置

package com.ruoyi.common.wx;

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


/**
 * wxpay pay properties.
 *
 * @author Binary Wang
 */
@Data
@ConfigurationProperties(prefix = "wx.pay")
public class WxPayProperties {
  /**
   * 设置微信公众号或者小程序等的appid
   */
  private String appId;

  private String secret;

  /**
   * 微信支付商户号
   */
  private String mchId;

  /**
   * 微信支付商户密钥
   */
  private String mchKey;

/**
   * 回调地址
   */
  private String notifyUrl;
}

微信支付业务代码

package com.ruoyi.common.wx;

import com.alibaba.fastjson.JSONObject;
import com.github.binarywang.wxpay.bean.order.WxPayNativeOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.util.SignUtils;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * @description: 支付相关通用服务
 */
@Service
public class PayService {

    @Autowired
    private WxPayService wxPayService;

    /**
     * 根据传入的tradeType来进行不同类型的支付
     * @param dto 商品参数
     * @param tradeType WxPayConstants.TradeType.MWEB为H5支付/WxPayConstants.TradeType.NATIVE为扫码支付/WxPayConstants.TradeType.JSAPI为JSAPI支付
     * @return
     */
    public Object transactions(WxPayDTO dto,String tradeType) {
        try {
            if (tradeType != null && !tradeType.isEmpty()){
                if (WxPayConstants.TradeType.MWEB.equals(tradeType)){
                    //H5支付
                    return noMiniappPay(dto, tradeType);
                }else if (WxPayConstants.TradeType.NATIVE.equals(tradeType)){
                    //NATIVE支付
                    return noMiniappPay(dto, tradeType);
                }else if (WxPayConstants.TradeType.JSAPI.equals(tradeType)){
                    //JSAPI支付
                    return miniappPay(dto);
                }
            }
        } catch (Exception e) {
            // 处理异常
            e.printStackTrace();
            return null;
        }
        return null;
    }

    private String noMiniappPay(WxPayDTO dto, String tradeType) throws WxPayException {
        //设置请求参数
        WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
        request.setOutTradeNo(dto.getOutTradeNo());
        request.setTotalFee(dto.getTotalFee());
        request.setBody(dto.getBody());
        HttpServletRequest httpServletRequest = getHttpServletRequest();
        request.setSpbillCreateIp(httpServletRequest.getRemoteAddr());
        request.setNotifyUrl(dto.getNotifyUrl());
        request.setProductId(dto.getOutTradeNo());
        //设置下单方式
        request.setTradeType(tradeType);
        // 调用统一下单接口
        WxPayNativeOrderResult result = wxPayService.createOrder(request);
        // Native支付返回的二维码/H5支付返回的跳转链接
        String codeUrl = result.getCodeUrl();
        // 返回codeUrl给前端
        return codeUrl;
    }

    /**
     *
     * @param dto
     * @return
     */
    @SneakyThrows
    public Map<String, String> miniappPay(WxPayDTO dto){
        //设置请求参数
        WxPayUnifiedOrderRequest request = WxPayUnifiedOrderRequest.newBuilder()
                .body(dto.getBody())
                .totalFee(dto.getTotalFee())
                .spbillCreateIp(this.getIpAddress(this.getHttpServletRequest()))
                .notifyUrl(dto.getNotifyUrl())
                .tradeType(WxPayConstants.TradeType.JSAPI)
                .openid(dto.getOpenId())
                .outTradeNo(dto.getOutTradeNo())
                .timeStart(dto.getTimeStart())
                .timeExpire(dto.getTimeExpire())
                .build();
        request.setSignType(WxPayConstants.SignType.MD5);

        //发起微信 统一下单
        WxPayUnifiedOrderResult result = null;
        result = this.wxPayService.unifiedOrder(request);
        //前端启动支付配置
        if (StringUtils.isBlank(result.getPrepayId())) {
            return null;
        }
        //返回前端调取jsapi支付的所需参数
        return getWxJsapiPayParam(result);
    }


    /**
     * 微信退款
     * @param body
     * @return
     */
    public void wxRefund(WxRefundDTO body) {
        WxPayRefundRequest refundRequest = new WxPayRefundRequest();
        refundRequest.setOutTradeNo(body.getOutTradeNo());
        refundRequest.setOutRefundNo(body.getOutRefundNo());
        refundRequest.setTotalFee(body.getTotalFee());
        refundRequest.setRefundFee(body.getRefundFee());
        refundRequest.setRefundDesc("商品退款");
        refundRequest.setNotifyUrl(body.getNotifyUrl());

        try {
            WxPayRefundResult result = wxPayService.refund(refundRequest);
            System.out.println("微信退款成功,返回参数{}" + JSONObject.toJSONString(result));
        } catch (WxPayException e) {
            System.out.println("微信退款异常,返回参数{}" + JSONObject.toJSONString(e));
        }
    }


    /**
     * 获取请求对象
     *
     * @return
     */
    private HttpServletRequest getHttpServletRequest() {
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String key = headerNames.nextElement();
            System.out.println("请求头:" + key + "值:" + request.getHeader(key));
        }
        return request;
    }

    /**
     * 获取到JS支付相关配置
     *
     * @param weiXinPayOrder
     * @return
     */
    private Map<String, String> getWxJsapiPayParam(WxPayUnifiedOrderResult weiXinPayOrder) {
        WxPayWebDTO wxPayParam = new WxPayWebDTO();
        String package_ = "prepay_id=" + weiXinPayOrder.getPrepayId();
        wxPayParam.setAppId(weiXinPayOrder.getAppid());
        wxPayParam.setTimeStamp(System.currentTimeMillis() / 1000 + "");
        wxPayParam.setNonceStr(UUID.randomUUID().toString().replace("-", ""));
        wxPayParam.setPackage1(package_);
        wxPayParam.setSignType(WxPayConstants.SignType.MD5);
        //WxPayParam中属性package1,签名使用key是package
        Map<String, String> signParam = new LinkedHashMap<String, String>();
        signParam.put("appId", weiXinPayOrder.getAppid());
        signParam.put("nonceStr", wxPayParam.getNonceStr());
        signParam.put("package", package_);
        signParam.put("signType", WxPayConstants.SignType.MD5);
        signParam.put("timeStamp", wxPayParam.getTimeStamp());
        String paySign = SignUtils.createSign(signParam,WxPayConstants.SignType.MD5, this.wxPayService.getConfig().getMchKey(), new String[0]);
        signParam.put("paySign", paySign);
        return signParam;
    }
}

微信支付接口

package com.ruoyi.web.controller.system;

import com.alibaba.fastjson.JSONObject;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import com.ruoyi.common.utils.DateUtil;
import com.ruoyi.common.wx.PayService;
import com.ruoyi.common.wx.StreamUtils;
import com.ruoyi.common.wx.WxPayDTO;
import com.ruoyi.common.wx.WxPayProperties;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Api(tags = "微信支付相关接口")
@RestController
@Slf4j
@Validated
@RequiredArgsConstructor
@RequestMapping("/pay")
public class WechatPayController {

    @Resource
    private PayService payService;
    @Resource
    private WxPayProperties wxPayProperties;

    @ApiOperation(value = "微信native下单,返回支付二维码")
    @GetMapping("/nativePay")
    public Object nativePay(@RequestParam("orderNumber") String orderNumber) {
        //todo 业务操作-根据订单编号查询订单信息
        //将订单信息中的数据存到WxPayDTO
        WxPayDTO payDTO = new WxPayDTO();
        payDTO.setBody("商品描述");
        //订单总金额,单位为分
        payDTO.setTotalFee(1);
        //支付回调地址
        payDTO.setNotifyUrl(wxPayProperties.getNotifyUrl());
        //商品订单编号
        payDTO.setOutTradeNo(orderNumber);
        //获取时间
        Date date = new Date();
        String timeStart = DateUtil.formatDateToString(date, "yyyyMMddHHmmss");
        //结束时间设置在30分钟后
        String timeExpire = DateUtil.formatDateToString(DateUtil.addMinutesToDate(date, 30),"yyyyMMddHHmmss");
        //交易起始时间
        payDTO.setTimeStart(timeStart);
        //交易结束时间
        payDTO.setTimeExpire(timeExpire);
        Object url = payService.transactions(payDTO, WxPayConstants.TradeType.NATIVE);
        return url;
    }

    @ApiOperation(value = "微信JSAPI下单,返回JS支付相关配置")
    @GetMapping("/jsapiPay")
    public Object jsapiPay(@RequestParam("orderNumber") String orderNumber) {
        //todo 业务操作-根据订单编号查询订单信息
        //将订单信息中的数据存到WxPayDTO
        WxPayDTO payDTO = new WxPayDTO();
        payDTO.setBody("商品描述");
        //订单总金额,单位为分
        payDTO.setTotalFee(1);
        //支付回调地址
        payDTO.setNotifyUrl(wxPayProperties.getNotifyUrl());
        payDTO.setOutTradeNo("商户订单号");
        //获取时间
        Date date = new Date();
        String timeStart = DateUtil.formatDateToString(date, "yyyyMMddHHmmss");
        //结束时间设置在30分钟后
        String timeExpire = DateUtil.formatDateToString(DateUtil.addMinutesToDate(date, 30),"yyyyMMddHHmmss");
        //交易起始时间
        payDTO.setTimeStart(timeStart);
        //交易结束时间
        payDTO.setTimeExpire(timeExpire);
        //todo jsapi下单需要用户的openid
        payDTO.setOpenId("openid");
        Object url = payService.transactions(payDTO, WxPayConstants.TradeType.JSAPI);

        return url;
    }

    @ApiOperation(value = "微信H5下单,返回跳转链接")
    @GetMapping("/h5Pay")
    public Object h5Pay(@RequestParam("orderNumber") String orderNumber, HttpServletRequest request) {
        //todo 业务操作-根据订单编号查询订单信息

        //将订单信息中的数据存到WxPayDTO
        WxPayDTO payDTO = new WxPayDTO();
        payDTO.setBody("商品描述");
        //订单总金额,单位为分
        payDTO.setTotalFee(1);
        //支付回调地址
        payDTO.setNotifyUrl(wxPayProperties.getNotifyUrl());
        payDTO.setOutTradeNo("商户订单号");
        //获取时间
        Date date = new Date();
        String timeStart = DateUtil.formatDateToString(date, "yyyyMMddHHmmss");
        //结束时间设置在30分钟后
        String timeExpire = DateUtil.formatDateToString(DateUtil.addMinutesToDate(date, 30),"yyyyMMddHHmmss");
        //交易起始时间
        payDTO.setTimeStart(timeStart);
        //交易结束时间
        payDTO.setTimeExpire(timeExpire);
        //todo H5下单需要用户的用户的客户端IP
        String remoteAddr = request.getRemoteAddr();
        payDTO.setPayerClientIp(remoteAddr);
        Object url = payService.transactions(payDTO, WxPayConstants.TradeType.JSAPI);

        return url;
    }

    @ApiOperation(value = "微信支付回调")
    @PostMapping("/wxCallback")
    public Object wxCallback(HttpServletRequest request, HttpServletResponse response) {
        ServletInputStream inputStream = null;
        try {
            inputStream = request.getInputStream();
            String notifyXml = StreamUtils.inputStream2String(inputStream, "utf-8");
            log.info(notifyXml);
            // 解析返回结果
            Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyXml);
            String jsonString = JSONObject.toJSONString(notifyMap);
            log.info(jsonString);
            // 判断支付是否成功
            if ("SUCCESS".equals(notifyMap.get("result_code"))) {
                //todo 修改订单状态

                // 支付成功:给微信发送我已接收通知的响应 创建响应对象
                Map<String, String> returnMap = new HashMap<>();
                returnMap.put("return_code", "SUCCESS");
                returnMap.put("return_msg", "OK");
                String returnXml = WXPayUtil.mapToXml(returnMap);
                response.setContentType("text/xml");
                log.info("支付成功");
                return returnXml;
            }else {
                //保存回调信息,方便排除问题
            }
            // 创建响应对象:微信接收到校验失败的结果后,会反复的调用当前回调函数
            Map<String, String> returnMap = new HashMap<>();
            returnMap.put("return_code", "FAIL");
            returnMap.put("return_msg", "");
            String returnXml = WXPayUtil.mapToXml(returnMap);
            response.setContentType("text/xml");
            log.info("校验失败");
            return returnXml;

        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

}

微信支付DTO

package com.ruoyi.common.wx;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class WxPayDTO {
    /**
     * openId
     */
    private String openId;


    /**
     * 字段名:商品描述.
     *   变量名:body
     *   是否必填:是
     *   类型:String(128)
     *   示例值: 腾讯充值中心-QQ会员充值
     *   描述:商品简单描述,该字段须严格按照规范传递,具体请见参数规定
     */
    private String body;

    /**
     * 字段名:总金额.
     * 变量名:total_fee
     * 是否必填:是
     * 类型:Int
     * 示例值: 888
     * 描述:订单总金额,单位为分,详见支付金额
     */
    private Integer totalFee;

    /**
     * 字段名:通知地址.
     * 变量名:notify_url
     * 是否必填:是
     * 类型:String(256)
     * 示例值:http://www.weixin.qq.com/wxpay/pay.php
     * 描述:接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。
     */
    private String notifyUrl;

    /**
     * 字段名:商户订单号.
     * 变量名:out_trade_no
     * 是否必填:是
     * 类型:String(32)
     * 示例值:20150806125346
     * 描述:商户系统内部的订单号,32个字符内、可包含字母, 其他说明见商户订单号
     */
    private String outTradeNo;

    /**
     * 字段名:交易起始时间.
     * 变量名:time_start
     * 是否必填:否
     * 类型:String(14)
     * 示例值:20091225091010
     * 描述:订单生成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则
     */
    private String timeStart;

    /**
     * 字段名:交易结束时间.
     * 变量名:time_expire
     * 是否必填:否
     * 类型:String(14)
     * 示例值:20091227091010
     * 描述:订单失效时间,格式为yyyyMMddHHmmss,如2009年12月27日9点10分10秒表示为20091227091010。其他详见时间规则
     *   注意:最短失效时间间隔必须大于5分钟
     */
    private String timeExpire;

    /**
     * 字段名:用户的客户端IP
     * 变量名:payer_client_ip
     * 是否必填:是
     * 类型:String(14)
     * 示例值:14.23.150.211
     * 描述:用户的客户端IP,支持IPv4和IPv6两种格式的IP地址。
     *   注意:最短失效时间间隔必须大于5分钟
     */
    private String payerClientIp;
}

package com.ruoyi.common.wx;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@ApiModel
public class WxPayWebDTO {
    /**
     * 公众号id
     */
    @ApiModelProperty("公众号id")
    private String appId;
    /**
     * 时间戳
     */
    @ApiModelProperty("时间戳")
    private String timeStamp;
    /**
     * 随机字符串
     */
    @ApiModelProperty("随机字符串")
    private String nonceStr;
    /**
     * 订单详情扩展字符串
     */
    @ApiModelProperty("订单详情扩展字符串")
    private String package1;
    /**
     * 签名方式
     */
    @ApiModelProperty("签名方式")
    private String signType;
    /**
     * 签名
     */
    @ApiModelProperty("签名")
    private String paySign;
}

package com.ruoyi.common.wx;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class WxRefundDTO {
    /**
     * 商户订单号
     */
    private String outTradeNo;

    /**
     * 商户退款单号
     */
    private String outRefundNo;

    /**
     * 订单金额 单位:分
     */
    private Integer totalFee;

    /**
     * 退款金额 单位:分
     */
    private Integer refundFee;

    /**
     * 退款结果通知url
     */
    private String notifyUrl;
}

可以自己先用测试数据进行测试,搞清楚后再进行业务逻辑的书写

  • 10
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用apiv2密钥jsapi支付方式的Java Spring Boot代码示例: 1. 创建微信支付配置类 ```java @Configuration public class WxPayConfig { @Value("${wxpay.appid}") private String appId; @Value("${wxpay.mchid}") private String mchId; @Value("${wxpay.key}") private String key; @Value("${wxpay.notifyurl}") private String notifyUrl; @Bean public WxPayService wxPayService() { WxPayService wxPayService = new WxPayServiceImpl(); WxPayConfig payConfig = new WxPayConfig(); payConfig.setAppId(appId); payConfig.setMchId(mchId); payConfig.setMchKey(key); payConfig.setNotifyUrl(notifyUrl); wxPayService.setConfig(payConfig); return wxPayService; } } ``` 2. 编写Controller接口 ```java @RestController @RequestMapping("/wxpay") public class WxPayController { @Autowired private WxPayService wxPayService; @PostMapping("/jsapi") public ResultCode<Map<String, String>> jsapiPay(@RequestBody WxPayDto wxPayDto) throws WxPayException { WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest(); request.setBody(wxPayDto.getBody()); request.setOutTradeNo(wxPayDto.getOutTradeNo()); request.setTotalFee(wxPayDto.getTotalFee()); request.setSpbillCreateIp(wxPayDto.getSpbillCreateIp()); request.setNotifyUrl(wxPayService.getConfig().getNotifyUrl()); request.setTradeType(WxPayConstants.TradeType.JSAPI); request.setOpenid(wxPayDto.getOpenid()); WxPayUnifiedOrderResult result = wxPayService.unifiedOrder(request); Map<String, String> jsApiParams = wxPayService.getJsapiPayParams(result.getPrepayId()); return ResultCode.success(jsApiParams); } } ``` 3. 编写WxPayDto类(用于接收支付请求参数) ```java @Data public class WxPayDto { @NotEmpty(message = "商品描述不能为空") private String body; @NotEmpty(message = "商户订单号不能为空") private String outTradeNo; @NotNull(message = "订单金额不能为空") private Integer totalFee; @NotEmpty(message = "终端IP不能为空") private String spbillCreateIp; @NotEmpty(message = "openid不能为空") private String openid; } ``` 4. 在application.yml文件中添加微信支付配置 ```yaml wxpay: appid: your_appid # 微信公众号appid mchid: your_mchid # 商户号 key: your_key # 商户密钥 notifyurl: your_notify_url # 支付成功回调地址 ``` 以上代码示例仅供参考,具体实现方式可能会因业务需求而异。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值