📄 sendsm.cpp
字号:
#include "StdAfx.h"
#include "smei.h"
#include "smset.h"
#include "SendSM.h"
extern char szIcpNbr[];
extern char szCorpId[];
typedef struct tagSUBMITINFO {
long lRelatedMO; //对应的MO标识,为0表示由SP发起的
LPCSTR lpcszFromMobile; //发送方,可以是服务号码+用户定义标识,最长不超过19位
LPCSTR lpcszToMobile; //接受该短消息的手机号
LPCSTR lpcszServiceType; //业务代码,由sp定义
int nFeeType; //计费类型
int nFeeCode; //该条短消息的收费值;单位为分
int nPriority; //优先级0-9,从低到高
LPCSTR lpcszFeeMobile; //收费的手机号码,为NULL或"",则表示不指定
LPCSTR lpcszExpireTime; //短消息寿命的终止时间;"yymmddhhmmsstnnp";"tnnp"取固定值"032+"
LPCSTR lpcszScheduleTime; //定时发送时间
int nMessageLength; //短消息长度
LPCSTR lpcszMsgContent; //短消息内容
} SUBMITINFO, * PSUBMITINFO, FAR * LPSUBMITINFO;
BOOL bInitOK = FALSE;
BOOL bLoginOK = FALSE;
static BOOL bStop = FALSE;
void MoveTitle()
{
char szChar[3], szTitle[80];
memset(szTitle, 0, sizeof(szTitle));
GetConsoleTitle(szTitle, sizeof(szTitle));
memcpy(szChar, szTitle, 2);
szChar[2] = '\0';
memmove(szTitle, szTitle + sizeof(unsigned short), strlen(szTitle + sizeof(unsigned short)) + 1);
strcat(szTitle, szChar);
SetConsoleTitle(szTitle);
}
void ProcRawMsgID(LPCSTR lpcszRawMsgID, LPSTR lpszMsgID, int cbMsgID)
{
_ASSERT(cbMsgID >= 21);
memset(lpszMsgID, 0, cbMsgID);
for (int i = 0; i < 10; i ++) sprintf(lpszMsgID + strlen(lpszMsgID), "%02X", 0xFF & lpcszRawMsgID[i]);
}
void LoggingDeliveryInfo(DELIVERRESP& dr)
{
CString strError;
CString msg, sql;
if (dr.nIsReply) {
// 收到状态报告
//printf("\n移动状态报告:%s\n", dr.sMsgContent);
return;
}
_ASSERT (dr.nMsgLen <= 116);
// 将信息拷入msg中,以便处理,因为dr.lpcszMsgContent不一定以\0结尾
try {
LPSTR p = msg.GetBuffer(dr.nMsgLen + 1);
memcpy(p, dr.sMsgContent, dr.nMsgLen);
p[dr.nMsgLen] = '\0';
msg.ReleaseBuffer();
} catch(CMemoryException*){
FatalAppExit(0, "内存不足,无法创建缓冲区。");
}
// 将 ' 变成 ''
msg.Replace("'", "\x3");
msg.Replace("\x3", "''");
CMyDatabase db;
printf("\n收到%s发到%s信息(ID:%s):%s", dr.sSrcTermID, dr.sDestTermID, dr.sServiceID, msg);
if (MakeSureDBConnected(db, strError)){
sql.Format( "EXECUTE ismr_sp_delivery \r\n"
" @FROMMOBILE = '%s', \r\n"
" @TOMOBILE = '%s', \r\n"
" @ICPNUMBER = '%s', \r\n"
" @MSGLEVEL = %d, \r\n"
" @MESSAGE = '%s' \r\n",
dr.sSrcTermID,
dr.sDestTermID,
dr.sServiceID,
dr.nMsgLevel,
msg);
if (db.ExecuteSQLEx(strError, sql) != -1){
printf("\n登记成功。");
strError = "";
}
}
if (!strError.IsEmpty()){
printf("\n登记失败,因为数据库错误:%s\n", strError);
LogError(".sql", "sqlError", "/* SQL */\n%s\n/* ERROR: %s */", sql, strError);
}
return;
}
int cngpSubmit(SUBMITINFO &submit, char* szMsgID, int lenMsgID, char szSrcTermId[21 + 1])
{
int nPhsFeeType = -1;
int nMsgFormat = MSG_FORMAT_ASCII;
int nResult = 0;
int nNeedReply = 1; // 0=不要求,1=要求
int nSubType = 2; // 短消息子类型(0=取消订阅,1=订阅或点播请求,2=点播下发,3=订阅下发,其他保留)
int nFeeUserType = 0;
char szFeeType[3], szFeeCode[7];
char szRawMsgID[11];
_ASSERT (strlen(szIcpNbr) + strlen(submit.lpcszFromMobile) <= 19);
sprintf(szSrcTermId, "%s%s", szIcpNbr, submit.lpcszFromMobile);
if (!submit.lpcszFeeMobile) submit.lpcszFeeMobile = "";
if (*submit.lpcszFeeMobile) nFeeUserType = 3;
switch(submit.nFeeType){
case 1:
nPhsFeeType = 0; // 转化成PHS的FeeType
if (!submit.lRelatedMO){
// 由SP发起的MT
nSubType = 3; // 订阅下发
nFeeUserType = 2; // 对SP计费
} else {
// 由MO发起的MT
nSubType = 2; // 点播下发
}
break;
case 2:
nPhsFeeType = 1; // 转化成PHS的FeeType
if (!submit.lRelatedMO){
// 由SP发起的MT
nSubType = 3; // 订阅下发
} else {
// 由MO发起的MT
nSubType = 2; // 点播下发
}
break;
case 3: // 包月扣费请求
nPhsFeeType = 4; // 扣费请求
nSubType = 3; // 订阅下发
break;
default:
return SP_ERROR_INVALID_FEETYPE;
}
for (unsigned i = 0; i < strlen(submit.lpcszMsgContent); i ++){
if ((unsigned char)submit.lpcszMsgContent[i] > 0x80){
nMsgFormat = MSG_FORMAT_GB;
}
}
_ASSERT (nPhsFeeType >= 0 && nPhsFeeType <= 4);
sprintf(szFeeType, "%02d", nPhsFeeType);
_ASSERT (submit.nFeeCode >= 0 && submit.nFeeType <= 999999);
sprintf(szFeeCode, "%06d", submit.nFeeCode);
/*
printf("\nSP企业代码: %s", szCorpId);
printf("\n短消息子类型:%d (0=取消订阅,1=订阅或点播请求,2=点播下发,3=订阅下发)", nSubType);
printf("\n确认报告:%d(0=不要求,1=要求)", nNeedReply);
printf("\n信息级别:%d(0=最低,1=正常,2=紧急,3=十分紧急)", submit.nPriority);
printf("\n业务类型:%s", submit.lpcszServiceType);
printf("\n资费类别:%s", szFeeType);
printf("\n计费用户类型:%d", nFeeUserType);
printf("\n资费代码:%s", szFeeCode);
printf("\n信息格式:%d", nMsgFormat);
printf("\n存活有效期:%s", submit.lpcszExpireTime);
printf("\n定时发送时间:%s", submit.lpcszScheduleTime);
printf("\n源发方号码:%s", szSrcTermId);
printf("\n被计费用户的号码:%s", submit.lpcszFeeMobile);
printf("\n接收方的手机号码:%s", submit.lpcszToMobile);
printf("\n短信长度:%d", submit.nMessageLength);
printf("\n短信内容:%s", submit.lpcszMsgContent);
*/
nResult = _CNGPSubmit(szCorpId, // SP企业代码
nSubType, // 短消息子类型(0=取消订阅,1=订阅或点播请求,2=点播下发,3=订阅下发,其他保留)
nNeedReply, // 是否要求返回状态报告:(0=不要求,1=要求)
submit.nPriority, // 信息级别(0=最低优先级,1=正常,2=紧急,3=十分紧急)
submit.lpcszServiceType, // 业务类型,最长10字节
szFeeType, // 资费类别,最长2字节(01-免费 02-按条 03-包月)
nFeeUserType, // 计费用户类型字段,0:对目的终端计费;1:对源终端计费;2:对SP计费; 3:表示本字段无效,对谁计费参见Fee_terminal_id字段。
szFeeCode, // 资费代码(以分为单位) ,最长6字节
nMsgFormat, // 信息格式
submit.lpcszExpireTime, // 存活有效期
submit.lpcszScheduleTime, // 定时发送时间
szSrcTermId, // 源发方的手机号码或ICP服务编号(特服号+用户自定义标识)
submit.lpcszFeeMobile, // 被计费用户的号码(如本字节填空,则表示本字段无效,对谁计费参见Fee_UserType字段。本字段与Fee_UserType字段互斥),最长21 bytes。
1, // 给多少个用户发
submit.lpcszToMobile, // 接收方的手机号码
submit.nMessageLength, // 短信长度
submit.lpcszMsgContent, // 短信内容
0, // 协议类型 0-缺省
(unsigned char*)szRawMsgID); // 用来取得MSGID (接收返回的短信标识)
memset(szMsgID, 0, lenMsgID);
ProcRawMsgID(szRawMsgID, szMsgID, lenMsgID);
return nResult;
}
// 返回页数,返回0表示页数太多,返回-1表示内存不足,要求释放aMsgPtr[i]内容
int SplitMessage(wchar_t* lpwMsg, int nWordCnt, wchar_t* aMsgPtr[], int nMsgPtr)
{
int nTotal = 0;
LPWSTR lpwBuffer;
// 将所有指针置 NULL
memset(aMsgPtr, 0, nMsgPtr * sizeof(LPWSTR));
if (nWordCnt <= 59){
// 中文和英文都可以一屏发送,故没有问题
lpwBuffer = new WCHAR[1 + nWordCnt];
if (lpwBuffer == NULL) return -1;
lpwBuffer[0] = nWordCnt;
memcpy(&lpwBuffer[1], lpwMsg, nWordCnt * sizeof(WCHAR));
aMsgPtr[0] = lpwBuffer;
return 1;
}
if (nWordCnt <= 112){
// 只有英文与数字或半角符号可以一屏发送,故判断
for (int i = 0; i < nWordCnt; i ++){
if (lpwMsg[i] > 0xFF) break;
}
if (i >= nWordCnt){
// 全是英文与数字或半角符号
lpwBuffer = new WCHAR[nWordCnt + 1];
if (lpwBuffer == NULL) return -1;
lpwBuffer[0] = nWordCnt;
memcpy(&lpwBuffer[1], lpwMsg, nWordCnt * sizeof(WCHAR));
aMsgPtr[0] = lpwBuffer;
return 1;
}
}
// 以下必须分屏显示
int nPageBytes = 112 - 8;
int nStart = 0;
int nLen = 0;
for (int i = 0; i < nWordCnt; i ++){
// 判断加上本字符是否超屏
if ((nLen == nPageBytes) || (lpwMsg[i] > 0xFF && nLen + 1 > 59 - 8)){
// 超过或到达一屏,则拷贝本屏
lpwBuffer = new WCHAR[1 + nLen + 8];
if (lpwBuffer == NULL){
for (int i = 0; i < nTotal; i++) delete aMsgPtr[i];
return -1;
}
lpwBuffer[0] = nLen + 8;
memcpy(&lpwBuffer[1], "(\0i\0/\0n\0)\0\0\0", 5 * sizeof(WCHAR));
lpwBuffer[2] = (nTotal + 1) + '0';
memcpy(&lpwBuffer[1 + 5], lpwMsg + nStart, nLen * sizeof(WCHAR));
memcpy(&lpwBuffer[1 + 5 + nLen], ".\0.\0.\0\0\0", 3 * sizeof(WCHAR));
aMsgPtr[nTotal++] = lpwBuffer;
if (nTotal >= 10){
for (int i = 0; i < nTotal; i++) delete aMsgPtr[i];
return 0;
}
// 重新设置有关初始,开始下一轮
nPageBytes = 112 - 8;
nStart += nLen;
nLen = 0;
}
// 判断当前字符是否为汉字,是则调整页长度
if (lpwMsg[i] > 0xFF) nPageBytes = 70 - 8;
// 并计数
nLen ++;
}
if (nLen > 0){
lpwBuffer = new WCHAR[1 + nLen + 8];
if (lpwBuffer == NULL){
for (int i = 0; i < nTotal; i++) delete aMsgPtr[i];
return -1;
}
lpwBuffer[0] = nLen + 8;
memcpy(&lpwBuffer[1], "(\0i\0/\0n\0)\0\0\0", 5 * sizeof(WCHAR));
lpwBuffer[2] = (nTotal + 1) + '0';
memcpy(&lpwBuffer[1 + 5], lpwMsg + nStart, nLen * sizeof(WCHAR));
memcpy(&lpwBuffer[1 + 5 + nLen], ".\0.\0.\0\0\0", 3 * sizeof(WCHAR));
aMsgPtr[nTotal++] = lpwBuffer;
if (nTotal >= 10){
for (int i = 0; i < nTotal; i++) delete aMsgPtr[i];
return 0;
}
}
for (i = 0; i < nTotal; i ++){
aMsgPtr[i][4] = nTotal + '0';
}
return nTotal;
}
long LoggingSubmitInfo(CMyDatabase& db, SUBMITINFO& submit, int index)
{
CString strError;
char sql[512]; // 196 + 10 + 21 + 21 + 10 + 10 + 10 + 10 + 16 + 16 + 10 + 161
CString msg;
_ASSERT(index <= 9);
_ASSERT(submit.nMessageLength <= 116);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -