2024最新自动发卡波猫商城专业版-基于springboot项目改进

🌼前言

【最新版波猫商店自动发卡售卡系统源码】——开启你的电商赚钱之旅!

想要拥有一个强大的电商平台,自动发卡售卡系统源码是你的不二选择!这套源码适用于各种电商、优惠券、论坛邀请码、充值卡、激活码、注册码、腾讯爱奇艺积分CDK等业务,支持手动和全自动发货,还具备类似1688的分层批发模式。

让我们来看看这套源码的功能特色:

  1. 先进的开发语言和框架:基于JAVA开发语言和Spring boot开发框架,保证系统的高效和稳定性。
  2. 炫丽的界面设计:前端UI采用layui开发的白天-黑夜-炫丽暗黑模板,让你的商店界面充满个性和吸引力。
  3. 多种主题模式:集成了后台多种主题模式,让你可以根据喜好自由切换界面风格。
  4. 自定义背景图片:炫丽暗黑界面支持自定义背景图片,让你的商店界面更加个性化。
  5. 卡片式商品展示:前台卡片式商品展示方式,让用户浏览商品更加方便快捷。
  6. 无限层级的批发模式:支持分层批发模式,让你的商店能够灵活应对不同的批发需求。
  7. 强大的支付接口集成:集成了微信官方扫码、支付宝当面付、v免签、payjs、虎皮椒V3、YunGouOS、值联码支付、码支付、USDT等多种支付接口,满足用户的支付需求。
  8. 多种通知方式:集成了微信订单消息通知和邮件系统,让你能够及时了解订单状态。
  9. 自定义网站设置:支持自定义网站标题、关键字、logo等,让你的商店更具品牌特色。
  10. 移动端支付宝唤醒APP支付:支持移动端支付宝唤醒APP支付,提升用户支付体验。
  11. 优惠券系统:集成了强大的优惠券系统,帮助你提升销售量和用户满意度。
  12. 商品购买备注字段:集成了自定义的商品购买备注字段,方便用户留言和交流。

这套最新版波猫商店自动发卡售卡系统源码,不仅功能强大,还具备美观的界面设计,为你的电商平台提供了完美的解决方案。立即获取源码,开启你的电商赚钱之旅吧!

🙋 仅供学习参考、不可用于违法用途。

内容

普通版和专业版对比:

普通版:

专业版:增加登录注册功能

自带三套模板

启动redis缓存让网站更加流畅

功能

相信遇到这个问题的朋友都会解决吧,我的win忘记装redis。

安装redis并启动,win下不关闭控制台

重新启动:成功启动

访问localhost:8085就可以得到你想要的页面啦

部分代码:

package cn.zlianpay.theme.controller;

import cn.zlianpay.common.core.annotation.OperLog;
import cn.zlianpay.common.core.web.*;
import cn.zlianpay.settings.entity.ShopSettings;
import cn.zlianpay.settings.service.ShopSettingsService;
import cn.zlianpay.theme.entity.Theme;
import cn.zlianpay.theme.service.ThemeService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 主题配置管理
 * Created by Panyoujie on 2021-06-28 00:36:29
 */
@Controller
@RequestMapping("/theme/theme")
public class ThemeController extends BaseController {
    @Autowired
    private ThemeService themeService;

    @Autowired
    private ShopSettingsService shopSettingsService;

    @RequiresPermissions("theme:theme:view")
    @RequestMapping()
    public String view() {
        return "theme/theme.html";
    }

    /**
     * 分页查询主题配置
     */
    @RequiresPermissions("theme:theme:list")
    @OperLog(value = "主题配置管理", desc = "分页查询")
    @ResponseBody
    @RequestMapping("/page")
    public PageResult<Theme> page(HttpServletRequest request) {
        PageParam<Theme> pageParam = new PageParam<>(request);
        return new PageResult<>(themeService.page(pageParam, pageParam.getWrapper()).getRecords(), pageParam.getTotal());
    }

    /**
     * 查询全部主题配置
     */
    @RequiresPermissions("theme:theme:list")
    @OperLog(value = "主题配置管理", desc = "查询全部")
    @ResponseBody
    @RequestMapping("/list")
    public JsonResult list(HttpServletRequest request) {
        PageParam<Theme> pageParam = new PageParam<>(request);
        return JsonResult.ok().setData(themeService.list(pageParam.getOrderWrapper()));
    }

    /**
     * 根据id查询主题配置
     */
    @RequiresPermissions("theme:theme:list")
    @OperLog(value = "主题配置管理", desc = "根据id查询")
    @ResponseBody
    @RequestMapping("/get")
    public JsonResult get(Integer id) {
        return JsonResult.ok().setData(themeService.getById(id));
    }

    /**
     * 添加主题配置
     */
    @RequiresPermissions("theme:theme:save")
    @OperLog(value = "主题配置管理", desc = "添加", param = false, result = true)
    @CacheEvict(value = "theme", allEntries = true)
    @ResponseBody
    @RequestMapping("/save")
    public JsonResult save(Theme theme) {
        if (themeService.save(theme)) {
            return JsonResult.ok("添加成功");
        }
        return JsonResult.error("添加失败");
    }

    /**
     * 修改主题配置
     */
    @RequiresPermissions("theme:theme:update")
    @OperLog(value = "主题配置管理", desc = "修改", param = false, result = true)
    @CacheEvict(value = "theme", allEntries = true)
    @ResponseBody
    @RequestMapping("/update")
    public JsonResult update(Theme theme) {
        if (themeService.updateById(theme)) {
            return JsonResult.ok("修改成功");
        }
        return JsonResult.error("修改失败");
    }

    /**
     * 删除主题配置
     */
    @RequiresPermissions("theme:theme:remove")
    @OperLog(value = "主题配置管理", desc = "删除", result = true)
    @CacheEvict(value = "theme", allEntries = true)
    @ResponseBody
    @RequestMapping("/remove")
    public JsonResult remove(Integer id) {
        if (themeService.removeById(id)) {
            return JsonResult.ok("删除成功");
        }
        return JsonResult.error("删除失败");
    }

