1. 程式人生 > >接入支付寶刷臉支付

接入支付寶刷臉支付

在接入之前先看下文件支付寶掃臉接入文件,

https://docs.open.alipay.com/20180402104715814204/intro

https://doc.open.alipay.com/docs/doc.htm?docType=1&articleId=108568

 

這裡一定要詳細瞭解官方提供的API,問下支付寶那邊的文件是不是最新的,避免一些不必要的坑.

 

接入
第一步:建立應用(後臺)
第二步:配置金鑰(後臺)
第三步:搭建和配置開發環境(後臺)
1.下載服務端SDK(後臺)
2.介面呼叫配置(後臺)
第四步:介面呼叫(前端)

這裡就不細說了, API上都有說明,大家看看就明白了

 

技術接入流程圖:

新增專案依賴:

第一個我用來請求資料,第二個我用來解析資料第三個是支付寶api那裡的下載

(這裡說一下,我專案之前用的是Rxjava,在對應的位置寫請求,報執行緒錯誤,在子執行緒也是報這個錯,所以就用async來請求,結果是可以)

 

在MerchantInfo配置自己需要的資料

看需求填寫自己的所需資料引數

看需求填寫自己的所需資料引數

 

在這個位置請求自己伺服器的刷臉介面

 

這裡自己寫的用android-async-http-master.jar請求資料用fastJson-1.1.45.jar解析

 

 

 

然後

//獲取zimId和zimInitClientData呼叫人臉初始化
String zimId = products.get(0).getZimId();
String zimInitClientData = products.get(0).getZimInitClientData();
smile(zimId, zimInitClientData);
Log.e("TAG", "zimid----------------"+zimId);
Log.e("TAG", "zimInitClientData----------------"+zimInitClientData);

 

/**
     * 發起刷臉支付請求.
     * @param zimId 刷臉付token,從服務端獲取,不要mock傳入
     * @param protocal 刷臉付協議,從服務端獲取,不要mock傳入
     */
    //. 喚起人臉識別
    private void smile(String zimId, String protocal) {
        Map params = new HashMap();
        params.put(KEY_INIT_RESP_NAME, protocal);

       //個詢問支付寶那邊的.我也不知道幹嘛用的
        /* start: 如果是預輸入手機號方案,請加入以下程式碼,填入會員繫結的手機號,必須與支付寶帳號對應的手機號一致 */
        params.put("phone_number", "1381XXXXX");
        /* end: --------------------------------------------- */
        zoloz.zolozVerify(zimId, params, new ZolozCallback() {
            @Override
            public void response(final Map smileToPayResponse) {
                if (smileToPayResponse == null) {
//                    promptText("2----------"+TXT_OTHER);
                    return;
                }
                String code = (String)smileToPayResponse.get("code");
                String fToken = (String)smileToPayResponse.get("ftoken");
                String subCode = (String)smileToPayResponse.get("subCode");
                String msg = (String)smileToPayResponse.get("msg");
                Log.e("TAG", "ftoken is:-----------" + fToken);
                Log.e("TAG", "code is:-----------" + code);
                Log.e("TAG", "subCode is:-----------" + subCode);
                Log.e("TAG", "msg is:-----------" + msg);

                //刷臉成功
                if (CODE_SUCCESS.equalsIgnoreCase(code) && fToken != null) {
                    //promptText("刷臉成功,返回ftoken為:" + fToken);
                    //這裡在Main執行緒,網路等耗時請求請放在非同步執行緒中
                    //後續這裡可以發起支付請求
                    //https://docs.open.alipay.com/api_1/alipay.trade.pay
                    //需要修改兩個引數
                    //scene固定為security_code
                    //auth_code為這裡獲取到的fToken值
                    //支付一分錢,支付需要在服務端發起,這裡只是模擬

                    sharedPreference = ISharedPreference.getInstance(getApplication());//獲取儲存的token
                    //聯網傳送資訊給伺服器(自己的伺服器)
                    String register = "http://test.shanghkj.com/api/merchant/SmTradePay";
                    //這裡是要傳送的引數
                    RequestParams params = new RequestParams();
                    params.put("token",sharedPreference.getToken());
                    params.put("remark",dataBinding.generalNote.getText().toString());//備註
                    params.put("code",fToken);//傳ftonen
                    params.put("total_amount",dataBinding.generalCount.getText().toString());//金額
                    params.put("desc","描述");
                    Log.e("TAG", "token------"+sharedPreference.getToken());
                    Log.e("TAG", "remark------"+dataBinding.generalNote.getText().toString());
                    Log.e("TAG", "fToken------"+fToken);
                    Log.e("TAG", "dataBinding.generalCount.getText().toString()------"+dataBinding.generalCount.getText().toString());
                    Log.e("TAG", "desc------");
                    client.post(register, params, new AsyncHttpResponseHandler(){
                        @Override
                        public void onSuccess(String content) {
                            Log.e("TAG", "content---第二步的成功-------------"+content);
                        }

                        @Override
                        public void onFailure(Throwable error, String content) {
                            Log.e("TAG", "content-------第二步的失敗---------"+content);
                        }
                    });
                }
            }

        });
    }

