diff --git a/README.md b/README.md index 1ebb1a7..3b694a3 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,239 @@ -# beecloud-android -BeeCloud Android SDK (Open Source) +# BeeCloud Android SDK (Open Source) + +![pass](https://img.shields.io/badge/Build-pass-green.svg) ![license](https://img.shields.io/badge/license-MIT-brightgreen.svg) ![version](https://img.shields.io/badge/version-v1.1.0-blue.svg) + +本SDK是根据[BeeCloud Rest API](https://github.com/beecloud/beecloud-rest-api) 开发的 Android SDK。可以作为调用BeeCloud Rest API的示例或者直接用于生产。 + +### [Android-SDK Changelog](https://github.com/beecloud/beecloud-android/blob/master/changelog.txt) + +## 流程 +![pic](http://7xavqo.com1.z0.glb.clouddn.com/UML.png) + +## 安装 +1. 添加依赖 + +>1. 对于通过添加`model`的方式(适用于`gradle`,推荐直接使用`Android Studio`)
+引入`sdk model`,在`project`的`settings.gradle`中`include ':sdk'`,并在需要支付的`model`(比如本项目中的`demo`) `build.gradle`中添加依赖`compile project(':sdk')`。 + +>2. 对于需要以`jar`方式引入的情况
+添加第三方的支付类,在`beecloud-android\sdk\libs`目录下
+`gson-2.2.4.jar`为必须引入的jar,
+微信支付需要引入`libammsdk.jar`,
+支付宝需要引入`alipaysdk.jar`、`alipayutdid.jar`、`alipaysecsdk.jar`,
+银联需要引入`UPPayAssistEx.jar`、`UPPayPluginEx.jar`,
+最后添加`beecloud android sdk`:`beecloud-android\sdk\beecloud.jar` + +2.对于银联支付需要将银联插件`beecloud-android\demo\src\main\assets\UPPayPluginEx.apk`引入你的工程`assets`目录下 + +## 注册 +1. 注册开发者:猛击[这里](http://www.beecloud.cn/register)注册成为BeeCloud开发者。 +2. 注册应用:使用注册的账号登陆[控制台](http://www.beecloud.cn/dashboard/)后,点击"+创建App"创建新应用,并配置支付参数。 + +## 使用方法 +>具体使用请参考项目中的`demo` + +### 1.初始化支付参数 +请参考`demo`中的`ShoppingCartActivity.java` +>1. 在主activity的onCreate函数中初始化BeeCloud账户中的AppID和AppSecret,例如 +```java +BeeCloud.setAppIdAndSecret("c5d1cba1-5e3f-4ba0-941d-9b0a371fe719", "39a7a518-9ac8-4a9e-87bc-7885f33cf18c"); +``` +
+>2. 如果用到微信支付,在用到微信支付的Activity的onCreate函数里调用以下函数,第二个参数需要换成你自己的微信AppID,例如 +```java +BCPay.initWechatPay(ShoppingCartActivity.this, "wxf1aa465362b4c8f1"); +``` + +### 2. 在`AndroidManifest.xml`中添加`permission` +```java + + + +``` + +### 3. 在`AndroidManifest.xml`中注册`activity` + +> 对于微信支付,需要添加 +```java + +``` +```java + +``` +> 对于支付宝,需要添加 +```java + +``` +> 对于银联,需要添加 +```java + +``` + +### 4.支付 + +请查看`doc`中的`API`,支付类`BCPay`,参照`demo`中`ShoppingCartActivity` + +**原型:** + +通过`BCPay`的实例,以`reqWXPaymentAsync`方法发起微信支付请求。
+通过`BCPay`的实例,以`reqAliPaymentAsync`方法发起支付宝支付请求。
+通过`BCPay`的实例,以`reqUnionPaymentAsync`方法发起银联支付请求。
+ +参数依次为 +> billTitle 商品描述, UTF8编码格式, 32个字节内
+> billTotalFee 支付金额,以分为单位,必须是整数格式
+> billNum 商户自定义订单号
+> optional 为扩展参数,可以传入任意数量的key/value对来补充对业务逻辑
+> callback 支付完成后的回调入口 + +**调用:(以微信为例)** + +```java +//定义回调 +BCCallback bcCallback = new BCCallback() { + @Override + public void done(final BCResult bcResult) { + //此处根据业务需要处理支付结果 + final BCPayResult bcPayResult = (BCPayResult)bcResult; + + ShoppingCartActivity.this.runOnUiThread(new Runnable() { + @Override + public void run() { + switch (bcPayResult.getResult()) { + case BCPayResult.RESULT_SUCCESS: + Toast.makeText(ShoppingCartActivity.this, "用户支付成功", Toast.LENGTH_LONG).show(); + break; + case BCPayResult.RESULT_CANCEL: + Toast.makeText(ShoppingCartActivity.this, "用户取消支付", Toast.LENGTH_LONG).show(); + break; + case BCPayResult.RESULT_FAIL: + Toast.makeText(ShoppingCartActivity.this, "支付失败, 原因: " + bcPayResult.getErrMsg() + + ", " + bcPayResult.getDetailInfo(), Toast.LENGTH_LONG).show(); + } + } + }); + } +}; + +//调用支付接口 +Map mapOptional = new HashMap<>(); +String optionalKey = "测试key字段1"; +String optionalValue = "测试value值1"; + +mapOptional.put(optionalKey, optionalValue); + +//订单标题, 订单金额(分), 订单号, 扩展参数(可以null), 支付完成后回调入口 +BCPay.getInstance(ShoppingCartActivity.this).reqWXPaymentAsync("微信支付测试", "1", UUID.randomUUID().toString().replace("-", ""), mapOptional, bcCallback); +``` + +### 5.查询 + +* **查询支付订单** + +请查看`doc`中的`API`,支付类`BCQuery`,参照`demo`中`BillListActivity` + +**原型:** + +通过构造`BCQuery`的实例,使用`queryBillsAsync`方法发起支付查询,该方法仅`channel`为必填参数,指代何种支付方式 + +**调用:** + +```java +//回调入口 +final BCCallback bcCallback = new BCCallback() { + @Override + public void done(BCResult bcResult) { + //根据需求处理结果数据 + final BCQueryResult bcQueryResult = (BCQueryResult)bcResult; + + //resultCode为0表示请求成功 + //count包含返回的订单个数 + if (bcQueryResult.getResultCode() == 0) { + //订单列表 + bills = bcQueryResult.getBills(); + Log.i(BillListActivity.TAG, "bill count: " + bcQueryResult.getCount()); + } else { + bills = null; + BillListActivity.this.runOnUiThread(new Runnable() { + @Override + public void run() { + //错误信息 + Toast.makeText(BillListActivity.this, "err code:" + bcQueryResult.getResultCode() + + "; err msg: " + bcQueryResult.getResultMsg() + + "; err detail: " + bcQueryResult.getErrDetail(), Toast.LENGTH_LONG).show(); + } + }); + } + } +}; + +//发起查询请求 +BCQuery.getInstance().queryBillsAsync( + BCReqParams.BCChannelTypes.UN_APP, //渠道 + null, //订单号 + startTime.getTime(), //订单生成时间 + endTime.getTime(), //订单完成时间 + 2, //忽略满足条件的前2条数据 + 15, //最低返回满足条件的15条数据 + bcCallback); +``` + +## Demo +考虑到个人的开发习惯,本项目提供了`Android Studio`和`Eclipse ADT`两种工程的demo,为了使demo顺利运行,请注意以下细节 +>1. 对于使用`Android Studio`的开发人员,下载源码后可以将`demo_eclipse`移除,`Import Project`的时候选择`beecloud-android`,`sdk`为`demo`的依赖`model`,`gradle`会自动关联。 +>2. 对于使用`Eclipse ADT`的开发人员,`Import Project`的时候选择`beecloud-android`下的`demo_eclipse`,该demo下面已经添加所有需要的`jar`。 + +## 测试 +TODO + +## 常见问题 +- 关于weekhook的接收 +文档请阅读 [webhook](https://github.com/beecloud/beecloud-webhook) + +## 代码贡献 +我们非常欢迎大家来贡献代码,我们会向贡献者致以最诚挚的敬意。 + +一般可以通过在Github上提交[Pull Request](https://github.com/beecloud/beecloud-android)来贡献代码。 + +Pull Request要求 + +- 代码规范 + +- 代码格式化 + +- 必须添加测试! - 如果没有测试(单元测试、集成测试都可以),那么提交的补丁是不会通过的。 + +- 记得更新文档 - 保证`README.md`以及其他相关文档及时更新,和代码的变更保持一致性。 + +- 创建feature分支 - 最好不要从你的master分支提交 pull request。 + +- 一个feature提交一个pull请求 - 如果你的代码变更了多个操作,那就提交多个pull请求吧。 + +- 清晰的commit历史 - 保证你的pull请求的每次commit操作都是有意义的。如果你开发中需要执行多次的即时commit操作,那么请把它们放到一起再提交pull请求。 + +## 联系我们 +- 如果有什么问题,可以到QQ群-**321545822**`BeeCloud开发者大联盟`提问 +- 更详细的文档,见源代码的注释以及[官方文档](https://beecloud.cn/doc/android.php) +- 如果发现了bug,欢迎提交[issue](https://github.com/beecloud/beecloud-android/issues) +- 如果有新的需求,欢迎提交[issue](https://github.com/beecloud/beecloud-android/issues) + +## 代码许可 +The MIT License (MIT). diff --git a/beecloud-android.iml b/beecloud-android.iml new file mode 100644 index 0000000..d02cd2c --- /dev/null +++ b/beecloud-android.iml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..9405f3f --- /dev/null +++ b/build.gradle @@ -0,0 +1,19 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:1.2.3' + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + jcenter() + } +} diff --git a/changelog.txt b/changelog.txt new file mode 100644 index 0000000..831d22a --- /dev/null +++ b/changelog.txt @@ -0,0 +1,10 @@ +BeeCloud Android SDK Changelog + +========================== +v1.1 2015年07年31日 +添加eclipse ADT demo用例 + +========================== +v1.0 2015年07年30日 +支持微信、支付宝、银联支付 +支持订单查询功能 diff --git a/demo/build.gradle b/demo/build.gradle new file mode 100644 index 0000000..51770b8 --- /dev/null +++ b/demo/build.gradle @@ -0,0 +1,27 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 21 + buildToolsVersion "22.0.1" + + defaultConfig { + applicationId "cn.beecloud.sdk_demo" + minSdkVersion 15 + targetSdkVersion 21 + versionCode 1 + versionName "1.0" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + compile fileTree(dir: 'libs', include: ['*.jar']) + compile 'com.android.support:appcompat-v7:22.2.1' + compile 'com.orhanobut:dialogplus:1.10@aar' + compile project(':sdk') +} diff --git a/demo/demo.iml b/demo/demo.iml new file mode 100644 index 0000000..55d5155 --- /dev/null +++ b/demo/demo.iml @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/proguard-rules.pro b/demo/proguard-rules.pro new file mode 100644 index 0000000..0081dc1 --- /dev/null +++ b/demo/proguard-rules.pro @@ -0,0 +1,17 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in C:\AndroidSDK/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/demo/src/androidTest/java/cn/beecloud/sdk_demo/ApplicationTest.java b/demo/src/androidTest/java/cn/beecloud/sdk_demo/ApplicationTest.java new file mode 100644 index 0000000..15c5810 --- /dev/null +++ b/demo/src/androidTest/java/cn/beecloud/sdk_demo/ApplicationTest.java @@ -0,0 +1,13 @@ +package cn.beecloud.sdk_demo; + +import android.app.Application; +import android.test.ApplicationTestCase; + +/** + * Testing Fundamentals + */ +public class ApplicationTest extends ApplicationTestCase { + public ApplicationTest() { + super(Application.class); + } +} \ No newline at end of file diff --git a/demo/src/main/AndroidManifest.xml b/demo/src/main/AndroidManifest.xml new file mode 100644 index 0000000..3a49d42 --- /dev/null +++ b/demo/src/main/AndroidManifest.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/demo/src/main/assets/UPPayPluginEx.apk b/demo/src/main/assets/UPPayPluginEx.apk new file mode 100644 index 0000000..b1e8ba9 Binary files /dev/null and b/demo/src/main/assets/UPPayPluginEx.apk differ diff --git a/demo/src/main/java/cn/beecloud/sdk_demo/BillListActivity.java b/demo/src/main/java/cn/beecloud/sdk_demo/BillListActivity.java new file mode 100644 index 0000000..625af0e --- /dev/null +++ b/demo/src/main/java/cn/beecloud/sdk_demo/BillListActivity.java @@ -0,0 +1,202 @@ +/** + * BillListActivity.java + * + * Created by xuanzhui on 2015/7/29. + * Copyright (c) 2015 BeeCloud. All rights reserved. + */ +package cn.beecloud.sdk_demo; + +import android.app.Activity; +import android.app.ProgressDialog; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.Button; +import android.widget.ListView; +import android.widget.Toast; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; + +import cn.beecloud.BCQuery; +import cn.beecloud.async.BCCallback; +import cn.beecloud.async.BCResult; +import cn.beecloud.entity.BCBill; +import cn.beecloud.entity.BCQueryResult; +import cn.beecloud.entity.BCReqParams; + + +public class BillListActivity extends Activity { + public static final String TAG = "BillListActivity"; + + Button btnWeChatOrder; + Button btnAliPayOrder; + Button btnUNPayOrder; + ListView listViewOrder; + + private Handler mHandler; + private List bills; + + private ProgressDialog loadingDialog; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_bill_list); + + loadingDialog = new ProgressDialog(BillListActivity.this); + loadingDialog.setMessage("正在请求服务器, 请稍后..."); + loadingDialog.setIndeterminate(true); + loadingDialog.setCancelable(true); + + // Defines a Handler object that's attached to the UI thread. + // 通过Handler.Callback()可消除内存泄漏警告 + mHandler = new Handler(new Handler.Callback() { + /** + * Callback interface you can use when instantiating a Handler to + * avoid having to implement your own subclass of Handler. + * + * handleMessage() defines the operations to perform when the + * Handler receives a new Message to process. + */ + @Override + public boolean handleMessage(Message msg) { + if (msg.what == 1) { + + BillListAdapter adapter = new BillListAdapter( + BillListActivity.this, bills); + listViewOrder.setAdapter(adapter); + } + return true; + } + }); + + + listViewOrder = (ListView) findViewById(R.id.listViewOrder); + + //回调入口 + final BCCallback bcCallback = new BCCallback() { + @Override + public void done(BCResult bcResult) { + + //此处关闭loading界面 + loadingDialog.dismiss(); + + final BCQueryResult bcQueryResult = (BCQueryResult) bcResult; + + //resultCode为0表示请求成功 + //count包含返回的订单个数 + if (bcQueryResult.getResultCode() == 0) { + + //订单列表 + bills = bcQueryResult.getBills(); + + Log.i(BillListActivity.TAG, "bill count: " + bcQueryResult.getCount()); + + } else { + //订单列表 + bills = null; + + BillListActivity.this.runOnUiThread(new Runnable() { + @Override + public void run() { + Toast.makeText(BillListActivity.this, "err code:" + bcQueryResult.getResultCode() + + "; err msg: " + bcQueryResult.getResultMsg() + + "; err detail: " + bcQueryResult.getErrDetail(), Toast.LENGTH_LONG).show(); + } + }); + + } + + Message msg = mHandler.obtainMessage(); + msg.what = 1; + mHandler.sendMessage(msg); + } + }; + + btnWeChatOrder = (Button) findViewById(R.id.btnWeChatOrder); + btnWeChatOrder.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + // 如果调起支付太慢,可以在这里开启动画,表示正在loading + //以progressdialog为例 + loadingDialog.show(); + + BCQuery.getInstance().queryBillsAsync( + BCReqParams.BCChannelTypes.WX_APP, bcCallback); + } + }); + + btnAliPayOrder = (Button) findViewById(R.id.btnAliPayOrder); + btnAliPayOrder.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + + loadingDialog.show(); + + BCQuery.getInstance().queryBillsAsync( + BCReqParams.BCChannelTypes.ALI_APP, //渠道 + "5aca2865fbf348f9a415cf18da5f48f7", //订单号 + bcCallback); + } + }); + + btnUNPayOrder = (Button) findViewById(R.id.btnUNPayOrder); + btnUNPayOrder.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + + loadingDialog.show(); + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + + Date startTime, endTime; + try { + startTime = sdf.parse("2015-07-29 12:00"); + endTime = sdf.parse("2015-07-30 12:00"); + } catch (ParseException e) { + startTime = new Date(); + endTime = new Date(); + e.printStackTrace(); + } + + BCQuery.getInstance().queryBillsAsync( + BCReqParams.BCChannelTypes.UN_APP, //渠道 + null, //订单号 + startTime.getTime(), //订单生成时间 + endTime.getTime(), //订单完成时间 + 2, //忽略满足条件的前2条数据 + 15, //只返回满足条件的15条数据 + bcCallback); + } + }); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.menu_bill_list, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + // Handle action bar item clicks here. The action bar will + // automatically handle clicks on the Home/Up button, so long + // as you specify a parent activity in AndroidManifest.xml. + int id = item.getItemId(); + + //noinspection SimplifiableIfStatement + if (id == R.id.action_settings) { + return true; + } + + return super.onOptionsItemSelected(item); + } +} diff --git a/demo/src/main/java/cn/beecloud/sdk_demo/BillListAdapter.java b/demo/src/main/java/cn/beecloud/sdk_demo/BillListAdapter.java new file mode 100644 index 0000000..ed17617 --- /dev/null +++ b/demo/src/main/java/cn/beecloud/sdk_demo/BillListAdapter.java @@ -0,0 +1,133 @@ +/** + * BillListAdapter.java + *

