八爪鱼现金流-019-个人对接付出,个人网站付出办理方案 ...

打印 上一主题 下一主题

主题 639|帖子 639|积分 1917

配景:
随着用户量不断增长,服务器本钱越来越大。想着实现会员制回点服务器本钱。
业务场景分析:
用户在站点上付款 -----> 我监听到付款金额 -----> 给用户开通会员
调研:

  • 付出宝和微信官方付出接口:基本都必要企业资格才能开通,最起码也要是个体工商户才可以(有营业执照)
  • 第三方付出平台:比方图灵付出,xpay等,支持个人开发者,但是手续费太高。
  • 野路子:网上有开源方案是监听付出宝app收款关照,实现收款,比方PaysApi、绿点付出等,本质上依然是采取挂机监听的计谋,但针对的是移动端付出宝或微信的收款关照消息,本钱高,配置麻烦,需24小时挂台安卓手机,难免费。
  • 使用第三方卡密平台进行发卡。因为手续费、提现规则等各种原因放弃。
调研效果:
付出宝当面付:支持个人开通,但是必要门店照片,这个百度就可以
营业执照是可选的,不上传的话,限制单笔收款≤1000,单日收款≤5W,对于个人开发者足够了。

效果图:

二维码付出成功后,实行本身的业务逻辑。比方给用户开通会员。
昵称金色展示。

接入流程:
1.点击这里进入,登陆付出宝账户选择立即接入。
2.经营内容选择百货零售-超市-超市(非平台类)
3.营业执照可不上传
4.店铺招牌 百度即可
5.提交申请后十多分钟就可收到通过关照。
可参考这个同砚的文章:【应用申请开通和配置】
开发流程:
成功接入以后,可以在蚂蚁金服开放平台 网页&移动应用中,看到我的应用列表中多了一个“应用2.0签约******”的应用: 或者是你本身起名字的应用

现在我们可以开发接入了,总体分为以下几个步骤(参考当面付文档 ,当面付开发流程):


  • 配置当面付公钥私钥
    找到 你的 应用,点击右侧查看详情

  • 在应用信息中设置公钥

    付出宝官方提供了密钥生成工具,很简单,使用工具生成应用公钥和私钥,应用公钥设置到付出宝,应用私钥保存到当地,应用公钥设置到付出宝后,付出宝会生成一个付出宝公钥,保存到当地。具体拜见这里
  • 回调地址配置

总结:
借鉴三个同砚的文章 + 并结合GPT4调试代码 + 返回base64码方便前端展示。 改造优化:
【本身个人拥有一个可以付出功能的网站?固然可以了!保姆级演示!】
【个人付出方案(免签约)-付出宝当面付】
【zxing生成二维码】
结合GPT4,代码报错改造优化
java.lang.UnsatisfiedLinkError: /usr/local/java/jdk1.8.0_152/jre/lib/amd64/libawt_xawt.so: libXrender.so.1: cannot open shared object file: No such file or directory
oro.sprinofrananork.neb.util.mestedserletEexception: Hanmer dispatch faled; nested exception is famna.amt.Eropr: can’t comet to xll window sener usin0 "locahost:10.0 as the vawe of the DIspl variabl
简单示例代码:
示例重要流程代码。后续优化,可自行调整,好比,金额配置到数据库或者配置中心,金额校验。 为简化,只贴出重要代码。请自行继承优化。
1.Maven引入必要的jar包
  1. <!--alipay SDK-->
  2. <dependency>
  3.         <groupId>com.alipay.sdk</groupId>
  4.         <artifactId>alipay-sdk-java</artifactId>
  5.         <version>4.35.9.ALL</version>
  6. </dependency>
  7. <!-- zxing -->
  8. <dependency>
  9.         <groupId>com.google.zxing</groupId>
  10.         <artifactId>core</artifactId>
  11.         <version>3.5.1</version>
  12. </dependency>
