微信:微信扫码支付、调用统一下单接口、网站支付 + springmvc
来源:互联网 发布:p57数据是bin还是dat 编辑:程序博客网 时间:2024/05/16 06:53
一、场景:公司需要在网站上进行微信支付。
二、API:使用微信开放平台的接入微信支付
-扫码支付。微信支付开发者平台链接三、分析:
- 接入扫码支付(包含PC网站支付)包含三个阶段,问这里只讲使用,也就是第2阶段的《启动设计和开发》。
- 点击查看开发者文档(扫码支付)后,这里感觉微信的文档没有支付宝好理解(稍微吐槽下~~~),不过我们忽略一切,直接进入模式二:模式二最简单直接,不需要在商户后台进行配置,推荐大家使用,微信也说流程更为简单,我这里也讲的是模式二,模式一大家有兴趣可以自行研究下。
- 如上图,总流程有14步,主要流程是生成订单、调统一下单API、将返回的支付交易链接生成二维码展示;我这边主要就是将这三步结合springmvc后,成功生儿二维码之后,用户就可以扫码支付了。后面的回调跟跟我的另一篇博文基本类似,大家借鉴下就行了:支付宝:web页面扫码支付、网站支付、支付宝即时到账 + springmvc
四、实现:
- 准备:根据统一下单接口API我先定义了三个对象:UnifiedOrderRequest(统一下单请求参数(必填))、UnifiedOrderRequestExt(统一下单请求参数(非必填))、UnifiedOrderRespose(统一下单返回参数);具体如下代码,get、set方法可自行生产,太占篇幅。
UnifiedOrderRequest.class-
-
-
-
-
- public class UnifiedOrderRequest {
- private String appid;
- private String mch_id;
- private String nonce_str;
- private String sign;
- private String body;
- private String out_trade_no; <span style="white-space:pre"> </span>
- private String total_fee;
- private String spbill_create_ip; <span style="white-space:pre"> </span>
- private String notify_url;
- private String trade_type;
- }
UnifiedOrderRequestExt.class-
-
-
-
-
- public class UnifiedOrderRequestExt extends UnifiedOrderRequest{
-
- private String device_info;
- private String detail;
- private String attach;
- private String fee_type;
- private String time_start;
- private String time_expire;
- private String goods_tag;
- private String product_id;
- private String limit_pay;
- private String openid;
- }
UnifiedOrderRespose.class-
-
-
-
-
- public class UnifiedOrderRespose {
- private String return_code;
- private String return_msg;
- private String appid;
- private String mch_id;
- private String device_info;
- private String nonce_str;
- private String sign;
- private String result_code;
- private String err_code;
- private String err_code_des; <span style="white-space:pre"> </span>
- private String trade_type;
- private String prepay_id;
- private String code_url;
- }
- Controller主入口:
-
-
-
- @RequestMapping("createQRCode")
- public void createQRCode(String orderId, HttpServletResponse response) {
-
-
- String orderInfo = createOrderInfo(orderId);
-
- String code_url = httpOrder(orderInfo);
-
-
- try {
- int width = 200;
- int height = 200;
- String format = "png";
- Hashtable hints = new Hashtable();
- hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
- BitMatrix bitMatrix = new MultiFormatWriter().encode(code_url, BarcodeFormat.QR_CODE, width, height, hints);
- OutputStream out = null;
- out = response.getOutputStream();
- MatrixToImageWriter.writeToStream(bitMatrix, format, out);
- out.flush();
- out.close();
- } catch (Exception e) {
- }
-
- }
- 生成订单:分两部分:一部分是业务需求的订单信息,就是发起支付前的订单信息,业务系统自行创建存储;另一部分是满足统一下单API要求的订单信息(也是我们这里要讲的)。“xxxxxx”:是你需要自己填写的对应信息:
-
-
-
-
-
- private String createOrderInfo(String orderId) {
-
- UnifiedOrderRequest unifiedOrderRequest = new UnifiedOrderRequest();
- unifiedOrderRequest.setAppid("xxxxxxxxxxxxx");
- unifiedOrderRequest.setMch_id("xxxxxxxxx");
- unifiedOrderRequest.setNonce_str(StringUtil.makeUUID());
- unifiedOrderRequest.setBody("xxxxxx");
- unifiedOrderRequest.setOut_trade_no(orderId);
- unifiedOrderRequest.setTotal_fee("x");
- unifiedOrderRequest.setSpbill_create_ip("xxxxxxxxxxxxx");
- unifiedOrderRequest.setNotify_url("xxxxxxxxxxxxxx");
- unifiedOrderRequest.setTrade_type("NATIVE");
- unifiedOrderRequest.setSign(createSign(unifiedOrderRequest));
-
- XStream xStream = new XStream(new XppDriver(new XmlFriendlyNameCoder("_-", "_")));
- xStream.alias("xml", UnifiedOrderRequest.class);
- return xStream.toXML(unifiedOrderRequest);
- }
- 调统一下单API:根据要求将生成订单中返回的xml向微信给定的统一下单URL地址:https://api.mch.weixin.qq.com/pay/unifiedorder,发送请求,成功并获得二维码。
-
-
-
-
-
- private String httpOrder(String orderInfo) {
- String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
- try {
- HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
-
- conn.setRequestMethod("POST");
- conn.setDoOutput(true);
-
- BufferedOutputStream buffOutStr = new BufferedOutputStream(conn.getOutputStream());
- buffOutStr.write(orderInfo.getBytes());
- buffOutStr.flush();
- buffOutStr.close();
-
-
- BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
-
- String line = null;
- StringBuffer sb = new StringBuffer();
- while((line = reader.readLine())!= null){
- sb.append(line);
- }
-
- XStream xStream = new XStream(new XppDriver(new XmlFriendlyNameCoder("_-", "_")));
-
- xStream.alias("xml", UnifiedOrderRespose.class);
- UnifiedOrderRespose unifiedOrderRespose = (UnifiedOrderRespose) xStream.fromXML(sb.toString());
-
-
-
- if(null!=unifiedOrderRespose
- && "SUCCESS".equals(unifiedOrderRespose.getReturn_code())
- && "SUCCESS".equals(unifiedOrderRespose.getResult_code())){
- return unifiedOrderRespose.getCode_url();
- }else{
- return null;
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
- 将返回的支付交易链接生成二维码展示:没有异常的情况下,在页面中使用<img>标签接收就行。实际使用时,结合前端和业务的需求放置二维码。可以在扫码支付/案例及规范中找到部分素材和界面规范来设计微信风格的支付页面。
- <img src="${ctx}/wxPay/createQRCode?orderId=1111" width="174px">
- 用户可以通过维系客户端进行扫码支付。支付完成后回调我们notify_url设置的url,通过成功的回调来更改业务系统中的订单状态或者一些业务需求。这里回调没有写出可以参考支付宝:web页面扫码支付、网站支付、支付宝即时到账 + springmvc中的回调。
五、说明:
- 二维码可以查看zxing实现二维码生成和解析;微信这边也提供了二维码的学习,大家有兴趣可以看看:http://www.thonky.com/qr-code-tutorial/ 和http://coolshell.cn/articles/10590.html
- 随机字符串:微信对随机字符串的要求是不超过32位。我这边是这样生成的,用时间戳。
-
-
-
-
- public static synchronized String makeUUID() {
- Date date = new Date();
- StringBuffer s = new StringBuffer(DateUtil.formatYmdhmsm(date));
- return s.append((new Random().nextInt(900) + 100)).toString();
- }
- 使用Xstream时,由于微信定义的变量名大部分使用了“_”,但是在Xstream中它是关键字,所以会自动变为“__”,引起报错。详情请看:XStream异常:对象转为XML时,会把"_"转成"__";报错:(Lcom/thoughtworks/xstream/io/naming/NameCoder;)V
- 获取二维码链接时,只有在return_code 和result_code都为SUCCESS的时候有返回;这里我就简单的满足时返回,不满足返回null,您写的时候需要结合业务考虑下,是否需要增加判断,从而满足不同的业务场景。统一下单API
- 签名在上面一直没有详细说明,首先查看微信的安全规范中签名算法。key值,需要自己填写
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- private String createSign(UnifiedOrderRequest unifiedOrderRequest) {
-
- SortedMap<String, String> packageParams = new TreeMap<String, String>();
- packageParams.put("appid", unifiedOrderRequest.getAppid());
- packageParams.put("body", unifiedOrderRequest.getBody());
- packageParams.put("mch_id", unifiedOrderRequest.getMch_id());
- packageParams.put("nonce_str", unifiedOrderRequest.getNonce_str());
- packageParams.put("notify_url", unifiedOrderRequest.getNotify_url());
- packageParams.put("out_trade_no", unifiedOrderRequest.getOut_trade_no());
- packageParams.put("spbill_create_ip", unifiedOrderRequest.getSpbill_create_ip());
- packageParams.put("trade_type", unifiedOrderRequest.getTrade_type());
- packageParams.put("total_fee", unifiedOrderRequest.getTotal_fee());
-
- StringBuffer sb = new StringBuffer();
- Set es = packageParams.entrySet();
- Iterator it = es.iterator();
- while (it.hasNext()) {
- Map.Entry entry = (Map.Entry) it.next();
- String k = (String) entry.getKey();
- String v = (String) entry.getValue();
-
- if (null != v && !"".equals(v) && !"sign".equals(k)
- && !"key".equals(k)) {
- sb.append(k + "=" + v + "&");
- }
- }
-
- sb.append("key=" +"xxxxxxxxxxxxxxxxx");
- String sign = MD5Util.MD5Encode(sb.toString(), "utf-8")
- .toUpperCase();
- return sign;
- }
相关文章:支付宝:web页面扫码支付、网站支付、支付宝即时到账 + springmvc
0 0