【GAS】Vectorのシェアレジのライセンスキーを自動でメール送信するGoogle App Script

Vecotorのシェアレジとは

個人でPCソフトを配布する方法として、Vectorに登録してVector経由で配布してもらう、という方法があります。その際、フリーソフトではなく有料で販売する場合は、プロレジもしくはシェアレジで販売するということになります。基本、法人はプロレジ、個人事業主はシェアレジです。プロレジとシェアレジ違いの詳細は、Vectorのサイトでご確認ください。

プロレジとシェアレジの関係

筆者はシェアレジを利用しているので、ここではシェアレジでの説明とさせていただきます。シェアレジの販売の流れとしては、以下のようになります。

  1. ソフト購入者がVectorのサイトでソフト購入の申し込み
  2. Vectorがソフト販売者にライセンスキーの登録依頼をメール送信
  3. ソフト販売者がVectorにライセンスキーをメール送信、もしくはVectorのサイトにライセンスキーを登録
  4. Vectorがソフト購入者にライセンスキー連絡
  5. ソフト購入者がライセンス購入

今回、このページでは3のソフト販売者(筆者)がVectorにライセンスキーのメール返信を自動でおこなうGoogle App Scriptの説明となります。このGoogle App Scriptを稼働させておくことにより、基本、ソフト購入申し込みがあってもソフト販売者は何もしなくてもOKとなります。

筆者がVectorに登録しているソフトは、たまーにしかライセンス登録依頼が来ないので、さほど手間がかかるわけでもなく登録依頼がきたらきたで嬉しいかぎりなのですが、外出時など朝に登録依頼が来ていても、夜家に帰ってきてからライセンスキーをメール送信、と結構タイムラグが生じます。

シェアレジでは事前にVectorのサイトにライセンスキーを登録しておく、ということができません。なので、ソフト購入者が購入申し込みの都度、ライセンスキーをメール送信、もしくはVectorのサイトにライセンスキーを登録しなければなりません。事前にいくつかライセンスキーを登録しておいて、購入申し込みがあったら自動でその登録分を購入者に連絡してくれたりしたら最高なんですが。

メール返信でのライセンスキー登録手順

まずは、Vectorでシェアレジを利用していない人向けに、Vectorからのメール連絡のサンプルをご紹介します。

Vectorからライセンスキー登録依頼メール

ソフト購入申し込みがあると、Vectorから”[シェアレジ]ライセンスキー登録依頼”という件名のメールが送られてきます。

件名:[シェアレジ]ライセンスキー登録依頼

●● 様

登録作品に対して下記のお申込みがありました。
至急、ライセンスキーをベクターレジサービスにご登録ください。

—————————–
お申込日            : 2021/12/01
キー登録期限        : 2021/12/07 24時まで
—————————–
作品番号            : ●●●●●●●●
お申込作品名        : ●●●●●●
—————————–
お申込番号          : ●●●●●●●●
—————————–
利用者連絡欄        :

★ご注意★
・ライセンスキーは、必ずベクターレジサービスにご登録してください。
  登録されたライセンスキーは、お客様のお支払手続が完了した後、
  送信いたします。
・皆様より、お客様に直接ライセンスキーを送らないでください。
  (まだお客様はお支払手続を完了しておりません。)

★本メールへの返信で登録するには★
・ライセンスキーの登録は、本メールへの返信としても登録できます。
・返信メールで登録する時は、以下の#softkey~#softkey_endの間に
  ライセンスキーを記入してください。
・なお、その際引用記号(‘> ‘など)は付けないようお願いいたします。
・ライセンスキーがファイルの場合はそのファイルを返信メールに添付し、
  #softkey~#softkey_endの間にファイル名を記入してください。
(ファイル名は、半角のアルファベットおよび英文字です。
  漢字、ひらがな、カタカナのファイル名は使用できません。)
・機種依存文字、半角カナなどは途中で文字化けの可能性がありますので、
 ご利用をお控えください。また、HTMLメールではメーラーの仕様により
 半角スペースが に置き換えられて送出されるなどのトラブルが
 見受けられますので、なるべくプレーンテキストでお送りください
・詳細はhttp://www.vector.co.jp/swauth/man/help/pagehelp09.htmlご覧
  ください。

—————————–
メールによる登録の場合、#startから#endまでは必ず含めて送ってください。
#start
#auth_id ●●●●●●●●
#srnum ●●●●●●●●
#recno ●●●●●●●●
#user_addr ******
#order_pw ●●●●●●●●
#comment ↓ライセンスキーを記入してください
#softkey