+ * Created by xuanzhui on 2015/7/29. + * Copyright (c) 2015 BeeCloud. All rights reserved. + */ +package cn.beecloud.sdk_demo; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.TextView; + +import java.util.Date; +import java.util.List; + +import cn.beecloud.entity.BCBill; +import cn.beecloud.entity.BCReqParams; + +public class BillListAdapter extends BaseAdapter { + + private List bills; + private LayoutInflater mInflater; + + public BillListAdapter(Context context, List bills) { + this.bills = bills; + mInflater = LayoutInflater.from(context); + } + + /** + * How many items are in the data set represented by this Adapter. + * + * @return Count of items. + */ + @Override + public int getCount() { + if (bills == null) + return 0; + + return bills.size(); + } + + /** + * Get the data item associated with the specified position in the data set. + * + * @param position Position of the item whose data we want within the adapter's + * data set. + * @return The data at the specified position. + */ + @Override + public Object getItem(int position) { + return bills.get(position); + } + + /** + * Get the row id associated with the specified position in the list. + * + * @param position The position of the item within the adapter's data set whose row id we want. + * @return The id of the item at the specified position. + */ + @Override + public long getItemId(int position) { + return position; + } + + /** + * Get a View that displays the data at the specified position in the data set. You can either + * create a View manually or inflate it from an XML layout file. When the View is inflated, the + * parent View (GridView, ListView...) will apply default layout parameters unless you use + * {@link android.view.LayoutInflater#inflate(int, android.view.ViewGroup, boolean)} + * to specify a root view and to prevent attachment to the root. + * + * @param position The position of the item within the adapter's data set of the item whose view + * we want. + * @param convertView The old view to reuse, if possible. Note: You should check that this view + * is non-null and of an appropriate type before using. If it is not possible to convert + * this view to display the correct data, this method can create a new view. + * Heterogeneous lists can specify their number of view types, so that this View is + * always of the right type (see {@link #getViewTypeCount()} and + * {@link #getItemViewType(int)}). + * @param parent The parent that this view will eventually be attached to + * @return A View corresponding to the data at the specified position. + */ + @Override + public View getView(int position, View convertView, ViewGroup parent) { + + final ViewHolder viewHolder; + + if (convertView == null) { + convertView = mInflater.inflate(R.layout.bill_list_item, null); + + viewHolder = new ViewHolder(); + + viewHolder.txtBillNum = (TextView) convertView + .findViewById(R.id.txtBillNum); + viewHolder.txtTotalFee = (TextView) convertView + .findViewById(R.id.txtTotalFee); + viewHolder.txtChannel = (TextView) convertView + .findViewById(R.id.txtChannel); + viewHolder.txtTitle = (TextView) convertView + .findViewById(R.id.txtTitle); + viewHolder.txtPayResult = (TextView) convertView + .findViewById(R.id.txtPayResult); + viewHolder.txtCreatedTime = (TextView) convertView + .findViewById(R.id.txtCreatedTime); + + convertView.setTag(viewHolder); + } else { + viewHolder = (ViewHolder) convertView.getTag(); + } + + BCBill bcBill = bills.get(position); + + viewHolder.txtBillNum.setText("订单号: " + bcBill.getBillNum()); + viewHolder.txtTotalFee.setText("订单金额/元: " + (bcBill.getTotalFee()/100.0)); + viewHolder.txtChannel.setText("支付渠道: " + BCReqParams.BCChannelTypes.getTranslatedChannelName(bcBill.getChannel())); + viewHolder.txtTitle.setText("订单标题: " + bcBill.getTitle()); + viewHolder.txtPayResult.setText("订单是否支付完成: " + (bcBill.getPayResult()?"是":"否")); + viewHolder.txtCreatedTime.setText("订单生成时间: " + new Date(bcBill.getCreatedTime())); + return convertView; + } + + private class ViewHolder { + public TextView txtBillNum; + public TextView txtTotalFee; + public TextView txtChannel; + public TextView txtTitle; + public TextView txtPayResult; + public TextView txtCreatedTime; + } +} diff --git a/demo/src/main/java/cn/beecloud/sdk_demo/DialogPlusAdapter.java b/demo/src/main/java/cn/beecloud/sdk_demo/DialogPlusAdapter.java new file mode 100644 index 0000000..0d303ca --- /dev/null +++ b/demo/src/main/java/cn/beecloud/sdk_demo/DialogPlusAdapter.java @@ -0,0 +1,80 @@ +/** + * DialogPlusAdapter.java + *

+ * Created by xuanzhui on 2015/7/29. + * Copyright (c) 2015 BeeCloud. All rights reserved. + */ +package cn.beecloud.sdk_demo; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ImageView; +import android.widget.TextView; + +public class DialogPlusAdapter extends BaseAdapter { + + private LayoutInflater layoutInflater; + + public DialogPlusAdapter(Context context) { + layoutInflater = LayoutInflater.from(context); + } + + @Override + public int getCount() { + return 3; + } + + @Override + public Object getItem(int position) { + return position; + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + ViewHolder viewHolder; + View view = convertView; + + if (view == null) { + view = layoutInflater.inflate(R.layout.dialogplus_list_item, parent, false); + + viewHolder = new ViewHolder(); + viewHolder.textView = (TextView) view.findViewById(R.id.text_view); + viewHolder.imageView = (ImageView) view.findViewById(R.id.image_view); + view.setTag(viewHolder); + } else { + viewHolder = (ViewHolder) view.getTag(); + } + + Context context = parent.getContext(); + switch (position) { + case 0: + viewHolder.textView.setText(context.getString(R.string.wechat_title)); + viewHolder.imageView.setImageResource(R.drawable.wechat); + break; + case 1: + viewHolder.textView.setText(context.getString(R.string.alipay_title)); + viewHolder.imageView.setImageResource(R.drawable.alipay); + break; + case 2: + viewHolder.textView.setText(context.getString(R.string.unionpay_title)); + viewHolder.imageView.setImageResource(R.drawable.unionpay); + break; + } + + return view; + } + + class ViewHolder { + TextView textView; + ImageView imageView; + } + +} diff --git a/demo/src/main/java/cn/beecloud/sdk_demo/ShoppingCartActivity.java b/demo/src/main/java/cn/beecloud/sdk_demo/ShoppingCartActivity.java new file mode 100644 index 0000000..ccb0c07 --- /dev/null +++ b/demo/src/main/java/cn/beecloud/sdk_demo/ShoppingCartActivity.java @@ -0,0 +1,282 @@ +/** + * ShoppingCartActivity.java + * + * Created by xuanzhui on 2015/7/29. + * Copyright (c) 2015 BeeCloud. All rights reserved. + */ +package cn.beecloud.sdk_demo; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.ProgressDialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.view.Gravity; +import android.view.View; +import android.widget.BaseAdapter; +import android.widget.Button; +import android.widget.ListView; +import android.widget.TextView; +import android.widget.Toast; + +import com.orhanobut.dialogplus.DialogPlus; +import com.orhanobut.dialogplus.Holder; +import com.orhanobut.dialogplus.ListHolder; +import com.orhanobut.dialogplus.OnClickListener; +import com.orhanobut.dialogplus.OnItemClickListener; +import com.unionpay.UPPayAssistEx; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import cn.beecloud.BCPay; +import cn.beecloud.BeeCloud; +import cn.beecloud.async.BCCallback; +import cn.beecloud.async.BCResult; +import cn.beecloud.entity.BCPayResult; + + +public class ShoppingCartActivity extends Activity { + + private static final String TAG = ShoppingCartActivity.class.getSimpleName(); + Button btnShopping; + Button btnQueryAndRefund; + + private ProgressDialog loadingDialog; + + private String[] names = new String[]{ + "衣服", "裤子", "鞋子", + }; + private String[] descs = new String[]{ + "我的新衣服", "我的新裤子", "我的新鞋子" + }; + private int[] imageIds = new int[]{ + R.drawable.yifu, R.drawable.kuzi, R.drawable.xiezi + }; + private Handler mHandler; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_shopping_cart); + + // 推荐在主Activity里的onCreate函数中初始化BeeCloud. + BeeCloud.setAppIdAndSecret("c5d1cba1-5e3f-4ba0-941d-9b0a371fe719", "39a7a518-9ac8-4a9e-87bc-7885f33cf18c"); + + // 如果用到微信支付,在用到微信支付的Activity的onCreate函数里调用以下函数. + // 第二个参数需要换成你自己的微信AppID. + BCPay.initWechatPay(ShoppingCartActivity.this, "wxf1aa465362b4c8f1"); + + // Defines a Handler object that's attached to the UI thread. + // 通过Handler.Callback()可消除内存泄漏警告 + mHandler = new Handler(new Handler.Callback() { + /** + * Callback interface you can use when instantiating a Handler to avoid + * having to implement your own subclass of Handler. + * + * handleMessage() defines the operations to perform when + * the Handler receives a new Message to process. + */ + @Override + public boolean handleMessage(Message msg) { + if (msg.what == 3) { + //如果用户手机没有安装银联支付控件,则会提示用户安装 + AlertDialog.Builder builder = new AlertDialog.Builder(ShoppingCartActivity.this); + builder.setTitle("提示"); + builder.setMessage("完成支付需要安装银联支付控件,是否安装?"); + + builder.setNegativeButton("确定", + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + UPPayAssistEx.installUPPayPlugin(ShoppingCartActivity.this); + dialog.dismiss(); + } + }); + + builder.setPositiveButton("取消", + new DialogInterface.OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + } + }); + builder.create().show(); + } + return true; + } + }); + + btnShopping = (Button) findViewById(R.id.btnPay); + btnShopping.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + showDialogPlus(Gravity.BOTTOM); + } + }); + + btnQueryAndRefund = (Button) findViewById(R.id.btnQueryAndRefund); + btnQueryAndRefund.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(ShoppingCartActivity.this, BillListActivity.class); + startActivity(intent); + } + }); + + List> listItems = new ArrayList<>(); + for (int i = 0; i < names.length; i++) { + Map listItem = new HashMap<>(); + listItem.put("icon", imageIds[i]); + listItem.put("name", names[i]); + listItem.put("desc", descs[i]); + listItems.add(listItem); + } + + ShoppingListAdapter adapter = new ShoppingListAdapter(this, listItems); + ListView listView = (ListView) findViewById(R.id.lstViewShoppingCart); + listView.setAdapter(adapter); + + } + + private void showDialogPlus(int gravity) { + + Holder holder = new ListHolder(); + + OnClickListener clickListener = new OnClickListener() { + @Override + public void onClick(DialogPlus dialog, View view) { + switch (view.getId()) { + case R.id.header_container: + Toast.makeText(ShoppingCartActivity.this, "Header clicked", Toast.LENGTH_SHORT).show(); + break; + case R.id.footer_confirm_button: + Toast.makeText(ShoppingCartActivity.this, "Confirm button clicked", Toast.LENGTH_SHORT).show(); + break; + case R.id.footer_close_button: + Toast.makeText(ShoppingCartActivity.this, "Close button clicked", Toast.LENGTH_SHORT).show(); + break; + } + dialog.dismiss(); + } + }; + + OnItemClickListener itemClickListener = new OnItemClickListener() { + @Override + public void onItemClick(DialogPlus dialog, Object item, View view, int position) { + TextView textView = (TextView) view.findViewById(R.id.text_view); + String clickItem = textView.getText().toString(); + dialog.dismiss(); + + BCCallback bcCallback = new BCCallback() { + @Override + public void done(final BCResult bcResult) { + final BCPayResult bcPayResult = (BCPayResult)bcResult; + //此处关闭loading界面 + loadingDialog.dismiss(); + + //对于支付宝,如果想通过Toast通知用户结果,请使用如下方式, + // 直接makeText会造成java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() + ShoppingCartActivity.this.runOnUiThread(new Runnable() { + @Override + public void run() { + + switch (bcPayResult.getResult()) { + case BCPayResult.RESULT_SUCCESS: + Toast.makeText(ShoppingCartActivity.this, "用户支付成功", Toast.LENGTH_LONG).show(); + break; + case BCPayResult.RESULT_CANCEL: + Toast.makeText(ShoppingCartActivity.this, "用户取消支付", Toast.LENGTH_LONG).show(); + break; + case BCPayResult.RESULT_FAIL: + Toast.makeText(ShoppingCartActivity.this, "支付失败, 原因: " + bcPayResult.getErrMsg() + + ", " + bcPayResult.getDetailInfo(), Toast.LENGTH_LONG).show(); + + if (bcPayResult.getErrMsg().equals(BCPayResult.FAIL_PLUGIN_NOT_INSTALLED) || + bcPayResult.getErrMsg().equals(BCPayResult.FAIL_PLUGIN_NEED_UPGRADE)) { + //银联需要重新安装控件 + Message msg = mHandler.obtainMessage(); + msg.what = 3; + mHandler.sendMessage(msg); + } + + break; + } + } + }); + } + }; + + // 如果调起支付太慢,可以在这里开启动画,表示正在loading + //以progressdialog为例 + loadingDialog = new ProgressDialog(ShoppingCartActivity.this); + loadingDialog.setMessage("启动第三方支付,请稍后..."); + loadingDialog.setIndeterminate(true); + loadingDialog.setCancelable(true); + loadingDialog.show(); + + Map mapOptional; + + switch (clickItem) { + //对于微信支付, 手机内存太小会有OutOfResourcesException造成的卡顿, 以致无法完成支付 + //这个是微信自身存在的问题 + case "微信支付": + + mapOptional = new HashMap<>(); + + mapOptional.put("测试key字段1", "测试value值1"); + + if (BCPay.isWXAppInstalledAndSupported() && + BCPay.isWXPaySupported()) { + //订单标题, 订单金额(分), 订单号, 扩展参数(可以null), 支付完成后回调入口 + BCPay.getInstance(ShoppingCartActivity.this).reqWXPaymentAsync("微信支付测试", "1", + UUID.randomUUID().toString().replace("-", ""), mapOptional, bcCallback); + } + break; + case "支付宝支付": + mapOptional = new HashMap<>(); + mapOptional.put("paymentid", ""); + mapOptional.put("consumptioncode", "consumptionCode"); + mapOptional.put("money", "2"); + + BCPay.getInstance(ShoppingCartActivity.this).reqAliPaymentAsync("支付宝支付测试", "1", + UUID.randomUUID().toString().replace("-", ""), mapOptional, bcCallback); + + break; + case "银联支付": + + BCPay.getInstance(ShoppingCartActivity.this).reqUnionPaymentAsync("银联支付测试", "1", + UUID.randomUUID().toString().replace("-", ""), null, bcCallback); + + break; + } + } + }; + + DialogPlusAdapter adapter = new DialogPlusAdapter(ShoppingCartActivity.this); + showCompleteDialog(holder, gravity, adapter, clickListener, itemClickListener); + } + + + private void showCompleteDialog(Holder holder, int gravity, BaseAdapter adapter, + OnClickListener clickListener, OnItemClickListener itemClickListener) { + final DialogPlus dialog = DialogPlus.newDialog(this) + .setContentHolder(holder) + .setHeader(R.layout.header) + .setFooter(R.layout.footer) + .setCancelable(true) + .setGravity(gravity) + .setAdapter(adapter) + .setOnClickListener(clickListener) + .setOnItemClickListener(itemClickListener) + .create(); + dialog.show(); + } +} diff --git a/demo/src/main/java/cn/beecloud/sdk_demo/ShoppingListAdapter.java b/demo/src/main/java/cn/beecloud/sdk_demo/ShoppingListAdapter.java new file mode 100644 index 0000000..aa80d0c --- /dev/null +++ b/demo/src/main/java/cn/beecloud/sdk_demo/ShoppingListAdapter.java @@ -0,0 +1,73 @@ +/** + * ShoppingListAdapter.java + *