    /**
     * 批量添加主题配置
     */
    @RequiresPermissions("theme:theme:save")
    @OperLog(value = "主题配置管理", desc = "批量添加", param = false, result = true)
    @CacheEvict(value = "theme", allEntries = true)
    @ResponseBody
    @RequestMapping("/saveBatch")
    public JsonResult saveBatch(@RequestBody List<Theme> list) {
        if (themeService.saveBatch(list)) {
            return JsonResult.ok("添加成功");
        }
        return JsonResult.error("添加失败");
    }

    /**
     * 批量修改主题配置
     */
    @RequiresPermissions("theme:theme:update")
    @OperLog(value = "主题配置管理", desc = "批量修改", result = true)
    @CacheEvict(value = "theme", allEntries = true)
    @ResponseBody
    @RequestMapping("/updateBatch")
    public JsonResult updateBatch(@RequestBody BatchParam<Theme> batchParam) {
        if (batchParam.update(themeService, "id")) {
            return JsonResult.ok("修改成功");
        }
        return JsonResult.error("修改失败");
    }

    /**
     * 批量删除主题配置
     */
    @RequiresPermissions("theme:theme:remove")
    @OperLog(value = "主题配置管理", desc = "批量删除", result = true)
    @CacheEvict(value = "theme", allEntries = true)
    @ResponseBody
    @RequestMapping("/removeBatch")
    public JsonResult removeBatch(@RequestBody List<Integer> ids) {
        if (themeService.removeByIds(ids)) {
            return JsonResult.ok("删除成功");
        }
        return JsonResult.error("删除失败");
    }

    /**
     * 修改状态
     */
    @RequiresPermissions("theme:theme:update")
    @OperLog(value = "主题配置管理", desc = "修改状态", result = true)
    @CacheEvict(value = "theme", allEntries = true)
    @ResponseBody
    @RequestMapping("/status/update")
    public JsonResult updateStates(Integer id, Integer enabled) {
        ShopSettings shopSettings = shopSettingsService.getById(1);
        if (shopSettings.getAuthorizeStatus() == 0) {
            return JsonResult.error("您的系统当前为副版、部分功能不能使用。");
        }

        if (enabled == null || (enabled != 0 && enabled != 1)) {
            return JsonResult.error("状态值不正确");
        }

        List<Theme> list = themeService.list();
        List<Theme> themeList = list.stream().map((theme) -> {
            theme.setEnable(0);
            return theme;
        }).collect(Collectors.toList());
        themeService.updateBatchById(themeList);

        Theme theme = new Theme();
        theme.setId(id);
        theme.setEnable(enabled);
        if (themeService.updateById(theme)) {
            return JsonResult.ok("主题切换成功!");
        }
        return JsonResult.error("主题切换失败!");
    }

    @ResponseBody
    @RequestMapping("/switchMode")
    public JsonResult switchMode(HttpServletResponse response, String dark_mode) {
        Cookie cookie = new Cookie("darkmode", dark_mode);
        cookie.setPath("/");
        cookie.setMaxAge(24 * 60 * 60 * 30); // 30天过期
        // 将cookie对象加入response响应
        response.addCookie(cookie);
        return JsonResult.ok(dark_mode);
    }

}
package cn.zlianpay.member.controller;

import cn.hutool.crypto.SecureUtil;
import cn.zlianpay.common.core.config.DelayQueueConfig;
import cn.zlianpay.common.core.pays.epusdt.entity.EpusdtNotify;
import cn.zlianpay.common.core.pays.epusdt.sendPay;
import cn.zlianpay.common.core.pays.mqpay.mqPay;
import cn.zlianpay.common.core.pays.payjs.SignUtil;
import cn.zlianpay.common.core.pays.paypal.PaypalSend;
import cn.zlianpay.common.core.pays.tronapi.lib.Helper;
import cn.zlianpay.common.core.pays.weidoufu.WeidouSignUtil;
import cn.zlianpay.common.core.pays.weidoufu.entity.ContentEntity;
import cn.zlianpay.common.core.pays.weidoufu.entity.NotifyEntity;
import cn.zlianpay.common.core.pays.xunhupay.PayUtils;
import cn.zlianpay.common.core.pays.zlianpay.ZlianPay;
import cn.zlianpay.common.core.utils.RequestParamsUtil;
import cn.zlianpay.common.core.utils.StringUtil;
import cn.zlianpay.common.core.web.JsonResult;
import cn.zlianpay.member.bo.UserGradeBo;
import cn.zlianpay.member.entity.GradeOrders;
import cn.zlianpay.member.entity.UserGrade;
import cn.zlianpay.member.mapper.UserGradeMapper;
import cn.zlianpay.member.service.GradeOrdersService;
import cn.zlianpay.reception.dto.NotifyDTO;
import cn.zlianpay.reception.entity.TronApiNotify;
import cn.zlianpay.reception.util.SynchronizedByKeyService;
import cn.zlianpay.settings.entity.Pays;
import cn.zlianpay.settings.service.PaysService;
import com.aizuda.limiter.annotation.RateLimit;
import com.alibaba.fastjson.JSON;
import com.alipay.easysdk.factory.Factory;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.wxpay.sdk.WXPayUtil;
import com.google.common.collect.Maps;
import com.paypal.api.payments.Payment;
import com.paypal.api.payments.Transaction;
import com.paypal.base.rest.PayPalRESTException;
import lombok.SneakyThrows;
import org.apache.commons.codec.Charsets;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;

@Controller
@Transactional
public class MemberNotifyController {

    @Autowired
    private PaysService paysService;

    @Autowired
    private GradeOrdersService gradeOrdersService;

    @Autowired
    private UserGradeMapper userGradeMapper;

    @Autowired
    private SynchronizedByKeyService synchronizedByKeyService;

    /**
     * 返回成功xml
     */
    private String WxpayresXml = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";

