仿电商App:笔记(十一):购物车,订单,支付功能开发(包含支付宝支付)(二)
6、订单和支付逻辑梳理和创建
6.1 购物车初始化时候的总价值
6.2 订单和支付逻辑梳理
7、封装傻瓜式操作支付工具
7.1 引入支付宝开发的jar包
7.2 支付dialog的布局与弹出效果
7.3 设置dialog,与对应的window绑定
7.4 根Fragment中加入结算事件逻辑
7.5 效果图
8、支付宝接入和实现支付
8.1 支付宝服务器的请求入口
8.2 支付宝请求的具体逻辑实现
8.3 支付请求后的回调
订单包含:用户id,订单id,描述,总之,类型等,通过post传递给自己服务器-->第三方服务器(认证)-->通知自己的服务器可以发起支付-->支付宝的sdk(将签名等信息传过去)-->返回响应值(支付宝规定的):支付状态:成功、失败、网络意外...
具体流程:在购物车根页面中:进行网络请求(自己的服务器,传入生成订单需要的参数)-->请求成功(省略了第三方认证环节,将第三方认证的orderId自己传入):调用支付宝支付平台,传入需要的信息(订单)-->进入FastPay中,进行异步的网络请求,调用客服端支付接口(使用AsyncTask)-->PayAsyncTask中,含有支付状态码,处理doInBackground():根据签名信息返回状态码,返回结果onPostExecute():对返回结果中的状态码进行判断,不同状态吗显示不同信息,具体接口方法实现在购物车根页面中。
逻辑:从adapter中获取到总价数据,赋值到总价按钮的View上。
位于latte-ec模块main->cart包下的ShopCartDelegate。
主要作用:购物车页面的根fragment,初始化总价钱按钮。
public class ShopCartDelegate extends BottomItemDelegate implements ISuccess,ICartItemListener {
......
private double mTotalPrice = 0.0;//初始化总价钱的数值
......
@BindView(R2.id.tv_shop_cart_total_price)//总价按钮
AppCompatTextView mTvTotalPrice = null;
......
@Override
public void onSuccess(String response) {
final ArrayList data =
new ShopCartDataConverter()
.setJsonData(response)
.convert();
mAdapter = new ShopCartAdapter(data);
mAdapter.setCartItemListener(this);
final LinearLayoutManager manager = new LinearLayoutManager(getContext());
mRecyclerView.setLayoutManager(manager);
mRecyclerView.setAdapter(mAdapter);//缓存到类中
** mTotalPrice = mAdapter.getTotalPrice();
** mTvTotalPrice.setText(String.valueOf(mTotalPrice));//初始化的时候直接更新数值
checkItemCount();
}
@Override
public void onItemClick(double itemTotalPrice) {
final double price = mAdapter.getTotalPrice();
** mTvTotalPrice.setText(String.valueOf(price));
}
}
订单和支付是两个不同的东西
订单:记录这次发起的行为:行为所标记的信息,支付成功、支付失败、支付意外等
支付:将钱给支付宝,支付宝管理
订单包含:用户id,订单id,描述,总之,类型等,通过post传递给自己服务器-->第三方服务器(认证)-->通知自己的服务器可以发起支付-->支付宝的sdk(将签名等信息传过去)-->返回响应值(支付宝规定的):支付状态:成功、失败、网络意外...
位于latte-ec模块main->cart包下的ShopCartDelegate。
主要作用:购物车页面的根fragment,创建订单。
public class ShopCartDelegate extends BottomItemDelegate implements ISuccess,ICartItemListener {
......
@OnClick(R2.id.tv_shop_cart_pay)//结算按钮
void onClickPay(){
}
//创建订单,注意:和支付是没有关系的
private void createOrder(){
final String orderUrl = "";
final WeakHashMap orderParams = new WeakHashMap<>();//订单需要传入的参数
orderParams.put("userid","");
orderParams.put("amount",0.01);//总价
orderParams.put("commit","测试支付");//描述
orderParams.put("type",1);
orderParams.put("ordertype",0);
orderParams.put("isanonymous",true);
orderParams.put("followeduser",0);
RestClient.builder()//发起订单
.url(orderUrl)//请求自己的服务器
.loader(getContext())
.params(orderParams)
.success(new ISuccess() {
@Override
public void onSuccess(String response) {
//进行具体的支付
}
})
.build()
.post();
}
......
}
Project模式下->latte-ec->libs包->将jar包复制到下面->右键add as library,放进你的module中(要是有多个module,要注意自己要放进哪个module),就会发现在该module中引入了
1、阿里pay支付后的状态的回调监听
位于latte-ec模块main->pay包下的IAlPayResultListener。
主要作用:阿里pay支付后的状态的回调监听。
public interface IAlPayResultListener {
void onPaySuccess();
void onPaying();
void onPayFail();
void onPayCancel();
void onPayConnectError();
}
2、支付dialog的布局
3、支付dialog的弹出和消失的动画效果
位于latte-ec模块res->anim包下的push_bottom_in.xml文件。
主要作用:dialog的进入的从下往上动画。
位于latte-ec模块res->anim包下的push_bottom_out.xml文件。
主要作用:dialog的出去的从上往下动画。
4、引入的style.xml文件包好动画效果,为了后续直接引入到代码中
位于latte-ec模块res->values包下的styles.xml文件。
主要作用:dialog的动画。
位于latte-ec模块main->pay包下的FastPay。
主要作用:支付宝,dialog选择支付的选择。
public class FastPay implements View.OnClickListener{
//设置支付会回调监听
private IAlPayResultListener mIAlPayResultListener = null;
private Activity mActivity = null;
private AlertDialog mDialog = null;//弹出框,选择支付方式
private int mOrderID = -1;
private FastPay(LatteDelegate delegate){//工厂方法
this.mActivity = delegate.getProxyActivity();
this.mDialog = new AlertDialog.Builder(delegate.getContext()).create();
}
public static FastPay create(LatteDelegate delegate){//静态工厂方法
return new FastPay(delegate);
}
public void beginPayDialog(){//支付方法
mDialog.show();
final Window window = mDialog.getWindow();
if (window!=null){
window.setContentView(R.layout.dialog_pay_pancel);//给dialog设置支付view
window.setGravity(Gravity.BOTTOM);//底部居中
window.setWindowAnimations(R.style.anim_panel_up_from_bottom);//设置从下往上动画
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));//透明的
//设置属性
final WindowManager.LayoutParams params = window.getAttributes();//先将原有属性取出,调整后,再设置回去
params.width = WindowManager.LayoutParams.MATCH_PARENT;
params.flags = WindowManager.LayoutParams.FLAG_DIM_BEHIND;
window.setAttributes(params);
window.findViewById(R.id.btn_dialog_pay_alpay).setOnClickListener(this);//设置点击的事件
window.findViewById(R.id.btn_dialog_pay_wechat).setOnClickListener(this);
window.findViewById(R.id.btn_dialog_pay_cancel).setOnClickListener(this);
}
}
@Override
public void onClick(View v) {
int id = v.getId();
if (id == R.id.btn_dialog_pay_alpay){//不能使用switch
mDialog.cancel();//点击后,dialog退出
}else if(id == R.id.btn_dialog_pay_wechat){
mDialog.cancel();
}else if(id == R.id.btn_dialog_pay_cancel){
mDialog.cancel();
}
}
}
位于latte-ec模块main->cart包下的ShopCartDelegate。
主要作用:购物车页面的根fragment,结算事件的添加。
@OnClick(R2.id.tv_shop_cart_pay)
void onClickPay(){
FastPay.create(this).beginPayDialog();//结算按钮添加事件
}
位于latte-ec模块main->pay包下的FastPay。
主要作用:支付宝,点击支付宝按钮,对支付包服务器进行请求。
public class FastPay implements View.OnClickListener{
//设置支付会回调监听
private IAlPayResultListener mIAlPayResultListener = null;
private Activity mActivity = null;
private AlertDialog mDialog = null;
private int mOrderID = -1;
public FastPay setPayResultListener(IAlPayResultListener listener){//传入回调
this.mIAlPayResultListener = listener;
return this;
}
public FastPay setOrderId(int orderId){
this.mOrderID = orderId;
return this;
}
public final void alPay(int orderId){//支付宝支付
final String singUrl = "";//签名串,请求服务器获取的
//获取签名字符串,服务端返回JSON数据,对JSON数据进行解析,取出需要的信息,发起Android客户端的支付
RestClient.builder()
.url(singUrl)
.success(new ISuccess() {
@Override
public void onSuccess(String response) {
final String paySign = "";//签名信息
//必须是异步的调用客服端支付接口
final PayAsyncTask payAsyncTask = new PayAsyncTask(mActivity,mIAlPayResultListener);
payAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,paySign);//多线程池同时执行
}
})
.build()
.post();
}
@Override
public void onClick(View v) {
int id = v.getId();
if (id == R.id.btn_dialog_pay_alpay){
alPay(mOrderID);
mDialog.cancel();
}else if(id == R.id.btn_dialog_pay_wechat){
mDialog.cancel();
}else if(id == R.id.btn_dialog_pay_cancel){
mDialog.cancel();
}
}
}
位于latte-ec模块main->pay包下的PayAsyncTask。
主要作用:支付包服务器进行请求,使用AsyncTask进行异步请求。
public class PayAsyncTask extends AsyncTask {
private final Activity ACTIVITY;//支付宝支付的变量
private final IAlPayResultListener LISTENER;
//订单支付成功
private static final String AL_PAY_STATUS_SUCCESS = "9000";
//订单处理中
private static final String AL_PAY_STATUS_PAYING = "8000";
//订单支付失败
private static final String AL_PAY_STATUS_FAIL = "4000";
//用户取消
private static final String AL_PAY_STATUS_CANCEL = "6001";
//支付网络错误
private static final String AL_PAY_STATUS_CONNECT_ERROR = "6002";
public PayAsyncTask(Activity activity, IAlPayResultListener listener) {
ACTIVITY = activity;
LISTENER = listener;
}
@Override
protected String doInBackground(String... params) {//返回的验证码
final String alPaySign = params[0];//签名信息
final PayTask payTask = new PayTask(ACTIVITY);//支付宝提供
return payTask.pay(alPaySign, true);//true:允许验证
}
@Override
protected void onPostExecute(String result) {//对返回值判断
super.onPostExecute(result);
LatteLoader.stopLoading();//关闭之前的loader
final PayResult payResult = new PayResult(result);//复制的PayResult文件:alibaba自带的
//支付宝返回此次支付结构及加签,建议对支付宝签名信息拿签约是支付宝提供的公钥做验签
final String resultInfo = payResult.getResult();//支付
final String resultStatus = payResult.getResultStatus();//支付状态
switch (resultStatus){//根据支付状态进行处理
case AL_PAY_STATUS_SUCCESS:
if (LISTENER!=null){
LISTENER.onPaySuccess();
}
break;
case AL_PAY_STATUS_FAIL:
if (LISTENER!=null){
LISTENER.onPayFail();
}
break;
case AL_PAY_STATUS_PAYING:
if (LISTENER!=null){
LISTENER.onPaying();
}
break;
case AL_PAY_STATUS_CANCEL:
if (LISTENER!=null){
LISTENER.onPayCancel();
}
break;
case AL_PAY_STATUS_CONNECT_ERROR:
if (LISTENER!=null){
LISTENER.onPayConnectError();
}
break;
default:
break;
}
}
}
位于latte-ec模块main->cart包下的ShopCartDelegate。
主要作用:购物车页面的根fragment,支付后的状态回调处理,支付调用入口。
public class ShopCartDelegate extends BottomItemDelegate implements ISuccess,ICartItemListener,IAlPayResultListener {
......
@OnClick(R2.id.tv_shop_cart_pay)
void onClickPay(){
createOrder();
}
//创建订单,注意:和支付是没有关系的
private void createOrder(){
final String orderUrl = "";
final WeakHashMap orderParams = new WeakHashMap<>();
orderParams.put("userid","");
orderParams.put("amount",0.01);
orderParams.put("commit","测试支付");
orderParams.put("type",1);
orderParams.put("ordertype",0);
orderParams.put("isanonymous",true);
orderParams.put("followeduser",0);
RestClient.builder()
.url(orderUrl)
.loader(getContext())
.params(orderParams)
.success(new ISuccess() {
@Override
public void onSuccess(String response) {
//进行具体的支付
// final int orderId = JSON.parseObject(response).getInteger("result");
FastPay.create(ShopCartDelegate.this)//调用FastPay进行支付请求
.setPayResultListener(ShopCartDelegate.this)//将监听事件放到本身
// .setOrderId(orderId)
.beginPayDialog();
}
})
.build()
.post();
}
......
@Override
public void onPaySuccess() {
}
@Override
public void onPaying() {
}
@Override
public void onPayFail() {
}
@Override
public void onPayCancel() {
}
@Override
public void onPayConnectError() {
}
}