Tài liệu SolanaThông số kỹ thuật

Đặc tả Solana Pay v1.1

Tóm tắt

Một giao thức chuẩn để mã hóa các yêu cầu giao dịch Solana trong URL nhằm hỗ trợ thanh toán và các trường hợp sử dụng khác.

Sự đồng thuận sơ bộ về đặc tả này đã đạt được, và các triển khai đã tồn tại trong Phantom, FTX và Slope.

Tiêu chuẩn này lấy cảm hứng từ BIP 21EIP 681.

Động lực

Một giao thức URL chuẩn để yêu cầu chuyển SOL gốc, chuyển SPL Token và các giao dịch Solana cho phép trải nghiệm người dùng tốt hơn trên các ứng dụng và ví trong hệ sinh thái Solana.

Các URL này có thể được mã hóa trong mã QR hoặc thẻ NFC, hoặc được gửi giữa người dùng và ứng dụng để yêu cầu thanh toán và soạn thảo giao dịch.

Các ứng dụng nên đảm bảo rằng một giao dịch đã được xác nhận và hợp lệ trước khi họ phát hành hàng hóa hoặc dịch vụ đang bán, hoặc cấp quyền truy cập vào các đối tượng hoặc sự kiện.

Ví di động nên đăng ký xử lý lược đồ URL để cung cấp trải nghiệm liền mạch nhưng an toàn khi gặp các URL Solana Pay trong môi trường.

Bằng cách tiêu chuẩn hóa một phương pháp đơn giản để giải quyết những vấn đề này, chúng tôi đảm bảo khả năng tương thích cơ bản của các ứng dụng và ví để các nhà phát triển có thể tập trung vào các trừu tượng cấp cao hơn.

Đặc tả: Yêu cầu Chuyển khoản

URL yêu cầu chuyển khoản Solana Pay mô tả một yêu cầu không tương tác để chuyển SOL hoặc SPL Token.

solana:<recipient>
?amount=<amount>
&spl-token=<spl-token>
&reference=<reference>
&label=<label>
&message=<message>
&memo=<memo>

Yêu cầu này là không tương tác vì các tham số trong URL được ví sử dụng để trực tiếp soạn thảo một giao dịch.

Người nhận

Một trường recipient duy nhất là bắt buộc làm đường dẫn. Giá trị phải là pubkey được mã hóa base58 của một tài khoản SOL gốc. associated token account không được sử dụng.

Thay vào đó, để yêu cầu chuyển SPL Token, trường spl-token phải được sử dụng để chỉ định một SPL Token mint, từ đó địa chỉ associated token account của người nhận sẽ được suy ra.

Số lượng

Một trường amount duy nhất được phép làm tham số truy vấn tùy chọn. Giá trị phải là số nguyên không âm hoặc số thập phân theo đơn vị "người dùng". Đối với SOL, đó là SOL chứ không phải lamport. Đối với token, hãy sử dụng uiAmountString chứ không phải amount.

0 là giá trị hợp lệ. Nếu giá trị là số thập phân nhỏ hơn 1, nó phải có số 0 đứng trước dấu .. Ký hiệu khoa học bị cấm.

Nếu không cung cấp giá trị, ví phải nhắc người dùng nhập số lượng. Nếu số chữ số thập phân vượt quá mức hỗ trợ cho SOL (9) hoặc SPL Token (tùy theo mint cụ thể), ví phải từ chối URL do định dạng không hợp lệ.

SPL Token

Một trường spl-token duy nhất được phép làm tham số truy vấn tùy chọn. Giá trị phải là pubkey được mã hóa base58 của tài khoản SPL Token mint.

Nếu trường này được cung cấp, quy ước Associated Token Account phải được sử dụng, và ví phải bao gồm lệnh TokenProgram.Transfer hoặc TokenProgram.TransferChecked làm lệnh cuối cùng của giao dịch.

Nếu trường này không được cung cấp, URL mô tả một giao dịch chuyển SOL gốc, và ví phải bao gồm lệnh SystemProgram.Transfer làm lệnh cuối cùng của giao dịch.

Ví phải suy ra địa chỉ ATA từ các trường recipientspl-token. Việc chuyển đến các token account phụ không được hỗ trợ.

Tham chiếu

Nhiều trường reference được phép làm tham số truy vấn tùy chọn. Các giá trị phải là mảng 32 byte được mã hóa base58. Chúng có thể là hoặc không phải là pubkey, trên hoặc ngoài đường cong, và có thể tương ứng hoặc không tương ứng với các tài khoản trên Solana.

Nếu các giá trị được cung cấp, ví phải bao gồm chúng theo thứ tự được cung cấp dưới dạng khóa chỉ đọc, không phải người ký cho lệnh SystemProgram.Transfer hoặc TokenProgram.Transfer/TokenProgram.TransferChecked trong giao dịch thanh toán. Các giá trị có thể là duy nhất hoặc không duy nhất đối với yêu cầu thanh toán, và có thể tương ứng hoặc không tương ứng với một tài khoản trên Solana.

Do các validator Solana lập chỉ mục giao dịch theo các khóa tài khoản này, các giá trị reference có thể được sử dụng làm ID khách hàng (ID có thể sử dụng trước khi biết giao dịch thanh toán cuối cùng). Phương thức RPC getSignaturesForAddress có thể được sử dụng để định vị giao dịch theo cách này.

Nhãn

Một trường label duy nhất được phép làm tham số truy vấn tùy chọn. Giá trị phải là một chuỗi UTF-8 được mã hóa URL mô tả nguồn của yêu cầu chuyển khoản.

Ví dụ, đây có thể là tên của một thương hiệu, cửa hàng, ứng dụng hoặc người đưa ra yêu cầu. Ví nên giải mã URL giá trị và hiển thị giá trị đã giải mã cho người dùng.

Thông báo

Một trường message duy nhất được phép làm tham số truy vấn tùy chọn. Giá trị phải là một chuỗi UTF-8 được mã hóa URL mô tả bản chất của yêu cầu chuyển khoản.

Ví dụ, đây có thể là tên của một mặt hàng đang được mua, ID đơn hàng hoặc một lời cảm ơn. Ví nên giải mã URL giá trị và hiển thị giá trị đã giải mã cho người dùng.

Ghi chú

Một trường memo duy nhất được phép làm tham số truy vấn tùy chọn. Giá trị phải là một chuỗi UTF-8 được mã hóa URL mà phải được bao gồm trong một lệnh SPL Memo trong giao dịch thanh toán.

Ví phải giải mã URL giá trị và nên hiển thị giá trị đã giải mã cho người dùng. Ghi chú sẽ được ghi lại bởi các validator và không nên bao gồm thông tin riêng tư hoặc nhạy cảm.

Nếu trường này được cung cấp, ví phải bao gồm một lệnh MemoProgram làm lệnh thứ hai từ cuối trong giao dịch, ngay trước lệnh chuyển SOL hoặc SPL Token, để tránh sự mơ hồ với các lệnh khác trong giao dịch.

Ví dụ

URL mô tả yêu cầu chuyển 1 SOL

solana:mvines9iiHiQTysrwkJjGf2gb9Ex9jXJX8ns3qwf2kN?amount=1&label=Michael&message=Thanks%20for%20all%20the%20fish&memo=OrderId12345

URL mô tả yêu cầu chuyển 0.01 USDC

solana:mvines9iiHiQTysrwkJjGf2gb9Ex9jXJX8ns3qwf2kN?amount=0.01&spl-token=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v

URL mô tả yêu cầu chuyển SOL (người dùng được yêu cầu nhập số lượng)

solana:mvines9iiHiQTysrwkJjGf2gb9Ex9jXJX8ns3qwf2kN?label=Michael