然後就對接到第三步了就完成簡單的支付了

因為涉及敏感欄位

第四步,第五步,建議在服務端實現




public class GeneralActivity extends BaseActivity<FragmentGeneralBinding> implements View.OnClickListener {

    private static final String TAG = GeneralActivity.class.getSimpleName();
    private static final int SCAN_CODE = 100;//掃碼requestCode
    private static final int SCAN_PAY_CODE = 101;//掃碼付款
    private static final int BANK_CODE = 102;//銀行卡收款  調起支付頁面
    private RxPermissions permissions;//許可權申請
    private BillViewModel model;
    private ProgressDialog dialog;
    private ProgressDialog bankDialog;
    private Intent bankIntent;
    private BankViewModel bankViewModel;



    //使用AsyncHttpClient,實現聯網的宣告
    public AsyncHttpClient client = new AsyncHttpClient();




    private boolean scanPay = false;//是否是掃碼收款
  public GeneralActivity(){}

    @Override
    protected Activity getChildActivity() {
        return this;
    }

    @Override
    protected int getLayoutId() {
        return R.layout.fragment_general;
    }


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//掃臉用的,要是不行就放在首頁開始初始化
        zoloz = com.alipay.zoloz.smile2pay.service.Zoloz.getInstance(getApplicationContext());
        //初始化印表機
        AidlUtil.getInstance().initPrinter();

        if (mImmersionBar != null)
            mImmersionBar.titleBar(dataBinding.norGatherToolbar).init();
        model = ViewModelProviders.of(this).get(BillViewModel.class);
        bankViewModel = ViewModelProviders.of(this).get(BankViewModel.class);
        permissions = new RxPermissions(this);

        //設定點選事件
        dataBinding.collectionList.setOnClickListener(this);
        dataBinding.norGatherToolbar.setNavigationOnClickListener(v -> {
            closeKeyBoard();
            onBackPressed();
        });

        dataBinding.collectionSearch.setOnClickListener(this);
        dataBinding.sweep.setOnClickListener(this);
        dataBinding.sweepReceive.setOnClickListener(this);
        dataBinding.bankCardReceive.setOnClickListener(this);
        dataBinding.fristDepositList.setOnClickListener(this);//押金收款
        
        
        
        
        dataBinding.generalCount.setFilters(new InputFilter[]{new AmountFilter()});
        showKeyBoard(dataBinding.generalCount);

