Commit eed55690 by 刘鹏

feat : 支付模块代码提交已完成

parent e60a7e72
plugins {
id 'com.android.library'
id 'kotlin-android'
id 'kotlin-android-extensions'
id 'kotlin-kapt'
}
apply from: "../maven_push.gradle"
android {
compileSdkVersion 31
buildToolsVersion "31.0.0"
defaultConfig {
minSdkVersion 21
minSdkVersion 17
targetSdkVersion 31
versionCode 1
versionName "1.0"
......@@ -34,12 +37,8 @@ android {
dependencies {
api fileTree(dir: 'libs', include: ['*.jar','*.aar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.3.1'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
implementation 'androidx.core:core-ktx:1.1.0'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
......
apply plugin: 'maven'
def mavenRepositoryUrl = "http://nexus.yidianling.com/repository/AndroidReleases/"
def getVersionName() {
return hasProperty('VERSION_NAME') ? VERSION_NAME : rootProject.ext.ydlPublishVersion[project.getName()]
}
afterEvaluate { project ->
uploadArchives {
repositories {
mavenDeployer {
pom.artifactId = project.getName().replace('_', "-")
pom.groupId = "com.ydl"
pom.version = getVersionName()
repository(url: mavenRepositoryUrl) {
authentication(userName: "admin", password: "fjoi#1+#@")
}
}
}
}
uploadArchives.doFirst {
// log
println String.format(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n>>>>> [%s] 正在将[%s]版本的[%s]包上传到Maven的[%s]仓库 >>>>>\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
, project.getName()
, getVersionName()
, "aar"
, "release"
)
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.medical.ydl.medical.pay">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<application>
<!--支付界面-->
<activity
android:name=".MedicalPayActivity"
android:screenOrientation="portrait"
android:theme="@style/platform_NoTitleTheme" />
</application>
</manifest>
\ No newline at end of file
package com.medical.ydl.medical.bean
data class CreatePayReqDtoBody(
//支付金额(交易金额),必须大于0,保留两位小数点,如99.99
var payAmount: String,
//问诊订单ID
var payBizId: String,
//支付渠道:1支付宝-APP支付、2支付宝-h5支付、3微信-APP支付、4微信-h5支付")
var payChannel: Int = 3,
//支付业务关联类型:0账户充值(充值记录表)、1问诊订单(inquiry_order表)、2药品订单
var payBizType: Int = 1
)
\ No newline at end of file
package com.medical.ydl.medical.bean
import com.google.gson.annotations.SerializedName
data class CreatePayRespose(
//支付宝返回数据
var payParams: String,
//微信返回数据
var result: String,
@SerializedName("package")
var packageValue: String,
var appid: String,
var sign: String,
var partnerid: String,
var prepayid: String,
var noncestr: String,
var timestamp: String
)
package com.medical.ydl.medical.http
import com.google.gson.Gson
import com.medical.ydl.medical.bean.CreatePayReqDtoBody
import com.medical.ydl.medical.bean.CreatePayRespose
import com.ydl.ydlcommon.data.http.BaseResponse
import com.ydl.ydlnet.YDLHttpUtils
import io.reactivex.Observable
import okhttp3.MediaType
import okhttp3.RequestBody
/**
*
* */
class MedicalPayServiceImpl {
companion object{
/**
* 获取下单的信息
*/
fun getOrderInfo(bean: CreatePayReqDtoBody): Observable<BaseResponse<CreatePayRespose>> {
var str = Gson().toJson(bean)
val body = RequestBody.create(
MediaType.parse("application/json; charset=utf-8"),
str
) as RequestBody
return YDLHttpUtils.obtainApi(MedicalPayServices::class.java).getOrderInfo(body)
}
}
}
\ No newline at end of file
package com.medical.ydl.medical.http
import com.medical.ydl.medical.bean.CreatePayRespose
import com.ydl.ydlcommon.base.config.YDL_DOMAIN
import com.ydl.ydlcommon.base.config.YDL_DOMAIN_JAVA_URL
import com.ydl.ydlcommon.data.http.BaseResponse
import io.reactivex.Observable
import okhttp3.RequestBody
import retrofit2.http.Body
import retrofit2.http.Headers
import retrofit2.http.POST
interface MedicalPayServices {
/**
* 问诊订单创建支付
*/
@POST("ydl-yiliao-api/api/pay/createPay")
@Headers(YDL_DOMAIN + YDL_DOMAIN_JAVA_URL)
fun getOrderInfo(@Body body: RequestBody): Observable<BaseResponse<CreatePayRespose>>
}
\ No newline at end of file
package com.medical.ydl.medical.pay
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.os.CountDownTimer
import android.os.Handler
import android.os.Message
import android.text.TextUtils
import android.util.Log
import com.alipay.sdk.app.PayTask
import com.medical.ydl.medical.bean.CreatePayReqDtoBody
import com.medical.ydl.medical.bean.CreatePayRespose
import com.medical.ydl.medical.http.MedicalPayServiceImpl
import com.medical.ydl.medical.pay.bean.MedicalPayResult
import com.medical.ydl.medical.pay.bean.MedicalPayStatus
import com.medical.ydl.medical.pay.bean.MedicalWXPayEvent
import com.tencent.mm.opensdk.constants.Build
import com.tencent.mm.opensdk.modelpay.PayReq
import com.tencent.mm.opensdk.openapi.WXAPIFactory
import com.ydl.ydlcommon.base.BaseActivity
import com.ydl.ydlcommon.data.http.BaseResponse
import com.ydl.ydlcommon.utils.LogUtil
import com.ydl.ydlcommon.utils.StatusBarUtils
import com.ydl.ydlcommon.view.dialog.NormalDialog
import com.yidianling.common.tools.ToastUtil
import de.greenrobot.event.EventBus
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import kotlinx.android.synthetic.main.medical_pay_activity.*
import java.util.*
/**
* 医疗 支付页
* */
class MedicalPayActivity : BaseActivity() {
companion object {
private const val PRICE_KEY = "price"
private const val ORDER_KEY = "orderId"
private lateinit var mPrice: String
private lateinit var mOrderId: String
private var timer: CountDownTimer? = null
//阿里支付
private const val PAY_ALI = 1
//微信支付
private const val PAY_WECHAT = 3
/**
* 已选择支付方式
*/
private var payType = PAY_WECHAT
/**
* @param price 价格
* @param orderId 订单id
* */
@JvmStatic
fun start(context: Context, price: String, orderId: String) {
val starter = Intent(context, MedicalPayActivity::class.java)
.putExtra(PRICE_KEY, price)
.putExtra(ORDER_KEY, orderId)
context.startActivity(starter)
}
@SuppressLint("HandlerLeak")
private val mHandler: Handler = object : Handler() {
override fun handleMessage(msg: Message) {
when (msg.what) {
PAY_ALI -> {
val payResult = MedicalPayResult(msg.obj as Map<String?, String?>)
/**
* 对于支付结果,请商户依赖服务端的异步通知结果。同步通知结果,仅作为支付结束的通知。
*/
val resultInfo: String = payResult.getResult() // 同步返回需要验证的信息
val resultStatus: String = payResult.getResultStatus()
// 判断resultStatus 为9000则代表支付成功
if (TextUtils.equals(resultStatus, "9000")) {
// 该笔订单是否真实支付成功,需要依赖服务端的异步通知。
LogUtil.e(resultStatus)
EventBus.getDefault().post(MedicalWXPayEvent(MedicalPayStatus(true)))
} else {
// 该笔订单真实的支付结果,需要依赖服务端的异步通知。
LogUtil.e(resultStatus)
EventBus.getDefault().post(MedicalWXPayEvent(MedicalPayStatus(false)))
}
}
else -> {
}
}
}
}
}
override fun layoutResId(): Int {
return R.layout.medical_pay_activity
}
override fun initDataAndEvent() {
EventBus.getDefault().register(this)
initStatus()
mPrice = intent.getStringExtra(PRICE_KEY)
mOrderId = intent.getStringExtra(ORDER_KEY)
price.text = mPrice
ll_alipay.setOnClickListener {
//选择阿里支付
payType = PAY_ALI
iv_wx_check.setImageResource(R.mipmap.medical_pay_uncheck)
iv_alipay_check.setImageResource(R.mipmap.medical_pay_check)
}
ll_wx_pay.setOnClickListener {
//选择微信
payType = PAY_WECHAT
iv_wx_check.setImageResource(R.mipmap.medical_pay_check)
iv_alipay_check.setImageResource(R.mipmap.medical_pay_uncheck)
}
iv_back.setOnClickListener {
backCheck()
}
to_pay.setOnClickListener {
//支付按钮
MedicalPayServiceImpl.getOrderInfo(
CreatePayReqDtoBody(
mPrice,
mOrderId,
payChannel = payType
)
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ response ->
if (response.code == 200) {
toPay(response, payType)
}
}, { e ->
e.printStackTrace()
})
}
}
override fun onDestroy() {
super.onDestroy()
EventBus.getDefault().unregister(this)
}
private fun backCheck() {
val builder = NormalDialog.Builder(this@MedicalPayActivity, "center", true)
builder.setTitle("")
builder.setMessage("\n已为您锁定问诊名额,请在24小时59分00秒内完成支付,超时名额自动取消\n")
builder.setPositiveButton(
"继续支付"
) { dialog, which ->
timer?.cancel()
dialog.dismiss()
}.setNegativeButton(
"确定离开"
) { dialog, which ->
//关闭页面
timer?.cancel()
finish()
dialog.dismiss()
}
builder.setRight_color("#3464EC")
builder.setLeft_color("#8595A9")
builder.setContent_color("#10233A")
builder.create().show()
var timeStamp: Long = 86400000
timer = object : CountDownTimer(timeStamp, 1000) {
override fun onTick(millisUntilFinished: Long) {
//单位时
var hour = millisUntilFinished / (1000 * 60 * 60)
//单位分
var minute =
(millisUntilFinished - hour * (1000 * 60 * 60)) / (1000 * 60)
//单位秒
var second =
(millisUntilFinished - hour * (1000 * 60 * 60) - minute * (1000 * 60)) / 1000
builder.setMessage(
"\n已为您锁定问诊名额,请在${hour}小时${minute}分${second}秒内完成支付,超时名额自动取消\n"
)
}
override fun onFinish() {
builder.dismiss()
finish()
}
}
timer?.start()
}
private fun toPay(response: BaseResponse<CreatePayRespose>, payType: Int) {
if (payType == PAY_ALI && response.data.payParams.isNotEmpty()) {
val payRunnable = Runnable {
val alipay = PayTask(this@MedicalPayActivity)
val result = alipay.payV2(response.data.payParams, true)
Log.i("msp", result.toString())
val msg = Message()
msg.what = payType
msg.obj = result
mHandler.sendMessage(msg)
}
// 必须异步调用
var payThread = Thread(payRunnable)
payThread.start()
} else {
var option = response.data
val api = WXAPIFactory.createWXAPI(this@MedicalPayActivity, null)
if (api.wxAppSupportAPI < Build.PAY_SUPPORTED_SDK_INT) {
ToastUtil.toastShort("目前您的微信版本过低或未安装微信,需要安装微信才能使用")
}
api.registerApp(option.appid)
val request = PayReq()
request.appId = option.appid
request.partnerId = option.partnerid
request.prepayId = option.prepayid
request.packageValue = option.packageValue
request.nonceStr = option.noncestr
request.timeStamp = option.timestamp
request.sign = option.sign
api.sendReq(request)
}
}
private fun initStatus() {
StatusBarUtils.setTransparentForImageView(this@MedicalPayActivity, null)
StatusBarUtils.statusBarLightMode(this@MedicalPayActivity)
}
fun onEvent(event: MedicalWXPayEvent) {
if (event.status.success) {
ToastUtil.toastShort("支付成功")
finish()
} else {
ToastUtil.toastShort("支付失败")
}
}
}
\ No newline at end of file
package com.medical.ydl.medical.pay.bean
/**
* author : Zhangwenchao
* e-mail : zhangwch@yidianling.com
* time : 2018/04/18
*/
data class MedicalCommonWXPayBean(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.medical.ydl.medical.pay.bean; import android.text.TextUtils; import java.util.Map; public class MedicalPayResult { private String resultStatus; private String result; private String memo; public MedicalPayResult(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.medical.ydl.medical.pay.bean
import androidx.annotation.Keep
/**
* author : Zhangwenchao
* e-mail : zhangwch@yidianling.com
* time : 2018/04/18
*
* 支付状态
*/
@Keep
data class MedicalPayStatus(val success: Boolean)
\ No newline at end of file
package com.medical.ydl.medical.pay.bean
/**
* @author : Zhangwenchao
* @e-mail : zhangwch@yidianling.com
* @time : 2018/6/4
*/
data class MedicalWXPayEvent(val status: MedicalPayStatus)
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#ff3464ec" />
<corners android:radius="8dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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="#f0f4f8"
tools:context=".MedicalPayActivity">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="96dp"
android:background="@color/white"
android:elevation="0dp"
android:gravity="bottom"
app:contentInsetStart="0dp"
app:layout_collapseMode="pin"
app:layout_constraintTop_toTopOf="parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="56dp"
android:ellipsize="end"
android:gravity="center"
android:maxEms="10"
android:maxLines="1"
android:text="支付订单"
android:textColor="#10233a"
android:textSize="18sp"
android:textStyle="bold" />
<ImageView
android:id="@+id/iv_back"
android:layout_width="wrap_content"
android:layout_height="56dp"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:src="@mipmap/medical_icon_title_back" />
</RelativeLayout>
</androidx.appcompat.widget.Toolbar>
<TextView
android:id="@+id/price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginTop="30dp"
android:textColor="#ff0c1d31"
android:textSize="32sp"
android:textStyle="bold"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintLeft_toRightOf="@id/price_unit"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/toolbar"
tools:text="99" />
<TextView
android:id="@+id/price_unit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="¥"
android:textColor="#ff0c1d31"
android:textSize="24sp"
app:layout_constraintBaseline_toBaselineOf="@id/price"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/price" />
<TextView
android:id="@+id/hold_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="13dp"
android:text="等待付款"
android:textColor="#ff0c1d31"
android:textSize="16sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/price" />
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginTop="27dp"
android:layout_marginRight="16dp"
android:background="@color/white"
android:elevation="0dp"
app:cardCornerRadius="8dp"
app:cardElevation="0dp"
app:layout_constraintTop_toBottomOf="@id/hold_text">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="12dp"
android:paddingTop="20dp"
android:paddingRight="12dp">
<TextView
android:id="@+id/tv_payType"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="支付方式"
android:textColor="#ff8595a9"
android:textSize="15sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="@+id/pay_type_line"
android:layout_width="0dp"
android:layout_height="1px"
android:layout_marginTop="12dp"
android:background="#E7ECF0"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_payType" />
<LinearLayout
android:id="@+id/ll_alipay"
android:layout_width="match_parent"
android:layout_height="60dp"
android:gravity="center_vertical"
android:orientation="horizontal"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/pay_type_line">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/medical_alipay_icon" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_weight="1"
android:gravity="left"
android:text="支付宝支付"
android:textColor="#ff0c1d31"
android:textSize="16sp" />
<ImageView
android:id="@+id/iv_alipay_check"
android:layout_width="20dp"
android:layout_height="20dp"
android:src="@mipmap/medical_pay_uncheck" />
</LinearLayout>
<View
android:id="@+id/alipay_line"
android:layout_width="0dp"
android:layout_height="1px"
android:background="#E7ECF0"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/ll_alipay" />
<LinearLayout
android:id="@+id/ll_wx_pay"
android:layout_width="match_parent"
android:layout_height="60dp"
android:gravity="center_vertical"
android:orientation="horizontal"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/alipay_line">
<ImageView
android:id="@+id/wx_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/medical_wx_pay_icon" />
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:text="微信支付"
android:textColor="#ff0c1d31"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="@id/wx_icon"
app:layout_constraintLeft_toRightOf="@id/wx_icon"
app:layout_constraintTop_toTopOf="@id/wx_icon" />
<ImageView
android:id="@+id/iv_wx_check"
android:layout_width="20dp"
android:layout_height="20dp"
android:src="@mipmap/medical_pay_check"
app:layout_constraintBottom_toBottomOf="@id/wx_icon"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@id/wx_icon" />
</LinearLayout>
<View
android:id="@+id/wx_line"
android:layout_width="0dp"
android:layout_height="1px"
android:background="#E7ECF0"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/ll_wx_pay" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
<LinearLayout
android:id="@+id/ll_pay"
android:layout_width="match_parent"
android:layout_height="98dp"
android:layout_alignParentBottom="true"
android:background="@color/white"
android:orientation="horizontal"
android:padding="16dp"
app:layout_constraintBottom_toBottomOf="parent">
<TextView
android:id="@+id/to_pay"
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="@drawable/medical_bg_3464ec_8dp"
android:gravity="center"
android:text="确认付款"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<resources>
<string name="app_name">ydl_medical_pay</string>
<string name="app_name">ydl-medical-pay</string>
</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