    private String WxpayH5resXml = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";

    /**
     * 返回失败xml
     */
    private String resFailXml = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml>";

    @RequestMapping("/member/mqpay/notifyUrl")
    @RateLimit(key = "#payId", count = 1, interval = "10s", message = "请勿频繁操作")
    @ResponseBody
    public String notifyUrl(HttpServletRequest request) {
        /**
         *验证通知 处理自己的业务
         */
        Map<String, String> params = RequestParamsUtil.getParameterMap(request);
        String param = params.get("param");
        String price = params.get("price");
        String money = params.get("reallyPrice");
        String sign = params.get("sign");
        String payId = params.get("payId");
        String type = params.get("type");

        String key = null;
        GradeOrders rechargeRecord = gradeOrdersService.getOne(new QueryWrapper<GradeOrders>().eq("member_id", payId));
        if (Integer.parseInt(type) == 1) { // wxpay
            Pays wxPays = paysService.getOne(new QueryWrapper<Pays>().eq("driver", "mqpay_wxpay"));

            /**
             * 防止破解
             */
            if (!rechargeRecord.getPayType().equals(wxPays.getDriver())) {
                return "Error Pperating!!!";
            }

            Map mapTypes = JSON.parseObject(wxPays.getConfig());
            key = mapTypes.get("key").toString();
        } else if (Integer.parseInt(type) == 2) { // alipay
            Pays aliPays = paysService.getOne(new QueryWrapper<Pays>().eq("driver", "mqpay_alipay"));

            /**
             * 防止破解
             */
            if (!rechargeRecord.getPayType().equals(aliPays.getDriver())) {
                return "Error Pperating!!!";
            }

            Map mapTypes = JSON.parseObject(aliPays.getConfig());
            key = mapTypes.get("key").toString();
        }

        String mysign = mqPay.md5(payId + param + type + price + money + key);

        if (mysign.equals(sign)) {
            String date = new SimpleDateFormat("yyyyMMdd").format(new Date());
            String seconds = new SimpleDateFormat("HHmmss").format(new Date());
            String number = StringUtil.getRandomNumber(6);
            String payNo = date + seconds + number;

            AtomicReference<String> notifyText = new AtomicReference<>();
            synchronizedByKeyService.exec(payId, () -> {
                String returnBig1 = returnBig(money, price, payId, payNo, param, "success", "fiald");
                notifyText.set(returnBig1);
            });
            return notifyText.get();
        } else {
            return "fiald";
        }
    }

    @RequestMapping("/member/mqpay/returnUrl")
    public void returnUrl(HttpServletRequest request, HttpServletResponse response) throws IOException {

        /**
         *验证通知 处理自己的业务
         */
        Map<String, String> params = RequestParamsUtil.getParameterMap(request);
        String param = params.get("param");
        String price = params.get("price");
        String reallyPrice = params.get("reallyPrice");
        String sign = params.get("sign");
        String payId = params.get("payId");
        String type = params.get("type");

        String key = null;
        if (Integer.parseInt(type) == 1) { // wxpay
            Pays wxPays = paysService.getOne(new QueryWrapper<Pays>().eq("driver", "mqpay_wxpay"));
            Map mapTypes = JSON.parseObject(wxPays.getConfig());
            key = mapTypes.get("key").toString();
        } else if (Integer.parseInt(type) == 2) { // alipay
            Pays aliPays = paysService.getOne(new QueryWrapper<Pays>().eq("driver", "mqpay_alipay"));
            Map mapTypes = JSON.parseObject(aliPays.getConfig());
            key = mapTypes.get("key").toString();
        }
        String mysign = mqPay.md5(payId + param + type + price + reallyPrice + key);
        if (mysign.equals(sign)) {
            String url = "/member/userinfo";
            response.sendRedirect(url);
        }
    }

    @RequestMapping("/member/zlianpay/notifyUrl")
    @RateLimit(key = "#out_trade_no", count = 1, interval = "10s", message = "请勿频繁操作")
    @ResponseBody
    public String zlianpNotify(HttpServletRequest request) {
        Map<String, String> parameterMap = RequestParamsUtil.getParameterMap(request);

        String pid = parameterMap.get("pid");
        String type = parameterMap.get("type");
        String out_trade_no = parameterMap.get("out_trade_no");

        String driver = "";
        if (type.equals("wxpay")) {
            driver = "zlianpay_wxpay";
        } else if (type.equals("alipay")) {
            driver = "zlianpay_alipay";
        } else if (type.equals("qqpay")) {
            driver = "zlianpay_qqpay";
        }

        Pays pays = paysService.getOne(new QueryWrapper<Pays>().eq("driver", driver));

        /**
         * 防止破解
         */
        GradeOrders rechargeRecord = gradeOrdersService.getOne(new QueryWrapper<GradeOrders>().eq("member_id", out_trade_no));
        if (!rechargeRecord.getPayType().equals(pays.getDriver())) {
            return "Error Pperating!!!";
        }

        Map mapTypes = JSON.parseObject(pays.getConfig());

        // 你的key 在后台获取
        String secret_key = mapTypes.get("key").toString();
        String trade_no = parameterMap.get("trade_no");
        String name = parameterMap.get("name");
        String money = parameterMap.get("money");
        String trade_status = parameterMap.get("trade_status");
        String return_url = parameterMap.get("return_url");
        String notify_url = parameterMap.get("notify_url");
        String sign = parameterMap.get("sign");
        String sign_type = parameterMap.get("sign_type");

        Map<String, Object> params = new HashMap<>();
        params.put("pid", pid);
        params.put("trade_no", trade_no);
        params.put("out_trade_no", out_trade_no);
        params.put("type", type);
        params.put("name", name);
        params.put("money", money);
        params.put("return_url", return_url);
        params.put("notify_url", notify_url);
        params.put("trade_status", trade_status);

        String sign1 = ZlianPay.createSign(params, secret_key);

        if (sign1.equals(sign)) {
            AtomicReference<String> notifyText = new AtomicReference<>();
            synchronizedByKeyService.exec(out_trade_no, () -> {
                String returnBig1 = returnBig(money, money, out_trade_no, trade_no, name, "success", "final");
                notifyText.set(returnBig1);
            });
            return notifyText.get();
        } else {
            return "签名错误!!";
        }
    }