#softkey_end
#end
—————————–

==================
ベクター・レジ・センター
お問い合わせ先
  Mail: swregmgr@vector.co.jp

Vectorへライセンスキーをメール返信

次は、Vectorへライセンスキーをメール返信の形で登録するメールサンプルです。返信の形で#startから#endまでを送ります。この#softkeyから#softkey_endの間の▲▲▲▲▲▲▲▲がライセンスキーとなります。

今回ご紹介するのは、このメール返信を自動返信するためのGoogle App Scriptとなります。

件名:Re: [シェアレジ]ライセンスキー登録依頼

#start
#auth_id ●●●●●
#srnum ●●●●●
#recno ●●●●●
#user_addr ******
#order_pw ●●●●●
#comment ↓ライセンスキーを記入してください
#softkey
▲▲▲▲▲▲▲▲
#softkey_end
#end

Vectorからライセンスキー登録受付メール

ライセンスキーをメール返信すると、即座にVectorよりライセンスキー登録の受付メールが届きます。”[プロレジ/シェアレジ]ライセンスキー登録結果”という件名で届くのですが、実際は、登録結果というより登録受付です。

件名:[プロレジ/シェアレジ]ライセンスキー登録結果

ライセンスキー登録のメールを受付けました。
結果はメールでお知らせいたします。

==================
ベクター・レジ・センター

Vectorよりライセンスキー登録結果メール

登録受付メールに続いて、Vectorよりライセンスキー登録結果メールが届きます。メール返信の際に、指定されたタグ#startで始まらなかったりした場合は、エラーの旨のメールが届きますので、再度正しい内容でメール返信します。

件名:[シェアレジ]ライセンスキー登録結果●●●●●●

ライセンスキー登録の結果を送付いたします。

——————————
レジ作者ID       : ●●●●●●
申請日           : 2021/12/01 12:00:00
——————————
処理件数:   1件
正常処理数: 1件
エラー数:   0件
——————————
●●●●●●,●●●●●●,2021/12/08 00:00:00,●●●●●●:ライセンスキーの登録に成功しました。
——————————

★ライセンスキーの再登録★
ライセンスキーの登録は、下記のURLのライセンスキー登録ページで
行ってください。

https://vecauthor.vector.co.jp/regauthor/htdocs/licence_key/

==================
ベクター・レジ・センター
お問い合わせ先
  Mail: swregmgr@vector.co.jp

Vectorより利用者がお支払いお知らせメール

ソフト購入者がVectorに支払いを完了すると、Vectorより購入者のお支払い完了メールが届きます。Vectorは購入者が支払手続きを済ませるとライセンスキーを購入者へ送付します。

件名:[シェアレジ]ご利用の連絡 ●●●●●●
●● 様

登録作品に対してお客様からのお支払い手続きがありましたの
でご連絡いたします。

———————————-
作品番号       : ●●●●●●
作品名         : ●●●●●●
———————————-
申込日         : 2021/12/01
支払日         : 2021/12/01
———————————-
お申込番号     : ●●●●●●
———————————-
送付ライセンスキー   : ▲▲▲▲▲▲▲▲
———————————-

==================
ベクター・レジ・センター
お問い合わせ先
  Mail: swregmgr@vector.co.jp

Vectorにライセンスキー送付後、支払手続きをしないままだったり、購入キャンセルの場合もあります。一定期間支払手続きがされないと、Vector側で自動でキャンセル扱いになり、Vectorよりキャンセルのお知らせメールが送られてきます。

ライセンスキー送付実行用 Google App Script

ここからは、ライセンスキー送付実行用のGoogle App Scriptの詳細となります。

まず、ライセンスキー送付用のGoogleスプレッドシートを用意します。筆者の場合は、事前にVBAである程度の数のライセンスキーを生成し、スプレッドシートに貼り付けます。

※ライセンスキー生成については、開発者によっていろいろ方法あると思いますが、筆者はVBAでロジックを組んでライセンスキーを生成し、ソフト側では同様のロジックでライセンスキーのパターンをチェックしています。

スプレッドシート用意

以下のヘッダのスプレッドシートを作成します。ライセンスキーにはあらかじめ作成しておいたキーをいくつか入れておきます。

ライセンスキー メールID 申込日 作品番号 申込番号 ライセンスキー送付日時 支払日 備考

 

スクリプト

スクリプトのコードは以下のとおりです。トリガで1時間に1回チェックするようにしています。

