热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

微信小程序微信支付+Java后台接口

微信小程序微信支付Java后台接口这块的内容比较复杂。在网上找了很多的文章,发现很多都不是能在我做的这个项目中跑起来。最终借助公司大佬的力量才勉强的把这块的内容完成

微信小程序 微信支付 + Java后台接口

这块的内容比较复杂。在网上找了很多的文章,发现很多都不是能在我做的这个项目中跑起来。最终借助公司大佬的力量才勉强的把这块的内容完成。实属不易。
https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_10&index=1
上面的链接是微信小程序开发文档关于微信支付的内容。建议看3遍以上

在微信支付之前必须要有下面5样材料

小程序的appid,APPsecret,支付商户号(mch_id),商户密钥(key),付款用户的openid
申请接入微信商户地址:https://pay.weixin.qq.com/static/applyment_guide/applyment_detail_miniapp.shtml

接下来就要贴代码了,首先是小程序端的代码:

//支付方法purchaseMember: function purchaseMember() {wx.showLoading({ title: '正在加载', mask: true });var that = this;var index = that.data.currentIndex;var priceInfo = that.data.priceObj;_utils2.default.requestPayment({url: '/webapi/pay/wxPay.json',data: { priceid: priceInfo[index].id },fail: function fail(res) {wx.showToast({ title: '支付取消', icon: 'none' });},success: function success(res) {wx.showToast({ title: '支付成功' });that.setData({ showGetMemberPopup: false });// 查询支付结果,支付成功后刷新用户缓存that.orderQuery();},callback: function callback(resultData) {wx.hideLoading();// that.data.orderno = resultData.ordernothat.data.orderno = resultData.orderno;}});},orderQuery: function orderQuery() {wx.showLoading({ title: '正在加载', mask: true });var that = this;getApp().GET({ url: "/webapi/pay/orderQuery.json",data: { orderno: that.data.orderno },success: function success(res) {wx.hideLoading();if (res.success && res.data.state == 'SUCCESS') {that.refresh();} else {wx.showToast({ title: res.msg, icon: 'none' });}}});},

统一下单的地址:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_1
这里面的参数很重要,要好好比对,必要的参数一定要有
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
Java后台代码相当多:
1.首先是支付的代码:
在刚支付的时候我们就要在会员权益表中增加这一条数据了,不管是否支付成功,因为支付失败那是回调之后的失败。

/*** 微信内调起支付* * &#64;param request* &#64;param response* &#64;return*/&#64;RequestMapping(value &#61; "/wxPay", method &#61; { RequestMethod.GET, RequestMethod.POST })&#64;ResponseBodypublic Response wxPay(HttpServletRequest request) {// 根据请求中的token来获取缓存中的用户信息Response resp &#61; new Response<>();Member loginUser &#61; MemberManager.getMember(request);if (loginUser &#61;&#61; null) {resp.setCode(CommonReturnCode.ERROR.code());return resp;}//前台传过来的数据String priceid &#61; ServletRequestUtils.getStringParameter(request, "priceid", null);String latitude &#61; ServletRequestUtils.getStringParameter(request, "payLatitude", null);String longitude &#61; ServletRequestUtils.getStringParameter(request, "payLongitude", null);Validator validator &#61; new Validator();// 获取地址情况 地址错误时不保存地址validator.required(latitude, "位置获取失败");validator.required(longitude, "位置获取失败");validator.number(request, "latitude", "位置获取失败");validator.number(request, "longitude", "位置获取失败");ReverseGeocodingResult RGResult &#61; null;if (!validator.isError()) {RGResult &#61; BaiduMapApi.getReverseGeocoding(latitude, longitude);}MemberPrice memberprice &#61; memberPriceService.selectById(priceid);// 判断订单是否存在SimpleDateFormat sdf &#61; new SimpleDateFormat("yyyyMMddHHmmss");String orderNum &#61; "HYQY" &#43; sdf.format(new Date()) &#43; StringRandom.getRandomNum();BigDecimal amount &#61; memberprice.getPrice();//把值塞进会员购买会员的表中MembershipBuyOrder order &#61; new MembershipBuyOrder();order.setMemberid(loginUser.getId());order.setPriceid(priceid);order.setPricename(memberprice.getName());order.setDuration(memberprice.getDuration());order.setTimeunit(Integer.valueOf(memberprice.getTimeunit()));order.setAmount(amount);order.setPaytype(OrderEnums.PayType.MONEY.getValue());order.setOrderno(orderNum);order.setStatus(1);order.setCreatetime(DateUtils.dateTimeToString(new Date()));PaymentLocation plRecord &#61; null;if (RGResult !&#61; null) {plRecord &#61; new PaymentLocation(PaymentLocation.BusinessType.MEMBERSHIP, order.getId(),RGResult.getFormatted_address(), RGResult.getSematic_description(), RGResult.getAddressComponent(),RGResult.getLocation());}//这些必要的数据是我们表中的数据String appid &#61; ApplicationConfigurer.getStringProperty("wxMiniprogramAppID", "");String mch_id &#61; ApplicationConfigurer.getStringProperty("wxMiniprogramAppMchId", "");String webContext &#61; ApplicationConfigurer.getStringProperty("web.context", "");String paternerKey &#61; ApplicationConfigurer.getStringProperty("wxpayAppKey", "");try {// 组织支付参数信息Map paraMap &#61; new HashMap();// 获取请求ip地址String ip &#61; RequestUtil.getRequestIP(request);// 下单成功的回调&#xff08;很重要&#xff09;String notifyUrl &#61; webContext &#43; "/wxpay/callOrder/memberCallback.json";WXPay wxpay &#61; new WXPay(WXMPPayConfigImpl.getInstance(), notifyUrl, true, false);// 拼接统一下单地址参数paraMap.put("openid", loginUser.getXcx_openid());paraMap.put("out_trade_no", orderNum);// 商品的订单号每次要唯一paraMap.put("fee_type", "CNY");// 化元为分&#xff0c;化小为整paraMap.put("total_fee", String.valueOf(amount.multiply(new BigDecimal(100)).longValue()));paraMap.put("mch_id", mch_id);paraMap.put("spbill_create_ip", ip);// 此路径是微信服务器调用支付结果通知路径paraMap.put("trade_type", "JSAPI");paraMap.put("body", "会员权益购买会员");paraMap.put("notify_url", notifyUrl);// 使用 wxpayAppKey 请求体 生成签名Map resultMap &#61; wxpay.unifiedOrder(paraMap);// 发送post请求"统一下单接口"返回预支付id:prepay_idif (!WXPayConstants.SUCCESS.equals(resultMap.get("result_code"))) {return new Response<>(CommonReturnCode.ERROR, "获取失败&#xff0c;请稍后重试");}String prepay_id &#61; resultMap.get("prepay_id");// 预支付idMap payMap &#61; new HashMap();payMap.put("appId", appid);payMap.put("timeStamp", WXPayUtil.getCurrentTimestamp() &#43; "");payMap.put("nonceStr", WXPayUtil.generateNonceStr());payMap.put("signType", "MD5");payMap.put("package", "prepay_id&#61;" &#43; prepay_id);String paySign &#61; WXPayUtil.generateSignature(payMap, paternerKey, SignType.HMACSHA256);payMap.put("paySign", paySign);boolean result &#61; membershipBuyOrderService.insert(order);Map responseResultMap &#61; new HashMap<>();payMap.remove("appId");responseResultMap.put("payData", payMap);responseResultMap.put("orderno", order.getOrderno());if (result) {if (plRecord !&#61; null) {plRecord.setRecordid(order.getId());// 保证订单支付地址的唯一性Wrapper plWrapper &#61; new EntityWrapper<>();plWrapper.eq("recordid", plRecord.getRecordid()).eq("businesstype", plRecord.getBusinesstype());paymentLocationService.delete(plWrapper);paymentLocationService.insert(plRecord);}return new Response<>(responseResultMap);} else {return new Response<>(CommonReturnCode.ERROR, "购买会员失败");}} catch (Exception e) {e.printStackTrace();}return new Response<>(CommonReturnCode.ERROR, "购买会员失败");}

