Android开发学习之加密总结+支付集成问题
> 算法总结
> 银联支付
> 支付宝:要求需要公司账号
> 微信支付:微信更新测试服务器,demo,丢失聊天记录(安全码策略:keystore)
> 扩展:混合开发(android+h5,通信三种方式)
* 1.js主动调用android
* 2.android主动调用js
* 3.js callback回调式调用android
### 01.数字签名应用实战-签名
> 对登录信息(用户名、密码、时间戳 签名)
inputstream ins = null;
string usrename = "heima104";
string password = "123456";
system.out.println(system.currenttimemillis());
stringbuilder stringbuilder = new stringbuilder();
stringbuilder.append("username="+usrename)
.append("&password="+md5utils.md5(password))
.append("×tamp="+system.currenttimemillis());
string input = stringbuilder.tostring();
string sign = signatureutils.sign(input);
try {
string url = "https://120.77.241.119/encryptserver/login_v5?"+input+"&sign="+sign;
url url2 = new url(url);
httpurlconnection conn = (httpurlconnection) url2.openconnection();
system.out.println(url2.touri().tostring());
ins = conn.getinputstream();
string result = ioutils.convertstreamtostring(ins);
system.out.println(result);
} catch (exception e) {
e.printstacktrace();
} finally {
ioutils.close(ins);
}
### 02.数字签名应用实战-避免抓包
> 对提交参数md5:如果用户没有登录过,存储到;如果登录过不让登录,该url已经失效
string url = "https://120.77.241.119/encryptserver/login_v6?"+input+"&sign="+sign;
url url2 = new url(url);
string md5 = md5utils.md5(input+"&sign="+sign);
system.out.println(md5);
httpurlconnection conn = (httpurlconnection) url2.openconnection();
system.out.println(url2.touri().tostring());
ins = conn.getinputstream();
string result = ioutils.convertstreamtostring(ins);
> 手机验证码
### 03.加密算法总结
> 对称加密(des、aes):
* 1.优先使用des,如果提高安全度使用aes
* 2.可逆:开发中只要可逆都可以选择对称加密,缓存联系人信息
> 非对称rsa
* 1.可逆:公钥加密私钥解密;私钥加密公钥解密
* 2.秘钥对:公钥和私钥,不能手动指定,必须由生成
* 3.加密速度慢:不能加密大文件
* 4.分段加密:每次最大加密长度117字节
* 5.分段解密:每次最大解密长度128字节
* 应用场景:一般很少使用rsa加密和解密,用的最多的是它的数字签名
> 消息摘要:
* md5:16个字节,转成16进制32个字节
* sha1:20个字节,转成16进制40个字节
* sha256:32个字节,转成16进制64个字节
* 应用:md5使用最多
* 特点:不可逆,比如微信缓存用户密码,下一次不需要重新输入登录
* 避免撞库:加密多次,加盐
> 数字签名
* 为了校验参数安全:支付传递参数,有可能被篡改
* 签名:必须使用私钥
* 校验:必须使用公钥
* 最常用算法sha256withrsa
### 04.第三方支付介绍
> 三大支付:支付宝支付、微信支付、银联支付、京东钱包、百度钱包
> ping++:集成了很多第三方支付平台的 第三方平台,为了便于开发者使用集成。不建议使用,支付很简单不需要使用别人集成好的sdk
> 以后开发能不能独立实现支付平台:不可能,需要支付牌照
> 支付难不难:不难,银联5分钟、支付宝10分钟、微信25分钟
### 05.结合美团支付分析支付四部曲
> 美团支付创建:挑选商品:价格、数量、名称 -> 选择支付方式
![](img/pay_four_step.png)
### 06.银联支付sdk
> 第三方支付开发平台:开发者网站,下载sdk
> 任何开发平台:不要着急集成,先运行demo
> 提供测试账号
### 07.银联支付前2步
> 前2步不需要集成sdk
> 提交参数到服务器
> 解析服务器返回的支付串码
private void requestvolley() {
//1.创建请求对象
stringrequest request = new stringrequest("https://101.231.204.84:8091/sim/getacptn", this, this);
//2.创建请求队列
requestqueue queue = volley.newrequestqueue(this);
queue.add(request);
}
@override
public void onresponse(string s) {
//支付四部曲第2步:解析服务器返回的“支付串码”(银联:交易流水号,一串数字)
string trun = s;
showlog(s);
}
### 08.银联支付后2步
> 先集成银联sdk:开发平台集成思想,李白“飞流直下三千尺”(从上往下开官方demo,asserts、libs、清单文件<权限+activity>)
> 调用银联支付sdk的,传入“支付串码”
string mode = "01";
uppayassistex.startpaybyjar(mainactivity.this, payactivity.class, null, null,trun, mode);
> 处理支付结果
protected void onactivityresult(int requestcode, int resultcode, intent data) {
super.onactivityresult(requestcode, resultcode, data);
string msg = null;
/** 支付控件返回字符串:success、fail、cancel 分别代表支付成功,支付失败,支付取消*/
string str = data.getextras().getstring("pay_result");
if (str.equalsignorecase("success")) {
msg = "支付成功104!";
} else if (str.equalsignorecase("fail")) {
msg = "支付失败104!";
} else if (str.equalsignorecase("cancel")) {
msg = "用户取消了支付104";
}
toast.maketext(this, msg, toast.length_short).show();
}
### 09.银联支付-异步通知同步返回
> 同步返回:客户端直接获取支付结果
> 异步通知:必须有银联服务器通知商户服务器,千万不能让客户端通知服务器,因为客户端通知不可靠
> 异步通知过程中商户服务器断网怎么办:订单发起30分钟后没有收到支付结果,主动向银联请求
### 10.支付宝支付sdk
> 支付宝支付sdkdemo:[https://docs.open.alipay.com/54/104509](https://docs.open.alipay.com/54/104509)
### 11.秘钥对配置1
> 默认运行sdkdemo不能调起支付,因为没有秘钥信息、商家账号
partner:商家pid
seller:商家收款账号
> 参考资料/pdf:配置秘钥对
### 12.秘钥对配置2
rsa_private:商家私钥
rsa_public:支付宝公钥
> 参考资料/pdf:配置秘钥对
> 2中方式:openssl命令生成,一键生成
### 13.支付宝支付-公钥互换
> 公钥互换入口:[https://openhome.alipay.com/platform/keymanage.htm](https://openhome.alipay.com/platform/keymanage.htm)
### 14.支付宝支付服务器签名
> 为了保证安全,支付宝要求生成签名信息让商家服务器操作
### 15.支付宝支付前2步
> 提交参数到服务器
stringrequest request = new stringrequest("https://120.77.241.119/tmall/pay?goodid=111&count=1&price=1"
, this, this);
requestqueue queue = volley.newrequestqueue(mcontext);
queue.add(request);
> 解析服务器返回的支付串码
// 2.解析服务器返回的支付串码
// string -> bean:gson、fastjson
alipayinfo alipayinfo = json.parseobject(s, alipayinfo.class);
toast.maketext(mcontext, ""+alipayinfo, toast.length_short).show();
### 16.支付宝支付集成sdk
> 导入一个jar包:支付宝sdk
> 配置清单文件
权限
activity
android:name="com.alipay.sdk.app.h5payactivity"
android:configchanges="orientation|keyboardhidden|navigation|screensize"
android:exported="false"
android:screenorientation="behind"
android:windowsoftinputmode="adjustresize|statehidden" >
### 17.支付宝支付-后2步
> 开发者文档:[https://docs.open.alipay.com/204/105296/](https://docs.open.alipay.com/204/105296/)
> 调用支付功能
paytask task = new paytask(mainactivity.this);
string payinfo = alipayinfo.getpayinfo();//支付串码
//参数1:支付串码,参数2:是否显示横条加载进度
string payresult = task.pay(payinfo, false);//同步返回支付结果
> 处理支付结果
payresult payresult = new payresult((string) msg.obj);
/**
* 同步返回的结果必须放置到服务端进行验证(验证的规则请看https://doc.open.alipay.com/doc2/
* detail.htm?spm=0.0.0.0.xdvau6&treeid=59&articleid=103665&
* doctype=1) 建议商户依赖异步通知
*/
string resultinfo = payresult.getresult();// 同步返回需要验证的信息
string resultstatus = payresult.getresultstatus();
// 判断resultstatus 为“9000”则代表支付成功,具体状态码代表含义可参考接口文档
if (textutils.equals(resultstatus, "9000")) {
showtoast("支付成功");
toast.maketext(mcontext, ""+(string)(msg.obj), toast.length_short).show();
} else {
// 判断resultstatus 为非"9000"则代表可能支付失败
// "8000"代表支付结果因为支付渠道原因或者系统原因还在等待支付结果确认,最终交易是否成功以服务端异步通知为准(小概率状态)
if (textutils.equals(resultstatus, "8000")) {
showtoast("支付结果确认中");
} else {
// 其他值就可以判断为支付失败,包括用户主动取消支付,或者系统返回的错误
showtoast("支付失败");
}
}
### 18.支付宝支付-同步返回异步通知
> 同步返回:客户端直接获取支付结果
> 异步通知:[支付宝服务器通知商户服务器](https://doc.open.alipay.com/doc2/detail.htm?spm=a219a.7629140.0.0.kund0s&treeid=59&articleid=103666&doctype=1#s1)
> 通知过程中商户服务器停止:25小时以内完成8次通知(通知的间隔频率一般是:4m,10m,10m,1h,2h,6h,15h);
程序执行完成后,该页面不能执行页面跳转。如果执行页面跳转,支付宝会收不到success字符,会被支付宝服务器判定为该页面程序运行出现异常,而重发处理结果通知;
### 19.微信支付sdk
> 微信支付:只要掌握支付、微信分享、微信登录,都一样
> 注意注意注意:微信支付demo运行(只能运行资料as demo)
> 安全码处理:包名+应用名+keystore,为了唯一确定一个应用程序
> 想要运行官方demo:必须使用它提供的debug.keystore,替换c:\users\youliang.ji\.android目录
> 如果运行了没有替换debug.keystore不能调起支付,想要调起支付必须卸载微信(或者清空所有缓存),因为你微信缓存上一次的keystore
### 20.微信支付-获取appid
> 创建应用,提交keystore md5
> 微信限制创建应用个数:10个
> 必须通过审核才能调用、而且必须是商家账号
### 21.微信支付-前2步
> 1.提交参数给服务器
stringrequest request = new stringrequest("https://wxpay.wxutil.com/pub_v2/app/app_pay.php", this, this);
requestqueue queue = volley.newrequestqueue(this);
queue.add(request);
> 2.解析服务器返回的“支付串码”
s = s.replace("package","packagevalue");
//2.解析获取服务器返回的支付串码
wechatpayinfo = json.parseobject(s, wechatpayinfo.class);
### 22.微信支付-集成sdk
> 导入jar包
> 配置清单文件:权限
> 配置清单文件:配置activity(wxpayentryactivity),包名和类名不能变
### 23.微信支付-后2步
> 1.调用微信支付sdk
private void callwechatpay() {
payreq req = new payreq();
req.appid = wechatpayinfo.getappid();
req.partnerid = wechatpayinfo.getpartnerid();
req.prepayid = wechatpayinfo.getprepayid();//微信支付核心参数:预支付订单号
req.noncestr = wechatpayinfo.getnoncestr();
req.timestamp = wechatpayinfo.gettimestamp()+"";
req.packagevalue = wechatpayinfo.getpackagevalue();
req.sign = wechatpayinfo.getsign();
// 在支付之前,如果应用没有注册到微信,应该先调用iwxmsg.registerapp将应用注册到微信
//3.调用微信支付sdk支付方法
api.sendreq(req);
}
> 2.处理支付结果:在wxpayentryactivity类onresp处理支付结果
public void onresp(baseresp resp) {
if (resp.gettype() == constantsapi.command_pay_by_wx) {
alertdialog.builder builder = new alertdialog.builder(this);
builder.settitle("微信支付结果104");
builder.setmessage("支付状态码:"+string.valueof(resp.errcode));
builder.show();
}
}
### 24.微信支付-同步返回异步通知
> 同步返回:客户端支付直接获取支付结果wxpayentryactivity类onresp方法
> 异步通知:微信服务器通知账号服务器,并且商户需要响应结果
> 通知过程中如果断网怎么办:商户需要响应结果
### 25.混合开发-初始化webview
> 开启js和android通信开关
> 设置2个webclient
### 26.混合开发-android调用js
> android代码
jsonobject json = new jsonobject();
json.put("name", "android");
json.put("msg", "你好,我是安卓,想加你为蚝友!");
//核心代码
mwebview.loadurl("javascript:showmessage("+json.tostring()+")");
> js代码
function showmessage(json) {
//弱类型
alert(json.stringify(json));
}
### 27.混合开发-js调用android
> android代码
mwebview.addjavascriptinterface(new javascriptmethods(this), "jsinterface");
public class javascriptmethods {
private context mcontext;
public javascriptmethods(context mcontext) {
this.mcontext = mcontext;
}
@javascriptinterface //android17以上,如果不加上该注解,js无法调用android方法(js反射调用android,为了安全)
public void showtoast(string json){
toast.maketext(mcontext, ""+json, toast.length_short).show();
}
}
> js代码
$("#btn1").on("click", function () {
console.log("点击了按钮");
//window.location.href = "https://m.ctrip.com/html5/";
//调用android方法
//window.android对象别名.方法名(参数)
var json = {"msg":"不想加你蚝友!"}
window.jsinterface.showtoast(json.stringify(json));
});
### 28.混合开发-js回调式调用android
> callback:h5显示数据,但是数据必须有android请求网络获取,js跨域问题(通过callback可以解决)
> 需求:h5显示酒店数据,来源服务器;通过android请求,返回给js
### 一.银联支付文档
* 1.[银联支付sdk下载](https://open.unionpay.com/ajweb/help/file/techfile?productid=3)
* 2.开发者平台:[https://open.unionpay.com/ajweb/help/file](https://open.unionpay.com/ajweb/help/file "https://open.unionpay.com/ajweb/help/file")
* 3.异步通知说明:
* 图片所在路径:**资料\第三方支付平台\银联支付\手机控件支付产品技术开发包3.1.0\手机控件支付产品入网材料\ppt**
*
![](img/unionpay_notify.png)
* 3.模拟器可能会遇到的错误
![](img/uuperror.png)
* 银联支付测试接口:[https://101.231.204.84:8091/sim/getacptn](https://101.231.204.84:8091/sim/getacptn "https://101.231.204.84:8091/sim/getacptn")
* 3 支付结果处理
onactivityresult方法中
* 4 支付参数
交易流水号,是一串数字,数字如何区别是哪个商家的订单?银行如何将该笔交易转账到指定商家?
请看下面的图:交易流水号是银联生成的,所有银行当然知道是谁的
* 5 支付流程图
![](img/unionpay_flow_chart.png)
----------
### 二.支付宝支付文档
* 1 开发者平台:[https://doc.open.alipay.com/doc2/alipaydocindex.htm](https://doc.open.alipay.com/doc2/alipaydocindex.htm "https://doc.open.alipay.com/doc2/alipaydocindex.htm")
* 2 异步通知说明:[https://doc.open.alipay.com/doc2/detail.htm?spm=a219a.7629140.0.0.kund0s&treeid=59&articleid=103666&doctype=1#s1](https://doc.open.alipay.com/doc2/detail.htm?spm=a219a.7629140.0.0.kund0s&treeid=59&articleid=103666&doctype=1#s1 "支付宝异步通知支付结果")
* 3 异步通知图文:
![](img/alipay_notify.png)
* 4.[支付宝支付开发者登录入口](https://auth.alipay.com/login/ant_sso_index.htm?goto=https%3a%2f%2fopenhome.alipay.com%2fplatform%2fmanageapp.htm)
* 5.[sdk下载](https://doc.open.alipay.com/doc2/detail.htm?treeid=54&articleid=104509&doctype=1)
* 6.[支付宝支付状态码](https://doc.open.alipay.com/docs/doc.htm?spm=a219a.7629140.0.0.s07wkc&treeid=193&articleid=105302&doctype=1#s2)
* 7.[支付宝参数说明](https://doc.open.alipay.com/docs/doc.htm?spm=a219a.7629140.0.0.ianz0u&treeid=59&articleid=103663&doctype=1)
----------
### 三.微信支付文档
* 运行demo报错:安全码策略:包名+应用名称+keystore,任何一个参数变化,支付失败
![](img/wechat_pay_error.gif)
> 解决方案:如果第一次没有使用微信demo自己的keystore,会报错;改成微信的keystore还是报错,可以清理微信客户端缓冲(注意备份自己的聊天数据),在重新支付就没问题
* **1.微信支付开发者平台**:[https://pay.weixin.qq.com/wiki/doc/api/index.html](https://pay.weixin.qq.com/wiki/doc/api/index.html "https://pay.weixin.qq.com/wiki/doc/api/index.html")
* **2.异步通知文档**:[https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_3](https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_3 "https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_3")
* **3.微信支付很特殊**:keystore签名+包名绑定+应用名称,安全码策略,为了给大家演示微信支付,上课的时候老师使用了微信demo的包名、应用名称、keystore。到公司肯定使用公司的keystore+包名+应用名称(如何创建提交应用:请看微信支付创建应用视频)
* **4.微信支付测试接口**:[https://wxpay.weixin.qq.com/pub_v2/app/app_pay.php?plat=android](https://wxpay.weixin.qq.com/pub_v2/app/app_pay.php?plat=android "https://wxpay.weixin.qq.com/pub_v2/app/app_pay.php?plat=android")
* **5.微信开发者平台登录入口**:[https://open.weixin.qq.com/](https://open.weixin.qq.com/ "https://open.weixin.qq.com/")
* **6.微信支付签名工具**:[https://open.weixin.qq.com/zh_cn/htmledition/res/dev/download/sdk/gen_signature_android.apk](https://open.weixin.qq.com/zh_cn/htmledition/res/dev/download/sdk/gen_signature_android.apk)
* 7.[微信支付参数生成规则](https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_7&index=3)
上一篇: Oracle的常用SQL语句(建议收藏)
下一篇: 葛饰北斋是谁?日本画家葛饰北斋生平简介