如何使用 Go 接入 imsafu
imsafu 是一个支付处理服务,允许您创建和查询支付。本文档将引导您完成访问 imsafu 服务。
准备
在开始之前,请确保满足以下先决条件:
- 在您的计算机上安装了 Go 编程语言。
- 配置了 Go 的开发环境。
安装依赖项
imsafu 服务的访问并不需要特定的依赖项,这里提供了一些默认的依赖库,您可以根据需要选择相应的库。
运行以下命令来安装依赖库:
go get github.com/go-resty/resty/v2
go get github.com/go-playground/validator/v10
导入所需模块
在您的 Go 文件中,导入所需的模块。添加以下导入语句到文件顶部:
import (
"fmt"
"net/http"
"encoding/json"
"github.com/go-resty/resty/v2"
"github.com/go-playground/validator/v10"
)
创建 imsafu 所需变量
连接到 imsafu 测试服务器,您可以使用以下变量。如果您想连接到正式服务器,请加入等待列表以获取相关信息。
type Options struct {
URL string `validate:"required"`
API string `validate:"required"`
APISecret string `validate:"required"`
Receiver string `validate:"required"`
MerchantBrand string `validate:"required"`
MerchantRedirectURL string `validate:"required"`
}
func main() {
options := Options{
URL: "https://devnet.imsafu.com",
API: "https://allowpay-api-devnet.fly.dev/v1",
APISecret: "your-api-secret",
Receiver: "your-wallet-account",
MerchantBrand: "imsafu demo",
MerchantRedirectURL: "https://merchant.com/redirect",
}
}
创建新的支付
首先,我们需要生成一个 32 位的十六进制字符串作为新订单的 ID。
func createOrderID() string {
str := uuid.Must(uuid.NewRandom()).String()
return fmt.Sprintf("0x%s", strings.Join([]string{strings.Repeat("0", 32-len(str)), str}, ""))
}
要创建新的支付,我们需要实现一个 createPayment
方法。此方法接受支付金额作为参数,并返回一个解析为 PaymentResponse
对象的结构。
type Payment struct {
OrderID string `json:"orderID"`
Receiver string `json:"receiver"`
Amount string `json:"amount"`
}
type PaymentResponse struct {
Status string `json:"status"`
Payment Payment `json:"payment"`
}
func createPayment(amount int64, options Options) (*PaymentResponse, error) {
orderID := createOrderID()
paymentResponse := &PaymentResponse{}
payload := struct {
Payment Payment `json:"payment"`
NotifyURL string `json:"notifyURL"`
}{
Payment: Payment{
OrderID: orderID,
Receiver: options.Receiver,
Amount: strconv.FormatInt(amount, 10),
},
NotifyURL: options.URL + "/notify",
}
client := resty.New()
resp, err := client.R().
SetHeader("Content-Type", "application/json").
SetHeader("Authorization", "Bearer " + options.APISecret).
SetBody(payload).
SetResult(&paymentResponse).
Post(options.API + "/depositPay")
if err != nil {
return nil, err
}
return &paymentResponse, nil
}
生成支付链接
首先编写一个方法来生成支付链接:
func buildPaymentURL(itemMemo string, paymentResponse *PaymentResponse, options Options) string {
paymentURL := fmt.Sprintf("%s/payment_qrcode", options.URL)
url := fmt.Sprintf("%s?payID=%s&brand=%s&memo=%s&redirect_url=%s¤cy=USD", paymentURL, paymentResponse.Payment.OrderID, options.MerchantBrand, itemMemo, options.MerchantRedirectURL)
return url
}
amount := int64(100)
paymentResponse, err := createPayment(amount, options)
if err != nil {
// 处理错误
}
paymentURL := buildPaymentURL("test item", paymentResponse, options)
用户支付
向用户展示生成的 paymentURL,用户点击后可以在网页中打开支付界面。具体支付流程可以参考 使用 imsafu 支付。
检索支付信息
在用户完成支付后,imsafu 将通过向创建订单时传入的 notifyURL
发送包含 payID
的 POST
请求。我们需要通过 getPayment
接口检索支付信息,并确认用户的支付是否成功。
要检索支付信息,我们需要实现 getPayment
方法。此方法接受支付ID(payID)作为参数,并返回解析为 PaymentResponse
对象的结构。
func getPayment(payID string, options Options) (*PaymentResponse, error) {
client := resty.New()
paymentResponse := &PaymentResponse{}
resp, err := client.R().
SetResult(&paymentResponse).
Get(options.API + "/depositPays/" + payID)
if err != nil {
return nil, err
}
return &paymentResponse, nil
}
// 从 notify 请求中获取 payID
paymentResponse, err := getPayment(payID, options)
if err != nil {
// 处理错误
}
// 进行其他操作
附录:在代码中使用的类型定义
type Payment struct {
PayID string `json:"payID"`
OrderID string `json:"orderID"`
Receiver string `json:"receiver"`
Amount string `json:"amount"`
OriginalAmount string `json:"originalAmount"`
MaxFeeAmount string `json:"maxFeeAmount"`
Deadline string `json:"deadline"`
}
type Chain struct {
ID int `json:"id"`
Symbol string `json:"symbol"`
Name string `json:"name"`
}
type Token struct {
Symbol string `json:"symbol"`
Address string `json:"address"`
}
type ReceiveTx struct {
Chain Chain `json:"chain"`
TxID string `json:"txID"`
ConfirmedAt string `json:"confirmedAt"`
Amount string `json:"amount"`
FeeAmount string `json:"feeAmount"`
Token Token `json:"token"`
}
type Deposit struct {
ChainID int `json:"chainID"`
Token string `json:"token"`
}
type PaymentResponse struct {
Status string `json:"status"`
Payment Payment `json:"payment"`
Owner string `json:"owner"`
DepositAddress string `json:"depositAddress"`
CallID int `json:"callID"`
ReceiveTx *ReceiveTx `json:"receiveTx,omitempty"`
Deposits []Deposit `json:"deposits,omitempty"`
}
请注意,上述代码仅为示例,可能需要根据您的具体情况进行修改和适应。