复制代码
2.Controller代码
  1. package com.kaihang.my.money.web.admin.web.controller;
  2. import com.alipay.api.AlipayApiException;
  3. import com.alipay.api.internal.util.AlipaySignature;
  4. import com.kaihang.my.money.dao.entity.TbUser;
  5. import com.kaihang.my.money.dao.entity.TbUserOrder;
  6. import com.kaihang.my.money.dao.entity.TbUserOrderExample;
  7. import com.kaihang.my.money.dao.mapper.TbUserOrderMapper;
  8. import com.kaihang.my.money.web.admin.util.AliPayUtil;
  9. import lombok.extern.slf4j.Slf4j;
  10. import org.springframework.beans.factory.annotation.Autowired;
  11. import org.springframework.stereotype.Controller;
  12. import org.springframework.util.CollectionUtils;
  13. import org.springframework.web.bind.annotation.RequestMapping;
  14. import org.springframework.web.bind.annotation.RequestMethod;
  15. import org.springframework.web.bind.annotation.ResponseBody;
  16. import javax.servlet.http.HttpServletRequest;
  17. import java.util.Base64;
  18. import java.util.Date;
  19. import java.util.HashMap;
  20. import java.util.Iterator;
  21. import java.util.List;
  22. import java.util.Map;
  23. /**
  24. * 支付回调接口
  25. */
  26. @Slf4j
  27. @Controller
  28. public class AliPayController {
  29.     @Autowired
  30.     private TbUserOrderMapper tbUserOrderMapper;
  31.     @RequestMapping(value = "/alipay/queryCode",method = RequestMethod.POST)
  32.     @ResponseBody
  33.     public HashMap<String,String> queryCode(HttpServletRequest request,TbUser tbUser){
  34.         HashMap<String,String> resultMap = new HashMap<>();
  35.         String onemonthVal = createQcode("八爪鱼1个月会员","onemonth","5",tbUser);
  36.         resultMap.put("onemonth",onemonthVal);
  37.         String threemonthVal = createQcode("八爪鱼3个月会员","threemonth","15",tbUser);
  38.         resultMap.put("threemonth",threemonthVal);
  39.         // 55元
  40.         String oneyearVal = createQcode("八爪鱼1年会员","oneyear","55",tbUser);
  41.         resultMap.put("oneyear",oneyearVal);
  42.         return resultMap;
  43.     }
  44.     public String createQcode(String productName,String productPrefix,String totalPrice,TbUser tbUser){
  45.         //自己生成一个订单号,我这里直接用时间戳演示,正常情况下创建完订单需要存储到自己的业务数据库,做记录和支付完成后校验
  46.         //  前缀pay    +  1个月的会员onemonth   +userId + 加时间戳
  47.         String orderNo = "pay"+productPrefix+tbUser.getId() + System.currentTimeMillis();
  48.         Date now = new Date();
  49.         // 保存到自己设计的订单表 order ,可自己设计。
  50.         saveUserOrder(productName,orderNo,totalPrice,tbUser,now);
  51.         // 获取到静态资源的绝对路径
  52.         // String logoPath = servletContext.getRealPath("/static/assets/img/logo1.jpg");
  53.         String logoPath = ""; //传递空就行,没必要加logo
  54.         byte[] qRcode = AliPayUtil.getQRcode(productName, orderNo, totalPrice, logoPath);
  55.         return Base64.getEncoder().encodeToString(qRcode);
  56.     }
  57.     public boolean saveUserOrder(String productName,String orderNo,String totalPrice,TbUser tbUser,Date now){
  58.         TbUserOrder userOrder = new TbUserOrder();
  59.         userOrder.setUserId(tbUser.getId()+"");
  60.         userOrder.setUserEmail(tbUser.getEmail());
  61.         userOrder.setTotalPrice(totalPrice);
  62.         userOrder.setOrderNo(orderNo);
  63.         userOrder.setProductName(productName);
  64.         userOrder.setBuyTime(now);
  65.         userOrder.setCreateTime(now);
  66.         userOrder.setOrderStatus("新建未支付");
  67.         userOrder.setValidInd("1");
  68.         int insert = tbUserOrderMapper.insert(userOrder);
  69.         // 如果大于0,保存成功,返回true
  70.         return insert>0;
  71.     }
  72.     /**
  73.      * 支付成功回调接口
  74.      * @return
  75.      */
  76.     @RequestMapping(value = "/alipay/bazhuayu/callback",method = RequestMethod.POST)
  77.     public Object callback(HttpServletRequest request){
  78.         log.info("【===支付宝回调开始===】");
  79.         Map<String, String> params = new HashMap<>();
  80.         Map requestParams = request.getParameterMap();
  81.         for(Iterator iter = requestParams.keySet().iterator(); iter.hasNext();){
  82.             String name = (String)iter.next();
  83.             String[] values = (String[]) requestParams.get(name);
  84.             String valueStr = "";
  85.             for(int i=0; i<values.length;i++){
  86.                 valueStr = (i == values.length-1) ? valueStr + values[i] : valueStr + values[i] + ",";
  87.             }
  88.             params.put(name,valueStr);
  89.         }
  90.         log.info("支付宝回调: sign:{}, trade_status:{}, 参数:{}",params.get("sign"),params.get("trade_status"),params.toString());
  91.         //验证回调的正确性:是不是支付宝发的
  92.         String alipayPublicKey = "xxxxxxxxxxxx"; // 你的支付宝公钥。TODO 替换为你自己的支付宝公钥!!!!
  93.         String signType = "RSA2";
  94.         params.remove("sign_type");
  95.         try {
  96.             //这里使用的是支付宝提供的验签方式
  97.             boolean alipayRSACheckedV2 = AlipaySignature.rsaCheckV2(params, alipayPublicKey,"utf-8",signType);
  98.             if(!alipayRSACheckedV2) {
  99.                 // return ServerResponse.createByErrorMessage("非法请求,验证不通过!");
  100.                 // throw new RuntimeException("非法请求,验证不通过!");
  101.                 log.info("非法请求,验证不通过!");
  102.                 return "failed";
  103.             }
  104.         } catch (AlipayApiException e) {
  105.             log.error("支付宝回调异常",e);
  106.         }
  107.         //订单支付后修改订单状态
  108.         // 订单金额,订单号 out_trade_no=payoneyear81714208576353 订单状态修改。同时给开通对应的会员天数
  109.         String outTradeNo = params.get("out_trade_no");
  110.         String totalAmount = params.get("total_amount");
  111.         TbUserOrderExample example = new TbUserOrderExample();
  112.         example.createCriteria().andValidIndEqualTo("1").andOrderNoEqualTo(outTradeNo);
  113.         List<TbUserOrder> tbUserOrders = tbUserOrderMapper.selectByExample(example);
  114.         if(!CollectionUtils.isEmpty(tbUserOrders)){
  115.             TbUserOrder tbUserOrder = tbUserOrders.get(0);
  116.             if(null != tbUserOrder){
  117.                 String totalPrice = tbUserOrder.getTotalPrice();
  118.                 // 校验金额
  119.                 if(totalPrice.equals(totalAmount)){
  120.                     // 旧的支付状态
  121.                     String oldOrderStatus = tbUserOrder.getOrderStatus();
  122.                     tbUserOrder.setOrderStatus("支付成功");
  123.                     tbUserOrderMapper.updateByPrimaryKey(tbUserOrder);
  124.                     // 成功之后,会员的,添加会员时间
  125.                     TbUser tbUser = addHuiYuan(tbUserOrder,oldOrderStatus);
  126.                     //返回支付状态给支付宝,避免支付宝重复通知
  127.                     return "TRADE_SUCCESS";
  128.                 }
  129.             }
  130.         }
  131.         return "failed";
  132.     }
  133.     public TbUser addHuiYuan(TbUserOrder tbUserOrder,String oldOrderStatus){
  134.         // 增加会员天数
  135.         // TODO 这里写你自己的业务处理逻辑。回调之后执行会到这里。
  136.         return null;
  137.     }
  138. }
