支付项目采用springMvc+Dubbo架构实现,只对外提供接口。

话说,为什么微信支付比支付宝来的晚了那么一点,一句话,那一阵挺忙的,然后就没有时间整理,最近做完支付宝支付,顺便也把微信支付的也整理一下。

这里再吐槽一下,微信支付的DEMO基本为零,很多代码都是从网上查找的(也可能我么有仔细找API)。

前期酝酿准备

扫码支付,目前来说个人是不可以申请的,包括现在支付宝的即时到帐个人相关业务也取消了。所以这里必须有一个微信支付商户平台,具体怎么申请的,我也不清楚,只是拿来用的。

商户平台是要配合绑定微信公众账号使用的,具体操作申请下来已经绑定了,这里你也只管用就是了。

什么是扫码支付?

场景介绍

用户扫描商户展示在各种场景的二维码进行支付。

步骤1:商户根据微信支付的规则,为不同商品生成不同的二维码(如图6.1),展示在各种场景,用于用户扫描购买。

步骤2:用户使用微信“扫一扫”(如图6.2)扫描二维码后,获取商品支付信息,引导用户完成支付(如图6.3)。

支付二维码
图6.1 支付二维码
打开微信扫一扫二维码
图6.2 打开微信扫一扫二维码
确认支付页面
图6.3 确认支付页面

步骤(3):用户确认支付,输入支付密码(如图6.4)。

步骤(4):支付完成后会提示用户支付成功(如图6.5),商户后台得到支付成功的通知,然后进行发货处理。

用户确认支付,输入密码
图6.4 用户确认支付,输入密码
支付成功提示
图6.5 支付成功提示

如何集成到项目中去?

