みなさんこんにちは! 今日は、Androidプラットフォーム上の周辺機器と経験を共有したいと考えています。
想像してみてください...
スキーのためにスキーレンタルに来て、カードで支払い、サービスと小切手の申し出を受ける必要があります。 それは簡単だと思われるでしょうか?
- 一度やってみます。 選択した機器(スキー、ポール、ブーツ、ヘルメット、マスク)。
- 従業員は巧妙にスマートフォンを取り出し、在庫のバーコードをスキャンします。
- 彼はすぐにプラスチック製のカードリーダーを取り出し、資金を引き出して預金を凍結します。
- そして、ベルトに取り付けられたプリンターで印刷された小切手とオファーがあります。
ああ、夢、夢...
現実には、すべてがはるかに長く、あなた自身がその理由を知っています。
1つの場所で在庫を選択し、レジに行きます。そこで、すべてのレンタルデスクの全員が集まって、そこで支払い、賃借人に戻り、在庫を受け取り、最終的に山に会う準備が整います。
そしてピーク時に、この物語は必然的に生き地獄に変わります。
- 借受人、選択されたインベントリへの長い待ち行列を守りました。
- 今、私たちはレジの一般的な列に並んでいます。
- その後、法的に支払われた賃借人に戻ります。 そして再び、ラインに立ち向かいましょう。 あなたが尋ねる(ピックアップ)する必要がありますか? 誰が気にします。
これが、サービスの速度が1分半から20分間持続した方法です。その時点で、誰かがすでに雪の斜面の朝のベルベットをスキーしています!
誰が責任を負い、何をすべきか?
すべてのチェックアウトカウンターをレンタルしてみませんか? はい、そのような問題は永続的ではないためです。 ピーク負荷は定期的に発生しますが、一般的にはそれほど頻繁ではありません-週末や休日の朝、そしてこれは天候が触媒的な場合のみです。 したがって、所有者の観点から金銭登録機器に投資することは明らかに優れたコストではありません。 この問題は、1回、2回、回線の解決を支援した追加のモバイル従業員の出現によって解決されます。
スキーの場合、スマートフォンとレジプリンターおよびカードリーダーを統合するための箱入りソリューションを購入するだけで十分です。 それらは、注文を配達する宅配業者、およびAeroexpressのチケットを販売する女の子によって使用されます。
金額を入力して支払いを受けることもできますが、 在庫のレンタルはありません!
私たちが協力した顧客のシステムでは、法律の書簡により、特定の金額の小切手のクライアントへの発行だけでなく、サービスの詳細な説明とそれに割り当てられた一意の番号を含む領収書の発行も要求されました。 つまり、支払いを行い、サーバーに登録し、一意のトランザクション番号を取得してから、この番号、サービスの完全な説明、エンコードされた情報を含むバーコードを表示する小切手を印刷する必要があります。
タスクが設定され、実装に渡されます。
実装
1.プリンターとカードリーダーを選択する
まず、ユーザーがサービスパラメータを構成してサーバーとやり取りできるようにするために、スマートフォンで複合体を使用する必要があると判断しました。 システム用のスマートフォンを選択する問題は、それ自体で決定されました。 顧客は「主力製品」であるAndroidスマートフォンを選択しました。 彼らはHuawei Honor 5Cであることが判明しました。 中国メーカーの便利で安価なデバイス。 主なことは、Bluetoothが機能していることです。 しかし、その後、問題をより困難に解決する必要がありました。 サービスの販売を伴うすべての業務が合法であるためには、財政登録機関が必要でした。 これは、販売操作の履歴を記録するメモリを備えたプリンタです。
モバイル会計プリンター(およびソリューションはモバイルでなければならないことを覚えています!)多くのロシア企業Atol、Incoteks、Accountmash、Shtrikh-Mによって製造されています。 提案を検討しましたが、提供されたサービスの詳細データを領収書に記載する必要があるため、ソリューションではプリンターを幅の広いリボン(2の代わりに3)に印刷する必要がありました。 州の登録に含まれるSHTRIH-MOBILE-PTKモバイルフィスカルプリンターのうち、幅の広いリボンが1つだけ見つかりました。
私たちは顧客からの現金支払いだけでなく、カードからお金を償却する必要があります。 したがって、支払いを行い、この方法で実行されたすべての資金を考慮に入れるには、カードリーダーとそのようなソリューションのプロバイダーが必要です。 そして、私たちの市場にはそのようなソリューションが十分にあります。 それらは、おそらく、読書のための読者のモデルの種類、獲得のための手数料の割合、および会計プリンターとの統合によって異なります! ここで、キーボード付きチップアンドピンカードリーダーを使用してiBox Proからソリューションを思い付き 、幸いにも、SHTRIH-MOBILE-PTKモバイル会計レジストラと統合しました。
同社はテストデバイスを提供してくれました。
2.お金を引き出す
iBox Pro支払いシステムを使用すると、モバイルアプリケーションを簡単に(インテントコールを介して)、複雑な方法で(SDKを介して)統合できます。 私たちは難しい道を選びましたが、困難を乗り越えるのが好きなので、まったく道を選びませんでした。 また、別の重要な理由があります。 ここでは余談が必要です。
インテントコールの場合、アルゴリズムは次のとおりです。
アルゴリズムは異なって見えます。 サービスの金額を受け取って、小切手を印刷することはできません。 サーバーにデータを送信し、サービスのコストを取得し、クライアントから支払いを受け取り、サーバーに連絡して一意のコードを取得し、このコードをチェックに反映する必要があります。
そのため、次のようなアルゴリズムを開発しました。
その結果、iBox SDK(進化しているSDKの最新バージョンはGitHUBからダウンロードできます)を使用して、モバイルアプリケーションにiBoxの呼び出しを統合しました。 ボーナスはより使いやすい単一のインターフェースでした-支払い段階では、ユーザーはサードパーティのiBoxインターフェースに切り替える必要がなく、すべてのプロセスはモバイルアプリケーションのフレームワーク内でのみ発生します。
// PaymentController- : // . PaymentController.getInstance().setSingleStepEMV(true); // PaymentController.getInstance().setCredentials(loginInfo.userName, loginInfo.userPassword); // , // . // PaymentCotroller-. ReaderBluetoothInfo readerBluetoothInfo = settingsService.getReaderBluetoothInfo(); List<BluetoothDevice> devices = PaymentController.getInstance().getBluetoothDevices(getView().getContext()); for (int i = 0; i < devices.size(); ++i) { if (devices.get(i).getAddress().equals(readerBluetoothInfo.readerAddres) && devices.get(i).getName().equals(readerBluetoothInfo.readerName)) { PaymentController.getInstance().setReaderType( getView().getContext(), PaymentController.ReaderType.WISEPAD, i, null); } } } ... PaymentDialog paymentDialog = new PaymentDialog(); // : // , ibox. , . PaymentController.getInstance().setPaymentControllerListener(paymentDialog); PaymentController.getInstance().enable(); // PaymentController.getInstance().startPayment(getContext(), mPaymentContext); ... // PaymentController . public void onReaderEvent(PaymentController.ReaderEvent event) { switch (event) { case CONNECTED : case START_INIT : lblState.setText(R.string.reader_state_init); break; case DISCONNECTED : stopProgress(); lblState.setText(R.string.reader_state_disconnected); break; case SWIPE_CARD : case TRANSACTION_STARTED : startProgress(); break; ... case EJECT_CARD : stopProgress(); lblState.setText(R.string.reader_state_eject); break; case BAD_SWIPE : Toast.makeText(mActivity, R.string.reader_bad_swipe, Toast.LENGTH_LONG).show(); break; case LOW_BATTERY : Toast.makeText(mActivity, R.string.reader_low_battery, Toast.LENGTH_LONG).show(); break; default : break; } }
3.文書を印刷する
売却の事実を修正した後、顧客に小切手と、場合によっては追加の文書(オファー契約、注文書、または保証書)を渡す必要があります。 「私たちは何に印刷しますか?」という質問-ユーザーがモバイルプリンターをベルトに掛けている場合、ユーザーに印刷させます。 そのため、プリンターに強制的に領収書以外の他の文書を印刷させました。
Shtrikh-Mの公式ライブラリを使用してプリンターを操作できます。これは、JPOSで作業するために作成したドキュメントと、愛好家の小さなサンプルライブラリを使用して作成できます。
注意、森をかき集めて!
モバイルプリンターでドキュメントを印刷するときに、マトリックスが失敗した場合に2つのケースが発生しました。
テストに使用した一部のスマートフォンとの組み合わせで、プリンターの速度は壊滅的に低下しました。 サービスの基準によると、顧客はサービスの登録から小切手の発行までの全プロセスを1.5分以内に維持する必要があるため、これは非常に心配でした。 幸いなことに、ターゲットデバイスはBluetooth経由で問題なく印刷されたため、この謎を未解決のままにすることにしました。
- 戦闘テストでは、まったく同じフィスカルプリンターの動作が異なりました。内部設定により、バーコードを印刷するときにドキュメントのバーコードを右に移動し、一部の情報を切り捨てました。 魔法の回避策を適用するだけで解決することができました:)-スキャナーによる読み取り品質を損なうことなく、チェックとバーコードのいくつかの要素を削減しました。
ShtrihFiscalPrinter printer = new ShtrihFiscalPrinter(new FiscalPrinter()); PrinterBarcode printerBarcode = new PrinterBarcode(); printerBarcode.setText(boardingPass.barcodeText); //, . printerBarcode.setLabel(""); // , . // - . . printerBarcode.setBarWidth(2); // 2 - small width printerBarcode.setType(PrinterBarcode.SM_BARCODE_PDF417); Map<EncodeHintType, Object> parameters = new HashMap<>(); // . // . parameters.put(EncodeHintType.PDF417_DIMENSIONS, new Dimensions(5, 5, 2, 60)); printerBarcode.addParameter(parameters); printer.printBarcode(printerBarcode);
- iBoxを使用しているときに、別の奇妙な問題が表面化しました。 スマートフォンで作業しているとき、デバイスはスリープモードになり、終了しませんでした。 Huaweiでのみ登場し、最新バージョンのカードリーダーファームウェアをインストールすることで解決しました。
4.会計小切手を印刷します
デフォルトでは、会計プリンターは最小限の情報で支払いシステムから小切手を発行します。 これは私たちに合わなかった。 最初に、他の顧客システムで承認されたチェックと同様に見える、美しくデザインされたチェックが必要でした。 第二に、チェックとサービスの受領およびサービスに関する詳細情報を組み合わせる必要がありました。 合計-プリンターSDKを使用して、美しいドキュメントの領収書を作成しました。 そして、テスト中に長時間、痛みを伴いながら、彼らは最終的に実際の紙がすべてのプリンターで同じように見えるようになるまで、パラメーターを変更しながら小切手を一つずつ印刷しました。
private void printTicket(PrinterInfo printerInfo, boolean isRefund, String agentId) throws Exception { ShtrihFiscalPrinter printer = new ShtrihFiscalPrinter(new FiscalPrinter()); // final String NO_TAX = "0"; final String TEN_PERCENT_TAX = "1000"; printer.setVatValue(1, NO_TAX); printer.setVatValue(2, TEN_PERCENT_TAX); // 10% printer.setVatValue(3, NO_TAX); printer.setVatValue(4, NO_TAX); printer.setVatTable(); printer.setHeaderLine(1, StringTools.appendStrings("", "*", LINE_LENGTH), false); printer.setHeaderLine(2, getHeader(" \" \""), false); printer.setHeaderLine(3, getHeader(" "), false); printer.setHeaderLine(4, getHeader(" , \n "), false); printer.setHeaderLine(5, getHeader("+7(XXX)XXX-XX-XX"), false); printer.setHeaderLine(6, StringTools.appendStrings("", "*", LINE_LENGTH), false); if (isRefund) { printer.setFiscalReceiptType(jpos.FiscalPrinterConst.FPTR_RT_REFUND); } else { printer.setFiscalReceiptType(jpos.FiscalPrinterConst.FPTR_RT_SALES); } printer.beginFiscalReceipt(true); printLine(); double priceSum = 0; //PrinterEmdData . for (PrinterEmdData printerEmdData : printerInfo.getPrinterEmdDatas()) { String description = getDescription(printerEmdData, printerInfo.isCashierFormat()); int tax = 0; final int TEN_PERCENT_NDS = 10; final int SECOND_TAX_SLOT = 2; if (printerEmdData.taxValue == TEN_PERCENT_TAX) { tax = SECOND_TAX_SLOT; // , 10% ( 2- ) } priceSum += printerEmdData.price; if (isRefund) { printer.printRecItemRefund(description, 0, 0, tax, (long) printerEmdData.price, ""); } else { printer.printRecItem(description, 0, 0, tax, (long) printerEmdData.price, ""); } } printLine(); if (printerInfo.isCard()) { printer.printRecTotal((long) priceSum, (long) priceSum, "1"); } else { long cashIn = (long) priceSum; if (printerInfo.getCashIn() > 0) { cashIn = (long) printerInfo.getCashIn(); } printer.printRecTotal((long) priceSum, cashIn, ""); } printer.endFiscalReceipt(true); }
5.システムの耐障害性を提供します
もちろん、システムに統合するだけでは十分ではなく、このシステムを信頼できるものにすることが重要です。 どの段階からでもロールバックするメカニズムを提供することが重要でした。 たとえば、支払いサービスがアプリケーションへの出金を確認し、アプリケーションがサービス予約サービスに一意のサービス番号を要求した後、サーバーへの接続が失われました。 そしてこの段階で、サーバーへのリクエストを繰り返すか、お金をカードに戻すことができるフォールバックメカニズムを作成する必要があります。
そのようなエラーには多くの選択肢がありました:お金を引き出すとき、彼らはカードを早く引き出し、PINコードを間違って入力しました、小切手を印刷しようとしたとき、レジが終了し、プリンターが使い果たされました。 各段階で必要なフォールトトレランスの境界は、経験豊富なレジ係が参加するテストセッション中に決定されました。 その結果、エラーごとに必要なフォールバックメカニズムが開発されました。
お金を受け取って小切手を印刷するプロセスで起こりうるエラー
合計:
- スマートフォン+カードリーダー+フィスカルプリンターのフェイルセーフ統合を行いました。
- 戦闘条件でテストし、すべてのフォールバックメカニズムを再度調整しました。
- ソリューションが実装され、機能し、アプリケーションユーザーとその顧客を満足させます。
サーバー側で各操作の厳密な記録を保持する必要がある場合でも、モバイルデバイスを使用して支払いを受け取る問題を解決できることを、独自の例で確認しました。 おそらく記事を読んだ後、誰かが列や他のエリアで時間を無駄にすることから人々を救う機会を見るでしょう。
あなたは私たちがそうであることが判明することができるより多くの快適さを顧客に与えます!