Skip to content

QR / MPM

QR / MPM

Merchant-Presented-Mode QR: generate, decode, bayar host-to-host, query, batalkan, dan refund — plus alur One-Time-Token yang dipakai ApplyOTT.

resp, err := transfercredit.GenerateQRMPM(ctx, transport, hb, transfercredit.GenerateQRMPMRequest{
	PartnerReferenceNo: "2020102900000000000001",
	Amount: &snap.Money{Value: "500000.00", Currency: "IDR"},
	FeeAmount: &snap.Money{Value: "500000.00", Currency: "IDR"},
})
if err != nil {
	// errors.Is(err, snap.ErrBadRequest), snap.ErrUnauthorized, etc.
}

GenerateQRMPM

Memanggil endpoint SNAP Generate QR MPM (Service Code 47, path …/{version}/qr/qr-mpm-generate, HTTP POST — tanpa override method). hb harus sudah membawa setiap field yang dibutuhkan snap.HeaderBuilder kecuali Body, yang diatur sendiri oleh GenerateQRMPM agar byte hasil marshal yang sama persis dipakai untuk signing dan wire body.

Tidak idempotent dan package ini tidak melakukan retry. Bila memanggil ulang setelah gagal/timeout, gunakan X-EXTERNAL-ID yang sama — deteksi duplikat di server mengacu pada header ini.

func GenerateQRMPM(ctx context.Context, t *snap.Transport, hb snap.HeaderBuilder, req GenerateQRMPMRequest) (GenerateQRMPMResponse, error)

Request — GenerateQRMPMRequest

Semua field Opsional — tidak ada field yang didokumentasikan Wajib.

FieldTypePresence
partnerReferenceNostringOpsional
amount*snap.MoneyOpsional
feeAmount*snap.MoneyOpsional
merchantIdstringOpsional
subMerchantIdstringOpsional
storeIdstringOpsional
terminalIdstringOpsional
validityPeriodstringOpsional

Response — GenerateQRMPMResponse

QRContent, QRURL, dan QRImage membentuk kondisi one-of-three yang tidak bisa diekspresikan sistem tipe: menurut standar, “jika qrContent kosong, qrUrl atau qrImage harus diisi.” Ketiganya dimodelkan Opsional di sini — pemanggil harus mengecek mana yang benar-benar terisi.

FieldTypePresence
responseCodestringWajib
responseMessagestringWajib
qrContentstringOpsional
qrUrlstringOpsional
redirectUrlstringOpsional
merchantNamestringOpsional
storeIdstringOpsional
terminalIdstringOpsional

ApplyOTT

Memanggil endpoint SNAP Payment Redirect - Apply OTT (Service Code 49, path …/{version}/qr/apply-ott, HTTP POST — tanpa override method). hb harus sudah membawa setiap field yang dibutuhkan snap.HeaderBuilder kecuali Body, yang diatur sendiri oleh ApplyOTT agar byte hasil marshal yang sama persis dipakai untuk signing dan wire body.

Tidak idempotent dan package ini tidak melakukan retry. Bila memanggil ulang setelah gagal/timeout, gunakan X-EXTERNAL-ID yang sama — deteksi duplikat di server mengacu pada header ini.

func ApplyOTT(ctx context.Context, t *snap.Transport, hb snap.HeaderBuilder, req ApplyOTTRequest) (ApplyOTTResponse, error)

Endpoint ini tidak punya request body bertipe selain parameter panggilan di atas.

Response — ApplyOTTResponse

FieldTypePresence
responseCodestringWajib
responseMessagestringWajib
userResources[]ApplyOTTUserResourceWajib
Field ApplyOTTUserResource

Satu entri dalam array userResources pada ApplyOTTResponse. Meski nama field-nya sama dengan request, ini bentuk yang berbeda (objek, bukan string biasa).

FieldTypePresence
resourceTypestringWajib
valuestringWajib

DecodeQRMPM

Memanggil endpoint SNAP Decode QR MPM (Service Code 48, path …/{version}/qr/qr-mpm-decode, HTTP POST — tanpa override method). hb harus sudah membawa setiap field yang dibutuhkan snap.HeaderBuilder kecuali Body, yang diatur sendiri oleh DecodeQRMPM agar byte hasil marshal yang sama persis dipakai untuk signing dan wire body.

Ini decode read-only; tidak seperti GenerateQRMPM, tidak ada catatan non-idempotency.

func DecodeQRMPM(ctx context.Context, t *snap.Transport, hb snap.HeaderBuilder, req DecodeQRMPMRequest) (DecodeQRMPMResponse, error)

Request — DecodeQRMPMRequest

QRContent dan ScanTime wajib.

FieldTypePresence
partnerReferenceNostringOpsional
qrContentstringWajib
amount*snap.MoneyOpsional
merchantIdstringOpsional
subMerchantIdstringOpsional
scanTimestringWajib