Đặc tả: Yêu cầu Giao dịch

URL yêu cầu giao dịch Solana Pay mô tả một yêu cầu tương tác cho bất kỳ giao dịch Solana nào.

solana:<link>

Yêu cầu mang tính tương tác vì các tham số trong URL được ví sử dụng để thực hiện yêu cầu HTTP nhằm soạn thảo một giao dịch.

Liên kết

Một trường link duy nhất được yêu cầu làm đường dẫn. Giá trị phải là một URL HTTPS tuyệt đối được mã hóa URL có điều kiện.

Nếu URL chứa các tham số truy vấn, nó phải được mã hóa URL. Các tham số truy vấn của giao thức có thể được thêm vào đặc tả này. Mã hóa URL giá trị này ngăn chặn xung đột với các tham số giao thức.

Nếu URL không chứa tham số truy vấn, nó không nên được mã hóa URL. Điều này tạo ra một URL ngắn hơn và mã QR ít dày đặc hơn.

Trong cả hai trường hợp, ví phải giải mã URL giá trị. Điều này không có hiệu lực nếu giá trị không được mã hóa URL. Nếu giá trị đã giải mã không phải là URL HTTPS tuyệt đối, ví phải từ chối nó vì không hợp lệ.

Yêu cầu GET

Ví nên thực hiện yêu cầu JSON GET qua HTTP đến URL. Yêu cầu không nên xác định danh tính của ví hoặc người dùng.

Ví nên thực hiện yêu cầu với header Accept-Encoding, và ứng dụng nên phản hồi với header Content-Encoding để nén HTTP.

Ví nên hiển thị tên miền của URL khi yêu cầu đang được thực hiện.

Phản hồi GET

Ví phải xử lý các phản hồi HTTP lỗi phía client, lỗi phía server, và chuyển hướng. Ứng dụng phải phản hồi với các trạng thái này, hoặc với phản hồi HTTP OK JSON có body như sau:

{ "label": "<label>", "icon": "<icon>" }

Giá trị <label> phải là chuỗi UTF-8 mô tả nguồn gốc của yêu cầu giao dịch. Ví dụ, đây có thể là tên thương hiệu, cửa hàng, ứng dụng hoặc người thực hiện yêu cầu.

Giá trị <icon> phải là URL HTTP hoặc HTTPS tuyệt đối của hình ảnh biểu tượng. Tệp phải là ảnh SVG, PNG hoặc WebP, nếu không ví phải từ chối vì không hợp lệ.

Ví không nên lưu cache phản hồi ngoại trừ khi được chỉ định bởi HTTP caching trong response headers.

Ví nên hiển thị nhãn và render hình ảnh biểu tượng cho người dùng.

Yêu cầu POST

Ví phải thực hiện yêu cầu HTTP POST JSON đến URL với body như sau:

{ "account": "<account>" }

Giá trị <account> phải là khóa công khai được mã hóa base58 của tài khoản có thể ký giao dịch.

Ví nên thực hiện yêu cầu với Accept-Encoding header, và ứng dụng nên phản hồi với Content-Encoding header để nén HTTP.

Ví nên hiển thị tên miền của URL khi yêu cầu đang được thực hiện. Nếu yêu cầu GET đã được thực hiện, ví cũng nên hiển thị nhãn và render hình ảnh biểu tượng từ phản hồi.

Phản hồi POST

Ví phải xử lý các phản hồi HTTP lỗi phía client, lỗi phía server, và chuyển hướng. Ứng dụng phải phản hồi với các trạng thái này, hoặc với phản hồi HTTP OK JSON có body như sau:

{ "transaction": "<transaction>" }

Giá trị <transaction> phải là một giao dịch đã được tuần tự hóa được mã hóa base64. Ví phải giải mã base64 giao dịch và khử tuần tự hóa nó.

