JAVA微信小程序支付源码

2023-10-31

做了很多次都没整理,总以为脑子记住了,可当下次用的时候又跟个脑瘫孩儿一样,今天就记录一下部分代码。需要帮助加QQ 1137586868

首先解释一下微信的签名制作方式:这里可能让小白最头疼的了,统一下单和支付时要的签名制作方式也都不一样。我这里只打个比喻让你理解怎么制作,具体的代码里已经有了。
比如说你要给统一下单接口发送请求参数 A B C D E F(其中F代表的你签名),ABCDE都是固定的参数,如appId,时间戳等, 那F怎么得来呢? 其实就是 A+B+C+D+E 以后,在通过MD5编译,形成的结果就是很长的字符串,在把字符串转为大写就做成了你的签名F。

总的来说,其实就3步。

1发起统一下单接口

统一下单接口是由java来搞得,但 通常情况下,由用户在小程序点击支付按钮触发,所以需要在小程序部分先发起请求,把自己业务的数据传到后台,在进行统一下单。

 // 立即购买
  justBuy: function () {
    var  that = this
    wx.request({
      url: app.globalData.PROJECTPATH + '/task/saveSalarGoods.htm',
      data: {
        userId: app.globalData.userId,//自己的用户ID
        openid: app.globalData.openid,//小程序用户的ID,
        goodsId: that.data.result.id,//自己商品ID
        name: that.data.addressArr[0].name,//自己的
        phone: that.data.addressArr[0].phone,//自己的
        address: that.data.addressArr[0].address,//自己的
        addressDetail: that.data.addressArr[0].addressDetail//自己的
      }, success: function (res) {
		//统一订单接口执行完成后,由小程序发起支付,调用wx.requestPayment方法,这个方法在第二步介绍
        }
      }
    })
  }