        if (SystemUtil.getSystemModel().contains("P1")) {

            dataBinding.bankCardReceive.setVisibility(View.VISIBLE);
        } else {
            dataBinding.bankCardReceive.setVisibility(View.GONE);
        }
        //初始化引數  調起銀行卡相關支付
        initIntent();
        //snackbar
        model.snackbarText.observe(this, s -> {
            if (s != null) {
                if (s.contains("等待使用者支付超時") || s.contains("訂單未支付")) {
                    showDepositDely(s);
                } else {
                    Toast.makeText(this, s, Toast.LENGTH_SHORT).show();
                }
            }

        });
        //dialog
        model.dialogText.observe(this, s -> {
            if (s == null) {
                if (dialog != null) {
                    dialog.dismiss();
                }
            } else {
                dialog = ProgressDialog.show(this, "正在交易...", s, false);
            }
        });
        //snackbar
        bankViewModel.snackText.observe(this, s -> {
            if (s != null) {
                if (s.contains("等待使用者支付超時") || s.contains("訂單未支付")) {
                    showDepositDely(s);
                } else
                    Snackbar.make(dataBinding.generalNoteLay, s, Snackbar.LENGTH_SHORT).show();
            }

        });
        //dialog
        bankViewModel.dialogText.observe(this, s -> {
            if (s == null) {
                if (bankDialog != null) {
                    bankDialog.dismiss();
                }
            } else {
                bankDialog = ProgressDialog.show(this, "請稍等...", s, false);
            }
        });
    }

    //顯示支付超時dialog
    private void showDepositDely(String content) {

        ViewDialog dialog = new ViewDialog();
        dialog.setLayoutId(R.layout.deposit_dialog);
        dialog.showViewListener(view -> {
            TextView title = view.findViewById(R.id.accept_dialog_title);
            TextView ok = view.findViewById(R.id.ok);

            if (content.contains("等待使用者支付超時")) {
                String result = String.valueOf(Html.fromHtml(content));
                int start = result.indexOf("(");
                int end = result.indexOf(")");
                SpannableStringBuilder spannableString = new SpannableStringBuilder(result);
                spannableString.setSpan(new ForegroundColorSpan(Color.parseColor("#FE4655")),
                        start + 1, end, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);

                title.setText(spannableString);
            } else if (content.contains("訂單未支付")) {
                title.setText(content);
            }


            ok.setOnClickListener(v -> dialog.dismiss());
        });
        dialog.show(getSupportFragmentManager(), "0");
    }

    //顯示鍵盤
    private void showKeyBoard(EditText editText) {
        editText.setFocusable(true);
        editText.setFocusableInTouchMode(true);
        editText.requestFocus();
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                InputMethodManager imm =
                        (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                Objects.requireNonNull(imm).showSoftInput(editText, 0);
                editText.setSelection(editText.getText().length());
            }
        }, 200);
    }

    //關閉軟鍵盤
    private void closeKeyBoard() {

        InputMethodManager manager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        View view = getWindow().peekDecorView();
        if (view != null) {
            if (Objects.requireNonNull(manager).isActive()) {
                manager.hideSoftInputFromWindow(view.getWindowToken(), 0);
            }
        }

    }

    //抽取各個交易型別公共的欄位
    private void initIntent() {
        bankIntent = new Intent();
        bankIntent.setComponent(new ComponentName("com.shengpay.smartpos.shengpaysdk",
                "com.shengpay.smartpos.shengpaysdk.activity.MainActivity"));
        bankIntent.putExtra("appId", this.getPackageName());
    }

    //關閉軟鍵盤
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            closeKeyBoard();
        }
        return super.onKeyDown(keyCode, event);
    }

    //將交易金額統一處理成12位,不足12位的在前面補0
    private String getAmount(String amount) {
        if (TextUtils.isEmpty(amount)) return null;
        while (amount.length() < 12) {
            amount = "0" + amount;
        }
        return amount;
    }

    @Override
    public void onClick(View v) {
        Intent intent;
        switch (v.getId()) {
            //掃一掃查詢訂單
            case R.id.sweep:
                requestScanPermission(SCAN_CODE);
                break;
            case R.id.frist_deposit_list:
//                intent = new Intent(GeneralActivity.this, DepositActivity.class);
//                startActivity(intent);
//                finish();
                Log.e("TAG", "去往掃臉收銀");
                if (TextUtils.isEmpty(dataBinding.generalCount.getText().toString())) {
                    Snackbar.make(v, "請輸入收款金額!", Snackbar.LENGTH_SHORT).show();
                    return;
                }
                smilePay();
//                initFacePay();
                break;
            //收款列表
            case R.id.collection_list:
                intent = new Intent(GeneralActivity.this, GatherListActivity.class);
                startActivity(intent);
                break;

            //普通收款查詢
            case R.id.collection_search:

                intent = new Intent(GeneralActivity.this, SearchGaActivity.class);
                startActivity(intent);
                break;


            //掃碼收款
            case R.id.sweep_receive:

                if (TextUtils.isEmpty(dataBinding.generalCount.getText().toString())) {
                    Snackbar.make(v, "請輸入收款金額!", Snackbar.LENGTH_SHORT).show();
                    return;
                }
                requestScanPermission(SCAN_PAY_CODE);

                break;

            case R.id.bank_card_receive:
                if (TextUtils.isEmpty(dataBinding.generalCount.getText().toString())) {
                    Snackbar.make(v, "請輸入收款金額!", Snackbar.LENGTH_SHORT).show();
                    return;
                }
                if (!ClickUtil.isFasClick()) {
                    bankViewModel.createBankOrder(Double.parseDouble(dataBinding.generalCount.getText().toString()),
                            "pay", dataBinding.generalNote.getText().toString(),
                            0, "0", () -> {
//                            dialog.dismiss();
                                Log.e("TAG", "onClick: 建立普通收款訂單成功:");
                                startGather();
                            });
                }
                //建立普通銀行卡收款訂單
                break;
        }

    }

    /*----------------------------掃臉--------------------------------我是分割線--------------以下------------------掃臉---------------------------------------------------*/
    /**
     * 發起刷臉支付請求,先zolozGetMetaInfo獲取本地app資訊,然後呼叫服務端獲取刷臉付協議.
     */


    // 值為"1000"呼叫成功
    // 值為"1003"使用者選擇退出
    // 值為"1004"超時
    // 值為"1005"使用者選用其他支付方式
    static final String CODE_SUCCESS = "1000";
    static final String CODE_EXIT = "1003";
    static final String CODE_TIMEOUT = "1004";
    static final String CODE_OTHER_PAY = "1005";

    static final String TXT_EXIT = "已退出刷臉支付";
    static final String TXT_TIMEOUT = "操作超時";
    static final String TXT_OTHER_PAY = "已退出刷臉支付";
    static final String TXT_OTHER = "抱歉未支付成功,請重新支付";

    //刷臉支付相關
    static final String SMILEPAY_CODE_SUCCESS = "10000";
    static final String SMILEPAY_SUBCODE_LIMIT = "ACQ.PRODUCT_AMOUNT_LIMIT_ERROR";
    static final String SMILEPAY_SUBCODE_BALANCE_NOT_ENOUGH = "ACQ.BUYER_BALANCE_NOT_ENOUGH";
    static final String SMILEPAY_SUBCODE_BANKCARD_BALANCE_NOT_ENOUGH = "ACQ.BUYER_BANKCARD_BALANCE_NOT_ENOUGH";

    static final String SMILEPAY_TXT_LIMIT = "刷臉支付超出限額,請選用其他支付方式";
    static final String SMILEPAY_TXT_EBALANCE_NOT_ENOUGH = "賬戶餘額不足,支付失敗";
    static final String SMILEPAY_TXT_BANKCARD_BALANCE_NOT_ENOUGH = "賬戶餘額不足,支付失敗";
    static final String SMILEPAY_TXT_FAIL = "抱歉未支付成功,請重新支付";
    static final String SMILEPAY_TXT_SUCCESS = "刷臉支付成功";
    private Zoloz zoloz;
    private ISharedPreference sharedPreference;
    private List<FacePayBean.DataBean> products;

    private void smilePay() {
        zoloz.zolozGetMetaInfo(mockInfo(), new ZolozCallback() {
            // 解析zolozGetMetaInfo返回的結果,如果成功,則請求商戶服務端呼叫人臉初始化介面
            @Override
            public void response(Map smileToPayResponse) {
                if (smileToPayResponse == null) {
                    Log.e("TAG", "response is null");
//                    promptText("5----------"+TXT_OTHER);
                    return;
                }
                String code = (String)smileToPayResponse.get("code");
                String  metaInfo = (String)smileToPayResponse.get("metainfo");
                Log.e("TAG", "code----------------"+code);//1000值為"1000"呼叫成功
                Log.e("TAG", "metaInfo----------------"+metaInfo);
                //獲取metainfo成功
                if (CODE_SUCCESS.equalsIgnoreCase(code) && metaInfo != null) {
//                    2. 刷臉初始化
                    //這裡用Rxjava 聯網請求報執行緒錯誤
                    //然後找了兩個個jar包android-async-http-master.jar和fastJson-1.1.45.jar
                    //android-async-http-master.jar請求資料用fastJson-1.1.45.jar解析
                    Log.e("TAG", "-------獲取metainfo成功並開始初始化人臉----"+metaInfo);
                    sharedPreference = ISharedPreference.getInstance(getApplication());//獲取儲存的token
                    //聯網傳送資訊給伺服器(自己的伺服器)
                    String register = "http://test.shanghkj.com/api/merchant/smilepayInit";
                    //這裡是要傳送的引數
                    RequestParams params = new RequestParams();
                    params.put("token",sharedPreference.getToken());
                    params.put("all",metaInfo);
                    //開始聯網請求
                    client.post(register,params ,new AsyncHttpResponseHandler(){
                        //成功
                        @Override
                        public void onSuccess(String content) {
                            Log.e("TAG", "woyao chenggh 安居客符號化---------"+content);
                            //這裡去解析資料content
                            JSONObject jsonObject = JSON.parseObject(content);
                            String proInfo = jsonObject.getString("data");
                            products = JSON.parseArray(proInfo, FacePayBean.DataBean.class);
                            Log.e("TAG", "product------getZimInitClientData---------"+products.get(0).getZimInitClientData());
                            Log.e("TAG", "product-----getZimId----------"+products.get(0).getZimId());
                            Log.e("TAG", "product-------getMsg--------"+products.get(0).getMsg());
                            Log.e("TAG", "product--------getType-------"+products.get(0).getType());
                            Log.e("TAG", "product-------getStore_name--------"+products.get(0).getStore_name());


                            //獲取zimId和zimInitClientData呼叫人臉初始化
                            String zimId = products.get(0).getZimId();
                            String zimInitClientData = products.get(0).getZimInitClientData();
                            smile(zimId, zimInitClientData);//喚起人臉識別
                            Log.e("TAG", "zimid----------------"+zimId);
                            Log.e("TAG", "zimInitClientData----------------"+zimInitClientData);

                            //這個我也不知道幹嘛的,好像不能註釋
                            UIUtils.getHandler().postDelayed(new Runnable() {
                                @Override
                                public void run() {
//                                    removeCurrentActivity();//銷燬當前的activity
                                }
                            },2000);
                        }
                        @Override
                        public void onFailure(Throwable error, String content) {
                            Toast.makeText(GeneralActivity.this, "網路異常,呼叫失敗!", Toast.LENGTH_SHORT).show();

                        }
                    } );
                }
          }
       });
    }
    public static final String KEY_INIT_RESP_NAME = "zim.init.resp";
    /**
     * 發起刷臉支付請求.
     * @param zimId 刷臉付token,從服務端獲取,不要mock傳入
     * @param protocal 刷臉付協議,從服務端獲取,不要mock傳入
     */
    //. 喚起人臉識別
    private void smile(String zimId, String protocal) {
        Map params = new HashMap();
        params.put(KEY_INIT_RESP_NAME, protocal);
        Log.e("TAG", "protocal----protocal---protocal---"+protocal);
        Log.e("TAG", "zimId----zimId---zimId---"+zimId);
       //個詢問支付寶那邊的.我也不知道幹嘛用的
        /* start: 如果是預輸入手機號方案,請加入以下程式碼,填入會員繫結的手機號,必須與支付寶帳號對應的手機號一致 */
//        這句程式碼就是掃臉之後會有一個使用者輸入手機號的頁面,您要是寫這一行,就不需要使用者去手動輸入,會直接把使用者手機號顯示在頁面,
// 不寫的話需要使用者手動去輸入
//        params.put("phone_number", "1381XXXXX");
        /* end: --------------------------------------------- */
        zoloz.zolozVerify(zimId, params, new ZolozCallback() {
            @Override
            public void response(final Map smileToPayResponse) {
                if (smileToPayResponse == null) {
//                    promptText("2----------"+TXT_OTHER);
                    Toast.makeText(GeneralActivity.this, TXT_OTHER, Toast.LENGTH_SHORT).show();
                    return;
                }
                String code = (String)smileToPayResponse.get("code");
                String fToken = (String)smileToPayResponse.get("ftoken");
                String subCode = (String)smileToPayResponse.get("subCode");
                String msg = (String)smileToPayResponse.get("msg");
                Log.e("TAG", "ftoken is:-----------" + fToken);
                Log.e("TAG", "code is:-----------" + code);
                Log.e("TAG", "subCode is:-----------" + subCode);
                Log.e("TAG", "msg is:-----------" + msg);

                //刷臉成功
                if (CODE_SUCCESS.equalsIgnoreCase(code) && fToken != null) {
                    //promptText("刷臉成功,返回ftoken為:" + fToken);
                    //這裡在Main執行緒,網路等耗時請求請放在非同步執行緒中
                    //後續這裡可以發起支付請求
                    //https://docs.open.alipay.com/api_1/alipay.trade.pay
                    //需要修改兩個引數
                    //scene固定為security_code
                    //auth_code為這裡獲取到的fToken值
                    //支付一分錢,支付需要在服務端發起,這裡只是模擬

                    sharedPreference = ISharedPreference.getInstance(getApplication());//獲取儲存的token
                    //聯網傳送資訊給伺服器(自己的伺服器)
                    String register = "http://test.shanghkj.com/api/merchant/SmTradePay";
                    //這裡是要傳送的引數
                    RequestParams params = new RequestParams();
                    params.put("token",sharedPreference.getToken());
                    params.put("remark",dataBinding.generalNote.getText().toString());//備註
                    params.put("code",fToken);//傳ftonen
                    params.put("total_amount",dataBinding.generalCount.getText().toString());//金額
                    params.put("desc","描述");
                    Log.e("TAG", "token------"+sharedPreference.getToken());
                    Log.e("TAG", "remark------"+dataBinding.generalNote.getText().toString());
                    Log.e("TAG", "fToken------"+fToken);
                    Log.e("TAG", "dataBinding.generalCount.getText().toString()------"+dataBinding.generalCount.getText().toString());
                    Log.e("TAG", "desc------");
                    client.post(register, params, new AsyncHttpResponseHandler(){
                        @Override
                        public void onSuccess(String content) {
                            Log.e("TAG", "content---第二步的成功-------------"+content);


                            ScanPayBean scanPayBean = model.scanPay.get();
                            if (scanPayBean != null) {
                                print(scanPayBean);
                                String contentSm = "掃臉收款成功  ¥" + dataBinding.generalCount.getText().toString() + " " + getCurrentTime();
                                //顯示列印dialog
                                showPrintDialog(scanPayBean);
                                model.startGt(ISharedPreference.getInstance(getApplication()).getCid(), "尚瀚支付推送提醒", contentSm, () -> {

                                });
                            }
                        }

                        @Override
                        public void onFailure(Throwable error, String content) {
                            Log.e("TAG", "content-------第二步的失敗---------"+content);
                        }
                    });
                }
            }

        });
    }
 /*----------------------------掃臉--------------------------------我是分割線----------以上----------------------掃臉---------------------------------------------------*/

    private void startGather() {
        if (bankViewModel.bankBean != null) {
            //獲取訂單成功後
            BankBean.DataBean bean = bankViewModel.bankBean.get();
            if (bean != null) {
                String str = bean.getAmount();
                double du = Double.valueOf(str) * 100;
                int result = (int) du;
                Log.d(TAG, "getInfo: 最後金額結果:" + result);
                bankIntent.putExtra("barcodeType", "0");//指定為銀行卡消費
                bankIntent.putExtra("amount", getAmount(String.valueOf(result)));//交易金額
                bankIntent.putExtra("orderNoSFT", bean.getOut_trade_no());//交易訂單號
                bankIntent.putExtra("transName", "0");//交易訂單號


                //使用者聯備註
                bankIntent.putExtra("printMerchantInfo",
                        "交易訂單號:" + bean.getOut_trade_no() + "        "
                                + "\n交易備註: " + "銀行卡押金收款");
                bankIntent.putExtra("printMerchantInfo2", bean.getOut_trade_no());
                bankIntent.putExtra("priInfo", "交易訂單號:" + bean.getOut_trade_no() + "        "
                        + "\n交易備註: " + "銀行卡押金收款");
                bankIntent.putExtra("priInfo2", bean.getOut_trade_no());
                //判斷是否安裝盛付通支付
                if (isInstallShengfuPay()) {
                    startActivityForResult(bankIntent, BANK_CODE);
                } else {
                    Toast.makeText(this, "請前往應用市場下載盛付通支付!", Toast.LENGTH_SHORT).show();
                }
            }
        }
    }

    //判斷是否安裝盛付通支付sdk
    private boolean isInstallShengfuPay() {
        PackageManager packageManager = getPackageManager();
        List<PackageInfo> list = packageManager.getInstalledPackages(0);
        for (int i = 0; i < list.size(); i++) {
            if (SystemUtil.getSystemModel().equals("P1") || SystemUtil.getSystemModel().equals("P1_4G")) {
                if (list.get(i).packageName.equalsIgnoreCase("sunmi.fw2.payment.shengpay") ||
                        list.get(i).packageName.equalsIgnoreCase("sunmimi.payment.shengpay")) {

                    return true;
                }
            }
            Log.d(TAG, "isInstallShengfuPay: 包名:" + list.get(i).packageName);
        }
        return false;
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        //處理二維碼掃描結果
        if (requestCode == SCAN_CODE && data != null) {
            Bundle bundle = data.getExtras();
            if (bundle == null) return;

            dealWithScanResult(bundle);
        }

        //當為掃碼付款時
        if (requestCode == SCAN_PAY_CODE && data != null) {
            Bundle bundle = data.getExtras();
            scanPay(bundle);
        }
        //這裡處理銀行卡收款  相關  交易成功 交易失敗  進行回撥
        if (requestCode == BANK_CODE && data != null) {
            Bundle extras1 = data.getExtras();

            bankPay(resultCode, extras1, data);

        }
    }


    /**
     * 處理二位掃描結果  查詢訂單
     *
     * @param bundle bundle
     */
    private void dealWithScanResult(Bundle bundle) {
        if (bundle.getInt(CodeUtils.RESULT_TYPE) == CodeUtils.RESULT_SUCCESS) {
            String result = bundle.getString(CodeUtils.RESULT_STRING);
            if (result == null) {
                return;
            }
            boolean strHead = result.contains("fu");
            Log.e("TAG", "onActivityResult: 小票擡頭是fu開頭:" + strHead + "結果:" + result);
            if (result.startsWith("fu")) {//當時預授權訂單時

                Intent intent = new Intent(GeneralActivity.this, AutTncActivity.class);
                intent.putExtra("orderId", result);
                startActivity(intent);

            } else {//否則是收款訂單  或者分期訂單   預授權結算後直接變成普通訂單

                Intent intent = new Intent(GeneralActivity.this, CollAndInstallDetailActivity.class);
                intent.putExtra("orderId", result);
                startActivity(intent);
            }

        } else if (bundle.getInt(CodeUtils.RESULT_TYPE) == CodeUtils.RESULT_FAILED)

        {
            Toast.makeText(GeneralActivity.this, "解析二維碼失敗", Toast.LENGTH_LONG).show();
        }

    }

    //掃描二維碼收款
    private void scanPay(Bundle bundle) {
        if (bundle == null) return;
        if (bundle.getInt(CodeUtils.RESULT_TYPE) == CodeUtils.RESULT_SUCCESS) {
            String result = bundle.getString(CodeUtils.RESULT_STRING);

            if (result == null) {
                return;
            }
            //改變狀態
            scanPay = true;
            //提交二維碼掃描生成訂單
            model.scanPay(dataBinding.generalNote.getText().toString(), result,
                    dataBinding.generalCount.getText().toString(), null, () -> {
                        dialog.dismiss();
                        //生成訂單後 結束顯示dialog
                        ScanPayBean scanPayBean = model.scanPay.get();
                        //支付成功後列印
                        if (scanPayBean != null) {
                            print(scanPayBean);
                            String content = "普通收款成功  ¥" + dataBinding.generalCount.getText().toString() + " " + getCurrentTime();
                            //顯示列印dialog
                            showPrintDialog(scanPayBean);
                            model.startGt(ISharedPreference.getInstance(getApplication()).getCid(), "尚瀚支付推送提醒", content, () -> {

                            });
                        }
                    });

            Log.d(TAG, "onActivityResult: 解析結果:" + result);

        } else if (bundle.getInt(CodeUtils.RESULT_TYPE) == CodeUtils.RESULT_FAILED) {
            Toast.makeText(GeneralActivity.this, "解析二維碼失敗", Toast.LENGTH_LONG).show();
        }
    }

    //顯示列印dialog
    private void showPrintDialog(ScanPayBean scanPayBean) {
        ViewDialog viewDialog = new ViewDialog();
        viewDialog.setLayoutId(R.layout.print_dialog);
        viewDialog.showViewListener(view -> {
            TextView title = view.findViewById(R.id.cancel_dialog_title);
            title.setText("收款成功,是否列印小票?");
            TextView print = view.findViewById(R.id.cancel_yes);
            TextView cancel = view.findViewById(R.id.cancel_no);
            print.setOnClickListener(v -> {
                reprint(scanPayBean);
            });
            cancel.setOnClickListener(v -> {
                viewDialog.dismiss();
             //跳轉到收款詳情
                Intent intent = new Intent(GeneralActivity.this, CollAndInstallDetailActivity.class);
                intent.putExtra("orderId", scanPayBean.getOut_trade_no());
                intent.putExtra("needPrint", false);
                startActivity(intent);
            });
        });
        viewDialog.show(getSupportFragmentManager(), "0");
    }



    //列印
    private void print(ScanPayBean scanPayBean) {
        if (scanPayBean == null) {
            return;
        }

        List<String> printContent = Objects.requireNonNull(scanPayBean).getPrint_array();

        String bitmapType = printContent.get(0);
        AidlUtil aidlUtil = AidlUtil.getInstance();
        aidlUtil.enterPrinterBuffer(true);
        int resId = 0;
        switch (bitmapType) {
            //支付寶支付
            case "0":
                resId = R.drawable.print_alipay;
                break;
            //微信支付
            case "1":
                resId = R.drawable.print_wx;
                break;
            //銀行卡支付
            case "2":
                resId = R.drawable.print_unicon;

                break;
        }
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), resId);
        //列印支付方式圖示
        aidlUtil.printBitmap(bitmap, "2", "2");
        aidlUtil.printText(printContent.get(12),
                "24", "24", "1", false, false);
