java-微信公众号充值

实现功能 :公众号内H5页面调用微信支付实现充值,
1.开发流程
1) 申请公众号 并且认证        (这个是前提 自行百度有很多方法)
2)获取用户授权 获取openid (上一篇文章有介绍怎么获取)
3)调用统一下单接口获取预支付id  微信统一接口API  https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
4)H5调起微信支付的内置JS  
5)支付完成后,微信回调URL的处理
第1).2)步就不在介绍了....
2.统一接口参数介绍
appid ==应用ID==登陆微信公众号后台-开发-基本配置
mch_id == 微信支付商户号==登陆微信支付后台,即可看到
body==商品描述==商品或支付单简要描述
spbill_create_ip == 获取发起电脑ip
代码如下
String spbill_create_ip = LLPayUtil.getIpAddr(request).replace("_", "."); 

    /**
     * 
     * 功能描述:获取真实的IP地址
     * @param request
     * @return
     * @author guoyx
     */
    public static String getIpAddr(HttpServletRequest request)
    {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
        {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
        {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
        {
            ip = request.getRemoteAddr();
        }
        if (!isnull(ip) && ip.contains(","))
        {
            String[] ips = ip.split(",");
            ip = ips[ips.length - 1];
        }
        //转换IP 格式
        if(!isnull(ip)){
            ip=ip.replace(".", "_");
        }
        return ip;
    }
trade_type==交易类型==取值如下:JSAPI,NATIVE,APP。我们这里使用的JSAPI。标题已经说了,是微信公众号支付。他们的区别,请参考https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_2
      ps:JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付,统一下单接口trade_type的传参可参考这里。MICROPAY--刷卡支付,刷卡支付有单独的支付接口,不调用统一下单接口
nonce_str==随机字符串==随机字符串,不长于32位
    代码如下

    /**
     * 获取随机字符串 Nonce Str
     *
     * @return String 随机字符串
     */
    public static String generateNonceStr() {
        return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
    }
notify_url==通知地址==接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。
out_trade_no==商户订单号==商户系统内部的订单号,32个字符内、可包含字母
代码如下
    /**
 * 生成订单号,格式:XX(前缀) + yyyyMMddHHmmss + 10位数
 * @param prefix
 * @return
 */
public static String generate(String prefix) {
synchronized(locker) {
if (sn == 999999999) {
sn = 0;
} else {
sn ++;
}
String str = String.format("%010d", sn);
return prefix + sdf.format(new Date()) + str;
}
}

total_fee==总金额==订单总金额
代码如下 money金额
String.valueOf((int)(money*100))
openid ==用户标识==trade_type=JSAPI,此参数必传,用户在商户appid下的唯一标识
sign ==签名==官方给的签名算法
代码如下


key ==key设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置
String sign = PayCommonUtil.createSign("UTF-8", packageParams, key);
/**
 * @author
 * @date 2016-4-22
 * @Description:sign签名
 * @param characterEncoding
 *            编码格式
 * @param parameters
 *            请求参数
 * @return
 */
public static String createSign(String characterEncoding, SortedMap<Object, Object> packageParams, String API_KEY) {
StringBuffer sb = new StringBuffer();
Set es = packageParams.entrySet();
Iterator it = es.iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
String k = (String) entry.getKey();
String v = (String) entry.getValue();
if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {
sb.append(k + "=" + v + "&");
}
}
sb.append("key=" + API_KEY);
String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
return sign;
}

封装成XML参数
SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
packageParams.put("appid", appid);
packageParams.put("mch_id", mch_id);
packageParams.put("nonce_str",nonce_str );
packageParams.put("body", body);
packageParams.put("out_trade_no", out_trade_no);
packageParams.put("total_fee", String.valueOf((int)(money*100)));// 价格(注意:价格的单位是分)
packageParams.put("spbill_create_ip", spbill_create_ip);
packageParams.put("notify_url", notify_url);
packageParams.put("trade_type", "JSAPI"); //交易类型 JSAPI--公众号支付
packageParams.put("openid", openid); //微信ID
packageParams.put("sign", sign)


准备好以上参数之后,封装成XML
格式如下:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xml>
    <appid>wxb1427ebebexxxxxx</appid>
    <body>XXX费用</body>
    <device_info>WEB</device_info>
    <mch_id>132186xxxx</mch_id>
    <nonce_str>6AED000AF86A084F9CB0264161E29DD3</nonce_str>
    <notify_url>https://一个域名/api/wechatPay/jsapiPayNotify</notify_url>
    <openid>oo8WUt0taCqjt552htW1vw-xxxxx</openid>
    <out_trade_no>1</out_trade_no>
    <sign>各种排序+key生成的那个sign</sign>
    <total_fee>1</total_fee>
    <trade_type>JSAPI</trade_type>
</xml>

代码如下
String requestXML = PayCommonUtil.getRequestXml(packageParams);
	/**
	 * @author
	 * @date 2016-4-22
	 * @Description:将请求参数转换为xml格式的string
	 * @param parameters
	 *            请求参数
	 * @return
	 */
	public static String getRequestXml(SortedMap<Object, Object> parameters) {
		StringBuffer sb = new StringBuffer();
		sb.append("<xml>");
		Set es = parameters.entrySet();
		Iterator it = es.iterator();
		while (it.hasNext()) {
			Map.Entry entry = (Map.Entry) it.next();
			String k = (String) entry.getKey();
			String v = (String) entry.getValue();
			if ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k) || "sign".equalsIgnoreCase(k)) {
				sb.append("<" + k + ">" + "<![CDATA[" + v + "]]></" + k + ">");
			} else {
				sb.append("<" + k + ">" + v + "</" + k + ">");
			}
		}
		sb.append("</xml>");
		return sb.toString();
	}



  
  
