吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1463|回复: 23
收起左侧

[学习记录] 结合AI+PHPMailer-master.zip实现的扫码开票系统

  [复制链接]
kissfox 发表于 2026-7-17 11:31
最近公司接到客户投诉,说在我们公司停车场停车后缴纳了停车费,可没有提供发票。
根据公司要求要实现扫码开票功能,可停车系统要实现扫码开票,必须缴纳对接服务费一年几百上千元。为了节省下来对接服务费,我结合AI编写UI界面,实现扫码后填写开票信息发送至后端制定邮箱来开票。

采用的PHP+PHPmailer+QQ邮箱发送接收来实现扫码开票
功能介绍:
扫码后进入停车开票助手
填写开票信息及上传缴费截图凭证
提交发送至后端指定财务邮箱
财务邮箱收到邮件后开票发送至缴费者
扫码开票系统.rar (147.62 KB, 下载次数: 63)
image.png
修改send_email.php文件中的*****星号区域
// ================================================================
//  📧 邮件配置 (请修改为您的真实信息)
// ================================================================
$SMTP_CONFIG = [
    // QQ 邮箱 SMTP 服务器
    'host' => 'smtp.qq.com',
    // SMTP 端口 (SSL)
    'port' => 465,
    // 是否使用 SSL
    'secure' => 'ssl',
    // 您的 QQ 邮箱账号 (完整地址)
    'username' => '***********',
    // QQ 邮箱授权码 (不是登录密码!)
    'password' => '**********',
    // 接收邮件的邮箱 (可以跟发件人相同)
    'to_email' => '**********',
    // 发件人名称 (显示用)
    'from_name' => '************'
];
// ================================================================