//        aidlUtil.printText("交易憑證重複列印",
//                "24", "24", "1", false, false);
        aidlUtil.printBlankLine("1", "10");
        //擡頭
        aidlUtil.printText(printContent.get(1), "32", "32", "1",
                true, false);
        aidlUtil.printBlankLine("1", "10");
        //門店
        aidlUtil.printText(printContent.get(2), "24", "24", "1",
                false, false);
        aidlUtil.printBlankLine("1", "10");
        //訂單支付方式text開始
        aidlUtil.printText(printContent.get(3).replace("\\n", "\n"),
                "24", "24", "0",
                false, false);
        //業務記錄
        aidlUtil.printText(printContent.get(4), "32", "32", "0",
                true, false);
        //業務記錄內容
        aidlUtil.printText("\n" + printContent.get(5)
                        .replace("\\n", "\n"), "24", "24", "0",
                false, false);

        //退款 ||收款
        aidlUtil.printText("\n" + printContent.get(6), "32", "32", "0",
                true, false);
        //退款獲取收款內容
        aidlUtil.printText("\n" + printContent.get(7)
                        .replace("\\n", "\n"), "24", "24", "0",
                false, false);
        aidlUtil.printBlankLine("1", "10");
        //列印二維碼
        aidlUtil.printQr(printContent.get(8), "8", "3");
        //收銀員   //列印時間
        aidlUtil.printText(printContent.get(9).replace("\\n", "\n"),
                "24", "24", "0", false, false);
        aidlUtil.printBlankLine("1", "10");
        aidlUtil.printText(printContent.get(10).replace("\\n", "\n"),
                "24", "24", "1", false, false);

        aidlUtil.printText("\n" + printContent.get(11).replace("\\n", "\n"),
                "24", "24", "1", false, false);

        aidlUtil.printBlankLine("5", "30");



        aidlUtil.printCommit();
    }
    //列印
    private void reprint(ScanPayBean scanPayBean) {
        if (scanPayBean == null) {
            return;
        }

        List<String> printContent = Objects.requireNonNull(scanPayBean).getPrint_array();

        String bitmapType = printContent.get(0);
        AidlUtil aidlUtil = AidlUtil.getInstance();
        aidlUtil.enterPrinterBuffer(true);
        int resId = 0;
        switch (bitmapType) {
            //支付寶支付
            case "0":
                resId = R.drawable.print_alipay;
                break;
            //微信支付
            case "1":
                resId = R.drawable.print_wx;
                break;
            //銀行卡支付
            case "2":
                resId = R.drawable.print_unicon;

                break;
        }
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), resId);
        //列印支付方式圖示
        aidlUtil.printBitmap(bitmap, "2", "2");
