A generic multi-client payment gateway so FlatRender, meezi.ir and bargevasat.ir can all pay through ZarinPal's single verified callback domain (pay.flatrender.ir). New Go service services/payment (clones the notification skeleton + vendored deps): - migration 31_payment_broker.sql — `payment` schema: client_apps, transactions, webhook_deliveries. - ZarinPal v4 client ported from the proven identity PaymentService (request.json -> StartPay -> verify.json; codes 100/101). - client API: POST /v1/pay/request + /v1/pay/inquiry, authed by X-Api-Key + HMAC body signature; GET /callback/zarinpal (the single verified endpoint) verifies, then 302s the user back to the site's return_url (signed) and fires a signed, retried webhook. - per-client ZarinPal merchant override (default = shared merchant); amount stored canonically in Rial, unit to ZarinPal env-configurable. - admin API /v1/admin/* (FlatRender admin JWT): client-app CRUD + key issue/rotate + transactions list. Deploy wiring: payment-svc in docker-compose.v2.yml (host port 1607), pay.flatrender.ir server block in mirror-nginx conf, ENV_FILE + README updates (cert SAN + manual migration note). Admin UI: src/components/admin/PaymentsAdmin.tsx (client apps with one-time key reveal + rotate, transactions table) + /admin/payments page + nav link + fa/en strings; pay-admin proxy route to payment-svc. Docs/SDK: deploy/PAYMENTS.md (integration contract) + deploy/sdk/flatpay.js (zero-dep Node client + webhook verifier) for meezi/any site. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
reflect2
reflect api that avoids runtime reflect.Value cost
- reflect get/set interface{}, with type checking
- reflect get/set unsafe.Pointer, without type checking
reflect2.TypeByNameworks likeClass.forNamefound in java
json-iterator use this package to save runtime dispatching cost. This package is designed for low level libraries to optimize reflection performance. General application should still use reflect standard library.
reflect2.TypeByName
// given package is github.com/your/awesome-package
type MyStruct struct {
// ...
}
// will return the type
reflect2.TypeByName("awesome-package.MyStruct")
// however, if the type has not been used
// it will be eliminated by compiler, so we can not get it in runtime
reflect2 get/set interface
valType := reflect2.TypeOf(1)
i := 1
j := 10
valType.Set(&i, &j)
// i will be 10
to get set type, always use its pointer *type
reflect2 get/set unsafe.Pointer
valType := reflect2.TypeOf(1)
i := 1
j := 10
valType.UnsafeSet(unsafe.Pointer(&i), unsafe.Pointer(&j))
// i will be 10
to get set type, always use its pointer *type
benchmark
Benchmark is not necessary for this package. It does nothing actually.
As it is just a thin wrapper to make go runtime public.
Both reflect2 and reflect call same function
provided by runtime package exposed by go language.
unsafe safety
Instead of casting []byte to sliceHeader in your application using unsafe.
We can use reflect2 instead. This way, if sliceHeader changes in the future,
only reflect2 need to be upgraded.
reflect2 tries its best to keep the implementation same as reflect (by testing).