下面是java的统一下单代码

	/**
	 * 购买商品统一下单接口
	 * @throws UnsupportedEncodingException 
	 */
	@RequestMapping("saveSalarGoods.htm")
	public void salasGoods(String name,String phone,String address,String addressDetail,String openid,String goodsId,String userId,HttpServletRequest request,HttpServletResponse response) throws UnsupportedEncodingException{
			if (StringUtils.isBlank(userId)) {
				printStrAjax(response, HttpUtil.getClientResult(-1, "传递参数错误", null));
				return;
			}
			YpSales ypgoods = ypSalesService.selectById(goodsId);
			if (ypgoods.getGoods_status() == 2 || ypgoods.getGoods_status() == 3 ) {
				 printStrAjax(response, HttpUtil.getClientResult(-1, "该商品已出售,请刷新页面获取最新数据", null));
				 return;
			}
			ypgoods.setAddress_user(new String(name.getBytes("ISO-8859-1"), "UTF-8"));
			ypgoods.setAddress_phone(phone);
			ypgoods.setAddress(new String(address.getBytes("ISO-8859-1"), "UTF-8"));
			ypgoods.setAddress_detail(new String(addressDetail.getBytes("ISO-8859-1"), "UTF-8"));
			ypSalesService.saveSales(ypgoods);
			String amount = String.valueOf(ypgoods.getGoods_money()*Constants.MOENY_PRPORTION);
			String payId = payService.savePay(goodsId, userId, Integer.parseInt(amount), 4);
			//上面的都是我的业务代码,下面开始进行统一下单接口前得准备工作
	        //创建hashmap(用户获得签名)
	        SortedMap<String, String> paraMap = new TreeMap<String, String>();
	        //设置body变量 (支付成功显示在微信支付 商品详情中)
	        String body = "LHGS-PAY-GOODS";
	        //设置随机字符串
	        String nonceStr = PayUtil.createCode(32);
	        
	        //设置请求参数(小程序ID)
	        paraMap.put("appid", Constants.appID);
	        //设置请求参数(商户号)
	        paraMap.put("mch_id", Constants.MCH_ID);
	        //设置请求参数(随机字符串)
	        paraMap.put("nonce_str", nonceStr);
	        //设置请求参数(商品描述)
	        paraMap.put("body", PayUtil.urlEncodeUTF8(body));
	        //设置请求参数(商户订单号)
	        paraMap.put("out_trade_no", payId);
	        //设置请求参数(总金额)
	        paraMap.put("total_fee", amount);
	        //设置请求参数(终端IP)
	        paraMap.put("spbill_create_ip", "127.0.0.1");
	        //设置请求参数(回调通知地址)
	        paraMap.put("notify_url", Constants.SALES_PAY_PATH);
	        //设置请求参数(交易类型)
	        paraMap.put("trade_type", "JSAPI");
	        //设置请求参数(openid)(在接口文档中 该参数 是否必填项 但是一定要注意 如果交易类型设置成'JSAPI'则必须传入openid)
	        paraMap.put("openid", openid);
	        //自定义参数(我放的流水ID,用于回调的时候修改状态)
	        paraMap.put("device_info", payId);
	        
	        String stringA = PayUtil.createLinkString(paraMap);
	        //第二步,在stringA最后拼接上key得到stringSignTemp字符串,并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值signValue。(签名)
	        String sign = PayUtil.sign(stringA, Constants.key, "utf-8").toUpperCase();
	        //将参数 编写XML格式
	        paraMap.put("sign",sign);
	        String s = null;
			s = PayUtil.GetMapToXML(paraMap);
		    Map map = null;
			try {
				map = PayUtil.doXMLParse(PayUtil.httpRequest(Constants.UNIFIED_ORDER_PATH,s));
			} catch (Exception e) {
	    	    printStrAjax(response, HttpUtil.getClientResult(-1, "统一下单接口执行失败", map));
	    	    return;
			}
			
			if (!map.get("return_code").equals("SUCCESS")) {
	    	    printStrAjax(response, HttpUtil.getClientResult(-1, "统一下单接口执行失败", map));
	    	    return;
			}
			
			/**
			 * 统一下单接口执行成功,即map中返回值return_code=SUCCESS时。
			 * 制作支付的请求参数,和签名,
			 */
			SortedMap<String, String> paraMapPay = new TreeMap<String, String>();
			String timeStampPay = Long.toString(System.currentTimeMillis() / 1000);
			String nonceStrPay = PayUtil.createCode(32);
			String packagePay = (String) map.get("prepay_id");//请求统一下单成功时,获取这个参数,调起支付时要传递
			String signTypePay ="MD5";
			paraMapPay.put("timeStamp", timeStampPay);
			paraMapPay.put("nonceStr", nonceStrPay);
			paraMapPay.put("package", "prepay_id="+packagePay);
			paraMapPay.put("signType", signTypePay);
			paraMapPay.put("appId", Constants.appID);
			String payString =  PayUtil.createLinkString(paraMapPay);
			String signPay = PayUtil.sign(payString, Constants.key, "utf-8").toUpperCase();
			String paySignPay = signPay;
			
			//这是传递给小程序的支付所需要的参数。
			Map<String, String> mapPay = new HashMap<String, String>();		
			mapPay.put("timeStampPay", timeStampPay);
			mapPay.put("nonceStrPay", nonceStrPay);
			mapPay.put("packagePay", "prepay_id="+packagePay);//传递时=号不要忘记
			mapPay.put("signTypePay", signTypePay);
			mapPay.put("paySignPay", paySignPay);
		    printStrAjax(response, HttpUtil.getClientResult(1, "统一下单接口执行成功", mapPay));
	}

以上代码,已经完成统一下单和支付前得准备工作。

2进行支付

当统一下单返回成功时,并且已经把调起支付的请求参数准备好了,那么直接调用wx.requestPayment。改方法可以写在统一下单请求的返回里面,参考第一步。
切记下面的参数都是JAVA后台制作好传递过来的。

wx.requestPayment(
            {
              'timeStamp': res.data.result.timeStampPay,
              'nonceStr': res.data.result.nonceStrPay,
              'package': res.data.result.packagePay,
              'signType': 'MD5',
              'paySign': res.data.result.paySignPay,
              'success': function (res) {
                console.info("微信支付成功");
                wx.redirectTo({//这里的成功不代表真的成功,微信文档上说的,具体要看支付回调通知,在java代码里。
                  url: "../status/status?desc=支付成功&price=" + that.data.myMoney + "元&status=success&title=支付成功"
                })
              },
              'fail': function (res) {
                console.info("掉起支付失败");
                wx.redirectTo({
                  url: "../status/status?desc=支付失败&status=fail&title=支付失败"
                })
              },
              'complete': function (res) {
                console.info("");
              }
            })