image.png
[PHP] 纯文本查看 复制代码
<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=yes">
    <title>停车开票助手</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
        }

        body {
            background: #f5f7fc;
            min-height: 100vh;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            padding: 24px 16px;
        }

        .container {
            width: 100%;
            max-width: 480px;
            background: white;
            border-radius: 32px;
            box-shadow: 0 12px 40px rgba(0, 0, 0, 0.06);
            padding: 28px 24px 32px;
            transition: all 0.2s;
        }

        h1 {
            font-size: 26px;
            font-weight: 700;
            color: #0b1b33;
            display: flex;
            align-items: center;
            gap: 12px;
            margin-bottom: 6px;
        }

        .subhead {
            font-size: 14px;
            color: #6b7a8f;
            border-left: 3px solid #2a7de1;
            padding-left: 14px;
            margin-bottom: 28px;
            line-height: 1.5;
        }

        .form-group {
            margin-bottom: 20px;
        }

        label {
            display: block;
            font-size: 14px;
            font-weight: 600;
            color: #1e2b3f;
            margin-bottom: 6px;
        }

        label i {
            margin-right: 8px;
            color: #2a7de1;
            width: 20px;
        }

        input,
        textarea,
        select {
            width: 100%;
            padding: 14px 16px;
            border: 1.5px solid #e2e8f0;
            border-radius: 16px;
            font-size: 15px;
            background: #fafcff;
            transition: 0.15s;
            outline: none;
            color: #0b1b33;
        }

        input:focus,
        textarea:focus,
        select:focus {
            border-color: #2a7de1;
            background: white;
            box-shadow: 0 0 0 4px rgba(42, 125, 225, 0.12);
        }

        textarea {
            min-height: 80px;
            resize: vertical;
        }

        .file-upload-wrapper {
            position: relative;
            border: 1.5px dashed #cbd5e1;
            border-radius: 16px;
            padding: 20px 12px;
            text-align: center;
            background: #f8fafd;
            transition: 0.15s;
            cursor: pointer;
        }

        .file-upload-wrapper:hover {
            border-color: #2a7de1;
            background: #f0f6ff;
        }

        .file-upload-wrapper input[type="file"] {
            position: absolute;
            inset: 0;
            opacity: 0;
            cursor: pointer;
        }

        .file-upload-text {
            pointer-events: none;
            color: #4b5e77;
        }

        .file-upload-text i {
            font-size: 28px;
            color: #2a7de1;
            display: block;
            margin-bottom: 6px;
        }

        .file-name {
            margin-top: 8px;
            font-size: 14px;
            color: #1f3a6b;
            font-weight: 500;
        }

        .btn-submit {
            width: 100%;
            background: #1a5bbf;
            color: white;
            border: none;
            border-radius: 40px;
            padding: 16px;
            font-size: 18px;
            font-weight: 700;
            margin-top: 10px;
            transition: 0.2s;
            cursor: pointer;
            box-shadow: 0 8px 20px rgba(26, 91, 191, 0.25);
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 10px;
        }

        .btn-submit:active {
            transform: scale(0.97);
            background: #124a9e;
        }

        .btn-submit:disabled {
            opacity: 0.7;
            transform: scale(0.98);
            cursor: not-allowed;
        }

        .hint {
            font-size: 13px;
            color: #6b7a8f;
            margin-top: 18px;
            display: flex;
            align-items: center;
            gap: 6px;
            background: #f0f5fe;
            padding: 12px 16px;
            border-radius: 40px;
        }

        .toast-message {
            background: #0b1b33;
            color: white;
            padding: 12px 24px;
            border-radius: 40px;
            font-weight: 500;
            font-size: 15px;
            box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
            position: fixed;
            bottom: 30px;
            left: 50%;
            transform: translateX(-50%);
            max-width: 90%;
            width: auto;
            text-align: center;
            z-index: 999;
            transition: 0.3s;
            opacity: 0;
            pointer-events: none;
        }

        .toast-message.show {
            opacity: 1;
            pointer-events: auto;
        }

        [url=home.php?mod=space&uid=945662]@media[/url] (max-width: 420px) {
            .container {
                padding: 20px 16px;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <h1><i class="fas fa-receipt" style="color:#2a7de1;"></i> 停车开票助手</h1>
        <div class="subhead">填写开票信息 · 上传凭证 · 选择接收方式</div>

        <form id="invoiceForm" autocomplete="off">
            <div class="form-group">
                <label><i class="fas fa-building"></i> 单位名称</label>
                <input type="text" id="companyName" placeholder="请输入开票单位全称" required>
            </div>
            <div class="form-group">
                <label><i class="fas fa-id-card"></i> 税号 / 统一社会信用代码</label>
                <input type="text" id="taxId" placeholder="如 91330100MA27X..." required>
            </div>
            <div class="form-group">
                <label><i class="fas fa-map-pin"></i> 注册地址 & 电话</label>
                <input type="text" id="addressPhone" placeholder="地址, 电话 (选填)">
            </div>
            <div class="form-group">
                <label><i class="fas fa-university"></i> 开户行 & 账号</label>
                <input type="text" id="bankAccount" placeholder="开户行, 银行账号 (选填)">
            </div>

            <div class="form-group">
                <label><i class="fas fa-paperclip"></i> 上传支付凭证截图</label>
                <div class="file-upload-wrapper">
                    <div class="file-upload-text">
                        <i class="fas fa-cloud-upload-alt"></i>
                        <span>点击上传 或 拍照</span>
                        <div style="font-size: 12px; color: #6b7a8f; margin-top: 4px;">支持 jpg, png, pdf</div>
                    </div>
                    <input type="file" id="paymentFile" accept=".jpg,.jpeg,.png,.pdf">
                    <div id="fileNameDisplay" class="file-name" style="display:none;"></div>
                </div>
            </div>

            <div class="form-group">
                <label><i class="fas fa-share-alt"></i> 发票接收方式</label>
                <select id="deliveryMethod">
                    <option value="email">&#128231; 邮箱</option>
                    <option value="wechat">&#128172; 微信</option>
                    <option value="qq">&#128039; QQ</option>
                </select>
            </div>
            <div class="form-group">
                <label><i class="fas fa-at"></i> 接收账号</label>
                <input type="text" id="deliveryAccount" placeholder="邮箱 / 微信号 / QQ号" required>
            </div>

            <button type="submit" class="btn-submit"><i class="fas fa-paper-plane"></i> 提交 · 发送到开票邮箱</button>
        </form>

        <div class="hint">
            <i class="fas fa-info-circle" style="color:#2a7de1;"></i>
            提交后信息将自动发送到开票邮箱
        </div>
    </div>

    <div id="toast" class="toast-message">&#10004;&#65039; 已提交</div>

    <script>
        (function() {
            "use strict";

            // ================================================================
            //  &#128231; 后端 API 地址 (请修改为您的实际地址)
            // ================================================================
            const API_URL = 'send_email.php';
            // ================================================================

            const form = document.getElementById('invoiceForm');
            const fileInput = document.getElementById('paymentFile');
            const fileNameDisplay = document.getElementById('fileNameDisplay');
            const toast = document.getElementById('toast');

            let toastTimer = null;

            function showToast(msg, isError = false) {
                toast.textContent = msg;
                toast.classList.add('show');
                toast.style.background = isError ? '#b91c1c' : '#0b1b33';
                clearTimeout(toastTimer);
                toastTimer = setTimeout(() => {
                    toast.classList.remove('show');
                    toast.style.background = '#0b1b33';
                }, 3200);
            }

            fileInput.addEventListener('change', function() {
                if (this.files && this.files.length > 0) {
                    const name = this.files[0].name;
                    fileNameDisplay.textContent = '&#128206; ' + name;
                    fileNameDisplay.style.display = 'block';
                } else {
                    fileNameDisplay.style.display = 'none';
                }
            });

            // ---------- 发送到后端 API ----------
            function sendToBackend(data) {
                return new Promise((resolve, reject) => {
                    // 使用 FormData 支持文件上传
                    const formData = new FormData();
                    formData.append('company', data.company);
                    formData.append('taxId', data.taxId);
                    formData.append('addressPhone', data.addressPhone || '');
                    formData.append('bankAccount', data.bankAccount || '');
                    formData.append('fileInfo', data.fileInfo);
                    formData.append('deliveryMethod', data.deliveryMethod);
                    formData.append('deliveryAccount', data.deliveryAccount);
                    
                    // 如果有文件,添加到 FormData
                    if (data.file) {
                        formData.append('paymentFile', data.file);
                    }

                    fetch(API_URL, {
                        method: 'POST',
                        body: formData,
                        // 不要设置 Content-Type,让浏览器自动设置
                    })
                    .then(response => response.json())
                    .then(result => {
                        if (result.success) {
                            resolve(result);
                        } else {
                            reject(new Error(result.message || '发送失败'));
                        }
                    })
                    .catch(error => {
                        reject(new Error('网络请求失败: ' + error.message));
                    });
                });
            }

            // ---------- 表单提交 ----------
            form.addEventListener('submit', function(e) {
                e.preventDefault();

                const company = document.getElementById('companyName').value.trim();
                const taxId = document.getElementById('taxId').value.trim();
                const addressPhone = document.getElementById('addressPhone').value.trim();
                const bankAccount = document.getElementById('bankAccount').value.trim();
                const deliveryMethod = document.getElementById('deliveryMethod').value;
                const deliveryAccount = document.getElementById('deliveryAccount').value.trim();

                if (!company || !taxId || !deliveryAccount) {
                    showToast('请填写完整信息 (单位/税号/接收账号)', true);
                    return;
                }

                let fileInfo = '未上传';
                let file = null;
                if (fileInput.files && fileInput.files.length > 0) {
                    file = fileInput.files[0];
                    fileInfo = file.name + ' (' + (file.size / 1024).toFixed(1) + ' KB)';
                }

                const data = {
                    company,
                    taxId,
                    addressPhone,
                    bankAccount,
                    fileInfo,
                    file,
                    deliveryMethod,
                    deliveryAccount
                };

                const sendBtn = form.querySelector('.btn-submit');
                const originalText = sendBtn.innerHTML;
                sendBtn.innerHTML = '<i class="fas fa-spinner fa-pulse"></i> 发送中...';
                sendBtn.disabled = true;

                sendToBackend(data)
                    .then(result => {
                        console.log('&#9989; 邮件发送成功:', result);
                        showToast(`&#9989; 已成功发送至 ${result.to || '预设邮箱'}`);
                        // 清空文件选择
                        fileInput.value = '';
                        fileNameDisplay.style.display = 'none';
                        // 可选: 清空其他字段
                        // document.getElementById('companyName').value = '';
                        // document.getElementById('taxId').value = '';
                        // document.getElementById('deliveryAccount').value = '';
                    })
                    .catch(error => {
                        console.error('&#10060; 邮件发送失败:', error);
                        showToast('&#10060; ' + error.message, true);
                    })
                    .finally(() => {
                        sendBtn.innerHTML = originalText;
                        sendBtn.disabled = false;
                    });
            });

        })();
    </script>
</body>
</html>

免费评分

参与人数 4吾爱币 +8 热心值 +4 收起 理由
蜘蛛人 + 1 + 1 用心讨论,共获提升!
苏紫方璇 + 5 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
leechjia + 1 + 1 谢谢@Thanks!
wuloveyou + 1 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

jun269 发表于 2026-7-17 14:28
附件中的压缩包是需要部署在服务器的吧?
天天哈皮 发表于 2026-7-17 14:49
liyuhuimuzi 发表于 2026-7-17 15:58
wangqing11116 发表于 2026-7-17 16:30
楼主厉害了
touristxxp 发表于 2026-7-17 16:54
感谢楼主,先用用试试。
liqcang 发表于 2026-7-17 17:02
哪位大佬说一下,如何部署?
nosilence 发表于 2026-7-17 19:54
让AI改写生golang版本,生成二进制文件直接部署执行,连php环境都免了
bccbj 发表于 2026-7-17 23:16
我们停车场也准备收费  这玩意是直接复制到主机吗?
lishengde322 发表于 2026-7-18 02:23
收到邮件后是财务看邮件人工开票还是自动开票?
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-8-16 09:33

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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