ホームページ  >  記事  >  バックエンド開発  >  WeChat ミニ プログラム テンプレート メッセージの無制限かつ無制限のアクティブ プッシュを実現します。

WeChat ミニ プログラム テンプレート メッセージの無制限かつ無制限のアクティブ プッシュを実現します。

韦小宝
韦小宝オリジナル
2018-03-01 14:55:599482ブラウズ

要件の背景

WeChat 通知チャネルに基づいて、WeChat ミニ プログラムは、ユーザーがミニ プログラム ページを操作した後にトリガーされ、WeChat チャット リストを通じてすばやくアクセスできます。サービス通知をクリックして詳細を表示し、メッセージを送信したミニ プログラムの指定されたページに移動します。

WeChat アプレットがテンプレート メッセージの発行を許可する条件は、支払いまたはフォーム送信の 2 つのカテゴリに分かれています。フォームの送信によるテンプレート メッセージの送信に関する制限は、「開発者が 7 日以内に限られた数のテンプレート メッセージをユーザーにプッシュできるようにする (フォームを送信すると 1 つのメッセージを送信でき、複数回送信されるメッセージの数は独立しています)」です。相互に影響しません)」。

ただし、ユーザーが一度トリガーされてから 7 日以内に 1 つの通知をプッシュするだけでは明らかに十分ではありません。たとえば、チェックイン機能は、テンプレート メッセージのプッシュを使用して、ユーザーに毎日チェックインすることを通知します。テンプレート メッセージをプッシュする機会は、ユーザーが前日にチェックインしたときに 1 回だけ取得し、それを使用して送信できます。翌日、ユーザーにチェックインのリマインダーを送信します。ただし、多くの場合、ユーザーが特定の日にサインインを忘れた場合、システムはユーザーに通知する権限を失い、その結果、ユーザーとの接続が切断されます。別の例として、システムはユーザーにサインインしていることを積極的に通知したいと考えています。特定のアクティビティを実行しようとしていますが、WeChat アプレットが受動的に通知制限をトリガーすると、システムはメッセージをアクティブにプッシュできなくなります。

テンプレートメッセージのプッシュが制限されないようにする方法は?

突破口: 「1 つのフォーム送信で 1 つのメッセージを発行でき、複数の送信で互いに影響を与えることなく独立した番号を発行できます。」

テンプレート メッセージのプッシュ制限を突破し、7 日以内に任意のプッシュを達成するには、次の手順を実行する必要があります。プッシュ コードは、フォームが送信されるたびに取得される formId です。 formId は、現在のユーザーにテンプレート メッセージをプッシュする開発者の 1 回限りの権限を表します。

クライアント

はプッシュコードを収集します

フォームコンポーネントの属性report-submit=trueがテンプレートメッセージの送信を意味し、フォームを送信することでformIdを取得できる場合。次に、元のページを変更し、ユーザーが最初にクリック イベントをバインドしたインターフェイスをフォーム コンポーネントのボタン ボタン コンポーネントに置き換えるだけです。つまり、ユーザーの対話型クリックのバインドタップ イベントをフォームのバインドサブミットに置き換えます。したがって、ユーザーのクリック イベントをキャプチャして、より多くのプッシュ コードを生成します。

// 收集推送码
Page({
   formSubmit: funcition(e) {
let formId = e.detail.formId;
this.collectFormIds(formId); //保存推送码
let type = e.detail.target.dataset.type; // 根据type执行点击事件
},

   collectFormIds: function(formId) { 
let formIds = app.globalData.globalFormIds; // 获取全局推送码数组
if (!formIds)
           formIds = [];
let data = {
           formId: formId,
           expire: new Data().getTime() + 60480000 // 7天后的过期时间戳
}
       formIds.push(data);
       app.globalData.globalFormIds = formIds;
},
})

レポートプッシュコード

次回ユーザーがネットワークリクエストを開始するのを待って、globalFormIdsがサーバーに送信されます。

// 上报推送码
Page({
   onLoad: funcition(e) {
this.uploadFormIds(); //上传推送码
},

   collectFormIds: function(formId) { 
var formIds = app.globalData.globalFormIds; // 获取全局推送码
if (formIds.length) {
            formIds = JSON.stringify(formIds); // 转换成JSON字符串
            app.globalData.gloabalFomIds = ''; // 清空当前全局推送码
}
       wx.request({ // 发送到服务器
           url: 'http://xxx',
           method: 'POST',
           data: {
               openId: 'openId',
               formIds: formIds
},
           success: function(res) {
}
});
},
})

サーバー

ストレージプッシュコード

Redisを使用してプッシュコードを保存する高頻度IO。

/**
* 收集用户推送码
*
* @param openId        用户的openid
* @param formTemplates 用户的表单模板
*/
public void collect(String openId, List<FormTemplateVO> formTemplates) {
   redisTemplate.opsForList().rightPushAll("mina:openid:" + openId, formTemplates);
}

Pushテンプレートメッセージ

以下は特定のユーザーと同様にグループ送信の機能を実装しています。

/**
* 推送消息
*
* @param templateId 模板消息id
* @param page       跳转页面
* @param keyWords   模板内容
*/
public void push(String templateId, String page, String keyWords) {
String logPrefix = "推送消息";

// 获取access token
String accessToken = this.getAccessToken();

// 创建消息通用模板
MsgTemplateVO msgTemplateVO = MsgTemplateVO.builder().template_id(templateId).build();
// 跳转页面
   msgTemplateVO.setPage(StringUtils.isNotBlank(page) ? page : "");
// 模板内容
if (StringUtils.isNotBlank(keyWords)) {
String[] keyWordArr = keyWords.split(BaseConsts.COMMA_STR);
Map<String, MsgTemplateVO.KeyWord> keyWordMap = new HashMap<>(8);
for (int i = 0; i < keyWordArr.length; i++) {
MsgTemplateVO.KeyWord keyWord = msgTemplateVO.new KeyWord(keyWordArr[i]);
           keyWordMap.put(MsgTemplateVO.KEYWORD + (i + 1), keyWord);
}
       msgTemplateVO.setData(keyWordMap);
} else {
       msgTemplateVO.setData(Collections.emptyMap());
}

// 获取所有用户
List<String> openIdList = minaRedisDao.getAllOpenIds();

for (String openId : openIdList) {
// 获取有效推送码
String formId = minaRedisDao.getValidFormId(openId);
if (StringUtils.isBlank(formId)) {
           LOGGER.error("{}>>>openId={}>>>已无有效推送码[失败]", logPrefix, openId);
continue;
}

// 指派消息
MsgTemplateVO assignMsgTemplateVO = msgTemplateVO.assign(openId, formId);

// 发送消息
Map<String, Object> resultMap;
try {
String jsonBody = JsonUtils.getObjectMapper().writeValueAsString(assignMsgTemplateVO);

String resultBody = OkHttpUtils.getInstance().postAsString(messageUrl + accessToken, jsonBody);
           resultMap = JsonUtils.getObjectMapper().readValue(resultBody, Map.class);
} catch (IOException e) {
           LOGGER.error("{}>>>openId={}>>>{}[失败]", logPrefix, openId, e.getMessage(), e);
continue;
}

if ((int) resultMap.get(ResponseConsts.Mina.CODE) != 0) {
           LOGGER.error("{}>>>openId={}>>>{}[失败]", logPrefix, openId, resultMap.get(ResponseConsts.Mina.MSG));
continue;
}

       LOGGER.info("{}>>>openId={}>>>[成功]", logPrefix, openId);
}
}

/**
* 根据用户获取有效的推送码
*
* @param openId 用户的openid
* @return 推送码
*/
public String getValidFormId(String openId) {
List<FormTemplateVO> formTemplates = redisTemplate.opsForList().range("mina:openid:" + openId, 0, -1);

String validFormId = "";
int trimStart = 0;

int size;
for (int i = 0; i < (size = formTemplates.size()); i++) {
if (formTemplates.get(i).getExpire() > System.currentTimeMillis()) {
           validFormId = formTemplates.get(i).getFormId();
           trimStart = i + 1;
break;
}
}

// 移除本次使用的和已过期的
   redisTemplate.opsForList().trim(KEY_MINA_PUSH + openId, trimStart == 0 ? size : trimStart, -1);

return validFormId;
}

上記のソリューションでは、ユーザーが最後にミニ プログラムを使用してから 7 日以内にユーザーを呼び戻すために、複数のテンプレート メッセージをユーザーに送信できます。

これは、WeChat ミニ プログラム テンプレート メッセージの無制限かつ無制限のアクティブ プッシュを実装する方法の詳細です。

関連記事:

WeChatアプレットメッセージプッシュPHPサーバー検証

以上がWeChat ミニ プログラム テンプレート メッセージの無制限かつ無制限のアクティブ プッシュを実現します。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。