//        aidlUtil.printText(printContent.get(12),
//                "24", "24", "1", false, false);
        aidlUtil.printText("交易憑證重複列印",
                "24", "24", "1", false, false);
        aidlUtil.printBlankLine("2", "10");
        //擡頭
        aidlUtil.printText(printContent.get(1), "32", "32", "1",
                true, false);
        aidlUtil.printBlankLine("1", "10");
        //門店
        aidlUtil.printText(printContent.get(2), "24", "24", "1",
                false, false);
        aidlUtil.printBlankLine("1", "10");
        //訂單支付方式text開始
        aidlUtil.printText(printContent.get(3).replace("\\n", "\n"),
                "24", "24", "0",
                false, false);
        //業務記錄
        aidlUtil.printText(printContent.get(4), "32", "32", "0",
                true, false);
        //業務記錄內容
        aidlUtil.printText("\n" + printContent.get(5)
                        .replace("\\n", "\n"), "24", "24", "0",
                false, false);

        //退款 ||收款
        aidlUtil.printText("\n" + printContent.get(6), "32", "32", "0",
                true, false);
        //退款獲取收款內容
        aidlUtil.printText("\n" + printContent.get(7)
                        .replace("\\n", "\n"), "24", "24", "0",
                false, false);
        aidlUtil.printBlankLine("1", "10");
        //列印二維碼
        aidlUtil.printQr(printContent.get(8), "8", "3");
        //收銀員   //列印時間
        aidlUtil.printText(printContent.get(9).replace("\\n", "\n"),
                "24", "24", "0", false, false);
        aidlUtil.printBlankLine("1", "10");
        aidlUtil.printText(printContent.get(10).replace("\\n", "\n"),
                "24", "24", "1", false, false);

        aidlUtil.printText("\n" + printContent.get(11).replace("\\n", "\n"),
                "24", "24", "1", false, false);

        aidlUtil.printBlankLine("5", "30");



        aidlUtil.printCommit();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        InputMethodManager imm = (InputMethodManager)
                getSystemService(Context.INPUT_METHOD_SERVICE);
        if (imm != null && imm.isActive()) {
            imm.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), 0);
            return true;
        } else {
            return super.onTouchEvent(event);


        }
    }

    //獲取當前時間
    private String getCurrentTime() {
        SimpleDateFormat simpleDateFormat = (SimpleDateFormat) SimpleDateFormat.getDateInstance();
        simpleDateFormat.applyPattern("MM-dd HH:mm:SS");

        return simpleDateFormat.format(new Date());
    }

    //處理銀行卡收款相關
    private void bankPay(int resultCode, Bundle extras1, Intent data) {
        boolean success = false;//是否交易成功
        if (extras1 == null) {
            return;
        }
        String payResult = null;//交易結果
        Set<String> keySet = extras1.keySet();
        switch (resultCode) {
            case Activity.RESULT_OK:
                Toast.makeText(GeneralActivity.this, "交易成功", Toast.LENGTH_SHORT).show();
                success = true;

                StringBuilder resultBuilder = new StringBuilder();
                for (String s : keySet) {
                    String str = s + ":" + extras1.getString(s) + ",";
                    resultBuilder.append(str);

                }
                Log.e("TAG" , "onActivityResult: 支付結果:" + resultBuilder.toString());
                payResult = resultBuilder.toString();
                //推送交易結果
                String content = "銀行卡普通收款成功  ¥" + dataBinding.generalCount.getText().toString() + " " + getCurrentTime();
                model.startGt(ISharedPreference.getInstance(getApplication()).getCid(), "尚瀚支付推送提醒", content, () -> {

                });
                break;
            case Activity.RESULT_CANCELED:
                success = false;
                String reason = data.getStringExtra("reason");
                Toast.makeText(GeneralActivity.this, reason, Toast.LENGTH_SHORT).show();

                StringBuilder failBuilder = new StringBuilder();
                for (String s : keySet) {
                    String str = s + ":" + extras1.getString(s) + ",";
                    failBuilder.append(str);

                }
                payResult = failBuilder.toString();
                break;

        }
        Log.e("TAG", "onActivityResult:payResult :普通收款交易資訊:=============" + payResult);

        //上傳交易結果


        //回撥上傳交易結果
        boolean finalSuccess = success;
        bankViewModel.uploadTradeInfo(payResult, () -> {
            if (finalSuccess) {//如果交易成功再跳轉
                Intent intent = new Intent(GeneralActivity.this, CollAndInstallDetailActivity.class);
                intent.putExtra("orderId", bankViewModel.bankBean.get().getOut_trade_no());
                intent.putExtra("needPrint", true);
                startActivity(intent);

            }
            Log.d(TAG, "bankPay: 上傳交易資訊成功!");
        });

    }

    /**
     * 申請二維碼掃描需要的許可權
     */
    @SuppressLint("CheckResult")
    private void requestScanPermission(int code) {
        permissions.requestEach(Manifest.permission.CAMERA).subscribe(permission -> {

            if (permission.granted) {
                scanCode(code);
            } else if (permission.shouldShowRequestPermissionRationale) {
                Toast.makeText(GeneralActivity.this, "掃描二維碼需要相機許可權!", Toast.LENGTH_SHORT).show();

            } else {
                Uri packageURI = Uri.parse("package:" + GeneralActivity.this.getPackageName());
                Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, packageURI);
                startActivity(intent);

            }
        });


    }

    //開始掃描二維碼
    private void scanCode(int code) {
        Intent scanIntent = new Intent(GeneralActivity.this, ScanActivity.class);
        startActivityForResult(scanIntent, code);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        zoloz.zolozUninstall();
        if (dialog != null) {
            dialog.dismiss();
        }
    }
}