微信公众号支付(已封装和未封装)

最近删了好几篇文章,也许成长就是不断地卸掉包袱

官方文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_3

目录

基础配置

未封装的pay

已封装的公众号支付


基础配置

一些基本的设置可以直接看我h5支付中有记载:https://blog.csdn.net/Goligory/article/details/78392505

需要APPID,微信支付商户号mch_id,API密钥key,Appsecret(secret),在微信公众平台设置网页授权域名

支付域名的设置,设置路径:商户平台-->产品中心-->开发配置

公众号支付和h5支付这都要设置一下,h5支付直接设置域名即可,不用设置后缀,但是公众号支付需要设置后缀,比如

如果你获取code后回调的路径是http://www.xxx.com/WX/wc/pay.do,那么你就应该填入支付域名为:http://www.xxx.com/WX/wc,也就是去掉后缀的上一级都要填写,否则验证会不成功

 

我这里给出的一个是封装的pay,一个是未封装的pay,都能支付,后面给链接

未封装的pay

<body>
    <h1>mtgg</h1>
    <div class="zdx3"><button onclick="pay()"><h1>共需支付1元  确认支付</h1></button></div>
	
</body>
    <script type="text/javascript">
        function pay() {
            var url="http://www.xxx.cn/WX/wc/pay.do?money=1"; //注意此处的basePath是没有端口号的域名地址。如果包含:80,在提交给微信时有可能会提示 “redirect_uri参数错误” 。
            var num=parseInt(Math.random()*10,10)+1;
            var state=Date.parse(new Date());
            state=state/1000+num;
            console.log(state)
            //money为订单需要支付的金额
            //state中存放的为商品订单号
            var weixinUrl="https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx08a8xxxxxxxxxxc3&redirect_uri="+encodeURI(url)+"&response_type=code&scope=snsapi_userinfo&state="+state+"#wechat_redirect";
            window.location.href=encodeURI(weixinUrl);
        }

    </script>

 

 

