新增订单处理相关文件和配置

- 新增 Excel 文件 order_info.xlsx,用于存储订单信息
- 新增 Jupyter Notebook 文件 order.ipynb,包含订单数据处理逻辑
- 新增 Linux x86 构建文件 verification_linux_x86
- 修改 submit_order.go,添加时间戳到订单发送日志
- 更新 config.go,商户配置中添加 submit_url 字段
- 优化 order_service.go,调整订单处理逻辑,确保使用正确的商户提交 URL
This commit is contained in:
danial
2025-07-12 22:07:19 +08:00
parent 7e9b7a1236
commit 93c7123890
6 changed files with 366 additions and 8 deletions

357
order_retry/order.ipynb Normal file
View File

@@ -0,0 +1,357 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"data = pd.read_excel(\"order_info.xlsx\")"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>id</th>\n",
" <th>merchant_order_id</th>\n",
" <th>shop_name</th>\n",
" <th>order_period</th>\n",
" <th>bank_order_id</th>\n",
" <th>bank_trans_id</th>\n",
" <th>order_amount</th>\n",
" <th>show_amount</th>\n",
" <th>fact_amount</th>\n",
" <th>roll_pool_code</th>\n",
" <th>...</th>\n",
" <th>is_ip_restricted</th>\n",
" <th>transaction_type</th>\n",
" <th>is_block</th>\n",
" <th>pay_url</th>\n",
" <th>is_replace</th>\n",
" <th>is_succeed_by_replace</th>\n",
" <th>send_count</th>\n",
" <th>is_amount_different</th>\n",
" <th>send_record</th>\n",
" <th>pool_order_id</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>869512</td>\n",
" <td>YD20250706211708112855680</td>\n",
" <td>NaN</td>\n",
" <td>24</td>\n",
" <td>666032d0c744f784d58822deac9a4e9b7b9</td>\n",
" <td>NaN</td>\n",
" <td>30</td>\n",
" <td>30</td>\n",
" <td>30</td>\n",
" <td>1</td>\n",
" <td>...</td>\n",
" <td>1</td>\n",
" <td>NaN</td>\n",
" <td>0.0</td>\n",
" <td>NaN</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>NaN</td>\n",
" <td>58fcbc5b59d845d08b2fc3e2a07c11c5</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>869513</td>\n",
" <td>WDI2025070621171999836F8D2C</td>\n",
" <td>NaN</td>\n",
" <td>24</td>\n",
" <td>6666b41e9cf17df4c7a8801c50f23fb8e22</td>\n",
" <td>NaN</td>\n",
" <td>20</td>\n",
" <td>20</td>\n",
" <td>20</td>\n",
" <td>1</td>\n",
" <td>...</td>\n",
" <td>1</td>\n",
" <td>NaN</td>\n",
" <td>0.0</td>\n",
" <td>NaN</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>NaN</td>\n",
" <td>97835b71183b441c877d4f498756ff67</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>968899</td>\n",
" <td>TP20250712111546677KX50V0</td>\n",
" <td>NaN</td>\n",
" <td>2</td>\n",
" <td>6662a16f25ad82c4943964ef2ed53554c83</td>\n",
" <td>NaN</td>\n",
" <td>50</td>\n",
" <td>50</td>\n",
" <td>50</td>\n",
" <td>1</td>\n",
" <td>...</td>\n",
" <td>1</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>NaN</td>\n",
" <td>d24cc9f3784f4dd38787af6bd81750bc</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>968900</td>\n",
" <td>202507121000042906</td>\n",
" <td>NaN</td>\n",
" <td>24</td>\n",
" <td>666e1a8e1eae4ac44c995ed0691c9f1a4f6</td>\n",
" <td>NaN</td>\n",
" <td>20</td>\n",
" <td>20</td>\n",
" <td>20</td>\n",
" <td>1</td>\n",
" <td>...</td>\n",
" <td>1</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>NaN</td>\n",
" <td>7c10a2092fa749c3852098532e62a399</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>968901</td>\n",
" <td>202507121000042933</td>\n",
" <td>NaN</td>\n",
" <td>24</td>\n",
" <td>6660c6befea286e4703b0c696204d6bba5f</td>\n",
" <td>NaN</td>\n",
" <td>30</td>\n",
" <td>30</td>\n",
" <td>30</td>\n",
" <td>1</td>\n",
" <td>...</td>\n",
" <td>1</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>NaN</td>\n",
" <td>72444a1da303425f8c36121bd31a43d4</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>5 rows × 50 columns</p>\n",
"</div>"
],
"text/plain": [
" id merchant_order_id shop_name order_period \\\n",
"0 869512 YD20250706211708112855680 NaN 24 \n",
"1 869513 WDI2025070621171999836F8D2C NaN 24 \n",
"2 968899 TP20250712111546677KX50V0 NaN 2 \n",
"3 968900 202507121000042906 NaN 24 \n",
"4 968901 202507121000042933 NaN 24 \n",
"\n",
" bank_order_id bank_trans_id order_amount \\\n",
"0 666032d0c744f784d58822deac9a4e9b7b9 NaN 30 \n",
"1 6666b41e9cf17df4c7a8801c50f23fb8e22 NaN 20 \n",
"2 6662a16f25ad82c4943964ef2ed53554c83 NaN 50 \n",
"3 666e1a8e1eae4ac44c995ed0691c9f1a4f6 NaN 20 \n",
"4 6660c6befea286e4703b0c696204d6bba5f NaN 30 \n",
"\n",
" show_amount fact_amount roll_pool_code ... is_ip_restricted \\\n",
"0 30 30 1 ... 1 \n",
"1 20 20 1 ... 1 \n",
"2 50 50 1 ... 1 \n",
"3 20 20 1 ... 1 \n",
"4 30 30 1 ... 1 \n",
"\n",
" transaction_type is_block pay_url is_replace is_succeed_by_replace \\\n",
"0 NaN 0.0 NaN 0 0 \n",
"1 NaN 0.0 NaN 0 0 \n",
"2 NaN NaN NaN 0 0 \n",
"3 NaN NaN NaN 0 0 \n",
"4 NaN NaN NaN 0 0 \n",
"\n",
" send_count is_amount_different send_record \\\n",
"0 0 0 NaN \n",
"1 0 0 NaN \n",
"2 0 0 NaN \n",
"3 0 0 NaN \n",
"4 0 0 NaN \n",
"\n",
" pool_order_id \n",
"0 58fcbc5b59d845d08b2fc3e2a07c11c5 \n",
"1 97835b71183b441c877d4f498756ff67 \n",
"2 d24cc9f3784f4dd38787af6bd81750bc \n",
"3 7c10a2092fa749c3852098532e62a399 \n",
"4 72444a1da303425f8c36121bd31a43d4 \n",
"\n",
"[5 rows x 50 columns]"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"data.head()"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0 58fcbc5b59d845d08b2fc3e2a07c11c5\n",
"1 97835b71183b441c877d4f498756ff67\n",
"2 d24cc9f3784f4dd38787af6bd81750bc\n",
"3 7c10a2092fa749c3852098532e62a399\n",
"4 72444a1da303425f8c36121bd31a43d4\n",
" ... \n",
"279 5be5c261a5c242b987cd347f50176424\n",
"280 04d46961c4b5436e9e7a9c4ab9fe0e30\n",
"281 0b547f1d0cd44e78969a773399138f06\n",
"282 6b8ce40eea7c4d0c868a187755115afb\n",
"283 cf6a0e18c564467eb08e4378fb7d75fe\n",
"Name: pool_order_id, Length: 284, dtype: object"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"data['pool_order_id']"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'code': 0,\n",
" 'message': 'OK',\n",
" 'data': {'total': 3,\n",
" 'list': [{'orderNo': '',\n",
" 'operation': '拉取订单',\n",
" 'remark': '',\n",
" 'createdAt': '2025-07-12 11:16:10',\n",
" 'accountName': ''},\n",
" {'orderNo': '',\n",
" 'operation': '用户提交卡密',\n",
" 'remark': '',\n",
" 'createdAt': '2025-07-12 11:16:10',\n",
" 'accountName': ''},\n",
" {'orderNo': '',\n",
" 'operation': '处理成功',\n",
" 'remark': '',\n",
" 'createdAt': None,\n",
" 'accountName': ''}],\n",
" 'bankOrderId': '666781fdcef96264ce4b51e24cd53e21d28',\n",
" 'createTime': '2025-07-12 11:16:10',\n",
" 'amount': 50}}"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"params = {\n",
" 'factPrice': '20.00',\n",
" 'failReason': '手动修正至成功',\n",
" 'orderNo': 'TP20250712111745875DWDLQS',\n",
" 'orderPrice': '20.00',\n",
" 'orderTime': '20250712192319',\n",
" 'payKey': 'kkkkd19ev5t6if8s739apfc0',\n",
" 'sign': '116ba14c9fe8cd7a4b99b6afbcac135c',\n",
" 'statusCode': '1',\n",
" 'trxNo': '6660e4c1bb4ed2640babf9461655680f906'\n",
"}\n",
"import requests\n",
"\n",
"requests.get('http://47.242.250.239:8081/order/paymentOrder/notify/TP20250712111745875DWDLQS', params)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.10"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

BIN
order_retry/order_info.xlsx Normal file

Binary file not shown.

Binary file not shown.

View File

@@ -25,7 +25,7 @@ func NewMockOrderSender(logger interfaces.Logger) interfaces.OrderSender {
func (s *OrderSender) Send(ctx context.Context, order *model.OrderInfo, productCode, payKey, paySecret, submitURL string) error {
// 这里实现实际的订单发送逻辑
s.logger.Info("发送订单", "order", order, "productCode", productCode, "payKey", payKey,
"paySecret", paySecret, "submitURL", submitURL)
"paySecret", paySecret, "submitURL", submitURL, "time", time.Now().Format("2006-01-02 15:04:05"))
if _, err := submitOrder(ctx, &SubmitOrder{
OrderPeriod: 1,
NotifyUrl: "https://www.baidu.com",

View File

@@ -8,8 +8,7 @@ import (
// Config 应用配置结构
type Config struct {
SubmitURL string `mapstructure:"submit_url"`
Database struct {
Database struct {
Host string `mapstructure:"host"`
Port int `mapstructure:"port"`
Username string `mapstructure:"username"`
@@ -18,6 +17,7 @@ type Config struct {
} `mapstructure:"database"`
Merchants []*struct {
Name string `mapstructure:"name"`
SubmitURL string `mapstructure:"submit_url"`
ProductCode string `mapstructure:"product_code"`
PayKey string `mapstructure:"pay_key"`
PaySecret string `mapstructure:"pay_secret"`

View File

@@ -5,7 +5,6 @@ import (
"database/sql"
"encoding/csv"
"encoding/json"
"fmt"
"order/internal/client"
"os"
"strings"
@@ -46,7 +45,7 @@ func NewOrderService(
// ProcessOrders 处理订单
func (s *OrderServiceImpl) ProcessOrders(ctx context.Context) error {
// 判断这个文件有没有,如果有,打开,没有就创建一个
filePath := fmt.Sprintf("order.csv")
filePath := "order.csv"
if _, err := os.Stat(filePath); os.IsNotExist(err) {
_, _ = os.Create(filePath)
}
@@ -70,7 +69,6 @@ func (s *OrderServiceImpl) ProcessOrders(ctx context.Context) error {
if len(orders) == 0 {
return nil
}
csvReader := csv.NewReader(csvFile)
// 读取所有数据
records, err2 := csvReader.ReadAll()
@@ -80,17 +78,19 @@ func (s *OrderServiceImpl) ProcessOrders(ctx context.Context) error {
// 筛选符合条件的数据
existBankOrders := slice.Filter(slice.Map(records, func(index int, record []string) string {
if len(record) > 1 {
if len(record) >= 1 {
return record[0]
}
return ""
}), func(index int, record string) bool {
return record != ""
})
existBankOrders = slice.Unique(existBankOrders)
for _, order := range orders {
if slice.Contain(existBankOrders, order.BankOrderID) {
continue
}
s.logger.Info("开始处理订单", "order", order, "已有订单数量", len(existBankOrders))
heePayClient := client.NewHeePayClient()
exRedeemValue := RedeemCardInfo{}
if err = json.Unmarshal([]byte(convertor.ToString(order.ExValue)), &exRedeemValue); err != nil {
@@ -109,6 +109,7 @@ func (s *OrderServiceImpl) ProcessOrders(ctx context.Context) error {
merchants := s.config.Merchants
merchant, ok := slice.FindBy(merchants, func(index int, item *struct {
Name string `mapstructure:"name"`
SubmitURL string `mapstructure:"submit_url"`
ProductCode string `mapstructure:"product_code"`
PayKey string `mapstructure:"pay_key"`
PaySecret string `mapstructure:"pay_secret"`
@@ -120,7 +121,7 @@ func (s *OrderServiceImpl) ProcessOrders(ctx context.Context) error {
s.logger.Error("未找到匹配的商户", "error", heePayResp)
continue
}
if err = s.sender.Send(ctx, order, merchant.ProductCode, merchant.PayKey, merchant.PaySecret, s.config.SubmitURL); err != nil {
if err = s.sender.Send(ctx, order, merchant.ProductCode, merchant.PayKey, merchant.PaySecret, merchant.SubmitURL); err != nil {
s.logger.Error("提交订单失败", "error", err)
continue
}