支付类型:
一次性支付
自动续费(支付宝周期扣款、微信委托扣款):1.支付并签约 2.先签约后扣费
注:微信委托扣款中先签约后扣费:自动续费、授权扣款、免密支付
支付宝
支付流程中各端交互逻辑
支付流程中商户APP端交互逻辑
先签约后扣费流程中各端交互逻辑:
1. 支付/签约前准备
导入aar集成支付宝客户端SDK,权限声明(网络,网络状态,WiFi状态)
对于先签约后扣费:判断是否安装支付宝。
根据用户ID、商品ID、支付平台等请求后台生成调起支付/签约所需参数:1.一次性支付、支付并签约:
String orderInfo
,订单号:String orderId
。2.先签约后扣费:String signParams
注:一次性支付、支付并签约:对APP调起支付来说没区别。区别在于后台请求生成订单时传入更多参数:如周期规则参数(首次扣费时间、扣费周期单位、扣费周期数量…)
// 判断是否安装支付宝:检查包名com.eg.android.AlipayGphone是否存在 List<PackageInfo> packageInfoList = context.getPackageManager().getInstalledPackages(0); boolean hasWallet = packageInfoList.stream() .map(packageInfo -> packageInfo.packageName) .anyMatch(s -> s.equals("com.eg.android.AlipayGphone"));
2. 调起支付/签约
- 一次性支付 、支付并签约
根据后台生成的订单信息,子线程中通过同步方法
PayTask#payV2(String orderInfo, boolean isShowPayLoading)
调起支付,完成同步支付与异步签约。
String orderInfo
:支付参数字符串,主要包含商户的订单信息,key=value形式,以&连接。
boolean isShowPayLoading
:调起支付宝时是否显示一个loading,建议为true// 服务器获取的订单信息 final String orderInfo = info; // 调起支付逻辑 Runnable payRunnable = new Runnable() { @Override public void run() { PayTask payTask = new PayTask(activity); Map<String, String> result = payTask.payV2(orderInfo, true); // 支付结果处理...... // handler.sendMessage() } }; // 调起支付 Thread payThread = new Thread(payRunnable); payThread.start();
- 先签约后扣费
将后台生成的签约参数拼接到下面链接之后(该链接里面的appid为固定值,不可修改),APP通过scheme唤起支付宝进行签约。
“alipays://platformapi/startapp?appId=&appClearTop=false&startMultApp=YES&sign_params=”
3. 支付/签约结果处理
- 一次性支付、支付并签约
支付完成之后会自动回到app中。
同步通知:
PayTask#payV2()
方法同步返回的结果Map<String, String>去后台验签解析获取支付结果。异步通知:后台创建订单的请求参数包含异步通知地址notify_url、sign_notify_url,支付完成后支付宝服务器会发送异步通知,后台也可查询接口确认结果。
Map<String, String>
:{ "memo" : "xxxxx", "result" : "{ \"alipay_trade_app_pay_response\":{ \"code\":\"10000\", \"msg\":\"Success\", \"app_id\":\"07148\", \"out_trade_no\":\"0853\", \"trade_no\":\"057647\", \"total_amount\":\"0.01\", \"seller_id\":\"71851\", \"charset\":\"utf-8\", \"timestamp\":\"2016-10-11 17:43:36\" }, \"sign\":\"NGfStJf3i3ooWBuCDIQSumOpaGBcQz+aoAqyGh3W6EqA/gmyPYwLJ2REFijY9XPTApI9YglZyMw+ZMhd3kb0mh4RAXMrb6mekX4Zu8Nf6geOwIa9kLOnw0IMCjxi4abDIfXhxrXyj\", \"sign_type\":\"RSA2\" }", "resultStatus" : "9000" }
resultStatus
:9000 订单支付成功 8000 正在处理中,支付结果未知(有可能已经支付成功),请查询商户订单列表中订单的支付状态 4000 订单支付失败 5000 重复请求 6001 用户中途取消 6002 网络连接出错 6004 支付结果未知(有可能已经支付成功),请查询商户订单列表中订单的支付状态 其它 其它支付错误 有些时候会出现商户app 在支付宝支付阶段被关闭导致无法正确收到同步结果,此时支付结果可以完全依赖服务端的异步通知。 由于同步通知和异步通知都可以作为支付完成的凭证,且异步通知支付宝一定会确保发送给商户服务端。为了简化集成流程,商户可以将同步结果仅仅作为一个支付结束的通知(忽略执行校验),实际支付是否成功,完全依赖服务端异步通知。
- 先签约后扣费
同步通知:后台调用支付宝个人协议页面签约接口时传入return_url;如果没有传入 return_url,那么签约完成后不再返回APP,直接回到支付宝首页。签约成功的情况下,可以在return_url里面设置APP的scheme地址去返回APP。同步通知会在return_url 后面拼接返回参数,可将参数去后台验签。
异步通知:异步通知(notify_url/应用网关地址)仅当用户签约成功或解约成功时触发。后台也可通过查询接口确认签约结果。
微信
支付流程中各端交互逻辑
支付流程中商户APP端交互逻辑
1. 支付/签约前准备
添加依赖:
implementation 'com.tencent.mm.opensdk:wechat-sdk-android-without-mta:+'
,权限声明:android.permission.INTERNET
。判断微信是否可用。
根据用户ID、商品ID、支付平台等请求后台生成调起支付/签约所需参数:1.一次性支付、支付并签约:prepay_id…。2.先签约后扣费:pre_entrustweb_id(两个小时内有效)。
注:一次性支付、支付并签约:对APP调起支付来说没区别。区别在于后台请求不同的接口生成prepay_id。
// 微信接口 IWXAPI wxapi = WXAPIFactory.createWXAPI(context, null); // 未安装微信 if (!wxapi.isWXAppInstalled()) {
} // 微信版本低不支持支付 if (wxapi.getWXAppSupportAPI() < Build.PAY_SUPPORTED_SDK_INT) {
}
// 需要服务器返回的订单信息 // 1.调起支付所需参数 private String appId; // APP ID private String partnerId; // 商户号 private String prepayId; // 后台去微信服务器请求生成的预支付ID:有效期2小时 private String packageValue; // 扩展字段,暂填写固定值"Sign=WXPay" private String nonceStr; // 随机字符串 private String timeStamp; // 时间戳:自1970年1月1日 0点0分0秒以来的秒数 private String sign; // 签名:签名方式一定要与统一下单接口使用的一致 // 2.订单号,用于支付结果查询 private String orderId;
2. 调起支付/签约
- 一次性付费、支付并签约
根据服务器获取的相关信息,创建PayReq,IWXAPI调起支付
// 微信API IWXAPI wxapi = WXAPIFactory.createWXAPI(context, null); // 注册APP wxapi.registerApp(appId); // 调起支付对象PayReq PayReq payReq = new PayReq(); payReq.appId = ""; payReq.partnerId = ""; payReq.prepayId = ""; payReq.packageValue = ""; payReq.nonceStr = ""; payReq.timeStamp = ""; payReq.sign = ""; payReq.extData = ""; // 可附加的额外数据(如加入订单号)。会在微信回调Activity中返回 // 调起支付 // PayReq参数不正确会导致调起微信支付失败,返回false; // PayReq参数正确则调起微信支付成功,返回true。 wxapi.sendReq(payReq);
- 先签约后扣费
后台预签约生成pre_entrustweb_id。
WXOpenBusinessWebview.Req req = new WXOpenBusinessWebview.Req(); req.businessType = 12; // 固定值 HashMap queryInfo = new HashMap<>(); queryInfo.put("pre_entrustweb_id","......"; req.queryInfo = queryInfo; api.sendReq(req);
3. 支付/签约结果处理
- 一次性支付、支付并签约
同步通知:通过微信支付界面返回APP,会回调WXPayEntryActivity,可在此界面处理支付结果。"失败"或"成功"则去后台查询确认结果,“取消"可直接提示。
异步通知:完成支付后微信将支付结果发送到notify_url,将签约结果发送到contract_notify_url。
注:未完成支付则签约也失败。
- 通过
WXPayEntryActivity
处理支付结果- 目录:申请商户号时提供的包名.wxapi.WXPayEntryActivity
- Activity注册
<activity name=".wxapi.WXPayEntryActivity" android:exported="true" android:launchMode="singleTop" />
- Activity实现
IWXAPIEventHandler
重写onResp(BaseResp resp)
public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler { private IWXAPI wxapi; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); wxapi = WXAPIFactory.createWXAPI(getApplicationContext(), null); wxapi.handleIntent(getIntent(), this); } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); setIntent(intent); wxapi.handleIntent(intent, this); } @Override public void onReq(BaseReq baseReq) { } @Override public void onResp(BaseResp baseResp) { // 微信支付 if (baseResp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) { // 订单号 String orderId = ((PayResp) baseResp).extData; switch (baseResp.errCode) { case 0: // 支付成功 BaseResp.ErrCode.ERR_OK // 支付结果服务器查询 break; case -1: // 支付错误 // 支付结果服务器查询 break; case -2: // 用户取消 BaseResp.ErrCode.ERR_USER_CANCEL // 支付取消,可通知服务器关闭此订单 break; default: break; } // 退出activity finish(); } } }
- 通过
WXPayEntryActivity
处理支付结果存在一个问题:不通过微信支付界面返回APP,支付结果得不到处理。- 调起支付情况分析:
微信启动了
微信返回APP
onPause() 支付界面 onResume()
不通过微信返回APP
onPause() 支付界面 home->onStop() app->onStart() onResume()
微信未启动
微信返回APP
onPause() 微信界面 onStop() 自动返回app->onStart() 支付界面 onResume()
不通过微信返回APP
onPause() 微信界面 onStop() 自动返回app->onStart() 支付界面 home->onResume()、onPause()、onStop() app->onStart() onResume()
- 解决方法
发起支付前,存下订单号。
String orderId = "...";
onResume()生命周期下查询订单支付结果。
if (orderId == null) { return; } // 服务器查询订单 // 重置 orderId = null;
注意:在“微信未启动”且“不通过微信返回APP”时,在微信支付界面按下home会回调onResume()去服务器查询支付结果。
- 调起支付情况分析:
- 通过
- 先签约后扣费
完成签约后微信将支付结果发送到notify_url,安卓暂不支持返回APP,签约完成后停留在微信内。
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.mushiming.com/mjyfx/571.html