/**
	 * 用户提交支付,获取微信支付订单接口
	 */
	@RequestMapping(value="/pay.do")
	public ModelAndView pay(HttpServletRequest request,HttpServletResponse response){
		System.out.println("-------------------pay.do       returnurl-----------------");
		ModelAndView mv = new ModelAndView();

	/*------1.获取参数信息------- */
		//商户订单号
		String out_trade_no= request.getParameter("state");
		System.out.println(out_trade_no+"-------------订单号");
		//价格
		String money = request.getParameter("money");
		System.out.println(money+"-------------money");
		//金额转化为分为单位
		String finalmoney = WeChat.getMoney(money);
		//获取用户的code
		String code = request.getParameter("code");
		System.out.println(code+"-------------code");
	
	/*------2.根据code获取微信用户的openId和access_token------- */
		//注: 如果后台程序之前已经得到了用户的openId 可以不需要这一步,直接从存放openId的位置或session中获取就可以。
		//提交的url路径也就不需要再经过微信重定向。写成:http://localhost:8080/项目名/wechat/pay?money=${sumPrice}&state=${orderId}
		String openid=null;
		try {
			List<Object> list = accessToken(code);
			openid=list.get(1).toString();
			System.out.println(openid+"--------------openid");
		} catch (IOException e) {
//		logger.error("根据code获取微信用户的openId出现错误", e);
			mv.setViewName("error");
			return mv;
		}
	
	/*------3.生成预支付订单需要的的package数据------- */
		//随机数
		String nonce_str= MD5.getMessageDigest(String.valueOf(new Random().nextInt(10000)).getBytes());
		System.out.println(nonce_str+"-------------------nonce_str");
		//订单生成的机器 IP
		String spbill_create_ip = request.getRemoteAddr();
		System.out.println(spbill_create_ip+"-------------------spbill_create_ip");
		//交易类型 :jsapi代表微信公众号支付
		String trade_type = "JSAPI";
		//这里notify_url是 微信处理完支付后的回调的应用系统接口url。
		String notify_url ="http://www.moodgame.cn/WX/wc/weixinNotify.do";
		
		SortedMap<String, String> packageParams = new TreeMap<String, String>();
		packageParams.put("appid",  GZHID);
		packageParams.put("mch_id",  SHHID);
		packageParams.put("nonce_str", nonce_str);
		packageParams.put("body", "费用");
		packageParams.put("out_trade_no", out_trade_no);
		packageParams.put("total_fee", finalmoney);
		packageParams.put("spbill_create_ip", spbill_create_ip);
		packageParams.put("notify_url", notify_url);
		packageParams.put("trade_type", trade_type);
		packageParams.put("openid", openid);
	
	/*------4.根据package数据生成预支付订单号的签名sign------- */
		RequestHandler reqHandler = new RequestHandler(request, response);
		reqHandler.init( GZHID,  GZHSecret,  SHHKEY);
		String sign = reqHandler.createSign(packageParams);
		System.out.println(sign+"----------sign");
	/*------5.生成需要提交给统一支付接口https://api.mch.weixin.qq.com/pay/unifiedorder 的xml数据-------*/
		String xml="<xml>"+
				           "<appid>"+ GZHID+"</appid>"+
				           "<mch_id>"+ SHHID+"</mch_id>"+
				           "<nonce_str>"+nonce_str+"</nonce_str>"+
				           "<sign>"+sign+"</sign>"+
				           "<body><![CDATA["+"费用"+"]]></body>"+
				           "<out_trade_no>"+out_trade_no+"</out_trade_no>"+
				           "<total_fee>"+finalmoney+"</total_fee>"+
				           "<spbill_create_ip>"+spbill_create_ip+"</spbill_create_ip>"+
				           "<notify_url>"+notify_url+"</notify_url>"+
				           "<trade_type>"+trade_type+"</trade_type>"+
				           "<openid>"+openid+"</openid>"+
				           "</xml>";
	
	/*------6.调用统一支付接口https://api.mch.weixin.qq.com/pay/unifiedorder 生产预支付订单----------*/
		String createOrderURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
		String prepay_id="";
		try {
			prepay_id = GetWxOrderno.getPayNo(createOrderURL, xml);
			System.out.println(prepay_id+"--------------------prepay_id");
			if(prepay_id.equals("")){
				mv.addObject("ErrorMsg", "支付错误");
				mv.setViewName("error");
				return mv;
			}
		} catch (Exception e) {
//		logger.error("统一支付接口获取预支付订单出错", e);
			mv.setViewName("error");
			return mv;
		}
	/*将prepay_id存到库中*/
	/*PageData p = new PageData();
	p.put("shopId", out_trade_no);
	p.put("prePayId", prepay_id);
	activityService.updatePrePayId(p);*/

	
	/*------7.将预支付订单的id和其他信息生成签名并一起返回到jsp页面 ------- */
		nonce_str= MD5.getMessageDigest(String.valueOf(new Random().nextInt(10000)).getBytes());
		SortedMap<String, String> finalpackage = new TreeMap<String, String>();
		String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
		System.out.println(timestamp+"-------timestamp");
		String packages = "prepay_id="+prepay_id;
		finalpackage.put("appId",  GZHID);
		finalpackage.put("timeStamp", timestamp);
		finalpackage.put("nonceStr", nonce_str);
		finalpackage.put("package", packages);
		finalpackage.put("signType", "MD5");
		String finalsign = reqHandler.createSign(finalpackage);
		
		mv.addObject("appid",  GZHID);
		mv.addObject("timeStamp", timestamp);
		mv.addObject("nonceStr", nonce_str);
		mv.addObject("packageValue", packages);
		mv.addObject("paySign", finalsign);
		mv.addObject("success","ok");
		mv.setViewName("pay");
		return mv;
	}

 

<body onload="javascript:pay();">
<script type="text/javascript">
    function pay(){
        if (typeof WeixinJSBridge == "undefined"){
            if( document.addEventListener ){
                document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
            }else if (document.attachEvent){
                document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
                document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
            }
        }else{
            onBridgeReady();
        }
    }
    function onBridgeReady(){
        var appid="${appid}";
        var timestamp="${timeStamp}";
        var nocncestr="${nonceStr}";
        var package="${packageValue}";
        var paysign="${paySign}";
        WeixinJSBridge.invoke(
            'getBrandWCPayRequest', {
                "appId" : "${appid}",     //公众号名称,由商户传入
                "timeStamp": "${timeStamp}",         //时间戳,自1970年以来的秒数
                "nonceStr" : "${nonceStr}", //随机串
                "package" : "${packageValue}",
                "signType" : "MD5",         //微信签名方式:
                "paySign" : "${paySign}"    //微信签名
            },function(res){
                if(res.err_msg == "get_brand_wcpay_request:ok"){
                    location.href="success.jsp";
                }else if(res.err_msg == "get_brand_wcpay_request:cancel"){
                    console.log("用户取消支付")
                }else{
                    alert("支付失败!");
                }
            });
    }
</script>
</body>


发送链接获取code,回调后获取openid,订单号可以后端生成,基本信息打包成package进行签名,统一下单获取prepared_id,最后将六个数据返回到前端pay中调起h5支付

 

 

已封装的公众号支付

这种支付和h5支付用的是一个jar,支付宝微信的都封装过,IJPay.jar,maven库中有,最近更新的只需要调用他的接口就行

 