复制代码
3.AliPayUtil工具类
  1. package com.kaihang.my.money.web.admin.util;
  2. /**
  3. * @Description: 支付宝-面对面支付
  4. *
  5. * @Author:
  6. * @Date: 2024-04-23 16:09:33
  7. */
  8. import com.alipay.easysdk.factory.Factory;
  9. import com.alipay.easysdk.kernel.BaseClient;
  10. import com.alipay.easysdk.payment.facetoface.models.AlipayTradePrecreateResponse;
  11. import org.slf4j.Logger;
  12. import org.slf4j.LoggerFactory;
  13. import javax.imageio.ImageIO;
  14. import java.awt.image.BufferedImage;
  15. import java.io.ByteArrayOutputStream;
  16. public class AliPayUtil {
  17.     private static Logger logger = LoggerFactory.getLogger(AliPayUtil.class);
  18.     public static byte[] getQRcode(String subject, String orderNo, String totalAmount,String logoPath) {
  19.         // 1. 设置参数(全局只需设置一次)
  20.         Factory.setOptions(getOptions());
  21.         try {
  22.             // 2. 发起API调用(使用面对面支付中的预下单)
  23.             AlipayTradePrecreateResponse response = Factory.Payment.FaceToFace().
  24.                     preCreate(subject,orderNo, totalAmount);
  25.             // 3. 处理响应或异常
  26.             if ("10000".equals(response.code)) {
  27.                 logger.info("调用成功:{}",response.qrCode);
  28.                 //获取生成的二维码,这里是一个String字符串,即二维码的内容;
  29.                 //然后用二维码生成SDK生成一下二维码,弄成图片返回给前端就行,我这里使用Zxing生成
  30.                 //其实也可以直接把这个字符串信息返回,让前端去生成,一样的道理,只需要关心这个二维码的内容就行
  31.                 String qrCode = response.qrCode;
  32.                 //生成支付二维码图片
  33.                 BufferedImage image = QRCodeUtil.createImage(qrCode,logoPath,true);
  34.                 ByteArrayOutputStream out = new ByteArrayOutputStream();
  35.                 ImageIO.write(image, "jpeg", out);
  36.                 byte[] b = out.toByteArray();
  37.                 out.write(b);
  38.                 out.close();
  39.                 //最终返回图片
  40.                 return b;
  41.             } else {
  42.                 logger.error("调用失败,原因:{},{}",response.msg,response.subMsg);
  43.             }
  44.         } catch (Exception e) {
  45.             logger.error("调用遭遇异常,原因:{}",e.getMessage());
  46.             throw new RuntimeException(e.getMessage(), e);
  47.         }
  48.         return null;
  49.     }
  50.     private static BaseClient.Config getOptions() {
  51.         BaseClient.Config config = new BaseClient.Config();
  52.         config.protocol = "https";
  53.         config.gatewayHost = "openapi.alipay.com";
  54.         config.signType = "RSA2";
  55.         // 请更换为您的AppId
  56.         config.appId = "xxxxxxxxxx"; // 请替换为您的AppId
  57.         // 请更换为您的PKCS8格式的应用私钥
  58.         config.merchantPrivateKey = "应用私钥RSA2048-敏感数据,请妥善保管xxxxxxxxxx"; // TODO 替换为你的支付宝私钥
  59.         // 支付宝公钥
  60.         config.alipayPublicKey = "xxxxxxxx"; // TODO 替换为你的支付宝公钥
  61.         config.notifyUrl = "https://你的域名/alipay/bazhuayu/callback";//这里是支付宝接口回调地址  成功后会调用AliPayController的callback方法
  62.         return config;
  63.     }
  64. }
复制代码
4.QRCodeUtil工具类
  1. package com.kaihang.my.money.web.admin.util;
  2. import com.google.zxing.BinaryBitmap;
  3. import com.google.zxing.DecodeHintType;
  4. import com.google.zxing.MultiFormatReader;
  5. import com.google.zxing.Result;
  6. import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
  7. import com.google.zxing.common.HybridBinarizer;
  8. import javax.imageio.ImageIO;
  9. import java.awt.image.BufferedImage;
  10. import java.io.File;
  11. import java.io.OutputStream;
  12. import java.util.Hashtable;
  13. import java.util.Random;
  14. /**
  15. * @Description: 生成二维码
  16. * @Author: 29489
  17. * @Date: 2024-04-23 17:41:42
  18. */
  19. public class QRCodeUtil {
  20.     private static final String CHARSET = "utf-8";
  21.     private static final String FORMAT = "JPG";
  22.     // 二维码尺寸
  23.     private static final int QRCODE_SIZE = 300;
  24.     // LOGO宽度
  25.     private static final int LOGO_WIDTH = 60;
  26.     // LOGO高度
  27.     private static final int LOGO_HEIGHT = 60;
  28.     public static BufferedImage createImage(String content, String logoPath, boolean needCompress) throws Exception {
  29.         BufferedImage result = QRCodeGenerator.generateQRCodeImage(content);
  30.         return result;
  31.     }
  32.     /**
  33.      * 生成二维码(内嵌LOGO)
  34.      * 二维码文件名随机,文件名可能会有重复
  35.      *
  36.      * @param content
  37.      *            内容
  38.      * @param logoPath
  39.      *            LOGO地址
  40.      * @param destPath
  41.      *            存放目录
  42.      * @param needCompress
  43.      *            是否压缩LOGO
  44.      * @throws Exception
  45.      */
  46.     public static String encode(String content, String logoPath, String destPath, boolean needCompress) throws Exception {
  47.         BufferedImage image = QRCodeUtil.createImage(content, logoPath, needCompress);
  48.         mkdirs(destPath);
  49.         String fileName = new Random().nextInt(99999999) + "." + FORMAT.toLowerCase();
  50.         ImageIO.write(image, FORMAT, new File(destPath + "/" + fileName));
  51.         return fileName;
  52.     }
  53.     /**
  54.      * 生成二维码(内嵌LOGO)
  55.      * 调用者指定二维码文件名
  56.      *
  57.      * @param content
  58.      *            内容
  59.      * @param logoPath
  60.      *            LOGO地址
  61.      * @param destPath
  62.      *            存放目录
  63.      * @param fileName
  64.      *            二维码文件名
  65.      * @param needCompress
  66.      *            是否压缩LOGO
  67.      * @throws Exception
  68.      */
  69.     public static String encode(String content, String logoPath, String destPath, String fileName, boolean needCompress) throws Exception {
  70.         BufferedImage image = QRCodeUtil.createImage(content, logoPath, needCompress);
  71.         mkdirs(destPath);
  72.         fileName = fileName.substring(0, fileName.indexOf(".")>0?fileName.indexOf("."):fileName.length())
  73.                 + "." + FORMAT.toLowerCase();
  74.         ImageIO.write(image, FORMAT, new File(destPath + "/" + fileName));
  75.         return fileName;
  76.     }
  77.     /**
  78.      * 当文件夹不存在时,mkdirs会自动创建多层目录,区别于mkdir.
  79.      * (mkdir如果父目录不存在则会抛出异常)
  80.      * @param destPath
  81.      *            存放目录
  82.      */
  83.     public static void mkdirs(String destPath) {
  84.         File file = new File(destPath);
  85.         if (!file.exists() && !file.isDirectory()) {
  86.             file.mkdirs();
  87.         }
  88.     }
  89.     /**
  90.      * 生成二维码(内嵌LOGO)
  91.      *
  92.      * @param content
  93.      *            内容
  94.      * @param logoPath
  95.      *            LOGO地址
  96.      * @param destPath
  97.      *            存储地址
  98.      * @throws Exception
  99.      */
  100.     public static String encode(String content, String logoPath, String destPath) throws Exception {
  101.         return QRCodeUtil.encode(content, logoPath, destPath, false);
  102.     }
  103.     /**
  104.      * 生成二维码
  105.      *
  106.      * @param content
  107.      *            内容
  108.      * @param destPath
  109.      *            存储地址
  110.      * @param needCompress
  111.      *            是否压缩LOGO
  112.      * @throws Exception
  113.      */
  114.     public static String encode(String content, String destPath, boolean needCompress) throws Exception {
  115.         return QRCodeUtil.encode(content, null, destPath, needCompress);
  116.     }
  117.     /**
  118.      * 生成二维码
  119.      *
  120.      * @param content
  121.      *            内容
  122.      * @param destPath
  123.      *            存储地址
  124.      * @throws Exception
  125.      */
  126.     public static String encode(String content, String destPath) throws Exception {
  127.         return QRCodeUtil.encode(content, null, destPath, false);
  128.     }
  129.     /**
  130.      * 生成二维码(内嵌LOGO)
  131.      *
  132.      * @param content
  133.      *            内容
  134.      * @param logoPath
  135.      *            LOGO地址
  136.      * @param output
  137.      *            输出流
  138.      * @param needCompress
  139.      *            是否压缩LOGO
  140.      * @throws Exception
  141.      */
  142.     public static void encode(String content, String logoPath, OutputStream output, boolean needCompress)
  143.             throws Exception {
  144.         BufferedImage image = QRCodeUtil.createImage(content, logoPath, needCompress);
  145.         ImageIO.write(image, FORMAT, output);
  146.     }
  147.     /**
  148.      * 生成二维码
  149.      *
  150.      * @param content
  151.      *            内容
  152.      * @param output
  153.      *            输出流
  154.      * @throws Exception
  155.      */
  156.     public static void encode(String content, OutputStream output) throws Exception {
  157.         QRCodeUtil.encode(content, null, output, false);
  158.     }
  159.     /**
  160.      * 解析二维码
  161.      *
  162.      * @param file
  163.      *            二维码图片
  164.      * @return
  165.      * @throws Exception
  166.      */
  167.     public static String decode(File file) throws Exception {
  168.         BufferedImage image;
  169.         image = ImageIO.read(file);
  170.         if (image == null) {
  171.             return null;
  172.         }
  173.         BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);
  174.         BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
  175.         Result result;
  176.         Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();
  177.         hints.put(DecodeHintType.CHARACTER_SET, CHARSET);
  178.         result = new MultiFormatReader().decode(bitmap, hints);
  179.         String resultStr = result.getText();
  180.         return resultStr;
  181.     }
  182.     /**
  183.      * 解析二维码
  184.      *
  185.      * @param path
  186.      *            二维码图片地址
  187.      * @return
  188.      * @throws Exception
  189.      */
  190.     public static String decode(String path) throws Exception {
  191.         return QRCodeUtil.decode(new File(path));
  192.     }
  193. }