调用微信的统一下单地址:https://api.mch.weixin.qq.com/pay/unifiedorder
调用代码如下
String resXml = HttpUtil.postData(PropertiesHandler.getConfigValue("UFDODER_URL").toString(), requestXML);

 见证奇迹的时刻。如果以上参数都神奇的对了,那么会收到微信返回的XML字符串,格式如下

<xml>
  <return_co de><![CDATA[SUCCESS]]></return_co de>
  <return_msg><![CDATA[OK]]></return_msg>
  <appid><![CDATA[wxb1427ebebexxxxxx]]></appid>
  <mch_id><![CDATA[132186xxxx]]></mch_id>
  <device_info><![CDATA[WEB]]></device_info>
  <nonce_str><![CDATA[Hh4LFHUUvtDYtNdp]]></nonce_str>
  <sign><![CDATA[079F8A915FD3044F4A17D75F4945E955]]></sign>
  <result_co de><![CDATA[SUCCESS]]></result_co de>
  <prepay_id><![CDATA[wx20160617155030d9e6a0e48b0533061255]]></prepay_id>
  <trade_type><![CDATA[JSAPI]]></trade_type>
</xml>

我们需要的,就是这货

prepay_id

拿到prepay_id后 进行下一步 生成paySign 签名 代码如下
	SortedMap<Object, Object> packagePara = new TreeMap<Object, Object>();
			//自1970年1月1日 0点0分0秒以来的秒数。注意:部分系统取到的值为毫秒级,需要转换成秒(10位数字)。
			long timeSt = (LLPayUtil.getPhoneCurrentDateTimeStr()); 
			String timeStr = Long.toString(timeSt);
			packagePara.put("appId", appid); //公众号名称,由商户传入    
			packagePara.put("timeStamp",timeStr); //时间戳,自1970年以来的秒数     
			packagePara.put("nonceStr", nonce_str); // 随机串  
			packagePara.put("package", "prepay_id="+urlCode); //prepay_id
			packagePara.put("signType", "MD5");	//微信签名方式	
			String paySign = PayCommonUtil.createSign("UTF-8", packagePara, key); // 微信签名
	/**
	 * @author
	 * @date 2016-4-22
	 * @Description:paySign 签名
	 * @param characterEncoding
	 *            编码格式
	 * @param parameters
	 *            请求参数
	 * @return
	 */
	public static String createSign(String characterEncoding, SortedMap<Object, Object> packageParams, String API_KEY) {
		StringBuffer sb = new StringBuffer();
		Set es = packageParams.entrySet();
		Iterator it = es.iterator();
		while (it.hasNext()) {
			Map.Entry entry = (Map.Entry) it.next();
			String k = (String) entry.getKey();
			String v = (String) entry.getValue();
			if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {
				sb.append(k + "=" + v + "&");
			}
		}
		sb.append("key=" + API_KEY);
		String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
		return sign;
	}

