English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

PHPで微信の红包発行と红包受け取り効果を模倣

最近のプロジェクトではチャットの上に红包機能を追加する必要があります。要件:微信(メッセージ機能を含まない)を模倣し、ただし、残高を使って红包を発行することができます。したがって、微信红包を何度も使用し、さまざまなインタラクションインターフェースおよびビジネス要件(表示情報、カテゴリ(個人、グループ通常、グループの当たり前)、個数制限(100)、金額制限(200)、有効期限(24時間(など、それから開発に着手し、以下に述べるのはすべてアプリエンド向けのインターフェースです。なぜなら、私はPHPプログラマーだからです。

一、设计数据表如下

一、以下のようにデータテーブルを設計します。
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(10CREATE TABLE `red_packet` (
) unsigned NOT NULL DEFAULT '0' COMMENT 'ユーザーID',10`for_id` int(
) unsigned NOT NULL DEFAULT '0' COMMENT '配布対象(ユーザーやグループID)',1`pay_status` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '支払い状態:0未支払い,
) unsigned NOT NULL DEFAULT '0' COMMENT '支払い済み',1`type` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT 'タイプ:',2、個人,3、群通常,
、群パズル手合い',255) NOT NULL DEFAULT '' COMMENT '紹介',
`number` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '数',
`total_money` decimal(10,2) unsigned NOT NULL DEFAULT '0.0' COMMENT '総金額',
`single_money` decimal(10,2) unsigned NOT NULL DEFAULT '0.0' COMMENT '単一の红包金額(群パズル手合い時は0)',
`return_money` decimal(10,2) unsigned NOT NULL DEFAULT '0.0' COMMENT '返金額',
`is_cli_handle` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT 'cliリフレンド処理が行われたか:0いいえ,1は
`expend_time` mediumint(1) unsigned NOT NULL DEFAULT '0' COMMENT 'リード消費時間',
`add_time` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '作成時間',
`pay_time` int(10unsigned NOT NULL DEFAULT '0' COMMENT '支払い時間',
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`),
KEY `pay_status` (`pay_status`),
KEY `pay_time` (`pay_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='红包配布テーブル';
CREATE TABLE `red_packet_log` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`rp_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT='红包ID',
`user_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT='取得人ID',
`money` decimal(10,2) unsigned NOT NULL DEFAULT '0.0' COMMENT='取得金額',
`is_good` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT='是否手气最佳:0否,1は
`add_time` int(10) unsigned NOT NULL DEFAULT '0' COMMENT='追加時間',
`update_time` int(10) unsigned NOT NULL DEFAULT '0' COMMENT='取得時間',
PRIMARY KEY (`id`),
KEY `rp_id` (`rp_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='红包取得ログテーブル';

二、红包の配布

支払いが成功した後、红包はすぐにチャットエリアに表示されますので、左図の「红包に金を入れる」時に红包情報をred_packetテーブル(支払い状態は未支払い)に挿入し、金額を割り当て、手数料をランダムに並べ替えてred_packet_logテーブル(取得者と取得時間は空)に挿入します。右図の「支払いを確認する」が成功した後、red_packetテーブルの支払い状態を更新し、红包を発行します。

三、红包の取得(ここでは、グループ红包に限って分析します)

红包を取得するための様々な前提条件は自分で考えてください。ここでは、グループ红包を取得する並行処理問題(グループ内の数十人で数個の红包を取得する)について説明し、MQを解決策として導入します。红包を配布する際には、まず红包の数を順番にMQに書き込んでください。3個の红包を、順次書き込みます。1、2、3。红包を奪取する際にはMQから値を取得し、取得できる数字がある場合、あなたが何番目に红包を奪取したかを示します。red_packet_log テーブル内の何番目の红包に対応します。次に、red_packet_log テーブルの引き出し人と引き出し時間、残高を加えるとともに、流水の記録などの業務処理を行い、引き出し結果を返します。取得できない数字の場合、当然、红包を奪取できません。"手遅れ"の画面を出力します。初期には、red_packet_log テーブルの主キーをMQに書き込むことを検討しましたが、これにより「引き出し消費時間」の字項の更新がより複雑になるため、MQに数字を保存して直接最後の红包かどうかを比較し、消費時間を更新することができます。

微信红包の引き出し結果ページ(手気ページと呼ばれる)は非常に多くの種類があります:個別とグループの結果が異なる、送信者と引き出し者が異なる、個別とグループの红包が期限切れになった場合のメッセージが異なるなど、すべてのものは画面に基づいてデータベースを確認するだけで済みます。

四、要求変更、第三者支払いの追加

第三者支払いについて言及すると、同期および非同期コールバック、そしてコールバック時間差が提唱されます。アプリ端が同期コールバックが成功した場合、红包が送信されます(アプリ端の支払い同期コールバックは直接callbackを呼び出します)。その場合、非同期コールバックが数秒遅れた場合、ユーザーはこの支払い状態が0の红包を奪取します。アプリ端が長い接続インターフェースを呼び出して非同期コールバックが成功したかどうかを確認し、红包を送信するという方法は、ユーザーエクスペリエンスが悪くなるでしょう。

# 中間状態の導入
テーブル `red_packet` を変更します。
カラム `pay_status` を変更します。1) SIGNED NOT NULL DEFAULT 0 COMMENT '支払い状態:0未支払い、1支払い済み、2入金待ち' `for_id` の後ろに追加します。
カラム `pay_type` を追加します。1) NOT NULL DEFAULT 0 COMMENT '支払い方法:0未知、1支付宝、2微信、3銀联' `pay_status` の後ろに追加します。
カラム `trade_no` を追加します。30) NOT NULL DEFAULT '' COMMENT '第三方支払い取引番号' `pay_type` の後ろに追加します;
テーブル `red_packet_log` を変更します。
カラム `is_into_account` を追加します。1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '到着:0いいえ,}}1が 'AFTER `is_good`;

ユーザーが红包を手に入れた場合、pay_statusに基づいてis_into_accountの値を決定します;

同期コールバックがアプリエンドに到着した場合、インターフェースを呼び出して支払いステータス pay_status を2;

非同期コールバックがサーバー側に到着した場合、支払いステータス pay_status を1、そして is_into_account=1 の red_packet_log レコードを処理します。

しかし、上記の三つのステップはすべて red_packet のクエリに対して FOR UPDATE 操作を行う必要があります。それしないと、実行時間と順序の問題が発生し、一部の red_packet_log レコードが未入金 is_into_account=0 になります。また、ロックメカニズムはユーザーが红包を引く際に非常に遅くなる原因にもなります。ロックが解放されるまで待つ必要があります。


以下のように改善しました:(全て FOR UPDATE なし)

ユーザーが红包を手に入れた場合、pay_statusに基づいてis_into_accountの値を決定します;

同期コールバックがアプリエンドに到着した場合、インターフェースを呼び出して支払いステータス pay_status を2;

非同期コールバックがサーバー側に到着した場合、支払いステータス pay_status を1、そして红包ID(red_packetの主キー)をMQに格納します;

バックエンドの自動スクリプトは、MQから红包IDを取得した後、is_into_account=0のレコードを処理し、その後遅延5秒単位で红包IDを再度MQに書き込み、再度処理を行い、データが全て入金されることを確実にします。

五、红包が期限切れとなった場合の返金

ここには自動スクリプトが一つあります。red_packet テーブルの pay_time に基づいて、超過しているかどうかを判断します。24時間が経過し、まだ受け取っていないお金は、ユーザーの残高に返金されます。

声明:この記事の内容はインターネットから取得され、著作権者は所有者であり、インターネットユーザーが自発的に貢献し、自己でアップロードしたものであり、このサイトは所有権を持ちません。また、人工的な編集は行われておらず、関連する法的責任も負いません。著作権侵害が疑われる内容がある場合は、以下のメールアドレスまでご連絡ください:notice#oldtoolbag.com(メールを送信する際、#を@に変更してください。届け出を行い、関連する証拠を提供してください。一旦確認がついたら、このサイトは侵害が疑われる内容をすぐに削除します。)

おすすめ