3支付回调
上面支付成功后,就比较简单了,微信会给你发很多次支付是否成功的请求,你必须得给人家回一个“知道了”,
他才停止。 这个请求需要你在微信小程序里面配置,并且在java代码中,支付的时候也要传递。

这里需要注意的是自己的业务,因为微信发很多次回调,当你接收了以后,你首先更改你订单的支付状态,其次加减库存,所以,在加减库存等操作的时候,可不要随着微信给你请求次数不断的叠加,一定要判断哦。

 * 销售商品金额支付后的回调函数
	 * @param code
	 * @param request
	 * @param response
	 */
	@RequestMapping("salesnotify.htm")
	public void salesnotify(HttpServletRequest request,HttpServletResponse response){
		try{
			logger.info("info已经入支付成功返回接口--销售");
			BufferedReader br = new BufferedReader(new InputStreamReader((ServletInputStream)request.getInputStream()));
	        String line = null;
	        StringBuilder sb = new StringBuilder();
	        while((line = br.readLine()) != null){
	            sb.append(line);
	        }
	        br.close();
	        //sb为微信返回的xml
	        String notityXml = sb.toString();
	        String resXml = "";
	        System.out.println("---------------接收到的报文------------:" + notityXml);
	        Map map = PayUtil.doXMLParse(notityXml);
	        System.out.println("---------------转换MAP正常------------:");
	        String returnCode = (String) map.get("return_code");
	        if("SUCCESS".equals(returnCode)){
	        	logger.info("---------------支付成功已进入------------");
	            //验证签名是否正确
	            Map<String, String> validParams = PayUtil.paraFilter(map);  //回调验签时需要去除sign和空值参数
	            String validStr = PayUtil.createLinkString(validParams);//把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
	            String sign = PayUtil.sign(validStr, Constants.key, "utf-8").toUpperCase();//拼装生成服务器端验证的签名
	            // 因为微信回调会有八次之多,所以当第一次回调成功了,那么我们就不再执行逻辑了
	            System.out.println("---------------组装签名已经完成------------:");
	            //根据微信官网的介绍,此处不仅对回调的参数进行验签,还需要对返回的金额与系统订单的金额进行比对等
	            if(sign.equals(map.get("sign"))){
	            	System.out.println("---------------签名正常------------");
	                /**此处添加自己的业务逻辑代码start**/
	            	String payId = (String) map.get("device_info");//获取我的自定义刺激参数 
	            	if (StringUtils.isNotBlank(payId)) {
	            		ypSalesService.updateNotify(payId);
	            	}	
	   
	                /**此处添加自己的业务逻辑代码end**/
	                //通知微信服务器已经支付成功
	                resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
	                        + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
	            } else {
	            	System.out.println("---------------微信支付回调失败!签名不一致------------");
	            }
	        }else{
	        	 System.out.println("---------------支付失败------------");
	            resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
	                    + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
	        }
	        System.out.println(resXml);
	        System.out.println("微信支付回调数据结束");
	 
	        BufferedOutputStream out = new BufferedOutputStream(
	                response.getOutputStream());
	        out.write(resXml.getBytes());
	        out.flush();
	        out.close();
	        logger.info("---------------已反馈给微信------------");
		} catch (Exception e) {
			logger.info("---------------进入异常------------");
		}
		
	}
	

直接复制使用的话,很多方法找不到,可以加我Q 1137586868

后面再发一篇退款的代码

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JAVA微信小程序支付源码 的相关文章

