一、前言
现在第三方支付在市场上几乎变成了不可或缺的支付方式,其中支付宝微信在其中可谓是翘楚,写这篇文章的目的旨在给刚接触支付或者是在集成的时候遇到坑的同胞们。
二、支付宝的接入
在这里只讲app支付,即在app里面集成支付sdk,在用户支付的时候唤起支付宝进行支付,下面讲一下如何接入支付宝
1.集成sdk,将alipaySdk-20161009(我在项目中使用的就是20161009版本).jar添加到应用libs目录下,并添加到库里面去
2.在manifest中进行注册相应的activity,其中h5payactivity,是用户手机中没有安装支付宝的时候跳转的h5页面,后者是已经安装支付宝的时候跳转的界面
<!--支付宝页面-->
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
<activity
android:name="com.alipay.sdk.app.H5PayActivity"
android:configChanges="orientation|keyboardHidden|navigation"
android:exported="false"
android:screenOrientation="behind" />
<activity
android:name="com.alipay.sdk.auth.AuthActivity"
android:configChanges="orientation|keyboardHidden|navigation"
android:exported="false"
android:screenOrientation="behind" />
3.声明权限,和添加混淆,这些权限无非就是网络权限,写入权限吗,读取手机状态的权限,等,这点过,没有什么坑
<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" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
添加混淆
-libraryjars libs/alipaySdk-20161009.jar
-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 *;}
4.在代码里面添加支付
首先是一堆参数,在这个里面坑挺多的,其中这些支付请求参数由于安全性的考虑需要后台进行返回,在返回的时候进行加密处理,然后客户端接收之后进行解密处理,在项目里面我们用的加密方式是des加密。参数详细
https://doc.open.alipay.com/doc2/detail.htm?spm=a219a.7629140.0.0.x7kkCI&treeId=204&articleId=105465&docType=1
其中请求参数appid,sign是后台生成的一个签名,其生成步骤,详细请见
https://doc.open.alipay.com/docs/doc.htm?treeId=291&articleId=105974&docType=1
支付代码如下:
HttpDataResultMall.userRecharge(Constants.USER_RECHARGE_AL, btnChongZhizhifu.getText().toString().substring(2, btnChongZhizhifu.getText().toString().length() - 1), new DataResult<CommonBean<DataBean>>() {
@Override
public void onSuccessData(CommonBean<DataBean> result) {
if (result.isSuccess()) {
//进行解密
String des = UtilDES.ebotongDecrypto(result.getData().getDes());
LogUtil.i("===============>>" + des);
payV2(view, des);
} else {
dialog.dismiss();
chongzhiPopwindow.dismiss();
showToast(result.getData().getDes());
}
}
});
通过向后台请求支付参数,返回之后通过des解密进行调用支付宝的支付接口
Runnable payRunnable = new Runnable() {
@Override
public void run() {
PayTask alipay = new PayTask(AccountActivity.this);
Map<String, String> result = alipay.payV2(orderInfo, true);
Log.i("msp", result.toString());
Message msg = new Message();
msg.what = SDK_PAY_FLAG;
msg.obj = result;
handler.sendMessage(msg);
}
};
Thread payThread = new Thread(payRunnable);
payThread.start();
5 . 通过handler进行处理返回信息
private Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message message) {
switch (message.what) {
case SDK_PAY_FLAG:
PayResultBean payResultBean = new PayResultBean((Map<String, String>) message.obj);
if (payResultBean.getResultStatus().equals("9000")) {
dialog.dismiss();
chongzhiPopwindow.dismiss();
//更新联赛币
getUserCoin();
} else {
dialog.dismiss();
chongzhiPopwindow.dismiss();
Toast.makeText(AccountActivity.this, payResultBean.getMemo(), Toast.LENGTH_SHORT).show();
}
break;
}
return false;
}
});
在resulestate =9000的时候说明成功支付,其他数据说明如下所示:
9000 订单支付成功
8000 正在处理中,支付结果未知(有可能已经支付成功),请查询商户订单列表中订单的支付状态
4000 订单支付失败
5000 重复请求
6001 用户中途取消
6002 网络连接出错
6004 支付结果未知(有可能已经支付成功),请查询商户订单列表中订单的支付状态
其它 其它支付错误
到此,支付宝的接入便成功完成,其中在签名的时候可能坑比较多,如果有什么问题的话,欢迎加qq群进行讨论, 570650538
三、微信的接入
在支付的时候微信的坑算是比较多的,其中微信跟支付宝的接入大同小异,下面我就来带大家一块接入一下,
1.集成sdk,将libammsdk.jar添加到libs目录下面,在此需要注意的是有的项目可能集成了友盟+的第三方登录和分享到微信的功能,那么在编译的时候可能会造成冲突,这个不用担心,把友盟中相应的jar包删掉就行了
2.和支付宝一样,微信在支付的时候同样需要传一系列的参数,同样appid 和sign等一系列重要的参数,均由后台提供,在返回的时候直接解密获取请求参数,然后调用微信的支付接口进行支付,在Android 端后台设置的时候需要一个应用签名,其生成方法如下所示,这个如果不正确的话,就会造成支付的失败,详细请见
https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_5
3.具体代码如下,调用支付接口
String des = UtilDES.ebotongDecrypto(result.getData().getDes());
Message message = handler.obtainMessage();
message.what = SDK_WXPAY_FLAG;
message.obj = des;
handler.sendMessage(message);
其中des,是生成的后台发送过来的支付请求参数在此进行解密,通过handler,进行轮循处理返回的消息,
private Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message message) {
switch (message.what) {
case SDK_WXPAY_FLAG:
try {
JSONObject json = new JSONObject((String) message.obj);
api = WXAPIFactory.createWXAPI(AccountActivity.this, Constants.WX_APPID);
api.registerApp(Constants.WX_APPID);
PayReq req = new PayReq();
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");
api.sendReq(req);
dialog.dismiss();
chongzhiPopwindow.dismiss();
} catch (Exception e) {
Log.e("PAY_GET", "异常:" + e.getMessage());
Toast.makeText(AccountActivity.this, "异常:" + e.getMessage(), Toast.LENGTH_SHORT).show();
}
break;
}
return false;
}
});
在支付处理的时候,微信和支付宝有点不一样就是微信会新建一个页面,支付之后跳转到相应的页面进行处理,
在mainfest里面进行添加结果处理页面,其中需要注意的是返回结果的activity名称不能错,这是由微信支付api决定的
<activity
android:name=".wxapi.WXPayEntryActivity"
android:exported="true"
android:launchMode="singleTop"
android:screenOrientation="portrait" />
activity里面相应处理代码:
@ContentView(R.layout.activity_wxpayentry_)
public class WXPayEntryActivity extends BaseActivity implements IWXAPIEventHandler{
private static final String TAG = "MicroMsg.SDKSample.WXPayEntryActivity";
private IWXAPI api;
@ViewInject(R.id.tv_wxpay_result)
private TextView tvPayResult;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setToolbar("支付结果");
api = WXAPIFactory.createWXAPI(this, Constants.WX_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) {
int code= baseResp.errCode;
if (code == 0){
//显示充值成功的页面和需要的操作
tvPayResult.setText("充值成功");
}
if (code == -1){
//错误
tvPayResult.setText("充值失败");
}
if (code == -2){
//用户取消
tvPayResult.setText("用户取消");
}
}
}
在返回的code值分别为0,-1,-2,分别代表成功,失败,取消,在具体项目里面开发人员可以定义相应的页面进行处理返回结果