Response — DecodeQRMPMResponse

ReferenceNo dan RedirectURL sama-sama dimodelkan Opsional — kondisi wajib dari standar untuk keduanya saling kontradiktif, jadi tidak ada yang dipaksakan di sini.

FieldTypePresence
responseCodestringWajib
responseMessagestringWajib
referenceNostringOpsional
redirectUrlstringOpsional
merchantNamestringOpsional
merchantCategorystringOpsional
merchantLocationstringOpsional
merchantInfos[]MPMMerchantInfoWajib
transactionAmount*snap.MoneyOpsional
feeAmount*snap.MoneyOpsional
Field MPMMerchantInfo

Satu entri dalam array merchantInfos pada DecodeQRMPMResponse.

MerchantPAN didokumentasikan numerik tapi dikirim sebagai string berkutip di wire — bentuk ambigu, jadi diketik json.RawMessage, bukan string atau tipe numerik.

FieldTypePresence
merchantPANjson.RawMessageWajib
acquirerNamestringWajib

QRMPMPaymentH2H

Memanggil endpoint SNAP Payment - Host to Host (Service Code 50, path …/{version}/qr/qr-mpm-payment, HTTP POST — tanpa override method). hb harus sudah membawa setiap field yang dibutuhkan snap.HeaderBuilder kecuali Body, yang diatur sendiri oleh QRMPMPaymentH2H agar byte hasil marshal yang sama persis dipakai untuk signing dan wire body.

Tidak idempotent dan package ini tidak melakukan retry. Bila memanggil ulang setelah gagal/timeout, gunakan X-EXTERNAL-ID yang sama — deteksi duplikat di server mengacu pada header ini.

func QRMPMPaymentH2H(ctx context.Context, t *snap.Transport, hb snap.HeaderBuilder, req QRMPMPaymentH2HRequest) (QRMPMPaymentH2HResponse, error)

Request — QRMPMPaymentH2HRequest

PartnerReferenceNo wajib; field lain Opsional.

VerificationID juga muncul di response dengan nama sama tapi batas panjang terdokumentasi berbeda — keduanya sama-sama string biasa di Go, package ini tidak menegakkan batas panjang.

FieldTypePresence
partnerReferenceNostringWajib
merchantIdstringOpsional
subMerchantIdstringOpsional
amount*snap.MoneyOpsional
feeAmount*snap.MoneyOpsional
otpstringOpsional
verificationIdstringOpsional

Response — QRMPMPaymentH2HResponse

FieldTypePresence
responseCodestringWajib
responseMessagestringWajib
referenceNostringOpsional
transactionDatestringOpsional
verificationIdstringOpsional

QR MPM Payment Notification

Hanya masuk (inbound) — package ini tidak memanggil endpoint untuk ini. Partner/switcher yang POST ke callback URL Anda; unmarshal body ke QRMPMPaymentNotificationRequest setelah memverifikasinya dengan snap.ServerVerifier (lihat Verifying inbound requests), lalu balas dengan bentuk di bawah.

Diterima — QRMPMPaymentNotificationRequest

Ini adalah callback settlement yang diterima PJP, bukan panggilan dari package ini — buat HTTP handler sendiri untuk path ini, autentikasi dengan ServerVerifier.VerifyTransactionRequest, lalu json.Unmarshal body ke tipe ini. OriginalReferenceNo dan LatestTransactionStatus wajib; field lain Opsional.

FieldTypePresence
originalReferenceNostringWajib
originalPartnerReferenceNostringOpsional
latestTransactionStatusstringWajib
customerNumberstringOpsional
accountTypestringOpsional
destinationNumberstringOpsional
destinationAccountNamestringOpsional
amount*snap.MoneyOpsional
sessionIdstringOpsional
bankCodestringOpsional
externalStoreIdstringOpsional

Handler Anda membalas dengan — QRMPMPaymentNotificationResponse

Tidak ada field lain selain envelope standar responseCode/responseMessage.

FieldTypePresence
responseCodestringWajib
responseMessagestringWajib

QRMPMQueryPayment

Memanggil endpoint SNAP Query Payment (Service Code 51, path …/{version}/qr/qr-mpm-query, HTTP POST — tanpa override method). hb harus sudah membawa setiap field yang dibutuhkan snap.HeaderBuilder kecuali Body, yang diatur sendiri oleh QRMPMQueryPayment agar byte hasil marshal yang sama persis dipakai untuk signing dan wire body.

Query status read-only; tidak ada catatan non-idempotency, sama seperti TransactionStatusInquiryBank.

func QRMPMQueryPayment(ctx context.Context, t *snap.Transport, hb snap.HeaderBuilder, req QRMPMQueryPaymentRequest) (QRMPMQueryPaymentResponse, error)

Request — QRMPMQueryPaymentRequest

