1.扫码支付流程
微信扫码支付,流程很简单,就是将你要付款的一些信息放到集合里面,然后用微信SDK来生成对
应的URL,再根据URL生成对应的二维码,扫码支付后,微信后台会有回调,异步通知(需要在服务器打
印日志查看).
2.配置
[SDK调用示例](https://pay.weixin.qq.com/wiki/doc/api/download/WxPayAPI_JAVA.zip)
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>适应版本</version>
</dependency>
新建一个配置类实现WXPayConfig接口,里面会配置AppID,MchID,Key,这些需要在公司的商户平台上获取.
private byte[] certData;
/*public WeChatConf() throws Exception {
String certPath = "/apiclient_cert.p12";
//String certPath = "退款需要存的证书路径";
File file = new File(certPath);
InputStream certStream = new FileInputStream(file);
this.certData = new byte[(int) file.length()];
certStream.read(this.certData);
certStream.close();
}*/
public String getAppID() {
return AppId;
}
public String getMchID() {
return MchID;
}
public String getKey() {
return Key;
}
public InputStream getCertStream() {
ByteArrayInputStream certBis = new ByteArrayInputStream(this.certData);
return certBis;
}
public int getHttpConnectTimeoutMs() {
return 8000;
}
public int getHttpReadTimeoutMs() {
return 10000;
}
3.开始实现功能
WeChatConf weChatConf = null;
try {
weChatConf = new WeChatConf();
} catch (Exception e) {
e.printStackTrace();
}
//账号信息
String appId = weChatConf.getAppID();
//商业号
String mch_id = weChatConf.getMchID();
//支付秘钥
String key = weChatConf.getKey();
Map<String, String> data = new HashMap<String, String>();
data.put("appid", 公众账号ID);
data.put("mch_id", 商业号);
data.put("nonce_str", 随机字符串);
data.put("body", 商品描述);
data.put("out_trade_no", 商户订单号,不可重复);
data.put("fee_type", "CNY");//标价币种(默认人民币)
data.put("total_fee", totalFee+"");//标价金额,单位:分
data.put("spbill_create_ip", 终端IP);
data.put("notify_url", 通知地址,必须是外网能访问的地址);
data.put("trade_type", "NATIVE"); // 此处指定为扫码支付
String sign = null;
try { //WXPayUtil在上方链接下载的SDK中可以找到
sign = WXPayUtil.generateSignature(data,key,WXPayConstants.SignType.MD5);
} catch (Exception e) {
e.printStackTrace();
}
data.put("sign", sign); //签名
WXPay wxpay = new WXPay(weChatConf);
Map<String, String> mss = null;
try {
mss = wxpay.unifiedOrder(data);
} catch (Exception e) {
e.printStackTrace();
}
String codeUrl = mss.get("code_url");//此处是微信微信返回的需生成二维码的URL
写到这里,当时出了问题,根据官方提供的技术,是后台用个方法生成二维码然后用流输出到前
台,因为是支付图片,是不能保存到本地的,可是我当时做的时候,只有当浏览器为兼容模式的情况下
才会显示二维码,极速模式下不显示,搞的很头大.因为支付宝支付的话就是直接返回一个URL就可以
了,二维码生成的问题交给阿里后台解决,所以我也换了一个思路,直接甩给前台返回一个URL,二维码
就在前台生成.
到这里的话,其实支付已经完成一大半了,不过我感觉支付宝和微信就差在回调这个地方了.支付
宝是直接给你返回一个状态,结果微信是需要写个回调接口,还得自己去查看回调结果,然后再给微信
返回接受情况.
下面我们来看一下回调接口,微信的回调数据需要用流来接收
String returnPage = "";
String notifyData = "";
InputStream is = request.getInputStream();
StringBuffer sb = new StringBuffer();
String s = null;
BufferedReader in = new BufferedReader(new InputStreamReader(is, "UTF-8"));
while ((s = in.readLine()) != null) {
sb.append(s);
}
in.close();
is.close();
notifyData = sb.toString();
Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyData);// 转换成map
if (wxpay.isPayResultNotifySignatureValid(notifyMap)) {
// 签名正确
//通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
resXml = "<xml>" + "<return_codSUCCESS]]></return_code>"
+ "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
} else {
// 签名错误,如果数据里没有sign字段,也认为是签名错误
resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
+ "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
}
BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
out.write(resXml.getBytes());
out.flush();
out.close();
写到这里,整体的二维码支付就结束了.另外,二维码在前台生成的话,是需要再写一个
轮询接口的,检测订单状态是否付款,然后根据返回结果,在前台跳转支付成功/支付失败.
刚刚工作不久,有写的不好的地方接受点评,给大佬们留个问题,前台生成二维码支付会不会有安
全问题,需要怎么解决?