/**
	 * 公众号支付
	 */
	@RequestMapping(value ="/gzhPay.do",method = {RequestMethod.POST,RequestMethod.GET})
	public ModelAndView webPay(HttpServletRequest request, HttpServletResponse response) {
		System.out.println("------------------gzhPay start-------------------");
		ModelAndView mv=new ModelAndView();
		String total_fee = request.getParameter("total_fee");
		//获取用户的code
		String code = request.getParameter("code");
		
		String openId=null;
		try {
			List<Object> list = accessToken(code);
			openId=list.get(1).toString();
		} catch (IOException e) {
			System.out.println("--openid获取错误");
		}
		//openid可以通过网页授权获取存到session中从而获取,IJPay是这样做的,我是另一种方式
		 /*openId,采用 网页授权获取 access_token API:SnsAccessTokenApi获取
		String openId = (String) request.getSession().getAttribute("openId");*/
		if (StrKit.isBlank(openId)) {
			return mv;
		}
		if (StrKit.isBlank(total_fee)) {
			return mv;
		}
		String ip = IpKit.getRealIp(request);
		if (StrKit.isBlank(ip)) {
			ip = "127.0.0.1";
		}
		WxPayApiConfigKit.putApiConfig(getApiConfig());
		Map<String, String> params = WxPayApiConfigKit.getWxPayApiConfig()
				                             .setAttach("IJPay 公众号支付测试  -By Javen")
				                             .setBody("IJPay 公众号支付测试  -By Javen")
				                             .setOpenId(openId)
				                             .setSpbillCreateIp(ip)
				                             .setTotalFee(total_fee)
				                             .setTradeType(WxPayApi.TradeType.JSAPI)
				                             .setNotifyUrl(notify_url)
				                             .setOutTradeNo(String.valueOf(System.currentTimeMillis()))
				                             .build();
		String xmlResult = WxPayApi.pushOrder(false,params);
		log.info(xmlResult);
		Map<String, String> resultMap = PaymentKit.xmlToMap(xmlResult);
		
		String return_code = resultMap.get("return_code");
		String return_msg = resultMap.get("return_msg");
		if (!PaymentKit.codeIsOK(return_code)) {
			return mv;
		}
		String result_code = resultMap.get("result_code");
		if (!PaymentKit.codeIsOK(result_code)) {
			return mv;
		}
		// 以下字段在return_code 和result_code都为SUCCESS的时候有返回
		String prepay_id = resultMap.get("prepay_id");
		String timeStamp=String.valueOf(System.currentTimeMillis() / 1000);
		String nonce_str=String.valueOf(System.currentTimeMillis());
		String packages = "prepay_id="+prepay_id;
		Map<String, String> packageParams = new HashMap<String, String>();
		packageParams.put("appId", appID);
		packageParams.put("timeStamp", timeStamp);
		packageParams.put("nonceStr", nonce_str);
		packageParams.put("package", "prepay_id=" + prepay_id);
		packageParams.put("signType", "MD5");
		String packageSign = PaymentKit.createSign(packageParams, WxPayApiConfigKit.getWxPayApiConfig().getPaternerKey());
		packageParams.put("paySign", packageSign);
		//下面可以通过Map传入参数获取json字符串,其形式和上面一样,传到前台可以转为json形式再用,也是一个不错的方式,可以参考IJPay
		/*Map<String, String> packageParams = PaymentKit.prepayIdCreateSign(prepay_id);
		String jsonStr = JSON.toJSONString(packageParams);
		mv.addObject("jsonStr",jsonStr);*/
		mv.addObject("appid",  appID);
		mv.addObject("timeStamp", timeStamp);
		mv.addObject("nonceStr", nonce_str);
		mv.addObject("packageValue", packages);
		mv.addObject("paySign", packageSign);
		mv.addObject("success","ok");
		mv.setViewName("pay");
		return mv;
	}


这里面我多多少少变动了一些东西,因为我用的是SpringMVC,封装的jar中接口实现类没有@service,所以有些东西用不了,比如前端请求获取openid的方式不一样,原来的demo是通过session去获取的,还有最后返回了6个参数到前端,而原来的demo中直接将json字符串jsonStr返回到前端使用,和传递的参数形式一样,只不过我传入json字符串解析的时候有些问题就没用这种方式,大神解析明白可以直接用就ok了

 

支付结果我就不贴了,都测试成功,notify_url在demo中有,注意重复通知的情况,一定要给微信返回return_code:success

完善:支付回调demo中会重复通知,没有闭嘴,用h5支付这个回调:

https://blog.csdn.net/Goligory/article/details/78392505

 

有需要源码的私我(包括设计)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

站长大人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值