Field dasar yang sama dengan TransactionStatusInquiryBankRequest, ditambah MerchantID, SubMerchantID, dan ExternalStoreID. ServiceCode satu-satunya field wajib.

FieldTypePresence
originalPartnerReferenceNostringOpsional
originalReferenceNostringOpsional
originalExternalIdstringOpsional
serviceCodestringWajib
transactionDatestringOpsional
amount*snap.MoneyOpsional
merchantIdstringOpsional
subMerchantIdstringOpsional
externalStoreIdstringOpsional
additionalInfojson.RawMessageOpsional

Response — QRMPMQueryPaymentResponse

Field yang sama dengan TransactionStatusInquiryBankResponse, ditambah PaidTime dan TerminalID.

FieldTypePresence
responseCodestringWajib
responseMessagestringWajib
originalPartnerReferenceNostringOpsional
originalReferenceNostringOpsional
originalExternalIdstringOpsional
serviceCodestringOpsional
transactionDatestringOpsional
amount*snap.MoneyOpsional
beneficiaryAccountNostringWajib
beneficiaryBankCodestringOpsional
previousResponseCodestringOpsional
referenceNumberstringWajib
sourceAccountNostringWajib
transactionIdstringOpsional
latestTransactionStatusstringWajib
transactionStatusDescstringOpsional
additionalInfojson.RawMessageOpsional
paidTimestringOpsional
terminalIdstringOpsional

QRMPMCancelPayment

Memanggil endpoint SNAP Cancel Payment (Service Code 77, path …/{version}/qr/qr-mpm-cancel, HTTP POST — tanpa override method). hb harus sudah membawa setiap field yang dibutuhkan snap.HeaderBuilder kecuali Body, yang diatur sendiri oleh QRMPMCancelPayment agar byte hasil marshal yang sama persis dipakai untuk signing dan wire body.

Tidak idempotent dan package ini tidak melakukan retry. Bila memanggil ulang setelah gagal/timeout, gunakan X-EXTERNAL-ID yang sama — deteksi duplikat di server mengacu pada header ini.

func QRMPMCancelPayment(ctx context.Context, t *snap.Transport, hb snap.HeaderBuilder, req QRMPMCancelPaymentRequest) (QRMPMCancelPaymentResponse, error)

Request — QRMPMCancelPaymentRequest

Berbeda dari endpoint pola originalX lain di package ini, baris ini tidak mendokumentasikan field serviceCode dan ketiga field originalX-nya Opsional — MerchantID dan Reason satu-satunya yang wajib.

FieldTypePresence
originalPartnerReferenceNostringOpsional
originalReferenceNostringOpsional
originalExternalIdstringOpsional
merchantIdstringWajib
subMerchantIdstringOpsional
externalStoreIdstringOpsional
reasonstringWajib
amount*snap.MoneyOpsional

Response — QRMPMCancelPaymentResponse

CancelTime Kondisional (dimodelkan Opsional, sesuai penanganan standar package ini — lihat Core Conventions); TransactionDate Opsional.

FieldTypePresence
responseCodestringWajib
responseMessagestringWajib
cancelTimestringOpsional
transactionDatestringOpsional

QRMPMRefundPayment

Memanggil endpoint SNAP Refund Payment (Service Code 78, path …/{version}/qr/qr-mpm-refund, HTTP POST — tanpa override method). hb harus sudah membawa setiap field yang dibutuhkan snap.HeaderBuilder kecuali Body, yang diatur sendiri oleh QRMPMRefundPayment agar byte hasil marshal yang sama persis dipakai untuk signing dan wire body.

Tidak idempotent dan package ini tidak melakukan retry. Bila memanggil ulang setelah gagal/timeout, gunakan X-EXTERNAL-ID yang sama — deteksi duplikat di server mengacu pada header ini.

func QRMPMRefundPayment(ctx context.Context, t *snap.Transport, hb snap.HeaderBuilder, req QRMPMRefundPaymentRequest) (QRMPMRefundPaymentResponse, error)

Request — QRMPMRefundPaymentRequest

OriginalPartnerReferenceNo dan PartnerRefundNo wajib; field lain Opsional.

FieldTypePresence
merchantIdstringOpsional
subMerchantIdstringOpsional
externalStoreIdstringOpsional
originalPartnerReferenceNostringWajib
originalReferenceNostringOpsional
originalExternalIdstringOpsional
partnerRefundNostringWajib
refundAmount*snap.MoneyOpsional
reasonstringOpsional

Response — QRMPMRefundPaymentResponse

RefundNo dan RefundTime wajib; PartnerRefundNo dan RefundAmount Opsional (dikembalikan lagi, tidak dijamin selalu ada).

FieldTypePresence
responseCodestringWajib
responseMessagestringWajib
refundNostringWajib
partnerRefundNostringOpsional
refundAmount*snap.MoneyOpsional
refundTimestringWajib