Class: Tingee::Client
- Inherits:
-
Object
- Object
- Tingee::Client
- Defined in:
- lib/tingee/client.rb
Overview
HTTP + endpoint methods. Only live-verified endpoints are wrapped — no speculative "complete SDK". Responses use a uniform message, data envelope EXCEPT get-banks, which returns a bare array (verified live).
Instance Method Summary collapse
-
#confirm_delete_va(bank_bin:, confirm_id:, otp_number:) ⇒ Object
POST /v1/confirm-delete-va — finishes the unlink with the bank's OTP.
- #confirm_register_notify(bank_bin:, confirm_id:, otp_number:) ⇒ Object
-
#confirm_va(bank_bin:, confirm_id:, otp_number:) ⇒ Object
POST /v1/confirm-va — finishes the link with the bank's OTP.
-
#create_bank_link_session(merchant_id: nil, redirect_url: nil, allowed_banks: nil, bank_name: nil, shop_id: nil) ⇒ Object
POST /v1/create-bank-link-session — returns the SDK URL string (data).
-
#create_va(bank_bin:, account_number:, account_name:, identity:, mobile:, webhook_url:, account_type: "personal-account", is_notify_account_number: false) ⇒ Object
POST /v1/create-va — starts a manual bank link (the raw API chain, usable when Tingee's hosted JS SDK is unavailable or broken — docs/tingee-api-reference.md §create-va, live-verified).
-
#create_va_vcb(account_number:, mobile:, request_id: SecureRandom.uuid, bank_name: "VCB", merchant_id: nil, merchant_name: nil, merchant_address: nil, shop_id: nil, redirect_url: nil, webhook_url: nil, va_prefix: nil, va_suffix: nil, app_type: "baas", account_type: "personal-account") ⇒ Object
POST /v1/create-va — VCB personal-account variant (docs/tingee-vcb-personal-link.md).
-
#delete_va(bank_name:, va_account_number:) ⇒ Object
POST /v1/delete-va — starts an unlink.
-
#get_banks ⇒ Object
GET /v1/get-banks — returns the bare bank array (the supported-bank/BIN map).
-
#get_transactions(start_time:, end_time:, filter: nil, skip_count: nil, max_result_count: nil, merchant_id: nil, shop_ids: nil, va_account_numbers: nil, bank_bin: nil) ⇒ Object
POST /v1/transaction/get-paging — transaction history.
-
#get_va_paging(merchant_id: nil) ⇒ Object
POST /v1/get-va-paging — returns items of linked virtual accounts.
-
#initialize(config = Tingee.config, read_timeout: 90) ⇒ Client
constructor
read_timeout: web requests keep the 90s default (stay under your proxy's response timeout); background jobs should pass a larger value — bank-side OTP verification on confirm_va can take minutes.
-
#register_notify(bank_bin:, va_account_number:) ⇒ Object
POST /v1/register-notify — ACB only, run once right after confirm_va succeeds.
Constructor Details
#initialize(config = Tingee.config, read_timeout: 90) ⇒ Client
read_timeout: web requests keep the 90s default (stay under your proxy's response timeout); background jobs should pass a larger value — bank-side OTP verification on confirm_va can take minutes.
14 15 16 17 18 |
# File 'lib/tingee/client.rb', line 14 def initialize(config = Tingee.config, read_timeout: 90) @config = config @read_timeout = read_timeout @config.validate! end |
Instance Method Details
#confirm_delete_va(bank_bin:, confirm_id:, otp_number:) ⇒ Object
POST /v1/confirm-delete-va — finishes the unlink with the bank's OTP. Params ride the BODY this time (unlike delete_va's query string above), and the bank is identified by bankBin here — bankName gets ignored and Tingee then fails with "Lỗi hệ thống phương thức xác thực" (seen live 2026-07-17).
125 126 127 |
# File 'lib/tingee/client.rb', line 125 def confirm_delete_va(bank_bin:, confirm_id:, otp_number:) post("/v1/confirm-delete-va", { bankBin: bank_bin, confirmId: confirm_id, otpNumber: otp_number }) end |
#confirm_register_notify(bank_bin:, confirm_id:, otp_number:) ⇒ Object
109 110 111 |
# File 'lib/tingee/client.rb', line 109 def confirm_register_notify(bank_bin:, confirm_id:, otp_number:) post("/v1/confirm-register-notify", { bankBin: bank_bin, confirmId: confirm_id, otpNumber: otp_number }) end |
#confirm_va(bank_bin:, confirm_id:, otp_number:) ⇒ Object
POST /v1/confirm-va — finishes the link with the bank's OTP. Returns accountType, accountNumber (real), vaAccountNumber (routing key), shopId.
99 100 101 |
# File 'lib/tingee/client.rb', line 99 def confirm_va(bank_bin:, confirm_id:, otp_number:) post("/v1/confirm-va", { bankBin: bank_bin, confirmId: confirm_id, otpNumber: otp_number }) end |
#create_bank_link_session(merchant_id: nil, redirect_url: nil, allowed_banks: nil, bank_name: nil, shop_id: nil) ⇒ Object
POST /v1/create-bank-link-session — returns the SDK URL string (data). No merchant_id is needed for the default merchant; pass one only for a sub-merchant.
27 28 29 30 31 32 33 34 35 |
# File 'lib/tingee/client.rb', line 27 def create_bank_link_session(merchant_id: nil, redirect_url: nil, allowed_banks: nil, bank_name: nil, shop_id: nil) payload = { type: "bank-link" } payload[:merchantId] = merchant_id if merchant_id payload[:redirectUrl] = redirect_url if redirect_url payload[:allowedBanks] = Array(allowed_banks) if allowed_banks payload[:bankName] = bank_name if bank_name payload[:shopId] = shop_id if shop_id post("/v1/create-bank-link-session", payload) end |
#create_va(bank_bin:, account_number:, account_name:, identity:, mobile:, webhook_url:, account_type: "personal-account", is_notify_account_number: false) ⇒ Object
POST /v1/create-va — starts a manual bank link (the raw API chain, usable when
Tingee's hosted JS SDK is unavailable or broken — docs/tingee-api-reference.md
§create-va, live-verified). The bank then sends/pushes an OTP to mobile.
Returns otpMethod. identity/mobile should never be persisted
by the caller.
is_notify_account_number: FALSE is the DEFAULT because it is the mode proved end-to-end — a real VietQR transfer to the linked real account fired the webhook on a notify=false link (2026-07-16). notify=true is documented as "watch the real account" and MAY also work, but was never confirmed to fire on a plain transfer; do not switch the default to true without a real-transfer test on a true link.
55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/tingee/client.rb', line 55 def create_va(bank_bin:, account_number:, account_name:, identity:, mobile:, webhook_url:, account_type: "personal-account", is_notify_account_number: false) payload = { accountType: account_type, bankBin: bank_bin, accountNumber: account_number, accountName: account_name, identity: identity, mobile: mobile, isNotifyAccountNumber: is_notify_account_number, webhookUrl: webhook_url } payload[:shopId] = @config.shop_id if @config.shop_id post("/v1/create-va", payload) end |
#create_va_vcb(account_number:, mobile:, request_id: SecureRandom.uuid, bank_name: "VCB", merchant_id: nil, merchant_name: nil, merchant_address: nil, shop_id: nil, redirect_url: nil, webhook_url: nil, va_prefix: nil, va_suffix: nil, app_type: "baas", account_type: "personal-account") ⇒ Object
POST /v1/create-va — VCB personal-account variant (docs/tingee-vcb-personal-link.md).
UNLIKE create_va above, VCB has no OTP confirm step: it returns a deepLink
(vcbpartner://…) you open in VCB Digibank; the customer confirms there and the
RESULT arrives asynchronously on your webhook_url as a webhook with
status "confirm-va-success" | "confirm-va-failed".
request_id is echoed back on that webhook — pass and STORE your own to correlate (defaults to a fresh UUID otherwise). Optional params are only sent when given. Returns Tingee's data payload, an array: [deepLink].
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/tingee/client.rb', line 77 def create_va_vcb(account_number:, mobile:, request_id: SecureRandom.uuid, bank_name: "VCB", merchant_id: nil, merchant_name: nil, merchant_address: nil, shop_id: nil, redirect_url: nil, webhook_url: nil, va_prefix: nil, va_suffix: nil, app_type: "baas", account_type: "personal-account") payload = { requestId: request_id, bankName: bank_name, accountNumber: account_number, accountType: account_type, mobile: mobile, appType: app_type } payload[:merchantId] = merchant_id if merchant_id payload[:merchantName] = merchant_name if merchant_name shop_id ||= @config.shop_id # one shop per project — same grouping as create_va payload[:merchantAddress] = merchant_address if merchant_address payload[:shopId] = shop_id if shop_id payload[:redirectUrl] = redirect_url if redirect_url payload[:webhookUrl] = webhook_url if webhook_url payload[:vaPrefix] = va_prefix if va_prefix payload[:vaSuffix] = va_suffix if va_suffix post("/v1/create-va", payload) end |
#delete_va(bank_name:, va_account_number:) ⇒ Object
POST /v1/delete-va — starts an unlink. Params ride the QUERY STRING (not the
JSON body) and identify the bank by bankName (Tingee's short bank CODE, e.g.
"STB") — NOT bankBin. Verified live 2026-07-16; Tingee is inconsistent here
(confirm-delete-va below takes the body instead). Returns confirmId.
117 118 119 |
# File 'lib/tingee/client.rb', line 117 def delete_va(bank_name:, va_account_number:) request(:post, "/v1/delete-va", query: { bankName: bank_name, vaAccountNumber: va_account_number }) end |
#get_banks ⇒ Object
GET /v1/get-banks — returns the bare bank array (the supported-bank/BIN map).
21 22 23 |
# File 'lib/tingee/client.rb', line 21 def get_banks get("/v1/get-banks") end |
#get_transactions(start_time:, end_time:, filter: nil, skip_count: nil, max_result_count: nil, merchant_id: nil, shop_ids: nil, va_account_numbers: nil, bank_bin: nil) ⇒ Object
POST /v1/transaction/get-paging — transaction history. start_time/end_time
are required, format "yyyyMMddHHmmss" (UTC+7); Tingee caps each query at a
10-day window (over that it returns an error — not enforced here). Optional
params are only sent when given. Returns items.
133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/tingee/client.rb', line 133 def get_transactions(start_time:, end_time:, filter: nil, skip_count: nil, max_result_count: nil, merchant_id: nil, shop_ids: nil, va_account_numbers: nil, bank_bin: nil) payload = { startTime: start_time, endTime: end_time } payload[:filter] = filter if filter payload[:skipCount] = skip_count if skip_count payload[:maxResultCount] = max_result_count if max_result_count payload[:merchantId] = merchant_id if merchant_id payload[:shopIds] = Array(shop_ids) if shop_ids payload[:vaAccountNumbers] = Array(va_account_numbers) if va_account_numbers payload[:bankBin] = bank_bin if bank_bin post("/v1/transaction/get-paging", payload) end |
#get_va_paging(merchant_id: nil) ⇒ Object
POST /v1/get-va-paging — returns items of linked virtual accounts.
38 39 40 41 42 |
# File 'lib/tingee/client.rb', line 38 def get_va_paging(merchant_id: nil) payload = {} payload[:merchantId] = merchant_id if merchant_id post("/v1/get-va-paging", payload) end |
#register_notify(bank_bin:, va_account_number:) ⇒ Object
POST /v1/register-notify — ACB only, run once right after confirm_va succeeds. Returns confirmId for a second OTP round (see #confirm_register_notify).
105 106 107 |
# File 'lib/tingee/client.rb', line 105 def register_notify(bank_bin:, va_account_number:) post("/v1/register-notify", { vaAccountNumber: va_account_number, bankBin: bank_bin }) end |