Commit a9a7a92e by 严久程

课程模块、支付模块

parent 1e8f36a5
......@@ -75,6 +75,7 @@ dependencies {
api project(":ydl-webview")
api project(":ydl-platform")
api project(":ydl-media")
api project(":ydl-pay")
} else {
//发布时使用
compileOnly rootProject.ext.dependencies["ydl-m-user-api"]
......
......@@ -12,7 +12,6 @@ import butterknife.BindView;
import butterknife.ButterKnife;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.ydl.ydlcommon.base.BaseActivity;
import com.yidianling.course.courseNew.home.CourseHomeFragment;
import com.yidianling.course.courseNew.mine.MyCourseActivity;
import com.yidianling.course.router.CourseIn;
import com.yidianling.course.widget.SearchBarView;
......@@ -25,8 +24,6 @@ public class CourseActivity extends BaseActivity {
@BindView(R2.id.content)
FrameLayout content;
@BindView(R2.id.img_music)
ImageView imgMusic;
@BindView(R2.id.iv_back)
ImageView ivBack;
@BindView(R2.id.tv_left_menu)
......@@ -79,15 +76,6 @@ public class CourseActivity extends BaseActivity {
finish();
}
});
imgMusic.setOnClickListener(v -> {
if (YDLMusicHelper.INSTANCE.isCoursePlaying()) {
//课程播放页
YDLMusicHelper.INSTANCE.startCoursePlayActivity(getMContext(), 1, 0, "", false);
} else {
imgMusic.setVisibility(View.GONE);
}
});
leftMenu.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
......@@ -104,23 +92,19 @@ public class CourseActivity extends BaseActivity {
* 初始化tab
*/
private void initTags() {
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.content);
if (fragment == null) {
fragment = new CourseHomeFragment();
getSupportFragmentManager().beginTransaction()
.add(R.id.content, fragment)
.commit();
}
//todo 引用flutter的课程频道页面
// Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.content);
// if (fragment == null) {
// fragment = new CourseHomeFragment();
// getSupportFragmentManager().beginTransaction()
// .add(R.id.content, fragment)
// .commit();
// }
}
@Override
protected void onResume() {
super.onResume();
if (YDLMusicHelper.INSTANCE.isCoursePlaying()) {
imgMusic.setVisibility(View.VISIBLE);
} else {
imgMusic.setVisibility(View.GONE);
}
}
public void disPro() {
......
......@@ -80,12 +80,7 @@ public class CourseListItemView extends ConstraintLayout implements View.OnClick
}
tvCourseItemComment.setOnClickListener(v -> CourseCommentActivity.Companion.startActivity((Activity) context, mCourse.id + ""));
tvCourseItemFirst.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
YDLRouterManager.Companion.router(mCourse.chatLinkUri);
}
});
tvCourseItemFirst.setOnClickListener(v -> YDLRouterManager.Companion.router(mCourse.chatLinkUri));
}
@Override
......
......@@ -24,10 +24,12 @@ import com.ydl.media.audio.utils.PlayProgressUtil
import com.ydl.media.view.PlayTypeEnum
import com.ydl.media.view.PlayerFloatHelper
import com.ydl.ydl_image.module.GlideApp
import com.ydl.ydl_pay.CommonPayDialog
import com.ydl.ydl_router.manager.YDLRouterManager
import com.ydl.ydlcommon.adapter.CommonRecyclerAdapter
import com.ydl.ydlcommon.base.BaseActivity
import com.ydl.ydlcommon.bean.ShareData
import com.ydl.ydlcommon.data.PlatformDataManager
import com.ydl.ydlcommon.router.IYDLRouterConstant
import com.ydl.ydlcommon.router.YdlCommonRouterManager
import com.ydl.ydlcommon.utils.ScreenUtil
......@@ -39,6 +41,7 @@ import com.ydl.ydlcommon.view.dialog.YDLShareDialog
import com.yidianling.common.tools.RxImageTool
import com.yidianling.common.tools.RxNetTool
import com.yidianling.common.tools.ToastUtil
import com.yidianling.course.BuildConfig
import com.yidianling.course.R
import com.yidianling.course.bean.CourseMediaBean
import com.yidianling.course.bean.CourseMediaDetailBean
......@@ -497,7 +500,7 @@ class CoursePlayActivity : BaseActivity() {
.setCourseId(course_id.toString())
.setToken(userInfo.token)
.setUid(userInfo.userId)
.setFfrom(YdlDataManager.getRam().getChannelName())
.setFfrom(PlatformDataManager.getRam().getChannelName())
.setListener(object : CommonPayDialog.OnPayResultListener {
override fun onSuccesed() {
//刷新界面
......
......@@ -4,18 +4,15 @@ import android.annotation.SuppressLint
import android.text.TextUtils
import android.view.ViewGroup
import android.widget.RelativeLayout
import com.ydl.media.audio.AudioPlayer
import com.ydl.media.audio.model.Music
import com.ydl.ydlcommon.view.dialog.CommonDialog
import com.yidianling.common.tools.RxDeviceTool
import com.yidianling.common.tools.RxNetTool
import com.yidianling.course.bean.CourseExtraBean
import com.yidianling.course.bean.CourseMediaBean
import com.yidianling.course.listener.HPlayStatusListener
import com.yidianling.course.widget.HPlayView
import com.yidianling.ydlcommon.bean.CourseExtraBean
import com.yidianling.ydlcommon.bean.CourseMediaBean
import com.yidianling.ydlcommon.dialog.CommonDialog
import com.yidianling.ydlcommon.player.MusicInfoBean
import com.yidianling.ydlcommon.player.YDLMusicHelper
import com.yidianling.ydlcommon.player.player.HPlayStatusListener
import com.yidianling.ydlcommon.player.view.HPlayView
/**
......@@ -69,12 +66,8 @@ class CoursePlayItemViewAudio : RelativeLayout, PlayViewInterface {
//设置监听事件
fun setListener() {
playView?.listener = object : HPlayStatusListener {
override fun isCanPlay(data: MusicInfoBean?): Boolean {
override fun isCanPlay(data: Music?): Boolean {
var canPlay = false
//判断当前课程是否试听
if (data?.isTestPlay == true) {
canPlay = true
} else {
//非试听
if (courseExtra!!.isBuy) {
//已购买
......@@ -95,11 +88,10 @@ class CoursePlayItemViewAudio : RelativeLayout, PlayViewInterface {
.setCancelAble(false)
.show()
}
}
return canPlay
}
override fun onPrepared(data: MusicInfoBean?, index: Int) {
override fun onPrepared(data: Music?, index: Int) {
//更新播放列表的状态
activity!!.updatePlayingListStatus(index)
}
......@@ -118,7 +110,7 @@ class CoursePlayItemViewAudio : RelativeLayout, PlayViewInterface {
this.courseExtra = courseExtra
currentIndex = index
YDLMusicHelper.course_id = courseExtra.id.toInt()
// YDLMusicHelper.course_id = courseExtra.id.toInt()
if (courseExtra.isBuy) {
playView?.setAutoNext(true)
......@@ -131,12 +123,12 @@ class CoursePlayItemViewAudio : RelativeLayout, PlayViewInterface {
playView!!.setData(stringToMusicPlayerList(playList))
if (playView?.control?.isPlaying() == true) {
if (AudioPlayer.get().isPlaying) {
hasEnsureNetStatus = true
}
if (RxNetTool.isWifi(activity!!)) {
if (playView?.control?.isPlaying() == true && (from == 1 || from == 2)) {
if (AudioPlayer.get().isPlaying && (from == 1 || from == 2)) {
if (TextUtils.equals(playView?.getCurrentUrl(), list[currentIndex].url)) {
playView?.updateView(currentIndex)
} else {
......@@ -147,7 +139,7 @@ class CoursePlayItemViewAudio : RelativeLayout, PlayViewInterface {
}
} else {
if (hasEnsureNetStatus) {
if (playView?.control?.isPlaying() == true && (from == 1 || from == 2)) {
if (AudioPlayer.get().isPlaying && (from == 1 || from == 2)) {
if (TextUtils.equals(playView?.getCurrentUrl(), list[currentIndex].url)) {
playView?.updateView(currentIndex)
} else {
......@@ -159,7 +151,7 @@ class CoursePlayItemViewAudio : RelativeLayout, PlayViewInterface {
} else {
playView?.showNetNotice {
hasEnsureNetStatus = true
if (playView?.control?.isPlaying() == true && (from == 1 || from == 2)) {
if (AudioPlayer.get().isPlaying && (from == 1 || from == 2)) {
if (TextUtils.equals(playView?.getCurrentUrl(), list[currentIndex].url)) {
playView?.updateView(currentIndex)
} else {
......@@ -174,15 +166,15 @@ class CoursePlayItemViewAudio : RelativeLayout, PlayViewInterface {
}
//将列表转为播放器可用列表
private fun stringToMusicPlayerList(list: List<CourseMediaBean>): ArrayList<MusicInfoBean> {
var nlist = ArrayList<MusicInfoBean>()
private fun stringToMusicPlayerList(list: List<CourseMediaBean>): ArrayList<Music> {
var nlist = ArrayList<Music>()
try {
for (i in list.indices) {
var be = MusicInfoBean()
be.url = list[i].url
be.pic = courseExtra!!.pic
be.isTestPlay = !courseExtra!!.isBuy
var be = Music()
be.path = list[i].url
be.coverPath = courseExtra!!.pic
be.title = list[i].title
be.artist = list[i].doctorName
nlist.add(be)
}
} catch (e: Exception) {
......@@ -193,10 +185,10 @@ class CoursePlayItemViewAudio : RelativeLayout, PlayViewInterface {
override fun onDestroy() {
//释放播放器
if (playView?.control?.isPlaying() != true) {
if (AudioPlayer.get().isPlaying) {
playView?.onDestroy()
playView = null
YDLMusicHelper.stop()
AudioPlayer.get().stopPlayer()
} else {
playView?.onDestroy()
playView = null
......
......@@ -57,10 +57,10 @@ class CourseSearchAdapterWrapper(
var view:View? = null
return when (viewType) {
TYPE_FOOTER_LOADING -> {
FooterHolder(mInflater!!.inflate(R.layout.footer, parent, false), TYPE_FOOTER_LOADING)
FooterHolder(mInflater!!.inflate(R.layout.course_footer, parent, false), TYPE_FOOTER_LOADING)
}
TYPE_FOOTER_NOMORE -> {
FooterHolder(mInflater!!.inflate(R.layout.footer, parent, false), TYPE_FOOTER_NOMORE)
FooterHolder(mInflater!!.inflate(R.layout.course_footer, parent, false), TYPE_FOOTER_NOMORE)
}
else -> {
mAdapter.onCreateViewHolder(parent, viewType)
......
package com.yidianling.course.listener
import com.ydl.media.audio.model.Music
/**
* 播放状态监听起
* Created by hgw on 2018/4/28.
*/
interface HPlayStatusListener{
//判断是否可以播放
fun isCanPlay(data : Music?):Boolean
//音频初始化完成
fun onPrepared(data : Music?, index:Int=0)
}
\ No newline at end of file
package com.yidianling.course.router
import android.app.Activity
import android.content.Intent
import com.alibaba.android.arouter.launcher.ARouter
import com.ydl.media.audio.AudioPlayer
import com.yidianling.course.courseNew.CourseTopicActivity
import com.yidianling.router.course.ICourseRouter
import com.yidianling.ydlcommon.player.YDLMusicHelper
/**
* Created by hgw on 2018/5/3.
......@@ -11,25 +13,30 @@ import com.yidianling.ydlcommon.player.YDLMusicHelper
class CourseRouterImp : ICourseRouter{
override fun closePlayer() {
if (YDLMusicHelper.isCoursePlaying()) {
YDLMusicHelper.stop()
if (AudioPlayer.get().isPlaying) {
AudioPlayer.get().stopPlayer()
}
}
override fun isPlaying(): Boolean {
return YDLMusicHelper.isPlaying()
return AudioPlayer.get().isPlaying
}
override fun play(){
YDLMusicHelper.replay()
AudioPlayer.get().play()
}
override fun pause(){
YDLMusicHelper.pause()
AudioPlayer.get().playPause()
}
override fun startCoursePlayPage(activity: Activity, from: Int) {
YDLMusicHelper.startCoursePlayActivity(activity,from)
ARouter.getInstance()
.build("/course/play")
.withInt("from", from)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.withBoolean("isFromFloatView", false)
.navigation()
}
override fun courseTopic(activity: Activity, id: String){
......
......@@ -11,7 +11,7 @@ import android.widget.LinearLayout
import com.yidianling.common.tools.RxImageTool
import com.yidianling.course.R
import com.yidianling.course.bean.CourseCouponBean
import kotlinx.android.synthetic.main.view_course_coupon_detail.view.*
import kotlinx.android.synthetic.main.course_view_course_coupon_detail.view.*
import java.lang.Float
import java.math.BigDecimal
......@@ -33,8 +33,8 @@ class CourseCouponDetailView : LinearLayout {
val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, RxImageTool.dp2px(90f))
params.bottomMargin = RxImageTool.dp2px(10f)
layoutParams = params
setBackgroundResource(R.drawable.img_course_coupon_detail_bg)
View.inflate(context, R.layout.view_course_coupon_detail, this)
setBackgroundResource(R.drawable.course_img_course_coupon_detail_bg)
View.inflate(context, R.layout.course_view_course_coupon_detail, this)
}
......
......@@ -11,10 +11,9 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.request.RequestOptions
import com.ydl.ydl_image.module.GlideApp
import com.ydl.ydl_image.transform.GlideRoundTopTransform
import com.yidianling.common.tools.RxImageTool
import com.yidianling.course.R
import com.yidianling.course.bean.PostersShareBean
import kotlinx.android.synthetic.main.view_course_poster_template.view.*
import kotlinx.android.synthetic.main.course_view_course_poster_template.view.*
import java.util.concurrent.Executors
......@@ -37,7 +36,7 @@ class CoursePosterTemplate(var mContext: Activity) : CardView(mContext) {
*/
private fun initView() {
// radius = RxImageTool.dp2px(10f).toFloat()
View.inflate(context, R.layout.view_course_poster_template, this)
View.inflate(context, R.layout.course_view_course_poster_template, this)
}
@SuppressLint("SetTextI18n")
......@@ -93,7 +92,7 @@ class CoursePosterTemplate(var mContext: Activity) : CardView(mContext) {
}
private fun setType(isDefault: Boolean) {
root_layout.setBackgroundResource(if (isDefault) R.drawable.poster_one else R.drawable.poster_two)
root_layout.setBackgroundResource(if (isDefault) R.drawable.course_poster_one else R.drawable.course_poster_two)
view_line.isEnabled = isDefault
iv_poster_one.isEnabled = isDefault
iv_poster_two.isEnabled = isDefault
......
......@@ -6,18 +6,22 @@ import android.view.View
import android.widget.RelativeLayout
import android.widget.SeekBar
import com.bumptech.glide.Glide
import com.ydl.media.audio.AudioPlayer
import com.ydl.media.audio.OnPlayerEventListener
import com.ydl.media.audio.enums.PlayModeEnum
import com.ydl.media.audio.model.Music
import com.ydl.media.view.PlayTypeEnum
import com.ydl.media.view.PlayerFloatHelper
import com.yidianling.course.R
import com.yidianling.course.listener.HPlayStatusListener
import kotlinx.android.synthetic.main.course_play_music_view.view.*
/**
* Created by hgw on 2018/4/28.
*/
class HPlayView : RelativeLayout, YDLMusicPlayer.MusicControlTaker {
var control: HMusicPlayService.MusicController? = null
var listener: HPlayStatusListener? = null
class HPlayView : RelativeLayout, OnPlayerEventListener {
var mHandler: Handler? = null
var listener: HPlayStatusListener? = null
//seekBar 按下标记
var seekBarIsDown = false
var progress = 0
......@@ -32,23 +36,20 @@ class HPlayView : RelativeLayout, YDLMusicPlayer.MusicControlTaker {
fun init() {
if (mContext == null) return
YDLMusicPlayer.getInstance().setMusicControlTaker(this)
View.inflate(context, R.layout.course_play_music_view, this)
play_icon.setOnClickListener {
if (control?.isPlaying() == true) {
control?.pause()
} else {
control?.start()
}
AudioPlayer.get().playPause()
}
img_gif.setOnClickListener {
if (control?.isPlaying() == false) {
control?.start()
if (!AudioPlayer.get().isPlaying) {
AudioPlayer.get().playPause()
}
}
AudioPlayer.get().addOnPlayEventListener(this)
pro_progress.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(p0: SeekBar?, p1: Int, p2: Boolean) {
if (p2) {
......@@ -65,7 +66,7 @@ class HPlayView : RelativeLayout, YDLMusicPlayer.MusicControlTaker {
seekBarIsDown = false
//拖动seekbar时不进行以下操作
if (!seekBarIsDown) {
control?.seekTo(progress)
AudioPlayer.get().seekTo(-1, progress.toLong())
}
}
})
......@@ -86,8 +87,8 @@ class HPlayView : RelativeLayout, YDLMusicPlayer.MusicControlTaker {
img_gif.visibility = View.VISIBLE
}
fun setData(urlLi: ArrayList<MusicInfoBean>): HPlayView {
control?.setData(urlLi)
fun setData(urlLi: ArrayList<Music>): HPlayView {
AudioPlayer.get().addPlayList(urlLi)
return this
}
......@@ -95,34 +96,27 @@ class HPlayView : RelativeLayout, YDLMusicPlayer.MusicControlTaker {
* 后台进入前台view
*/
fun updateView(index: Int) {
if (control?.isPlaying()!!) {
if (AudioPlayer.get().isPlaying) {
mHandler?.postDelayed({
pro_progress.max = control?.getDuration() ?: 0
pro_progress.max = AudioPlayer.get().getDuration().toInt()
text_end_time.text = getStringTime(pro_progress.max)
listener?.onPrepared(control?.getCurrentData(), index)
listener?.onPrepared(AudioPlayer.get().playMusic, index)
}, 0)
updateButton()
}
}
/**
* 获取当前播放下标
*/
fun getCurrentIndex(): Int {
return control?.getCurrentIndex() ?: 0
}
/**
* 获取当前播放url
*/
fun getCurrentUrl(): String {
return control?.getCurrentUrl() ?: ""
return AudioPlayer.get().playMusic?.path ?: ""
}
fun play(index: Int) {
updateButton()
YDLMusicHelper.playingType = YDLMusicHelper.PLAY_TYPE_COURSE
YDLMusicHelper.directPlay(index, true)
PlayerFloatHelper.playingType=PlayTypeEnum.PLAY_TYPE_COURSE
AudioPlayer.get().play(index)
}
fun setImageBackground(url: String?) {
......@@ -130,131 +124,105 @@ class HPlayView : RelativeLayout, YDLMusicPlayer.MusicControlTaker {
}
/**
* 获取播放控制器
*/
fun getPlayControl(): HMusicPlayService.MusicController? {
return control
}
/**
* 设置自动播放下一曲
*/
fun setAutoNext(auto: Boolean) {
control?.setAutoPlayNext(auto)
if(!auto){
AudioPlayer.get().playMode=PlayModeEnum.SINGLE
}
}
override fun onReceiveControl(control: HMusicPlayService.MusicController) {
this.control = control
setControl1(control)
}
var playStatusListener: PlayStatusListener? = null
private fun setControl1(control: HMusicPlayService.MusicController?) {
control?.setOpenNotifyCation(true)
if (playStatusListener == null) {
playStatusListener = object : PlayStatusListener {
override fun beforeStart(index: Int) {
showBufferLoading(true)
}
override fun onCompletionListener() {
// LogH.d("onCompletionListener")
updateButton()
}
override fun loading() {
// LogH.d("loading")
showBufferLoading(true)
}
override fun onChange(music: Music) {
}
override fun onPrepared() {
// LogH.d("onPrepared")
mHandler?.postDelayed({
pro_progress.max = control?.getDuration() ?: 0
text_end_time.text = getStringTime(pro_progress.max)
listener?.onPrepared(control?.getCurrentData(), control?.getCurrentIndex()
?: 0)
}, 0)
}
override fun onPlayerStart() {
setGifVisibity(true)
}
override fun start() {
// LogH.d("start")
setGifVisibity(true)
}
override fun onPlayerPause() {
if (AudioPlayer.get().isPlaying){
setGifVisibity(true)
}else{
setGifVisibity(false)
}
}
override fun pause() {
// LogH.d("pause")
setGifVisibity(false)
}
override fun onPublish(percent: Int, currentPosition: Long) {
mHandler?.postDelayed({
//拖动seekbar时不进行以下操作
if (!seekBarIsDown) {
pro_progress.progress = progress
text_start_time.text = getStringTime(progress)
}
}, 0)
}
override fun onProgressUpdate(progress: Int) {
mHandler?.postDelayed({
//拖动seekbar时不进行以下操作
if (!seekBarIsDown) {
pro_progress.progress = progress
text_start_time.text = getStringTime(progress)
}
}, 0)
}
override fun onBufferingUpdate(percent: Int) {
showBufferLoading(true)
mHandler?.postDelayed({
pro_progress.secondaryProgress = percent * pro_progress.max / 100
}, 0)
}
override fun OnErrorListener(p1: Int, p2: String) {
// LogH.d("OnErrorListener:$p1 $p2")
setGifVisibity(false)
}
override fun onPrepared(duration: Long) {
mHandler?.postDelayed({
pro_progress.max = duration.toInt()
text_end_time.text = getStringTime(pro_progress.max)
var index=AudioPlayer.get().getMusicList()?.indexOf(AudioPlayer.get().playMusic)?:0
listener?.onPrepared(
AudioPlayer.get().playMusic, index
)
}, 0)
override fun OnBufferingUpdateListener(p1: Int) {
// LogH.d("OnBufferingUpdateListener:$p1")
mHandler?.postDelayed({
pro_progress.secondaryProgress = p1 * pro_progress.max / 100
}, 0)
}
}
}
YDLMusicPlayer.getInstance().addListener(playStatusListener!!)
}
override fun onComplete() {
updateButton()
}
fun showBufferLoading(show: Boolean) {
private fun showBufferLoading(show: Boolean) {
mHandler?.postDelayed({
if (show) {
if (mContext != null) {
Glide.with(mContext).asGif().load(R.mipmap.loading5).into(img_gif)
Glide.with(mContext).asGif().load(R.drawable.course_loading5).into(img_gif)
}
play_icon.setImageResource(R.drawable.ico_course_play)
play_icon.setImageResource(R.drawable.course_ico_course_play)
} else {
if (mContext != null) {
Glide.with(mContext).asGif().load(R.mipmap.audio_play).into(img_gif)
Glide.with(mContext).asGif().load(R.drawable.course_audio_play).into(img_gif)
}
play_icon.setImageResource(R.drawable.ico_course_pause)
play_icon.setImageResource(R.drawable.course_ico_course_pause)
}
}, 0)
}
//显示或隐藏播放动画
fun setGifVisibity(show: Boolean) {
private fun setGifVisibity(show: Boolean) {
if (context == null) return
mHandler?.postDelayed({
if (show) {
if (mContext != null) {
Glide.with(mContext).asGif().load(R.mipmap.audio_play).into(img_gif)
Glide.with(mContext).asGif().load(R.drawable.course_audio_play).into(img_gif)
}
play_icon.setImageResource(R.drawable.ico_course_pause)
play_icon.setImageResource(R.drawable.course_ico_course_pause)
} else {
if (mContext != null) {
Glide.with(mContext).asBitmap().load(R.drawable.ico_course_bg_pause).into(img_gif)
Glide.with(mContext).asBitmap().load(R.drawable.course_ico_course_bg_pause).into(img_gif)
}
play_icon.setImageResource(R.drawable.ico_course_play)
play_icon.setImageResource(R.drawable.course_ico_course_play)
}
}, 0)
}
//跟新上下音频按钮状态
fun updateButton() {
private fun updateButton() {
mHandler?.postDelayed({
if (control?.isPlaying() == true) {
if (AudioPlayer.get().isPlaying) {
setGifVisibity(true)
}
}, 0)
......@@ -280,6 +248,6 @@ class HPlayView : RelativeLayout, YDLMusicPlayer.MusicControlTaker {
fun onDestroy() {
mContext = null
mHandler = null
playStatusListener?.let { YDLMusicPlayer.getInstance().removeListener(it) }
AudioPlayer.get().removeOnPlayEventListener(this)
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true">
<shape>
<corners android:radius="21dp"/>
<gradient android:endColor="@color/color_FAD642" android:startColor="@color/color_FA5729" />
</shape>
</item>
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true">
<shape>
<corners android:radius="11dp"/>
<gradient
android:angle="180"
android:endColor="@color/color_FFC000" android:startColor="@color/color_FF8C00" />
</shape>
</item>
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:angle="270"
android:endColor="@color/white"
android:startColor="#00FFFFFF" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true">
<shape android:shape="oval">
<solid android:color="@color/color_0D1A30" />
<size android:width="15dp" android:height="15dp" />
</shape>
</item>
<item android:state_enabled="false">
<shape android:shape="oval">
<solid android:color="@color/color_FDD33D" />
<size android:width="15dp" android:height="15dp" />
</shape>
</item>
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true">
<shape>
<solid android:color="@color/white" />
<corners android:radius="10dp" />
</shape>
</item>
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true">
<shape android:shape="line">
<stroke android:width="2px" android:color="@color/color_0D1A30" android:dashWidth="15px" android:dashGap="20px" />
<size android:height="1dp" />
</shape>
</item>
<item android:state_enabled="false">
<shape android:shape="line">
<stroke android:width="2px" android:color="@color/color_FDD33D" android:dashWidth="15px" android:dashGap="20px" />
<size android:height="1dp" />
</shape>
</item>
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true">
<shape>
<corners android:radius="2dp" />
<solid android:color="@color/white" />
<stroke android:width="0.5dp" android:color="@color/color_BFBFBF" />
</shape>
</item>
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="7dp" />
<solid android:color="@color/main_theme" />
<stroke
android:width="1dp"
android:color="@color/main_theme" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="45dp"
android:orientation="horizontal"
android:background="@color/color_50FFFFFF"
android:gravity="center">
<TextView
android:id="@+id/footer_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:gravity="center">
<TextView
android:id="@+id/tv_price"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:lineSpacingExtra="0dp"
android:textColor="@color/color_FF9100"
android:textSize="26sp"
android:textStyle="bold"
tools:text="50" />
<TextView
android:id="@+id/tv_discountCont"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/tv_price"
android:gravity="center_horizontal"
android:lineSpacingExtra="0dp"
android:textColor="@color/color_FF9100"
android:textSize="10sp"
tools:text="满500元可用" />
</RelativeLayout>
<RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="5"
android:paddingLeft="16dp"
android:paddingRight="2dp">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginTop="17dp"
android:layout_marginRight="10dp"
android:layout_toLeftOf="@+id/tv_use"
android:ellipsize="end"
android:maxLength="20"
android:maxLines="1"
android:textColor="@color/color_242424"
android:textSize="15sp"
tools:text="咨询优惠券" />
<TextView
android:id="@+id/tv_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/tv_title"
android:layout_marginTop="1dp"
android:text="有效期至2018-08-31"
android:textColor="@color/color_242424"
android:textSize="11sp" />
<TextView
android:id="@+id/tv_use"
android:layout_width="wrap_content"
android:layout_height="22dp"
android:layout_alignParentRight="true"
android:layout_marginTop="16dp"
android:layout_marginRight="12dp"
android:background="@drawable/course_background_course_coupon_detail_use"
android:gravity="center"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="使用"
android:textColor="@color/white"
android:textSize="12sp"
android:visibility="gone"
tools:visibility="visible" />
<TextView
android:id="@+id/tv_use_condition"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginTop="1dp"
android:layout_marginBottom="14dp"
android:text="指定课程使用"
android:textColor="@color/color_666666"
android:textSize="11sp" />
</RelativeLayout>
</merge>
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:myapp="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/course_poster_one"
tools:ignore="MissingDefaultResource">
<android.support.constraint.ConstraintLayout
android:id="@+id/content_layout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="14dp"
android:layout_marginTop="38dp"
android:layout_marginEnd="14dp"
android:layout_marginBottom="18dp"
android:background="@drawable/course_background_course_poster_content"
app:layout_constraintBottom_toTopOf="@+id/imageView2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/iv_pic"
android:layout_width="match_parent"
android:layout_height="130dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<TextView
android:id="@+id/tv_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="11dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="11dp"
android:ellipsize="end"
android:lineSpacingExtra="3dp"
android:maxLines="3"
android:textColor="@color/color_242424"
android:textSize="15sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/iv_pic"
tools:text="丁sir说抑郁:像心理学家一样去挽回去挽回像心理学家一样去挽回去挽回"/>
<TextView
android:id="@+id/tv_intro"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="11dp"
android:layout_marginTop="3dp"
android:layout_marginEnd="11dp"
android:ellipsize="end"
android:lineSpacingExtra="3dp"
android:maxLines="2"
android:textColor="@color/color_242424"
android:textSize="12sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_title"
tools:text="这是课程简介这是课程简介这是课程简介这是课程简介这是课程简介这是课程简介"/>
<TextView
android:id="@+id/tv_symbol"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="¥"
android:textColor="@color/color_FF5A4C"
android:textSize="10sp"
app:layout_constraintBottom_toBottomOf="@+id/tv_price"
app:layout_constraintStart_toStartOf="@+id/tv_intro"
app:layout_constraintTop_toTopOf="@+id/tv_price"/>
<TextView
android:id="@+id/tv_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="7dp"
android:textColor="@color/color_FF5A4C"
android:textSize="17sp"
android:textStyle="bold"
app:layout_constraintStart_toEndOf="@+id/tv_symbol"
app:layout_constraintTop_toBottomOf="@+id/tv_intro"
tools:text="100"/>
<TextView
android:id="@+id/tv_original_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:textColor="@color/color_999999"
android:textSize="9sp"
app:layout_constraintBottom_toBottomOf="@+id/tv_price"
app:layout_constraintStart_toEndOf="@+id/tv_price"
app:layout_constraintTop_toTopOf="@+id/tv_price"
tools:text="原价399.00"/>
<TextView
android:id="@+id/tv_view_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/color_242424"
android:textSize="10sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/tv_price"
app:layout_constraintEnd_toStartOf="@+id/tv_view_count_unit"
app:layout_constraintTop_toTopOf="@+id/tv_price"
tools:text="2819"/>
<TextView
android:id="@+id/tv_view_count_unit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="4dp"
android:text="人已学 |"
android:textColor="@color/color_666666"
android:textSize="10sp"
app:layout_constraintBottom_toBottomOf="@+id/tv_price"
app:layout_constraintEnd_toStartOf="@+id/tv_course_num"
app:layout_constraintTop_toTopOf="@+id/tv_price"/>
<TextView
android:id="@+id/tv_course_unit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="11dp"
android:text="讲"
android:textColor="@color/color_666666"
android:textSize="10sp"
app:layout_constraintBottom_toBottomOf="@+id/tv_price"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/tv_price"/>
<TextView
android:id="@+id/tv_course_num"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/color_242424"
android:textSize="10sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/tv_price"
app:layout_constraintEnd_toStartOf="@+id/tv_course_unit"
app:layout_constraintTop_toTopOf="@+id/tv_price"
tools:text="24"/>
<RelativeLayout
android:id="@+id/rl_line"
android:layout_width="match_parent"
android:layout_height="15dp"
android:layout_marginTop="19dp"
app:layout_constraintTop_toBottomOf="@+id/tv_price">
<View
android:id="@+id/view_line"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_centerVertical="true"
android:background="@drawable/course_background_course_poster_line"
android:layerType="software"/>
<ImageView
android:id="@+id/iv_poster_one"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginStart="-8dp"
android:background="@drawable/course_background_course_poster_circle"/>
<ImageView
android:id="@+id/iv_poster_two"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginEnd="-8dp"
android:background="@drawable/course_background_course_poster_circle"/>
</RelativeLayout>
<com.ydl.ydlcommon.view.widgets.RoundImageView
android:id="@+id/iv_head"
android:layout_width="26dp"
android:layout_height="26dp"
android:layout_marginStart="11dp"
android:layout_marginTop="19dp"
android:src="@drawable/course_poster_share_head"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/rl_line"
myapp:type="circle"/>
<TextView
android:id="@+id/tv_user_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:text="壹点灵用户"
android:textColor="@color/color_242424"
android:textSize="12sp"
android:textStyle="bold"
app:layout_constraintStart_toEndOf="@+id/iv_head"
app:layout_constraintTop_toTopOf="@+id/iv_head"/>
<TextView
android:id="@+id/tv_note"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="向你推荐这门课"
android:textColor="@color/color_666666"
android:textSize="9sp"
app:layout_constraintStart_toStartOf="@+id/tv_user_name"
app:layout_constraintTop_toBottomOf="@+id/tv_user_name"/>
<TextView
android:id="@+id/tv_note_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:background="@drawable/course_bg_radius_green_7"
android:paddingLeft="7dp"
android:paddingTop="1dp"
android:paddingRight="7dp"
android:paddingBottom="1dp"
android:text="长按扫码进入课程"
android:textColor="@color/white"
android:textSize="9sp"
app:layout_constraintStart_toStartOf="@+id/tv_user_name"
app:layout_constraintTop_toBottomOf="@+id/tv_note"/>
<View
android:layout_width="1dp"
android:layout_height="1dp"
android:layout_marginTop="22dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_note_2"/>
<RelativeLayout
android:id="@+id/view_bord"
android:layout_width="52dp"
android:layout_height="52dp"
android:layout_marginEnd="10dp"
android:background="@drawable/course_background_qrcode_bord"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/iv_head">
<com.ydl.ydlcommon.view.widgets.RoundImageView
android:id="@+id/iv_qrc_code"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:layout_margin="0.5dp"
myapp:borderRadius="2dp"
myapp:type="round"/>
</RelativeLayout>
</android.support.constraint.ConstraintLayout>
<ImageView
android:id="@+id/imageView2"
android:layout_width="60dp"
android:layout_height="20dp"
android:layout_marginBottom="18dp"
android:src="@drawable/course_poster_logo"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/content_layout"/>
</android.support.constraint.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00000000"
android:gravity="center"
android:orientation="vertical">
<android.support.v7.widget.CardView
android:id="@+id/card_view"
android:layout_width="310dp"
android:layout_height="397dp"
android:layout_marginLeft="33dp"
android:layout_marginRight="32dp"
android:background="@color/color_FFFFFF"
app:cardCornerRadius="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="28dp"
android:textColor="@color/color_242424"
android:textSize="20sp"
tools:text="领取成功" />
<TextView
android:id="@+id/tv_introduction"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="未领到的优惠券已经被抢光了"
android:textColor="@color/color_666666"
android:textSize="12sp"
android:visibility="gone" />
<ImageView
android:id="@+id/iv_empty"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_weight="1"
android:scaleType="center"
android:src="@drawable/course_img_course_background"
android:visibility="gone" />
<ScrollView
android:id="@+id/scrollview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_weight="1"
android:scrollbars="none">
<LinearLayout
android:id="@+id/ll_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:orientation="vertical" />
</ScrollView>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="82dp"
android:layout_marginBottom="30dp"
android:background="@drawable/course_background_course_coupon_layer">
<TextView
android:id="@+id/tv_ensure"
android:layout_width="match_parent"
android:layout_height="42dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginLeft="45dp"
android:layout_marginRight="45dp"
android:background="@drawable/course_background_coupon_button"
android:gravity="center"
android:textColor="@color/white"
android:textSize="15sp"
tools:text="立即领取" />
</RelativeLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
<ImageView
android:id="@+id/iv_close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="37dp"
android:padding="10dp"
android:src="@drawable/course_dialog_pop_close" />
</LinearLayout>
\ No newline at end of file
......@@ -130,4 +130,11 @@
<color name="color_66000000">#66000000</color>
<color name="color_FFFFFF">#FFFFFF</color>
<color name="color_ACACAC">#ACACAC</color>
<color name="color_50FFFFFF">#B3FFFFFF</color>
<color name="color_FF9100">#FF9100</color>
<color name="color_FFC000">#FFC000</color>
<color name="color_FF8C00">#FF8C00</color>
<color name="color_0D1A30">#0D1A30</color>
<color name="color_FDD33D">#FDD33D</color>
<color name="color_BFBFBF">#BFBFBF</color>
</resources>
\ No newline at end of file
include ':app',":router", ":m-course", ':ydl-net', ':ydl-utils', ':ydl-platform', ':ydl-webview', ':ydl-media',":m-user", ':m-consultant', ':m-muse', ':m-fm', ':m-tests'
\ No newline at end of file
include ':app',":router", ":m-course", ':ydl-net', ':ydl-utils', ':ydl-platform', ':ydl-webview', ':ydl-media',":m-user", ':m-consultant', ':m-muse', ':m-fm', ':m-tests', ':ydl-pay'
\ No newline at end of file
......@@ -24,13 +24,41 @@ android {
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
api fileTree(dir: 'libs', include: ['*.jar','*.aar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.8.0'
implementation 'com.facebook.stetho:stetho:1.5.0'
implementation 'com.facebook.stetho:stetho-okhttp3:1.4.1'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
implementation 'com.android.support:recyclerview-v7:27.1.1'
implementation 'de.greenrobot:eventbus:2.4.0'
api 'com.umeng.sdk:share-wechat:6.9.1'
}
repositories {
flatDir {
dirs 'libs'
}
mavenCentral()
}
\ No newline at end of file
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.yidianling.ydl_pay"/>
package="com.yidianling.ydl_pay">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
</manifest>
package com.ydl.ydl_pay
import android.app.Activity
import android.app.Dialog
import android.content.Context
import android.graphics.Point
import android.os.Bundle
import android.support.v4.view.PagerAdapter
import android.support.v7.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.ydl_pay.bean.*
import com.ydl.ydl_pay.http.HttpConfig
import com.ydl.ydl_pay.http.HttpUtils
import com.ydl.ydl_pay.http.PayRetrofitUtils
import com.ydl.ydl_pay.toast.ToastHelper
import com.ydl.ydl_pay.widget.PayCouponView
import com.ydl.ydl_pay.widget.PayInfoDetailView
import com.yidianling.ydl_pay.BuildConfig
import com.yidianling.ydl_pay.R
import com.yidianling.ydl_pay.bean.AllCouponListBean
import com.yidianling.ydl_pay.bean.CommonCouponBean
import com.yidianling.ydl_pay.bean.OrderInfoBean
import com.yidianling.ydl_pay.bean.PayResult
import com.yidianling.ydl_pay.bean.params.*
import com.yidianling.ydl_pay.http.utils.NetUtils
import com.yidianling.ydl_pay.http.utils.RxDeviceTool
import de.greenrobot.event.EventBus
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import kotlinx.android.synthetic.main.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 dialog: AlertDialog? = null
private var dialogContentView: View? = null
/**
* 支付方式
* 1024.微信支付 1025.支付宝支付
*/
private var payWay = 0
/**
* 支付的业务类型
* [TYPE_COURSE] 课程支付
* [TYPE_CONFIDE] 倾诉支付
* [TYPE_TEST] 测评支付
* [TYPE_CONSULTANT] 咨询支付
*/
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
/**
* 支付方式
* 1024.微信支付 1025.支付宝支付
*/
private const val PAY_WECHAT = 1024
private const val PAY_ALI = 1025
}
private constructor(context: Context) : super(context, R.style.common_dialog_style)
private constructor(build: CommonPayDialog.Build) : this(build.mActivity) {
this.goodsId = build.goodsId
this.activity = build.mActivity
this.listener = build.listener
this.payBusinessType = build.payType
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.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)
getOrderInfo()
}
override fun show() {
super.show()
showProgressDialog()
}
/**
* 获取下单信息
*/
private fun getOrderInfo() {
if (!NetUtils.isConnected(activity)) {
ToastHelper.show(activity, activity.getString(R.string.net_error))
// 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
updateDataOnView(it.data)
} else {
ToastHelper.show(activity, it.msg)
// progress.visibility = View.GONE
}
} else {
ToastHelper.show(activity, it.msg)
// progress.visibility = View.GONE
}
}, { e ->
dismissProgressDialog()
// progress.visibility = View.GONE
ToastHelper.show(activity, e.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
}
/**
获取所有选择优惠券
*/
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混合
*
*/
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()
showProgressDialog()
HttpUtils.createOrder(bean)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
if (it.code == 200) {
if (it.data != null) {
if (it.data.payStatus) {
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)
}
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!!)
})
}
/**
* 支付宝支付
*
*/
private fun getAliPayOrderId(payId: String, isThreePay: Int) {
if (!NetUtils.isConnected(activity)) {
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) {
aliPay(it.data.aliSign)
} else {
activity.runOnUiThread {
ToastHelper.show(activity, it.msg)
}
dismissProgressDialog()
}
}, {
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) {
activity.runOnUiThread {
ToastHelper.show(activity, "支付成功")
listener!!.onSuccesed()
dismiss()
}
dismissProgressDialog()
} else {
dismissProgressDialog()
activity.runOnUiThread {
ToastHelper.show(activity, payResult.memo)
}
}
}
/**
* 微信支付
*/
private fun getWeiXinPayOrderId(payId: String, isThreePay: Int) {
if (!NetUtils.isConnected(activity)) {
activity.runOnUiThread {
ToastHelper.show(activity, activity.getString(R.string.net_error))
}
return
}
var bean = WxPayParam(payId, isThreePay)
HttpUtils.wxPay(bean)
.subscribeOn(Schedulers.io())
.subscribe({
if (it.data != null) {
weixinPay(it.data.option)
} else {
activity.runOnUiThread {
ToastHelper.show(activity, it.msg)
}
dismissProgressDialog()
}
}, {
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)
}
fun onEvent(event: WeiXinPayStatusEvent) {
dismissProgressDialog()
if (event.success) {
ToastHelper.show(activity, "支付成功")
listener!!.onSuccesed()
dismiss()
} else {
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
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 = CommonPayDialog.TYPE_COURSE
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()
}
}
package com.ydl.ydl_pay.actionpoint
import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkInfo
import com.ydl.ydl_pay.http.HttpUtils
import com.ydl.ydl_pay.http.utils.RxDeviceTool
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
/**
* 行为数据埋点工具类
* Created by xj on 2019/6/22.
*/
internal class ActionCountUtils {
companion object {
const val TAG: String = "ActionCountUtils"
/**
* 基础行为数据埋点调用的方法
*/
fun count(uid: String?, partId: String, position: String, url: String, api: String, sign1: String) {
try {
val actionDataParams = ActionDataBean.Builder()
actionDataParams.partId(partId)
actionDataParams.position(position)
actionDataParams.url(url)
uid?.let {
actionDataParams.uid(uid)
}
actionDataParams.time(System.currentTimeMillis())
actionDataParams.appVersion(RxDeviceTool.getAppVersionName(RxDeviceTool.getContext()))
actionDataParams.appId(BIConstants.APP_ID)
actionDataParams.api(api)
actionDataParams.manufacturer(android.os.Build.BRAND.trim().toUpperCase())
actionDataParams.model(android.os.Build.MODEL)
actionDataParams.os(BIConstants.OS)
actionDataParams.osVersion(android.os.Build.VERSION.RELEASE)
actionDataParams.wifi(if (isWifi()) 0 else 1)
actionDataParams.sign1(sign1)
actionDataParams.screenWidth(RxDeviceTool.getScreenWidth(RxDeviceTool.getContext()))
actionDataParams.screenHeight(RxDeviceTool.getScreenHeight(RxDeviceTool.getContext()))
//剩余额外参数根据需求定义
//请求
request(actionDataParams.build())
} catch (e: Exception) {
}
}
/**
* 传入ActionDataParams参数,访问接口
*/
fun request(actionDataBean: ActionDataBean) {
try {
HttpUtils.actionDataCount(actionDataBean)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
}) {
}
} catch (e: Exception) {
e.printStackTrace()
}
}
/**
* 判断是否是wifi
*/
private fun isWifi(): Boolean {
try {
var connectivityManager: ConnectivityManager = RxDeviceTool.getContext().getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
var info: NetworkInfo = connectivityManager.activeNetworkInfo
if (info != null && info.type == ConnectivityManager.TYPE_WIFI) {
return true
}
return false
} catch (e: Exception) {
return false
}
}
}
}
\ No newline at end of file
package com.ydl.ydl_pay.actionpoint
/**
* Created by xj on 2019/6/22.
*/
internal class ActionDataBean private constructor(builder: Builder) {
/**
* partId : sy_1 //埋点板块
* position : psychic_advisory_click //点击事件
* uid : 123 //用户ID
* time : 1560389634000 //事件发生时间,毫秒级时间戳
* ip : 192.168.0.1 //IP地址
* appVersion : 3.8.00 //版本号
* appId : ydl-app-android-user
* url : https://www.baidu.com //访问地址
* server : 123
* api : https://www.baidu.com/api
* manufacturer : Apple //设备厂商,字符串类型,如"Apple"
* model : iphone6 //设备型号,字符串类型,如"iphone6"
* os : iOS //操作系统,字符串类型,如"iOS"
* osVersion : 8.1.1 //操作系统版本,字符串类型,如"8.1.1"
* screenHeight : 1920 //屏幕高度,数字类型,如1920
* screenWidth : 1080 //屏幕宽度,数字类型,如1080
* wifi : 0 是否 WIFI,byte类型,如0(是),1(否)
* sign1 :
* sign2 :
* sign3 :
* sign4 :
* sign5 :
*/
var partId: String? = null
var position: String? = null
var uid: String? = null
var time: Long = 0.toLong()
var ip: String? = null
var appVersion: String? = null
var appId: String? = null
var url: String? = null
var server: String? = null
var api: String? = null
var manufacturer: String? = null
var model: String? = null
var os: String? = null
var osVersion: String? = null
var screenHeight: Int = 0
var screenWidth: Int = 0
var wifi: Int = 0
var sign1: String? = null
var sign2: String? = null
var sign3: String? = null
var sign4: String? = null
var sign5: String? = null
init {
this.partId = builder.partId
this.position = builder.position
this.uid = builder.uid
this.time = builder.time
this.ip = builder.ip
this.appVersion = builder.appVersion
this.appId = builder.appId
this.url = builder.url
this.server = builder.server
this.api = builder.api
this.manufacturer = builder.manufacturer
this.model = builder.model
this.os = builder.os
this.osVersion = builder.osVersion
this.screenHeight = builder.screenHeight
this.screenWidth = builder.screenWidth
this.wifi = builder.wifi
this.sign1 = builder.sign1
this.sign2 = builder.sign2
this.sign3 = builder.sign3
this.sign4 = builder.sign4
this.sign5 = builder.sign5
}
class Builder {
internal var partId: String? = ""
internal var position: String? = ""
internal var uid: String? = ""
internal var time: Long = 0.toLong()
internal var ip: String? = ""
internal var appVersion: String? = ""
internal var appId: String? = ""
internal var url: String? = ""
internal var server: String? = ""
internal var api: String? = ""
internal var manufacturer: String? = ""
internal var model: String? = ""
internal var os: String? = ""
internal var osVersion: String? = ""
internal var screenHeight: Int = 0
internal var screenWidth: Int = 0
internal var wifi: Int = 0
internal var sign1: String? = ""
internal var sign2: String? = ""
internal var sign3: String? = ""
internal var sign4: String? = ""
internal var sign5: String? = ""
fun partId(partId: String = ""): Builder {
this.partId = partId
return this
}
fun position(position: String = ""): Builder {
this.position = position
return this
}
fun uid(uid: String = ""): Builder {
this.uid = uid
return this
}
fun time(time: Long = 0.toLong()): Builder {
this.time = time
return this
}
fun ip(ip: String = ""): Builder {
this.ip = ip
return this
}
fun appVersion(appVersion: String = ""): Builder {
this.appVersion = appVersion
return this
}
fun appId(appId: String = ""): Builder {
this.appId = appId
return this
}
fun url(url: String = ""): Builder {
this.url = url
return this
}
fun server(server: String = ""): Builder {
this.server = server
return this
}
fun api(api: String = ""): Builder {
this.api = api
return this
}
fun manufacturer(manufacturer: String = ""): Builder {
this.manufacturer = manufacturer
return this
}
fun model(model: String = ""): Builder {
this.model = model
return this
}
fun os(os: String = ""): Builder {
this.os = os
return this
}
fun osVersion(osVersion: String = ""): Builder {
this.osVersion = osVersion
return this
}
fun screenHeight(screenHeight: Int = 0): Builder {
this.screenHeight = screenHeight
return this
}
fun screenWidth(screenWidth: Int = 0): Builder {
this.screenWidth = screenWidth
return this
}
fun wifi(wifi: Int = 0): Builder {
this.wifi = wifi
return this
}
fun sign1(sign1: String = ""): Builder {
this.sign1 = sign1
return this
}
fun sign2(sign2: String = ""): Builder {
this.sign2 = sign2
return this
}
fun sign3(sign3: String = ""): Builder {
this.sign3 = sign3
return this
}
fun sign4(sign4: String = ""): Builder {
this.sign4 = sign4
return this
}
fun sign5(sign5: String = ""): Builder {
this.sign5 = sign5
return this
}
fun build() : ActionDataBean {
return ActionDataBean(this)
}
}
}
\ No newline at end of file
package com.ydl.ydl_pay.actionpoint
/**
* Created by xj on 2019/7/1.
*/
internal class BIConstants{
companion object {
/**
* 消息端来源
*/
const val APP_ID = "ydl-app-android-user" //这是用户端主包的
/**
* 操作系统
*/
const val OS = "Android" //android系统
/**
* 埋点板块
*/
const val PART_ID_COURSE_COUPON_PAGE= "course_coupon_page"//课程兑换码弹出页
/**
* position
* 点击类型
*/
const val POSITION_COURSE_COUPON_CLICK = "course_coupon_click" //课程兑换券点击
}
}
\ No newline at end of file
package com.ydl.ydl_pay.adapter
import android.annotation.SuppressLint
import android.content.Context
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import com.ydl.ydl_pay.actionpoint.ActionCountUtils
import com.ydl.ydl_pay.actionpoint.BIConstants
import com.ydl.ydl_pay.http.HttpConfig
import com.ydl.ydl_pay.widget.CouponInfoDetailView
import com.yidianling.ydl_pay.R
import com.yidianling.ydl_pay.bean.AllCouponListBean
import com.yidianling.ydl_pay.bean.CommonCouponBean
import kotlinx.android.synthetic.main.item_coupon_title.view.*
/**
* @author jiucheng
* @描述:选择优惠券adpater
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/4/19
*/
class SelectCouponAdapter(var couponListBean: AllCouponListBean, var context: Context, var event: (selectedCouponBean: CommonCouponBean?) -> Unit) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var headView: View? = null
companion object {
//可用优惠券title
const val TYPE_AVAILABLE_TITLE = 0
//可用优惠券内容
const val TYPE_AVAILABLE_CONTENT = 1
//不可用优惠券title
const val TYPE_UNAVAILABLE_TITLE = 2
//不可用优惠券内容
const val TYPE_UNAVAILABLE_CONTENT = 3
//headview
const val TYPE_HEAD = 1024
}
fun setHeadView(headView: View) {
this.headView = headView
}
private fun getHeadVieCount(): Int {
return if (headView == null) 0 else 1
}
override fun getItemViewType(position: Int): Int {
if (getHeadVieCount() > 0) { //有头部布局
if (position == 0) {
return TYPE_HEAD
}
//可用优惠券为0
if (couponListBean.availableCount == 0) {
return if (position == 1) {
TYPE_UNAVAILABLE_TITLE
} else {
TYPE_UNAVAILABLE_CONTENT
}
}
return if (position == 1) {
//可用优惠券title
TYPE_AVAILABLE_TITLE
} else if (position > 1 && position <= couponListBean.availableCount + 1) {
//可用优惠券
TYPE_AVAILABLE_CONTENT
} else if (position == couponListBean.availableCount + 2) {
//不可用优惠券title
TYPE_UNAVAILABLE_TITLE
} else {
//不可用优惠券
TYPE_UNAVAILABLE_CONTENT
}
} else {
//可用优惠券为0
if (couponListBean.availableCount == 0) {
return if (position == 0) {
TYPE_UNAVAILABLE_TITLE
} else {
TYPE_UNAVAILABLE_CONTENT
}
}
return if (position == 0) {
//可用优惠券title
TYPE_AVAILABLE_TITLE
} else if (position > 0 && position <= couponListBean.availableCount) {
//可用优惠券
TYPE_AVAILABLE_CONTENT
} else if (position == couponListBean.availableCount + 1) {
//不可用优惠券title
TYPE_UNAVAILABLE_TITLE
} else {
//不可用优惠券
TYPE_UNAVAILABLE_CONTENT
}
}
}
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): RecyclerView.ViewHolder {
return when (viewType) {
TYPE_HEAD -> {
HeadViewHolder(headView!!)
}
TYPE_AVAILABLE_TITLE -> {
TitleViewHolder(LayoutInflater.from(context).inflate(R.layout.item_coupon_title, null))
}
TYPE_AVAILABLE_CONTENT -> {
CouponViewHolder(CouponInfoDetailView(context))
}
TYPE_UNAVAILABLE_TITLE -> {
TitleViewHolder(LayoutInflater.from(context).inflate(R.layout.item_coupon_title, null))
}
TYPE_UNAVAILABLE_CONTENT -> {
CouponViewHolder(CouponInfoDetailView(context))
}
else -> {
TitleViewHolder(LayoutInflater.from(context).inflate(R.layout.item_coupon_title, null))
}
}
}
override fun getItemCount(): Int {
if (couponListBean.availableCount + couponListBean.unAvailableCount > 0) {
//如果没有可用优惠券,那可用优惠券标题和内容都不显示
if (couponListBean.availableCount == 0) {
return couponListBean.unAvailableCount + 1 + getHeadVieCount()
}
return couponListBean.availableCount + couponListBean.unAvailableCount + 2 + getHeadVieCount()
} else {
return 0 + getHeadVieCount()
}
}
@SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: RecyclerView.ViewHolder?, position: Int) {
when (getItemViewType(position)) {
TYPE_HEAD -> {
}
TYPE_AVAILABLE_TITLE -> {
(holder as TitleViewHolder).textView!!.text = "可用券(${couponListBean.availableCount})"
}
TYPE_AVAILABLE_CONTENT -> {
var realPosition = if (getHeadVieCount() == 0) position else position - 1
(holder as CouponViewHolder).view.setData(couponListBean.available[realPosition - 1], true)
holder.view.setOnClickListener {
//点击的优惠券是未选中的
if (couponListBean.available[realPosition - 1].hasSelected != 1) {
repeat(couponListBean.available.size) {
couponListBean.available[it].hasSelected = 0
}
couponListBean.available[realPosition - 1].hasSelected = 1
ActionCountUtils.count(HttpConfig.uid, BIConstants.PART_ID_COURSE_COUPON_PAGE,
BIConstants.POSITION_COURSE_COUPON_CLICK, "", "", couponListBean.available[realPosition - 1].couponId)
notifyDataSetChanged()
event(couponListBean.available[realPosition - 1])
} else { //点击的优惠券是选中的
couponListBean.available[realPosition - 1].hasSelected = 0
ActionCountUtils.count(HttpConfig.uid, BIConstants.PART_ID_COURSE_COUPON_PAGE,
BIConstants.POSITION_COURSE_COUPON_CLICK, "", "", "")
notifyDataSetChanged()
event(null)
}
}
}
TYPE_UNAVAILABLE_TITLE -> {
(holder as TitleViewHolder).textView!!.text = "不可用券(${couponListBean.unAvailableCount})"
}
TYPE_UNAVAILABLE_CONTENT -> {
var realPosition = if (getHeadVieCount() == 0) position else position - 1
if (couponListBean.unAvailableCount > 0) {
if (couponListBean.availableCount == 0) {
(holder as CouponViewHolder).view.setData(couponListBean.unAvailable[realPosition - 1], false)
} else {
(holder as CouponViewHolder).view.setData(couponListBean.unAvailable[realPosition - couponListBean.availableCount - 2], false)
}
}
}
}
}
inner class CouponViewHolder(var view: CouponInfoDetailView) : RecyclerView.ViewHolder(view)
inner class HeadViewHolder(var view: View) : RecyclerView.ViewHolder(view)
inner class TitleViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
var textView: TextView? = null
init {
textView = this.view.tv_title
}
}
}
package com.yidianling.ydl_pay.bean;
import java.util.ArrayList;
import java.util.List;
/**
* @author jiucheng
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/4/18
*/
public class AllCouponListBean {
public int availableCount;
public List<CommonCouponBean> available = new ArrayList<>();
public List<CommonCouponBean> unAvailable = new ArrayList<>();
public int unAvailableCount;
}
package com.yidianling.ydl_pay.bean;
/**
* @author jiucheng
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/4/17
*/
public class CheckCourseCouponBean {
/**
* "isAvailable": false,
* "couponInfo": null,
* "msg": "",
* "msgCode": "课程不存在"
*/
public boolean isAvailable = false;
public String msg;
public String msgCode;
}
package com.yidianling.ydl_pay.bean;
import java.util.List;
/**
* @author jiucheng
* @描述:优惠券的bean
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/4/17
*/
public class CommonCouponBean {
public float amount;//优惠金额
public float combinedAmount;//合计优惠金额
public String couponType;//券类型 1兑换券 2新优惠券(优先判断这个)
public String discount;//折扣
public String discountCont;//优惠的文案
public String effective;//有效期的文案
public String endDate;//截止有效期 ,
public String code;//code +type 可组成唯一标识
public boolean isAvailableCoupon;
public boolean isAvailableMaxCoupon;
public boolean isReceiveCoupon;
public boolean isTheFailure;// 是否即将过期 true是 2false ,
public float price;//兑换券的金额
public String type;//优惠券形式:1立减,2折扣 ,
public String rangeCont;//使用范围的文案
public List<String> specifiedGoodsList;//指定商品列表
public int isSpecifiedGoods;//是否指定商品 1是 2否 ,
public String couponId;//优惠券id
public String title;//优惠券名称 ,
public String validityType;//有效期类型:1永久有效,2指定日期
public String id;// 用户领用记录的id(不是优惠券id)
public String useCondition;// 使用条件 1无限制 2满金额
public float useConditionValue;//使用条件的值(金额或次数) ,
//是否选中 0 未选中 1 选中
public int hasSelected = 0;
}
package com.yidianling.ydl_pay.bean;
/**
* @author jiucheng
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/4/23
*/
public class CommonPayRecharge {
public String rechargeId;
/**
* 支付金额
*/
public String money;
/**
* 支付宝 加签
*/
public String aliSign;
}
package com.ydl.ydl_pay.bean
/**
* author : Zhangwenchao
* e-mail : zhangwch@yidianling.com
* time : 2018/04/18
*/
data class CommonWXPayBean(val option: WXOption) {
data class WXOption(val appid: String,
val timestamp: String,
val noncestr: String,
val partnerid: String,
val prepayid: String,
val sign: String)
}
\ No newline at end of file
package com.yidianling.ydl_pay.bean;
/**
* @author jiucheng
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/4/19
*/
public class CouponCodeInfoBean {
public boolean isAvailable;//是否可用
public String msg;//是否可用
public String msgCode;//错误码
public CommonCouponBean couponInfo;//优惠券信息
}
package com.yidianling.ydl_pay.bean;
/**
* @author jiucheng
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/4/16
*/
public class OrderInfoBean {
/**
* applyFee (number, optional): 课程金额 ,
* availableMoney (number, optional): 现金余额 ,
* goodsId (integer, optional): 对应的商品id ,
* isShowCoupon (boolean, optional): 是否展示优惠入口 true展示 false不展示 ,
* isVirtual (string, optional): 虚拟商品 1是 2不是 ,
* orderType (string, optional): 业务类型 1课程 ,
* title (string, optional): 商品名称 ,
* ybBalance (number, optional): 壹贝金额
*/
public float applyFee;
public float availableMoney;
public String goodsId;
public boolean isShowCoupon;
public String isVirtual;
public String orderType;
public String title;
//ios 壹贝字段
public String ybBalance;
public CommonCouponBean maxCoupon;
}
package com.yidianling.ydl_pay.bean;
/**
* @author jiucheng
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/4/22
*/
public class PayOrderBean {
public String orderId;//订单id
public String payId;//支付id
public String payWay;//1调用三方支付 2调用充值接口
public String title;//业务名称
public String uid;//用户id
public float rechargeMoney;//需要充值的金额
public boolean payStatus;//支付状态 true已支付 false未支付 ,
}
package com.yidianling.ydl_pay.bean; import android.text.TextUtils; import java.util.Map; public class PayResult { private String resultStatus; private String result; private String memo; public PayResult(Map<String, String> rawResult) { if (rawResult == null) { return; } for (String key : rawResult.keySet()) { if (TextUtils.equals(key, "resultStatus")) { resultStatus = rawResult.get(key); } else if (TextUtils.equals(key, "result")) { result = rawResult.get(key); } else if (TextUtils.equals(key, "memo")) { memo = rawResult.get(key); } } } @Override public String toString() { return "resultStatus={" + resultStatus + "};memo={" + memo + "};result={" + result + "}"; } /** * @return the resultStatus */ public String getResultStatus() { return resultStatus; } /** * @return the memo */ public String getMemo() { return memo; } /** * @return the result */ public String getResult() { return result; }}
\ No newline at end of file
package com.ydl.ydl_pay.bean
/**
* @author jiucheng
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/5/7
*/
data class WeiXinPayStatusEvent(val success: Boolean, val msg: String?)
\ No newline at end of file
package com.yidianling.ydl_pay.bean.params;
/**
* @author jiucheng
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/4/24
*/
public class AliPayParam extends CommonPayParam {
public AliPayParam(String payId,int isThreePay) {
super(payId, "aliapp",isThreePay);
}
}
package com.yidianling.ydl_pay.bean.params;
/**
* @author jiucheng
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/4/23
*/
public class BalancePayParam extends BaseCommand {
public String payId;
}
package com.yidianling.ydl_pay.bean.params;
import com.ydl.ydl_pay.http.HttpConfig;
/**
* 基础网络请求类
* Created by Dog on 2015/5/8.
*/
public class BaseCommand {
public String uid = HttpConfig.INSTANCE.getUid();
public String accessToken = HttpConfig.INSTANCE.getAccessToken();
public String ts;
public String version = HttpConfig.INSTANCE.getVersion();
public String osBuild = HttpConfig.INSTANCE.getOsBuild();
public String isFromApp = "1";//2表示专家版1表示用户版
public String ffrom = HttpConfig.INSTANCE.getFfrom();//渠Y道来源
public BaseCommand() {
ts = (System.currentTimeMillis() / 1000) + "";
}
}
package com.yidianling.ydl_pay.bean.params;
/**
* @author jiucheng
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/4/17
*/
public class CheckRequestCouponBean {
public String couponCode;//兑换券码 ,
public String courseId;// 课程id
}
package com.yidianling.ydl_pay.bean.params;
/**
* @author jiucheng
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/4/23
*/
public class CommonPayParam extends BaseCommand {
public String payId;
public String type;
public int isThreePay = 0;//混合支付 0 纯三方支付 isThreePay 1
public CommonPayParam(String payId, String type, int isThreePay) {
this.payId = payId;
this.isThreePay = isThreePay;
this.type = type;
}
}
package com.yidianling.ydl_pay.bean.params;
/**
* @author jiucheng
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/4/22
*/
public class CreateOrderRequestBean {
public String code;//优惠券code
public String couponType ;//券类型 1兑换券 2新优惠券 ,
public String goodsId;//商品id ,
public String orderType;//业务类型 1课程 ,
public String payType;//1余额,2三方支付,3混合 4壹贝(ios的虚拟商品)
}
package com.yidianling.ydl_pay.bean.params;
/**
* @author jiucheng
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/4/18
*/
public class GetAllCouponRequestBean {
public String applyEnds;// 适用终端 1PC官网 2wap站点 3用户app 4好杮app 5专家app ,
public String goodsId;// 商品Id
public String receiveType = "1";// 领取条件方式 1前台领取 2链接领取 ,
public String services;//适用服务 1预约咨询 2电话倾诉 3课程(用户课程 专家课程) 5测评
}
package com.yidianling.ydl_pay.bean.params;
/**
* @author jiucheng
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/4/16
*/
public class OrderRequestBean {
/**
* goodsId (integer, optional): 商品id ,
* orderType (string, optional): 业务类型 1课程
*/
public String goodsId;
public String orderType;
}
package com.yidianling.ydl_pay.bean.params;
/**
* @author jiucheng
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/4/24
*/
public class WxPayParam extends CommonPayParam {
public WxPayParam(String payId, int isThreePay) {
super(payId, "wxapp_hz", isThreePay);
}
}
package com.yidianling.ydl_pay.http;
/**
* Post请求表单
*/
public class FormatText {
//key
private String mKey;
//value
private String mValue;
public FormatText(String mKey, String mValue) {
this.mKey = mKey;
this.mValue = mValue;
}
public String getmKey() {
return mKey;
}
public String getmValue() {
return mValue;
}
@Override
public String toString() {
return "FormatText{" +
"mKey='" + mKey + '\'' +
", mValue='" + mValue + '\'' +
'}';
}
}
package com.ydl.ydl_pay.http
/**
* @author jiucheng
* @描述: 网络请求的一些基本参数
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/4/3
*/
object HttpConfig {
var ffrom = ""
/**
* //1表示用户版2表示专家版
*/
var isFromApp = "1"
var version = ""
var osBuild = ""
var accessToken = ""
var uid = ""
/**
* 调试参数:
*仅在debug包下切换环境使用
*
*
* true 测试环境 false 线上环境
* 默认测试环境
*
*
* release包 此参数无效
*/
var isTestEnvironment = true
}
\ No newline at end of file
package com.ydl.ydl_pay.http
import com.google.gson.Gson
import com.ydl.ydl_pay.BuildConfig
import com.ydl.ydl_pay.actionpoint.ActionDataBean
import com.ydl.ydl_pay.bean.*
import com.ydl.ydl_pay.bean.params.*
import com.ydl.ydl_pay.http.response.BaseResponse
import com.ydl.ydl_pay.http.utils.HttpUrlUtils
import com.ydl.ydl_pay.http.utils.NetUtils
import com.ydl.ydl_pay.http.utils.RxHttpUtils
import io.reactivex.Observable
import okhttp3.MediaType
import okhttp3.RequestBody
/**
* @author jiucheng
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/4/17
*/
class HttpUtils {
companion object {
/**
* 获取下单的信息
*/
fun getOrderInfo(bean: OrderRequestBean): Observable<BaseResponse<OrderInfoBean>> {
var str = Gson().toJson(bean)
val body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), str) as RequestBody
return PayRetrofitUtils.getRetrofit().create(PayServices::class.java).getOrderInfo(body)
}
/**
* 验证课程兑换券是否可用
*/
fun checkCourseCoupon(bean: CheckRequestCouponBean): Observable<BaseResponse<CouponCodeInfoBean>> {
var str = Gson().toJson(bean)
val body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), str) as RequestBody
return PayRetrofitUtils.getRetrofit().create(PayServices::class.java).checkCourseCoupon(body)
}
/**
* 下单时候选择优惠券
*/
fun selectCoupon(bean: GetAllCouponRequestBean): Observable<BaseResponse<AllCouponListBean>> {
var str = Gson().toJson(bean)
val body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), str) as RequestBody
return PayRetrofitUtils.getRetrofit().create(PayServices::class.java).selectCoupon(body)
}
/**
* 创建订单
*/
fun createOrder(bean: CreateOrderRequestBean): Observable<BaseResponse<PayOrderBean>> {
var str = Gson().toJson(bean)
val body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), str) as RequestBody
return PayRetrofitUtils.getRetrofit().create(PayServices::class.java).createOrder(body)
}
/**
* 支付宝在线支付
*/
fun getAliPayOrderId(bean: BaseCommand): Observable<BaseResponse<CommonPayRecharge>> {
var params = PayRetrofitUtils.getPostList(bean)
var map = PayRetrofitUtils.getMaps(params)
return PayRetrofitUtils.getRetrofit().newBuilder().baseUrl(HttpUrlUtils.getBaseUrl(HttpConfig.isTestEnvironment, false))
.build().create(PayServices::class.java).getAliPayOrderId(map)
}
/**
* 微信在线支付
*/
fun wxPay(bean: BaseCommand): Observable<BaseResponse<CommonWXPayBean>> {
var params = PayRetrofitUtils.getPostList(bean)
var map = PayRetrofitUtils.getMaps(params)
return PayRetrofitUtils.getRetrofit().newBuilder().baseUrl(HttpUrlUtils.getBaseUrl(HttpConfig.isTestEnvironment, false)).build().create(PayServices::class.java).wxPay(map)
}
/**
* 行为数据埋点统计接口
*/
internal fun actionDataCount(actionDataParams: ActionDataBean): Observable<BaseResponse<String>> {
val body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), Gson().toJson(actionDataParams))
return PayRetrofitUtils.getRetrofit().newBuilder().baseUrl(HttpUrlUtils.geActionUrl(HttpConfig.isTestEnvironment)).build().create(PayServices::class.java).actionDataCount(body)
}
}
}
package com.ydl.ydl_pay.http
import android.annotation.SuppressLint
import com.facebook.stetho.okhttp3.StethoInterceptor
import com.ydl.ydl_pay.BuildConfig
import com.ydl.ydl_pay.bean.params.BaseCommand
import com.ydl.ydl_pay.http.log.LogUtil
import com.ydl.ydl_pay.http.utils.HttpUrlUtils
import okhttp3.FormBody
import okhttp3.MultipartBody
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import okio.Buffer
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import java.security.KeyManagementException
import java.security.MessageDigest
import java.security.NoSuchAlgorithmException
import java.security.SecureRandom
import java.security.cert.X509Certificate
import java.util.*
import java.util.concurrent.TimeUnit
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.TrustManager
import javax.net.ssl.X509TrustManager
/**
* @author jiucheng
* @描述:支付模块的网络请求
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/4/3
*/
class PayRetrofitUtils private constructor() {
private lateinit var config: HttpConfig
companion object {
private const val AUTHORIZATION_NAME = "Authorization"
private const val SESSION_KEY_DEFAULT_VALUE = "dc59cf294f37d237c1f06240568ffe21"
private const val YDL = "Ydl "
private const val UID = "uid"
private const val FFROM = "ffrom"
private const val IS_FROM_APP = "isFromApp"//1表示用户版2表示专家版
private const val OS_BUILD = "osBuild"
private const val TS = "ts"
private const val VERSION = "version"
private const val TOKEN = "accessToken"
private const val DEFAULT_TIMEOUT = 15
private const val OS_TYPE = "osType"// 1.ios 2.android
private fun getInstance(): PayRetrofitUtils {
return Holder.INSTANCE
}
fun setConfig(config: HttpConfig) {
getInstance().config = config
}
// 调用此方法获取 Retrofit 对象
fun getRetrofit(): Retrofit {
return getInstance().retrofit
}
fun getPostList(crq: BaseCommand): List<FormatText> {
val formTextList = ArrayList<FormatText>()
val fields = crq.javaClass.fields
for (field in fields) {
try {
val accessFlag = field.isAccessible
field.isAccessible = true
val o = field.get(crq)
if (o != null) {
val formatText = FormatText(field.name, o.toString())
formTextList.add(formatText)
}
field.isAccessible = accessFlag
} catch (e: IllegalAccessException) {
e.printStackTrace()
}
}
return formTextList
}
//获取网络请求表
fun getMaps(list: List<FormatText>): Map<String, String> {
val map = HashMap<String, String>()
val size = list.size
for (i in 0 until size) {
val formatText = list[i]
map[formatText.getmKey()] = formatText.getmValue().toString()
}
return map
}
}
private val retrofit: Retrofit by lazy {
Retrofit.Builder()
.baseUrl(getBaseJavaUrl())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(getOkHttp())
.build()
}
private fun getBaseJavaUrl(): String {
return HttpUrlUtils.getBaseUrl(config.isTestEnvironment, true)
}
private fun getOkHttp(): OkHttpClient {
val builder = OkHttpClient.Builder()
builder.retryOnConnectionFailure(false)
builder.addInterceptor { chain ->
val body = chain.request().body()
val list = ArrayList<FormatText>()
if (body is FormBody) {
val formBody = body as FormBody?
for (i in 0 until formBody!!.size()) {
list.add(FormatText(formBody.name(i), formBody.value(i)))
}
}
if (body is MultipartBody) {
val multipartBody = body as MultipartBody?
val parts = multipartBody!!.parts()
for (part in parts) {
if ("text/plain; charset=utf-8" == part.body().contentType()!!.toString()) {
val headerStr = part.headers()!!.toString()
val name = headerStr.split("\"\\n".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[0].split("=\"".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[1]
val buffer = Buffer()
part.body().writeTo(buffer)
val value = buffer.readUtf8()
list.add(FormatText(name, value))
}
}
}
val head = YDL + getSign(list)
LogUtil.i("RetrofitLog", "head = $head")
val build = chain.request()
.newBuilder()
.header(AUTHORIZATION_NAME, head)
.addHeader(FFROM, config.ffrom)
.addHeader(IS_FROM_APP, config.isFromApp)
.addHeader(VERSION, config.version)
.addHeader(OS_BUILD, config.osBuild)
.addHeader(OS_TYPE, "2")
.addHeader(TOKEN, config.accessToken)
.addHeader(TS, (System.currentTimeMillis() / 1000).toString())
.addHeader(UID, config.uid)
chain.proceed(build.build())
}
if (BuildConfig.DEBUG) {
builder.addInterceptor(HttpLoggingInterceptor { message ->
//打印retrofit日志
LogUtil.i("RetrofitLog", "retrofitBack = $message")
}.setLevel(HttpLoggingInterceptor.Level.BODY))
builder.addNetworkInterceptor(StethoInterceptor())
}
//使用自定义SSLSocketFactory
val factory = createSSLSocketFactory()
if (factory != null) {
builder.sslSocketFactory(factory)
.hostnameVerifier { _, _ -> true }
}
builder.connectTimeout(DEFAULT_TIMEOUT.toLong(), TimeUnit.SECONDS)
.readTimeout(DEFAULT_TIMEOUT.toLong(), TimeUnit.SECONDS)
.writeTimeout(DEFAULT_TIMEOUT.toLong(), TimeUnit.SECONDS)
return builder.build()
}
//获取请求头签名
private fun getSign(list: List<FormatText>): String? {
//将请求参数倒序排列
Collections.sort(list, SortData())
val stringBuilder = StringBuilder()
val size = list.size
for (i in 0 until size) {
val formatText = list[i]
if (i != 0) {
stringBuilder.append("&")
}
stringBuilder.append(String.format("%s=%s", formatText.getmKey(), formatText.getmValue()))
}
stringBuilder.append(SESSION_KEY_DEFAULT_VALUE)
return digestMD5(stringBuilder.toString())
}
//用来命名排序规则的
internal class SortData : Comparator<FormatText> {
override fun compare(lhs: FormatText, rhs: FormatText): Int {
val res = lhs.getmKey().compareTo(rhs.getmKey())
if (res == 0) {
return 0
}
return if (res > 0) -1 else 1
}
}
/**
* 用于MD5加密
*
* @param clear 明文
* @return 密文
*/
private fun digestMD5(clear: String): String? {
val hexDigits = charArrayOf('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f')
try {
val strTemp = clear.toByteArray(charset("utf-8"))
// 使用MD5创建MessageDigest对象
val mdTemp = MessageDigest.getInstance("MD5")
mdTemp.update(strTemp)
val md = mdTemp.digest()
val j = md.size
val str = CharArray(j * 2)
var k = 0
for (b in md) {
// 将每个数(int)b进行双字节加密
str[k++] = hexDigits[b.toInt() shr 4 and 0xf]
str[k++] = hexDigits[b.toInt() and 0xf]
}
return String(str)
} catch (e: Exception) {
return null
}
}
/**
* 默认信任所有的证书
*/
@SuppressLint("TrustAllX509TrustManager")
private fun createSSLSocketFactory(): SSLSocketFactory? {
val xtm = object : X509TrustManager {
override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {}
override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {}
override fun getAcceptedIssuers(): Array<X509Certificate?> {
return arrayOfNulls(0)
}
}
val sslContext: SSLContext
try {
sslContext = SSLContext.getInstance("SSL")
sslContext.init(null, arrayOf<TrustManager>(xtm), SecureRandom())
} catch (e: NoSuchAlgorithmException) {
e.printStackTrace()
return null
} catch (e: KeyManagementException) {
e.printStackTrace()
return null
}
return sslContext.socketFactory
}
private object Holder {
val INSTANCE = PayRetrofitUtils()
}
}
\ No newline at end of file
package com.ydl.ydl_pay.http
import com.ydl.ydl_pay.bean.*
import com.ydl.ydl_pay.http.response.BaseResponse
import io.reactivex.Observable
import okhttp3.RequestBody
import retrofit2.http.Body
import retrofit2.http.FieldMap
import retrofit2.http.FormUrlEncoded
import retrofit2.http.POST
/**
* @author jiucheng
* @描述:支付相关的接口
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/4/16
*/
interface PayServices {
/**
* 获取下单的信息
*/
@POST("auth/Order/getOrderInfo")
fun getOrderInfo(@Body body: RequestBody): Observable<BaseResponse<OrderInfoBean>>
/**
* 验证课程兑换券是否可用
*/
@POST("auth/course/checkCourseCoupon")
fun checkCourseCoupon(@Body body: RequestBody): Observable<BaseResponse<CouponCodeInfoBean>>
/**
* 下单时候选择优惠券
*/
@POST("auth/new_coupon/selectCoupon")
fun selectCoupon(@Body body: RequestBody): Observable<BaseResponse<AllCouponListBean>>
/**
* 创建订单
*/
@POST("auth/Order/createOrder")
fun createOrder(@Body body: RequestBody): Observable<BaseResponse<PayOrderBean>>
/**
* 支付宝在线支付
*/
@FormUrlEncoded
@POST("pay/get-recharge")
fun getAliPayOrderId(@FieldMap params: Map<String, String>): Observable<BaseResponse<CommonPayRecharge>>
/**
* 微信在线支付
*/
@FormUrlEncoded
@POST("pay/to-pay")
fun wxPay(@FieldMap params: Map<String, String>): Observable<BaseResponse<CommonWXPayBean>>
//行为动作埋点统计接口
@POST("maidian/writeMaiDianData")
fun actionDataCount(@Body body: RequestBody): Observable<BaseResponse<String>>
}
\ No newline at end of file
package com.yidianling.ydl_pay.http.log;
import android.util.Log;
import com.ydl.ydl_pay.BuildConfig;
/**
* LogUtil
* Created by Jim on 2017/11/2 0002.
*/
@SuppressWarnings("unused")
public class LogUtil {
private static String className;//类名
private static String methodName;//方法名
private static int lineNumber;//行数
private static String lastMethodName;
private static boolean debug = BuildConfig.DEBUG;
public static String TAG = "hzs";
private LogUtil() {
}
private static String printLog(String log) {
return "| " + Thread.currentThread().getName() + " | " +
lastMethodName+"() -->" + methodName + "() | " +
" (" + className + ":" + lineNumber + ") | " +
log;
}
private static void getMethodNames(StackTraceElement[] sElements) {
className = sElements[1].getFileName();
methodName = sElements[1].getMethodName();
lineNumber = sElements[1].getLineNumber();
lastMethodName=sElements[2].getMethodName();
}
public static void e(String message) {
if (debug) {
getMethodNames(new Throwable().getStackTrace());
Log.e(TAG, printLog(message));
}
}
public static void e(String tag, String message) {
if (debug) {
getMethodNames(new Throwable().getStackTrace());
Log.e(TAG + "_" + tag, printLog(message));
}
}
public static void i(String message) {
if (debug) {
getMethodNames(new Throwable().getStackTrace());
Log.i(TAG, printLog(message));
}
}
public static void i(String tag, String message) {
if (debug) {
getMethodNames(new Throwable().getStackTrace());
Log.i(TAG + "_" + tag, printLog(message));
}
}
public static void d(String message) {
if (debug) {
getMethodNames(new Throwable().getStackTrace());
Log.d(TAG, printLog(message));
}
}
public static void d(String tag, String message) {
if (debug) {
getMethodNames(new Throwable().getStackTrace());
Log.d(TAG + "_" + tag, printLog(message));
}
}
public static void v(String message) {
if (debug) {
getMethodNames(new Throwable().getStackTrace());
Log.v(TAG, printLog(message));
}
}
public static void v(String tag, String message) {
if (debug) {
getMethodNames(new Throwable().getStackTrace());
Log.v(TAG + "_" + tag, printLog(message));
}
}
public static void w(String message) {
if (debug) {
getMethodNames(new Throwable().getStackTrace());
Log.w(TAG, printLog(message));
}
}
public static void w(String tag, String message) {
if (debug) {
getMethodNames(new Throwable().getStackTrace());
Log.w(TAG + "_" + tag, printLog(message));
}
}
public static void wtf(String message) {
if (debug) {
getMethodNames(new Throwable().getStackTrace());
Log.wtf(TAG, printLog(message));
}
}
}
package com.yidianling.ydl_pay.http.response;
import com.google.gson.annotations.SerializedName;
/**
* 基础返回数据类
* Created by Dog on 2015/5/8.
*/
public class BaseResponse<T> {
public int code;
public String msg;
public int status;
@SerializedName("total_page")
public int totalPage;
public T data;
}
package com.yidianling.ydl_pay.http.utils;
import com.ydl.ydl_pay.BuildConfig;
/**
* @author jiucheng
* @描述:获取api的baseUrl
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/4/23
*/
public class HttpUrlUtils {
private static final String JAVA_BASE_URL = "https://api.ydl.com/api/";
private static final String ACTION_BASE_URL = "https://api.ydl.com/api/data/bigdata/";
private static final String PHP_BASE_URL = "https://app2.yidianling.com/v3/";
private static final String DEBUG_JAVA_BASE_URL = "http://testapi.ydl.com/api/";
private static final String DEBUG_PHP_BASE_URL = "https://testapp2.yidianling.com/v3/";
private static final String DEBUG_ACTION_BASE_URL = "https://testapi.ydl.com/api/data/bigdata/";
/**
* 获取baseUrl
*
* @param isTestEnvironment 是否是测试环境
* @param isJava 是否是java url
* @return
*/
public static String getBaseUrl(boolean isTestEnvironment, boolean isJava) {
String baseUrl;
if (BuildConfig.DEBUG) {//debug包
if (isTestEnvironment) {//测试环境
if (isJava) {
baseUrl = DEBUG_JAVA_BASE_URL;
} else {
baseUrl = DEBUG_PHP_BASE_URL;
}
} else {
if (isJava) {
baseUrl = JAVA_BASE_URL;
} else {
baseUrl = PHP_BASE_URL;
}
}
} else {//release 包
if (isJava) {
baseUrl = JAVA_BASE_URL;
} else {
baseUrl = PHP_BASE_URL;
}
}
return baseUrl;
}
/**
* 获取埋点的baseurl
*
* @param isTestEnvironment 是否是测试环境
* @return
*/
public static String geActionUrl(boolean isTestEnvironment) {
String baseUrl;
if (BuildConfig.DEBUG) {//debug包
if (isTestEnvironment) {//测试环境
baseUrl = DEBUG_ACTION_BASE_URL;
} else {
baseUrl = ACTION_BASE_URL;
}
} else {//release 包
baseUrl = DEBUG_ACTION_BASE_URL;
}
return baseUrl;
}
}
package com.yidianling.ydl_pay.http.utils;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.telephony.TelephonyManager;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* Created by vonde on 2016/1/29.
*/
public class NetUtils {
public static final int NETWORK_NO = -1; // no network
public static final int NETWORK_WIFI = 1; // wifi network
public static final int NETWORK_2G = 2; // "2G" networks
public static final int NETWORK_3G = 3; // "3G" networks
public static final int NETWORK_4G = 4; // "4G" networks
public static final int NETWORK_UNKNOWN = 5; // unknown network
private static final int NETWORK_TYPE_GSM = 16;
private static final int NETWORK_TYPE_TD_SCDMA = 17;
private static final int NETWORK_TYPE_IWLAN = 18;
/**
* 需添加权限
*
* @param context 上下文
* @return 网络类型
* @code <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
* <p>
* 它主要负责的是
* 1 监视网络连接状态 包括(Wi-Fi, 2G, 3G, 4G)
* 2 当网络状态改变时发送广播通知
* 3 网络连接失败尝试连接其他网络
* 4 提供API,允许应用程序获取可用的网络状态
* <p>
* netTyped 的结果
* @link #NETWORK_NO = -1; 当前无网络连接
* @link #NETWORK_WIFI = 1; wifi的情况下
* @link #NETWORK_2G = 2; 切换到2G环境下
* @link #NETWORK_3G = 3; 切换到3G环境下
* @link #NETWORK_4G = 4; 切换到4G环境下
* @link #NETWORK_UNKNOWN = 5; 未知网络
*/
public static int getNetWorkType(Context context) {
// 获取ConnectivityManager
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo ni = cm.getActiveNetworkInfo();// 获取当前网络状态
int netType = NETWORK_NO;
if (ni != null && ni.isConnectedOrConnecting()) {
switch (ni.getType()) {//获取当前网络的状态
case ConnectivityManager.TYPE_WIFI:// wifi的情况下
netType = NETWORK_WIFI;
// ToastUtil.toastShort("切换到wifi环境下");
break;
case ConnectivityManager.TYPE_MOBILE:
switch (ni.getSubtype()) {
case NETWORK_TYPE_GSM:
case TelephonyManager.NETWORK_TYPE_GPRS: // 联通2g
case TelephonyManager.NETWORK_TYPE_CDMA: // 电信2g
case TelephonyManager.NETWORK_TYPE_EDGE: // 移动2g
case TelephonyManager.NETWORK_TYPE_1xRTT:
case TelephonyManager.NETWORK_TYPE_IDEN:
netType = NETWORK_2G;
// ToastUtil.toastShort("切换到2G环境下");
break;
case TelephonyManager.NETWORK_TYPE_EVDO_A: // 电信3g
case TelephonyManager.NETWORK_TYPE_UMTS:
case TelephonyManager.NETWORK_TYPE_EVDO_0:
case TelephonyManager.NETWORK_TYPE_HSDPA:
case TelephonyManager.NETWORK_TYPE_HSUPA:
case TelephonyManager.NETWORK_TYPE_HSPA:
case TelephonyManager.NETWORK_TYPE_EVDO_B:
case TelephonyManager.NETWORK_TYPE_EHRPD:
case TelephonyManager.NETWORK_TYPE_HSPAP:
case NETWORK_TYPE_TD_SCDMA:
netType = NETWORK_3G;
// ToastUtil.toastShort("切换到3G环境下");
break;
case TelephonyManager.NETWORK_TYPE_LTE:
case NETWORK_TYPE_IWLAN:
netType = NETWORK_4G;
// ToastUtil.toastShort("切换到4G环境下");
break;
default:
String subtypeName = ni.getSubtypeName();
if (subtypeName.equalsIgnoreCase("TD-SCDMA")
|| subtypeName.equalsIgnoreCase("WCDMA")
|| subtypeName.equalsIgnoreCase("CDMA2000")) {
netType = NETWORK_3G;
} else {
netType = NETWORK_UNKNOWN;
}
// ToastUtil.toastShort("未知网络");
}
break;
default:
netType = 5;
// ToastUtil.toastShort("未知网络");
}
} else {
netType = NETWORK_NO;
// ToastUtil.toastShort("当前无网络连接");
}
return netType;
}
/**
* 获取当前的网络类型(WIFI,2G,3G,4G)
* <p>依赖上面的方法</p>
*
* @param context 上下文
* @return 网络类型名称
* <ul>
* <li>NETWORK_WIFI </li>
* <li>NETWORK_4G </li>
* <li>NETWORK_3G </li>
* <li>NETWORK_2G </li>
* <li>NETWORK_UNKNOWN</li>
* <li>NETWORK_NO </li>
* </ul>
*/
public static String getNetWorkTypeName(Context context) {
switch (getNetWorkType(context)) {
case NETWORK_WIFI:
return "NETWORK_WIFI";
case NETWORK_4G:
return "NETWORK_4G";
case NETWORK_3G:
return "NETWORK_3G";
case NETWORK_2G:
return "NETWORK_2G";
case NETWORK_NO:
return "NETWORK_NO";
default:
return "NETWORK_UNKNOWN";
}
}
/**
* 判断网络连接是否可用
*/
public static boolean isNetworkAvailable(Context context) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (cm == null) {
} else {
//如果仅仅是用来判断网络连接
//则可以使用 cm.getActiveNetworkInfo().isAvailable();
NetworkInfo[] info = cm.getAllNetworkInfo();
if (info != null) {
for (int i = 0; i < info.length; i++) {
if (info[i].getState() == NetworkInfo.State.CONNECTED) {
return true;
}
}
}
}
return false;
}
/**
* 判断网络是否可用
* 需添加权限
*
* @code <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
*/
public static boolean isAvailable(Context context) {
NetworkInfo info = getActiveNetworkInfo(context);
return info != null && info.isAvailable();
}
/**
* 判断网络是否连接
* 需添加权限
*
* @code <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
*/
public static boolean isConnected(Context context) {
NetworkInfo info = getActiveNetworkInfo(context);
return info != null && info.isConnected();
}
/**
* 判断是否有外网连接(普通方法不能判断外网的网络是否连接,比如连接上局域网)
* 不要在主线程使用,会阻塞线程
*/
public static final boolean ping() {
String result = null;
try {
String ip = "www.baidu.com";// ping 的地址,可以换成任何一种可靠的外网
Process p = Runtime.getRuntime().exec("ping -c 3 -w 100 " + ip);// ping网址3次
// 读取ping的内容,可以不加
InputStream input = p.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(input));
StringBuffer stringBuffer = new StringBuffer();
String content = "";
while ((content = in.readLine()) != null) {
stringBuffer.append(content);
}
// Log.d("------ping-----", "result content : " + stringBuffer.toString());
// ping的状态
int status = p.waitFor();
if (status == 0) {
result = "success";
return true;
} else {
result = "failed";
}
} catch (IOException e) {
result = "IOException";
} catch (InterruptedException e) {
result = "InterruptedException";
} finally {
// Log.d("----result---", "result = " + result);
}
return false;
}
/**
* 判断WIFI是否打开
*/
public static boolean isWifiEnabled(Context context) {
ConnectivityManager mgrConn = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
TelephonyManager mgrTel = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
return ((mgrConn.getActiveNetworkInfo() != null
&& mgrConn.getActiveNetworkInfo().getState() == NetworkInfo.State.CONNECTED)
|| mgrTel.getNetworkType() == TelephonyManager.NETWORK_TYPE_UMTS);
}
/**
* 判断网络连接方式是否为WIFI
*/
public static boolean isWifi(Context context) {
NetworkInfo networkINfo = getActiveNetworkInfo(context);
return networkINfo != null && networkINfo.getType() == ConnectivityManager.TYPE_WIFI;
}
/**
* 判断wifi是否连接状态
* <p>需添加权限 {@code <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>}</p>
*
* @param context 上下文
* @return {@code true}: 连接<br>{@code false}: 未连接
*/
public static boolean isWifiConnected(Context context) {
ConnectivityManager cm = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
return cm != null && cm.getActiveNetworkInfo() != null
&& cm.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI;
}
/**
* 判断是否为3G网络
*/
public static boolean is3rd(Context context) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkINfo = cm.getActiveNetworkInfo();
return networkINfo != null
&& networkINfo.getType() == ConnectivityManager.TYPE_MOBILE;
}
/**
* 判断网络是否是4G
* 需添加权限
*
* @code <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
*/
public static boolean is4G(Context context) {
NetworkInfo info = getActiveNetworkInfo(context);
return info != null && info.isAvailable() && info.getSubtype() == TelephonyManager.NETWORK_TYPE_LTE;
}
// /**
// * GPS是否打开
// *
// * @param context
// * @return
// */
// public static boolean isGpsEnabled(Context context) {
// LocationManager lm = ((LocationManager) context.getSystemService(Context.LOCATION_SERVICE));
// List<String> accessibleProviders = lm.getProviders(true);
// return accessibleProviders != null && accessibleProviders.size() > 0;
// }
/*
* 下面列举几个可直接跳到联网设置的意图,供大家学习
*
* startActivity(new Intent(android.provider.Settings.ACTION_APN_SETTINGS));
* startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS));
*
* 用下面两种方式设置网络
*
* startActivity(new Intent(android.provider.Settings.ACTION_WIFI_SETTINGS));
* startActivity(new Intent(android.provider.Settings.ACTION_WIRELESS_SETTINGS));
*/
/**
* 打开网络设置界面
* <p>3.0以下打开设置界面</p>
*
* @param context 上下文
*/
public static void openWirelessSettings(Context context) {
if (Build.VERSION.SDK_INT > 10) {
context.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS));
} else {
context.startActivity(new Intent(android.provider.Settings.ACTION_WIRELESS_SETTINGS));
}
}
/**
* 获取活动网络信息
*
* @param context 上下文
* @return NetworkInfo
*/
private static NetworkInfo getActiveNetworkInfo(Context context) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
return cm.getActiveNetworkInfo();
}
/**
* 获取移动网络运营商名称
* <p>如中国联通、中国移动、中国电信</p>
*
* @param context 上下文
* @return 移动网络运营商名称
*/
public static String getNetworkOperatorName(Context context) {
TelephonyManager tm = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
return tm != null ? tm.getNetworkOperatorName() : null;
}
/**
* 获取移动终端类型
*
* @param context 上下文
* @return 手机制式
* <ul>
* <li>{@link TelephonyManager#PHONE_TYPE_NONE } : 0 手机制式未知</li>
* <li>{@link TelephonyManager#PHONE_TYPE_GSM } : 1 手机制式为GSM,移动和联通</li>
* <li>{@link TelephonyManager#PHONE_TYPE_CDMA } : 2 手机制式为CDMA,电信</li>
* <li>{@link TelephonyManager#PHONE_TYPE_SIP } : 3</li>
* </ul>
*/
public static int getPhoneType(Context context) {
TelephonyManager tm = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
return tm != null ? tm.getPhoneType() : -1;
}
}
package com.yidianling.ydl_pay.http.utils;
import android.app.Activity;
import android.app.KeyguardManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Surface;
import android.view.View;
import android.view.WindowManager;
import java.lang.reflect.Method;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* 设备工具类
* Created by vondear on 2016/1/24.
*/
public class RxDeviceTool {
private static Context mContext;
public static void initContext(Context context) {
mContext = context;
}
public static Context getContext() {
return mContext;
}
/**
* 得到屏幕的高
*
* @param context
* @return
*/
public static int getScreenHeight(Context context) {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
int height = wm.getDefaultDisplay().getHeight();
return height;
}
public static String getIP(Context context) {
try {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
NetworkInterface intf = en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
InetAddress inetAddress = enumIpAddr.nextElement();
if (!inetAddress.isLoopbackAddress() && (inetAddress instanceof Inet4Address)) {
return inetAddress.getHostAddress().toString();
}
}
}
} catch (SocketException ex) {
ex.printStackTrace();
}
return null;
}
/**
* 得到屏幕的宽
*
* @param context
* @return
*/
public static int getScreenWidth(Context context) {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
int width = wm.getDefaultDisplay().getWidth();
return width;
}
/**
* 得到设备屏幕的宽度
*/
public static int getScreenWidths(Context context) {
return context.getResources().getDisplayMetrics().widthPixels;
}
/**
* 得到设备屏幕的高度
*/
public static int getScreenHeights(Context context) {
return context.getResources().getDisplayMetrics().heightPixels;
}
/**
* 得到设备的密度
*/
public static float getScreenDensity(Context context) {
return context.getResources().getDisplayMetrics().density;
}
/**
* 获取手机唯一标识序列号
*
* @return
*/
public static String getUniqueSerialNumber() {
String phoneName = Build.MODEL;// Galaxy nexus 品牌类型
String manuFacturer = Build.MANUFACTURER;//samsung 品牌
Log.d("详细序列号", manuFacturer + "-" + phoneName + "-" + getSerialNumber());
return manuFacturer + "-" + phoneName + "-" + getSerialNumber();
}
/**
* IMEI (唯一标识序列号)
* <p>需与{@link #isPhone(Context)}一起使用</p>
* <p>需添加权限 {@code <uses-permission android:name="android.permission.READ_PHONE_STATE"/>}</p>
*
* @param context 上下文
* @return IMEI
*/
// public static String getIMEI(Context context) {
// String deviceId;
// if (isPhone(context)) {
// deviceId = getDeviceIdIMEI(context);
// } else {
// deviceId = getAndroidId(context);
// }
// return deviceId;
// }
/**
* 获取设备的IMSI
*
* @param context
* @return
*/
// public static String getIMSI(Context context) {
// return getSubscriberId(context);
// }
/**
* 获取设备的IMEI
*
* @param context
* @return
*/
// public static String getDeviceIdIMEI(Context context) {
// String id;
// //android.telephony.TelephonyManager
// TelephonyManager mTelephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
// if (mTelephony.getDeviceId() != null) {
// id = mTelephony.getDeviceId();
// } else {
// //android.provider.Settings;
// id = Settings.Secure.getString(context.getApplicationContext().getContentResolver(), Settings.Secure.ANDROID_ID);
// }
// return id;
// }
/**
* 获取设备的软件版本号
*
* @param context
* @return
*/
// public static String getDeviceSoftwareVersion(Context context) {
// TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
// return tm.getDeviceSoftwareVersion();
// }
/**
* 获取android系统版本号
*/
public static String getOsBuileVersion() {
return Build.VERSION.RELEASE;
}
/**
* 获取手机号
*
* @param context
* @return
*/
// public static String getLine1Number(Context context) {
// TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
// return tm.getLine1Number();
// }
/**
* 获取ISO标准的国家码,即国际长途区号
*
* @param context
* @return
*/
public static String getNetworkCountryIso(Context context) {
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
return tm.getNetworkCountryIso();
}
/**
* 获取设备的 MCC + MNC
*
* @param context
* @return
*/
public static String getNetworkOperator(Context context) {
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
return tm.getNetworkOperator();
}
/**
* 获取(当前已注册的用户)的名字
*
* @param context
* @return
*/
public static String getNetworkOperatorName(Context context) {
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
return tm.getNetworkOperatorName();
}
/**
* 获取当前使用的网络类型
*
* @param context
* @return
*/
public static int getNetworkType(Context context) {
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
return tm.getNetworkType();
}
/**
* 获取手机类型
*
* @param context
* @return
*/
public static int getPhoneType(Context context) {
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
return tm.getPhoneType();
}
/**
* 获取SIM卡的国家码
*
* @param context
* @return
*/
public static String getSimCountryIso(Context context) {
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
return tm.getSimCountryIso();
}
/**
* 获取SIM卡提供的移动国家码和移动网络码.5或6位的十进制数字
*
* @param context
* @return
*/
public static String getSimOperator(Context context) {
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
return tm.getSimOperator();
}
/**
* 获取服务商名称
*
* @param context
* @return
*/
public static String getSimOperatorName(Context context) {
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
return tm.getSimOperatorName();
}
/**
* 获取SIM卡的序列号
*
* @param context
* @return
*/
// public static String getSimSerialNumber(Context context) {
// TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
// return tm.getSimSerialNumber();
// }
/**
* 获取SIM的状态信息
*
* @param context
* @return
*/
public static int getSimState(Context context) {
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
return tm.getSimState();
}
/**
* 获取唯一的用户ID
*
* @param context
* @return
*/
// public static String getSubscriberId(Context context) {
// TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
// return tm.getSubscriberId();
// }
/**
* 获取语音邮件号码
*
* @param context
* @return
*/
// public static String getVoiceMailNumber(Context context) {
// TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
// return tm.getVoiceMailNumber();
// }
/**
* 获取ANDROID ID
*
* @param context
* @return
*/
public static String getAndroidId(Context context) {
return Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
}
/**
* 获取设备型号,如MI2SC
*
* @return 设备型号
*/
public static String getBuildBrandModel() {
return Build.MODEL;// Galaxy nexus 品牌类型
}
public static String getBuildBrand() {
return Build.BRAND;//google
}
/**
* 获取设备厂商,如Xiaomi
*
* @return 设备厂商
*/
public static String getBuildMANUFACTURER() {
return Build.MANUFACTURER;// samsung 品牌
}
/**
* 序列号
*
* @return
*/
public static String getSerialNumber() {
String serial = null;
try {
Class<?> c = Class.forName("android.os.SystemProperties");
Method get = c.getMethod("get", String.class);
serial = (String) get.invoke(c, "ro.serialno");
} catch (Exception e) {
e.printStackTrace();
}
return serial;
}
/**
* 获取App版本名称
*
* @param context
* @return
*/
public static String getAppVersionName(Context context) {
// 获取packagemanager的实例
PackageManager packageManager = context.getPackageManager();
// getPackageName()是你当前类的包名,0代表是获取版本信息
PackageInfo packInfo = null;
try {
packInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
if (packInfo == null) {
return "";
}
return packInfo.versionName;
}
/**
* 获取App版本号
*
* @param context
* @return
*/
public static int getAppVersionNo(Context context) {
// 获取packagemanager的实例
PackageManager packageManager = context.getPackageManager();
// getPackageName()是你当前类的包名,0代表是获取版本信息
PackageInfo packInfo = null;
try {
packInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
int version = packInfo.versionCode;
return version;
}
/**
* 检查权限
*
* @param context
* @param permission 例如 Manifest.permission.READ_PHONE_STATE
* @return
*/
public static boolean checkPermission(Context context, String permission) {
boolean result = false;
if (Build.VERSION.SDK_INT >= 23) {
try {
Class clazz = Class.forName("android.content.Context");
Method method = clazz.getMethod("checkSelfPermission", String.class);
int rest = (Integer) method.invoke(context, permission);
result = rest == PackageManager.PERMISSION_GRANTED;
} catch (Exception e) {
result = false;
}
} else {
PackageManager pm = context.getPackageManager();
if (pm.checkPermission(permission, context.getPackageName()) == PackageManager.PERMISSION_GRANTED) {
result = true;
}
}
return result;
}
/**
* 获取设备信息
*
* @param context
* @return
*/
// public static String getDeviceInfo(Context context) {
// try {
// org.json.JSONObject json = new org.json.JSONObject();
// TelephonyManager tm = (TelephonyManager) context
// .getSystemService(Context.TELEPHONY_SERVICE);
// String device_id = null;
// if (checkPermission(context, Manifest.permission.READ_PHONE_STATE)) {
// device_id = getDeviceIdIMEI(context);
// }
// String mac = null;
// FileReader fstream = null;
// try {
// fstream = new FileReader("/sys/class/net/wlan0/address");
// } catch (FileNotFoundException e) {
// fstream = new FileReader("/sys/class/net/eth0/address");
// }
// BufferedReader in = null;
// if (fstream != null) {
// try {
// in = new BufferedReader(fstream, 1024);
// mac = in.readLine();
// } catch (IOException e) {
// } finally {
// if (fstream != null) {
// try {
// fstream.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
// if (in != null) {
// try {
// in.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
// }
// }
// json.put("mac", mac);
// if (TextUtils.isEmpty(device_id)) {
// device_id = mac;
// }
// if (TextUtils.isEmpty(device_id)) {
// device_id = Settings.Secure.getString(context.getContentResolver(),
// Settings.Secure.ANDROID_ID);
// }
// json.put("device_id", device_id);
// return json.toString();
// } catch (Exception e) {
// e.printStackTrace();
// }
// return null;
// }
/**
* 遍历LOG输出HashMap
*
* @param res
*/
public static void ThroughArray(HashMap res) {
Iterator ite = res.entrySet().iterator();
while (ite.hasNext()) {
Map.Entry entry = (Map.Entry) ite.next();
Object key = entry.getKey();
Object value = entry.getValue();
Log.d("MSG_AUTH_COMPLETE", (key + ": " + value));
}
}
/**
* 判断设备是否是手机
*
* @param context 上下文
* @return {@code true}: 是<br>{@code false}: 否
*/
public static boolean isPhone(Context context) {
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
return tm.getPhoneType() != TelephonyManager.PHONE_TYPE_NONE;
}
/**
* 获取手机状态信息
* <p>需添加权限 {@code <uses-permission android:name="android.permission.READ_PHONE_STATE"/>}</p>
*
* @param context 上下文
* @return DeviceId(IMEI) = 99000311726612<br>
* DeviceSoftwareVersion = 00<br>
* Line1Number =<br>
* NetworkCountryIso = cn<br>
* NetworkOperator = 46003<br>
* NetworkOperatorName = 中国电信<br>
* NetworkType = 6<br>
* honeType = 2<br>
* SimCountryIso = cn<br>
* SimOperator = 46003<br>
* SimOperatorName = 中国电信<br>
* SimSerialNumber = 89860315045710604022<br>
* SimState = 5<br>
* SubscriberId(IMSI) = 460030419724900<br>
* VoiceMailNumber = *86<br>
*/
public static String getPhoneStatus(Context context) {
TelephonyManager tm = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
String str = "";
// str += "DeviceId(IMEI) = " + getDeviceIdIMEI(context) + "\n";
// str += "DeviceSoftwareVersion = " + tm.getDeviceSoftwareVersion() + "\n";
// str += "Line1Number = " + tm.getLine1Number() + "\n";
str += "NetworkCountryIso = " + tm.getNetworkCountryIso() + "\n";
str += "NetworkOperator = " + tm.getNetworkOperator() + "\n";
str += "NetworkOperatorName = " + tm.getNetworkOperatorName() + "\n";
str += "NetworkType = " + tm.getNetworkType() + "\n";
str += "honeType = " + tm.getPhoneType() + "\n";
str += "SimCountryIso = " + tm.getSimCountryIso() + "\n";
str += "SimOperator = " + tm.getSimOperator() + "\n";
str += "SimOperatorName = " + tm.getSimOperatorName() + "\n";
// str += "SimSerialNumber = " + tm.getSimSerialNumber() + "\n";
str += "SimState = " + tm.getSimState() + "\n";
// str += "SubscriberId(IMSI) = " + tm.getSubscriberId() + "\n";
// str += "VoiceMailNumber = " + tm.getVoiceMailNumber() + "\n";
return str;
}
/**
* 跳至填充好phoneNumber的拨号界面
*
* @param context 上下文
* @param phoneNumber 电话号码
*/
public static void dial(Context context, String phoneNumber) {
context.startActivity(new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + phoneNumber)));
}
/**
* 打开手机联系人界面点击联系人后便获取该号码
* <p>参照以下注释代码</p>
*/
public static void getContantNum() {
Log.i("tips", "U should copy the following code.");
/*
Intent intent = new Intent();
intent.setAction("android.intent.action.PICK");
intent.setType("vnd.android.cursor.dir/phone_v2");
startActivityForResult(intent, 0);
@Override
protected void onActivityResult ( int requestCode, int resultCode, Intent data){
super.onActivityResult(requestCode, resultCode, data);
if (data != null) {
Uri uri = data.getData();
String num = null;
// 创建内容解析者
ContentResolver contentResolver = getContentResolver();
Cursor cursor = contentResolver.query(uri,
null, null, null, null);
while (cursor.moveToNext()) {
num = cursor.getString(cursor.getColumnIndex("data1"));
}
cursor.close();
num = num.replaceAll("-", "");//替换的操作,555-6 -> 5556
}
}
*/
}
/**
* 设置屏幕为横屏
* <p>还有一种就是在Activity中加属性android:screenOrientation="landscape"</p>
* <p>不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次</p>
* <p>设置Activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次</p>
* <p>设置Activity的android:configChanges="orientation|keyboardHidden|screenSize"(4.0以上必须带最后一个参数)时
* 切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法</p>
*
* @param activity activity
*/
public static void setLandscape(Activity activity) {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
/**
* 设置屏幕为竖屏
*
* @param activity activity
*/
public static void setPortrait(Activity activity) {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
/**
* 判断是否横屏
*
* @param context 上下文
* @return {@code true}: 是<br>{@code false}: 否
*/
public static boolean isLandscape(Context context) {
return context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
}
/**
* 判断是否竖屏
*
* @param context 上下文
* @return {@code true}: 是<br>{@code false}: 否
*/
public static boolean isPortrait(Context context) {
return context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
}
/**
* 获取屏幕旋转角度
*
* @param activity activity
* @return 屏幕旋转角度
*/
public static int getScreenRotation(Activity activity) {
switch (activity.getWindowManager().getDefaultDisplay().getRotation()) {
default:
case Surface.ROTATION_0:
return 0;
case Surface.ROTATION_90:
return 90;
case Surface.ROTATION_180:
return 180;
case Surface.ROTATION_270:
return 270;
}
}
/**
* 获取当前屏幕截图,包含状态栏
*
* @param activity activity
* @return Bitmap
*/
public static Bitmap captureWithStatusBar(Activity activity) {
View view = activity.getWindow().getDecorView();
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap bmp = view.getDrawingCache();
int width = getScreenWidth(activity);
int height = getScreenHeight(activity);
Bitmap ret = Bitmap.createBitmap(bmp, 0, 0, width, height);
view.destroyDrawingCache();
return ret;
}
/**
* 获取DisplayMetrics对象
*
* @param context 应用程序上下文
* @return
*/
public static DisplayMetrics getDisplayMetrics(Context context) {
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics displayMetrics = new DisplayMetrics();
windowManager.getDefaultDisplay().getMetrics(displayMetrics);
return displayMetrics;
}
/**
* 判断是否锁屏
*
* @param context 上下文
* @return {@code true}: 是<br>{@code false}: 否
*/
public static boolean isScreenLock(Context context) {
KeyguardManager km = (KeyguardManager) context
.getSystemService(Context.KEYGUARD_SERVICE);
return km.inKeyguardRestrictedInputMode();
}
/**
* 设置安全窗口,禁用系统截屏。防止 App 中的一些界面被截屏,并显示在其他设备中造成信息泄漏。
* (常见手机设备系统截屏操作方式为:同时按下电源键和音量键。)
*
* @param activity
*/
public static void noScreenshots(Activity activity) {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
}
/**
* Return the version name of device's system.
*
* @return the version name of device's system
*/
public static String getSDKVersionName() {
return Build.VERSION.RELEASE;
}
}
package com.ydl.ydl_pay.http.utils
import com.ydl.ydl_pay.http.response.BaseResponse
import io.reactivex.Observable
import io.reactivex.ObservableTransformer
import java.net.ConnectException
/**
* author : Zhangwenchao
* e-mail : zhangwch@yidianling.com
*/
object RxHttpUtils {
/**
* 根据返回数据,得到真正需要的数据
* 若状态码不为0,抛出接口异常
*/
@JvmStatic
fun <T> resultData(): ObservableTransformer<BaseResponse<T>, T> {
return ObservableTransformer {
it.flatMap {
if (it.code == 0) Observable.just(it.data)
else Observable.error(Throwable(it.msg))
}
}
}
}
package com.ydl.ydl_pay.toast
import android.content.Context
import android.support.annotation.StringRes
import android.text.TextUtils
import android.widget.Toast
/**
* author : Zhangwenchao
* e-mail : zhangwch@yidianling.com
* time : 2018/01/29
*
* 提示信息的封装类,使用单例 toast,防止重复弹出提示
*/
class ToastHelper private constructor() {
private var toast: Toast? = null
companion object {
private fun getInstance(): ToastHelper {
return Holder.INSTANCE
}
fun show(context: Context, text: String) {
getInstance().show(context.applicationContext, text)
}
fun show(context: Context, @StringRes resId: Int) {
getInstance().show(context.applicationContext, resId)
}
}
private fun show(context: Context, text: CharSequence) {
if (TextUtils.isEmpty(text)) return
if (toast == null) toast = Toast.makeText(context, text, Toast.LENGTH_SHORT)
else toast?.setText(text)
toast?.show()
}
private fun show(context: Context, @StringRes resId: Int) {
if (toast == null) toast = Toast.makeText(context, resId, Toast.LENGTH_SHORT)
else toast?.setText(resId)
toast?.show()
}
private object Holder {
val INSTANCE = ToastHelper()
}
}
package com.ydl.ydl_pay.widget
import android.annotation.SuppressLint
import android.content.Context
import android.text.TextUtils
import android.view.View
import android.view.ViewGroup
import android.widget.RelativeLayout
import com.yidianling.ydl_pay.R
import com.yidianling.ydl_pay.bean.CommonCouponBean
import kotlinx.android.synthetic.main.view_coupon_info_detail.view.*
import java.lang.Float
import java.math.BigDecimal
/**
* @author jiucheng
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/4/19
*/
class CouponInfoDetailView(context: Context) : RelativeLayout(context) {
init {
initView()
}
private fun initView() {
val params = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
layoutParams = params
View.inflate(context, R.layout.view_coupon_info_detail, this)
}
@SuppressLint("SetTextI18n")
fun setData(bean: CommonCouponBean, isUseAble: Boolean) {
if (bean.couponType == "1") {//1兑换券
tv_price.text = "¥" + bean.price
} else {//优惠券
tv_price.text = "¥" + bean.amount
if (bean.type == "1") {
tv_price.text = "¥" + bean.amount
} else {
val a1 = BigDecimal(Float.toString(bean.discount.toFloat()))
val b1 = BigDecimal(Float.toString(10f))
val result = a1.multiply(b1).toFloat()// 相乘结果
val discountStr = "${result}折"
tv_price.text = discountStr
}
}
if (bean.couponType == "1") {
tv_discountCont.text = "${bean.price}元以内可用"
tv_discountCont.visibility = View.VISIBLE
}
if (!TextUtils.isEmpty(bean.discountCont)) {
tv_discountCont.text = bean.discountCont
tv_discountCont.visibility = View.VISIBLE
}
if (TextUtils.isEmpty(bean.discountCont) && bean.useCondition == "1") {
tv_discountCont.text = "无限制"
tv_discountCont.visibility = View.VISIBLE
}
tv_title.text = bean.title
tv_duration.text = bean.effective
tv_use_condition.text = bean.rangeCont
if (bean.isTheFailure) {
iv_background.setBackgroundResource(R.drawable.bg_kgq)
} else {
iv_background.setBackgroundResource(R.drawable.item_coupon_background)
}
if (isUseAble) {
iv_select.visibility = View.VISIBLE
if (bean.hasSelected == 1) {
iv_select.setImageResource(R.drawable.img_coupon_selsect)
} else {
iv_select.setImageResource(R.drawable.img_no_select)
}
} else {
iv_select.visibility = View.GONE
tv_title.setTextColor(resources.getColor(R.color.color_666666))
tv_duration.setTextColor(resources.getColor(R.color.color_666666))
tv_use_condition.setTextColor(resources.getColor(R.color.color_666666))
iv_background.setBackgroundResource(R.drawable.item_coupon_background_unuse)
if (bean.isTheFailure) {
iv_background.setBackgroundResource(R.drawable.bg_dis_kgq)
}
}
}
}
package com.yidianling.ydl_pay.widget;
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
/**
* @author jiucheng
* @描述:是否可左右滑动viewp
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/10/15
*/
public class NoScrollViewPager extends ViewPager {
private boolean isCanScroll = false;
public NoScrollViewPager(Context context) {
super(context);
}
public NoScrollViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setScanScroll(boolean isCanScroll) {
this.isCanScroll = isCanScroll;
}
@Override
public void scrollTo(int x, int y) {
super.scrollTo(x, y);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (isCanScroll) {
return super.onTouchEvent(event);
} else {
return false;
}
}
@Override
public void setCurrentItem(int item, boolean smoothScroll) {
super.setCurrentItem(item, smoothScroll);
}
@Override
public void setCurrentItem(int item) {
super.setCurrentItem(item);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (isCanScroll) {
return super.onInterceptTouchEvent(event);
} else {
return false;
}
}
}
package com.ydl.ydl_pay.widget
import android.content.Context
import android.os.Handler
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.text.Editable
import android.text.TextUtils
import android.text.TextWatcher
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
import android.widget.LinearLayout
import android.widget.TextView
import com.ydl.ydl_pay.adapter.SelectCouponAdapter
import com.ydl.ydl_pay.http.HttpUtils
import com.ydl.ydl_pay.toast.ToastHelper
import com.yidianling.ydl_pay.R
import com.yidianling.ydl_pay.bean.AllCouponListBean
import com.yidianling.ydl_pay.bean.CommonCouponBean
import com.yidianling.ydl_pay.bean.params.CheckRequestCouponBean
import com.yidianling.ydl_pay.http.utils.NetUtils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import kotlinx.android.synthetic.main.head_course_code_view.view.*
import kotlinx.android.synthetic.main.view_pay_coupon.view.*
/**
* @author jiucheng
* @描述:支付优惠券选择view
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/4/4
*/
class PayCouponView(context: Context) : LinearLayout(context) {
private var selectedCouponBean: CommonCouponBean? = null
private var couponListBean: AllCouponListBean? = null
private var listener: OnCouponClickListener? = null
private var goodsId: String? = null
private var adapter: SelectCouponAdapter? = null
private var hasUseCouponCode = false
private var courseCodeView: View? = null
private var rt_coupon_code: EditText? = null
private var tv_ensure: TextView? = null
init {
initView()
}
private fun initView() {
orientation = VERTICAL
val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
layoutParams = params
View.inflate(context, R.layout.view_pay_coupon, this)
rl_back.setOnClickListener {
hideSoftInput()
if (listener != null) {
listener!!.onBackClick(selectedCouponBean)
}
}
var linearLayoutManager = LinearLayoutManager(context)
rv_content.layoutManager = linearLayoutManager
}
/**
* 动态隐藏软键盘
*
* @param context 上下文
* @param edit 输入框
*/
private fun hideSoftInput() {
if (rt_coupon_code == null) {
return
}
rt_coupon_code!!.clearFocus()
val inputmanger = context
.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputmanger.hideSoftInputFromWindow(rt_coupon_code!!.windowToken, 0)
}
/**
验证兑换券是否可用
*/
private fun checkCourseCoupon(couponCode: String) {
hideSoftInput()
if (!NetUtils.isConnected(context)) {
ToastHelper.show(context, context.getString(R.string.net_error))
return
}
var bean = CheckRequestCouponBean()
bean.couponCode = couponCode
bean.courseId = goodsId
HttpUtils.checkCourseCoupon(bean)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
if (it.code == 200) {
if (it.data != null) {
if (it.data.couponInfo != null) {
hasUseCouponCode = true
selectedCouponBean = it.data.couponInfo
if (tv_ensure != null) {
tv_ensure!!.text = "取消使用"
}
clearSelectCoupon()
Handler().postDelayed({
if (listener != null) {
listener!!.onSelectCoupon(selectedCouponBean)
}
}, 300)
} else {
ToastHelper.show(context, it.data.msg)
}
} else {
ToastHelper.show(context, it.msg)
}
} else {
ToastHelper.show(context, it.msg)
}
}, { e ->
ToastHelper.show(context, e.message!!)
})
}
fun setListener(listener: OnCouponClickListener) {
this.listener = listener
}
/**
* 设置数据
*/
fun setData(couponListBean: AllCouponListBean, isCoursePay: Boolean, selectedCouponBean: CommonCouponBean?, goodsId: String) {
// rl_course.visibility = if (isCoursePay) View.VISIBLE else View.GONE
if (isCoursePay) {
if (courseCodeView == null) {
initCourseCodeView()
}
}
this.couponListBean = couponListBean
this.selectedCouponBean = selectedCouponBean
this.goodsId = goodsId
if (couponListBean.availableCount == 0 && couponListBean.unAvailableCount == 0) {
rl_empty.visibility = View.VISIBLE
// rv_content.visibility = View.GONE
} else {
if (this.selectedCouponBean == null && couponListBean.availableCount != 0) {
this.couponListBean!!.available[0].hasSelected = 1
this.selectedCouponBean = this.couponListBean!!.available[0]
}
}
adapter = SelectCouponAdapter(this.couponListBean!!, context) {
this.selectedCouponBean = it
hasUseCouponCode = false
if (tv_ensure != null) {
tv_ensure!!.text = "使用"
}
hideSoftInput()
Handler().postDelayed({
if (listener != null) {
listener!!.onSelectCoupon(it)
}
}, 300)
}
if (courseCodeView != null) {
adapter!!.setHeadView(courseCodeView!!)
}
rv_content.adapter = adapter
}
/**
* 输入课程兑换码
*/
private fun initCourseCodeView() {
courseCodeView = View.inflate(context, R.layout.head_course_code_view, null)
var parmas = RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
courseCodeView!!.layoutParams = parmas
rt_coupon_code = courseCodeView!!.rt_coupon_code
tv_ensure = courseCodeView!!.tv_ensure
rt_coupon_code!!.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
tv_ensure!!.isEnabled = !TextUtils.isEmpty(s) && s!!.length == 8
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
})
tv_ensure!!.setOnClickListener {
if (hasUseCouponCode) {
selectedCouponBean = null
tv_ensure!!.text = "使用"
hasUseCouponCode = false
} else {
checkCourseCoupon(rt_coupon_code!!.text.toString())
}
}
}
private fun clearSelectCoupon() {
if(couponListBean!!.available!=null){
repeat(couponListBean!!.available.size) {
couponListBean!!.available[it].hasSelected = 0
}
adapter!!.notifyDataSetChanged()
}
}
interface OnCouponClickListener {
//返回按钮
fun onBackClick(selectedCouponBean: CommonCouponBean?)
//选择了优惠券
fun onSelectCoupon(selectedCouponBean: CommonCouponBean?)
}
}
package com.ydl.ydl_pay.widget
import android.annotation.SuppressLint
import android.content.Context
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import com.yidianling.ydl_pay.R
import com.yidianling.ydl_pay.bean.CommonCouponBean
import com.yidianling.ydl_pay.bean.OrderInfoBean
import kotlinx.android.synthetic.main.view_pay_info_detail.view.*
import java.math.BigDecimal
/**
* @author jiucheng
* @描述:支付详细信息view
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/4/4
*/
@SuppressLint("ViewConstructor")
class PayInfoDetailView(context: Context, var listener: OnCouponDetailClickListener) : LinearLayout(context) {
private var orderInfoBean: OrderInfoBean? = null
/**
* 是否使用余额
*/
private var isUseChange = true
/**
* 使用余额,余额是否足够
*/
private var isBalanceSufficient = false
//需要sdk(支付宝、微信)支付的金额
private var sdkPayMoney = 0.00f
/**
* 支付方式
* 1024.微信支付 1025.支付宝支付
*/
private var payWay = PAY_WECHAT
/**
* 支付类型
* 1余额,2三方支付,3混合
*/
private var useMoneyType = 1
/**
* 可用优惠券的数量
*/
private var availableCount: Int = 0
companion object {
/**
* 支付方式
* 1024.微信支付 1025.支付宝支付
*/
private const val PAY_WECHAT = 1024
private const val PAY_ALI = 1025
/**
* 支付类型
* 1余额,2三方支付,3混合
*/
private const val MONEY_TYPE_CHANGE = 1
private const val MONEY_TYPE_THIRD_PAY = 2
private const val MONEY_TYPE_MIXED = 3
}
init {
initView()
}
private fun initView() {
orientation = VERTICAL
val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
layoutParams = params
View.inflate(context, R.layout.view_pay_info_detail, this)
rl_discount.setOnClickListener {
listener.selectCoupon("")
}
tv_change_money.setOnClickListener {
if (isBalanceSufficient) {
isUseChange = true
} else {
isUseChange = !isUseChange
}
setChooseChangeMoney(isUseChange)
updateNeedPayMoney()
}
rl_weixin_pay.setOnClickListener {
if (isBalanceSufficient) {
isUseChange = false
setChooseChangeMoney(isUseChange)
updateNeedPayMoney()
}
setSelectPayWay(PAY_WECHAT)
}
rl_ali_pay.setOnClickListener {
if (isBalanceSufficient) {
isUseChange = false
setChooseChangeMoney(isUseChange)
updateNeedPayMoney()
}
setSelectPayWay(PAY_ALI)
}
tv_ensure_pay.setOnClickListener {
useMoneyType = if (!isUseChange) {
MONEY_TYPE_THIRD_PAY
} else if (isUseChange && sdkPayMoney > 0) {
MONEY_TYPE_MIXED
} else {
MONEY_TYPE_CHANGE
}
if (orderInfoBean!!.maxCoupon != null) {
listener.ensurePay(payWay, sdkPayMoney, useMoneyType, orderInfoBean!!.maxCoupon.code, orderInfoBean!!.maxCoupon.couponType)
} else {
listener.ensurePay(payWay, sdkPayMoney, useMoneyType, "", "")
}
}
}
fun setAvailableCount(availableCount: Int) {
this.availableCount = availableCount
}
/**
* 订单的信息
* @param payBusinessType 业务类型
*/
@SuppressLint("SetTextI18n")
fun setData(orderInfoBean: OrderInfoBean, payBusinessType: Int) {
this.orderInfoBean = orderInfoBean
if (payBusinessType == 1) {
tv_pay_title.text = "课程服务"
}
if (payBusinessType == 2) {
tv_pay_title.text = "倾诉服务"
}
if (payBusinessType == 3) {
tv_pay_title.text = "测评服务"
}
if (payBusinessType == 4) {
tv_pay_title.text = "咨询服务"
}
//价格
tv_price.text = orderInfoBean.applyFee.toString()
//可用余额
tv_change_useful.text = "[可用¥${orderInfoBean.availableMoney}]"
rl_discount.visibility = if (orderInfoBean.isShowCoupon) View.VISIBLE else View.GONE
setCouponData(orderInfoBean.maxCoupon)
}
/**
* 设置优惠券的数据
*
*/
@SuppressLint("SetTextI18n")
fun setCouponData(commonCouponBean: CommonCouponBean?) {
if (commonCouponBean == null) {
tv_discount_money.text = "0"
tv_flag.visibility = View.GONE
tv_discount_money.visibility = View.GONE
tv_no_choose.visibility = View.VISIBLE
if (availableCount == 0) {
tv_no_choose.text = "暂无优惠"
} else {
tv_no_choose.text = "有${availableCount}张优惠券可用"
}
orderInfoBean!!.maxCoupon = null
} else {
tv_flag.visibility = View.VISIBLE
tv_discount_money.visibility = View.VISIBLE
tv_no_choose.visibility = View.GONE
orderInfoBean!!.maxCoupon = commonCouponBean
//优惠
tv_discount_money.text = commonCouponBean.combinedAmount.toString()
}
updateNeedPayMoney()
}
/**
* 更新还需支付的金额
*/
private fun updateNeedPayMoney() {
var needPay = if (orderInfoBean!!.maxCoupon == null) {
orderInfoBean!!.applyFee
} else {
val b1 = BigDecimal(orderInfoBean!!.applyFee.toString())
val b2 = BigDecimal(orderInfoBean!!.maxCoupon.combinedAmount.toString())
b1.subtract(b2).toFloat()
}
if (needPay == 0f) {//优惠券已经完全抵扣
ll_third_pay.visibility = View.GONE
view_empty.visibility = View.VISIBLE
ll_third_pay.isEnabled = false
} else {//不能完全抵扣
ll_third_pay.visibility = View.VISIBLE
view_empty.visibility = View.GONE
ll_third_pay.isEnabled = true
}
if (isUseChange) {//使用余额
if (orderInfoBean!!.availableMoney >= needPay) {
tv_change_money.text = needPay.toString()
sdkPayMoney = 0f
setSelectPayWay(0)
isBalanceSufficient = true
} else {
tv_change_money.text = orderInfoBean!!.availableMoney.toString()
val bd1 = BigDecimal(needPay.toString())
val bd2 = BigDecimal(orderInfoBean!!.availableMoney.toString())
sdkPayMoney = bd1.subtract(bd2).toFloat()
// sdkPayMoney = needPay - orderInfoBean!!.availableMoney
if (payWay == 0) {
setSelectPayWay(PAY_WECHAT)
}
isBalanceSufficient = false
}
} else {//不使用余额
sdkPayMoney = needPay
}
// val bg = BigDecimal(sdkPayMoney.toDouble()).setScale(2, RoundingMode.UP)
tv_pay_money.text = sdkPayMoney.toString()
}
/**
* 选择支付方式
*/
private fun setSelectPayWay(way: Int) {
if (payWay == way) {
return
}
payWay = way
when (payWay) {
PAY_WECHAT -> {//微信
img_weixin_way.setImageResource(R.drawable.img_select)
img_ali_way.setImageResource(R.drawable.img_no_select)
}
PAY_ALI -> {//支付宝
img_weixin_way.setImageResource(R.drawable.img_no_select)
img_ali_way.setImageResource(R.drawable.img_select)
}
else -> {
img_ali_way.setImageResource(R.drawable.img_no_select)
img_weixin_way.setImageResource(R.drawable.img_no_select)
}
}
}
/**
* 是否选使用余额
*/
private fun setChooseChangeMoney(isUse: Boolean) {
if (isUse) {
tv_change_money.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.img_select, 0)
} else {
tv_change_money.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.img_no_select, 0)
}
}
interface OnCouponDetailClickListener {
/**
* 选择优惠券
*/
fun selectCoupon(couponId: String)
/**
* 确认支付
* @param payWay 支付方式 1024.微信支付 1025.支付宝支付
* @param payMoney 还需支付金额
* @param useMoneyType 支付类型 1余额,2三方支付,3混合
* @param code 优惠券code
* @param couponType 券类型 1兑换券 2新优惠券
*
*/
fun ensurePay(payWay: Int, payMoney: Float, useMoneyType: Int, code: String, couponType: String)
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/color_F3F3F3" />
<corners android:radius="20dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/color_FFFFFF" />
<corners
android:bottomLeftRadius="0dp"
android:bottomRightRadius="0dp"
android:topLeftRadius="10dp"
android:topRightRadius="10dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="false">
<shape>
<corners android:radius="15dp" />
<solid android:color="@color/color_CCCCCC" />
</shape>
</item>
<item android:state_enabled="true">
<shape>
<corners android:radius="15dp" />
<solid android:color="@color/color_FF6666" />
</shape>
</item>
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00000000"
android:gravity="bottom">
<RelativeLayout
android:id="@+id/progress_layout"
android:layout_width="match_parent"
android:layout_height="411dp"
android:background="@drawable/background_common_pay_dialog">
<!--<ProgressBar-->
<!--android:id="@+id/progress"-->
<!--style="?android:attr/progressBarStyleSmall"-->
<!--android:indeterminateTint="@color/color_3D9EFF"-->
<!--android:indeterminateTintMode="src_atop"-->
<!--android:layout_width="32dp"-->
<!--android:layout_height="32dp"-->
<!--android:layout_centerInParent="true" />-->
</RelativeLayout>
<com.yidianling.ydl_pay.widget.NoScrollViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="425dp"
android:background="@drawable/background_common_pay_dialog"
android:visibility="gone"/>
</RelativeLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/rl_course"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginTop="21dp"
android:layout_marginRight="15dp"
android:orientation="vertical">
<!-- 课程兑换码-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="课程兑换券码"
android:textColor="@color/color_3D3D3D"
android:textSize="15sp"
android:textStyle="bold" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginTop="10dp"
android:background="@drawable/background_choose_coupon">
<EditText
android:id="@+id/rt_coupon_code"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginLeft="15dp"
android:layout_toLeftOf="@+id/tv_ensure"
android:background="@null"
android:digits="1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"
android:hint="请输入课程兑换券码"
android:textColor="@color/color_242424"
android:textColorHint="@color/color_999999"
android:textSize="14sp" />
<TextView
android:id="@+id/tv_ensure"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="5dp"
android:background="@drawable/background_coupon_ensure_button"
android:enabled="false"
android:gravity="center"
android:paddingLeft="13dp"
android:paddingRight="12dp"
android:text="确认"
android:textColor="@color/color_FFFFFF"
android:textSize="15sp"
tools:enabled="true"
tools:text="取消使用" />
</RelativeLayout>
</LinearLayout>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="15dp"
android:paddingTop="20dp"
android:paddingRight="15dp"
android:paddingBottom="10dp"
android:textColor="@color/color_3D3D3D"
android:textSize="15dp"
android:textStyle="bold" />
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="24dp">
<ProgressBar
style="?android:attr/progressBarStyleSmall"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_centerInParent="true"
android:layout_gravity="center" />
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginBottom="8dp">
<ImageView
android:id="@+id/iv_background"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="@drawable/item_coupon_background" />
<LinearLayout
android:id="@+id/ll_background"
android:layout_width="match_parent"
android:layout_height="100dp"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="114"
android:gravity="center"
android:orientation="vertical">
<TextView
android:id="@+id/tv_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lineSpacingExtra="0dp"
android:textColor="@color/color_FFFFFF"
android:textSize="25sp"
tools:text="¥100" />
<TextView
android:id="@+id/tv_discountCont"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/color_FFFFFF"
android:textSize="14sp"
android:visibility="gone"
tools:text="满50元可用" />
</LinearLayout>
<RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="231"
android:paddingLeft="12dp">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginTop="15dp"
android:layout_marginRight="10dp"
android:layout_toLeftOf="@+id/iv_select"
android:text="咨询优惠券"
android:textColor="@color/color_242424"
android:textSize="16dp"
tools:text="咨询优咨咨询优咨询优惠券惠券询优惠券惠券"
android:textStyle="bold" />
<TextView
android:id="@+id/tv_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/tv_title"
android:layout_marginTop="3dp"
android:textColor="@color/color_242424"
android:textSize="11sp"
tools:text="有效期至2018-08-31" />
<TextView
android:id="@+id/tv_use_condition"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="11dp"
android:text="使用规则"
android:textColor="@color/color_666666"
android:textSize="10sp" />
<ImageView
android:id="@+id/iv_select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginTop="18dp"
android:layout_marginRight="12dp"
android:src="@drawable/img_no_select" />
</RelativeLayout>
</LinearLayout>
</RelativeLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@color/color_FFFFFF">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="68dp">
<RelativeLayout
android:id="@+id/rl_back"
android:layout_width="40dp"
android:layout_height="match_parent">
<ImageView
android:layout_width="9dp"
android:layout_height="18dp"
android:layout_centerVertical="true"
android:layout_marginLeft="15dp"
android:src="@drawable/img_pay_back"/>
</RelativeLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="选择优惠"
android:textColor="@color/color_242424"
android:textSize="17sp"
android:textStyle="bold"/>
</RelativeLayout>
<View style="@style/divide_color_style"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<RelativeLayout
android:id="@+id/rl_empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone">
<ImageView
android:id="@+id/img"
android:layout_width="46dp"
android:layout_height="35dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="75dp"
android:src="@drawable/img_empty"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/img"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:text="还没有优惠券哦"
android:textColor="@color/color_999999"
android:textSize="13sp"/>
</RelativeLayout>
</LinearLayout>
</merge>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:background="@color/color_FFFFFF">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="68dp"
android:paddingLeft="15dp"
android:paddingRight="15dp">
<TextView
android:id="@+id/tv_pay_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:textColor="@color/color_242424"
android:textSize="17dp"
android:textStyle="bold"
tools:text="课程服务" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toLeftOf="@+id/tv_price"
android:text="¥"
android:textColor="@color/color_242424"
android:textSize="12dp" />
<TextView
android:id="@+id/tv_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:textColor="@color/color_242424"
android:textSize="16dp"
android:textStyle="bold"
tools:text="129.00" />
</RelativeLayout>
<View style="@style/divide_color_style" />
<RelativeLayout
android:id="@+id/rl_discount"
android:layout_width="match_parent"
android:layout_height="54dp"
android:paddingLeft="15dp"
android:paddingRight="15dp">
<TextView
android:id="@+id/tv_discount_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="优惠"
android:textColor="@color/color_242424"
android:textSize="15dp" />
<TextView
android:id="@+id/tv_flag"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toLeftOf="@+id/tv_discount_money"
android:text="-¥"
android:textColor="@color/color_242424"
android:textSize="12dp" />
<TextView
android:id="@+id/tv_discount_money"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginRight="6dp"
android:layout_toLeftOf="@+id/tv_more"
android:textColor="@color/color_242424"
android:textSize="16dp"
android:textStyle="bold"
tools:text="129.00" />
<TextView
android:id="@+id/tv_no_choose"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginRight="6dp"
android:layout_toLeftOf="@+id/tv_more"
android:textColor="@color/color_242424"
android:textSize="14dp"
android:visibility="gone"
tools:text="129.00" />
<ImageView
android:id="@+id/tv_more"
android:layout_width="5dp"
android:layout_height="10dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:src="@drawable/ico_zf_more" />
</RelativeLayout>
<View style="@style/divide_color_style" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="54dp"
android:paddingLeft="15dp"
android:paddingRight="15dp">
<TextView
android:id="@+id/tv_change_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="使用余额"
android:textColor="@color/color_242424"
android:textSize="15dp" />
<TextView
android:id="@+id/tv_change_useful"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="8dp"
android:layout_toRightOf="@+id/tv_change_title"
android:textColor="@color/color_666666"
android:textSize="13dp"
tools:text="[可用¥9.00]" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toLeftOf="@+id/tv_change_money"
android:text="-¥"
android:textColor="@color/color_242424"
android:textSize="12dp" />
<TextView
android:id="@+id/tv_change_money"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:drawableRight="@drawable/img_select"
android:drawablePadding="6dp"
android:textColor="@color/color_242424"
android:textSize="16dp"
android:textStyle="bold"
tools:text="129.00" />
</RelativeLayout>
<View style="@style/divide_color_style" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="54dp"
android:paddingLeft="15dp"
android:paddingRight="15dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="还需支付"
android:textColor="@color/color_242424"
android:textSize="15dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toLeftOf="@+id/tv_pay_money"
android:text="¥"
android:textColor="@color/color_FF5A4C"
android:textSize="12dp" />
<TextView
android:id="@+id/tv_pay_money"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:drawablePadding="6dp"
android:textColor="@color/color_FF5A4C"
android:textSize="20dp"
android:textStyle="bold"
tools:text="129.00" />
</RelativeLayout>
<LinearLayout
android:id="@+id/ll_third_pay"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="30dp"
android:background="@color/color_F7F7F7"
android:gravity="bottom"
android:paddingLeft="15dp"
android:paddingBottom="4dp"
android:text="选择支付方式"
android:textSize="12dp" />
<RelativeLayout
android:id="@+id/rl_weixin_pay"
android:layout_width="match_parent"
android:layout_height="54dp"
android:gravity="center_vertical"
android:paddingLeft="15dp"
android:paddingRight="15dp">
<ImageView
android:id="@+id/img_weixin"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_centerVertical="true"
android:src="@drawable/wechat_for_pay" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="5dp"
android:layout_toRightOf="@+id/img_weixin"
android:gravity="center_vertical"
android:text="微信支付"
android:textColor="@color/color_242424"
android:textSize="15dp"
android:textStyle="bold" />
<ImageView
android:id="@+id/img_weixin_way"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:src="@drawable/img_select" />
</RelativeLayout>
<View style="@style/divide_color_style" />
<RelativeLayout
android:id="@+id/rl_ali_pay"
android:layout_width="match_parent"
android:layout_height="54dp"
android:gravity="center_vertical"
android:paddingLeft="15dp"
android:paddingRight="15dp">
<ImageView
android:id="@+id/img_ali"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_centerVertical="true"
android:src="@drawable/zhifubao_for_pay" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="5dp"
android:layout_toRightOf="@+id/img_ali"
android:gravity="center_vertical"
android:text="支付宝支付"
android:textColor="@color/color_242424"
android:textSize="15dp"
android:textStyle="bold" />
<ImageView
android:id="@+id/img_ali_way"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:src="@drawable/img_no_select" />
</RelativeLayout>
</LinearLayout>
<View
android:id="@+id/view_empty"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@color/color_F7F7F7"
android:visibility="gone" />
<TextView
android:id="@+id/tv_ensure_pay"
android:layout_width="match_parent"
android:layout_height="55dp"
android:background="@color/color_3D9EFF"
android:gravity="center"
android:text="确认付款"
android:textColor="@color/color_FFFFFF"
android:textSize="17dp"
android:textStyle="bold" />
</merge>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- 颜色透明度
100% — FF
95% — F2
90% — E6
85% — D9
80% — CC
75% — BF
70% — B3
65% — CC
60% — 99
55% — 8C
50% — 80
45% — 73
40% — 66
35% — 59
30% — 4D
25% — 40
20% — 33
15% — 26
10% — 1A
5% — 0D
0% — 00
-->
<color name="color_242424">#242424</color>
<color name="color_E0E0E0">#E0E0E0</color>
<color name="color_EBEBEB">#EBEBEB</color>
<color name="color_666666">#666666</color>
<color name="color_F7F7F7">#F7F7F7</color>
<color name="color_FFFFFF">#FFFFFF</color>
<color name="color_FF5A4C">#FF5A4C</color>
<color name="color_3D9EFF">#3D9EFF</color>
<color name="color_3D3D3D">#3D3D3D</color>
<color name="color_F3F3F3">#F3F3F3</color>
<color name="color_999999">#999999</color>
<color name="color_CCCCCC">#CCCCCC</color>
<color name="color_FF6666">#FF6666</color>
</resources>
<resources>
<string name="app_name">ydl_pay</string>
<string name="net_error">请检查网络连接</string>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="divide_color_style">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">0.5dp</item>
<item name="android:layout_marginRight">15dp</item>
<item name="android:layout_marginLeft">15dp</item>
<item name="android:background">@color/color_E0E0E0</item>
</style>
<!--自定义分享-->
<style name="common_dialog_style" parent="android:style/Theme.Dialog">
<item name="colorPrimary">@color/color_3D9EFF</item>
<item name="colorPrimaryDark">@color/color_3D9EFF</item>
<!-- 边框 -->
<item name="android:windowFrame">@null</item>
<!-- 是否浮现在activity之上 -->
<item name="android:windowIsFloating">true</item>
<!-- 半透明 -->
<item name="android:windowIsTranslucent">true</item>
<!-- 无标题 -->
<item name="android:windowNoTitle">true</item>
<item name="android:background">@android:color/transparent</item>
<!-- 背景透明 -->
<item name="android:windowBackground">@android:color/transparent</item>
<!-- 模糊 -->
<item name="android:backgroundDimEnabled">true</item>
<!-- 遮罩层 -->
<item name="android:backgroundDimAmount">0.5</item>
</style>
</resources>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment