Documentation
¶
Overview ¶
Package protocol implements EPay V1 and V2 using Go's standard library. NewClient selects V2 (RSA); NewV1Client selects V1 (MD5). Neither client automatically retries financial operations. Adapted from the local github.com/herta-network/epay SDK (2026-10-25). See docs/guide/epay.md for protocol coverage and backend integration boundaries.
Index ¶
- func CanonicalString(params Params) (string, error)
- func ParseAmount(value string) (int64, error)
- func V1CanonicalString(params Params) (string, error)
- type APIError
- type Client
- func (c *Client) Call(ctx context.Context, apiPath string, request Request) (*Response, error)
- func (c *Client) CloseOrder(ctx context.Context, ref OrderRef) error
- func (c *Client) CreatePayment(ctx context.Context, request CreatePaymentRequest) (*PaymentResult, error)
- func (c *Client) PagePayment(payment Payment) (*PageForm, error)
- func (c *Client) QueryOrder(ctx context.Context, ref OrderRef) (*Order, error)
- func (c *Client) QueryRefund(ctx context.Context, ref RefundRef) (*RefundStatus, error)
- func (c *Client) Refund(ctx context.Context, request RefundRequest) (*RefundResult, error)
- func (c *Client) SignedParams(params Params) (Params, error)
- func (c *Client) UploadComplaintImage(ctx context.Context, complaintID string, data []byte) (string, error)
- func (c *Client) VerifyNotification(values url.Values) (*Notification, error)
- type Config
- type CreatePaymentRequest
- type HTTPError
- type Notification
- type Order
- type OrderRef
- type OrderStatus
- type PageForm
- type Params
- type Payment
- type PaymentResult
- type RefundRef
- type RefundRequest
- type RefundResult
- type RefundStatus
- type Request
- type Response
- type V1APIError
- type V1Client
- func (c *V1Client) CreatePayment(ctx context.Context, request V1CreatePaymentRequest) (*V1PaymentResult, error)
- func (c *V1Client) MerchantInfo(ctx context.Context) (*V1Response, error)
- func (c *V1Client) Orders(ctx context.Context, request V1OrdersRequest) (*V1Response, error)
- func (c *V1Client) PagePayment(payment V1Payment) (*PageForm, error)
- func (c *V1Client) QueryOrder(ctx context.Context, ref OrderRef) (*V1Order, error)
- func (c *V1Client) Refund(ctx context.Context, request V1RefundRequest) (*V1RefundResult, error)
- func (c *V1Client) Settlements(ctx context.Context) (*V1Response, error)
- func (c *V1Client) SignedParams(params Params) (Params, error)
- func (c *V1Client) VerifyNotification(values url.Values) (*Notification, error)
- type V1Config
- type V1CreatePaymentRequest
- type V1Order
- type V1OrdersRequest
- type V1Payment
- type V1PaymentResult
- type V1RefundRequest
- type V1RefundResult
- type V1Response
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CanonicalString ¶
CanonicalString follows the reference PHP SDK: retain "0", omit whitespace-only values, and preserve every byte of nonempty values. Do not URL-encode here.
func ParseAmount ¶
ParseAmount converts a decimal yuan string into integer cents without floating point. Zero is valid for balances; payment/refund wrappers require a positive amount.
func V1CanonicalString ¶
V1CanonicalString preserves whitespace-only values, unlike the V2 reference SDK. Only empty strings, sign and sign_type are omitted. Values are not encoded.
Types ¶
type APIError ¶
APIError reports a V2 nonzero code. Verified=false means the error was unsigned: it is diagnostic information, not authenticated evidence of a financial outcome.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client implements EPay V2. Use V1Client for the MD5 protocol.
func (*Client) Call ¶
Call sends a single form POST and verifies successful responses before exposing their contents. Use this for merchant, transfer and complaint API extensions too.
func (*Client) CreatePayment ¶
func (c *Client) CreatePayment(ctx context.Context, request CreatePaymentRequest) (*PaymentResult, error)
func (*Client) QueryOrder ¶
func (*Client) QueryRefund ¶
func (*Client) Refund ¶
func (c *Client) Refund(ctx context.Context, request RefundRequest) (*RefundResult, error)
func (*Client) SignedParams ¶
SignedParams injects pid, timestamp and sign_type. Caller-owned maps are not changed.
func (*Client) UploadComplaintImage ¶
func (c *Client) UploadComplaintImage(ctx context.Context, complaintID string, data []byte) (string, error)
UploadComplaintImage uploads one PNG/JPEG (SDK limit: 5 MiB). File bytes are excluded from the protocol signature; HTTPS remains mandatory.
func (*Client) VerifyNotification ¶
func (c *Client) VerifyNotification(values url.Values) (*Notification, error)
VerifyNotification validates authenticity, age, merchant and successful trade status. The caller must still match the stored order amount/type and atomically commit payment/delivery idempotently before replying with the literal "success".
type Config ¶
type Config struct {
BaseURL string // Required HTTPS origin of the target EPay deployment.
MerchantID string
MerchantPrivateKey []byte // Unencrypted PEM or bare Base64 DER.
PlatformPublicKey []byte // PEM or bare Base64 DER; never the merchant public key.
HTTPClient *http.Client
MaxClockSkew time.Duration // Zero selects the PHP SDK's 300-second window.
}
Config configures the EPay V2 RSA client. Use V1Config for shared-key V1.
type CreatePaymentRequest ¶
type CreatePaymentRequest struct {
Payment
Method string // web, jump, jsapi, app, scan, applet.
Device string // pc, mobile, qq, wechat, alipay, douyin.
ClientIP string
}
func (CreatePaymentRequest) Validate ¶
func (request CreatePaymentRequest) Validate() error
Validate checks a create before the application persists its attempt fence.
type Notification ¶
type Order ¶
type Order struct {
TradeNo string `json:"trade_no"`
OutTradeNo string `json:"out_trade_no"`
APITradeNo string `json:"api_trade_no"`
Type string `json:"type"`
Status OrderStatus `json:"status"`
Name string `json:"name"`
Money string `json:"money"`
RefundMoney string `json:"refundmoney"`
Param string `json:"param"`
Buyer string `json:"buyer"`
ClientIP string `json:"clientip"`
CreatedAt string `json:"addtime"`
CompletedAt string `json:"endtime"`
}
type OrderStatus ¶
type OrderStatus int
const ( OrderUnpaid OrderStatus = iota OrderPaid OrderRefunded OrderFrozen )
type PageForm ¶
PageForm can be rendered with html/template. Fields are signed but not HTML-safe strings on their own; never concatenate them into HTML without escaping.
type Payment ¶
type Payment struct {
Type string // alipay, wxpay, qqpay; empty permitted for page cashier / scan autodetection.
OutTradeNo string
NotifyURL string
ReturnURL string
Name string
Money string // Yuan, e.g. "1.00". Never convert through float64.
Param string
Extra Params // merchant_id, channel_id, fee_mode, cert_no, cert_name, min_age, etc.
}
type PaymentResult ¶
type RefundRequest ¶
type RefundResult ¶
type RefundStatus ¶
type RefundStatus struct {
RefundResult
OutTradeNo string `json:"out_trade_no"`
Status int `json:"status"` // 0 failed, 1 succeeded; separate from API code.
CreatedAt string `json:"addtime"`
}
type Request ¶
Request separates signed scalar fields from arrays, which the upstream protocol excludes from its signature. Arrays use PHP-compatible key[index] encoding.
type Response ¶
type Response struct {
UnsignedFields []string
// contains filtered or unexported fields
}
Response is only returned after validating a code=0 response's signature and timestamp. Nested arrays/objects are NOT covered by this upstream protocol.
type V1APIError ¶
V1APIError identifies an API failure using the operation-specific success code. In particular code=0 fails ordinary V1 requests but succeeds for refunds.
func (*V1APIError) Error ¶
func (e *V1APIError) Error() string
type V1Client ¶
type V1Client struct {
// contains filtered or unexported fields
}
V1Client implements EPay V1. It never falls back to V2 or retries requests.
func NewV1Client ¶
func (*V1Client) CreatePayment ¶
func (c *V1Client) CreatePayment(ctx context.Context, request V1CreatePaymentRequest) (*V1PaymentResult, error)
func (*V1Client) MerchantInfo ¶
func (c *V1Client) MerchantInfo(ctx context.Context) (*V1Response, error)
MerchantInfo returns account data, including KEY on some deployments. Decode only the fields needed by the application instead of logging JSON().
func (*V1Client) Orders ¶
func (c *V1Client) Orders(ctx context.Context, request V1OrdersRequest) (*V1Response, error)
func (*V1Client) QueryOrder ¶
func (*V1Client) Refund ¶
func (c *V1Client) Refund(ctx context.Context, request V1RefundRequest) (*V1RefundResult, error)
func (*V1Client) Settlements ¶
func (c *V1Client) Settlements(ctx context.Context) (*V1Response, error)
Settlements returns the deployment's settlement records in data. The reference document does not specify their row schema; use Decode with a site-specific type.
func (*V1Client) SignedParams ¶
SignedParams adds the configured pid and MD5 signature without exposing KEY. V1 does not inject a timestamp. Caller-owned maps are not changed.
func (*V1Client) VerifyNotification ¶
func (c *V1Client) VerifyNotification(values url.Values) (*Notification, error)
VerifyNotification validates V1's MD5 signature, merchant and successful trade status. There is no protocol timestamp/replay window; durable idempotency belongs to the business Store. All additional scalar fields participate in verification.
type V1CreatePaymentRequest ¶
type V1CreatePaymentRequest struct {
V1Payment
ClientIP string
Device string // pc, mobile, qq, wechat, alipay, douyin, jump; empty uses the server default.
}
func (V1CreatePaymentRequest) Validate ¶
func (request V1CreatePaymentRequest) Validate() error
Validate checks a create before the application persists its attempt fence.
type V1Order ¶
type V1Order struct {
MerchantID string `json:"pid"`
TradeNo string `json:"trade_no"`
OutTradeNo string `json:"out_trade_no"`
APITradeNo string `json:"api_trade_no"`
Type string `json:"type"`
Name string `json:"name"`
Money string `json:"money"`
Status int `json:"status"`
Param string `json:"param"`
Buyer string `json:"buyer"`
CreatedAt string `json:"addtime"`
CompletedAt string `json:"endtime"`
}
V1Order deliberately uses a separate status field from V2's status enum. The V1 reference defines only 0 (unpaid) and 1 (paid).
func (*V1Order) UnmarshalJSON ¶
UnmarshalJSON tolerates PHP's integer strings for pid/status, while preserving money and order identifiers as strings and rejecting duplicate top-level keys.
type V1OrdersRequest ¶
type V1PaymentResult ¶
type V1RefundRequest ¶
type V1RefundResult ¶
type V1RefundResult struct {
Message string `json:"msg"`
}
type V1Response ¶
type V1Response struct {
// contains filtered or unexported fields
}
V1Response has passed JSON and API success-code checks only. V1 does not define signed JSON responses; HTTPS authenticates transport. MerchantInfo may include the shared key, so never log the complete response.
func (*V1Response) Decode ¶
func (r *V1Response) Decode(destination any) error
func (*V1Response) JSON ¶
func (r *V1Response) JSON() []byte