免SDK實現微信/支付寶轉賬打賞功能

常興E站發表於2019-03-04

安卓開發者都應該有一個屬於自己的APP釋出到市場,可以完善自己的技術站之外,加入廣告,還可以有一份小收入。

但是這個年代,各家的應用市場是不歡迎帶廣告sdk的個人開發者應用的。還好我們可以用外掛技術加入廣告sdk,或者直接想一種方面實現打賞功能,讓使用者通過支付寶或微信轉賬到自己賬戶。

免sdk實現 微信/支付寶 轉賬打賞功能

安卓個人開發者如果如果想著App裡實現支付打賞功能,嵌入sdk不說成本大外,基本是過不了市場稽核的。那麼我們可以利用有限資源,封裝元件實現一個mini型的打賞功能。

一、支付寶轉賬分析

支付寶的轉賬和支付功能,都可以通過二維碼開啟相關的支付頁面,並且用瀏覽器掃一掃後也是可以正常呼起正常支付頁面的。那麼我們簡單分析下,支付寶的二維碼整個跳轉肯定不需要相關整合sdk的,那麼到底什麼樣的資料格式可以做到的?

在支付寶個人資訊頁,找到 我的二維碼,截圖自己的支付寶二維碼,識別下,得到以下資訊:

qa

二維碼線上解析網址移步

可以看到支付寶的支付二維碼就是一個普通的http url, 然後它主要資訊就存在字尾字元: apafm3kp91df7yo517 裡。

https://qr.alipay.com/apafm3kp91df7yo517

網上查詢後,發現果然可以通過scheme去開啟支付寶轉賬頁面。參考

ali

於是馬上動手實現,驗證scheme方式是有效的。剩下的就是怎麼封裝下方面呼叫。

二、微信轉賬分析

有了支付寶的轉賬經驗,我們同樣從二維碼資訊入手,發現微信隨著版本更新,會有很多驗證,直接用scheme調微信,會開啟微信的一個空白網頁。

分析

然後研究裡下微信支付sdk,發現在介面呼叫的時間需要商戶id,及appsecret等資訊驗證,這就意味這我們單純的沒有任何身份資訊去調起微信支付是不可能的。
那麼我們退而求其次,用引導方式幫使用者直接開啟微信掃一掃頁面,文案引導使用者從相簿開啟二維碼,然後支付。

下一步,就是找到開啟微信掃一掃的方法。

    private void toWeChatScan() {
        try {
            //利用Intent開啟微信
            Uri uri = Uri.parse("weixin://dl/scan");
            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
            startActivity(intent);
        } catch (Exception e) {
            //若無法正常跳轉,在此進行錯誤處理
            Toast.makeText(DinpayWeChatActivity.this, "無法跳轉到微信,請檢查您是否安裝了微信!", Toast.LENGTH_SHORT).show();
        }
    }
複製程式碼

以上是網上推薦的方法,那麼很不幸的是,這種方法估計在很早之前版本可以,但是現在這種方法是無效的

那麼是不是高版本就沒有方法裡呢?繼續google,發現以下方法是可行的:

  /*package*/ static void startWechatScan(Context c) {
        Intent intent = new Intent();
        intent.setComponent(new ComponentName("com.tencent.mm", "com.tencent.mm.ui.LauncherUI"));
        intent.putExtra("LauncherUI.From.Scaner.Shortcut", true);
        intent.setFlags(335544320);
        intent.setAction("android.intent.action.VIEW");
    
        if (MiniPayUtils.isActivityAvailable(c, intent)) {
            c.startActivity(intent);
        } else {
            Toast.makeText(c, "未安裝微信~", Toast.LENGTH_SHORT).show();
        }
    }
複製程式碼

二維碼微信相簿儲存

實現微信掃一掃跳轉後,使用者在從相簿選擇二維碼時,怎麼樣才能一眼選出我們的目標轉賬二維碼呢?

觀察發現微信的二維碼選擇相簿是按照時間順序排序,那麼只要我們的圖片生成時間最新就可以排在第一位,每次新生成截圖儲存即可。

相關圖片生成及相簿儲存邏輯如下:

    /*package*/
    static void startWeZhi(Context c, View view) {
        File dir = c.getExternalFilesDir("pay_img");
        if (dir != null &&
                !dir.exists() && !dir.mkdirs()) {
            return;
        } else {
            File[] f = dir.listFiles();
            for (File file : f) {
                file.delete();//刪除舊截圖,每次用新截圖,保證相簿排序。
            }
        }

        String fileName = System.currentTimeMillis() + "weixin_qa.png";
        File file = new File(dir, fileName);
        if (!file.exists()) {
            file.delete();
        }

        snapShot(c, file, view);
        startWechat(c);
    }

	/**
	  * 截圖儲存邏輯
	  */
    private static void snapShot(Context context, @NonNull File file, @NonNull View view) {
        Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas();
        canvas.setBitmap(bitmap);
        view.draw(canvas);

        FileOutputStream fos = null;
        boolean isSuccess = false;
        try {
            fos = new FileOutputStream(file);
            //通過io流的方式來壓縮儲存圖片
            isSuccess = bitmap.compress(Bitmap.CompressFormat.PNG, 80, fos);
            fos.flush();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            MiniPayUtils.closeIO(fos);
        }
        if (isSuccess) {
            ContentResolver contentResolver = context.getContentResolver();
            ContentValues values = new ContentValues(4);
            values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis());
            values.put(MediaStore.Images.Media.MIME_TYPE, "image/png");
            values.put(MediaStore.Images.Media.ORIENTATION, 0);
            values.put(MediaStore.Images.Media.TITLE, "捐贈");
            values.put(MediaStore.Images.Media.DESCRIPTION, "捐贈二維碼");
            values.put(MediaStore.Images.Media.DATA, file.getAbsolutePath());
            values.put(MediaStore.Images.Media.DATE_MODIFIED,System.currentTimeMillis()/1000);
            Uri url = null;

            try {
                url = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); //其實質是返回 Image.Meida.DATA中圖片路徑path的轉變而成的uri
                OutputStream imageOut = contentResolver.openOutputStream(url);
                try {
                    bitmap.compress(Bitmap.CompressFormat.PNG, 100, imageOut);
                } finally {
                    MiniPayUtils.closeIO(imageOut);
                }

                long id = ContentUris.parseId(url);
                MediaStore.Images.Thumbnails.getThumbnail(contentResolver, id, MediaStore.Images.Thumbnails.MINI_KIND, null);//獲取縮圖

            } catch (Exception e) {
                if (url != null) {
                    contentResolver.delete(url, null, null);
                }
            }
        }
    }
複製程式碼

這裡涉及到螢幕截圖儲存邏輯,需要指定截圖範圍,儲存後,還需要通知系統媒體資料庫(微信圖片的獲取應該是讀取的系統媒體庫),保證資料更新。

wechat

三、封裝sdk

既然可以實現免sdk的支付打賞功能,那麼我們把這個功能封裝成一個sdk,方便專案的植入。

那麼本者 方便引入、簡單使用,體驗好等原則,實現了MiniPay開源專案

專案把微信和支付寶整合了一個支付頁面,點選背景可切換打賞途徑。

wechat
ali

只要一行程式碼即可引入自己專案

     compile `com.canking.minipay:minipay:1.0.x`
複製程式碼

只要一行即個啟動MiniPay打賞元件

     MiniPayUtils.setupPay(this, config);
複製程式碼

程式碼完全開放,原始碼傳送門,可以完全自定意邏輯。

Get it on Google Play

歡迎轉載,請標明出處:常興E站 canking.win

相關文章