随机推荐

  • 【Log日志】springboot项目中集成Log日志详解

    springboot项目中集成Log日志详解 一 Log日志介绍 1 Log 日志组件主要作用及用途 2 日志的级别Level 级别控制 3 日志的输出Import 3 1 快速使用 3 2 日志文件输出 3 3 自定义配置 4 Sprin
  • 微派三轮面试总结

    三轮技术面 面试周期 2023 6 19 2023 6 26 目录 一面 1 介绍一下自己的项目 2 Vue2中父子组件的声明周期执行顺序是怎么样的 3 computed和watch的区别 4 Vue路由中包含两种模式 hash和histo
  • 在windows中使用scp命令

    windows自带scp命令 上传文件 使用方法 scp 源文件路径 账户 地址 目的路径 scp C Users zbh Desktop 1 txt lucas 192 168 11 150 home lucas 然后输入密码即可 下载文
  • React18的useEffect会执行两次

    React18的useEffect会执行两次 useeffect执行两次 翼晗的博客 CSDN博客
  • ubuntu20.04开启SSH远程登录

    默认情况下 首次安装Ubuntu时 不允许通过SSH进行远程访问 以root 用户或具有sudo特权的用户执行以下步骤 以在Ubuntu系统上安装并启用SSH 1 打开终端并安装openssh server软件包 sudo apt upda
  • 入门级动态规划:2018年第九届蓝桥杯省赛B组第四题—测试次数( 摔手机 )

    目录 下面列出用动态规划如何解决此问题 计算若干层楼用若干部手机最少需要摔多少次 计算用若干部手机摔若干次最多可以确定多少层楼 原题描述 x星球的居民脾气不太好 但好在他们生气的时候唯一的异常举动是 摔手机 各大厂商也就纷纷推出各种耐摔型手
  • IntelliJ IDEA中创建jsp项目

    原 IntelliJ IDEA中创建jsp项目 2019年06月13日 22 24 08 炸天帮陈长生 阅读数 88 更多 分类专栏 IDEA 版权声明 本文为博主原创文章 遵循 CC 4 0 BY SA 版权协议 转载请附上原文出处链接和
  • SpringBoot集成ffmpeg、javacv自动为视频生成动态封面和静态封面图片

    引入依赖
  • 根据电子设计大赛心率检测的设计实践思路

    该装置具有以下几个特征 1 电路简单 系统整体功耗低 发热量低 可以稳定连续运行 2 使用新型 主频高的控制芯片 能在芯片上实现数据滤波 3 设计安卓端上位机显示心电信号与反馈信息 4 PC端上位机显示信号波形 将采集的数据以文件格式储存
  • Android蓝牙开发浅析

    由于近期正在开发一个通过蓝牙进行数据传递的模块 在参考了有关资料 并详细阅读了Android的官方文档后 总结了Android中蓝牙模块的使用 更新 之前承诺的蓝牙通讯模块的源码已经放出 详情请点击一下链接 http blog csdn n
  • Hive和hadoop的区别

    Hive和hadoop的区别就是 Hive是通过SQL语句实现的MapReduce功能 SQL语句的优点是语句简单 不需要过多的程序语句就能实现 可以理解成Hive是通过语句封装之后的hadoop
  • sqoop报错ERROR tool.ImportTool: Encountered IOException running import job: java.io.IOException: Query

    一 详细报错 ERROR tool ImportTool Encountered IOException running import job java io IOException Query select id login name f
  • 全球最火的R工具包一网打尽,超过300+工具,立马收藏!

    虽然很早就知道R被微软收购 也很早知道R在统计分析处理方面很强大 开始一直没有行动过 直到 直到12月初在微软技术大会 看到我软的工程师演示R的使用 我就震惊了 然后最近在网上到处了解和爬一些R的资料 看着看着就入迷了 这就是个大宝库了 以
  • fastadmin如何实现关联表查询

    这里需对表fa setting employees进行关联 yewu为本表字段 employee num为fa setting employees的字段 通过yewu与employee num进行关联 需要查询fa setting empl
  • JS的运算

    一JavaScript的算数运算符 加 var c a b console log c 13 减 console log a b 7 乘 console log a b 30 除 console log a b 3 333333333333
  • STL——list容器

    include
  • GD32F4XX SPI DMA容易被中断打断导致传输异常问题

    主要注意点在 2 dma触发spi传输函数 部分 如下图加入这个后就稳定了 1 初始化代码 void spi4 dma config void dma single data parameter struct dma init struct
  • centos 7 安装 RabbitMQ

    1 更新 yum 仓库 yum y update 2 安装Erlang yum y install epel release 查看安装的版本 erl version 3 下载安装 rabbitMQ wget content disposit
  • 投影时出现错误ERROR 999999: Error executing function.

    shapefile文件mtroads shp投影在NAD 1983 State Plane Montana FIPS 2500坐标系统 线单位为米 但没有投影文件 这时 如果要用define prijection定义mtroads shp时
  • JAVA微信小程序支付源码

    做了很多次都没整理 总以为脑子记住了 可当下次用的时候又跟个脑瘫孩儿一样 今天就记录一下部分代码 需要帮助加QQ 1137586868 首先解释一下微信的签名制作方式 这里可能让小白最头疼的了 统一下单和支付时要的签名制作方式也都不一样 我