区长的专栏

业精于勤,荒于嬉;行成于思,毁于随!

Android 个人开发者接入支付功能

如果是公司的产品,那么也就不存在问题了,Ping++对所有支付做了一个集成。如果开发者个人想接入支付系统,这个申请过程几乎是不大可能的。而Bmob为广大开发人员提供的统一、正规的收费手段,让没有企业认证的个人开发者,也能通过支付宝和微信向用户收费。但是有一个缺点,支持的渠道少,只支持支付宝和微信。此外,微信支付还要安装一个插件,用户体验及其不好。

官方的文档在这里Android支付SDK

接入Bomb也很简单,首先下载BmobPay_Sdk_V1.0.2a.zip

将Lib中的四个jar文件拷到项目中的libs目录下,将plugin目录中的assets拷到项目的main目录下。如图

这里写图片描述

声明权限

    <!-- alipay sdk permission begin -->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <!-- alipay sdk permission end -->

由于微信支付需要安装它的插件,所以如果在root的设备上我们希望能够静默安装,否则使用正常的安装方式,静默安装需要一个权限。

    <uses-permission android:name="android.permission.INSTALL_PACKAGES" />

在AndroidManifest.xml的Application标签下添加以下内容,声明组件

 <!-- bmob pay sdk activity begin ,please put below code into application tag -->
        <activity
            android:name="com.alipay.sdk.app.H5PayActivity"
            android:configChanges="orientation|keyboardHidden|navigation"
            android:exported="false"
            android:screenOrientation="behind"
            android:windowSoftInputMode="adjustResize|stateHidden" >
        </activity>

        <activity
            android:name="com.bmob.pay.tool.PayActivity"
            android:screenOrientation="portrait"
            android:theme="@android:style/Theme.Translucent" />
        <!-- bmob pay sdk activity end -->

在您的应用程序主Activity的onCreate中调用如下方法:(Application ID在后台应用管理的 数据浏览->应用信息->应用密钥->Application ID)

private BmobPay bmobPay = null;
BmobPay.init(context,"你的Application ID");
bmobPay = new BmobPay(MainActivity.this);

调用支付宝支付

