Android 微信支付接入—— 客户端
最近接到项目需要,需要接入微信支付。微信支付的麻烦早有耳闻,所以之前也一直不敢接这样的项目,但是没办法为了生计,还是要学习。本篇教程主要讲述如何接入微信支付客户端
一:添加依赖:
api 'com.tencent.mm.opensdk:wechat-sdk-android-without-mta:+'//微信支付SDK
implementation 'com.squareup.okhttp3:okhttp:3.10.0'//网络请求okhttp
implementation 'com.google.code.gson:gson:2.8.2'//Gson
添加相关权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/><!-- 文件写入权限 -->
<uses-permission android:name="android.permission.INTERNET" /><!-- 网络权限-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><!--访问网络状态-->
使用:
//获取手机设备ip地址
String ip = getIPAddress(this);
//构建请求body,设置请求参数
RequestBody body = new FormBody.Builder()
.add("account", "sanyesan")
.add("password", "1234")
.add("totalAmount", "5")
.add("subject", "使用微信支付付款")
.add("ip", ip)
.build();
final Request request = new Request.Builder()
.url(WECHAT_PAY_URL)
.addHeader("Content-type", "application/json")
.post(body)
.build();
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NonNull Call call, @NonNull IOException e) {
Log.d(TAG, "onFailure: 服务器请求错误");
}
@Override
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
if (response.body() == null) {
return;
}
String resBodyString = response.body().string();
Log.d(TAG, "onResponse: 请求成功");
System.out.println(resBodyString);
Runnable payRunnable = () -> {
//将返回的Json请求转成Json对象
ReturnPayRequestBean returnPayRequestBean = new Gson().fromJson(resBodyString, ReturnPayRequestBean.class);
// 通过WXAPIFactory工厂,获取IWXAPI的实例
IWXAPI api = WXAPIFactory.createWXAPI(this, APP_ID, true);
//在微信中注册应用
api.registerApp(APP_ID);//微信开放平台对应的应用id
if (returnPayRequestBean != null) {
//设置微信支付请求参数并返回请求
PayReq payRequest = new PayReq();
payRequest.appId = returnPayRequestBean.getAppId();
payRequest.partnerId = returnPayRequestBean.getMchId();
payRequest.prepayId = returnPayRequestBean.getPrepayId();
payRequest.nonceStr = returnPayRequestBean.getNonceStr();
payRequest.timeStamp = returnPayRequestBean.getTimeStamp();
Log.d(TAG, "run: package:" + returnPayRequestBean.getPackageName());
payRequest.packageValue = returnPayRequestBean.getPackageName();
payRequest.sign = returnPayRequestBean.getSign();
api.sendReq(payRequest);
} else {
Log.d(TAG, "onResponse: 未获取预支付交易会话ID");
}
};
Thread payThread = new Thread(payRunnable);
payThread.start();
}
});
获取手机客户端ip地址:
/**
* 获取手机客户端的ip地址
* @param activity 当前活动Context
* @return IP地址
*/
public static String getIPAddress(Activity activity) {
ConnectivityManager mConnectivityManager = (ConnectivityManager)activity.getSystemService(CONNECTIVITY_SERVICE);//获取系统的连接服务
NetworkInfo info = mConnectivityManager.getActiveNetworkInfo();
if (info != null && info.isConnected()) {
if ((info.getType() == ConnectivityManager.TYPE_MOBILE) || (info.getType() == ConnectivityManager.TYPE_WIFI) ){//当前使用2G/3G/4G网络
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();
}
}
}
}
catch (SocketException e) {
e.printStackTrace();
}
}
}
else { //
ToastUtil.toastSync(activity, "当前无网络连接,请在设置中打开网络");
return "";
}
return "";
}
在你的包的根目录下,创建wxapi这个package包(命名一定是wxapi,否则后面回调不成),然后再创建WXPayEntryActivity这个类
WXPayEntryActivity实现IWXAPIEventHandler接口,这个Activity页面就是支付结果的回调页面,下面是它最简单地实现:
public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler {
private IWXAPI api;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_w_x_pay_entry);
// 1.将app注册到微信端
api = WXAPIFactory.createWXAPI(this, Config.APPID);
api.handleIntent(getIntent(),this);
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
api.handleIntent(intent,this);
}
@Override
public void onReq(BaseReq baseReq) {
}
@Override
public void onResp(BaseResp baseResp) {
// 2.接收传过来的参数
PayResp resp = (PayResp) baseResp;
String order_id = resp.extData;
// 3. 根据状态去做相应的处理
if (baseResp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
switch (baseResp.errCode) {
case 0://支付成功
paySuccess(order_id); //支付成功页面返回或点击返回商家所做的事情
break;
case -1://错误,可能的原因:签名错误、未注册APPID、项目设置APPID不正确、注册的APPID与设置的不匹配、其他异常等
Toast.makeText(this, 支付错误, Toast.LENGTH_SHORT).show();
break;
case -2://用户取消,无需处理。发生场景:用户不支付了,点击取消,返回APP。
Toast.makeText(this, 用户取消了订单, Toast.LENGTH_SHORT).show();
break;
}
finish();//这里需要关闭该页面
}
}
/**
* 支付成功处理 (api)
* @param order_id
*/
private void paySuccess(String order_id){
//支付成功后要做的事....
}
}
注:targetSdkVersion升级到30的第三方应用,由于Android 11 软件包可见性 特性的影响,OpenSDK的接口可能无法正常拉起微信,从而无法使用微信的部分功能,需要在主工程的AndroidManifest.xml 中增加标签,代码如下:
// 在应用的AndroidManifest.xml添加如下<queries>标签
<queries>
<package android:name="com.tencent.mm" /> // 指定微信包名
</queries>
添加以上标签之后,需要开发者升级编译工具,否则会出现编译错误。
- Android Studio 需要升级至 3.3 及以上,建议升级至 4.0 及以上版本
- Android SDK Build-Tools 需要升级至 30 及以上版本
- com.android.tools.build:gradle 需要升级至 3.6.0 版本及以上