diff --git a/aleksis/apps/tezor/models/invoice.py b/aleksis/apps/tezor/models/invoice.py
index b7c1eb5418bde62776942ccd74b0564a86b82601..84b44135a91e478dda880bbaa7ae4be0848f23f6 100644
--- a/aleksis/apps/tezor/models/invoice.py
+++ b/aleksis/apps/tezor/models/invoice.py
@@ -88,7 +88,7 @@ class Invoice(BasePayment, PureDjangoModel):
         return TotalsTable(values)
 
     def get_success_url(self):
-        return reverse("invoice_by_pk", kwargs={"pk": self.pk})
+        return reverse("invoice_by_token", kwargs={"token": self.token})
 
     def get_failure_url(self):
-        return reverse("invoice_by_pk", kwargs={"pk": self.pk})
+        return reverse("invoice_by_token", kwargs={"token": self.token})
diff --git a/aleksis/apps/tezor/rules.py b/aleksis/apps/tezor/rules.py
index b82cc5b6d0cbfeb4d105f597231641f9740b6c3f..12a27e3b55a38bbff4d7af450d0b9b757e0a01b6 100644
--- a/aleksis/apps/tezor/rules.py
+++ b/aleksis/apps/tezor/rules.py
@@ -84,5 +84,8 @@ do_payment_predicate = has_person & (is_in_payment_status(PaymentStatus.WAITING)
 rules.add_perm("tezor.do_payment", do_payment_predicate)
 
 # View invoice
-view_invoice_predicate = is_own_invoice | is_site_preference_set("payments", "public_payments") | has_global_perm("tezor.view_invoice") | has_object_perm("tezor.view_invoice")
+view_invoice_predicate = has_person & is_own_invoice | is_site_preference_set("payments", "public_payments") | has_global_perm("tezor.view_invoice") | has_object_perm("tezor.view_invoice")
 rules.add_perm("tezor.view_invoice_rule", view_invoice_predicate)
+
+print_invoice_predicate = (view_invoice_predicate & display_billing_predicate & display_purchased_items_predicate)
+rules.add_perm("tezor.print_invoice_rule", print_invoice_predicate)
diff --git a/aleksis/apps/tezor/tables.py b/aleksis/apps/tezor/tables.py
index 1139c5eae99adb5ea61b632c504b703836646789..32e2e3f07ad3c1c009d94ea376909a50feb63f94 100644
--- a/aleksis/apps/tezor/tables.py
+++ b/aleksis/apps/tezor/tables.py
@@ -92,14 +92,14 @@ class InvoicesTable(tables.Table):
     billing_last_name = tables.Column()
     total = tables.Column()
     view = tables.LinkColumn(
-        "invoice_by_pk",
-        args=[A("id")],
+        "invoice_by_token",
+        args=[A("token")],
         verbose_name=_("View"),
         text=_("View"),
     )
     print = tables.LinkColumn(
         "print_invoice",
-        args=[A("id")],
+        args=[A("token")],
         verbose_name=_("Print"),
         text=_("Print"),
     )
diff --git a/aleksis/apps/tezor/urls.py b/aleksis/apps/tezor/urls.py
index 54856887d61bf33ec3959d5fc081975a817fa1af..73273fc5474b8489b22037925ce169f7ad2acb66 100644
--- a/aleksis/apps/tezor/urls.py
+++ b/aleksis/apps/tezor/urls.py
@@ -4,7 +4,7 @@ from . import views
 
 urlpatterns = [
     path("payments/", include("payments.urls")),
-    path("invoice/<int:pk>/print/", views.GetInvoicePDF.as_view(), name="print_invoice"),
+    path("invoice/<str:token>/print/", views.GetInvoicePDF.as_view(), name="print_invoice"),
     path("invoice/<str:token>/pay", views.do_payment, name="do_payment"),
     path(
         "clients/",
@@ -52,8 +52,8 @@ urlpatterns = [
         name="delete_invoice_group_by_pk",
     ),
     path(
-        "invoice/<int:pk>/",
+        "invoice/<str:slug>/",
         views.InvoiceDetailView.as_view(),
-        name="invoice_by_pk",
+        name="invoice_by_token",
     ),
 ]
diff --git a/aleksis/apps/tezor/views.py b/aleksis/apps/tezor/views.py
index 27df0e260bcd2230782829338a781a54b2552044..9517888d7abb64cc30414a6f319bed978d47b750 100644
--- a/aleksis/apps/tezor/views.py
+++ b/aleksis/apps/tezor/views.py
@@ -25,7 +25,7 @@ class GetInvoicePDF(PermissionRequiredMixin, RenderPDFView):
 
     def get_context_data(self, *args, **kwargs):
         context = super().get_context_data(*args, **kwargs)
-        invoice = Invoice.objects.get(id=self.kwargs["pk"])
+        invoice = Invoice.objects.get(token=self.kwargs["token"])
         self.template_name = invoice.group.template_name
         context["invoice"] = invoice
 
@@ -171,5 +171,6 @@ class InvoiceGroupDeleteView(PermissionRequiredMixin, AdvancedDeleteView):
 class InvoiceDetailView(PermissionRequiredMixin, DetailView):
 
     model = Invoice
+    slug_field = "token"
     permission_required = "tezor.view_invoice_rule"
     template_name = "tezor/invoice/full.html"