⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sendsm.cpp

📁 小灵通(网通)短信接口程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#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 + -