Python-CTP PyCTP 接口

已经编译好文件,内附调用示例.具体参数可参考ctp头文件.
支持python3.4/linux, python3.4/windows
PyCTP_build_20170122

这是程序化期货交易上期ctp接口版本. 为方便数值计算.将其包装为python版本. 支 python3.4.3, win64/32/vs2010/centos7.2/gcc4.8.5上调试和编译
编译需求:vs2010,
https://github.com/shizhuolin/PyCTP

为了省事, 绝大部分代码是直接从ctp源码转换而来.
所有char[x] 均用 pybytes代替, 数据结构用pydict代替,char用pybyte代替,bool使用pybool或int
调用示范:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#!/usr/bin/python
# -*- coding: UTF-8 -*-
 
from sys import *
from threading import *
from PyCTP import *
 
class CTP_Trader_API(CThostFtdcTraderApi):
 
    _event = Event()
    _BrokerID = None
    _UserID = None
    _InvestorID = None
    _FrontID = None
    _SessionID = None
    _MaxOrderRef = None
 
    def Connect(self, frontAddr):
        self.RegisterSpi(self)
        self.SubscribePrivateTopic(THOST_TERT_RESUME)
        self.SubscribePublicTopic(THOST_TERT_RESUME)
        self.RegisterFront(frontAddr)
        self.Init()
        self._event.clear()
        self._event.wait()
 
    def Login(self, BrokerID, UserID, Password):
        reqUserLogin = {}
        reqUserLogin["BrokerID"] = BrokerID
        reqUserLogin["UserID"] = UserID
        reqUserLogin["Password"] = Password
        self.ReqUserLogin(reqUserLogin, 0)
        self._event.clear()
        self._event.wait()
 
    def setInvestorID(self, InvestorID):
        self._InvestorID = InvestorID
 
    def QrySettlementInfo(self, TradingDay):
        QrySettlementInfoField = {}
        QrySettlementInfoField["BrokerID"] = self._BrokerID
        QrySettlementInfoField["InvestorID"] = self._InvestorID
        QrySettlementInfoField["TradingDay"] = TradingDay
        self.ReqQrySettlementInfo(QrySettlementInfoField, 0)
 
    def OnFrontConnected(self):
        self._event.set()
 
    def OnRspUserLogin(self, RspUserLogin, RspInfo, RequestID, IsLast):
        self._BrokerID = RspUserLogin["BrokerID"]
        self._UserID = RspUserLogin["UserID"]
        self._FrontID = RspUserLogin["FrontID"]
        self._SessionID = RspUserLogin["SessionID"]
        self._MaxOrderRef = RspUserLogin["MaxOrderRef"]
        self._event.set()
 
    def OnRspQrySettlementInfo(self, SettlementInfo, RspInfo, RequestID, IsLast):
        print(SettlementInfo)
 
class CTP_Market_API(CThostFtdcMdApi):
 
    _event = Event()
    _BrokerID = None
    _UserID = None
 
    def Connect(self, frontAddr):
        self.RegisterSpi(self)
        self.RegisterFront(frontAddr)
        self.Init()
        self._event.clear()
        self._event.wait()
 
    def Login(self, BrokerID, UserID, Password):
        reqUserLogin = {}
        reqUserLogin["BrokerID"] = BrokerID
        reqUserLogin["UserID"] = UserID
        reqUserLogin["Password"] = Password
        self.ReqUserLogin(reqUserLogin, 0)
        self._event.clear()
        self._event.wait()
 
    def setInvestorID(self, InvestorID):
        self._InvestorID = InvestorID
 
    def OnFrontConnected(self):
        self._event.set()
 
    def OnRspUserLogin(self, RspUserLogin, RspInfo, RequestID, IsLast):
        self._BrokerID = RspUserLogin["BrokerID"]
        self._UserID = RspUserLogin["UserID"]
        self._event.set()
 
    def OnRspSubMarketData(self, SpecificInstrument, RspInfo, RequestID, bIsLast):
        pass
 
    def OnRtnDepthMarketData(self, data):
        print(repr(data))
 
print(CTP_Trader_API.GetApiVersion())
trader = CTP_Trader_API.CreateFtdcTraderApi(b"_trader_0393_00150_")
trader.Connect(b"tcp://180.168.146.187:10000")
trader.Login(b"9999", b"00150", bytes(input("password:"), "gb2312"))
print(trader.GetTradingDay())
trader.setInvestorID(b"00150")
##trader.QrySettlementInfo(b"")
 
print(CTP_Market_API.GetApiVersion())
market = CTP_Market_API.CreateFtdcMdApi(b"_market_0393_00150_")
market.Connect(b"tcp://180.168.146.187:10010")
market.Login(b"9999", b"00150", bytes(input("password:"), "gb2312"))
print(market.GetTradingDay())
market.SubscribeMarketData([b"IF1508", b"IF1509"], 2)

55 Responses to“Python-CTP PyCTP 接口”

  1. lucas.yuan
    2016年6月27日 at pm9:23 #

    可否告知您采用的什么封装方法么?

    • zhuolin
      2016年7月3日 at am12:02 #

      python 官方c/c++扩展封装, 先手工写好部分函数试验效果,可行后做成py脚本批量转换头文件为c/c++文件

  2. valleysong
    2016年7月27日 at am8:59 #

    stdafx.h(9): fatal error C1083: 无法打开包括文件: “Python.h”: No such file or directory
    提示这个啥原因啊?

    • zhuolin
      2016年8月1日 at pm3:04 #

      已经更改过代码,重新git. 现在可以直接使用setup.py编译, 自动寻找python.h相关配置

  3. new13
    2016年12月5日 at pm12:23 #

    您好,我运行python setup.py build时提示,查了很多资料都没解决,故此求救,谢谢:
    D:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\BIN\amd64\cl.exe /c /nologo /Ox /MD /W3 /GS- /DNDEBUG -I./v6.3.6_20160606_tradeapi64_windows -IC:\Python27\include -IC:\Python27\PC /Tp.\src\stdafx.cpp /Fobuild\temp.win-amd64-2.7\Release\.\src\stdafx.obj
    stdafx.cpp
    D:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\BIN\amd64\cl.exe /c /nologo /Ox /MD /W3 /GS- /DNDEBUG -I./v6.3.6_20160606_tradeapi64_windows -IC:\Python27\include -IC:\Python27\PC /Tp.\src\PyCTP.cpp /Fobuild\temp.win-amd64-2.7\Release\.\src\PyCTP.obj
    PyCTP.cpp
    .\src\PyCTP.cpp(12) : error C2065: “PyModuleDef_HEAD_INIT”: 未声明的标识符
    .\src\PyCTP.cpp(13) : error C2514: “PyModuleDef”: 类没有构造函数
    .\src\PyCTP.cpp(10) : 参见“PyModuleDef”的声明
    .\src\PyCTP.cpp(21) : error C3861: “PyModule_Create”: 找不到标识符
    .\src\PyCTP.cpp(25) : error C2562: “PyInit_PyCTP”:“void”函数返回值
    .\src\PyCTP.cpp(16) : 参见“PyInit_PyCTP”的声明
    .\src\PyCTP.cpp(31) : error C2562: “PyInit_PyCTP”:“void”函数返回值
    .\src\PyCTP.cpp(16) : 参见“PyInit_PyCTP”的声明
    .\src\PyCTP.cpp(40) : error C2562: “PyInit_PyCTP”:“void”函数返回值
    .\src\PyCTP.cpp(16) : 参见“PyInit_PyCTP”的声明
    .\src\PyCTP.cpp(49) : error C2562: “PyInit_PyCTP”:“void”函数返回值
    .\src\PyCTP.cpp(16) : 参见“PyInit_PyCTP”的声明
    error: command ‘D:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\BIN\\amd64\\cl.exe’ failed with exit status 2

    • zhuolin
      2016年12月7日 at am9:08 #

      目前pyctp只支持python3 并在python3.4.3下完美测试通过(windows/linux)

  4. Anonymous
    2017年1月16日 at pm4:09 #

    版主你好,看到了pyctp,感觉挺好的,想使用但需要 vs2013编译, 不过本人未装 vs2013,也不熟悉,将否将编译后的dll也放上,方便直接使用

  5. dongfang
    2017年1月18日 at pm4:29 #

    能不能将编译好的dll也放上

    • zhuolin
      2017年1月22日 at am10:23 #

      好的,我放一份编译好的上来

  6. Anonymous
    2017年2月19日 at pm2:49 #

    def QryInstrument(self, ExchangeID=b”, InstrumentID=b”):
    “”” 查询和约 “””
    QryInstrument = dict(ExchangeID = ExchangeID
    , InstrumentID = InstrumentID)
    self.__rsp_QryInstrument = dict(event = threading.Event()
    , RequestID = self.__IncRequestID()
    , results = []
    , ErrorID = 0)
    ret = self.ReqQryInstrument(QryInstrument, self.__rsp_QryInstrument[‘RequestID’])
    if ret == 0:
    self.__rsp_QryInstrument[‘event’].clear()
    if self.__rsp_QryInstrument[‘event’].wait(self.TIMEOUT):
    if self.__rsp_QryInstrument[‘ErrorID’] != 0:
    return self.__rsp_QryInstrument[‘ErrorID’]
    return self.__rsp_QryInstrument[‘results’]
    else:
    return -4
    return ret

    我看好几段代码都是这个格式,但是我不太明白,能不能麻烦给解释一下这段代码是什么意思

    • zhuolin
      2017年2月20日 at pm9:04 #

      CTP指令基本都是异步指令. 也就是说发送请求后不等结果返回就会继续执行下一行代码. 这里的目的是事件等待.必须等到查询消息返回结束才会继续执行后续代码. 这么做的目的是为了方便策略编写. 每个def 指令(self,…) 方法都对应有一个 def On指令(self,…)事件处理。

  7. Anonymous
    2017年2月21日 at am10:28 #

    请问要想通过CTP实现开仓,平仓,撤单等操作,代码应该怎么写啊?

    • zhuolin
      2017年3月7日 at pm9:37 #

      参考例子中的python订单操作代码

  8. Anonymous
    2017年2月21日 at am10:34 #

    请问想要通过CTP进行开仓,平仓,撤单操作,代码应该怎么写啊,您有写好的吗?

  9. zfw
    2017年5月17日 at am7:37 #

    满屏全是
    AttributeError: ‘PyCTP_Trader’ object has no attribute ‘OnRtnInstrumentStatus’
    AttributeError: ‘PyCTP_Trader’ object has no attribute ‘OnRtnInstrumentStatus’
    AttributeError: ‘PyCTP_Trader’ object has no attribute ‘OnRtnInstrumentStatus’
    AttributeError: ‘PyCTP_Trader’ object has no attribute ‘OnRtnInstrumentStatus’
    AttributeError: ‘PyCTP_Trader’ object has no attribute ‘OnRtnInstrumentStatus’

  10. zfw
    2017年5月20日 at pm7:02 #

    非常感谢回复,问题已经解决。代码中的测试部分全部通过,没有问题。但是不知道怎么写开仓,平仓,撤单操作。你的代码中只有限价单(没有市价单、条件单),试了试,可能是传参有问题,限价单也不会用。哈哈哈哈。能不能写个demo。我看上面好多人都在问这个问题。望百忙之中,抽点时间帮助一下我们这样的小白。谢谢!万分感谢!

  11. ltw
    2017年12月7日 at am10:32 #

    请问在 OnFrontDisconnected 函数里的 self.__Inst_Interval() 方法是啥?

    • zhuolin
      2017年12月20日 at pm7:54 #

      最初设想如果掉线,就过段时间自动登陆,这个函数是用来延迟的。不过后发现ctp有自动掉线重连功能,也就注释掉了.

  12. lin
    2017年12月30日 at pm9:00 #

    请问楼主,查询复数合约怎么写?
    单数合约是InstrumentID= b’cu1802′
    这里试了很多写法,比如想写2,3个合约,都运行失败啊

    • zhuolin
      2018年1月11日 at pm2:27 #

      多个合约用 list传递 例如 InstrumentID= [b’cu1802′, b’cu1803′]

  13. warrock
    2018年1月24日 at pm10:18 #

    求问兄台能不能共享下.h转换h&cpp的新脚本学习下,github的运行结果稍微一点点对不上的。

    • zhuolin
      2018年1月25日 at am9:41 #

      ctp新版本有变化,需要针对修改一下才行, 其实转换脚本只是一些正则.

  14. Anonymous
    2018年3月30日 at pm3:45 #

    行情退出登录有问题。 (‘OnRspError’, [68, ‘CTP:无此功能’], 0, True)

    • zhuolin
      2018年3月30日 at pm3:55 #

      此问题无法解决。原因是官方CTP服务器并不存在退出功能. 客户api只是做个样子.

  15. lg
    2018年3月30日 at pm3:48 #

    交易退出登录也有问题:登出: {‘UserID’: b’112769′, ‘BrokerID’: b’9999′}
    CThostFtdcUserApiImplBase::OnSessionDisconnected[0000000002B03778][-313393151][ 4097]
    其他都很好,就是退出登录行情,及交易都会有问。

    • zhuolin
      2018年3月30日 at pm3:55 #

      此提示信息是官方CTPapi自行产生, 忽视即可. windows上似乎无此信息.

  16. lg
    2018年3月30日 at pm3:50 #

    行情退出登录: 显示错误–(‘OnRspError’, [68, ‘CTP:无此功能’], 0, True)

    • zhuolin
      2018年3月30日 at pm3:53 #

      此问题无法解决。原因是官方CTP服务器并不存在退出功能. 客户段这个api只是做个样子.

  17. rookie
    2018年4月8日 at pm8:13 #

    我在做web版的ctp 登录的时候发现 ctp有自动掉线重连功能 导致OnFrontDisconnected这个函数会不断的触发 如何才能停止这个函数的调用呢

    • zhuolin
      2018年4月9日 at am11:31 #

      无法停止调用,要想看不到显示,把函数体留空就是了.

  18. j88r
    2018年5月18日 at am10:31 #

    能不能共享下.h转换h&cpp的新脚本学习下。
    因为api不停的更新,所以想着也能跟进更新一下pyctp接口,如果API有变化,我也可以尝试修改正则,然后再共享出来:D

    • zhuolin
      2018年5月20日 at pm4:44 #

      github中已共享出此脚本

  19. jian
    2018年5月22日 at pm4:42 #

    请问博主 在win10(64位)Python3.6环境下运行PyCTP_build_20170122 无法导入PyCTP 是什么问题
    Traceback (most recent call last):
    File “test_PyCTP_Market.py”, line 12, in
    from PyCTP_Market import PyCTP_Market
    File “C:\Users\Windows\Desktop\PyCTP_build_20170122\PyCTP_Market.py”, line 11, in
    import PyCTP
    ImportError: DLL load failed: 找不到指定的模块。

    • zhuolin
      2018年5月22日 at pm8:53 #

      需要先编译得到pyctp.pyd,编译后把编译得到的 pyctp.pyd文件复制到自己项目根目录,同时把下载文件里面带的ctp官方提供的两个windows ctp dll文件也复制到项目根目录

  20. shi
    2018年6月8日 at am12:10 #

    博主,对于其中的请求行情模块,test_PyCTP.py里的def SubMarketData(self, InstrumentID):这个函数里,ret = self.SubscribeMarketData(InstrumentID, len(InstrumentID))应该是这一行触发了请求行情吧,我如何能把在窗口里的滚动的每秒的数据存成一个个字典,供我别的分析啊,SubscribeMarketData这个函数只返回了个int值,我如何把得到的行情数据存起来哈,谢谢

    • zhuolin
      2018年6月9日 at pm7:50 #

      使用python list或queue对象保存数据. 保存行情只能在回调中实现. 这点需要有python基础

  21. geekmo
    2018年6月8日 at pm4:08 #

    你好!刚研究PYCTP,有个问题不是很清楚,可以解答一下不?谢谢。

    订阅行情的结果:
    {‘InstrumentID’: ‘rb1810’, ‘time’: datetime.datetime(2018, 6, 8, 15, 13, 24, 500000), ‘last’: 3806.000000000001, ‘volume’: 3697188, ‘amount’: 140560926800.0, ‘position’: 3311490.0, ‘ask1’: 3807.0, ‘bid1’: 3806.000000000001, ‘asize1’: 339, ‘bsize1’: 333}
    这些结果能不能找个变量接收。如果能,怎么接收?

    • zhuolin
      2018年6月9日 at pm7:48 #

      设计pyctp的目的就是为了方便python接收和处理数据,这点需要有python基础. 总的来说就是可以使用队列或列表保存

  22. imlooker
    2018年6月10日 at pm11:43 #

    您好!非常感谢提供此CTP的python接口,我想把它用到32位的linux系统上运行,请问是否可以自己更改源代码实现?我安装了VS2015社区版,结果报Unable to find vcvarsall.bat错误,请问那两个libthostmduserapi.so和libthosttraderapi.so是在windows下编译出来的吗?我试过linux下如果没有这两个so文件,不能编译出第三个PyCTP.cpython-34m.so。真的非常感谢提供了这个接口!

    • zhuolin
      2018年6月12日 at am9:16 #

      不可以应用于32位linux,CTP官方只提供了64位的库

  23. wlock
    2018年7月18日 at pm10:03 #

    请教个扩展的问题,char[x],用pybytes;如果是struct里面有int[x],double[x],用啥做转换啊?

    • zhuolin
      2018年7月19日 at am8:18 #

      用数组或列表就可以了,在c++中需做一次转换处理. 另外,如是非ctp, 那么python好像提供有直接的c结构类。

  24. wlock
    2018年7月19日 at am9:38 #

    struct OrderBookStruct {
    XTP_EXCHANGE_TYPE exchange_id;
    char ticker[XTP_TICKER_LEN];
    double last_price;
    int64_t qty;
    double turnover;
    int64_t trades_count;
    ///十档申买价
    double bid[10];
    ///十档申卖价
    double ask[10];
    ///十档申买量
    int64_t bid_qty[10];
    ///十档申卖量
    int64_t ask_qty[10];
    /// 时间类
    int64_t data_time;
    } ;

    类似这样的,请教转换函数该怎么写?。。。我先尝试转成list,没有成功;如果是转换成dict怎么写?

    PyObject *PyXTP_PyDict_FromStruct(XTPOB *pOB)
    {
    if(pOB == nullptr) Py_RETURN_NONE;

    PyObject *lbid = PyList_New(10);
    PyObject *lask = PyList_New(10);
    PyObject *lbid_qty = PyList_New(10);
    PyObject *lask_qty = PyList_New(10);
    for(int i=0; i < 10; i++){
    PyList_SetItem(lbid, i, PyFloat_FromDouble(pOB->bid[i]));
    PyList_SetItem(lask, i, PyFloat_FromDouble(pOB->ask[i]));
    PyList_SetItem(lbid_qty, i, PyLong_FromLongLong(pOB->bid_qty[i]));
    PyList_SetItem(lask_qty, i, PyLong_FromLongLong(pOB->ask_qty[i]));
    }

    PyObject *ret=Py_BuildValue("[i,y,d,L,d,L,L]"
    , pOB->exchange_id
    , pOB->ticker
    , pOB->last_price
    , pOB->qty
    , pOB->turnover
    , pOB->trades_count
    , pOB->data_time
    );
    PyList_Append(ret, lbid);
    PyList_Append(ret, lask);
    PyList_Append(ret, lbid_qty);
    PyList_Append(ret, lask_qty);
    Py_DECREF(lbid);
    Py_DECREF(lask);
    Py_DECREF(lbid_qty);
    Py_DECREF(lask_qty);
    return ret;

    }

  25. wlock
    2018年7月19日 at am10:35 #

    PyObject *PyXTP_PyDict_FromStruct(XTPOB *pOB)
    {
    if(pOB == nullptr) Py_RETURN_NONE;

    PyObject *lbid = PyList_New(10);
    PyObject *lask = PyList_New(10);
    PyObject *lbid_qty = PyList_New(10);
    PyObject *lask_qty = PyList_New(10);
    for(int i=0; i < 10; i++){
    PyList_SetItem(lbid, i, PyFloat_FromDouble(pOB->bid[i]));
    PyList_SetItem(lask, i, PyFloat_FromDouble(pOB->ask[i]));
    PyList_SetItem(lbid_qty, i, PyLong_FromLongLong(pOB->bid_qty[i]));
    PyList_SetItem(lask_qty, i, PyLong_FromLongLong(pOB->ask_qty[i]));
    }

    PyObject *ret=Py_BuildValue("{s:i,s:y,s:d,s:L,s:d,s:L,s:O,s:O,s:O,s:O,s:L}"
    , "exchange_id", pOB->exchange_id
    , "ticker", pOB->ticker
    , "last_price", pOB->last_price
    , "qty", pOB->qty
    , "turnover", pOB->turnover
    , "trades_count", pOB->trades_count
    , "bid", lbid
    , "ask", lask
    , "bid_qty", lbid_qty
    , "ask_qty", lask_qty
    , "data_time", pOB->data_time
    );
    Py_DECREF(lbid);
    Py_DECREF(lask);
    Py_DECREF(lbid_qty);
    Py_DECREF(lask_qty);
    return ret;

    }

    另外之前这么写过dict的也不行

    • zhuolin
      2018年7月20日 at pm5:06 #

      python有一个debug模式,在debug模式下,可以直接调试扩展代码。这样更容易发现原因

      • wlock
        2018年7月20日 at pm9:52 #

        好的,多谢

  26. xiong
    2018年8月9日 at pm12:18 #

    您好,请问运行test_PyCTP.py产生
    trader = File “test_PyCTP.py”, line 598, in main
    trader = PyCTP_Trader.CreateFtdcTraderApi(b’tmp_t‘)
    ValueError: parameter invalid.
    报错是什么原因呢?

  27. xiong
    2018年8月9日 at pm12:18 #

    您好,请问运行test_PyCTP.py产生
    trader = File “test_PyCTP.py”, line 598, in main
    trader = PyCTP_Trader.CreateFtdcTraderApi(b’tmp_t‘)
    ValueError: parameter invalid.
    报错是什么原因呢?

    • zhuolin
      2018年8月10日 at pm3:00 #

      必须设置已经存在的文件夹路径,注意看参考代码

  28. xiong
    2018年8月9日 at pm1:59 #

    你好,我使用python2.7 32位的环境编译成功但运行test_PyCTP报错:
    File “test_PyCTP.py”, line 598, in main
    trader = PyCTP_Trader.CreateFtdcTraderApi(b’tmp_t‘)
    ValueError: parameter invalid.
    请问这是什么原因呢?

  29. zhiyi
    2018年10月10日 at am10:46 #

    满屏都是下面的错误
    AttributeError: ‘PyCTP_Trader’ object has no attribute ‘OnRtnQuote’
    AttributeError: ‘PyCTP_Trader’ object has no attribute ‘OnRtnQuote’
    AttributeError: ‘PyCTP_Trader’ object has no attribute ‘OnRtnQuote’
    AttributeError: ‘PyCTP_Trader’ object has no attribute ‘OnRtnQuote’
    AttributeError: ‘PyCTP_Trader’ object has no attribute ‘OnRtnQuote’
    AttributeError: ‘PyCTP_Trader’ object has no attribute ‘OnRtnQuote’

    • zhuolin
      2018年10月11日 at pm1:50 #

      故意增加的这个错误信息,目的是避免事件遗漏。请建立空OnRtnQuote方法 。

  30. Tony
    2018年11月3日 at pm5:20 #

    您好, 很感谢您的开源代码, 看到这个函数不太明白, 好像是不用这个去register spi, 而是在 CTP_THOST_FTDC_MD_API_CreateFtdcMdApi 中就注册好了


    PyObject *CTP_THOST_FTDC_MD_API_RegisterSpi(PyObject *self, PyObject *args)
    {
    CTP_THOST_FTDC_MD_API *api = (CTP_THOST_FTDC_MD_API *) self;
    PyObject *tmp = api->pySpi;
    if (!PyArg_ParseTuple(args, "O", &api->pySpi))
    {
    PyErr_SetString(PyExc_ValueError, "parameter invalid.");
    return nullptr;
    }

    Py_XDECREF(tmp);
    Py_INCREF(api->pySpi);

    Py_RETURN_NONE;
    };

    • zhuolin
      2018年11月6日 at pm1:54 #

      只是为了模拟注册效果,总需要有个回调类.

Leave a Reply

Your email address will not be published.

Time limit is exhausted. Please reload the CAPTCHA.

Proudly powered by WordPress   Premium Style Theme by www.gopiplus.com
渝公网安渝公网安备 50010702500270号 渝ICP备09056628号-7