    @RequestMapping("/member/zlianpay/returnUrl")
    @ResponseBody
    public void zlianpReturnUrl(HttpServletRequest request, HttpServletResponse response) throws IOException {

        /**
         *验证通知 处理自己的业务
         */
        Map<String, String> parameterMap = RequestParamsUtil.getParameterMap(request);

        String pid = parameterMap.get("pid");
        String type = parameterMap.get("type");

        String driver = "";
        if (type.equals("wxpay")) {
            driver = "zlianpay_wxpay";
        } else if (type.equals("alipay")) {
            driver = "zlianpay_alipay";
        } else if (type.equals("qqpay")) {
            driver = "zlianpay_qqpay";
        }

        Pays pays = paysService.getOne(new QueryWrapper<Pays>().eq("driver", driver));
        Map mapTypes = JSON.parseObject(pays.getConfig());

        // 你的key 在后台获取
        String secret_key = mapTypes.get("key").toString();
        String trade_no = parameterMap.get("trade_no");
        String out_trade_no = parameterMap.get("out_trade_no");
        String name = parameterMap.get("name");
        String money = parameterMap.get("money");
        String trade_status = parameterMap.get("trade_status");
        String return_url = parameterMap.get("return_url");
        String notify_url = parameterMap.get("notify_url");
        String sign = parameterMap.get("sign");
        String sign_type = parameterMap.get("sign_type");

        Map<String, Object> params = new HashMap<>();
        params.put("pid", pid);
        params.put("trade_no", trade_no);
        params.put("out_trade_no", out_trade_no);
        params.put("type", type);
        params.put("name", name);
        params.put("money", money);
        params.put("return_url", return_url);
        params.put("notify_url", notify_url);
        params.put("trade_status", trade_status);

        String sign1 = ZlianPay.createSign(params, secret_key);

        if (sign1.equals(sign)) {
            String url = "/member/userinfo";
            response.sendRedirect(url);
        }
    }

    /**
     * @param request
     * @return
     */
    @ResponseBody
    @RateLimit(key = "#outTradeNo", count = 1, interval = "10s", message = "等待上一个回调处理完成")
    @RequestMapping("/member/yungouos/notify")
    public String notify(HttpServletRequest request) throws NoSuchAlgorithmException {
        Map<String, String> params = RequestParamsUtil.getParameterMap(request);
        String payNo = params.get("payNo");
        String code = params.get("code");
        String mchId = params.get("mchId");
        String orderNo = params.get("orderNo");
        String money = params.get("money");
        String outTradeNo = params.get("outTradeNo");
        String sign = params.get("sign");
        String payChannel = params.get("payChannel");
        String attach = params.get("attach");

        Map<String, String> map = new HashMap<>();
        map.put("code", code);
        map.put("orderNo", orderNo);
        map.put("outTradeNo", outTradeNo);
        map.put("payNo", payNo);
        map.put("money", money);
        map.put("mchId", mchId);

        String key = null;
        GradeOrders rechargeRecord = gradeOrdersService.getOne(new QueryWrapper<GradeOrders>().eq("member_id", outTradeNo));
        switch (payChannel) {
            //此处因为没启用独立密钥 支付密钥支付宝与微信支付是一样的 (密钥获取:登录 yungouos.com-》我的账户-》商户管理-》商户密钥)
            case "wxpay":
                Pays wxPays = paysService.getOne(new QueryWrapper<Pays>().eq("driver", "yungouos_wxpay"));

                /**
                 * 防止恶意回调
                 */
                if (!rechargeRecord.getPayType().equals(wxPays.getDriver())) {
                    return "Error Pperating!!!";
                }

                Map wxMap = JSON.parseObject(wxPays.getConfig());
                key = wxMap.get("key").toString();
                break;
            case "alipay":
                Pays alipays = paysService.getOne(new QueryWrapper<Pays>().eq("driver", "yungouos_alipay"));

                /**
                 * 防止恶意回调
                 */
                if (!rechargeRecord.getPayType().equals(alipays.getDriver())) {
                    return "Error Pperating!!!";
                }

                Map aliMap = JSON.parseObject(alipays.getConfig());
                key = aliMap.get("key").toString();
                break;
            default:
                break;
        }

        String mySign = createSign(map, key);
        if (mySign.equals(sign) && Integer.parseInt(code) == 1) {
            AtomicReference<String> notifyText = new AtomicReference<>();
            synchronizedByKeyService.exec(outTradeNo, () -> {
                String returnBig1 = returnBig(money, money, outTradeNo, payNo, attach, "SUCCESS", "FIALD");
                notifyText.set(returnBig1);
            });
            return notifyText.get();
        } else {
            //签名错误
            return "FIALD";
        }
    }

    /**
     * 虎皮椒支付通知
     *
     * @param request
     * @return
     */
    @RequestMapping("/member/xunhupay/notifyUrl")
    @RateLimit(key = "#trade_order_id", count = 1, interval = "10s", message = "等待上一个回调处理完成")
    @ResponseBody
    public String xunhuNotifyUrl(HttpServletRequest request) {
        // 记得 map 第二个泛型是数组 要取 第一个元素 即[0]
        Map<String, String> params = RequestParamsUtil.getParameterMap(request);
        Map<String, Object> map = new HashMap<>();
        for (Map.Entry<String, String> stringStringEntry : params.entrySet()) {
            map.put(stringStringEntry.getKey(), stringStringEntry.getValue());
        }
        String hash = params.get("hash");
        GradeOrders rechargeRecord = gradeOrdersService.getOne(new QueryWrapper<GradeOrders>().eq("member_id", params.get("trade_order_id")));
        String key = null;
        if (rechargeRecord.getPayType().equals("xunhupay_wxpay")) {
            Pays xunhuwxPays = paysService.getOne(new QueryWrapper<Pays>().eq("driver", "xunhupay_wxpay"));

            /**
             * 防止恶意回调
             */
            if (!rechargeRecord.getPayType().equals(xunhuwxPays.getDriver())) {
                return "Error Pperating!!!";
            }

            Map xunhuwxMap = JSON.parseObject(xunhuwxPays.getConfig());
            key = xunhuwxMap.get("appsecret").toString();
        } else if (rechargeRecord.getPayType().equals("xunhupay_alipay")) {
            Pays xunhualiPays = paysService.getOne(new QueryWrapper<Pays>().eq("driver", "xunhupay_alipay"));

            /**
             * 防止恶意回调
             */
            if (!rechargeRecord.getPayType().equals(xunhualiPays.getDriver())) {
                return "Error Pperating!!!";
            }

            Map xunhualiMap = JSON.parseObject(xunhualiPays.getConfig());
            key = xunhualiMap.get("appsecret").toString();
        }

        String sign = PayUtils.createSign(map, key);
        if (sign.equals(hash) && "OD".equals(params.get("status"))) {
            AtomicReference<String> notifyText = new AtomicReference<>();
            synchronizedByKeyService.exec(params.get("trade_order_id"), () -> {
                String returnBig1 = returnBig(params.get("total_fee"), params.get("total_fee"), params.get("trade_order_id"), params.get("transaction_id"), params.get("plugins"), "success", "fiald");
                notifyText.set(returnBig1);
            });
            return notifyText.get();
        } else {
            return "fiald";
        }
    }

    /**
     * 虎皮椒支付通知
     *
     * @param request
     * @return
     */
    @RequestMapping("/member/xunhupay/returnUrl")
    @ResponseBody
    public void xunhuReturnUrl(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 记得 map 第二个泛型是数组 要取 第一个元素 即[0]
        Map<String, String> params = RequestParamsUtil.getParameterMap(request);
        String url = "/member/userinfo";
        response.sendRedirect(url);
    }

    /**
     * 异步通知
     *
     * @param notifyDTO
     * @return
     */
    @RequestMapping("/member/payjs/notify")
    @RateLimit(key = "#out_trade_no", count = 1, interval = "10s", message = "等待上一个回调处理完成")
    @ResponseBody
    public Object payjsNotify(NotifyDTO notifyDTO) {
        Map<String, Object> notifyData = new HashMap<>();
        notifyData.put("return_code", notifyDTO.getReturn_code());
        notifyData.put("total_fee", notifyDTO.getTotal_fee());
        notifyData.put("out_trade_no", notifyDTO.getOut_trade_no());
        notifyData.put("payjs_order_id", notifyDTO.getPayjs_order_id());
        notifyData.put("transaction_id", notifyDTO.getTransaction_id());
        notifyData.put("time_end", notifyDTO.getTime_end());
        notifyData.put("openid", notifyDTO.getOpenid());
        notifyData.put("mchid", notifyDTO.getMchid());

        // options
        if (notifyDTO.getAttach() != null) {
            notifyData.put("attach", notifyDTO.getAttach());
        }
        if (notifyDTO.getType() != null) {
            notifyData.put("type", notifyDTO.getType());
        }

        String key = null;
        GradeOrders rechargeRecord = gradeOrdersService.getOne(new QueryWrapper<GradeOrders>().eq("member_id", notifyDTO.getOut_trade_no()));
        if (notifyDTO.getType() != null) { // 支付宝
            Pays aliPays = paysService.getOne(new QueryWrapper<Pays>().eq("driver", "payjs_alipay"));

            /**
             * 防止恶意回调
             */
            if (!rechargeRecord.getPayType().equals(aliPays.getDriver())) {
                return "Error Pperating!!!";
            }

            Map wxMap = JSON.parseObject(aliPays.getConfig());
            key = wxMap.get("key").toString();
        } else { // 微信
            Pays wxPays = paysService.getOne(new QueryWrapper<Pays>().eq("driver", "payjs_wxpay"));

            /**
             * 防止恶意回调
             */
            if (!rechargeRecord.getPayType().equals(wxPays.getDriver())) {
                return "Error Pperating!!!";
            }

            Map wxMap = JSON.parseObject(wxPays.getConfig());
            key = wxMap.get("key").toString();
        }

        String sign = SignUtil.sign(notifyData, key);
        if (sign.equals(notifyDTO.getSign())) {
            AtomicReference<String> notifyText = new AtomicReference<>();
            synchronizedByKeyService.exec(notifyDTO.getOut_trade_no(), () -> {
                String returnBig1 = returnBig(notifyDTO.getTotal_fee(), notifyDTO.getTotal_fee(), notifyDTO.getOut_trade_no(), notifyDTO.getTransaction_id(), notifyDTO.getAttach(), "success", "failure");
                notifyText.set(returnBig1);
            });
            return notifyText.get();
        } else {
            return "failure";
        }
    }

    /**
     * 微信官方异步通知
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping("/member/wxpay/notify")
    @RateLimit(key = "#out_trade_no", count = 1, interval = "10s", message = "等待上一个回调处理完成")
    @ResponseBody
    public String wxPayNotify(HttpServletRequest request, HttpServletResponse response) {
        String resXml = "";
        InputStream inStream;
        try {
            inStream = request.getInputStream();
            ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = inStream.read(buffer)) != -1) {
                outSteam.write(buffer, 0, len);
            }
            System.out.println("wxnotify:微信支付----start----");
            // 获取微信调用我们notify_url的返回信息
            String result = new String(outSteam.toByteArray(), "utf-8");
            System.out.println("wxnotify:微信支付----result----=" + result);

            // 关闭流
            outSteam.close();
            inStream.close();

            // xml转换为map
            Map<String, String> resultMap = WXPayUtil.xmlToMap(result);
            boolean isSuccess = false;
            String result_code = resultMap.get("result_code");
            String out_trade_no = resultMap.get("out_trade_no");// 商户系统内部订单号
            if ("SUCCESS".equals(result_code)) {
                Pays pays = paysService.getOne(new QueryWrapper<Pays>().eq("driver", "wxpay"));

                /**
                 * 防止恶意回调
                 */
                GradeOrders rechargeRecord = gradeOrdersService.getOne(new QueryWrapper<GradeOrders>().eq("member_id", out_trade_no));
                if (!rechargeRecord.getPayType().equals(pays.getDriver())) {
                    return "Error Pperating!!!";
                }

