【0111】【项目实战】-【Android通用框架设计与完整电商APP开发】-【11】购物车,订单,支付功能开发(包含支付宝支付和微信支付)
1.购物车UI编写
1.1 购物车布局
【新建包和类】
【ToolBar的布局】
1 <?xml version="1.0" encoding="utf-8"?> 2 <android.support.v7.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:tools="http://schemas.android.com/tools" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent" 6 android:background="#1111" 7 android:orientation="vertical"> 8 9 <android.support.v7.widget.Toolbar 10 android:layout_width="match_parent" 11 android:layout_height="75dp" 12 android:background="@color/app_main" 13 android:gravity="center"> 14 15 <RelativeLayout 16 android:layout_width="match_parent" 17 android:layout_height="match_parent"> 18 19 <android.support.v7.widget.AppCompatTextView 20 android:id="@+id/tv_top_shop_cart_clear" 21 android:layout_width="wrap_content" 22 android:layout_height="match_parent" 23 android:layout_alignParentLeft="true" 24 android:layout_marginLeft="20dp" 25 android:gravity="center" 26 android:text="清空" 27 android:textColor="@android:color/white" 28 android:textSize="18sp" 29 tools:ignore="HardcodedText,RtlHardcoded" /> 30 31 <android.support.v7.widget.AppCompatTextView 32 android:layout_width="wrap_content" 33 android:layout_height="match_parent" 34 android:layout_centerHorizontal="true" 35 android:gravity="center" 36 android:text="购物车" 37 android:textColor="@android:color/white" 38 android:textSize="20sp" 39 tools:ignore="HardcodedText" /> 40 41 <android.support.v7.widget.AppCompatTextView 42 android:id="@+id/tv_top_shop_cart_remove_selected" 43 android:layout_width="wrap_content" 44 android:layout_height="match_parent" 45 android:layout_alignParentRight="true" 46 android:layout_marginLeft="20dp" 47 android:layout_marginRight="20dp" 48 android:gravity="center" 49 android:text="删除" 50 android:textColor="@android:color/white" 51 android:textSize="18sp" 52 tools:ignore="HardcodedText,RtlHardcoded" /> 53 </RelativeLayout> 54 </android.support.v7.widget.Toolbar>
1 <?xml version="1.0" encoding="utf-8"?> 2 <android.support.v7.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:tools="http://schemas.android.com/tools" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent" 6 android:background="#1111" 7 android:orientation="vertical"> 8 9 <android.support.v7.widget.Toolbar 10 android:layout_width="match_parent" 11 android:layout_height="75dp" 12 android:background="@color/app_main" 13 android:gravity="center"> 14 15 <RelativeLayout 16 android:layout_width="match_parent" 17 android:layout_height="match_parent"> 18 19 <android.support.v7.widget.AppCompatTextView 20 android:id="@+id/tv_top_shop_cart_clear" 21 android:layout_width="wrap_content" 22 android:layout_height="match_parent" 23 android:layout_alignParentLeft="true" 24 android:layout_marginLeft="20dp" 25 android:gravity="center" 26 android:text="清空" 27 android:textColor="@android:color/white" 28 android:textSize="18sp" 29 tools:ignore="HardcodedText,RtlHardcoded" /> 30 31 <android.support.v7.widget.AppCompatTextView 32 android:layout_width="wrap_content" 33 android:layout_height="match_parent" 34 android:layout_centerHorizontal="true" 35 android:gravity="center" 36 android:text="购物车" 37 android:textColor="@android:color/white" 38 android:textSize="20sp" 39 tools:ignore="HardcodedText" /> 40 41 <android.support.v7.widget.AppCompatTextView 42 android:id="@+id/tv_top_shop_cart_remove_selected" 43 android:layout_width="wrap_content" 44 android:layout_height="match_parent" 45 android:layout_alignParentRight="true" 46 android:layout_marginLeft="20dp" 47 android:layout_marginRight="20dp" 48 android:gravity="center" 49 android:text="删除" 50 android:textColor="@android:color/white" 51 android:textSize="18sp" 52 tools:ignore="HardcodedText,RtlHardcoded" /> 53 </RelativeLayout> 54 </android.support.v7.widget.Toolbar> 55 56 <android.support.v7.widget.RecyclerView //购物车中的货物展示都是使用recyclerView控件显示的 57 android:id="@+id/rv_shop_cart" 58 android:layout_width="match_parent" 59 android:layout_height="0dp" 60 android:layout_weight="8" /> 61 62 <android.support.v7.widget.ViewStubCompat //如果购物车中没有货物,进行占位的功能 63 android:id="@+id/stub_no_item" 64 android:layout_width="match_parent" 65 android:layout_height="0dp" 66 android:layout_weight="8" 67 android:background="@android:color/white" 68 android:layout="@layout/stub_shop_cart_no_item" 69 android:minHeight="50dp" 70 android:orientation="horizontal" /> 71 72 <android.support.v7.widget.LinearLayoutCompat 73 android:layout_width="match_parent" 74 android:layout_height="0dp" 75 android:layout_gravity="bottom" 76 android:layout_weight="1" 77 android:minHeight="50dp" 78 android:orientation="horizontal"> 79 80 <!--全选图标模块--> 81 <android.support.v7.widget.LinearLayoutCompat 82 android:layout_width="0dp" 83 android:layout_height="match_parent" 84 android:layout_weight="1" 85 android:minHeight="50dp" 86 android:orientation="horizontal"> 87 88 <com.joanzapata.iconify.widget.IconTextView 89 android:id="@+id/icon_shop_cart_select_all" 90 android:layout_width="0dp" 91 android:layout_height="match_parent" 92 android:layout_weight="1" 93 android:gravity="center" 94 android:text="{fa-check-circle}" 95 android:textColor="@android:color/darker_gray" 96 android:textSize="20sp" /> 97 98 <android.support.v7.widget.AppCompatTextView 99 android:layout_width="0dp" 100 android:layout_height="match_parent" 101 android:layout_weight="1" 102 android:gravity="center" 103 android:text="全选" 104 android:textColor="@color/app_main" /> 105 </android.support.v7.widget.LinearLayoutCompat> 106 <!--全选部分结束--> 107 108 <!--合计部分--> 109 <android.support.v7.widget.LinearLayoutCompat 110 android:layout_width="0dp" 111 android:layout_height="match_parent" 112 android:layout_weight="2" 113 android:minHeight="50dp" 114 android:orientation="horizontal"> 115 116 <android.support.v7.widget.AppCompatTextView 117 android:layout_width="0dp" 118 android:layout_height="match_parent" 119 android:layout_weight="1" 120 android:gravity="center" 121 android:text="合计" 122 android:textColor="@android:color/darker_gray" 123 tools:ignore="HardcodedText" /> 124 125 <android.support.v7.widget.AppCompatTextView 126 android:id="@+id/tv_shop_cart_total_price" 127 android:layout_width="0dp" 128 android:layout_height="match_parent" 129 android:layout_weight="1" 130 android:gravity="center|left" 131 android:text="¥0.01" 132 android:textColor="@color/app_main" 133 android:textSize="20sp" 134 tools:ignore="HardcodedText,RtlHardcoded" /> 135 136 </android.support.v7.widget.LinearLayoutCompat> 137 138 <android.support.v7.widget.AppCompatTextView 139 android:id="@+id/tv_shop_cart_pay" 140 android:layout_width="0dp" 141 android:layout_height="match_parent" 142 android:layout_weight="1" 143 android:background="@color/app_main" 144 android:gravity="center" 145 android:text="结算" 146 android:textColor="@android:color/white" 147 android:textSize="20sp" 148 tools:ignore="HardcodedText" /> 149 150 </android.support.v7.widget.LinearLayoutCompat> 151 152 </android.support.v7.widget.LinearLayoutCompat>
1.2 recycleView中的item的布局
1 <?xml version="1.0" encoding="utf-8"?> 2 <android.support.v7.widget.LinearLayoutCompat 3 xmlns:android="http://schemas.android.com/apk/res/android" 4 xmlns:tools="http://schemas.android.com/tools" 5 android:layout_width="match_parent" 6 android:layout_height="100dp" 7 android:layout_marginBottom="5dp" 8 android:background="@android:color/white" 9 android:orientation="horizontal"> 10 11 <com.joanzapata.iconify.widget.IconTextView 12 android:id="@+id/icon_item_shop_cart" 13 android:layout_width="wrap_content" 14 android:layout_height="wrap_content" 15 android:layout_gravity="center_vertical" 16 android:layout_marginLeft="10dp" 17 android:gravity="center" 18 android:text="{fa-check-circle}" 19 android:textColor="@android:color/darker_gray" 20 tools:ignore="HardcodedText,RtlHardcoded" /> 21 22 <android.support.v7.widget.AppCompatImageView 23 android:id="@+id/image_item_shop_cart" 24 android:layout_width="80dp" 25 android:layout_height="80dp" 26 android:layout_gravity="center_vertical" 27 android:layout_marginLeft="10dp" 28 android:layout_marginRight="10dp" /> 29 30 <!--商品信息--> 31 <android.support.v7.widget.LinearLayoutCompat 32 android:layout_width="0dp" 33 android:layout_height="match_parent" 34 android:layout_weight="2" 35 android:gravity="center_vertical" 36 android:orientation="vertical" 37 android:padding="10dp"> 38 39 <android.support.v7.widget.AppCompatTextView 40 android:id="@+id/tv_item_shop_cart_title" 41 android:layout_width="wrap_content" 42 android:layout_height="wrap_content" 43 android:layout_marginBottom="5dp" 44 android:text="商品标题" 45 tools:ignore="HardcodedText" /> 46 47 <android.support.v7.widget.AppCompatTextView 48 android:id="@+id/tv_item_shop_cart_desc" 49 android:layout_width="wrap_content" 50 android:layout_height="wrap_content" 51 android:layout_marginBottom="5dp" 52 android:text="商品描述" 53 tools:ignore="HardcodedText" /> 54 55 <android.support.v7.widget.AppCompatTextView 56 android:id="@+id/tv_item_shop_cart_price" 57 android:layout_width="wrap_content" 58 android:layout_height="wrap_content" 59 android:text="2.00" 60 android:textColor="@color/app_main" 61 android:typeface="monospace" 62 tools:ignore="HardcodedText" /> 63 </android.support.v7.widget.LinearLayoutCompat> 64 <!--商品信息结束--> 65 66 <android.support.v7.widget.LinearLayoutCompat 67 android:layout_width="0dp" 68 android:layout_height="match_parent" 69 android:layout_marginBottom="20dp" 70 android:layout_weight="1" 71 android:gravity="bottom" 72 android:orientation="horizontal"> 73 74 <com.joanzapata.iconify.widget.IconTextView 75 android:id="@+id/icon_item_minus" 76 android:layout_width="20dp" 77 android:layout_height="20dp" 78 android:gravity="center" 79 android:text="{fa-minus-square-o}" 80 android:textSize="24sp" 81 tools:ignore="HardcodedText" /> 82 83 <android.support.v7.widget.AppCompatTextView 84 android:id="@+id/tv_item_shop_cart_count" 85 android:layout_width="20dp" 86 android:layout_height="20dp" 87 android:gravity="center" 88 android:text="1" 89 android:textSize="18sp" 90 tools:ignore="HardcodedText" /> 91 92 <com.joanzapata.iconify.widget.IconTextView 93 android:id="@+id/icon_item_plus" 94 android:layout_width="20dp" 95 android:layout_height="20dp" 96 android:gravity="center" 97 android:text="{fa-plus-square-o}" 98 android:textSize="24sp" 99 tools:ignore="HardcodedText" /> 100 101 </android.support.v7.widget.LinearLayoutCompat> 102 103 </android.support.v7.widget.LinearLayoutCompat>
2. 购物车数据结构分析、解析与转化
2.1 解析的数据
【json数据】data中的每个字段就是要解析的item的数据;
2.2 数据的转化
【构建entivity】
2.3 数据适配器的添加
【添加购物车的布局】
【取出所有的值】
【取出控件】
【赋值】
【设置适配器】
[视图绑定]
3. 购物车逻辑梳理与实现
3.1 是否选中的事件的响应
【完成icon的点击事件】
【说明】此处的点击事件:不要实现接口,要单独的书写onClick方法,否则,每个item无法响应事件;
3.2 全选按钮事件的响应
【item对全选事件的响应】
【完善】
【item对全选状态的改变】
【效果】但是会闪一下,需要去除掉更新的动画效果;
3.3 闪屏bug
3.4 删除按钮的功能实现
3.5 清空购物车
【修改】
3.6 清空购物车之后的额外内容的显示
【原理】填充一个新的View;
【调用】
【bug1】
【bug2】下半部变得很宽
3.7 左右加号减号的功能的实现
【减号功能的实现】与服务器的数据实时的进行更新同步;每次都需要请求服务器更新数据;
【加号功能的实现】
3.8 结算功能的实现
【接口的定义】因为在全选、点击加减按钮的时候,都需要进行全局的数据的价格的更新,以接口的形式返回数据;
【取出总价】
【BUG】
【现象】之前显示的数据是不正确的;现在增加一个变量;
4.订单和支付逻辑梳理和处理
4.1 支付的流程
【说明】需要我们自己的服务向第三方的支付平台进行请求,然后进行认证等之后返回状态;
【区别】区别订单和支付的不同;
4.2 额外梳理、整理module结构、升级依赖、更好的进行分离
【fragment的依赖的处理】已经进行了升级;降低了耦合度;
5. 封装傻瓜式操作支付工具
【说明】主要是界面的布局和完善;
【引入依赖】
【封装返回状态的回调接口】
【封装工具类】
[注意]更新fragment的依赖之后的mActivity有所改变;
【弹框的layout】
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:tools="http://schemas.android.com/tools" 4 android:layout_width="match_parent" 5 android:layout_height="wrap_content" 6 android:background="@android:color/white" 7 android:orientation="vertical" 8 android:paddingBottom="20dp"> 9 10 <LinearLayout 11 android:layout_width="match_parent" 12 android:layout_height="200dp" 13 android:orientation="horizontal"> 14 15 <com.joanzapata.iconify.widget.IconTextView 16 android:id="@+id/btn_dialog_pay_alpay" 17 android:layout_width="0dp" 18 android:layout_height="match_parent" 19 android:layout_weight="1" 20 android:gravity="center" 21 android:text="{icon-ali-pay}" 22 android:textColor="@android:color/holo_blue_bright" 23 android:textSize="50sp" 24 tools:ignore="HardcodedText" /> 25 26 <com.joanzapata.iconify.widget.IconTextView 27 android:id="@+id/btn_dialog_pay_wechat" 28 android:layout_width="0dp" 29 android:layout_height="match_parent" 30 android:layout_weight="1" 31 android:gravity="center" 32 android:text="{fa-weixin}" 33 android:textColor="#04b00f" 34 android:textSize="50sp" 35 tools:ignore="HardcodedText" /> 36 </LinearLayout> 37 38 <Button 39 android:id="@+id/btn_dialog_pay_cancel" 40 android:layout_width="match_parent" 41 android:layout_height="50dp" 42 android:layout_marginLeft="50dp" 43 android:layout_marginRight="50dp" 44 android:background="@color/app_main" 45 android:gravity="center" 46 android:text="取消支付" 47 android:textColor="@android:color/white" 48 android:textSize="16sp" /> 49 50 </LinearLayout>
【完善支付工具类】
【增加动画】从底向上的动画封装
【设置动画和属性】
【设置点击事件的响应】
【响应点击事件】
6.支付宝的接入和实现支付
【异步类的封装】
【根据返回的状态进行处理】
1 package com.flj.latte.ec.pay; 2 3 import android.app.Activity; 4 import android.os.AsyncTask; 5 6 import com.alipay.sdk.app.PayTask; 7 import com.flj.latte.ui.loader.LatteLoader; 8 import com.flj.latte.util.log.LatteLogger; 9 13 14 public class PayAsyncTask extends AsyncTask<String, Void, String> { 15 16 private final Activity ACTIVITY; 17 private final IAlPayResultListener LISTENER; 18 19 //订单支付成功 20 private static final String AL_PAY_STATUS_SUCCESS = "9000"; 21 //订单处理中 22 private static final String AL_PAY_STATUS_PAYING = "8000"; 23 //订单支付失败 24 private static final String AL_PAY_STATUS_FAIL = "4000"; 25 //用户取消 26 private static final String AL_PAY_STATUS_CANCEL = "6001"; 27 //支付网络错误 28 private static final String AL_PAY_STATUS_CONNECT_ERROR = "6002"; 29 30 public PayAsyncTask(Activity activity, IAlPayResultListener listener) { 31 this.ACTIVITY = activity; 32 this.LISTENER = listener; 33 } 34 35 @Override 36 protected String doInBackground(String... params) { 37 final String alPaySign = params[0]; 38 final PayTask payTask = new PayTask(ACTIVITY); 39 return payTask.pay(alPaySign, true); 40 } 41 42 @Override 43 protected void onPostExecute(String result) { 44 super.onPostExecute(result); 45 LatteLoader.stopLoading(); 46 final PayResult payResult = new PayResult(result); 47 // 支付宝返回此次支付结构及加签,建议对支付宝签名信息拿签约是支付宝提供的公钥做验签 48 final String resultInfo = payResult.getResult(); 49 final String resultStatus = payResult.getResultStatus(); 50 LatteLogger.d("AL_PAY_RESULT", resultInfo); 51 LatteLogger.d("AL_PAY_RESULT", resultStatus); 52 53 switch (resultStatus) { 54 case AL_PAY_STATUS_SUCCESS: 55 if (LISTENER != null) { 56 LISTENER.onPaySuccess(); 57 } 58 break; 59 case AL_PAY_STATUS_FAIL: 60 if (LISTENER != null) { 61 LISTENER.onPayFail(); 62 } 63 break; 64 case AL_PAY_STATUS_PAYING: 65 if (LISTENER != null) { 66 LISTENER.onPaying(); 67 } 68 break; 69 case AL_PAY_STATUS_CANCEL: 70 if (LISTENER != null) { 71 LISTENER.onPayCancel(); 72 } 73 break; 74 case AL_PAY_STATUS_CONNECT_ERROR: 75 if (LISTENER != null) { 76 LISTENER.onPayConnectError(); 77 } 78 break; 79 default: 80 break; 81 } 82 } 83 }
【结果的处理】
【在购物车结算中进行调用】
7.微信支付和通过代码生成器生成支付代码