美文网首页iOS开发之常用技术点秒杀&支付
基于工厂模式的支付宝和微信支付封装(Kotlin、Java)

基于工厂模式的支付宝和微信支付封装(Kotlin、Java)

作者: Taonce | 来源:发表于2018-11-05 23:00 被阅读219次
    刘诗诗.jpeg

    简单工厂模式:

    简单工厂.png

    简单工厂:产品基类有一个,可延伸多个具体的产品,比如:男产品,女产品。工厂类控制生成具体的产品对象。

    // 产品基类
    abstract class BaseProduct{
     abstract fun makePrd();
    }
    ​
    // 男产品
    class MaleProduct:BaseProduct(){
     override fun makePrd() {
     println("male product make a prd")
     }
    }
    ​
    // 女产品
    class FemaleProduct:BaseProduct(){
     override fun makePrd() {
     println("female product make a prd")
     }
    }
    ​
    // 工厂类
    class Factory {
    ​
     /**
     * 根据不同类型,生成不同的产品对象
     */
     fun createProduct(type: String): BaseProduct {
     return when (type) {
     "male" -> MaleProduct()
     "female" -> FemaleProduct()
     else -> MaleProduct()
     }
     }
    }
    ​
    // 调用和输出
    fun main(args: Array<String>) {
     Factory().createProduct("male").makePrd()
     Factory().createProduct("female").makePrd()
     //输出:
     //male product make a prd
     //female product make a prd
    }
    

    优势:想拿到具体的对象不需要再手动new,也就是说你具体对象如何改变,只需要改变工厂类的new方法,不需要再调用处修改。

    劣势:具体产品类的类名修改,那么就需要修改工厂类的when方法,没有达到理想状态。


    工厂模式

    工厂.png

    工厂模式:产品模块和简单工厂一致,但是工厂的实现改变了,不再通过type来判断生成什么产品类,而是通过反射机制来生成。

    // 工厂基类
    abstract class BaseFactory {
     abstract fun <T : BaseProduct> createProduct(clazz: Class<T>): T
    }
    ​
    // 工厂类,继承工厂基类,通过clazz: Class<T>实现反射来生成具体的产品类
    object Factory : BaseFactory() {
     override fun <T : BaseProduct> createProduct(clazz: Class<T>): T {
     val baseProduct: BaseProduct?
     val className = clazz.name
     baseProduct = Class.forName(className).newInstance() as BaseProduct
     return baseProduct as T
     }
    }
    ​
    // 调用和输出
    fun main(args: Array<String>) {
     Factory.createProduct(MaleProduct::class.java).makePrd()
     Factory.createProduct(FemaleProduct::class.java).makePrd()
    }
    ​
    // male product make a prd
    // female product make a prd
    

    总结:工厂模式在改变产品具体类的时候,是不需要修改工厂类的,不再需要增加标志位,这样就把工厂和产品分开了。


    利用简单工厂和工厂模式封装支付模块

    支付.png

    在下面的demo中只封装了两种支付方式:支付宝和微信

    注意:demo是用Java代码完成的,可对照上面Kotlin代码理解两种语言的写法

    基础产品类:只有一个动作:支付
    import android.app.Activity;
    ​
    /**
     * Author: taonce
     * Date: 2018/11/2
     * Project: 
     * Desc: 支付基类
     */
    ​
    public abstract class BasePay {
     public abstract void pay(Activity activity, String orderString, OnPayCallBack callBack);
    }
    
    回调接口:目前之封装了成功和失败,可拓展
    /**
     * Author: taonce
     * Date: 2018/11/2
     * Project: 
     * Desc: 支付成功或失败的回调
     */
    ​
    public interface OnPayCallBack {
    ​
     void onPaySuccess(String orderId);
    ​
     void onPayFailed();
    }
    
    具体支付类:
    1. 支付宝支付:支付宝支付是通过Handler完成的,直接在pay方法里实现就行了,不依赖其他类
        /**
         * Author: taonce
         * Date: 2018/11/2
         * Project: 
         * Desc: 支付宝支付
         */
        ​
        public class AliPay extends BasePay {
        ​
         private Activity mActivity;
         private OnPayCallBack mCallBack;
        ​
        ​
         @Override
         public void pay(Activity activity, final String orderString, OnPayCallBack onPayCallBack) {
         this.mActivity = activity;
         mCallBack = onPayCallBack;
         Runnable payRunnable = new Runnable() {
         @Override
         public void run() {
         PayTask payTask = new PayTask(mActivity);
         Map<String, String> result = payTask.payV2(orderString, true);
         LogUtil.showLog("taonce", "result = " + result);
        ​
         Message msg = new Message();
         msg.what = 1;
         msg.obj = result;
         mHandler.sendMessage(msg);
         }
         };
        ​
         Thread payThread = new Thread(payRunnable);
         payThread.start();
         }
        ​
         @SuppressLint("HandlerLeak")
         private Handler mHandler = new Handler() {
         @SuppressWarnings("unused")
         public void handleMessage(Message msg) {
         switch (msg.what) {
         case 1: {
         @SuppressWarnings("unchecked")
         PayResult payResult = new PayResult((Map<String, String>) msg.obj);
         /**
         对于支付结果,请商户依赖服务端的异步通知结果。同步通知结果,仅作为支付结束的通知。
         */
         String resultInfo = payResult.getResult();// 同步返回需要验证的信息
         String resultStatus = payResult.getResultStatus();
         LogUtil.showLog("aulton", "result = " + resultInfo);
         // 判断resultStatus 为9000则代表支付成功
         if (TextUtils.equals(resultStatus, "9000")) {
         // 该笔订单是否真实支付成功,需要依赖服务端的异步通知。
         PayinfoBean payInfoBean;
         Gson gson = new Gson();
         payInfoBean = gson.fromJson(resultInfo, PayinfoBean.class);
         String order_id = payInfoBean.alipay_trade_app_pay_response.out_trade_no;
         mCallBack.onPaySuccess(order_id);
         } else {
         // 该笔订单真实的支付结果,需要依赖服务端的异步通知。
         mCallBack.onPayFailed();
    
         }
         break;
         }
         default:
         break;
         }
         }
         };
        }
    
    1. 微信支付:

      微信支付需要使用单例,因为微信依赖其他类,也就是指定的WXPayEntryActivity,支付完回调现在这个类中得知的,我们需要在这个类中判断回调的成功与否。

      先看具体实现类:

    /**
         * Author: taonce
         * Date: 2018/11/2
         * Project: 
         * Desc: 微信支付
         */
        ​
        public class WxPay extends BasePay {
        ​
         private String mPrePayId;
         private OnPayCallBack mCallBack;
         private Activity mActivity;
         private static WxPay mWxPay;
        ​
        ​
         public static WxPay getInstance() {
         if (mWxPay == null) {
         mWxPay = new WxPay();
         }
         return mWxPay;
         }
        ​
         /**
         * 实现支付请求
         * @param activity 当前的activity
         * @param orderString 订单字符串
         * @param callBack 回调
         */
         @Override
         public void pay(Activity activity, String orderString, OnPayCallBack callBack) {
         this.mActivity = activity;
         mCallBack = callBack;
        ​
         Gson gson = new Gson();
         WeiXinBean weiXinBean = gson.fromJson(orderString, WeiXinBean.class);
         if (!CommonUtils.isWeinXinExist(mActivity)) {
         ToastUitl.showShort("未安装微信");
         return;
         }
        ​
         if (weiXinBean == null) {
         ToastUitl.showShort("参数为空");
         return;
         }
        ​
         IWXAPI api;
         api = WXAPIFactory.createWXAPI(mActivity, null);
         PayReq request = new PayReq();
         request.appId = weiXinBean.appid;
         request.nonceStr = weiXinBean.noncestr;
         request.partnerId = String.valueOf(weiXinBean.partnerid);
         request.prepayId = weiXinBean.prepayid;
         mPrePayId = weiXinBean.prepayid;
         request.packageValue = weiXinBean.packageValue;
         request.sign = weiXinBean.sign;
         request.timeStamp = weiXinBean.timestamp;
         api.sendReq(request);
         }
        ​
         /**
         * 根据错误码判断支付成功与否
         * @param errCode 错误码
         */
         public void dealResult(int errCode) {
         if (errCode == 0) {
         // 该笔订单是否真实支付成功,需要依赖服务端的异步通知。
         // 调用服务端接口来获取准确的支付成功信息
         mCallBack.onPaySuccess(mPrePayId);
         } else {
         // 该笔订单真实的支付结果,需要依赖服务端的异步通知。
         mCallBack.onPayFailed();
         }
         }
        }
    

    接着看微信指定类:WXPayEntryActivity

    onResp方法中判断结果,把errCode错误码传给WxPay,在WxPay中的dealResult方法中去处理具体的回调。

    public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler {
        ​
         private static final String TAG = "WXPayEntryActivity";
        ​
         private IWXAPI api;
        ​
         @Override
         public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.pay_result);
         api = WXAPIFactory.createWXAPI(this, null);
         api.handleIntent(getIntent(), this);
         }
        ​
         @Override
         protected void onNewIntent(Intent intent) {
         super.onNewIntent(intent);
         setIntent(intent);
         api.handleIntent(intent, this);
         }
        ​
         @Override
         public void onReq(BaseReq req) {
    
         }
        ​
         @Override
         public void onResp(BaseResp resp) {
         LogUtil.showLog("weixinpay", "transaction =" + resp.transaction);
         if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
         WxPay.getInstance().dealResult(resp.errCode);
         finish();
         }
         }
        }
    
    简单工厂类:

    根据不同的支付方式,创建不同的产品

    /**
     * Author: taonce
     * Date: 2018/11/2
     * Project: 
     * Desc: 支付的工厂类
     */
    ​
    public class PayFactory {
     public static BasePay createPay(String type) {
     BasePay basePay;
     switch (type) {
     case "ali":
     basePay = new AliPay();
     break;
     case "wx":
     basePay = WxPay.getInstance();
     break;
     default:
     basePay = WxPay.getInstance();
     break;
     }
     return basePay;
     }
    }
    

    工厂类:通过反射来获得具体的支付类对象

    工厂基类:

    public abstract class BaseFactory {
     public abstract <T extends BasePay> T createPay(Class<T> tClass);
    }
    

    具体工厂类:

    public class PayFactory extends BaseFactory {
    ​
     @Override
     public <T extends BasePay> T createPay(Class<T> tClass) {
     BasePay basePay = null;
     String className = tClass.getName();
     try {
     basePay = (BasePay) Class.forName(className).newInstance();
     } catch (InstantiationException e) {
     e.printStackTrace();
     } catch (IllegalAccessException e) {
     e.printStackTrace();
     } catch (ClassNotFoundException e) {
     e.printStackTrace();
     }
     return (T) basePay;
     }
    }
    

    调用:

    简单工厂模式调用:

    只需要传入不同的工厂类型就行了,以后如果要添加第三种第四种,只需在工厂类中加入一种类型就行。

    PayFactory.createPay("ali").pay(this, paramStr, new OnPayCallBack() {
     @Override
     public void onPaySuccess(String orderId) {
     LogUtil.showLog("pay success");
     }
    ​
     @Override
     public void onPayFailed() {
    ​
     }
     });
    

    工厂模式调用:

    工厂模式的调用同样也是很简单的,传参传入类名.class就行了。

    PayFactory payFactory = new PayFactory();
     payFactory.createPay(AliPay.class).pay(this, paramStr, new OnPayCallBack() {
     @Override
     public void onPaySuccess(String orderId) {
    
     }
    ​
     @Override
     public void onPayFailed() {
    ​
     }
     });
    

    如果大家对支付有兴趣或者有业务需要去了解,那么这里告诫大家一定要把官方支付流程图看懂,尤其是支付宝的流程,在不懂的情况下去写支付,那么接下来肯定会有很多的坑等着你的。


    写在最后

    每个人不是天生就强大,你若不努力,如何证明自己,加油!

    Thank You!

    --Taonce

    如果你觉得这篇文章对你有所帮助,那么就动动小手指,长按下方的二维码,关注一波吧~~非常期待大家的加入

    专注Kotlin知识的公众号

    相关文章

      网友评论

        本文标题:基于工厂模式的支付宝和微信支付封装(Kotlin、Java)

        本文链接:https://www.haomeiwen.com/subject/djnexqtx.html