拼接好参数之后 传回给前台
	if(null != paySign){
				model.put("res", true);
				model.put("appId", appid);
				model.put("timeStamp", timeStr);
				model.put("nonceStr", nonce_str);
				model.put("packag","prepay_id="+urlCode);
				model.put("signType", "MD5");
				model.put("paySign", paySign);
				return model;
			}
注意:记得添加授权目录

  
  
 

前台JSP代码
//微信充值
	function wechat(){
		var phone = '${userInfo.phone}';
		var money = $("#money").val();
		if(money == "" || money == 0){
			 layer.msg("充值的金额不能为空");
			return false;
		}
		var moneyCheck = /^[0-9]+(.[0-9]{1,2})?$/;
		if(!moneyCheck.test(money)){
			 layer.msg("请保留两位小数!");
			return;
		}
		$.ajax({
			url: '<%=WEBPATH%>/fund/phoenWechatpay',
			type: "post",
			async: false, 
			data: {"money" : money},
			success: function(data){
				if(data.res){
					callPay(data.appId,data.timeStamp,data.nonceStr,
							data.packag,data.signType,data.paySign);
				}else{
					alert("充值失败!");
				}
			}		
		})
	}

		  //调用微信内置浏览器的微信支付  
	  function callPay(appId,timeStamp,nonceStr,
				packag,signType,paySign) {  
		    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(appId,timeStamp,nonceStr,
						packag,signType,paySign);  
		    }  
		  }  
			//提交微信充值
		 function onBridgeReady(appId,timeStamp,nonceStr,
					packag,signType,paySign) {  	
			// alert("appId:"+appId+",timeStamp:"+timeStamp+",nonceStr:"+nonceStr+",packag:"+packag+",signType:"+signType+",paySign:"+paySign);								
			    WeixinJSBridge.invoke('getBrandWCPayRequest', {  
			      "appId" : appId, //公众号名称,由商户传入     
			      "timeStamp" : timeStamp, //时间戳,自1970年以来的秒数     
			      "nonceStr" : nonceStr, //随机串     
			      "package" : packag,	//"prepay_id=u802345jgfjsdfgsdg888",  
			      "signType" : signType, //微信签名方式:     
			      "paySign" : paySign //微信签名   
			    }, function(res) { // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回  ok,但并不保证它绝对可靠。    
			    	if (res.err_msg == "get_brand_wcpay_request:ok") {  	
			    	  //充值成功后返回页面
			        window.location.replace("<%=WEBPATH %>/fund/phone_return_url");
			      }  
			      if (res.err_msg == "get_brand_wcpay_request:cancel") {  
			    	  layer.msg("交易取消");  
			    	  return false;
			      }  
			      if (res.err_msg == "get_brand_wcpay_request:fail") {  
			    	  layer.msg("支付失败");  
			    	  return false;
			      }  
			    });  
			  }  