复制代码
5.前端代码
  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <!DOCTYPE html>
  3. <html>
  4. <head>
  5.   <title>八爪鱼官网-会员购买页面</title>
  6.   <meta charset="utf-8">
  7.   <meta http-equiv="X-UA-Compatible" content="IE=edge">
  8.   <!-- SEO 关键字 -->
  9.   <meta name="keywords" content="八爪鱼,财务自由,财务,财务自由之路,什么叫财务自由,财务自由需要多少资产,什么叫被动收入,打造被动收入,增加被动收入,怎样获得被动收入,价值投资,个人资产管理,理财,躺着赚钱,让钱为我打工,市场风云">
  10.   <meta name="description" content="个人资产管理平台,帮助您打造被动收入,发现投资机会,助力实现财务自由。财务自由、被动收入、个人资产管理、价值投资平台">
  11.   <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
  12.   <style>
  13.     * {
  14.       box-sizing: border-box;
  15.     }
  16.     body {
  17.       font-family: 'Arial', sans-serif;
  18.       background-color: #1a1a1a; /* 页面的背景色 */
  19.       color: #ccc; /* 文字颜色 */
  20.       margin: 0;
  21.       padding: 0;
  22.       display: flex;
  23.       flex-direction: column; /* 使导航栏在顶部 */
  24.     }
  25.     .navbar {
  26.       position: relative; /* 如果之前没有设置,现在需要设置为相对定位 */
  27.       background-color: #202020; /* 导航栏背景色 */
  28.       padding: 10px 20px;
  29.       display: flex;
  30.       justify-content: space-between; /* 企业名称和导航项分开 */
  31.       align-items: center;
  32.     }
  33.     .navbar .logo {
  34.       color: #fff;
  35.       font-weight: bold; /* 企业名称字体加粗 */
  36.       font-size: 24px;
  37.     }
  38.     /* 确保主内容区域有足够的下边距,以免被固定位置的footer遮挡 */
  39.     .main-content {
  40.       margin-top: 50px; /* 导航栏的高度 */
  41.       padding-bottom: 40px; /* 根据新的footer高度调整,确保内容可见 */
  42.     }
  43.     /* 其他样式保持不变 */
  44.     .main-content {
  45.       display: flex;
  46.       justify-content: center;
  47.       align-items: center;
  48.       flex-direction: column;
  49.       height: 100vh; /* 确保 .main-content 高度充满视口,以便居中 */
  50.       text-align: center; /* 文本居中 */
  51.       color: #FFFFFF; /* 设置文字颜色为亮白色 */
  52.     }
  53.     /* 保持原有的logo样式,现在应用于a标签 */
  54.     .logo {
  55.       color: #fff;
  56.       font-weight: bold; /* 企业名称字体加粗 */
  57.       font-size: 24px;
  58.       text-decoration: none; /* 去除链接下划线 */
  59.       display: inline-block; /* 或其他适合的显示方式,确保布局正确 */
  60.     }
  61.     /* 可选:指定鼠标悬停在logo上时的样式,例如改变颜色 */
  62.     .logo:hover {
  63.       color: #e0e0e0; /* 鼠标悬停时的颜色,可自定义 */
  64.     }
  65.     .qr-codes-container {
  66.       display: flex;
  67.       justify-content: center; /* 子元素水平居中 */
  68.       flex-wrap: wrap; /* 允许子元素在容器满时换行 */
  69.       gap: 20px; /* 子元素之间的间隔 */
  70.       width: 100%; /* 充满父容器宽度 */
  71.       max-width: 1200px; /* 最大宽度,根据需要调整 */
  72.       margin: 137px 20px auto; /* 上下保持20px,左右auto使得容器居中 */
  73.     }
  74.     .qr-code {
  75.       text-align: center;
  76.       /* Add additional styling as needed */
  77.     }
  78.     /* 二维码图片的样式,根据需要增加尺寸 */
  79.     .qr-code img {
  80.       width: 250px; /* 图片宽度,根据需要调整 */
  81.       height: auto; /* 高度自动,保持图片比例 */
  82.     }
  83.     /* 二维码描述的样式 */
  84.     .qr-code p {
  85.       color: #ffffff; /* 保持文字颜色为白色 */
  86.       font-size: 1rem; /* 调整字体大小为1rem,根据需要调整 */
  87.     }
  88.   </style>
  89. </head>
  90. <body>
  91. <div class="navbar">
  92.   <a href="/moneyTotal" class="logo">八爪鱼</a>
  93. </div>
  94. <div class="main-content">
  95.   <p>注:此页面暂时不自动跳转,购买支付成功后,请您重新登录网站!!!</p>
  96.   <p style="font-size: 14px">如有其他问题请邮件联系我们:294894616@qq.com</p>
  97.   <div class="qr-codes-container">
  98.     <div class="qr-code">
  99.       <img src="data:image/png;base64,${onemonth}" alt="八爪鱼1个月会员(5元)"/>
  100.       <p>1个月会员(5元)</p>
  101.     </div>
  102.     <div class="qr-code">
  103.       <img src="data:image/png;base64,${threemonth}" alt="八爪鱼3个月会员(15元)"/>
  104.       <p>3个月会员(15元)</p>
  105.     </div>
  106.     <div class="qr-code">
  107.       <img src="data:image/png;base64,${oneyear}" alt="八爪鱼1年会员(55元)"/>
  108.       <p>1年会员(55元)</p>
  109.     </div>
  110.     <p style="font-size: 14px; color: #f39c12">会员权益:尊享金色会员标识。月报、资产包、负债包、机会卡额度限制放开。</p>
  111.   </div>
  112. </div>
  113. </body>
  114. </html>
复制代码
八爪鱼现金流

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

耶耶耶耶耶

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表