Native⽀付
Native⽀付对接(扫码)
由于有业务需求对接了和paypal⽀付,这边做个记录
⼀、⽀付⽅式
这边有个坑,h5⽀付和Native⽀付都是外部使⽤的⽀付⽅式,但是h5⽀付适⽤于移动端,因为⽀付时是从外部唤醒本地移动端的app进⾏⽀付;
⽽Native⽀付则是在pc端⽣成订单后,⽤户使⽤移动端的app扫码完成⽀付
付款码⽀付:需要⽤户有扫码.如:肯德基,麦当劳的⽀付
JSAPI⽀付: 主要服务于内部调⽤的⽀付接⼝
Native⽀付:扫码⽀付
h5⽀付:⼿机浏览器调⽤的⽀付
⼆、⽀付流程介绍
⽤户:客户
前端:ui界⾯,客户端
后端:java写的服务端
系统:包括⽣产订单的接⼝等
流程:
⽤户点击前端的⽀付按钮
前端将对应的订单信息发送给后端
后端预处理订单的信息(如在数据库中⽣成对应的记录),然后调⽤⽀付系统⽣成订单的接⼝
⽀付系统返回对应订单的⽀付地址给后端
后端将该订单地址返还给前端,前端调⽤⼯具⽣成⼆维码
⽤户打开⼿机app扫码完成⽀付(由于和我们业务并没有直接的相关性,这个过程没有直接在上图中表现出来)
系统异步(有延时)收到⽀付成功的回调,回调函数中应该包括对于验证订单的有效性(如果被⼈攻破就⿇烦了),存储数据库(确认订单已结算),回复系统(否则会在⼀天之内多次发送回调
信息)等步骤
后端可以通知前端订单完成,以便后续的操作(具体的做法可以是从订单⽣成之后,前端可以以⼀定的时间间隔询问订单的状态)
注:其它⽀付⼿段的流程应该也是⼤致相同的
三、准备⼯作
⾸先必然是下载sdk(software development kit).值的注意的⼀点是,对⽐于⽹上的许多旧的博客,可以发现的api有了极⼤的改进,我们只要调⽤少许的接⼝即可完成开发.同时api的命名⽬前也是⽐较统⼀的
徐凤年申请⼀个商机号
注:商家号的申请是需要相关的营业执照的
上商户号中开通Native⽀付的服务
准备调⽤订单⽀付接⼝相关的(这⾥只展⽰⼀下必填项)
字段名变量名描述
公众账号ID appid⽀付分配的公众账号ID
商户号mch_id⽀付分配的商户号
随机字符串nonce_str由内置的⽣成
签名sign由内置的⽣成
高考体检检查什么商品描述body商品的简单描述
商品订单号out_trade_no可以直接⽤订单id
标价⾦额total_fee单位为分(CNY)
终端IP spbill_creat
通知地址notify_url异步回调的地址(回调不能在本地测试)
交易类型trade_type NATIVE -Native⽀付
商品ID product_id商品id,Native必填
密匙key商家⾃⾏设置的密匙
在后台获得appid,mch_id,设置key
out_trade_no必须⼤于10,不能重复
total_fee不能有⼩数点(正常情况也不应该有⼩数点)
nonce_str变量⽤于提⾼⽣成的sign不确定
sign的算法是先将所有的参数进⾏排序,然后按key=value的形式拼接为字符串,最后加上key.最后,对拼接后字符串进⾏加密,加密⽅式⼀种是⽤MD5,⼀种使⽤HMAC-SHA256.具体的过程可以查看sdk原码,实际使⽤只要传⼊参数map给相关的api即可,但是了解⼀下有助于调试,另外附加⼀个官⽅的
key是保证整个⽀付过程加密以及回调地址不被攻破的关键!
可以⽤额外的attach附加参数,如订单id
四、开发⼯作
这⾥主要说明⼀下后端接⼝的调⽤
调⽤接⼝⽣成订单
public String getWxQrCode(HashMap<String,Object> paraMap) throws Exception {
/*数据库操作*/
Integer maxId = MaxUserId();
Integer id = maxId==null?1:maxId+1;
paraMap.put("user_id",id);
userMapper.addUser(paraMap);
/*获得code_url*/
Map<String, String> map = new HashMap<>();
map.put("appid",AppID());
map.put("mch_id",MchID());
map.put("body",Body());
map.put("out_trade_no",id.toString());
map.put("total_fee",("order_amount").toString());
map.put("spbill_create_ip",("ip").toString());
map.put("notify_url",NotifyUrl());
map.put("trade_type",TradeType());
map.put("attach",id.toString());
//Native必传
map.put("product_id",("order_productid").toString());
/
/获得sign
WXPay wxPay = new WXPay(wxPayConfigBean);
Map<String, String> backMap = wxPay.unifiedOrder(map);
HashMap<String, Object> resMap = new HashMap<>();
resMap.put("url",("code_url"));
resMap.put("id",id);
JsonString(resMap);
}
回调
public void wxNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
//拿到回调信息(以字节流的⽅式)
InputStream inputStream = InputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(inputStream,"UTF-8"));
//String是字符串变量,StringBuffer是字符串变量
StringBuffer sb = new StringBuffer();
七夕到底是不是情人节//将字节流转换为字符串
String line;
while ((line = in.readLine()) != null){
//每次⽤line读取⼀⾏的字节流,如果这⼀⾏不为空就扩展到sb上
sb.append(line);
池方圆图片}
System.out.println("*****************************sb**************************");
System.out.println(sb);
System.out.println("*****************************sb**************************");
//关闭
in.close();
inputStream.close();
String strXml = sb.toString();
Map<String, String> toMap = lToMap(strXml);
System.out.println(toMap);
//获取业务信息
String outTradeNo = ("out_trade_no");
String totalFee = ("total_fee");
String appId = ("appId");
String mchId = ("mch_id");
String resultCode = ("result_code");
String attach = ("attach"); //附加数据
//该对象⽤于通知
PrintWriter writer = Writer();
//验签
String res = null;
Map<String,String> paraMap = lToMap(strXml);
boolean signatureValid = WXPayUtil.isSignatureValid(paraMap, Key(), WXPayConstants.SignType.HMACSHA256); //注:注意返回时有nonce_str if (signatureValid){
System.out.println("验证成功~");
if ("SUCCESS".("result_code"))){
System.out.println("返回的是SUCCESS");
/*⾃⼰的业务逻辑*/
}
//返回值——仍然有问题,不断刷回复
String noticeStr = setXML("SUCCESS","");
writer.write(noticeStr);
writer.flush(); //情况缓存区,并完成⽂件写⼊操作
}
}else{空调不制热是什么原因造成的
痞幼视频3分25秒黑料System.out.println("验证失败");
String noticeStr = setXML("FATL","");
writer.write(noticeStr);
writer.flush();
};
}
private static String setXML(String return_code, String return_msg) {
return "<xml><return_code><![CDATA[" + return_code + "]]></return_code><return_msg><![CDATA[" + return_msg + "]]></return_msg></xml>";
}
注:
有时候回调好像没有正确地返还个⽀付系统,对java的输⼊输出不太了解,⿇烦有⼤佬知道问题的请留⾔
在最开始尝试对接⽀付时查阅了较多的博客,代码,在这⾥表⽰感谢.但因为实在太过庞杂,就不⼀⼀列出了.
发布评论