ConfigUtil参数配置:

  1. import java.util.Map;

  2. import java.util.ResourceBundle;

  3. import java.util.SortedMap;

  4. import java.util.TreeMap;

  5. /**

  6. * 相关配置参数

  7. * 创建者 张志朋

  8. * 创建时间 2016年9月28日

  9. *

  10. */

  11. public class ConfigUtil {

  12. /**

  13. * 服务号相关信息

  14. */

  15. public final static String APP_ID = "2016";//服务号的应用ID

  16. public final static String APP_SECRET = "2016";//服务号的应用密钥

  17. public final static String TOKEN = "weixinCourse";//服务号的配置token

  18. public final static String MCH_ID = "2016";//商户号

  19. public final static String API_KEY = "2016";//API密钥

  20. public final static String SIGN_TYPE = "MD5";//签名加密方式

  21. public final static String CERT_PATH = "apiclient_cert.p12";//微信支付证书存放路径地址

  22. static ResourceBundle resource = ResourceBundle.getBundle("config");

  23. //微信支付统一接口的回调action

  24. public final static String NOTIFY_URL = resource.getString("WEIXIN_NOTIFY_URL");

  25. /**

  26. * 微信基础接口地址

  27. */

  28. //获取token接口(GET)

  29. public final static String TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";

  30. //oauth2授权接口(GET)

  31. public final static String OAUTH2_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";

  32. //刷新access_token接口(GET)

  33. public final static String REFRESH_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN";

  34. // 菜单创建接口(POST)

  35. public final static String MENU_CREATE_URL = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";

  36. // 菜单查询(GET)

  37. public final static String MENU_GET_URL = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN";

  38. // 菜单删除(GET)

  39. public final static String MENU_DELETE_URL = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN";

  40. /**

  41. * 微信支付接口地址

  42. */

  43. //微信支付统一接口(POST)

  44. public final static String UNIFIED_ORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";

  45. //微信退款接口(POST)

  46. public final static String REFUND_URL = "https://api.mch.weixin.qq.com/secapi/pay/refund";

  47. //订单查询接口(POST)

  48. public final static String CHECK_ORDER_URL = "https://api.mch.weixin.qq.com/pay/orderquery";

  49. //关闭订单接口(POST)

  50. public final static String CLOSE_ORDER_URL = "https://api.mch.weixin.qq.com/pay/closeorder";

  51. //退款查询接口(POST)

  52. public final static String CHECK_REFUND_URL = "https://api.mch.weixin.qq.com/pay/refundquery";

  53. //对账单接口(POST)

  54. public final static String DOWNLOAD_BILL_URL = "https://api.mch.weixin.qq.com/pay/downloadbill";

  55. //短链接转换接口(POST)

  56. public final static String SHORT_URL = "https://api.mch.weixin.qq.com/tools/shorturl";

  57. //接口调用上报接口(POST)

  58. public final static String REPORT_URL = "https://api.mch.weixin.qq.com/payitil/report";

  59. public static void commonParams(SortedMap<Object, Object> packageParams){

  60. // 账号信息

  61. String appid = ConfigUtil.APP_ID; // appid

  62. String mch_id = ConfigUtil.MCH_ID; // 商业号

  63. // 生成随机字符串

  64. String currTime = PayCommonUtil.getCurrTime();

  65. String strTime = currTime.substring(8, currTime.length());

  66. String strRandom = PayCommonUtil.buildRandom(4) + "";

  67. String nonce_str = strTime + strRandom;

  68. packageParams.put("appid", appid);// 公众账号ID

  69. packageParams.put("mch_id", mch_id);// 商户号

  70. packageParams.put("nonce_str", nonce_str);// 随机字符串

  71. }

  72. /**

  73. * 该接口主要用于扫码原生支付模式一中的二维码链接转成短链接(weixin://wxpay/s/XXXXXX),减小二维码数据量,提升扫描速度和精确度。

  74. * @Author 张志朋

  75. * @param urlCode void

  76. * @Date 2016年10月26日

  77. * 更新日志

  78. * 2016年10月26日 张志朋 首次创建

  79. *

  80. */

  81. @SuppressWarnings("rawtypes")

  82. public static void shorturl(String urlCode){

  83. try {

  84. String key = ConfigUtil.API_KEY; // key

  85. SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();

  86. ConfigUtil.commonParams(packageParams);

  87. packageParams.put("long_url", urlCode);// URL链接

  88. String sign = PayCommonUtil.createSign("UTF-8", packageParams, key);

  89. packageParams.put("sign", sign);// 签名

  90. String requestXML = PayCommonUtil.getRequestXml(packageParams);

  91. String resXml = HttpUtil.postData(ConfigUtil.SHORT_URL, requestXML);

  92. Map map = XMLUtil.doXMLParse(resXml);

  93. String returnCode = (String) map.get("return_code");

  94. if("SUCCESS".equals(returnCode)){

  95. String resultCode = (String) map.get("return_code");

  96. if("SUCCESS".equals(resultCode)){

  97. urlCode = (String) map.get("short_url");

  98. }

  99. }

  100. } catch (Exception e) {

  101. e.printStackTrace();

  102. }

  103. }

参数必填项 APP_ID 和APP_SECRET 是从微信公众号里面获取的,而MCH_ID和API_KEY是从商户平台获取的。CERT_PATH 证书可选,但是如果做退款接口必须要使用证书。NOTIFY_URL 为回调地址,自定义路径,但是一定要微信平台可以调用到你的url。

如何生成二维码订单?

API文档地址

文档有详细的参数说明,具体生成需要xml解析,这里就不放了,好多的说,有需要的可以留言。

支付回调:

  1. /**

  2. * 二维码支付

  3. * 创建者 张志朋

  4. * 创建时间 2016年10月31日

  5. *

  6. */

  7. @Controller

  8. @RequestMapping(value = "weixin")

  9. public class WeixinPayController {

  10. @Autowired

  11. private IWeixinPayService weixinpayBack;

  12. /**

  13. * 微信支付回调

  14. * @Author 张志朋

  15. * @param request

  16. * @param response

  17. * @throws Exception void

  18. * @Date 2016年9月28日

  19. * 更新日志

  20. * 2016年9月28日 张志朋 首次创建

  21. *

  22. */

  23. @SuppressWarnings({ "unchecked", "rawtypes" })

  24. @RequestMapping(value = "pay")

  25. public void weixin_notify(HttpServletRequest request, HttpServletResponse response) throws Exception {

  26. LogUtil.info("支付成功回调");

  27. // 读取参数

  28. InputStream inputStream = request.getInputStream();

  29. StringBuffer sb = new StringBuffer();

  30. String s;

  31. BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));

  32. while ((s = in.readLine()) != null) {

  33. sb.append(s);

  34. }

  35. in.close();

  36. inputStream.close();

  37. // 解析xml成map

  38. Map<String, String> m = new HashMap<String, String>();

  39. m = XMLUtil.doXMLParse(sb.toString());

  40. // 过滤空 设置 TreeMap

  41. SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();

  42. Iterator it = m.keySet().iterator();

  43. while (it.hasNext()) {

  44. String parameter = (String) it.next();

  45. String parameterValue = m.get(parameter);

  46. String v = "";

  47. if (null != parameterValue) {

  48. v = parameterValue.trim();

  49. }

  50. packageParams.put(parameter, v);

  51. }

  52. // 账号信息

  53. String key = ConfigUtil.API_KEY; // key

  54. // 判断签名是否正确

  55. if (PayCommonUtil.isTenpaySign("UTF-8", packageParams, key)) {

  56. // ------------------------------

  57. // 处理业务开始

  58. // ------------------------------

  59. String resXml = "";

  60. if ("SUCCESS".equals((String) packageParams.get("result_code"))) {

  61. // 这里是支付成功

  62. String orderNo = (String) packageParams.get("out_trade_no");

  63. String attach = (String) packageParams.get("attach");

  64. //回调K12

  65. LogUtil.info(attach+"(订单号:"+orderNo+"付款成功)");

  66. // 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.

  67. resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";

  68. weixinpayBack.updateAccOrder(orderNo);

  69. } else {

  70. LogUtil.info("支付失败,错误信息:" + packageParams.get("err_code"));

  71. resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>"+ "</xml> ";

  72. }

  73. // ------------------------------

  74. // 处理业务完毕

  75. // ------------------------------

  76. BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());

  77. out.write(resXml.getBytes());

  78. out.flush();

  79. out.close();

  80. } else {

  81. LogUtil.info("通知签名验证失败");

  82. }

  83. }

  84. }

