Skip to content
Thuan Bui's Blog
Go back

Invoice Ninja - Giải pháp tạo hóa đơn thanh toán cho doanh nghiệp nhỏ và freelancer

Để phục vụ cho công việc kinh doanh, mình đang sử dụng khá nhiều các ứng dụng mã nguồn mở để tiết kiệm chi phí vận hành:

Từ ngày dọn nhà qua Nhật, có thêm 1 ứng dụng đã nhanh chóng trở thành một phần không thể thiếu cho công ty mới của mình ở Nhật. Đó là Invoice Ninja - ứng dụng tạo và quản lý hóa đơn cho khách hàng. Mình đang sử dụng Invoice Ninja để nhận thanh toán từ khách hàng ở nhiều quốc gia khác nhau, thông qua cổng thanh toán Stripe.

Bài viết này sẽ hướng dẫn bạn cách cài đặt Invoice Ninja để sử dụng cho mục đích kinh doanh của mình

I. Invoice Ninja là gì?

Invoice Ninja là một phần mềm mã nguồn mở giúp bạn quản lý hóa đơn, báo giá, và các khoản thanh toán cho công việc kinh doanh. Nó được thiết kế phù hợp cho các doanh nghiệp nhỏ, freelancer cần một công cụ đơn giản nhưng mạnh mẽ để quản lý tài chính.

Các tính năng nổi bật của Invoice Ninja:

II. Cài đặt Invoice Ninja bằng Docker Compose

Bạn có thể cài đặt Invoice Ninja trực tiếp lên server, hoặc sử dụng Docker. Mình sẽ cài đặt thông qua Docker Compose cho nhanh gọn.

Yêu cầu máy chủ đã được cài đặt sẵn DockerDocker Compose.

1. Clone Invoice Ninja về server

SSH vào máy chủ và clone repo của Invoice Ninja về máy chủ

Terminal window
git clone https://github.com/invoiceninja/dockerfiles.git -b master invoice-ninja
cd invoice-ninja

File docker-compose.yml sẽ có nội dung tương tự như sau

Terminal window
version: '3.7'
services:
server:
image: nginx
restart: always
env_file: env
volumes:
# Vhost configuration
#- ./config/caddy/Caddyfile:/etc/caddy/Caddyfiledocker-com
- ./config/nginx/in-vhost.conf:/etc/nginx/conf.d/in-vhost.conf:ro
- ./docker/app/public:/var/www/app/public:ro
depends_on:
- app
# Run webserver nginx on port 80
# Feel free to modify depending what port is already occupied
ports:
- "80:80"
#- "443:443"
networks:
- invoiceninja
extra_hosts:
- "in5.localhost:192.168.0.124 " #host and ip
app:
image: invoiceninja/invoiceninja:5
env_file: env
restart: always
volumes:
- ./config/hosts:/etc/hosts:ro
- ./docker/app/public:/var/www/app/public:rw,delegated
- ./docker/app/storage:/var/www/app/storage:rw,delegated
- ./config/php/php.ini:/usr/local/etc/php/php.ini
- ./config/php/php-cli.ini:/usr/local/etc/php/php-cli.ini
depends_on:
- db
networks:
- invoiceninja
extra_hosts:
- "in5.localhost:192.168.0.124 " #host and ip
db:
image: mysql:8
# When running on ARM64 use MariaDB instead of MySQL
# image: mariadb:10.4
# For auto DB backups comment out image and use the build block below
# build:
# context: ./config/mysql
restart: always
env_file: env
volumes:
- ./docker/mysql/data:/var/lib/mysql:rw,delegated
# remove comments for next 4 lines if you want auto sql backups
#- ./docker/mysql/bak:/backups:rw
#- ./config/mysql/backup-script:/etc/cron.daily/daily:ro
#- ./config/mysql/backup-script:/etc/cron.weekly/weekly:ro
#- ./config/mysql/backup-script:/etc/cron.monthly/monthly:ro
networks:
- invoiceninja
extra_hosts:
- "in5.localhost:192.168.0.124 " #host and ip
# THIS IS ONLY A VALID CONFIGURATION FOR IN 4. DO NOT USE FOR IN 5.
# cron:
# image: invoiceninja/invoiceninja:alpine-4
# volumes:
# - ./docker/app/public:/var/www/app/public:rw,delegated
# - ./docker/app/storage:/var/www/app/storage:rw,delegated
# - ./docker/app/public/logo:/var/www/app/public/logo:rw,delegated
# entrypoint: |
# /bin/sh -c 'sh -s <<EOF
# trap "break;exit" SIGHUP SIGINT SIGTERM
# sleep 300s
# while /bin/true; do
# ./artisan ninja:send-invoices
# ./artisan ninja:send-reminders
# sleep 1d
# done
# EOF'
# networks:
# - invoiceninja
#
networks:
invoiceninja:

3. Thay thế nginx bằng Caddy

File docker-compose.yml đã được tích hợp Nginx làm Reverse Proxy. Bạn có thể xóa phần khai báo nginx nếu trên hệ thống đã có sẵn Reverse Proxy.

MÌnh không thích dùng nginx nên sẽ thay bằng caddy để làm Reverse Proxy. Đổi lại nội dung file docker-compose.yml như bên dưới

services:
server:
image: caddy:alpine
container_name: caddy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- ./caddy_data:/data
- ./caddy_config:/config
- ./docker/app/public:/var/www/app/public:ro
networks:
- invoiceninja
app:
image: invoiceninja/invoiceninja:5
container_name: invoiceninja
env_file: env
restart: always
volumes:
- ./config/hosts:/etc/hosts:ro
- ./docker/app/public:/var/www/app/public:rw,delegated
- ./docker/app/storage:/var/www/app/storage:rw,delegated
- ./config/php/php.ini:/usr/local/etc/php/php.ini
- ./config/php/php-cli.ini:/usr/local/etc/php/php-cli.ini
depends_on:
- db
networks:
- invoiceninja
db:
image: mariadb:10.4
restart: always
env_file: env
volumes:
- ./docker/mysql/data:/var/lib/mysql:rw,delegated
networks:
- invoiceninja
extra_hosts:
- "in5.localhost:192.168.0.124 " #host and ip
networks:
invoiceninja:

Tạo thêm file Caddyfile với nội dung sau

invoice.thuanbui.me {
root * /var/www/app/public
php_fastcgi invoiceninja:9000
encode zstd gzip
file_server browse
}

Bạn cần thay thế invoice.thuanbui.me bằng tên miền bạn sử dụng để truy cập Invoice Ninja.

2. Tạo APP_KEY

Trước khi kích hoạt dịch vụ, cần phải tạo APP_KEY bằng lệnh sau

docker run --rm -it invoiceninja/invoiceninja php artisan key:generate --show

Chờ vài phút để hệ thống xử lý, bạn sẽ nhận được kết quả trả về tương tự như bên dưới

base64:5fOFQtFaQcwFxQ2nAEwBdMUWzB5DcOGS7y+uvkL5W2c=

3. Cập nhật thông số env

Chỉnh sửa lại file env bằng lệnh

Terminal window
nano env
# IN application vars
APP_URL=https://invoice.thuanbui.me
APP_KEY=base64:5fOFQtFaQcwFxQ2nAEwBdMUWzB5DcOGS7y+uvkL5W2c=
APP_DEBUG=true
REQUIRE_HTTPS=false
PHANTOMJS_PDF_GENERATION=false
PDF_GENERATOR=snappdf
TRUSTED_PROXIES='*'

Cập nhật thêm thông số tài khoản admin và mật khẩu

# Create initial user
# Default to these values if empty
# IN_USER_EMAIL=admin@example.com
# IN_PASSWORD=changeme!
IN_USER_EMAIL=thuan@thuanbui.me
IN_PASSWORD=123456

Ngoài ra, để Invoice Ninja có thể gửi email đến khách hàng, cần phải cấu hình thêm mục #Mail options, cần khai báo các thông số cần thiết tương tự như sau

# Mail options
MAIL_MAILER=smtp
MAIL_HOST=smtp.sendgrid.net
MAIL_PORT=587
MAIL_USERNAME=apikey
MAIL_PASSWORD=SG.wPFD3423dffdsfdsfdsfdsfZxRjSi0T4T-Rn7UsSd2F_-5ySJUV_4
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=noreply@thuanbui.me
MAIL_FROM_NAME=ThuanBui

Sau khi hoàn thành, lưu lại (Ctrl + O) và thoát ra (Ctrl + X)

4. Chỉnh sửa permission

Để đảm bảo quyền thư mục được thiết lập chính xác khi container khởi động, cần sử dụng lệnh sau thiết lập đúng quyền truy cập cho thư mục Docker.

Terminal window
chmod 755 docker/app/public
sudo chown -R 1500:1500 docker/app

3. Kích hoạt dịch vụ

Khởi động Invoice Ninja bằng lệnh

Terminal window
docker compose up -d

Truy cập vào Invoice Ninja thông qua tên miền bạn đã cấu hình. Chúng ta sẽ bắt đầu phần cấu hình thông số ban đầu cho Invoice Ninja

III. Cấu hình Invoice Ninja

Bạn cần đăng nhập vào invoice Ninja bằng thông tin email và mật khẩu đã thiết lập trong file env

1. Thông tin công ty

Ở lần đăng nhập đầu tiên, chúng ta cần phải thiết lập tên công ty (Company Name), ngôn ngữ (Language) và tiền tệ (Currency)

Giao diện trang Dashboard của Invoice Ninja sẽ hiện ra như bên dưới

Truy cập thêm vào phần Setting / Company Details để khai báo thêm các thông tin liên quan: Website, Email, Địa chỉ,… Các thông tin này sẽ hiển thị trên các hóa đơn gửi cho khách hàng.

2. Kết nối với Stripe & PayPal

Invoice Ninja hỗ trợ kết nối với cổng thanh toán như StripePayPal giúp khách hàng có thẻ thanh toán trực tiếp từ các hóa đơn được tạo từ hệ thống.

Truy cập vào mục Settings > Payment Settings, chọn Add Gateway, chọn Stripe hoặc Paypal, sau đó nhập các thông tin cần thiết (API Keys) lấy từ tài khoản Stripe / Paypal của bạn


IV. Tạo hóa đơn và nhận thanh toán

1. Tạo hóa đơn mới

  1. Truy cập vào Invoices và chọn Create Invoice.

  2. Thêm thông tin khách hàng, dịch vụ/sản phẩm, thuế (nếu có).

  3. Tùy chỉnh hóa đơn theo ý muốn (logo, màu sắc, điều khoản).

Sau khi hoàn tất, nhấn nút Save để lưu lại invoice.

2. Gửi invoice cho khách hàng

Bạn có thể gửi invoice cho khách hàng bằng 2 cách:

  1. Bấm vào nút mũi tên bên cạch nút Save và chọn Email Invoice để gửi invoice qua email

  2. Right click vào dòng View in Portal, chọn Copy Link. Sau đó gửi link này cho khách hàng qua Zalo / Facebook / SMS/…

3. Nhận thanh toán

Khách hàng sau khi nhận invoice email / portal link có thể thanh toán bằng Stripe / Paypal (nếu bạn đã cấu hình). Sau khi thanh toán thành công, hóa đơn sẽ được tự động cập nhật trạng thái từ Sent thành Paid.


Invoice Ninja đã giúp mình tiết kiệm rất nhiều thời gian và công sức trong việc quản lý hóa đơn cho công ty. Nếu bạn đang tìm kiếm một công cụ quản lý hóa đơn và để nhận thanh toán từ khách hàng hãy thử cài đặt và sử dụng Invoice Ninja.

Chúc bạn thực hiện thành công!

Nếu bạn cần hỗ trợ thiết lập Invoice Ninja, tham khảo dịch vụ cài đặt Self-Hosting app của mình bên dưới nhé


Share this post on:

Previous Post
[Proxmox] Thiết lập USB Passthrough cho máy ảo KVM
Next Post
Paperless-ngx - Ứng dụng quản lý hồ sơ, hóa đơn điện tử tiện lợi