微信:微信扫码支付、调用统一下单接口、网站支付 + springmvc
来源:互联网 发布:广西银河交易软件 编辑:程序博客网 时间:2024/06/05 09:22
微信:微信扫码支付、调用统一下单接口、网站支付 + springmvc
标签: 微信支付微信扫码支付扫码支付
一、场景:公司需要在网站上进行微信支付。
二、API:使用微信开放平台的接入微信支付
-扫码支付。微信支付开发者平台链接
三、分析:
1. 接入扫码支付(包含PC网站支付)包含三个阶段,问这里只讲使用,也就是第2阶段的《启动设计和开发》。
2. 点 击查看开发者文档(扫码支付)后,这里感觉微信的文档没有支付宝好理解(稍微吐槽下~~~),不过我们忽略一切,直接进入模式二:模式二最简单直接,不需 要在商户后台进行配置,推荐大家使用,微信也说流程更为简单,我这里也讲的是模式二,模式一大家有兴趣可以自行研究下。
3. 如上图,总流程有14步,主要流程是生成订单、调统一下单API、将返回的支付交易链接生成二维码展示;我这边主要就是将这三步结合springmvc后,成功生儿二维码之后,用户就可以扫码支付了。后面的回调跟跟我的另一篇博文基本类似,大家借鉴下就行了:支付宝:web页面扫码支付、网站支付、支付宝即时到账 + springmvc
四、实现:
1. 准备:根据统一下单接口API我 先定义了三个对象:UnifiedOrderRequest(统一下单请求参数(必填))、UnifiedOrderRequestExt(统一下单请求 参数(非必填))、UnifiedOrderRespose(统一下单返回参数);具体如下代码,get、set方法可自行生产,太占篇幅。
UnifiedOrderRequest.class
[javascript] view plain copy
1. /**
2. * 统一下单请求参数(必填)
3. * @author Y
4. *
5. */
6. public class UnifiedOrderRequest {
7. private String appid; //公众账号ID
8. private String mch_id; //商户号
9. private String nonce_str; //随机字符串
10. private String sign; //签名
11. private String body; //商品描述
12. private String out_trade_no; <span style="white-space:pre"> </span>//商户订单号
13. private String total_fee; //总金额
14. private String spbill_create_ip; <span style="white-space:pre"> </span>//终端IP
15. private String notify_url; //通知地址
16. private String trade_type; //交易类型
17. }
UnifiedOrderRequestExt.class
[javascript] view plain copy
1. /**
2. * 统一下单请求参数(非必填)
3. * @author Y
4. *
5. */
6. public class UnifiedOrderRequestExt extends UnifiedOrderRequest{
7.
8. private String device_info; //设备号
9. private String detail; //商品详情
10. private String attach; //附加数据
11. private String fee_type; //货币类型
12. private String time_start; //交易起始时间
13. private String time_expire; //交易结束时间
14. private String goods_tag; //商品标记
15. private String product_id; //商品ID
16. private String limit_pay; //指定支付方式
17. private String openid; //用户标识
18. }
UnifiedOrderRespose.class
[javascript] view plain copy
1. /**
2. * 统一下单返回参数
3. * @author Y
4. *
5. */
6. public class UnifiedOrderRespose {
7. private String return_code; //返回状态码
8. private String return_msg; //返回信息
9. private String appid; //公众账号ID
10. private String mch_id; //商户号
11. private String device_info; //设备号
12. private String nonce_str; //随机字符串
13. private String sign; //签名
14. private String result_code; //业务结果
15. private String err_code; //错误代码
16. private String err_code_des; <span style="white-space:pre"> </span>//错误代码描述
17. private String trade_type; //交易类型
18. private String prepay_id; //预支付交易会话标识
19. private String code_url; //二维码链接
20. }
1. Controller主入口:
[javascript] view plain copy
1. /**
2. * 创建二维码
3. */
4. @RequestMapping("createQRCode")
5. public void createQRCode(String orderId, HttpServletResponse response) {
6.
7. //生成订单
8. String orderInfo = createOrderInfo(orderId);
9. //调统一下单API
10. String code_url = httpOrder(orderInfo);
11. //将返回预支付交易链接(code_url)生成二维码图片
12. //这里使用的是zxing <span style="color:#ff0000;"><strong>说明1(见文末)</strong></span>
13. try {
14. int width = 200;
15. int height = 200;
16. String format = "png";
17. Hashtable hints = new Hashtable();
18. hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
19. BitMatrix bitMatrix = new MultiFormatWriter().encode(code_url, BarcodeFormat.QR_CODE, width, height, hints);
20. OutputStream out = null;
21. out = response.getOutputStream();
22. MatrixToImageWriter.writeToStream(bitMatrix, format, out);
23. out.flush();
24. out.close();
25. } catch (Exception e) {
26. }
27.
28. }
1. 生成订单:分两部分:一部分是业务需求的订单信息,就是发起支付前的订单信息,业务系统自行创建存储;另一部分是满足统一下单API要求的订单信息(也是我们这里要讲的)。“xxxxxx”:是你需要自己填写的对应信息:
[javascript] view plain copy
1. /**
2. * 生成订单
3. * @param orderId
4. * @return
5. */
6. private String createOrderInfo(String orderId) {
7. //生成订单对象
8. UnifiedOrderRequest unifiedOrderRequest = new UnifiedOrderRequest();
9. unifiedOrderRequest.setAppid("xxxxxxxxxxxxx");//公众账号ID
10. unifiedOrderRequest.setMch_id("xxxxxxxxx");//商户号
11. unifiedOrderRequest.setNonce_str(StringUtil.makeUUID());//随机字符串 <span style="color:#ff0000;"><strong>说明2(见文末)</strong></span>
12. unifiedOrderRequest.setBody("xxxxxx");//商品描述
13. unifiedOrderRequest.setOut_trade_no(orderId);//商户订单号
14. unifiedOrderRequest.setTotal_fee("x"); //金额需要扩大100倍:1代表支付时是0.01
15. unifiedOrderRequest.setSpbill_create_ip("xxxxxxxxxxxxx");//终端IP
16. unifiedOrderRequest.setNotify_url("xxxxxxxxxxxxxx");//通知地址
17. unifiedOrderRequest.setTrade_type("NATIVE");//JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付
18. unifiedOrderRequest.setSign(createSign(unifiedOrderRequest));//签名<span style="color:#ff0000;"><strong>说明5(见文末,签名方法一并给出)</strong></span>
19. //将订单对象转为xml格式
20. XStream xStream = new XStream(new XppDriver(new XmlFriendlyNameCoder("_-", "_"))); //<span style="color:#ff0000;"><strong>说明3(见文末)</strong></span>
21. xStream.alias("xml", UnifiedOrderRequest.class);//根元素名需要是xml
22. return xStream.toXML(unifiedOrderRequest);
23. }
1. 调统一下单API:根据要求将生成订单中返回的xml向微信给定的统一下单URL地址:https://api.mch.weixin.qq.com/pay/unifiedorder,发送请求,成功并获得二维码。
[javascript] view plain copy
1. /**
2. * 调统一下单API
3. * @param orderInfo
4. * @return
5. */
6. private String httpOrder(String orderInfo) {
7. String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
8. try {
9. HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
10. //加入数据
11. conn.setRequestMethod("POST");
12. conn.setDoOutput(true);
13.
14. BufferedOutputStream buffOutStr = new BufferedOutputStream(conn.getOutputStream());
15. buffOutStr.write(orderInfo.getBytes());
16. buffOutStr.flush();
17. buffOutStr.close();
18.
19. //获取输入流
20. BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
21.
22. String line = null;
23. StringBuffer sb = new StringBuffer();
24. while((line = reader.readLine())!= null){
25. sb.append(line);
26. }
27.
28. XStream xStream = new XStream(new XppDriver(new XmlFriendlyNameCoder("_-", "_")));//说明3(见文末)
29. //将请求返回的内容通过xStream转换为UnifiedOrderRespose对象
30. xStream.alias("xml", UnifiedOrderRespose.class);
31. UnifiedOrderRespose unifiedOrderRespose = (UnifiedOrderRespose) xStream.fromXML(sb.toString());
32.
33. //根据微信文档return_code 和result_code都为SUCCESS的时候才会返回code_url
34. //<span style="color:#ff0000;"><strong>说明4(见文末)</strong></span>
35. if(null!=unifiedOrderRespose
36. && "SUCCESS".equals(unifiedOrderRespose.getReturn_code())
37. && "SUCCESS".equals(unifiedOrderRespose.getResult_code())){
38. return unifiedOrderRespose.getCode_url();
39. }else{
40. return null;
41. }
42. } catch (Exception e) {
43. e.printStackTrace();
44. }
45. return null;
46. }
1. 将返回的支付交易链接生成二维码展示:没有异常的情况下,在页面中使用<img>标签接收就行。实际使用时,结合前端和业务的需求放置二维码。可以在扫码支付/案例及规范中找到部分素材和界面规范来设计微信风格的支付页面。
[javascript] view plain copy
1. <img src="${ctx}/wxPay/createQRCode?orderId=1111" width="174px">
1. 用户可以通过维系客户端进行扫码支付。支付完成后回调我们notify_url设置的url,通过成功的回调来更改业务系统中的订单状态或者一些业务需求。这里回调没有写出可以参考支付宝:web页面扫码支付、网站支付、支付宝即时到账 + springmvc中的回调。
五、说明:
1. 二维码可以查看zxing实现二维码生成和解析;微信这边也提供了二维码的学习,大家有兴趣可以看看:http://www.thonky.com/qr-code-tutorial/ 和http://coolshell.cn/articles/10590.html
2. 随机字符串:微信对随机字符串的要求是不超过32位。我这边是这样生成的,用时间戳。
[javascript] view plain copy
1. /**
2. * 创建UUID
3. * @return
4. */
5. public static synchronized String makeUUID() {
6. Date date = new Date();
7. StringBuffer s = new StringBuffer(DateUtil.formatYmdhmsm(date));
8. return s.append((new Random().nextInt(900) + 100)).toString();
9. }
3. 使用Xstream时,由于微信定义的变量名大部分使用了“_”,但是在Xstream中它是关键字,所以会自动变为“__”,引起报错。详情请看:XStream异常:对象转为XML时,会把"_"转成"__";报错:(Lcom/thoughtworks/xstream/io/naming/NameCoder;)V
4. 获取二维码链接时,只有在return_code 和result_code都为SUCCESS的时候有返回;这里我就简单的满足时返回,不满足返回null,您写的时候需要结合业务考虑下,是否需要增加判断,从而满足不同的业务场景。统一下单API
5. 签名在上面一直没有详细说明,首先查看微信的安全规范中签名算法。key值,需要自己填写
[javascript] view plain copy
1. /**
2. * 生成签名
3. *
4. * @param appid_value
5. * @param mch_id_value
6. * @param productId
7. * @param nonce_str_value
8. * @param trade_type
9. * @param notify_url
10. * @param spbill_create_ip
11. * @param total_fee
12. * @param out_trade_no
13. * @return
14. */
15. private String createSign(UnifiedOrderRequest unifiedOrderRequest) {
16. //根据规则创建可排序的map集合
17. SortedMap<String, String> packageParams = new TreeMap<String, String>();
18. packageParams.put("appid", unifiedOrderRequest.getAppid());
19. packageParams.put("body", unifiedOrderRequest.getBody());
20. packageParams.put("mch_id", unifiedOrderRequest.getMch_id());
21. packageParams.put("nonce_str", unifiedOrderRequest.getNonce_str());
22. packageParams.put("notify_url", unifiedOrderRequest.getNotify_url());
23. packageParams.put("out_trade_no", unifiedOrderRequest.getOut_trade_no());
24. packageParams.put("spbill_create_ip", unifiedOrderRequest.getSpbill_create_ip());
25. packageParams.put("trade_type", unifiedOrderRequest.getTrade_type());
26. packageParams.put("total_fee", unifiedOrderRequest.getTotal_fee());
27.
28. StringBuffer sb = new StringBuffer();
29. Set es = packageParams.entrySet();//字典序
30. Iterator it = es.iterator();
31. while (it.hasNext()) {
32. Map.Entry entry = (Map.Entry) it.next();
33. String k = (String) entry.getKey();
34. String v = (String) entry.getValue();
35. //为空不参与签名、参数名区分大小写
36. if (null != v && !"".equals(v) && !"sign".equals(k)
37. && !"key".equals(k)) {
38. sb.append(k + "=" + v + "&");
39. }
40. }
41. //第二步拼接key,key设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置
42. sb.append("key=" +"xxxxxxxxxxxxxxxxx");
43. String sign = MD5Util.MD5Encode(sb.toString(), "utf-8")
44. .toUpperCase();//MD5加密
45. return sign;
46. }
相关文章:支付宝:web页面扫码支付、网站支付、支付宝即时到账 + springmvc
- 微信:微信扫码支付、调用统一下单接口、网站支付 + springmvc
- 微信:微信扫码支付、调用统一下单接口、网站支付 + springmvc
- 微信:微信扫码支付、调用统一下单接口、网站支付 + springmvc
- 微信:微信扫码支付、调用统一下单接口、网站支付 + springmvc
- 微信:微信扫码支付、调用统一下单接口、网站支付 + springmvc
- 微信支付》统一下单接口调用
- Android 集成微信支付流程和统一下单接口的调用
- 微信支付-----统一下单action
- 微信支付统一下单
- 微信支付之统一下单
- 微信app支付-统一下单
- 【微信开发】支付-统一下单
- Java使用微信支付-发起统一下单支付接口
- 微信支付统一下单及调起支付接口的php接口实现 (可以用于app集成)
- 微信公众号—公众号支付JSPAI统一下单接口,详细流程
- 微信公众号支付 (二、统一下单接口)
- 微信支付-扫码支付-原生支付-统一下单-参数说明
- 微信支付-扫码支付-原生支付-统一下单-参数说明
- 欢迎使用CSDN-markdown编辑器
- 一篇博文从认识到熟练使用JAVA多线程
- CTF——php弱类型
- qt工程cmakelists编写注意事项
- 单例模式中为什么用枚举更好
- 微信:微信扫码支付、调用统一下单接口、网站支付 + springmvc
- 数据库-视图
- Spring Mvc之HelloWorld
- Weex环境简单配置
- js实现图片切换与轮播
- sqlite中求和运算有可能null且不能使用isnull判断解决
- HTTP请求报文和HTTP响应报文
- UITableView优化技巧
- 美图45亿美元估值赴港上市仅次腾讯,成10年来最大科技公司上市交易