移动支付实际上是很是简单的,由于只要按照第三方的文档来就好了,因此在本次分享中,其实更像是支付总结。作过支付的人都知道支付的难点实际上是在第三方文档和demo上(集中体现文档陈旧、demo容易误导人、槽点太多),那就不得不先来吐槽下WX的开发文档和示例,我相信大部分人都被坑过,没有对比就没有伤害,相对而言,支付宝好不少,下面我先说重点再谈支付流程。php
<!--解决微信支付回调部分机型黑屏闪烁的问题-->
<style name="wxPayTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowNoTitle">true</item>
</style>
<!--回调页面WXPayEntryActivity关闭finish的时候增长-->
overridePendingTransition(0, 0);
<!--回调页面WXPayEntryActivity配置-->
<activity
android:name=".wxapi.WXPayEntryActivity"
android:configChanges="orientation|screenSize"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/wxPayTheme"
android:windowSoftInputMode="adjustPan|stateAlwaysHidden" />
<!--另一种解决方案-->
android:launchMode="singleTop"改成android:launchMode="singleInstance"
建议优先采起第一种方案,该方案做为备选,毕竟微信推荐使用"singleTop"启动模式。
复制代码
<!--底部弹框支付Activity主题样式-->
<style name="PayTranslucentTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowAnimationStyle">@null</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowNoTitle">true</item> <!-- 无标题 -->
<item name="android:windowContentOverlay">@null</item>
<item name="android:backgroundDimEnabled">true</item><!-- 半透明 -->
</style>
<!-- R.anim.push_bottom_in 进入动画-->
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="300"
android:fromYDelta="100%p"
android:toYDelta="0" />
</set>
<!-- R.anim.push_bottom_out 淡出动画-->
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="300"
android:fromYDelta="0"
android:toYDelta="100%p" />
</set>
<!-- R.anim.push_bottom_silent 原点-->
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fromYDelta="0"
android:toYDelta="0" />
<!-- 底部弹框-->
startActivity(intent);
overridePendingTransition(R.anim.push_bottom_in,R.anim.push_bottom_silent);
<!-- 关闭底部弹框-->
finish();
overridePendingTransition(R.anim.push_bottom_silent,R.anim.push_bottom_out);
<!-- 实现透明状态栏-->
setContentView(R.layout.activity_dialog_pay_custom);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().setStatusBarColor(Color.TRANSPARENT);
}
复制代码
IWXAPI api = WXAPIFactory.createWXAPI(this, APP_ID);
复制代码
/**
* 微信支付
*
* @param payInfo 预支付信息
*/
private void wechatPay(final String payInfo) {
try {
JSONObject json = new JSONObject(payInfo);
if (!json.has("retcode")) {
PayReq req = new PayReq();
// 测试用appId
req.appId = APP_ID;
// req.appId = json.getString("appid");
req.partnerId = json.getString("partnerid");
req.prepayId = json.getString("prepayid");
req.nonceStr = json.getString("noncestr");
req.timeStamp = json.getString("timestamp");
req.packageValue = json.getString("package");
req.sign = json.getString("sign");
req.extData = "app data";
Toast.makeText(PayDialogActivity.this, "正常调起支付", Toast.LENGTH_SHORT).show();
// 在支付以前,若是应用没有注册到微信,应该先调用IWXMsg.registerApp将应用注册到微信
api.sendReq(req);
}
} catch (JSONException e) {
e.printStackTrace();
showToast(this, "异常:" + e.getMessage());
}
}
复制代码
/**
* @author hule
* @date 2019/7/29 15:58
* description: 微信支付回调
*/
public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler {
private IWXAPI api;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//此处若是须要显示界面须要设置setContentView();
//通常状况下会都不会去设置界面,拿到回调后直接关闭界面,发送通知处理
api = WXAPIFactory.createWXAPI(this, PayDialogActivity.APP_ID);
api.handleIntent(getIntent(), this);
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
api.handleIntent(intent, this);
}
@Override
public void onReq(BaseReq req) {
}
@Override
public void onResp(BaseResp resp) {
if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
//通知咱们回调,咱们拿来查询订单的状态
EventBus.getDefault().post(new WXPayEntryEntity(resp.errCode));
}
// 清除动画,有助于防止黑屏闪烁
overridePendingTransition(0, 0);
finish();
}
}
复制代码
3.回调页面配置html
<!--解决微信支付回调部分机型黑屏闪烁的问题-->
<style name="wxPayTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowNoTitle">true</item>
</style>
<!--回调页面WXPayEntryActivity关闭finish的时候增长-->
overridePendingTransition(0, 0);
<activity
android:name=".wxapi.WXPayEntryActivity"
android:configChanges="orientation|screenSize"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/wxPayTheme"
android:windowSoftInputMode="adjustPan|stateAlwaysHidden" />
复制代码
@Subscribe(threadMode = ThreadMode.MAIN)
public void payment(WXPayEntryEntity wxPayEntryEntity) {
//TODO 当客户端收到微信支付成功的回调后,继续向后台服务器进行验证为最终的结果
// .......此处省略调用服务器接口,查询结果逻辑......
// 此处如下代码只是做为测试使用,这里须要去服务器异步查询结果
switch (wxPayEntryEntity.getPayStatus()) {
case BaseResp.ErrCode.ERR_OK:
showToast(this, "支付成功");
break;
case BaseResp.ErrCode.ERR_AUTH_DENIED:
showToast(this, "微信受权失败");
break;
case BaseResp.ErrCode.ERR_COMM:
showToast(this, "订单支付失败!");
break;
case BaseResp.ErrCode.ERR_SENT_FAILED:
showToast(this, "微信发送失败");
break;
case BaseResp.ErrCode.ERR_UNSUPPORT:
showToast(this, "微信不支持");
break;
case BaseResp.ErrCode.ERR_USER_CANCEL:
showToast(this, "用户点击取消并返回");
break;
default:
showToast(this, "订单支付失败!");
break;
}
}
复制代码
# 微信混淆
-keep class com.tencent.mm.opensdk.** { *; }
-keep class com.tencent.wxop.** { *; }
-keep class com.tencent.mm.sdk.** { *; }
复制代码
alipaySdk-15.6.5-20190718211148.aar
复制到libs
目录下allprojects {
repositories {
// 支付宝 SDK AAR 包所需的配置
flatDir {
dirs 'libs'
}
google()
jcenter()
}
}
复制代码
4.Module项目的build.gradle增长依赖android
// 支付宝 SDK AAR 包所需的配置
implementation (name: 'alipaySdk-15.6.5-20190718211148', ext: 'aar')
复制代码
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
复制代码
/**
* 支付宝支付
*
* @param payInfo 预支付信息
*/
private void aliPay(final String payInfo) {
// 1.去服务器拿支付订单
final Runnable payRunnable = new Runnable() {
@Override
public void run() {
PayTask aliPay = new PayTask(PayDialogActivity.this);
Map<String, String> result = aliPay.payV2(payInfo, true);
Log.d(TAG, result.toString());
Message msg = new Message();
msg.what = SDK_PAY_FLAG;
msg.obj = result;
payHandler.sendMessage(msg);
}
};
// 必须异步调用
Thread payThread = new Thread(payRunnable);
payThread.start();
}
复制代码
/**
* 支付宝回调
*/
static class PayHandler extends Handler {
private final WeakReference<PayDialogActivity> payDialogActivityWrf;
private PayHandler(PayDialogActivity payDialogActivityWrf) {
this.payDialogActivityWrf = new WeakReference<>(payDialogActivityWrf);
}
@Override
public void handleMessage(Message msg) {
if (SDK_PAY_FLAG == msg.what) {
@SuppressWarnings("unchecked")
PayResult payResult = new PayResult((Map<String, String>) msg.obj);
//对于支付结果,请商户依赖服务端的异步通知结果。同步通知结果,仅做为支付结束的通知。
String resultStatus = payResult.getResultStatus();
// 判断resultStatus 为9000则表明支付成功
if (TextUtils.equals(resultStatus, CODE_9000)) {
// TODO 该笔订单是否真实支付成功,须要依赖[服务端的异步通知]。
// 该笔订单是否真实支付成功,须要依赖服务端的异步通知。
if (payDialogActivityWrf.get() != null) {
payDialogActivityWrf.get().showAlert(payDialogActivityWrf.get(), "支付成功!");
}
} else {
// TODO 该笔订单是否真实支付成功,须要依赖[服务端的异步通知]。
if (payDialogActivityWrf.get() != null) {
payDialogActivityWrf.get().showAlert(payDialogActivityWrf.get(), "支付失败!");
}
}
}
}
}
复制代码
# 这个 ProGuard 文件被指定为 consumerProguardFiles。
# 如此一来,AAR 包的使用者在其应用进行 ProGuard 混淆时,将自动附加下列规则,
# 省去了接入 JAR 时手动在 ProGuard 规则文件中加入支付宝 SDK 规则的步骤。
-keep class com.alipay.android.app.IAlixPay{*;}
-keep class com.alipay.android.app.IAlixPay$Stub{*;}
-keep class com.alipay.android.app.IRemoteServiceCallback{*;}
-keep class com.alipay.android.app.IRemoteServiceCallback$Stub{*;}
-keep class com.alipay.sdk.app.PayTask{ public *;}
-keep class com.alipay.sdk.app.AuthTask{ public *;}
-keep class com.alipay.sdk.app.H5PayCallback {
<fields>;
<methods>;
}
-keep class com.alipay.android.phone.mrpc.core.** { *; }
-keep class com.alipay.apmobilesecuritysdk.** { *; }
-keep class com.alipay.mobile.framework.service.annotation.** { *; }
-keep class com.alipay.mobilesecuritysdk.face.** { *; }
-keep class com.alipay.tscenter.biz.rpc.** { *; }
-keep class org.json.alipay.** { *; }
-keep class com.alipay.tscenter.** { *; }
-keep class com.ta.utdid2.** { *;}
-keep class com.ut.device.** { *;}
# SDK 包可能不包含 utdid
-dontwarn com.ta.utdid2.**
-dontwarn com.ut.device.**
# SDK 包可能不包含 securitysdk
-dontwarn com.alipay.mobilesecuritysdk.**
复制代码
关于支付大概就是这么多了,总而言之,对于移动支付,APP客户端流程只须要作到如下几点就能完成支付:git
你好LiveDatagithub
移动支付那点事儿json
Android插件化探索性能优化