/*
* Vectorシェアレジライセンスキー返信メール送付
*/
function sendLicenseKey() {
  var exeStartDateTime = new Date();
  var mySh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('リスト');
  const inputDateTimeRange = 'J1';
  const searchSubject = '[シェアレジ]ライセンスキー登録依頼';
  var afterQuery = '';
  //スクリプト最終実行日時を取得
  var lastDateTime = mySh.getRange(inputDateTimeRange).getValue();
  if(isDate(lastDateTime)){
    var lastDateTimeUnixTime = lastDateTime.getTime();
    var lastDateTimeMillSec = Math.floor(lastDateTimeUnixTime/1000);
    afterQuery = ' after:' + lastDateTimeMillSec;
  }
  else{
    //スクリプト最終実行日時が日時でない場合は、1週間以内を条件にセット
    afterQuery = ' newer_than:7d';
  }

  //対象メール取得 /件名が一致、かつスクリプト最終実行日時より後(または1週間以内のメール)
  var query = 'subject:' + searchSubject + afterQuery;
  var threads = GmailApp.search(query, 0, 30);
  var msgs = GmailApp.getMessagesForThreads(threads);

  var resultAr = [];
  var n = 0;
  var keyAr;
  if(msgs.length > 0){
    var rows = mySh.getRange("B:B").getValues();
    //開始行取得
    var startRow = rows.filter(String).length + 1;
    //送付用ライセンスキーを配列に格納
    keyAr = mySh.getRange(startRow, 1, msgs.length, 1).getValues();
  }
  
  //対象メールを古い順に検索
  for(var i = msgs.length-1; i >= 0; i--) {
    var isTarget = true;
    //返信がないスレッドかどうかチェック
    for(var k = 0; k <= msgs[i].length-1; k++){
      if(msgs[i][k].getSubject() != searchSubject){
        isTarget = false;
        break;
      }
    }
    
    if(isTarget){
      //対象スレッドを古い順に処理
      for(var k = msgs[i].length-1; k>=0; k--){
        var msgId = msgs[i][k].getId();
        var sendDate = msgs[i][k].getDate();
        var sendTo = msgs[i][k].getTo();
        var msgBody = msgs[i][k].getPlainBody();
        var bodyAry = msgBody.split('\n');
        var startIndex = -1;
        //本文返信用開始行#startを取得
        for(var j = 0; j < bodyAry.length; j++){
          if(bodyAry[j].startsWith('#start')){
            var startIndex = j;
            break;
          }
        }
        
        var appNo = '';
        var applyNo = '';
        var replyBody = '';
        
        if(startIndex > -1 && keyAr[n][0].length > 1){
          //返信用本文組み立て
          for(var j = startIndex; j < bodyAry.length; j++){
            //本文組み立て
            var bodyStr;
            if(bodyAry[j].length < 2 && j != startIndex && bodyAry[j-1].startsWith('#softkey')
              && j != bodyAry.length-1 && bodyAry[j+1].startsWith('#softkey_end')){
                //ライセンスキーを本文にセット
                bodyStr = keyAr[n][0];
              }
            else{
              bodyStr = bodyAry[j];
            }
            replyBody += bodyStr + '\n';
            
            //#end=ループ終了
            if(bodyAry[j].startsWith('#end')){
              break;
            }
            else if(bodyAry[j].startsWith('#srnum ')){
              //申込番号取得
              appNo = bodyAry[j].replace('#srnum ','');
            }
            else if(bodyAry[j].startsWith('#recno ')){
              //作品番号取得
              applyNo = bodyAry[j].replace('#recno ','');
            }
          }
          
          //メール返信実行
          msgs[i][k].reply(replyBody, {
            from: sendTo
          });
          
          var sendDateTime = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyy/MM/dd HH:mm:ss')
          
          //結果を配列に格納
          var result = [msgId, sendDate, appNo, applyNo, sendDateTime];
          resultAr.push(result);
          n += 1;
        }
      }
    }
  }
  
  //送信結果書き込み
  if(resultAr.length > 0){
    mySh.getRange(startRow, 2, resultAr.length, 5).setValues(resultAr);
  }
  //実行日時をセット
  mySh.getRange(inputDateTimeRange).setValue(exeStartDateTime);
  //処理件数をセット
  mySh.getRange(inputDateTimeRange).offset(0, 1).setValue(resultAr.length);
}

/*
* 日付判定
*/
function isDate(d) {
  if (Object.prototype.toString.call(d) === "[object Date]") {
    if (isNaN(d.getTime())) {
      return false;
    } else {
      return true;
    }
  } else {
    return false;
  }
}

 

 

 

コメント

タイトルとURLをコピーしました