go-pay/gopay: a Go SDK that aggregates WeChat Pay, Alipay and eight other payment channels
微信、支付宝、抖音、通联支付、拉卡拉、PayPal、Apple 的Go版本SDK。【极简、易用的聚合支付SDK】
At a glance
- What is it?
- gopay is an Apache-2.0 Go module that wraps the HTTP APIs of Alipay, WeChat Pay, Douyin, QQ, Allinpay, Lakala, PayPal, Saobei, CMB and Apple receipt verification behind per-channel client types. It is for Go backend teams that need more than one of those channels and do not want to hand-roll ten signing schemes.
- Who is it for?
- Adopt gopay if you are a Go shop integrating two or more of the covered channels and you are willing to read each doc/ file and the matching client_test.go before writing code, because that is where the working call patterns live. Stay away if you need only one channel: the official SDK for that channel is a smaller dependency, and gopay's value is the shared client, logging and HTTP layer across channels, not any single integration.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 40 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem gopay solves: ten payment APIs, one Go import path
Each Chinese payment platform ships its own request signing, its own callback verification and its own error envelope. WeChat Pay V3 signs with RSA over a canonical string and expects a platform certificate for verification. Alipay V3 signs differently and has its own response wrapper. Allinpay, Lakala, Saobei and CMB each add another scheme on top. A Go team that accepts three of these ends up maintaining three unrelated HTTP stacks, three retry policies and three logging conventions.
gopay puts those channels in one module. The repository layout makes the split explicit: alipay/, wechat/, douyin/, qq/, allinpay/, lakala/, paypal/, saobei/, cmbpay/ and apple/ are top-level directories, with pkg/ holding shared code. The README describes the project as an aggregated payment SDK and links a separate document per channel under doc/. The intended reader is a Go backend engineer who already knows which platforms the business needs and wants the signing and transport handled once.
Per-channel clients on a shared pkg/ layer
The architecture is a thin channel layer over shared helpers. Each channel directory exposes a client type with methods that map to that platform's endpoints, and the cross-cutting concerns live in pkg/. The README names pkg/xhttp for the HTTP client and xlog for logging, and go.mod shows the module depends on github.com/go-pay/crypto, github.com/go-pay/xlog, github.com/go-pay/util, github.com/go-pay/xtime, github.com/go-pay/smap and github.com/go-pay/errgroup alongside golang.org/x/crypto.
That dependency set tells you where the shared work sits: crypto for signing primitives, xlog for the XLogger interface, xtime for timestamps, smap for ordered or safe maps, errgroup for concurrent calls. The client itself is injectable. The README states that after constructing a client you can call SetHttpClient to replace the HTTP client and SetLogger to replace the logger, and that the custom logger only needs to implement the xlog.XLogger interface. So the seams are the transport and the log sink, not the signing logic. If you need to change how a signature is computed, you are editing inside a channel package, not configuring it.
Installing gopay and reading the version at runtime
The README's install section is one command. The module path is the repository path, and go.mod declares go 1.25.0, so your toolchain needs to satisfy that directive.
go get github.com/go-pay/gopayThe README then shows how to confirm which build you are running by importing the root package and logging gopay.Version through xlog:
import (
"github.com/go-pay/gopay"
"github.com/go-pay/xlog"
)
func main() {
xlog.Info("GoPay Version: ", gopay.Version)
}That is the whole first run: no client construction, no credentials. It is a reasonable smoke test for a vendored or pinned build, because it prints the constant rather than reading module metadata. For an actual call you have to pick a channel, and the README is blunt about where the examples are: read the xxx_test.go files, listing gopay/wechat/v3/client_test.go, gopay/alipay/v3/client_test.go, gopay/alipay/client_test.go, gopay/qq/client_test.go, gopay/allinpay/client_test.go, gopay/lakala/client_test.go, gopay/paypal/client_test.go and gopay/apple/verify_test.go, plus gopay/examples/douyin/douyin.go as sample code. There is also a separate reference project, go-pay/gopay-platform, for integration patterns. Treat the test files as the API documentation, because the README does not inline per-channel request examples.
TLS verification changed in v1.5.119, and sandbox work pays for it
The README's own notes section carries the most consequential change in the project's recent history. Before v1.5.119, pkg/xhttp.NewClient() defaulted to tls.Config{InsecureSkipVerify: true}, which the README describes as a man-in-the-middle risk and tags CWE-295. From v1.5.119 the default follows the Go standard library's secure configuration.
The README argues this does not affect production, because the official domains of the payment platforms present trusted certificates. The cost lands on sandbox and self-signed certificate setups, which must now opt back in deliberately. The documented path is to build an xhttp client with a custom TLS config and inject it:
import (
"crypto/tls"
"github.com/go-pay/gopay/pkg/xhttp"
)
hc := xhttp.NewClient().SetHttpTLSConfig(&tls.Config{InsecureSkipVerify: true})
client.SetHttpClient(hc)The README states this injection is supported for wechat, alipay, douyin, paypal, qq, allinpay, lakala and saobei. Note what that sentence does not include: cmbpay and apple are absent from the list, so if you rely on a self-signed endpoint for either of those, the README does not tell you the injection works there. That is a gap worth confirming in the source before you build a test harness around it.
Where gopay is the wrong choice
The README points developers at test files instead of a generated API reference. That is a real cost. If your team wants typed request and response structs for every field, with an upgrade path that flags breaking signature changes, you are reading Go source to find out what a call does. The doc/ directory holds per-channel guides, but the README itself does not inline the request shapes, so the depth of each guide is something you have to check per channel rather than assume.
The second boundary is breadth versus depth. Ten channels in one module means each channel moves at the pace of whoever maintains it. The README notes that WeChat merchant transfer was upgraded to support the new merchant transfer interface, which is the kind of platform-side change that has to be chased per channel. If you use exactly one platform, the official SDK for that platform is a smaller surface with a single vendor behind it. gopay's advantage is shared transport, logging and client injection across channels; with one channel there is nothing to share.
The third is version pinning. Because the TLS default flipped at v1.5.119, a stale go.sum can silently keep the insecure default. If you inherited a project pinned below that version, the README's note is the reason to move, and the release_note.md file is where the project records the change.
How gopay differs from a single-vendor SDK
Take the official Alipay or WeChat Pay Go SDK as the alternative. The difference is not feature parity, it is ownership of the transport layer. A vendor SDK is written by the platform for its own API, so it tracks that platform's changes closely and its types match the platform's documentation one to one. It also does nothing for your second payment channel.
gopay inverts that. It owns the HTTP client, the logger and the signing helpers in pkg/, then implements each platform against those shared pieces. The payoff is uniform operations: one SetHttpClient call changes transport for every channel, one SetLogger call routes every channel's logs into your existing sink, and a team that adds Lakala after shipping WeChat Pay does not add a second logging convention. The price is that gopay sits between you and the vendor, so a platform change arrives when the maintainer lands it. The README's note about the new WeChat merchant transfer interface is exactly that dynamic in miniature.
Licence and the cost of keeping up
gopay is Apache-2.0. That permissive licence allows commercial use and modification, and it includes a patent grant and a notice requirement, but this is not legal advice and your counsel should read the LICENSE file in the repository root before you redistribute anything.
The practical upgrade cost is the drift between the module and the platforms it wraps. Recent releases show a steady cadence: v1.5.121 on 2026-06-28, v1.5.122 on 2026-07-03, v1.5.123 on 2026-08-22. The last push to the default branch was on 2026-08-22, the same day as v1.5.123. Numbers like that tell you the project is being touched, not that any given channel is current, so the thing to watch is release_note.md, which the README links as the version changelog. The go.mod toolchain requirement of Go 1.25.0 is a second upgrade cost: it moves with the language, and a team on an older toolchain has to move with it. The README also mentions paid technical consulting and a WeChat group for questions, which means some support flows outside the repository and is not something you can audit after the fact.
Editorial conclusion
Adopt gopay if you are a Go shop integrating two or more of the covered channels and you are willing to read each doc/ file and the matching client_test.go before writing code, because that is where the working call patterns live. Stay away if you need only one channel: the official SDK for that channel is a smaller dependency, and gopay's value is the shared client, logging and HTTP layer across channels, not any single integration. Verify two things first: that the module version you pin is at or above v1.5.119, since the release notes state TLS certificate verification became the default there and earlier versions shipped InsecureSkipVerify: true, and that the channel you need still has a doc page under doc/ plus a test file, since the README lists the per-channel documents and that list is the honest scope statement.
Frequently asked questions
How do I install go-pay/gopay in a Go project?
Run go get github.com/go-pay/gopay. The module declares go 1.25.0 in its go.mod, so your toolchain has to satisfy that directive.
Which payment platforms does go-pay/gopay support?
The README lists Alipay V3 and the older Alipay API, WeChat Pay V3 and V2, Douyin, CMB aggregated payment, QQ, Allinpay, Lakala, PayPal, Apple receipt verification and Saobei, each with a document under doc/.
Does go-pay/gopay still skip TLS certificate verification by default?
No. The README states that from v1.5.119 pkg/xhttp.NewClient() uses the Go standard library's secure TLS configuration instead of tls.Config{InsecureSkipVerify: true}, and that sandbox or self-signed setups must inject a client with a custom TLS config via SetHttpClient.
Where are the usage examples for go-pay/gopay?
The README points at the per-channel test files, such as gopay/wechat/v3/client_test.go and gopay/alipay/v3/client_test.go, plus gopay/examples/douyin/douyin.go, and mentions the go-pay/gopay-platform project as a reference integration.
Can I replace the HTTP client or logger that go-pay/gopay uses?
Yes. The README documents SetHttpClient for injecting a custom xhttp client and SetLogger for injecting a custom logger that implements the xlog.XLogger interface.
What licence does go-pay/gopay use?
The repository is Apache-2.0, with the LICENSE file at the repository root.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/go-pay-gopay)