大体就这个样子,后续的可能就是安全优化了。涉及到钱可不是小问题。

转载于:https://blog.51cto.com/hzz333/1919475

JAVA实现的微信扫描二维码支付相关推荐

  1. iOS - 需求 - 微信扫描二维码支付(草稿)

    首先先讲一下这个流程: 1.商户即公司,根据微信官方支付的规则,为不同的商品或者是订单号生成不同的链接,将链接转换成二维码. 2.用户扫描二维码 3.微信客户端引导用户完成支付 4.用户完成支付,用户 ...

  2. JAVA实现的支付宝扫描二维码支付

    支付项目采用springMvc+Dubbo架构实现,只对外提供接口 原文地址:http://blog.52itstyle.com/archives/169/ 前期酝酿准备 最近项目中要上线支付功能.前 ...

  3. 微信扫描二维码跳转至浏览器打开 jsp

    微信扫描二维码总是用默认浏览器打开,无法下载任何东西.怎么办呢? 微信识别到打开为pdf 时,会自动给跳转至浏览器,所以解决方法就是服务器判断请求端为微信时,返回头部添加 Content-type:a ...

  4. 微信扫描二维码和浏览器扫描二维码 ios和Android 分别进入不用的提示页面

    实现微信扫描二维码和浏览器扫描二维码 ios和Android 分别进入不用的提示页面 而进入商城下载该项目 详情地址:gitee.com/DuJiaHui123- 1.创建完之后 替换文件里面的ios ...

  5. 微信扫描二维码在内置浏览器打不开文件的下载链接怎么办?哪些api接口可以解决...

    有哪些api接口可以实现微信扫描二维码在内置浏览器打开文件的下载链接? 经常看到贴吧上有人吐槽微信的检测系统太严格了,动不动就拦截第三方链接.怎么才能解决,怎么才能避免等等一系列的问题.因为平时我也会 ...

  6. 微信扫描二维码-电脑上网

    展视网北京科技有限公司--cuidc 由于 wifi 成为人们生活中不可或缺的一部分,店家 wifi 免费上网的招数也就日益增多. 今天我们介绍一种破解<微信扫描二维码上网>的招数,此招数 ...

  7. 使用电脑微信扫描二维码

    使用电脑微信扫描二维码 将二维码图片发送至文件传输助手 在与文件传输助手的聊天界面点开图片,右键,点击识别图中二维码即可 扫描完成.

  8. 微信扫描二维码快速登录网站

    在近期的一个项目中用到了微信扫描注册.登录网站功能所以整理了下希望对读者有帮助. 首先,你需要有一个没有绑定微信.微信公众平台的邮箱注册成为微信开放平台开发者,在管理中心创建移动应用.或者网站应用获得 ...

  9. 前端怎么从H5调起微信扫描二维码?小程序使用扫码功能.

    小程序如何使用扫码的功能呢? wx.scanCode(Object object) 参数 属性 类型 默认值 必填 说明 最低版本 onlyFromCamera boolean false 否 是否只 ...

最新文章

  1. 【字符串操作之】返回指定位置的字符和Unicode 字符代码 根据unicode返回字符→→charAt、charCodeAt和fromCharCode...
  2. php pdo 查询语句,PDO:预处理语句(参数化查询)
  3. Windows XP系统的“恢复”办法
  4. linux文件在哪个分区,linux下肿么查看目录所在的分区
  5. 如何基于Jupyter notebook搭建Spark集群开发环境
  6. mysql 查询排序位置_MySQL-基础查询与排序
  7. Coinbase发生一笔7500枚BTC巨额转出交易 转移金额近2.5亿美元
  8. heap python_python topN max heap,使用heapq还是自实现?
  9. Windows 7有用的20条新功能及技巧
  10. 贺利坚老师汇编课程37笔记:运用栈加两层循环之把六个字符串里的字母都改写成大写字母
  11. domain or business logic
  12. Linux 内核参数:meminfo
  13. Genotype陨石的秘密
  14. Temporal Action Proposal
  15. LTE的核心网之:MME,SGW,PGW
  16. 5.5.JMeter中调度器起作用(需要循环次数设置成永远)
  17. 为了监控老板,我用Python做了个摸鱼神器
  18. 使用 redis 连接指定端口的 redis 数据库
  19. 怎样检查mysql是否安装成功_怎么检验mysql安装成功
  20. SWAN测试用例botan/net2net-ed25519

热门文章

  1. 玩转华为ENSP模拟器系列 | 配置静态LSP示例
  2. 网站页面布局的原则有哪些呢?
  3. 【UE4 第一人称射击游戏】08-使用“AK47”发射子弹
  4. CMMI2.0之我见-过程管理PCM过程资产开发PAD
  5. css 边框 不连续,css 不规则边框怎么设置
  6. 手机怎么把证件照缩小到100k以下?手机照片如何压缩变小?
  7. 创业经验教训-新的思考
  8. 03-CSS文字文本样式
  9. 通过css让鼠标变小手样式
  10. ESP8266 AT指令连接阿里云物联网平台