feat(payment): add native USDT payment provider with live CNY rate display#2915
Open
s258852s wants to merge 1 commit into
Open
feat(payment): add native USDT payment provider with live CNY rate display#2915s258852s wants to merge 1 commit into
s258852s wants to merge 1 commit into
Conversation
…splay Adds a first-class `usdt` payment provider so EasyPay-protocol crypto gateways that settle in stablecoins (e.g. self-hosted BEpusdt) can be configured directly from the admin UI, instead of being shoehorned into the alipay/wxpay sub-types of the generic EasyPay provider. ## Backend - New provider `payment/provider/usdt.go` builds EasyPay-style submit requests with the on-chain trade type sent natively (default `usdt.trc20`, configurable per instance). Sign/verify reuse the EasyPay MD5 helpers, so the provider only differs in the wire-level `type` field and the snapshot/notification metadata. - Provider key `usdt` registered in factory, types, webhook routes, webhook handler, `validProviderKeys`, sensitive-field list and the pending-order-protected config field list. PID is snapshotted on order create and verified on notification, matching how alipay / wxpay / easypay enforce merchant identity. - New endpoint `GET /api/v1/payment/usdt/rate` returns a cached (60s, singleflight, stale-on-error) CNY/USDT rate fetched from CoinGecko, used by the recharge UI to show the user the implied USDT amount before they leave Sub2API for the gateway's checkout. ## Frontend - USDT is selectable in admin provider management, with its own icon (`assets/icons/usdt.svg`) and brand color (#26A17B), wired through `providerConfig.ts`, the payment flow helpers, order tables/filters, i18n (zh + en) and `types/payment.ts`. - `PaymentMethodSelector` accepts an optional `usdtRate` + `usdtImpliedAmount` and, when USDT is among the visible methods, renders a "Live rate 1 USDT ≈ X CNY · pay ~Y USDT" hint plus a one-line note that the checkout page amount is authoritative. - `PaymentView` polls `/payment/usdt/rate` on mount and every 60s, passing the rate + entered amount to the selector; the line softly hides when the rate fetch fails so the UI never blocks. ## Why Without a native provider, hosting a crypto gateway required either overloading the EasyPay alipay/wxpay channel (confusing UI, brittle sign), or running an external re-signing bridge. The new provider is ~170 lines of code and fits cleanly into the existing EasyPay helpers — no protocol fork, no new dependencies. ## Not included - The fork-local GHA workflow that publishes the image to GHCR is intentionally omitted; consumers can keep using the upstream publishing pipeline. ## Testing - Verified end-to-end against a self-hosted BEpusdt instance: a real TRC20 payment (10.06 USDT for 68 CNY at live CoinGecko rate of 6.76) was created, confirmed on-chain, notified back via webhook, and credited to the user balance. - `go build ./...`, `golangci-lint`, `vue-tsc --noEmit` and the existing vitest critical suite all pass.
Contributor
|
Thank you for your contribution! Before we can merge this PR, we need you to sign our Contributor License Agreement (CLA). To sign, please reply with the following comment:
You only need to sign once — it will be valid for all your future contributions to this project. I have read the CLA Document and I hereby sign the CLA You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a first-class
usdtpayment provider so EasyPay-protocol crypto gateways that settle in stablecoins (e.g. self-hosted BEpusdt) can be configured directly from the admin UI, instead of being shoehorned into the alipay/wxpay sub-types of the generic EasyPay provider.Bundled with the provider is a small UX helper: a live CNY/USDT rate is shown beside the USDT method on the recharge page, so users know roughly how much USDT they will pay before being redirected to the gateway's checkout.
Motivation
Without a native provider, self-hosting a crypto gateway today requires either:
alipayorwxpaychannel — confusing UI, brittle signing semantics, and the order'spayment_typedoes not match what the user actually paid in.A real
usdtprovider is ~170 lines that fits cleanly into the existing EasyPay helpers, with no new dependencies or protocol fork.What's added
Backend
payment/provider/usdt.go— new provider, builds EasyPay-style submit requests with the on-chain trade type sent natively (usdt.trc20by default, configurable per instance). Sign/verify reuse the EasyPay MD5 helpers; only the wire-leveltypefield and the snapshot/notification metadata differ from EasyPay.usdtregistered infactory,types, webhook routes, webhook handler,validProviderKeys, sensitive-field list, and the pending-order-protected config field list.GET /api/v1/payment/usdt/rate— cached (60s, singleflight, stale-on-error) CNY/USDT rate fetched from CoinGecko. Used by the recharge UI to preview the implied USDT amount.Frontend
assets/icons/usdt.svg) and brand color (#26A17B), wired throughproviderConfig.ts, the payment flow helpers, admin order tables/filters, i18n (zh + en) andtypes/payment.ts.PaymentMethodSelectoraccepts an optionalusdtRate+usdtImpliedAmount. When USDT is among the visible methods, it renders an inline hint —Live rate 1 USDT ≈ X CNY · pay ~Y USDT— plus a one-line note that the checkout page amount is authoritative.PaymentViewpolls/payment/usdt/rateon mount and every 60s, passing the rate + entered amount to the selector. The line softly hides if the rate fetch fails, so the UI never blocks.Compatibility
payment_provider_instancesJSON config.Testing
go build ./...,golangci-lint,vue-tsc --noEmitand the existing vitest critical suite all pass.CLA
I will sign the CLA in a separate comment below.