bmobPay.pay(0.01, "某商品","这里是商品描述", new PayListener() {
    @Override
    public void orderId(String s) {
        orderId = s;
        Toast.makeText(MainActivity.this, "订单号:" + s, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void succeed() {
        Toast.makeText(MainActivity.this, "支付成功", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void fail(int i, String s) {
        Toast.makeText(MainActivity.this, "支付失败:" + s, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void unknow() {
        Toast.makeText(MainActivity.this, "未知", Toast.LENGTH_SHORT).show();
    }
});

调用微信支付,微信支付需要安装插件,我们首先尝试进行静默安装,如果返回异常,则进行正常安装。我们需要编写一个工具类

public class PackageUtils {

    public static String moveFileFromAssetsToSdcard(Context context, String fileName) {
        return moveFileFromAssetsToSdcard(context,fileName,fileName);
    }
    public static String moveFileFromAssetsToSdcard(Context context, String fileName, String tempName) {
        InputStream is = null;
        FileOutputStream fos = null;
        try {
            is = context.getAssets().open(fileName);
            File file = new File(Environment.getExternalStorageDirectory()
                    .getPath() + "/" + tempName);
            file.createNewFile();
            fos = new FileOutputStream(file);
            byte[] temp = new byte[1024];
            int i = 0;
            while ((i = is.read(temp)) > 0) {
                fos.write(temp, 0, i);
            }
            return file.getAbsolutePath();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }
    /**
     * install slient
     *
     * @param context
     * @param filePath
     * @return 0 means normal, 1 means file not exist, 2 means other exception error
     */
    public static int installSlient(Context context, String filePath) {
        File file = new File(filePath);
        if (filePath == null || filePath.length() == 0 || (file = new File(filePath)) == null || file.length() <= 0
                || !file.exists() || !file.isFile()) {
            return 1;
        }

        String[] args = {"pm", "install", "-r", filePath};
        ProcessBuilder processBuilder = new ProcessBuilder(args);

        Process process = null;
        BufferedReader successResult = null;
        BufferedReader errorResult = null;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder errorMsg = new StringBuilder();
        int result;
        try {
            process = processBuilder.start();
            successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));
            errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            String s;
            while ((s = successResult.readLine()) != null) {
                successMsg.append(s);
            }
            while ((s = errorResult.readLine()) != null) {
                errorMsg.append(s);
            }
        } catch (IOException e) {
            e.printStackTrace();
            result = 2;
        } catch (Exception e) {
            e.printStackTrace();
            result = 2;
        } finally {
            try {
                if (successResult != null) {
                    successResult.close();
                }
                if (errorResult != null) {
                    errorResult.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (process != null) {
                process.destroy();
            }
        }
        if (successMsg.toString().contains("Success") || successMsg.toString().contains("success")) {
            result = 0;
        } else {
            result = 2;
        }
        Log.e("installSlient", "successMsg:" + successMsg + ", ErrorMsg:" + errorMsg);
        return result;
    }


    public static void installNormal(Context context, String fileName) {
        File file = new File(fileName);
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setDataAndType(Uri.parse("file://" + file),
                "application/vnd.android.package-archive");
        context.startActivity(intent);

    }

需要将assets目录下的插件拷到文件系统中,然后调用静默安装方法,如果返回0,则安装成功,否则调用正常安装方法。我们可以在微信支付的回调函数中判断是否安装过插件。

bmobPay.payByWX(0.01, "某商品","这里是商品描述", new PayListener() {
    @Override
    public void orderId(String s) {
        orderId = s;
        Toast.makeText(MainActivity.this, "订单号:" + s, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void succeed() {
        Toast.makeText(MainActivity.this, "支付成功", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void fail(int i, String s) {
        if (i == -3) {
            Toast.makeText(MainActivity.this, "未安装支付插件,正在准备安装" + s, Toast.LENGTH_SHORT).show();
            String tempFile = PackageUtils.moveFileFromAssetsToSdcard(MainActivity.this, "BmobPayPlugin.apk");
            Log.e("TAG", "installFile:" + tempFile);
            int installResult = PackageUtils.installSlient(MainActivity.this,tempFile);
            Log.e("TAG", "installResult:" + installResult);
            if(installResult!=0){
                PackageUtils.installNormal(MainActivity.this,tempFile);
            }
            Toast.makeText(MainActivity.this, "插件安装成功!" + s, Toast.LENGTH_SHORT).show();
            return ;
        }
        Toast.makeText(MainActivity.this, "支付失败:" + s, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void unknow() {
        Toast.makeText(MainActivity.this, "未知", Toast.LENGTH_SHORT).show();
    }
});

支付过程中会生成一个订单,该订单开发者需要自己进行存储,可以用该订单号进行查询支付状态

bmobPay.query(orderId, new OrderQueryListener() {
    @Override
    public void succeed(String s) {
        Toast.makeText(MainActivity.this, "查询结果:" + s, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void fail(int i, String s) {
        Toast.makeText(MainActivity.this, "查询失败:" + s, Toast.LENGTH_SHORT).show();
    }
});

succeed回调说明查询成功(并不是说支付成功),返回的status有NOTPAY和SUCCESS两种可能,只有返回SUCCESS才说明支付成功。

支付过程中可能会返回错误码,常见的错误码如下

这里写图片描述

还有一点需要注意的就是

当上一次支付操作尚未完成时,如果BmobPay对象发起再次请求,PayListener会回调fail方法返回并10077错误码,以免生成多个订单
如果使用过程中出现了阻塞(比如异常强制关闭支付插件页面,会导致一直不能再发起请求,这是小概率事件),则调用此方法进行BmobPay的重置
仅对下一次请求生效,而不是永久消除限制。

如果你想查询订单的详细信息,可以使用GET请求,使用Bomb的Restful API发起查询,返回结果是一个json字符串,详细内容如下

效果图

这里写图片描述

这里写图片描述

这里写图片描述

后台订单查询

这里写图片描述

源码下载
http://download.csdn.net/download/sbsujjbcy/9143253

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sbsujjbcy/article/details/48781749
个人分类: 【Android 基础】
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