什么是移动支付
移动支付指的是用户使用移动的设备,完成对所购买商品或者服务的支付功能。
移动支付分为:
l远程支付(网上支付,短信支付)
l近场支付(刷卡,pos机)
常见的支付厂商
支付宝——阿里出品,使用量比较多
微信——腾讯出品,使用量也是越来越多
易付宝——苏宁易购
财付通——腾讯出品,使用量不大
银联——不属于某一个公司,是指中国的银行卡联合组织
百付宝——百度出品
支付宝钱包——阿里的
百度钱包——百度
快钱
ping++——三方聚合支付平台,整合了很多支付平台,类似 SharedSDK 在分享中的作用,不建议接入
1、接入前准备,需要在支付宝创建应用
https://openhome.alipay.com/platform/appManage.htm#/apps
a.创建应用;
b.公钥互换;
b.商户签约;
支付宝状态码:https://docs.open.alipay.com/204/105302
支付宝集成文档:https://docs.open.alipay.com/204/105296/
1、创建应用
如果是模拟的话选应用就可以(网页应用不需要太多认证,后面也能实现 APP 支付功能),真正写 APP 的话再选移动应用
真正上线的 APP 可以根据需求勾选对应的功能,模拟 demo 的话不需要这些,只需要下面的加签方式(下张图),设置公钥(和支付宝交换公钥)
2、公钥互换
点击设置公钥,验证手机,完成后显示如下界面
点击支付宝密钥生成器下载工具,解压目录如下(如果打开生成器出现闪退的情况,一:没配置 Java 环境变量;二:压缩包在中文目录的文件夹下)
点击:生产 RSA 秘钥
文件夹下会多出三个文件
rsa_public_key.pem 公共密钥
rsa_private_key.pem
rsa_private_key_pkcs8.pem 这两个都是私有密钥(上一张图片有一行文字(Java 代码请使用 pkcs8 格式的私钥签名),所以根据自己的需求选择)
将公钥复制到支付宝支付宝需要公钥的输入框中
如果不小心把密钥生成器关了,而你还没复制公钥,可以在 rsa_public_key.pem 中找到,但不要复制开头和结尾的那两行(不要复制 -----BEGIN PRIVATE KEY----- 和 -----END PRIVATE KEY----- ,复制中间的就可以)
点击验证公钥正确性,验证公钥是否正确
点击下载下载签名工具并解压
双击:支付宝报文签名生成器 SHA256withRSA2048_V1.0.bat
复制 pkcs8 中的私钥到输入框中
注意不要复制 -----BEGIN PRIVATE KEY----- 和 -----END PRIVATE KEY-----
点击生产签名
将生产的签名复制到验证输入框中,点击验证,提示验证成功即可
3、商户签约
支付宝完整支付流程
2、参照支付宝的集成文档
1、在开放平台文档中心的左边点 SDK&DEMO下载
2、点击 SDK&DEMO
3、根据支付宝的集成文档导入支付宝 SDK
根据文档在 App Module 的 build.gradle 中添加依赖的时候,依赖的名字要和SDK 的名字一样
alipaySdk-15.6.2-20190416165036 要和 SDK 的名字一样
implementation (name: 'alipaySdk-15.6.2-20190416165036', ext: 'aar')
其他的根据文档就可以了,代码在下面
3、代码操作
1、清单文件中添加权限
2、在 Activity 中初始化权限
private void initPermission() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE)
!= PackageManager.PERMISSION_GRANTED
|| ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
}, 1002);
} else {
showToast("支付宝 SDK 已有所需的权限");
}
}
3、模拟用户下单
1.请求自己家的服务器(商品 id,用户 userid,金额,商品数量)
2.解析自己家服务器返回的的数据,拿到支付串码
3.调用支付的 sdk,拉起支付界面
4.处理支付宝 app 返回的支付结果
/**
* amount 价格
* token url 地址需要的用户的标识
* version 应用版本号
* os 操作系统
* 这些都是网络请求接口需要的参数,根据自己实际情况更改就行
*/
private void aliPay() {
RequestQueue requestQueue = Volley.newRequestQueue(MainActivity.this);
StringRequest request = new StringRequest(Request.Method.POST, mUrl, this, this){
@Override
protected Map getParams() throws AuthFailureError {
ArrayMap map = new ArrayMap<>();
map.put("amount","1.0");
map.put("token","mKVoQRrXlMvmfWbgWzyDYHF1KOUN5e4bwWrOiab9tZ8sWIQAZmg48lSa2NOORqpko6V0l4cYCs1Uip23M6MglE6Xp6LvHKO9RUNP4m8pHjp1zHb8nmK1bU1pvRp2LFkwA");
map.put("version","3.3.3");
map.put("os","android");
return map;
}
};
requestQueue.add(request);
}
// 请求失败的回调
@Override
public void onErrorResponse(VolleyError volleyError) {
}
// 请求成功的回调
@Override
public void onResponse(String string) {
//2.解析自己家服务器返回的的数据,拿到支付串码
Gson gson = new Gson();
AliPayBean aliPayBean = gson.fromJson(string, AliPayBean.class);
//3.调用支付的sdk,拉起支付界面
callAliSdk(aliPayBean);
}
private void callAliSdk(AliPayBean aliPayBean) {
final String orderInfo = aliPayBean.getResult().getSign(); // 订单信息
Runnable payRunnable = new Runnable() {
@Override
public void run() {
PayTask alipay = new PayTask(MainActivity.this);
Map result = alipay.payV2(orderInfo,true);
Message msg = new Message();
msg.what = SDK_PAY_FLAG;
msg.obj = result;
mHandler.sendMessage(msg);
}
};
// 必须异步调用
Thread payThread = new Thread(payRunnable);
payThread.start();
}
//4.处理支付宝app返回的支付结果
@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case SDK_PAY_FLAG: {
@SuppressWarnings("unchecked")
PayResult payResult = new PayResult((Map) msg.obj);
/**
* 对于支付结果,请商户依赖服务端的异步通知结果。同步通知结果,仅作为支付结束的通知。
*/
String resultInfo = payResult.getResult();// 同步返回需要验证的信息
String resultStatus = payResult.getResultStatus();
// 判断resultStatus 为9000则代表支付成功
if (TextUtils.equals(resultStatus, "9000")) {
// 该笔订单是否真实支付成功,需要依赖服务端的异步通知。
showToast("支付成功:"+payResult);
Log.d(TAG, "支付成功: "+payResult+",resultInfo:"+resultInfo);
} else {
// 该笔订单真实的支付结果,需要依赖服务端的异步通知。
showToast("支付失败:"+payResult);
Log.d(TAG, "支付失败: "+payResult+",resultInfo:"+resultInfo);
}
break;
}
default:
break;
}
};
};
public void showToast(String msg){
Toast.makeText(this,msg,Toast.LENGTH_SHORT).show();
}
PayResult(这个类是在之前下载的 SDK&DEMO 中的 DEMO 中找的)
import java.util.Map;
import android.text.TextUtils;
public class PayResult {
private String resultStatus;
private String result;
private String memo;
public PayResult(Map rawResult) {
if (rawResult == null) {
return;
}
for (String key : rawResult.keySet()) {
if (TextUtils.equals(key, "resultStatus")) {
resultStatus = rawResult.get(key);
} else if (TextUtils.equals(key, "result")) {
result = rawResult.get(key);
} else if (TextUtils.equals(key, "memo")) {
memo = rawResult.get(key);
}
}
}
@Override
public String toString() {
return "resultStatus={" + resultStatus + "};memo={" + memo
+ "};result={" + result + "}";
}
/**
* @return the resultStatus
*/
public String getResultStatus() {
return resultStatus;
}
/**
* @return the memo
*/
public String getMemo() {
return memo;
}
/**
* @return the result
*/
public String getResult() {
return result;
}
}
AliPayBean(解析数据用的bean类)
public class AliPayBean {
/**
* code : 0
* desc :
* result : {"sign":"app_id=2017071807800448&method=alipay.trade.app.pay&version=1.0&format=JSON&charset=utf8&sign_type=RSA2×tamp=2019-06-04%2010%3A53%3A22¬ify_url=https%3A%2F%2Fapi.banmi.com%2Fapi%2Fapp%2Fv3%2Fpayments%2Falibaba&biz_content=%7B%22subject%22%3A%22%E4%BC%B4%E7%B1%B3%E6%97%85%E8%A1%8C%22%2C%22out_trade_no%22%3A%22APP1559616802973ALIPAY321072%22%2C%22total_amount%22%3A%221.00%22%2C%22timeout_express%22%3A%2215m%22%7D&sign=Li%2FBFrL1OH3txIRs3yGNsY%2FWrKv9vB%2BF3gg4rakf5RuGZpqRuksr1Mf7AOySylLE809n4%2BjI3Rt3dbwxzg0AtAjuGP3%2BbQ4FAqj%2B6vaIbRIdiZhKoYTimVsdAFgpt93i3mdfl7B6x7jPfBLPyMmRAmJxwYcdZRreqT0oJiihs7LsfIrwDqjlQ9pJllmOE4AiZNuGEgBgPFNlqOiRQCplcfYNTCcw5bJGHJSiKAGOr5EpClQTJFzk28L%2BgOLZkKtXHgu62aQ1ZYxmeio8nXHfiaa0vv9D0FlTKWkFQErHcwub%2Bys5JkCwnkc%2FNiyLSlN%2BtDaMI6H9%2FRI6k6QEGyedsQ%3D%3D","id":10572}
*/
private int code;
private String desc;
private ResultBean result;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public ResultBean getResult() {
return result;
}
public void setResult(ResultBean result) {
this.result = result;
}
public static class ResultBean {
/**
* sign : app_id=2017071807800448&method=alipay.trade.app.pay&version=1.0&format=JSON&charset=utf8&sign_type=RSA2×tamp=2019-06-04%2010%3A53%3A22¬ify_url=https%3A%2F%2Fapi.banmi.com%2Fapi%2Fapp%2Fv3%2Fpayments%2Falibaba&biz_content=%7B%22subject%22%3A%22%E4%BC%B4%E7%B1%B3%E6%97%85%E8%A1%8C%22%2C%22out_trade_no%22%3A%22APP1559616802973ALIPAY321072%22%2C%22total_amount%22%3A%221.00%22%2C%22timeout_express%22%3A%2215m%22%7D&sign=Li%2FBFrL1OH3txIRs3yGNsY%2FWrKv9vB%2BF3gg4rakf5RuGZpqRuksr1Mf7AOySylLE809n4%2BjI3Rt3dbwxzg0AtAjuGP3%2BbQ4FAqj%2B6vaIbRIdiZhKoYTimVsdAFgpt93i3mdfl7B6x7jPfBLPyMmRAmJxwYcdZRreqT0oJiihs7LsfIrwDqjlQ9pJllmOE4AiZNuGEgBgPFNlqOiRQCplcfYNTCcw5bJGHJSiKAGOr5EpClQTJFzk28L%2BgOLZkKtXHgu62aQ1ZYxmeio8nXHfiaa0vv9D0FlTKWkFQErHcwub%2Bys5JkCwnkc%2FNiyLSlN%2BtDaMI6H9%2FRI6k6QEGyedsQ%3D%3D
* id : 10572
*/
private String sign;
private int id;
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
}