Ứng dụng có thể phản hồi bằng một giao dịch đã được ký một phần hoặc đầy đủ. Ví phải xác thực giao dịch như không đáng tin cậy.

Chữ Ký Rỗng

Nếu signatures của giao dịch rỗng:

  • Ứng dụng nên đặt feePayer thành account trong yêu cầu, hoặc giá trị không (new PublicKey(0) hoặc new PublicKey("11111111111111111111111111111111")).
  • Ứng dụng nên đặt recentBlockhash thành blockhash mới nhất, hoặc giá trị không (new PublicKey(0).toBase58() hoặc "11111111111111111111111111111111").
  • Ví phải bỏ qua feePayer trong giao dịch và đặt feePayer thành account trong yêu cầu.
  • Ví phải bỏ qua recentBlockhash trong giao dịch và đặt recentBlockhash thành blockhash mới nhất.

Nếu signatures của giao dịch không rỗng:

Ví chỉ được ký giao dịch bằng account trong yêu cầu, và chỉ được thực hiện nếu chữ ký cho account trong yêu cầu được yêu cầu.

Nếu bất kỳ chữ ký nào ngoài chữ ký cho account trong yêu cầu được yêu cầu, ví phải từ chối giao dịch là độc hại.

Ứng dụng cũng có thể bao gồm trường message tùy chọn trong phần thân phản hồi:

{ "message": "<message>", "transaction": "<transaction>" }

Giá trị <message> phải là một chuỗi UTF-8 mô tả bản chất của phản hồi giao dịch.

Ví dụ, đây có thể là tên của một mặt hàng đang được mua, một khoản chiết khấu được áp dụng cho giao dịch mua, hoặc một lời cảm ơn. Ví nên hiển thị giá trị này cho người dùng.

Ví và ứng dụng nên cho phép các trường bổ sung trong phần thân yêu cầu và phần thân phản hồi, có thể được thêm vào bởi các đặc tả trong tương lai.

Ví dụ

URL mô tả một yêu cầu giao dịch.
solana:https://example.com/solana-pay
URL mô tả một yêu cầu giao dịch với các tham số truy vấn.
solana:https%3A%2F%2Fexample.com%2Fsolana-pay%3Forder%3D12345
Yêu cầu GET
GET /solana-pay?order=12345 HTTP/1.1
Host: example.com
Connection: close
Accept: application/json
Accept-Encoding: br, gzip, deflate
Phản hồi GET
HTTP/1.1 200 OK
Connection: close
Content-Type: application/json
Content-Length: 62
Content-Encoding: gzip
{"label":"Michael Vines","icon":"https://example.com/icon.svg"}
Yêu cầu POST
POST /solana-pay?order=12345 HTTP/1.1
Host: example.com
Connection: close
Accept: application/json
Accept-Encoding: br, gzip, deflate
Content-Type: application/json
Content-Length: 57
{"account":"mvines9iiHiQTysrwkJjGf2gb9Ex9jXJX8ns3qwf2kN"}
Phản hồi POST
HTTP/1.1 200 OK
Connection: close
Content-Type: application/json
Content-Length: 298
Content-Encoding: gzip
{"message":"Thanks for all the fish","transaction":"AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECC4JMKqNplIXybGb/GhK1ofdVWeuEjXnQor7gi0Y2hMcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAAAMAgAAAAAAAAAAAAAA"}

Tiện ích mở rộng

Các định dạng và trường bổ sung có thể được tích hợp vào đặc tả này để kích hoạt các trường hợp sử dụng mới trong khi vẫn đảm bảo khả năng tương thích với các ứng dụng và ví.

Vui lòng mở một vấn đề trên Github để đề xuất các thay đổi cho đặc tả nhằm thu thập phản hồi từ các nhà phát triển ứng dụng và ví.

Một ví dụ thực tế về đề xuất như vậy.

Is this page helpful?

Quản lý bởi

© 2026 Solana Foundation.
Đã đăng ký bản quyền.
Kết nối