                Map mapTypes = JSON.parseObject(pays.getConfig());
                String key = mapTypes.get("key").toString(); // 密钥

                /**
                 * 签名成功
                 */
                if (WXPayUtil.isSignatureValid(resultMap, key)) {
                    String total_fee = resultMap.get("total_fee");// 订单总金额,单位为分
                    String transaction_id = resultMap.get("transaction_id");// 微信支付订单号
                    String attach = resultMap.get("attach");// 商家数据包,原样返回
                    String appid = resultMap.get("appid");// 微信分配的小程序ID

                    BigDecimal bigDecimal = new BigDecimal(total_fee);
                    BigDecimal multiply = bigDecimal.divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_DOWN);
                    String money = new DecimalFormat("0.##").format(multiply);
                    GradeOrders gradeOrders = gradeOrdersService.getOne(new QueryWrapper<GradeOrders>().eq("member_id", out_trade_no));
                    if (gradeOrders.getPayType().equals("wxpay")) {
                        AtomicReference<String> notifyText = new AtomicReference<>();
                        synchronizedByKeyService.exec(out_trade_no, () -> {
                            String returnBig1 = returnBig(money, money, out_trade_no, transaction_id, attach, WxpayresXml, resFailXml);
                            notifyText.set(returnBig1);
                        });
                        resXml = notifyText.get();
                    } else {
                        AtomicReference<String> notifyText = new AtomicReference<>();
                        synchronizedByKeyService.exec(out_trade_no, () -> {
                            String returnBig1 = returnBig(money, money, out_trade_no, transaction_id, attach, WxpayH5resXml, resFailXml);
                            notifyText.set(returnBig1);
                        });
                        resXml = notifyText.get();
                    }
                } else {
                    System.out.println("签名判断错误!!");
                }
            }
        } catch (Exception e) {
            System.out.println("wxnotify:支付回调发布异常:" + e);
        } finally {
            try {
                // 处理业务完毕
                BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
                out.write(resXml.getBytes());
                out.flush();
                out.close();
            } catch (IOException e) {
                System.out.println("wxnotify:支付回调发布异常:out:" + e);
            }
        }
        return resXml;
    }

    /**
     * 支付宝当面付 异步通知
     *
     * @param request 接收
     * @return 返回
     */
    @RequestMapping("/member/alipay/notify")
    @ResponseBody
    @SneakyThrows(Exception.class)
    public String alipayNotifyUrl(HttpServletRequest request) {
        Map<String, String> params = Maps.newHashMap();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (String name : requestParams.keySet()) {
            String[] values = requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决,这段代码在出现乱码时使用
            valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }

        String out_trade_no = params.get("out_trade_no");// 商户订单号
        GradeOrders gradeOrders = gradeOrdersService.getOne(new QueryWrapper<GradeOrders>().eq("member_id", out_trade_no));
        GradeOrders rechargeRecord = gradeOrdersService.getOne(new QueryWrapper<GradeOrders>().eq("member_id", out_trade_no));
        if ("alipay".equals(gradeOrders.getPayType())) {
            Pays pays = paysService.getOne(new QueryWrapper<Pays>().eq("driver", "alipay"));
            /**
             * 防止恶意回调
             */
            if (!rechargeRecord.getPayType().equals(pays.getDriver())) {
                return "Error Pperating!!!";
            }
        } else if ("alipay_pc".equals(gradeOrders.getPayType())) {
            Pays pays = paysService.getOne(new QueryWrapper<Pays>().eq("driver", "alipay_pc"));
            /**
             * 防止恶意回调
             */
            if (!rechargeRecord.getPayType().equals(pays.getDriver())) {
                return "Error Pperating!!!";
            }
        }
        Boolean verifyNotify = Factory.Payment.Common().verifyNotify(params);
        if (verifyNotify) {
            String total_amount = params.get("total_amount");// 付款金额
            String trade_no = params.get("trade_no");// 流水
            String receipt_amount = params.get("receipt_amount");// 实际支付金额
            String body = params.get("body");// 状态
            AtomicReference<String> notifyText = new AtomicReference<>();
            synchronizedByKeyService.exec(out_trade_no, () -> {
                String returnBig1 = returnBig(receipt_amount, total_amount, out_trade_no, trade_no, body, "success", "failure");
                notifyText.set(returnBig1);
            });
            return notifyText.get();
        } else {
            System.out.println("签名错误!!");
            return "failure";
        }
    }

    /**
     * 支付宝PC支付返回接口
     *
     * @param request
     * @param response
     * @throws IOException
     */
    @RequestMapping("/member/alipay/return_url")
    @SneakyThrows(Exception.class)
    public void alipayReturnUrl(HttpServletRequest request, HttpServletResponse response) {
        Map<String, String> params = Maps.newHashMap();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (String name : requestParams.keySet()) {
            String[] values = requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决,这段代码在出现乱码时使用
            valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }

        Boolean verifyNotify = Factory.Payment.Common().verifyNotify(params);
        // 验签成功
        if (verifyNotify) {
            String pay_no = params.get("trade_no"); // 流水号
            if (pay_no != null || pay_no != "") {
                String url = "/member/userinfo";
                response.sendRedirect(url);
            }
        } else {
            System.out.println("支付, 验签失败...");
        }
    }

    @RequestMapping(value = "/member/weidoufu/notifyUrl", method = RequestMethod.POST)
    @ResponseBody
    public String notifyUrl(@RequestBody NotifyEntity notifyEntity) {
        System.out.println("notifyEntity = " + notifyEntity);
        GradeOrders gradeOrders = gradeOrdersService.getOne(new QueryWrapper<GradeOrders>().eq("member_id", notifyEntity.getContent().getOut_order_no()));
        String secret_key = "";
        if (notifyEntity.getContent().getPay_type() == 1) {
            Pays wxPays = paysService.getOne(new QueryWrapper<Pays>().eq("driver", "weidoufu_wxpay"));
            if (!gradeOrders.getPayType().equals(wxPays.getDriver())) return "Error Pperating!!!";
            Map wxMap = JSON.parseObject(wxPays.getConfig());
            secret_key = wxMap.get("secret_key").toString();
        } else {
            Pays wxPays = paysService.getOne(new QueryWrapper<Pays>().eq("driver", "weidoufu_alipay"));
            if (!gradeOrders.getPayType().equals(wxPays.getDriver())) return "Error Pperating!!!";
            Map wxMap = JSON.parseObject(wxPays.getConfig());
            secret_key = wxMap.get("secret_key").toString();
        }
        String toJSONString = JSON.toJSONString(notifyEntity.getContent());
        String sha256_hmac = WeidouSignUtil.sha256_HMAC(toJSONString, secret_key);
        String newSign = SecureUtil.md5(sha256_hmac).toUpperCase();
        if (notifyEntity.getSign().equals(newSign)) {
            /**
             * 这里写业务
             */
            System.out.println("签名成功");
            ContentEntity entityContent = notifyEntity.getContent();
			AtomicReference<String> notifyText = new AtomicReference<>();
            synchronizedByKeyService.exec(entityContent.getOut_order_no(), () -> {
            	String returnBig1 = returnBig(gradeOrders.getMoney().toString(),
                        gradeOrders.getMoney().toString(),
                        entityContent.getOut_order_no(),
                        entityContent.getTransaction_id(),
                        entityContent.getAttach(), "ok", "error");
            	notifyText.set(returnBig1);
            });
            return notifyText.get();
        }
        return "ok";
    }

    /**
     * 取消订单
     *
     * @return
     */
    @GetMapping("/member/paypal/cancel")
    @ResponseBody
    public String cancelPay() {
        return "cancel";
    }

    /**
     * 完成支付
     *
     * @param paymentId
     * @param payerId
     * @param response
     * @return
     */
    @GetMapping("/member/paypal/success")
    @ResponseBody
    public String successPay(@RequestParam("paymentId") String paymentId, @RequestParam("PayerID") String payerId, HttpServletResponse response) {
        try {
            Pays pays = paysService.getOne(new QueryWrapper<Pays>().eq("driver", "paypal"));
            Map mapTypes = JSON.parseObject(pays.getConfig());
            String clientId = mapTypes.get("clientId").toString();
            String clientSecret = mapTypes.get("clientSecret").toString();
            Payment payment = PaypalSend.executePayment(clientId, clientSecret, paymentId, payerId);
            if (payment.getState().equals("approved")) {
                String member = null; // 订单号
                String total = null;  // 金额
                String pay_no = payment.getId();
                List<Transaction> transactions = payment.getTransactions();
                for (Transaction transaction : transactions) {
                    member = transaction.getDescription();
                    total = transaction.getAmount().getTotal(); // 实际付款金额
                }
                GradeOrders gradeOrders = gradeOrdersService.getOne(new QueryWrapper<GradeOrders>().eq("member_id", member));
                /**
                 * 防止恶意回调
                 */
                if (!gradeOrders.getPayType().equals(pays.getDriver())) {
                    return "Error Pperating!!!";
                }
                String returnBig = returnBig(total, gradeOrders.getMoney().toString(), member, pay_no, gradeOrders.getGradeId().toString(), "success", "failure");
                if (returnBig.equals("success")) {
                    response.sendRedirect("/search/order/" + member);
                } else {
                    response.sendRedirect("/search/order/" + member);
                }
            }
        } catch (PayPalRESTException | IOException e) {
            e.printStackTrace();
        }
        return "redirect:/";
    }

    @PostMapping("/member/tronapi/notifyUrl")
    @ResponseBody
    public JsonResult tronapi(TronApiNotify tronApiNotify) {
        GradeOrders gradeOrders = gradeOrdersService.getOne(Wrappers.<GradeOrders>lambdaQuery().eq(GradeOrders::getMemberId, tronApiNotify.getOrder_id()));
        Pays pays = paysService.getOne(new QueryWrapper<Pays>().eq("driver", "tronapi"));
        if (!gradeOrders.getPayType().equals(pays.getDriver())) {
            return JsonResult.error("错误!!");
        }
        Map wxMap = JSON.parseObject(pays.getConfig());
        String private_key = wxMap.get("private_key").toString();

        String signatureStr = tronApiNotify.getTransaction_token() +
                tronApiNotify.getOrder_id() +
                tronApiNotify.getAmount() +
                tronApiNotify.getCurrency() +
                tronApiNotify.getCoin_code() +
                tronApiNotify.getCoin_amount() +
                tronApiNotify.getHash() +
                private_key;

        String signatureThis = Helper.md5(signatureStr).toLowerCase();

        if (signatureThis.equals(tronApiNotify.getSignature())) {
            AtomicReference<String> notifyText = new AtomicReference<>();
            synchronizedByKeyService.exec(tronApiNotify.getOrder_id(), () -> {
                String returnBig1 = returnBig(gradeOrders.getMoney().toString(), gradeOrders.getMoney().toString(), tronApiNotify.getOrder_id(), tronApiNotify.getTransaction_token(), "", "success", "failure");
                notifyText.set(returnBig1);
            });
            if (notifyText.get().equals("success")) {
                return JsonResult.ok("ok").setCode(200);
            } else {
                return JsonResult.ok("遇到错误").setCode(500);
            }
        } else {
            return JsonResult.error("签名错误");
        }
    }

    @PostMapping("/member/epusdt/notifyUrl")
    @ResponseBody
    public String epusdt(@RequestBody EpusdtNotify epusdtNotify) {
        epusdtNotify.setAmount(epusdtNotify.getAmount().setScale(2, RoundingMode.HALF_UP).stripTrailingZeros().stripTrailingZeros());
        GradeOrders gradeOrders = gradeOrdersService.getOne(Wrappers.<GradeOrders>lambdaQuery().eq(GradeOrders::getMemberId, epusdtNotify.getOrder_id()));
        Pays pays = paysService.getOne(new QueryWrapper<Pays>().eq("driver", "epusdt"));
        if (!gradeOrders.getPayType().equals(pays.getDriver())) {
            return "error!";
        }
        Map mapTypes = JSON.parseObject(pays.getConfig());
        String key = mapTypes.get("key").toString();
        String sign = sendPay.createSign(epusdtNotify, key);
        if (sign.equals(epusdtNotify.getSignature())) {
            AtomicReference<String> notifyText = new AtomicReference<>();
            synchronizedByKeyService.exec(epusdtNotify.getOrder_id(), () -> {
                String returnBig = returnBig(gradeOrders.getMoney().toString(),
                        gradeOrders.getMoney().toString(), epusdtNotify.getOrder_id(),
                        epusdtNotify.getTrade_id(),"","ok", "fail");
                notifyText.set(returnBig);
            });
            return notifyText.get();
        }
        return "fail";
    }

    @RequestMapping("/member/epusdt/returnUrl")
    @ResponseBody
    public void epusdtReturnUrl(String order_id, HttpServletResponse response) throws IOException {
        String url = "/member/vip";
        response.sendRedirect(url);
    }

    /**
     * 业务处理
     *
     * @param money   实收款金额
     * @param price   订单金额
     * @param payId   订单号
     * @param pay_no  流水号
     * @param param   自定义内容
     * @param success 返回成功
     * @param fiald   返回失败
     * @return this
     */
    private String returnBig(String money, String price, String payId, String pay_no, String param, String success, String fiald) {
        GradeOrders gradeOrders = gradeOrdersService.getOne(new QueryWrapper<GradeOrders>().eq("member_id", payId));
        if (ObjectUtils.isEmpty(gradeOrders)) {
            return fiald;
        }
        if (gradeOrders.getStatus() == 1) {
            return success;
        }
        GradeOrders gradeOrders1 = new GradeOrders();
        gradeOrders1.setId(gradeOrders.getId());
        gradeOrders1.setStatus(1);
        gradeOrders1.setPayNo(pay_no);
        gradeOrders1.setMoney(new BigDecimal(money));
        gradeOrders1.setPayTime(new Date());

        if (this.gradeOrdersService.updateById(gradeOrders1)) {
            this.userGradeMapper.delete((Wrapper)(new QueryWrapper()).eq("user_id", gradeOrders.getUserId()));
            this.userGradeMapper.insertOne(gradeOrders.getUserId(), gradeOrders.getGradeId(), gradeOrders.getExpireTime());
            UserGrade userGrade = this.userGradeMapper.selectOne((Wrapper)(new QueryWrapper()).eq("user_id", gradeOrders.getUserId()));
            UserGradeBo userGrade1 = new UserGradeBo(userGrade.getId(), userGrade.getUserId(), userGrade.getGradeId(), userGrade.getCreateTime(), userGrade.getUpdateTime(), userGrade.getExpireTime());
            DelayQueueConfig.queue.add(userGrade1);
            return success;
        } else {
            return fiald;
        }
    }

    @GetMapping("/member/order/state/{orderid}")
    @ResponseBody
    public JsonResult state(@PathVariable("orderid") String orderid) {
        GradeOrders gradeOrders = gradeOrdersService.getOne(new QueryWrapper<GradeOrders>().eq("id", orderid));
        if (gradeOrders.getStatus() == 1) {
            return JsonResult.ok().setCode(200).setData(1);
        } else {
            return JsonResult.ok().setData(0);
        }
    }

    public static String packageSign(Map<String, String> params, boolean urlEncoder) {
        // 先将参数以其参数名的字典序升序进行排序
        TreeMap<String, String> sortedParams = new TreeMap<String, String>(params);
        // 遍历排序后的字典,将所有参数按"key=value"格式拼接在一起
        StringBuilder sb = new StringBuilder();
        boolean first = true;
        for (Map.Entry<String, String> param : sortedParams.entrySet()) {
            String value = param.getValue();
            if (org.apache.commons.lang3.StringUtils.isBlank(value)) {
                continue;
            }
            if (first) {
                first = false;
            } else {
                sb.append("&");
            }
            sb.append(param.getKey()).append("=");
            if (urlEncoder) {
                try {
                    value = urlEncode(value);
                } catch (UnsupportedEncodingException e) {
                }
            }
            sb.append(value);
        }
        return sb.toString();
    }

    public static String urlEncode(String src) throws UnsupportedEncodingException {
        return URLEncoder.encode(src, Charsets.UTF_8.name()).replace("+", "%20");
    }

    public static String createSign(Map<String, String> params, String partnerKey) throws NoSuchAlgorithmException {
        // 生成签名前先去除sign
        params.remove("sign");
        String stringA = packageSign(params, false);
        String stringSignTemp = stringA + "&key=" + partnerKey;

        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update((stringSignTemp).getBytes());
        String mySign = new BigInteger(1, md.digest()).toString(16).toUpperCase();
        if (mySign.length() != 32) {
            mySign = "0" + mySign;
        }
        return mySign;
    }

}

最后我再强调一下:学过网站搭建的很容易上手操作,但是如果没有做网站经验的小伙伴可能需要费点精力了,如果需要我帮你来完成搭建的,可以找我。

这里一个不务正业的程序员,广交天下好友。

祝大家发财,需要源码到公众号找我

  • 28
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值