+ * Created by xuanzhui on 2015/7/27. + * Copyright (c) 2015 BeeCloud. All rights reserved. + */ +package cn.beecloud.sdk_demo; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ImageView; +import android.widget.TextView; + +import java.util.List; +import java.util.Map; + +public class ShoppingListAdapter extends BaseAdapter { + + private LayoutInflater mInflater; + private List> mDatas; + + public ShoppingListAdapter(Context context, List> data) { + mInflater = LayoutInflater.from(context); + mDatas = data; + } + + @Override + public int getCount() { + return mDatas.size(); + } + + @Override + public Object getItem(int position) { + return mDatas.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + ViewHolder viewHolder; + + if (convertView == null) { + convertView = mInflater.inflate(R.layout.list_item_shopping_cart, parent, false); + + viewHolder = new ViewHolder(); + viewHolder.txtViewName = (TextView) convertView.findViewById(R.id.txtViewName); + viewHolder.txtViewDesc = (TextView) convertView.findViewById(R.id.txtViewDesc); + viewHolder.imageView = (ImageView) convertView.findViewById(R.id.imageView); + + convertView.setTag(viewHolder); + } else { + viewHolder = (ViewHolder) convertView.getTag(); + } + Map map = mDatas.get(position); + viewHolder.txtViewName.setText(map.get("name").toString()); + viewHolder.txtViewDesc.setText(map.get("desc").toString()); + viewHolder.imageView.setImageResource((int) map.get("icon")); + return convertView; + } + + static class ViewHolder { + TextView txtViewName; + TextView txtViewDesc; + ImageView imageView; + } +} diff --git a/demo/src/main/res/drawable-hdpi/alipay.png b/demo/src/main/res/drawable-hdpi/alipay.png new file mode 100644 index 0000000..27a45a2 Binary files /dev/null and b/demo/src/main/res/drawable-hdpi/alipay.png differ diff --git a/demo/src/main/res/drawable-hdpi/ic_launcher.png b/demo/src/main/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000..96a442e Binary files /dev/null and b/demo/src/main/res/drawable-hdpi/ic_launcher.png differ diff --git a/demo/src/main/res/drawable-hdpi/kuzi.png b/demo/src/main/res/drawable-hdpi/kuzi.png new file mode 100644 index 0000000..7adab48 Binary files /dev/null and b/demo/src/main/res/drawable-hdpi/kuzi.png differ diff --git a/demo/src/main/res/drawable-hdpi/unionpay.png b/demo/src/main/res/drawable-hdpi/unionpay.png new file mode 100644 index 0000000..b76620b Binary files /dev/null and b/demo/src/main/res/drawable-hdpi/unionpay.png differ diff --git a/demo/src/main/res/drawable-hdpi/wechat.png b/demo/src/main/res/drawable-hdpi/wechat.png new file mode 100644 index 0000000..10a89f0 Binary files /dev/null and b/demo/src/main/res/drawable-hdpi/wechat.png differ diff --git a/demo/src/main/res/drawable-hdpi/xiezi.png b/demo/src/main/res/drawable-hdpi/xiezi.png new file mode 100644 index 0000000..c06ebf5 Binary files /dev/null and b/demo/src/main/res/drawable-hdpi/xiezi.png differ diff --git a/demo/src/main/res/drawable-hdpi/yifu.png b/demo/src/main/res/drawable-hdpi/yifu.png new file mode 100644 index 0000000..8cfa872 Binary files /dev/null and b/demo/src/main/res/drawable-hdpi/yifu.png differ diff --git a/demo/src/main/res/drawable-mdpi/alipay.png b/demo/src/main/res/drawable-mdpi/alipay.png new file mode 100644 index 0000000..f8a5617 Binary files /dev/null and b/demo/src/main/res/drawable-mdpi/alipay.png differ diff --git a/demo/src/main/res/drawable-mdpi/ic_launcher.png b/demo/src/main/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 0000000..359047d Binary files /dev/null and b/demo/src/main/res/drawable-mdpi/ic_launcher.png differ diff --git a/demo/src/main/res/drawable-mdpi/unionpay.png b/demo/src/main/res/drawable-mdpi/unionpay.png new file mode 100644 index 0000000..96618c2 Binary files /dev/null and b/demo/src/main/res/drawable-mdpi/unionpay.png differ diff --git a/demo/src/main/res/drawable-mdpi/wechat.png b/demo/src/main/res/drawable-mdpi/wechat.png new file mode 100644 index 0000000..b387933 Binary files /dev/null and b/demo/src/main/res/drawable-mdpi/wechat.png differ diff --git a/demo/src/main/res/drawable-xhdpi/alipay.png b/demo/src/main/res/drawable-xhdpi/alipay.png new file mode 100644 index 0000000..9d978d9 Binary files /dev/null and b/demo/src/main/res/drawable-xhdpi/alipay.png differ diff --git a/demo/src/main/res/drawable-xhdpi/beecloud_logo.png b/demo/src/main/res/drawable-xhdpi/beecloud_logo.png new file mode 100644 index 0000000..974fc8f Binary files /dev/null and b/demo/src/main/res/drawable-xhdpi/beecloud_logo.png differ diff --git a/demo/src/main/res/drawable-xhdpi/ic_launcher.png b/demo/src/main/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 0000000..71c6d76 Binary files /dev/null and b/demo/src/main/res/drawable-xhdpi/ic_launcher.png differ diff --git a/demo/src/main/res/drawable-xhdpi/unionpay.png b/demo/src/main/res/drawable-xhdpi/unionpay.png new file mode 100644 index 0000000..2c92278 Binary files /dev/null and b/demo/src/main/res/drawable-xhdpi/unionpay.png differ diff --git a/demo/src/main/res/drawable-xhdpi/wechat.png b/demo/src/main/res/drawable-xhdpi/wechat.png new file mode 100644 index 0000000..4ca4ec5 Binary files /dev/null and b/demo/src/main/res/drawable-xhdpi/wechat.png differ diff --git a/demo/src/main/res/drawable-xxhdpi/alipay.png b/demo/src/main/res/drawable-xxhdpi/alipay.png new file mode 100644 index 0000000..d605ff8 Binary files /dev/null and b/demo/src/main/res/drawable-xxhdpi/alipay.png differ diff --git a/demo/src/main/res/drawable-xxhdpi/ic_launcher.png b/demo/src/main/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..4df1894 Binary files /dev/null and b/demo/src/main/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/demo/src/main/res/drawable-xxhdpi/unionpay.png b/demo/src/main/res/drawable-xxhdpi/unionpay.png new file mode 100644 index 0000000..f4935ca Binary files /dev/null and b/demo/src/main/res/drawable-xxhdpi/unionpay.png differ diff --git a/demo/src/main/res/drawable-xxhdpi/wechat.png b/demo/src/main/res/drawable-xxhdpi/wechat.png new file mode 100644 index 0000000..45efcdd Binary files /dev/null and b/demo/src/main/res/drawable-xxhdpi/wechat.png differ diff --git a/demo/src/main/res/drawable/selector_bg_button.xml b/demo/src/main/res/drawable/selector_bg_button.xml new file mode 100644 index 0000000..c257bd3 --- /dev/null +++ b/demo/src/main/res/drawable/selector_bg_button.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/demo/src/main/res/layout/activity_bill_list.xml b/demo/src/main/res/layout/activity_bill_list.xml new file mode 100644 index 0000000..b414d93 --- /dev/null +++ b/demo/src/main/res/layout/activity_bill_list.xml @@ -0,0 +1,51 @@ + + +