效果图如下

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 要获取微信公众号的code,需要使用Java编程语言和微信公众号的开发接口。以下是详细步骤: 第一步,通过微信官方网站注册一个公众号,并在开发者中心中下载微信公众号的SDK。 第二步,使用Java进行开发,编写相应的代码,实现接收微信公众平台的消息、回复微信公众平台的消息等功能。同时,在代码中需要配置微信公众平台的各种参数,例如APPID、APPSECRET、SIGNATURE等。 第三步,通过调用微信公众平台提供的接口获取微信公众号的code。 在Java代码中,可以使用HttpClient这个类库来请求微信公众平台提供的获取code的接口,然后通过解析返回的json数据,获取到相应的code。 最后,获取到code之后,可以使用该code来获取access_token等重要信息,在公众号开发中应用。通过这些方法,可以成功获取到微信公众号的code,进而实现更加多样化的公众号开发。 ### 回答2: Java 获取微信公众号code 的方法有以下两种: 1. 使用微信官方提供的开发接口 微信官方提供了开发者工具包 Weixin-java-tools,其中包含了获取微信公众号code 的方法。 具体步骤如下: a. 在 pom.xml 文件中引入 Weixin-java-tools 工具包: ```xml <dependency> <groupId>com.github.binarywang</groupId> <artifactId>weixin-java-tools</artifactId> <version>3.4.0</version> </dependency> ``` b. 在代码中调用 Weixin-java-tools 中的方法实现获取 code: ```java public String getCode() throws WxErrorException { WxMpService wxMpService = new WxMpServiceImpl(); wxMpService.setWxMpConfigStorage(wxMpInMemoryConfigStorage); String redirectUrl = wxMpService.oauth2buildAuthorizationUrl( "http://example.com/wx/oauth/callback", WxConsts.OAuth2Scope.SNSAPI_USERINFO, null); return redirectUrl; } ``` 2. 使用第三方开源库 除了使用微信官方提供的工具包外,还有第三方开源库 WeChat-Java-SDK,也可以实现获取微信公众号 code。 具体步骤如下: a. 在 pom.xml 文件中引入 WeChat-Java-SDK 工具包: ```xml <dependency> <groupId>com.github.sd4324530</groupId> <artifactId>wechat-java-sdk</artifactId> <version>1.3.8.2</version> </dependency> ``` b. 在代码中调用 WeChat-Java-SDK 中的方法实现获取 code: ```java public String getCode() { WeChat weChat = new WeChat(config); String redirectUrl = weChat.getOpenOauthUrl(WxConsts.OAuth2Scope.SNSAPI_USERINFO, callbackUrl, null); return redirectUrl; } ``` 以上就是 Java 获取微信公众号 code 的两种方法,开发者可以根据自己的需求选择相应的方法。 ### 回答3: 在 Java 中获取微信公众号 code 通常涉及到两个主要步骤,首先是在前端页面中获取 code,然后是使用 Java 后端将 code 传递给微信服务器进行验证,最终获得用户信息。 第一步,前端页面中获取 code 在前端页面中获取微信公众号 code 可以通过使用微信官方提供的 JS-SDK 来实现。首先需要在页面引入 JS-SDK,然后使用微信提供的方法获取 code。其中,获取 code 的过程需要用户在微信客户端内打开并登录公众号,否则获取 code 会失败。 以下是获取 code 的示例代码: ```javascript $.ajax({ type: 'GET', url: 'https://open.weixin.qq.com/connect/oauth2/authorize?appid={APPID}&redirect_uri={REDIRECT_URI}&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect', dataType: 'json', success: function (data) { var code = data.code; console.log(code); }, error: function (xhr, errorType, error) { console.log(error); } }); ``` 在以上代码中,{APPID} 是公众号AppID,{REDIRECT_URI} 指定了用户授权后重定向的页面路径。获取到的 code 可以通过 AJAX 请求发送到后端进行验证。 第二步,使用 Java 后端将 code 传递给微信服务器进行验证 在 Java 后端中,我们可以通过使用 Spring 框架提供的 RestTemplate 类进行 HTTP 请求。同样需要注意的是,在进行 HTTP 请求之前需要在公众号后台配置安全域名,否则会出现请求失败的情况。 以下是使用 RestTemplate 类进行 HTTP 请求的示例代码: ```java RestTemplate restTemplate = new RestTemplate(); String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={APPID}&secret={SECRET}&code={CODE}&grant_type=authorization_code"; String appId = "****"; // 公众号AppID String secret = "****"; // 公众号AppSecret String code = "****"; // 前端获取到的 code String result = restTemplate.getForObject(url, String.class, appId, secret, code); System.out.println(result); ``` 以上代码中,url 指定了微信接口的地址和参数,其中 appId、secret 和 code 分别是公众号AppID、AppSecret 和前端获取到的 code。getForObject() 方法用于发送 HTTP GET 请求,并返回接口返回的字符串结果。 最终,我们可以通过解析微信接口返回的 JSON 字符串,获取用户的 openid、access_token 等信息。获取到用户信息后,我们可以将其存储到数据库中,或者再次发送 HTTP 请求获取更多信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

zengsange

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

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

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

打赏作者

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

抵扣说明:

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

余额充值