package com.yidianling.ydl_pay.common import android.annotation.SuppressLint import android.app.Activity import android.app.Dialog import android.content.Context import android.graphics.Point import android.os.Bundle import androidx.viewpager.widget.PagerAdapter import androidx.appcompat.app.AlertDialog import android.text.TextUtils import android.view.* import android.widget.LinearLayout import com.alipay.sdk.app.PayTask import com.tencent.mm.opensdk.modelpay.PayReq import com.tencent.mm.opensdk.openapi.WXAPIFactory import com.ydl.ydlcommon.utils.log.AliYunLogConfig import com.ydl.ydlcommon.utils.log.AliYunRichLogsHelper import com.yidianling.common.tools.RxImageTool import com.yidianling.ydl_pay.R import com.yidianling.ydl_pay.common.bean.* import com.yidianling.ydl_pay.common.bean.params.* import com.yidianling.ydl_pay.common.http.HttpUtils import com.yidianling.ydl_pay.common.http.utils.NetUtils import com.yidianling.ydl_pay.common.http.utils.RxDeviceTool import com.yidianling.ydl_pay.common.toast.ToastHelper import com.yidianling.ydl_pay.common.widget.PayCouponView import com.yidianling.ydl_pay.common.widget.PayInfoDetailView import de.greenrobot.event.EventBus import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.schedulers.Schedulers import kotlinx.android.synthetic.main.pay_dialog_common_pay.* import java.util.* /** * @author jiucheng * @描述:支付的弹窗 * @Copyright Copyright (c) 2018 * @Company 壹点灵 * @date 2019/4/3 */ class CommonPayDialog : Dialog { private var goodsId: String? = null private lateinit var activity: Activity private var viewList = ArrayList<LinearLayout>() private var couponListBean: AllCouponListBean? = null //选中的优惠券 private var selectedCouponBean: CommonCouponBean? = null private var payCouponView: PayCouponView? = null private var detailView: PayInfoDetailView? = null private var listener: OnPayResultListener? = null private var payMoney: Float? = null private var thankPayId: String? = null //加载中弹窗 private var dialog: AlertDialog? = null private var dialogContentView: View? = null /** * 支付方式 * 1024.微信支付 1025.支付宝支付 */ private var payWay = 0 /** * 支付的业务类型 * [TYPE_COURSE] 课程支付 * [TYPE_CONFIDE] 倾诉支付 * [TYPE_TEST] 测评支付 * [TYPE_CONSULTANT] 咨询支付 * [TYPE_TRENDS_THANKS] 动态打赏 */ private var payBusinessType = 0 companion object { /** * 课程业务 */ const val TYPE_COURSE = 1 /** * 倾诉 */ const val TYPE_CONFIDE = 2 /** * 测评 */ const val TYPE_TEST = 3 /** * 咨询 */ const val TYPE_CONSULTANT = 4 /** * 动态打赏 */ const val TYPE_TRENDS_THANKS = 5 /** * 支付方式 * 1024.微信支付 1025.支付宝支付 */ private const val PAY_WECHAT = 1024 private const val PAY_ALI = 1025 } private constructor(context: Context) : super(context, R.style.pay_common_dialog_style) private constructor(build: Build) : this(build.mActivity) { this.goodsId = build.goodsId this.activity = build.mActivity this.listener = build.listener this.payBusinessType = build.payType this.payMoney = build.payMoney this.thankPayId = build.payId } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.pay_dialog_common_pay) window.attributes.width = WindowManager.LayoutParams.MATCH_PARENT window.attributes.height = WindowManager.LayoutParams.WRAP_CONTENT window.setGravity(Gravity.BOTTOM) setCanceledOnTouchOutside(true) EventBus.getDefault().register(this) if (payBusinessType == TYPE_TRENDS_THANKS) { var parmas = view_pager.layoutParams parmas.width = ViewGroup.LayoutParams.MATCH_PARENT parmas.height = RxImageTool.dp2px(371f) view_pager.layoutParams = parmas getMyBalance() } else { getOrderInfo() } } private fun initThanksPayInfoDetailView(bean: OrderInfoBean) { view_pager.setScanScroll(false) detailView = PayInfoDetailView( activity, object : PayInfoDetailView.OnCouponDetailClickListener { override fun selectCoupon(couponId: String) { } override fun ensurePay( payWay: Int, payMoney: Float, useMoneyType: Int, code: String, couponType: String ) { //感谢的时候比较暴力:payid是外部传过来的、余额一定会被扣掉 if (payBusinessType == TYPE_TRENDS_THANKS) { showProgressDialog() if (payMoney > 0) { when (payWay) { PAY_WECHAT -> { getWeiXinPayOrderId( thankPayId!!, if (useMoneyType == 2) 1 else 0, bean.merchantType ) } else -> { getAliPayOrderId( thankPayId!!, if (useMoneyType == 2) 1 else 0 ) } } } else { //余额支付 payByCharge() } } } }) if (bean.maxCoupon != null) { //最优的优惠券id为0时,把最优优惠券对象置为null,因为正常的可用的优惠券id一定不为0,这里接口为了前端页面展示,返回的maxCoupon对象不为null, //但maxCoupon的属性均为null或初始值 if (TextUtils.equals(bean.maxCoupon.id, "0")) { bean.maxCoupon = null } } detailView!!.setData(bean, payBusinessType) viewList.add(detailView!!) view_pager.adapter = ViewPagerAdapter() view_pager.currentItem = 0 } override fun show() { super.show() showProgressDialog() } /** * 获取下单信息 */ @SuppressLint("CheckResult") private fun getOrderInfo() { if (!NetUtils.isConnected(activity)) { ToastHelper.show(activity, activity.getString(R.string.net_error)) AliYunRichLogsHelper.getInstance().sendRichLog(AliYunLogConfig.PAY, "获取下单信息,无网络") // progress.visibility = View.GONE dismissProgressDialog() return } val bean = OrderRequestBean() bean.goodsId = goodsId bean.orderType = payBusinessType.toString() HttpUtils.getOrderInfo(bean) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ dismissProgressDialog() if (it.code == 200) { if (it.data != null) { progress_layout.visibility = View.GONE view_pager.visibility = View.VISIBLE AliYunRichLogsHelper.getInstance().sendRichLog(AliYunLogConfig.PAY, "获取下单信息,成功") updateDataOnView(it.data) } else { AliYunRichLogsHelper.getInstance() .sendRichLog(AliYunLogConfig.PAY, "获取下单信息data=null msg: ${it.msg}") ToastHelper.show(activity, it.msg) // progress.visibility = View.GONE } } else { AliYunRichLogsHelper.getInstance() .sendRichLog(AliYunLogConfig.PAY, "获取下单信息code!=200 msg: ${it.msg}") ToastHelper.show(activity, it.msg) // progress.visibility = View.GONE } }, { e -> dismissProgressDialog() // progress.visibility = View.GONE ToastHelper.show(activity, e.message!!) AliYunRichLogsHelper.getInstance() .sendRichLog(AliYunLogConfig.PAY, "获取下单信息error e:${e.message}") }) } @SuppressLint("CheckResult") private fun getMyBalance() { HttpUtils.getMyBalance(BalanceParam()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ dismissProgressDialog() if (it.status == 200) { if (it.data != null) { progress_layout.visibility = View.GONE view_pager.visibility = View.VISIBLE val bean = OrderInfoBean() bean.availableMoney = it.data.balance bean.applyFee = payMoney!! bean.isShowCoupon = false initThanksPayInfoDetailView(bean) } else { ToastHelper.show(activity, it.msg) } } else { ToastHelper.show(activity, it.msg) } }, { dismissProgressDialog() ToastHelper.show(activity, it.message!!) }) } private fun updateDataOnView(bean: OrderInfoBean) { view_pager.setScanScroll(false) detailView = PayInfoDetailView( activity, object : PayInfoDetailView.OnCouponDetailClickListener { override fun selectCoupon(couponId: String) { if (couponListBean != null) { view_pager.currentItem = 1 } else { getAllCoupon() } } override fun ensurePay( payWay: Int, payMoney: Float, useMoneyType: Int, code: String, couponType: String ) { createOrder(payWay, payMoney, useMoneyType, code, couponType) } }) if (bean.maxCoupon != null) { //最优的优惠券id为0时,把最优优惠券对象置为null,因为正常的可用的优惠券id一定不为0,这里接口为了前端页面展示,返回的maxCoupon对象不为null, //但maxCoupon的属性均为null或初始值 if (TextUtils.equals(bean.maxCoupon.id, "0")) { bean.maxCoupon = null } } detailView!!.setData(bean, payBusinessType) payCouponView = PayCouponView(activity) payCouponView!!.setListener(object : PayCouponView.OnCouponClickListener { override fun onBackClick(selectedCouponBean: CommonCouponBean?) { this@CommonPayDialog.selectedCouponBean = selectedCouponBean view_pager.currentItem = 0 detailView!!.setCouponData(selectedCouponBean) } override fun onSelectCoupon(selectedCouponBean: CommonCouponBean?) { this@CommonPayDialog.selectedCouponBean = selectedCouponBean view_pager.currentItem = 0 detailView!!.setCouponData(selectedCouponBean) } }) viewList.add(detailView!!) viewList.add(payCouponView!!) view_pager.adapter = ViewPagerAdapter() view_pager.currentItem = 0 } /** 获取所有选择优惠券 */ @SuppressLint("CheckResult") private fun getAllCoupon() { if (!NetUtils.isConnected(activity)) { ToastHelper.show(activity, activity.getString(R.string.net_error)) return } val bean = GetAllCouponRequestBean() val packageName = activity.packageName if (packageName.endsWith("zj.android")) {//专家版 bean.applyEnds = "5" } else { bean.applyEnds = "3" } bean.goodsId = goodsId if (payBusinessType == TYPE_COURSE) { bean.services = "3" } showProgressDialog() HttpUtils.selectCoupon(bean) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ dismissProgressDialog() if (it.code == 200) { if (it.data != null) { couponListBean = it.data updateSelectCouponView() } else { ToastHelper.show(activity, it.msg) } } else { ToastHelper.show(activity, it.msg) } }, { e -> dismissProgressDialog() ToastHelper.show(activity, e.message!!) }) } /** * 更新选择优惠券的页面 */ private fun updateSelectCouponView() { detailView!!.setAvailableCount(couponListBean!!.availableCount) payCouponView!!.setData( couponListBean!!, payBusinessType == TYPE_COURSE, selectedCouponBean, goodsId!! ) view_pager.currentItem = 1 } /** * 创建订单 * @param payWay 支付方式 1024.微信支付 1025.支付宝支付 * @param payMoney 还需支付金额 * @param useMoneyType 支付类型 1余额,2三方支付,3混合 * */ @SuppressLint("CheckResult") private fun createOrder( payWay: Int, payMoney: Float, useMoneyType: Int, code: String, couponType: String ) { if (!NetUtils.isConnected(activity)) { ToastHelper.show(activity, activity.getString(R.string.net_error)) return } this.payWay = payWay val bean = CreateOrderRequestBean() bean.goodsId = goodsId if (TextUtils.isEmpty(code)) { bean.code = null } else { bean.code = code } if (TextUtils.isEmpty(couponType)) { bean.couponType = null } else { bean.couponType = couponType } bean.orderType = payBusinessType.toString() bean.payType = useMoneyType.toString() AliYunRichLogsHelper.getInstance().sendRichLog( AliYunLogConfig.PAY, "创建订单,支付方式payWay:$payWay---payMoney:$payMoney----useMoneyType:$useMoneyType" ) showProgressDialog() HttpUtils.createOrder(bean) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ if (it.code == 200) { if (it.data != null) { if (it.data.payStatus) { AliYunRichLogsHelper.getInstance().sendRichLog( AliYunLogConfig.PAY, "创建订单,支付成功" ) dismissProgressDialog() ToastHelper.show(activity, "支付成功") if (listener != null) { listener!!.onSuccesed() } dismiss() } else { when (payWay) { PAY_WECHAT -> { getWeiXinPayOrderId( it.data.payId, if (useMoneyType == 2) 1 else 0, it.data.merchantType ) } else -> { getAliPayOrderId(it.data.payId, if (useMoneyType == 2) 1 else 0) } } } } else { dismissProgressDialog() ToastHelper.show(activity, it.msg) } } else { dismissProgressDialog() ToastHelper.show(activity, it.msg) } }, { e -> dismissProgressDialog() ToastHelper.show(activity, e.message!!) }) } /** * 支付宝支付 * */ @SuppressLint("CheckResult") private fun getAliPayOrderId(payId: String, isThreePay: Int) { if (!NetUtils.isConnected(activity)) { AliYunRichLogsHelper.getInstance().sendRichLog( AliYunLogConfig.PAY, "支付宝支付:无网络" ) activity.runOnUiThread { ToastHelper.show(activity, activity.getString(R.string.net_error)) } return } var bean = AliPayParam(payId, isThreePay) HttpUtils.getAliPayOrderId(bean) .subscribeOn(Schedulers.io()) .subscribe({ if (it.data != null) { AliYunRichLogsHelper.getInstance().sendRichLog( AliYunLogConfig.PAY, "支付宝支付:无网络" ) aliPay(it.data.aliSign) } else { AliYunRichLogsHelper.getInstance().sendRichLog( AliYunLogConfig.PAY, "支付宝支付:data = null msg: ${it.msg} " ) activity.runOnUiThread { ToastHelper.show(activity, it.msg) } dismissProgressDialog() } }, { AliYunRichLogsHelper.getInstance().sendRichLog( AliYunLogConfig.PAY, "支付宝支付:error message: ${it.message} localizedMessage: ${it.localizedMessage}" ) activity.runOnUiThread { ToastHelper.show(activity, it.localizedMessage) } dismissProgressDialog() }) } private fun aliPay(aliSign: String) { val alipay = PayTask(activity) val result = alipay.payV2(aliSign, true) val payResult = PayResult(result) if ("9000" == payResult.resultStatus) { AliYunRichLogsHelper.getInstance().sendRichLog( AliYunLogConfig.PAY, "支付宝支付:支付成功" ) activity.runOnUiThread { ToastHelper.show(activity, "支付成功") listener!!.onSuccesed() dismiss() } dismissProgressDialog() } else { AliYunRichLogsHelper.getInstance().sendRichLog( AliYunLogConfig.PAY, "支付宝支付:resultStatus != 9000 memo${payResult.memo} " ) dismissProgressDialog() activity.runOnUiThread { ToastHelper.show(activity, payResult.memo) } } } /** * 微信支付 */ @SuppressLint("CheckResult") private fun getWeiXinPayOrderId(payId: String, isThreePay: Int, merchantType: String) { if (!NetUtils.isConnected(activity)) { AliYunRichLogsHelper.getInstance().sendRichLog( AliYunLogConfig.PAY, "微信支付,无网络" ) activity.runOnUiThread { ToastHelper.show(activity, activity.getString(R.string.net_error)) } return } var bean = WxPayParam(payId, isThreePay, merchantType) HttpUtils.wxPay(bean) .subscribeOn(Schedulers.io()) .subscribe({ if (it.data != null) { weixinPay(it.data.option) } else { AliYunRichLogsHelper.getInstance().sendRichLog( AliYunLogConfig.PAY, "微信支付data=null ${it.msg}" ) activity.runOnUiThread { ToastHelper.show(activity, it.msg) } dismissProgressDialog() } }, { AliYunRichLogsHelper.getInstance().sendRichLog( AliYunLogConfig.PAY, "微信支付,异常:message:${it.message}----localizedMessage:${it.localizedMessage}" ) activity.runOnUiThread { ToastHelper.show(activity, it.localizedMessage) } dismissProgressDialog() }) } private fun weixinPay(option: CommonWXPayBean.WXOption) { val api = WXAPIFactory.createWXAPI(context, null) if (api.wxAppSupportAPI < com.tencent.mm.opensdk.constants.Build.PAY_SUPPORTED_SDK_INT) { return } api.registerApp(option.appid) val request = PayReq() request.appId = option.appid request.partnerId = option.partnerid request.prepayId = option.prepayid request.packageValue = "Sign=WXPay" request.nonceStr = option.noncestr request.timeStamp = option.timestamp request.sign = option.sign api.sendReq(request) } @SuppressLint("CheckResult") private fun payByCharge() { var bean = ChargePayParam() bean.payId = thankPayId HttpUtils.payByCharge(bean) .subscribeOn(Schedulers.io()) .subscribe({ dismissProgressDialog() if (it.data != null && it.code == 0) { AliYunRichLogsHelper.getInstance().sendRichLog( AliYunLogConfig.PAY, "余额支付:成功" ) activity.runOnUiThread { listener!!.onSuccesed() dismiss() } } else { AliYunRichLogsHelper.getInstance().sendRichLog( AliYunLogConfig.PAY, "余额支付:失败 msg:${it.msg}" ) activity.runOnUiThread { ToastHelper.show(activity, it.msg) } } }, { AliYunRichLogsHelper.getInstance().sendRichLog( AliYunLogConfig.PAY, "余额支付:ERROR message:${it.message} localizedMessage: ${it.localizedMessage}" ) activity.runOnUiThread { ToastHelper.show(activity, it.localizedMessage) } dismissProgressDialog() }) } fun onEvent(event: WeiXinPayStatusEvent) { dismissProgressDialog() if (event.success) { AliYunRichLogsHelper.getInstance().sendRichLog( AliYunLogConfig.PAY, "微信支付成功" ) ToastHelper.show(activity, "支付成功") listener!!.onSuccesed() dismiss() } else { AliYunRichLogsHelper.getInstance().sendRichLog( AliYunLogConfig.PAY, "微信支付:失败 msg:${event.msg}" ) if (!TextUtils.isEmpty(event.msg)) { ToastHelper.show(activity, event.msg!!) } listener!!.onFailed() } } /** * 显示加载中弹窗 */ private fun showProgressDialog() { if (dialog != null && dialog!!.isShowing) { return } if (dialog == null) { dialog = AlertDialog.Builder(activity) .create() } if (dialogContentView == null) { dialogContentView = LayoutInflater.from(activity).inflate(R.layout.pay_loading_dialog, null) } dialog?.show() dialog?.window?.setContentView(dialogContentView) dialog?.window?.setGravity(Gravity.CENTER) val p = dialog?.window!!.attributes //获取对话框当前的参数值 var point = Point() activity.windowManager.defaultDisplay.getSize(point)// 获取屏幕宽、高用 p.height = (point.y * 0.2).toInt() p.width = (point.x * 0.35).toInt() dialog?.window!!.attributes = p //设置生效 } /** * 隐藏加载中弹窗 */ private fun dismissProgressDialog() { activity.runOnUiThread { if (dialog != null && dialog!!.isShowing) { dialog!!.dismiss() } } } internal inner class ViewPagerAdapter : PagerAdapter() { override fun getCount(): Int { return viewList.size } override fun isViewFromObject(view: View, `object`: Any): Boolean { return view === `object` } override fun instantiateItem(container: ViewGroup, position: Int): Any { val view = viewList[position] container.addView(view) return view } override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { container.removeView(`object` as View) } } /** * ============================= * ============================= * ===== [Build] ====== * ============================= * ============================= */ class Build(internal var mActivity: Activity) { internal var goodsId: String? = null internal var payId: String? = null internal var payMoney: Float? = null private lateinit var uid: String private lateinit var token: String private lateinit var ffrom: String internal lateinit var listener: OnPayResultListener private var isTestEnvironment = true /** * 支付的业务类型[CommonPayDialog.payBusinessType] */ internal var payType = 0 /** * 课程id(如果是其他业务线支付时,请将[payBusinessType]设置为对应的[CommonPayDialog.payBusinessType]类型) */ fun setCourseId(courseId: String): Build { this.goodsId = courseId payType = TYPE_COURSE return this@Build } fun setPayId(payId: String): Build { this.payId = payId payType = TYPE_TRENDS_THANKS return this@Build } fun setPayMoney(money: Float): Build { this.payMoney = money return this@Build } /** * 商品id(调用此方法请务必再调用[setBusinessType]方法) */ fun setGoodsId(goodsId: String): Build { this.goodsId = goodsId return this@Build } /** * 业务类型 */ fun setBusinessType(payType: Int): Build { this.payType = payType return this@Build } /** * uid */ fun setUid(uid: String): Build { this.uid = uid return this@Build } /** * token */ fun setToken(token: String): Build { this.token = token return this@Build } /** * ffrom */ fun setFfrom(ffrom: String): Build { this.ffrom = ffrom return this@Build } /** * listener 回调 */ fun setListener(listener: OnPayResultListener): Build { this.listener = listener return this@Build } /** * [setIsTestEnvironment] true 测试环境 false 线上环境 * 默认测试环境 * release包无效 */ fun setIsTestEnvironment(isTestEnvironment: Boolean): Build { this.isTestEnvironment = isTestEnvironment return this@Build } fun build(): CommonPayDialog { initHttpHeadConfig() return CommonPayDialog(this) } /** * 初始化网络的的参数 */ private fun initHttpHeadConfig() { RxDeviceTool.initContext(mActivity) // HttpConfig.version = RxDeviceTool.getAppVersionName(mActivity) // HttpConfig.osBuild = RxDeviceTool.getBuildMANUFACTURER() + "," + RxDeviceTool.getBuildBrandModel() + "," + RxDeviceTool.getOsBuileVersion() + "," + RxDeviceTool.getAppVersionName(mActivity) // HttpConfig.uid = uid // HttpConfig.accessToken = token // HttpConfig.ffrom = ffrom // HttpConfig.isTestEnvironment = isTestEnvironment // val packageName = mActivity.packageName // if (packageName.endsWith("zj.android")) {//专家版 // HttpConfig.isFromApp = "2" // } else { // HttpConfig.isFromApp = "1" // } // if (BuildConfig.DEBUG) { // if (TextUtils.isEmpty(HttpConfig.ffrom)) { // ToastHelper.show(mActivity, "请先调用--setFfrom()--方法") // } // if (TextUtils.isEmpty(HttpConfig.uid)) { // ToastHelper.show(mActivity, "请先调用--setUid()--方法") // } // if (TextUtils.isEmpty(HttpConfig.accessToken)) { // ToastHelper.show(mActivity, "请先调用--setToken()--方法") // } // } // PayRetrofitUtils.setConfig(HttpConfig) } } interface OnPayResultListener { fun onSuccesed() fun onFailed() } }