1、支付宝
这里首先肯定是申请好支付宝支付功能和商户ID等等信息,然后给到后台配置。
支付宝官方demo中目前有2种调起方式:原生调起,H5调起
1.如果你的项目是原生APP,那么项目组的后台接入支付宝SDK后会返回给客户端一串超长的字符串:
比如
alipay_root_cert_sn=6879rjofjosjfoiwjfw7dddf3d3b83462e1dfcf6&app_cert_sn=85fkpwejopfjw320dadf8f68a5ffb&app_id=202....
客户端拿着这串去调起支付宝即可,这串字符串中包含了appid,私钥等信息,所以本地无需配置这些信息,因为支付宝有这样一段话:
在真实 App 中,私钥(如 RSA_PRIVATE 等)数据严禁放在客户端,同时加签过程务必要放在服务端完成,
否则可能造成商户私密数据泄露或被盗用,造成不必要的资金损失,面临各种安全风险。
所以客户端无需配置什么,直接调起就完事儿
第一步:
先导入这个aar包
第二步
调起支付:orderInfo就是那个超长字符串
fun toAliPay(activity: AppCompatActivity, orderInfo: String, mHandler: Handler, flag: Int) {
val payRunnable = Runnable {
val alipay = PayTask(activity)
val result = alipay.payV2(orderInfo, true)
//发送给handle
val msg = Message()
msg.what = flag
msg.obj = result
mHandler.sendMessage(msg)
}
// 必须异步调用
val payThread = Thread(payRunnable)
payThread.start()
}
这样就OK了,支付完成还有个回调,解析handle发出去的result参数即可,
code = 9000代表支付成功,其他失败
2.如果你的项目是APP嵌套的H5商城需要调起支付宝,那么有2个方案:
方案一:H5拿到那个超长字符串给APP,APP去调起支付宝,同上
方案二:H5直接调起支付宝,无需上面那串字符串。(前提是你的H5商城已经实现了支付宝支付,也就是说在系统浏览器可以调起支付宝支付)
下面我们说下方案二:
核心代码:
private class MyWebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(final WebView view, String url) {
if (!(url.startsWith("http") || url.startsWith("https"))) {
return true;
}
/**
* 推荐采用的新的二合一接口(payInterceptorWithUrl),只需调用一次
*/
final PayTask task = new PayTask(H5PayDemoActivity.this);
boolean isIntercepted = task.payInterceptorWithUrl(url, true, new H5PayCallback() {
@Override
public void onPayResult(final H5PayResultModel result) {
final String url = result.getReturnUrl();
if (!TextUtils.isEmpty(url)) {
H5PayDemoActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
view.loadUrl(url);
}
});
}
}
});
/**
* 判断是否成功拦截
* 若成功拦截,则无需继续加载该URL;否则继续加载
*/
if (!isIntercepted) {
view.loadUrl(url);
}
return true;
}
}
mWebView.setWebViewClient(new MyWebViewClient());
这里拦截到H5的支付即可调起支付宝支付,当然也是需要aar包的
这里记得不要修改WebView的userAgent,不然shouldOverrideUrlLoading不会回调,那么自然也不会拦截到了。
2、微信
这里首先肯定是申请好微信支付功能和商户ID等等信息,然后给到后台配置。
微信和支付宝一样也有2种方式,也可以H5中调起,但是我一直没测成功,修改了refer还是没成功,所以这里只说原生调起微信支付
第一步:导入包依赖
api 'com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+'
第二步:调起微信支付(这些参数后台会返回给客户端)
fun toWechatPay(context: Context, wxPayBean: Pay.WxpayBean) {
val api = WXAPIFactory.createWXAPI(context, wxPayBean.appid)
api.registerApp(wxPayBean.appid)
//这里的bean,是服务器返回的json生成的bean
val payRequest = PayReq()
payRequest.appId = wxPayBean.appid
payRequest.partnerId = wxPayBean.partnerid
payRequest.prepayId = wxPayBean.prepayid
payRequest.packageValue = "Sign=WXPay"//固定值
payRequest.nonceStr = wxPayBean.noncestr
payRequest.timeStamp = wxPayBean.timestamp.toString()
payRequest.sign = wxPayBean.sign
//发起请求,调起微信前去支付
api.sendReq(payRequest)
}
public static class WxpayBean {
private String appid;
private String partnerid;
private String prepayid;
private String noncestr;
private long timestamp;
@SerializedName("package")
private String packageX;
private String sign;
}
这样就可以调起支付了,接下来就是支付完成之后的回调了,微信的回调必须在你的项目包名下创建一个包名.wxapi的包名,然后把WXPayEntryActivity放入即可,
微信测试支付参数:
https://wxpay.wxutil.com/pub_v2/app/app_pay.php
这里要注意,如果你是一个包名,然后想通过不同的渠道去打包多个不同的APP,那么可以在AndroidManifest中配置一下activity-alias 别名的方式解决,(其他,比如人脸识别,分享等等需要包名一致的都可以通过此方式解决)否则将会收不到回调
如下配置即可(applicationId为build.gradle中的productFlavors的applicationId):
<activity
android:name=".wxapi.WXPayEntryActivity"
android:exported="true"
android:launchMode="singleTop" />
<activity-alias
android:name="${applicationId}.wxapi.WXPayEntryActivity"
android:exported="true"
android:targetActivity=".wxapi.WXPayEntryActivity"/>
下面是回调代码:
public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler {
private IWXAPI api;
private String app_id = "wx88888888888";//微信开发后台申请的app_id
private static final String TAG = "TAG";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//这里可以不填写
// setContentView(R.layout.pay_result);
api = WXAPIFactory.createWXAPI(this, 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) {
}
/**
* 处理结果回调
*
* @param resp
*/
@Override
public void onResp(BaseResp resp) {
Log.d(TAG, "onPayFinish, errCode = " + resp.errCode);
if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
//返回给客户端或者H5反馈
EventBus.getDefault().post(new WxPayEvent(resp.errCode));
switch (resp.errCode) {
case 0://支付成功
Log.d(TAG, "onResp: resp.errCode = 0 支付成功");
break;
case -1://错误,可能的原因:签名错误、未注册APPID、项目设置APPID不正确、注册的APPID与设置的不匹配、其他异常等
Log.d(TAG, "onResp: resp.errCode = -1 支付错误");
break;
case -2://用户取消,无需处理。发生场景:用户不支付了,点击取消,返回APP。
Log.d(TAG, "onResp: resp.errCode = -2 用户取消");
break;
}
finish();//这里需要关闭该页面
}
}
}
另外如果大家想要把支付做成一个lib的话,需要把aar包放在module中通过api引用,那么需要在你的project的gradle中加一个配置,不然无法通过api引用
在module中使用api导入aar的时候会报错,需要在project的gradle中配置
//module依赖aar
flatDir {
dirs project(':lib-pay').file('libs')
}
然后在module lib中引用:
api (name: 'alipaySdk-15.7.9-20200727142846', ext: 'aar')
再次同步即可。