美文网首页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