/*** 向指定 URL 发送POST方法的请求* * &#64;param url* 发送请求的 URL* &#64;param param* 请求参数,请求参数应该是 name1&#61;value1&name2&#61;value2 的形式。* &#64;return 所代表远程资源的响应结果*/public static String sendPost(String url, String param) {PrintWriter out &#61; null;BufferedReader in &#61; null;String result &#61; "";try {URL realUrl &#61; new URL(url);// 打开和URL之间的连接URLConnection conn &#61; realUrl.openConnection();// 设置通用的请求属性conn.setRequestProperty("accept", "*/*");conn.setRequestProperty("connection", "Keep-Alive");conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");// 发送POST请求必须设置如下两行conn.setDoOutput(true);conn.setDoInput(true);// 获取URLConnection对象对应的输出流out &#61; new PrintWriter(conn.getOutputStream());// 发送请求参数out.print(param);// flush输出流的缓冲out.flush();// 定义BufferedReader输入流来读取URL的响应in &#61; new BufferedReader(new InputStreamReader(conn.getInputStream()));String line;while ((line &#61; in.readLine()) !&#61; null) {result &#43;&#61; line;}} catch (Exception e) {System.out.println("发送 POST 请求出现异常&#xff01;" &#43; e);e.printStackTrace();}// 使用finally块来关闭输出流、输入流finally {try {if (out !&#61; null) {out.close();}if (in !&#61; null) {in.close();}} catch (IOException ex) {ex.printStackTrace();}}return result;}

/*** 微信支付账单查询&#xff1a;该接口不做复杂的业务处理&#xff0c;仅根据商户订单号查询订单情况返回支付结果* * &#64;param request* &#64;param response*/&#64;RequestMapping(value &#61; "/orderQuery", method &#61; { RequestMethod.POST, RequestMethod.GET })&#64;ResponseBodypublic Response orderQuery(HttpServletRequest request, HttpServletResponse response) {String orderno &#61; ServletRequestUtils.getStringParameter(request, "orderno", "");if (StringUtils.isBlank(orderno)) {return new Response<>(CommonReturnCode.ERROR, "订单查询失败");}try {WXPay wxpay &#61; new WXPay(WXMPPayConfigImpl.getInstance());Map data &#61; new HashMap();data.put("out_trade_no", orderno);Map resp &#61; wxpay.orderQuery(data);if (WXPayConstants.SUCCESS.equals(resp.get("result_code"))&& WXPayConstants.SUCCESS.equals(resp.get("return_code"))) {Map resultMap &#61; new HashMap();resultMap.put("state", resp.get("trade_state"));resultMap.put("desc", resp.get("trade_state_desc"));return new Response<>(resultMap);}} catch (Exception e) {e.printStackTrace();}return new Response<>(CommonReturnCode.ERROR, "订单支付失败");}

2.支付回调的方法&#xff08;很重要&#xff09;

/*** 购买会员积分回调* * &#64;param request* &#64;param response* &#64;return*/&#64;RequestMapping(value &#61; "memberCallback", method &#61; { RequestMethod.GET, RequestMethod.POST })&#64;ResponseBodypublic void memberCallback(HttpServletRequest request, HttpServletResponse response) {BufferedReader br &#61; null;String xml &#61; "";try {StringBuilder result &#61; new StringBuilder();br &#61; request.getReader();for (String line; (line &#61; br.readLine()) !&#61; null;) {if (result.length() > 0) {result.append("\n");}result.append(line);}String notifyData &#61; result.toString(); // 支付结果通知的xml格式数据WXPay wxpay &#61; new WXPay(WXMPPayConfigImpl.getInstance());Map notifyMap &#61; WXPayUtil.xmlToMap(notifyData); // 转换成mapif (wxpay.isResponseSignatureValid(notifyMap)) {// 签名正确&#xff0c;处理// 进行处理BigDecimal cash_fee &#61; new BigDecimal(notifyMap.get("cash_fee"));// 根据订单流水号查询会员升级订单Wrapper wrapper &#61; new EntityWrapper<>();wrapper.eq("orderno", notifyMap.get("out_trade_no"));MembershipBuyOrder record &#61; membershipBuyOrderService.selectOne(wrapper);// 比对支付金额是否正确和支付状态if (cash_fee.compareTo(record.getAmount().multiply(new BigDecimal(100))) &#61;&#61; 0&& record.getStatus() &#61;&#61; OrderEnums.Status.TODO.getValue()) {Member member &#61; memberService.selectById(record.getMemberid());//处理复杂的各种表的逻辑if (flag) {xml &#61; "";}}} else {// 签名错误&#xff0c;如果数据里没有sign字段&#xff0c;也认为是签名错误}response.getWriter().write(xml);} catch (Exception e) {e.printStackTrace();} finally {if (br !&#61; null) {try {br.close();} catch (IOException e) {e.printStackTrace();}}}}

再调用的话就可以了 总结就是回调的方法真的非常重要&#xff01;&#xff01;&#xff01;
在这里插入图片描述


推荐阅读
  • 本文详细介绍了PHP中的几种超全局变量,包括$GLOBAL、$_SERVER、$_POST、$_GET等,并探讨了AJAX的工作原理及其优缺点。通过具体示例,帮助读者更好地理解和应用这些技术。 ... [详细]
  • 为什么会崩溃? ... [详细]
  • 前端技术分享——利用Canvas绘制鼠标轨迹
    作为一名前端开发者,我已经积累了Vue、React、正则表达式、算法以及小程序等方面的技能,但Canvas一直是我的盲区。因此,我在2018年为自己设定了一个新的学习目标:掌握Canvas,特别是如何使用它来创建CSS3难以实现的动态效果。 ... [详细]
  • This article explores the process of integrating Promises into Ext Ajax calls for a more functional programming approach, along with detailed steps on testing these asynchronous operations. ... [详细]
  • 本文详细介绍了如何使用 Python 编程语言中的 Scapy 库执行 DNS 欺骗攻击,包括必要的软件安装、攻击流程及代码示例。 ... [详细]
  • 本文探讨了在使用Apache HttpClient 4.x(作为commons-httpclient 3.x的后续版本)时,如何配置默认的HttpContext,以确保每次执行请求时无需显式传递上下文。 ... [详细]
  • 华为云openEuler环境下的Web应用部署实践
    本文详细记录了在华为云openEuler系统上进行Web应用部署的具体步骤,包括配置yum源、安装Apache、MariaDB、PHP及其相关组件,并完成WordPress的安装与配置过程。 ... [详细]
  • 本文深入探讨了领域驱动设计(DDD)中的聚合概念及其在事件溯源架构中的应用。聚合是一组紧密相关的类,这些类作为一个整体运作,形成一个有明确边界的组织。只有通过聚合根才能与聚合内的对象进行交互。 ... [详细]
  • Kubernetes 实践指南:初次体验
    本文介绍了如何通过官方提供的简易示例,快速上手 Kubernetes (K8S),并深入理解其核心概念和操作流程。 ... [详细]
  • 本文探讨了如何在Sitecore 9环境中通过Postman使用API密钥发送请求,包括解决常见错误的方法。 ... [详细]
  • iOS 小组件开发指南
    本文详细介绍了iOS小部件(Widget)的开发流程,从环境搭建、证书配置到业务逻辑实现,提供了一系列实用的技术指导与代码示例。 ... [详细]
  • Web开发实践:创建连连看小游戏
    本文详细介绍了如何在Web环境中开发一款连连看小游戏,适合初学者和技术爱好者参考。通过本文,您将了解游戏的基本结构、连线算法以及实现方法。 ... [详细]
  • 我在尝试将组合框转换为具有自动完成功能时遇到了一个问题,即页面上的列表框也被转换成了自动完成下拉框,而不是保持原有的多选列表框形式。 ... [详细]
  • 本文详细介绍了如何在PHP中使用Memcached进行数据缓存,包括服务器连接、数据操作、高级功能等。 ... [详细]
  • 本文介绍了如何通过安装和配置php_uploadprogress扩展来实现文件上传时的进度条显示功能。通过一个简单的示例,详细解释了从安装扩展到编写具体代码的全过程。 ... [详细]
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有