integration wordpress
This commit is contained in:
78
integration/wordpress/api-bridge/README.md
Normal file
78
integration/wordpress/api-bridge/README.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# M2Pool API Bridge
|
||||
|
||||
这是一个中间 API 服务,用于连接 WordPress 插件和基于 RabbitMQ 的支付系统。
|
||||
|
||||
## 功能
|
||||
|
||||
- 接收 WordPress 插件的 HTTP 请求
|
||||
- 将请求转换为 RabbitMQ 消息
|
||||
- 监听 RabbitMQ 响应并返回给 WordPress
|
||||
|
||||
## 安装
|
||||
|
||||
```bash
|
||||
cd api-bridge
|
||||
go mod download
|
||||
go build -o api-bridge main.go
|
||||
```
|
||||
|
||||
## 配置
|
||||
|
||||
修改 `main.go` 中的 RabbitMQ 配置:
|
||||
|
||||
```go
|
||||
rmqConfig = RabbitMQConfig{
|
||||
URL: "amqp://m2pool:m2pool@localhost:5672",
|
||||
Exchange: "pay.exchange",
|
||||
Queues: map[string]string{
|
||||
"pay": "pay.auto.routing.key",
|
||||
"topup": "pay.recharge.routing.key",
|
||||
"status": "pay.auto.return.routing.key",
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 运行
|
||||
|
||||
```bash
|
||||
./api-bridge
|
||||
```
|
||||
|
||||
服务将在 `http://localhost:8080` 启动。
|
||||
|
||||
## API 接口
|
||||
|
||||
### 创建支付请求
|
||||
|
||||
```
|
||||
POST /api/payment/create
|
||||
```
|
||||
|
||||
### 查询支付状态
|
||||
|
||||
```
|
||||
GET /api/payment/status/{queue_id}
|
||||
```
|
||||
|
||||
### 创建充值请求
|
||||
|
||||
```
|
||||
POST /api/topup/create
|
||||
```
|
||||
|
||||
### 查询充值状态
|
||||
|
||||
```
|
||||
GET /api/topup/status/{queue_id}
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
当前实现是基础版本,实际使用中需要:
|
||||
|
||||
1. 实现状态缓存(Redis 或数据库)
|
||||
2. 监听 RabbitMQ 响应队列
|
||||
3. 实现签名验证
|
||||
4. 添加错误处理和日志记录
|
||||
5. 添加认证和授权
|
||||
|
||||
8
integration/wordpress/api-bridge/go.mod
Normal file
8
integration/wordpress/api-bridge/go.mod
Normal file
@@ -0,0 +1,8 @@
|
||||
module m2pool-api-bridge
|
||||
|
||||
go 1.21
|
||||
|
||||
require (
|
||||
github.com/gorilla/mux v1.8.1
|
||||
github.com/streadway/amqp v1.1.0
|
||||
)
|
||||
4
integration/wordpress/api-bridge/go.sum
Normal file
4
integration/wordpress/api-bridge/go.sum
Normal file
@@ -0,0 +1,4 @@
|
||||
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||
github.com/streadway/amqp v1.1.0 h1:py12iX8XSyI7aN/3dUT8DFIDJazNJsVJdxNVEpnQTZM=
|
||||
github.com/streadway/amqp v1.1.0/go.mod h1:WYSrTEYHOXHd0nwFeUXAe2G2hRnQT+deZJJf88uS9Bg=
|
||||
241
integration/wordpress/api-bridge/main.go
Normal file
241
integration/wordpress/api-bridge/main.go
Normal file
@@ -0,0 +1,241 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/streadway/amqp"
|
||||
)
|
||||
|
||||
// PaymentRequest 支付请求
|
||||
type PaymentRequest struct {
|
||||
QueueID string `json:"queue_id"`
|
||||
Chain string `json:"chain"`
|
||||
Symbol string `json:"symbol"`
|
||||
FromAddress string `json:"from_address"`
|
||||
ToAddress string `json:"to_address"`
|
||||
Amount float64 `json:"amount"`
|
||||
Fee float64 `json:"fee"`
|
||||
Timestamp uint64 `json:"timestamp"`
|
||||
Sign string `json:"sign"`
|
||||
}
|
||||
|
||||
// TopupRequest 充值请求
|
||||
type TopupRequest struct {
|
||||
QueueID string `json:"queue_id"`
|
||||
Chain string `json:"chain"`
|
||||
Symbol string `json:"symbol"`
|
||||
Address string `json:"address"`
|
||||
Timestamp uint64 `json:"timestamp"`
|
||||
Sign string `json:"sign"`
|
||||
}
|
||||
|
||||
// APIResponse API 响应
|
||||
type APIResponse struct {
|
||||
Success bool `json:"success"`
|
||||
Data interface{} `json:"data,omitempty"`
|
||||
Message string `json:"message,omitempty"`
|
||||
}
|
||||
|
||||
// RabbitMQConfig RabbitMQ 配置
|
||||
type RabbitMQConfig struct {
|
||||
URL string
|
||||
Exchange string
|
||||
Queues map[string]string
|
||||
}
|
||||
|
||||
var rmqConfig RabbitMQConfig
|
||||
var rmqConn *amqp.Connection
|
||||
var rmqCh *amqp.Channel
|
||||
|
||||
func main() {
|
||||
// 初始化 RabbitMQ 配置
|
||||
rmqConfig = RabbitMQConfig{
|
||||
URL: "amqp://m2pool:m2pool@localhost:5672",
|
||||
Exchange: "pay.exchange",
|
||||
Queues: map[string]string{
|
||||
"pay": "pay.auto.routing.key",
|
||||
"topup": "pay.recharge.routing.key",
|
||||
"status": "pay.auto.return.routing.key",
|
||||
},
|
||||
}
|
||||
|
||||
// 连接 RabbitMQ
|
||||
var err error
|
||||
rmqConn, err = amqp.Dial(rmqConfig.URL)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to connect to RabbitMQ: %v", err)
|
||||
}
|
||||
defer rmqConn.Close()
|
||||
|
||||
rmqCh, err = rmqConn.Channel()
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to open channel: %v", err)
|
||||
}
|
||||
defer rmqCh.Close()
|
||||
|
||||
// 设置路由
|
||||
r := mux.NewRouter()
|
||||
|
||||
// 支付相关接口
|
||||
r.HandleFunc("/api/payment/create", createPaymentHandler).Methods("POST")
|
||||
r.HandleFunc("/api/payment/status/{queue_id}", getPaymentStatusHandler).Methods("GET")
|
||||
|
||||
// 充值相关接口
|
||||
r.HandleFunc("/api/topup/create", createTopupHandler).Methods("POST")
|
||||
r.HandleFunc("/api/topup/status/{queue_id}", getTopupStatusHandler).Methods("GET")
|
||||
|
||||
// 健康检查
|
||||
r.HandleFunc("/health", healthCheckHandler).Methods("GET")
|
||||
|
||||
log.Println("API Bridge Server starting on :8080")
|
||||
log.Fatal(http.ListenAndServe(":8888", r))
|
||||
}
|
||||
|
||||
// createPaymentHandler 创建支付请求
|
||||
func createPaymentHandler(w http.ResponseWriter, r *http.Request) {
|
||||
var req PaymentRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
respondJSON(w, http.StatusBadRequest, APIResponse{
|
||||
Success: false,
|
||||
Message: "Invalid request body",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 发送到 RabbitMQ
|
||||
body, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
respondJSON(w, http.StatusInternalServerError, APIResponse{
|
||||
Success: false,
|
||||
Message: "Failed to marshal request",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
err = rmqCh.Publish(
|
||||
rmqConfig.Exchange,
|
||||
rmqConfig.Queues["pay"],
|
||||
false,
|
||||
false,
|
||||
amqp.Publishing{
|
||||
ContentType: "application/json",
|
||||
Body: body,
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Printf("Failed to publish payment request: %v", err)
|
||||
respondJSON(w, http.StatusInternalServerError, APIResponse{
|
||||
Success: false,
|
||||
Message: "Failed to send payment request",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
respondJSON(w, http.StatusOK, APIResponse{
|
||||
Success: true,
|
||||
Data: map[string]string{
|
||||
"queue_id": req.QueueID,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// getPaymentStatusHandler 查询支付状态
|
||||
func getPaymentStatusHandler(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
queueID := vars["queue_id"]
|
||||
|
||||
// 这里应该从数据库或缓存中查询状态
|
||||
// 为了演示,我们返回一个模拟响应
|
||||
// 实际实现中,应该监听 RabbitMQ 的响应队列并存储状态
|
||||
|
||||
respondJSON(w, http.StatusOK, APIResponse{
|
||||
Success: true,
|
||||
Data: map[string]interface{}{
|
||||
"queue_id": queueID,
|
||||
"status": 0, // 0=待支付, 1=成功, 2=待确认, 3=失败
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// createTopupHandler 创建充值请求
|
||||
func createTopupHandler(w http.ResponseWriter, r *http.Request) {
|
||||
var req TopupRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
respondJSON(w, http.StatusBadRequest, APIResponse{
|
||||
Success: false,
|
||||
Message: "Invalid request body",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 发送到 RabbitMQ
|
||||
body, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
respondJSON(w, http.StatusInternalServerError, APIResponse{
|
||||
Success: false,
|
||||
Message: "Failed to marshal request",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
err = rmqCh.Publish(
|
||||
rmqConfig.Exchange,
|
||||
rmqConfig.Queues["topup"],
|
||||
false,
|
||||
false,
|
||||
amqp.Publishing{
|
||||
ContentType: "application/json",
|
||||
Body: body,
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Printf("Failed to publish topup request: %v", err)
|
||||
respondJSON(w, http.StatusInternalServerError, APIResponse{
|
||||
Success: false,
|
||||
Message: "Failed to send topup request",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
respondJSON(w, http.StatusOK, APIResponse{
|
||||
Success: true,
|
||||
Data: map[string]string{
|
||||
"queue_id": req.QueueID,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// getTopupStatusHandler 查询充值状态
|
||||
func getTopupStatusHandler(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
queueID := vars["queue_id"]
|
||||
|
||||
// 这里应该从数据库或缓存中查询状态
|
||||
respondJSON(w, http.StatusOK, APIResponse{
|
||||
Success: true,
|
||||
Data: map[string]interface{}{
|
||||
"queue_id": queueID,
|
||||
"status": 0,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// healthCheckHandler 健康检查
|
||||
func healthCheckHandler(w http.ResponseWriter, r *http.Request) {
|
||||
respondJSON(w, http.StatusOK, APIResponse{
|
||||
Success: true,
|
||||
Message: "API Bridge is running",
|
||||
})
|
||||
}
|
||||
|
||||
// respondJSON 返回 JSON 响应
|
||||
func respondJSON(w http.ResponseWriter, status int, data interface{}) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(status)
|
||||
json.NewEncoder(w).Encode(data)
|
||||
}
|
||||
Reference in New Issue
Block a user