Chuyển tới nội dung chính

Thanh Toán VND Qua InfoCMS

Hiện tại MCV vẫn lưu số dư ví theo USD cents. Payment rail VND dùng tỷ giá nội bộ cố định:

$1 = 26,000 VND

:::info Kế hoạch VND mặc định Khi chuyển hệ thống sang VND mặc định, cần refactor tiền tệ sang amount_minor + currency. Với VND, amount_minor chính là số tiền VND nguyên. :::

Nạp VND

User có thể tạo QR top-up VND từ Billing.

Số tiền VND -> quy đổi sang wallet amount USD -> tạo InfoCMS QuickQR request -> chờ callback -> credit ví

Ví dụ:

VND đã trảWallet Credit
2,600,000 VND$100.00

Payment được lưu như sau:

  • payments.provider = infocms_qr
  • payments.status = requires_payment
  • payments.metadata.vnd_amount
  • payments.metadata.exchange_rate = 26000

InfoCMS UAT QuickQR dùng:

POST {INFOCMS_BASE_URL}/ocms/v1/auth/login
Header AuthorizationHeaderParameters: base64(clientId)
Header Authorization: base64(hmac_sha512(clientId + yyyyMMdd + clientSecret, clientSecret))
Header bankCode: {INFOCMS_BANK_CODE}
Body: {"data": {"masterId": "{INFOCMS_MASTER_ID}", "clientId": "{INFOCMS_CLIENT_ID}"}}

MCV cache token trả về và dùng token đó cho QuickQR requests. Nếu cấu hình INFOCMS_ACCESS_TOKEN, hệ thống dùng trực tiếp token này thay vì login.

POST {INFOCMS_BASE_URL}/ocms/v3/ec/create_quick_qr
Header token: {INFOCMS_ACCESS_TOKEN}
Header bankCode: {INFOCMS_BANK_CODE}
Header CMS-RSA-Signature: RSA-SHA256 signature of JSON-minified data
Body: {"data": {...}}

MCV giữ RSA private key và chỉ gửi RSA public key cho InfoCMS/Infoplus. InfoCMS public key được lưu riêng và dùng để verify callback ký bằng header CMS-RSA-Signature. Khi callback body có data, MCV verify JSON-minified data; nếu không, verify JSON-minified callback body.

Khi InfoCMS xác nhận deposit, InfoCMS gọi:

POST https://app.mcv.network/infocms/e-collect/callback

Các reference field được chấp nhận gồm orderId, order_id, transUUID, trans_uuid, provider_reference, hoặc reference.

Callback verification:

Header CMS-RSA-Signature: RSA-SHA256 signature from InfoCMS
Verified by MCV with INFOCMS_PROVIDER_PUBLIC_KEY

Callback có idempotency. Ví chỉ được credit một lần bằng key:

infocms_qr:{provider_reference}:posted

Subscription Payment Và Invoice

Với payment có metadata.payment_purpose = service_subscription, callback InfoCMS không credit ví. Hệ thống chuyển kỳ thu tương ứng sang paid và phát hành invoice tự động.

Luồng:

Admin tạo service contract
-> hệ thống sinh service_billing_cycles
-> khách tạo QR Pay cho từng kỳ
-> InfoCMS callback xác nhận tiền về
-> payment = succeeded
-> billing cycle = paid
-> service invoice = issued
-> email gửi khách hàng + billing email + admin ops

Quy tắc:

  • Top-up ví không xuất hóa đơn vì đó là khoản đặt cọc.
  • Subscription/service fee chỉ xuất invoice sau khi tiền thật sự được ghi nhận.
  • Mỗi billing cycle chỉ có một invoice nhờ unique key service_billing_cycle_id.
  • Invoice có thể xem/in tại /subscriptions/invoices/{invoice}.
  • Nếu admin mark-paid thủ công, hệ thống cũng phát hành invoice theo cùng service idempotent.

MISA meInvoice

MCV đã chuẩn bị adapter MISA meInvoice ở chế độ chờ credential.

Root admin cấu hình tại:

/admin/system-settings

Khách hàng cấu hình thông tin xuất hóa đơn tại:

/profile

Billing profile lưu ở cấp account và gồm:

FieldÝ nghĩa
billing_legal_nameTên pháp lý công ty
billing_tax_idMã số thuế
billing_addressĐịa chỉ xuất hóa đơn
billing_emailEmail nhận hóa đơn
billing_contact_nameTên người nhận
billing_invoice_noteGhi chú/nội dung mong muốn trên hóa đơn

Các trường cần nhập khi MISA bàn giao:

FieldÝ nghĩa
meinvoice.enabledBật/tắt gửi HĐĐT sang MISA
meinvoice.base_urlBase URL API do MISA cung cấp
meinvoice.auth_endpointEndpoint lấy token nếu dùng username/password
meinvoice.issue_endpointEndpoint lập/phát hành hóa đơn
meinvoice.company_tax_codeMST MCV phát hành hóa đơn
meinvoice.app_idApp ID/client ID nếu MISA cấp
meinvoice.usernameUsername API
meinvoice.passwordPassword/client secret API
meinvoice.access_tokenToken tĩnh nếu MISA cấp thay cho login
meinvoice.template_codeMẫu hóa đơn
meinvoice.invoice_seriesKý hiệu/series hóa đơn
meinvoice.vat_percentVAT mặc định, thường 10%

Sau khi cấu hình, các invoice đang chờ sẽ được scheduler gửi lại mỗi 15 phút:

php artisan billing:submit-einvoices --limit=25

Trạng thái HĐĐT được lưu tại service_invoices.einvoice_status:

StatusÝ nghĩa
pending_configurationChưa đủ credential MISA
disabledMISA chưa bật
submittedĐã gửi sang MISA nhưng chưa thấy mã CQT/link tra cứu trong response
issuedĐã có dữ liệu phát hành như mã CQT, số hóa đơn hoặc link tra cứu
failedMISA trả lỗi hoặc API lỗi

Rút VND

User có thể yêu cầu rút VND từ Billing.

Số tiền VND -> quy đổi sang wallet amount USD -> reserve số dư ví -> tạo InfoCMS transfer request

Ví dụ:

Số tiền rútWallet Reserved
2,600,000 VND$100.00

Withdrawal request được lưu trong withdrawal_requests.

Khi InfoCMS xác nhận hoặc báo fail transfer, InfoCMS gọi:

POST https://app.mcv.network/infocms/transfer/callback

Nếu transfer fail, MCV hoàn lại wallet amount đã reserve một lần bằng:

withdrawal:{withdrawal_id}:refund

Biến Môi Trường

INFOCMS_ENABLED=false
INFOCMS_BASE_URL=
INFOCMS_ACCESS_TOKEN=
INFOCMS_CLIENT_ID=
INFOCMS_CLIENT_SECRET=
INFOCMS_MERCHANT_ID=
INFOCMS_BANK_CODE=
INFOCMS_MASTER_ID=
INFOCMS_MOTHER_ACCOUNT=
INFOCMS_ECOLLECTION_NAME="MCV Network"
INFOCMS_SIGNATURE_PRIVATE_KEY=
INFOCMS_PROVIDER_PUBLIC_KEY=
INFOCMS_LOGIN_ENDPOINT=/ocms/v1/auth/login
INFOCMS_CREATE_QUICK_QR_ENDPOINT=/ocms/v3/ec/create_quick_qr
INFOCMS_TRANSFER_ENDPOINT=/transfer

Khi INFOCMS_ENABLED=false, request chạy ở sandbox mode và lưu outbound payload vào metadata. Điều này cho phép product và finance test workflow trước khi cấu hình production credentials.