微信公众号类型选择支付需要什么类型的公众号?

微信公众号最新注册说明(2015)
官方微信扫一扫
热门行业应用解决方案
顶级增值服务解决方案
微信公众号最新注册说明(2015)
☆人已学习|发布者:黄保|发布时间: 10:39
导读:做微商,第一选择就是微信官方平台微信公众号,作为新手做微商必须要了解一些关于注册微信公众号的说明信息。...
  做微商,第一选择就是微信官方平台微信公众号与,作为新手做微商必须要了解一些关于注册微信公众号的说明信息。
  注册公众平台都需要准备哪些材料?
  订阅号和服务号的区别?
  如何选择信息登记类型?
  建议可以参考组织机构代码证上的组织类型选择公众平台信息登记类型;
  举例:
  1、个体工商户选择=》企业类型;
  2、企业法人、企业非法人选择=》企业类型;
  3、医院选择=》其他组织类型;
  4、民办学校、学校选择=》其他组织类型;
  5、驾校用道路经营许可证选择=》其他组织类型;
  6、民办非企业用登记证书选择=》其他组织类型;
  温馨提示:
  1、若组织机构代码证上&机构类型&为:、企业法人、企业非法人、请勿选择&其他组织类型&进行登记。
  2、若&个体工商户&无&对公账号&请选择&其他组织&完成注册公众帐号。
  信息登记的审核时间多长?
  微信公众号信息登记时,请您按照真实信息进行填写,填写后有相关工作人员对您的身份信息进行审核,审核时间为7个工作日(节假日、周末除外)。
  信息登记审核通过后可正常使用微信公众平台,审核不通过登录时页面会提示。
  证件登记次数限制?
  1、运营者身份证名称,是指运营者姓名。
  2、同一个身份证(不支持临时身份证)可登记5次信息。目前仅支持中国内地年满18周岁的身份证进行信息登记(不包含港、澳、台湾);
  3、同一个手机号码,可登记5次信息。 支持填写中国内地的手机号码(不包含港、澳、台),其它国家的手机号码暂不支持。
  4、同一个公司可以注册和认证50个公众号,其他类型组织同一个机构可注册和认证50个公众号。
  5、目前只支持填写中国大陆的营业执照(不包含香港、澳门、台湾)进行信息登记,其他国家地区暂未开放。&&点击这里进入查看详情
  审核期间哪些功能无法使用?
  1、审核期间,微信公众帐号无法申请认证;
  2、审核期间,群发消息功能、高级功能无法使用;
  3、审核期间,他人无法通过&搜索公众帐号&无法搜索到微信公众帐号。
 电商随着其应用领域的不断扩大和信息服务方式的不断创新,电商的类型也层出不穷,那么主要分为哪几种类型呢?
关注HiShop
咨询热线:推荐这篇日记的豆列
······版权所有 京ICP备号-2
迷上了代码!当前访客身份:游客 [
我很懒、什么都没留下
:楼主,关于测试目录是怎么回事??难道是服务器里...
:引用来自“常育新”的评论RequestHandler 这个类...
:引用来自“啥都别说了”的评论需要这么麻烦吗?b...
:引用来自“常育新”的评论RequestHandler 这个类...
:RequestHandler 这个类可以把代码放出来嘛?...
:需要这么麻烦吗?bmob支付组件几句代码就可以实现...
今日访问:58
昨日访问:26
本周访问:58
本月访问:930
所有访问:8057
微信公众号支付 js api
发表于8个月前( 16:49)&&
阅读(8605)&|&评论()
0人收藏此文章,
&&&&&&&&说起来.微信支付真是一堆坑. 居然官网都没有java版本的完整代码. 就算是php版本的.还都有错误.且前后各种版本.各种文档一大堆....不停的误导开发人员.
&&&& & &花了一天半时间.总算实现了微信公众号支付.和pc端的微信扫码支付.其他不说了.直接给思路
& & & &&本人做的是微信V3版本的微信支付.微信的官方文档中.提供的demo 只有一些工具类.这些类还是很有作用的.
&&&&&&&&& 可以在这个连接中找到相应的java类.
&&&&&&&&这里一定要注意.在官网填写的授权目录一定要写到三级目录.如:
我的回调地址是:
那么,官网填写都授权目录就是:
我试过.授权目录写到2级.是没用的.此处差评,第一个坑.
& 首先,定义各种微信支付所需要的参数
GzhConfig.java
public&static&String&APPID&=&"XXXXXXXXXXXX";
//受理商ID,身份标识
public&static&String&MCHID&=&"XXXXXXXXXXXXxx";
//商户支付密钥Key。审核通过后,在微信发送的邮件中查看
public&static&String&KEY&=&"XXXXXXXXXXXXXXXXX";
//JSAPI接口中获取openid,审核后在公众平台开启开发模式后可查看
public&static&String&APPSECRET&=&"xxxxxxxxxxxxxx";
//重定向地址
public&static&String&REDIRECT_URL&=&"http://XXXXXXXXXXXXXXXXXXX/callWeiXinPay";
//异步回调地址
public&static&String&NOTIFY_URL&=&"http://XXXXXXXXXXXXXXXXXXXXXX/weixinPay_notify";
//web回调地址
public&static&String&WEB_NOTIFY_URL&=&"http://XXXXXXXXXXXXXXXXXXXXXXXXX/weixinPay_notify";
然后.就是正式的开始代码了:
1.使用Oauth2.0授权.进行页面跳转,获取code .(code关系着后面获取openid.)
https://open./connect/oauth2/authorize?appid=&redirect_uri=orderPay&response_type=code&scope=snsapi_base&state=#wechat_redirect
此处.appid 这个在微信官网可以获取. 重定向地址. 就是获取code 后.跳转指向你的地址.这里可以是你的订单结算页面.response_type=code和scope=snsapi_base 都是固定格式. & state 是传入传出.这个参数用户自定义为任何都可以,比如说订单id. 然后会和code 一起传递到你的重定向地址,如我上面写的重定向地址就是 orderPay链接.
2.在重定向到页面(orderPay)的时候中间执行java方法(如获取openid 如执行微信统一下单接口,获取预支付ID.).处理各种参数.下面贴具体代码做说明.
GzhService.java
String&code&=&request.getParameter("code");
String&state&=&request.getParameter("state");
Debug.log("code-======"+code+"===========state======"+state);
String&noncestr&=&Sha1Util.getNonceStr();//生成随机字符串
String&timestamp&=&Sha1Util.getTimeStamp();//生成1970年到现在的秒数.
//state&可以传递你的订单号.然后根据订单号&查询付款金额.我就不详细写了.
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
String&out_trade_no&=&//订单号
GenericValue&orderHeader&=&delegator.findOne("OrderHeader",&UtilMisc.toMap("orderId",&out_trade_no),false);
String&total_fee&=&String.valueOf(orderHeader.getBigDecimal("grandTotal").doubleValue()*100);
String&order_price&=&total_fee.substring(0,&total_fee.indexOf("."));//订单金额
//微信金额&以分为单位.这是第二坑.如果不注意.页面的报错.你基本看不出来.因为他提示系统升级,正在维护.扯淡.....
String&product_name=out_trade_//订单名称
//获取jsapi_ticket.此参数是为了生成&js&api&&加载时候的签名用.必须.jsapi_ticket只会存在7200秒.并且有时间限制,(好像一年还只能调用两万次.所以一定要缓存.)这是第三坑.
//可以在java中模拟url请求.就能获取access_token&然后根据access_token&取得&jsapi_ticket,但一定要缓存起来..这个代码.我只提供获取.缓存你们自己处理.
//SendGET方法我会在后面放出
String&tokenParam&=&"grant_type=client_credential&appid="+GzhConfig.APPID+"&secret="+GzhConfig.APPSECRET;
String&tokenJsonStr&=&SendGET("https://api./cgi-bin/token",&tokenParam);
Map&tokenMap&=&JSON.parseObject(tokenJsonStr);
//获取access_token
String&access_token&=&(String)tokenMap.get("access_token");
String&ticketParam&=&"access_token="+access_token+"&type=jsapi";
String&ticketJsonStr&=&SendGET("https://api./cgi-bin/ticket/getticket",&ticketParam);
Map&ticketMap&=&JSON.parseObject(ticketJsonStr);
//获取jsapi_ticket
String&ticket&=&(String)ticketMap.get("ticket");
&//下面就到了获取openid,这个代表用户id.
//获取openID
String&openParam&=&"appid="+GzhConfig.APPID+"&secret="+GzhConfig.APPSECRET+"&code="+code+"&grant_type=authorization_code";
String&openJsonStr&=&SendGET("https://api./sns/oauth2/access_token",&openParam);
Map&openMap&=&JSON.parseObject(openJsonStr);
String&openid&=&(String)&openMap.get("openid");
RequestHandler&reqHandler&=&new&RequestHandler(request,&response);
&//初始化&&&&&RequestHandler&&类可以在微信的文档中找到.还有相关工具类&&&&
reqHandler.init();
reqHandler.init(GzhConfig.APPID,&GzhConfig.APPSECRET,&GzhConfig.KEY,&"");
//执行统一下单接口&获得预支付id
reqHandler.setParameter("appid",GzhConfig.APPID);
reqHandler.setParameter("mch_id",&GzhConfig.MCHID);&&&&&&&&&&&&&&&&//商户号
reqHandler.setParameter("nonce_str",&noncestr);&&&&&&&&&&&&//随机字符串
reqHandler.setParameter("body",&product_name);&&&&&&&&&&&&&&&&&&&&&&&&//商品描述(必填.如果不填.也会提示系统升级.正在维护我艹.)
reqHandler.setParameter("out_trade_no",&out_trade_no);&&&&&&&&//商家订单号
reqHandler.setParameter("total_fee",&order_price);&&&&&&&&&&&&&&&&&&&&//商品金额,以分为单位
reqHandler.setParameter("spbill_create_ip",request.getRemoteAddr());&&&//用户的公网ip&&IpAddressUtil.getIpAddr(request)
//下面的notify_url是用户支付成功后为微信调用的action&&异步回调.
reqHandler.setParameter("notify_url",&GzhConfig.NOTIFY_URL);
reqHandler.setParameter("trade_type",&"JSAPI");
//------------需要进行用户授权获取用户openid-------------
reqHandler.setParameter("openid",&openid);&&&//这个必填.
//这里只是在组装数据.还没到执行到统一下单接口.因为统一下单接口的数据传递格式是xml的.所以才需要组装.
String&requestUrl&=&reqHandler.getRequestURL();
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&requestUrl&例子:
&xml&&appid&wx0ec43b&/appid&&attach&支付测试&/attach&&body&JSAPI支付测试&/body&&mch_id&&/mch_id&&nonce_str&1add1a30ac87aa2db72f57a2375d8fec&/nonce_str&&notify_url&http://wxpay./pub_v2/pay/notify.v2.php&/notify_url&&openid&oUpF8uMuAJO_M2pxb1Q9zNjWeS6o&/openid&&out_trade_no&&/out_trade_no&&spbill_create_ip&14.23.150.211&/spbill_create_ip&&total_fee&1&/total_fee&&trade_type&JSAPI&/trade_type&&sign&0CBEFBCA001&/sign&&/xml&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
Debug.log("requestUrl==================="+requestUrl);
//统一下单接口提交&&xml格式
URL&orderUrl&=&new&URL("https://api.mch./pay/unifiedorder");
HttpURLConnection&conn&=&(HttpURLConnection)&orderUrl.openConnection();
conn.setConnectTimeout(30000);&//&设置连接主机超时(单位:毫秒)
conn.setReadTimeout(30000);&//&设置从主机读取数据超时(单位:毫秒)
conn.setDoOutput(true);&//&post请求参数要放在http正文内,顾设置成true,默认是false
conn.setDoInput(true);&//&设置是否从httpUrlConnection读入,默认情况下是true
conn.setUseCaches(false);&//&Post&请求不能使用缓存
//&设定传送的内容类型是可序列化的java对象(如果不设此项,在传送序列化对象时,当WEB服务默认的不是这种类型时可能抛java.io.EOFException)
conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
conn.setRequestMethod("POST");//&设定请求的方法为"POST",默认是GET
conn.setRequestProperty("Content-Length",requestUrl.length()+"");
String&encode&=&"utf-8";
OutputStreamWriter&out&=&new&OutputStreamWriter(conn.getOutputStream(),&encode);
out.write(requestUrl.toString());
out.flush();
out.close();
String&result&=&getOut(conn);
Debug.log("result=========返回的xml============="+result);
Map&String,&String&&orderMap&=&XMLUtil.doXMLParse(result);
Debug.log("orderMap==========================="+orderMap);
//得到的预支付id
String&prepay_id&=&orderMap.get("prepay_id");
SortedMap&String,String&&params&=&new&TreeMap&String,String&();
params.put("appId",&GzhConfig.APPID);
params.put("timeStamp",timestamp);
params.put("nonceStr",&noncestr);
params.put("package",&"prepay_id="+prepay_id);
params.put("signType",&"MD5");
//生成支付签名,这个签名&给&微信支付的调用使用
String&paySign&=&&reqHandler.createSign(params);&&&&&&&&
request.setAttribute("paySign",&paySign);
request.setAttribute("appId",&GzhConfig.APPID);
request.setAttribute("timeStamp",&timestamp);&&&&&&&&//时间戳
request.setAttribute("nonceStr",&noncestr);&&&&&&&&&&&&//随机字符串
request.setAttribute("signType",&"MD5");&&&&&&&&//加密格式
request.setAttribute("out_trade_no",&out_trade_no);&&&&&&&&&&//订单号
request.setAttribute("package",&"prepay_id="+prepay_id);//预支付id&,就这样的格式.
String&url&=&"http://xxxxxxxxxx/control/wxPayment";
String&signValue&=&"jsapi_ticket="+ticket+"&noncestr="+noncestr+"&timestamp="+timestamp+"&url="+
Debug.log("url====="+signValue);
//这个签名.主要是给加载微信js使用.别和上面的搞混了.
String&signature&=&Sha1Util.getSha1((signValue));
request.setAttribute("signature",&signature);
&&&&&&&&&&&&&&&&
//此页面的一些其他方法
public&static&String&getOut(HttpURLConnection&conn)&throws&IOException{
&&&&&&&&if&(conn.getResponseCode()&!=&HttpURLConnection.HTTP_OK)&{
&&&&&&&&&&&&return&
&&&&&&&&//&获取响应内容体
&&&&&&&&BufferedReader&in&=&new&BufferedReader(new&InputStreamReader(
&&&&&&&&&&&&&&&&conn.getInputStream(),&"UTF-8"));
&&&&&&&&String&line&=&"";
&&&&&&&&StringBuffer&strBuf&=&new&StringBuffer();
&&&&&&&&while&((line&=&in.readLine())&!=&null)&{
&&&&&&&&&&&&strBuf.append(line).append("\n");
&&&&&&&&in.close();
&&&&&&&&return&&strBuf.toString().trim();
public&static&String&SendGET(String&url,String&param){
&&&String&result="";//访问返回结果
&&&BufferedReader&read=//读取访问结果
&&&&//创建url
&&&&URL&realurl=new&URL(url+"?"+param);
&&&&//打开连接
&&&&URLConnection&connection=realurl.openConnection();
&&&&&//&设置通用的请求属性
&&&&&&&&&&&&&connection.setRequestProperty("accept",&"*/*");
&&&&&&&&&&&&&connection.setRequestProperty("connection",&"Keep-Alive");
&&&&&&&&&&&&&connection.setRequestProperty("user-agent",
&&&&&&&&&&&&&&&&&&&&&"Mozilla/4.0&(&MSIE&6.0;&Windows&NT&5.1;SV1)");
&&&&&&&&&&&&&//建立连接
&&&&&&&&&&&&&connection.connect();
&&&&&&&&&&//&获取所有响应头字段
//&&&&&&&&&&&&&Map&String,&List&String&&&map&=&connection.getHeaderFields();
&&&&&&&&&&&&&//&遍历所有的响应头字段,获取到cookies等
//&&&&&&&&&&&&&for&(String&key&:&map.keySet())&{
//&&&&&&&&&&&&&&&&&System.out.println(key&+&"---&"&+&map.get(key));
//&&&&&&&&&&&&&}
&&&&&&&&&&&&&//&定义&BufferedReader输入流来读取URL的响应
&&&&&&&&&&&&&read&=&new&BufferedReader(new&InputStreamReader(
&&&&&&&&&&&&&&&&&&&&&connection.getInputStream(),"UTF-8"));
&&&&&&&&&&&&&String&//循环读取
&&&&&&&&&&&&&while&((line&=&read.readLine())&!=&null)&{
&&&&&&&&&&&&&&&&&result&+=&
&&&&&&&&&&&&&}
&&&}&catch&(IOException&e)&{
&&&&e.printStackTrace();
&&&}finally{
&&&&if(read!=null){//关闭流
&&&&&try&{
&&&&&&read.close();
&&&&&}&catch&(IOException&e)&{
&&&&&&e.printStackTrace();
&&&return&&
&&&&&&&&&&&&
&&&&&&&&&&&&其他相关类的方法:
&&&&&&&&&&&&
'============================================================================
'api说明:
'createSHA1Sign创建签名SHA1
'getSha1()Sha1签名
'============================================================================
public&class&Sha1Util&{
public&static&String&getNonceStr()&{
Random&random&=&new&Random();
return&MD5Util.MD5Encode(String.valueOf(random.nextInt(10000)),&"UTF-8");
public&static&String&getTimeStamp()&{
return&String.valueOf(System.currentTimeMillis()&/&1000);
&&&//创建签名SHA1
public&static&String&createSHA1Sign(SortedMap&String,&String&&signParams)&throws&Exception&{
StringBuffer&sb&=&new&StringBuffer();
Set&es&=&signParams.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();
sb.append(k&+&"="&+&v&+&"&");
//要采用URLENCODER的原始值!
String&params&=&sb.substring(0,&sb.lastIndexOf("&"));
System.out.println("sha1&sb:"&+&params);
return&getSha1(params);
//Sha1签名
public&static&String&getSha1(String&str)&{
if&(str&==&null&||&str.length()&==&0)&{
char&hexDigits[]&=&{&'0',&'1',&'2',&'3',&'4',&'5',&'6',&'7',&'8',&'9',
'a',&'b',&'c',&'d',&'e',&'f'&};
MessageDigest&mdTemp&=&MessageDigest.getInstance("SHA1");
mdTemp.update(str.getBytes("GBK"));
byte[]&md&=&mdTemp.digest();
int&j&=&md.
char&buf[]&=&new&char[j&*&2];
int&k&=&0;
for&(int&i&=&0;&i&&&j;&i++)&{
byte&byte0&=&md[i];
buf[k++]&=&hexDigits[byte0&&&&&4&&&0xf];
buf[k++]&=&hexDigits[byte0&&&0xf];
return&new&String(buf);
}&catch&(Exception&e)&{
&* xml工具类
public&class&XMLUtil&{
&*&解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。
&*&@param&&strxml
&*&@return&
&*&@throws&&JDOMException
&*&@throws&&IOException
public&static&Map&String,String&&doXMLParse(String&strxml)&throws&JDOMException,&IOException&{
if(null&==&strxml&||&"".equals(strxml))&{
Map&String,String&&m&=&new&HashMap&String,String&();
InputStream&in&=&HttpClientUtil.String2Inputstream(strxml);
SAXBuilder&builder&=&new&SAXBuilder();
Document&doc&=&builder.build(in);
Element&root&=&doc.getRootElement();
List&list&=&root.getChildren();
Iterator&it&=&list.iterator();
while(it.hasNext())&{
Element&e&=&(Element)&it.next();
String&k&=&e.getName();
String&v&=&"";
List&children&=&e.getChildren();
if(children.isEmpty())&{
v&=&e.getTextNormalize();
v&=&XMLUtil.getChildrenText(children);
m.put(k,&v);
in.close();
&*&获取子结点的xml
&*&@param&children
&*&@return&String
public&static&String&getChildrenText(List&children)&{
StringBuffer&sb&=&new&StringBuffer();
if(!children.isEmpty())&{
Iterator&it&=&children.iterator();
while(it.hasNext())&{
Element&e&=&(Element)&it.next();
String&name&=&e.getName();
String&value&=&e.getTextNormalize();
List&list&=&e.getChildren();
sb.append("&"&+&name&+&"&");
if(!list.isEmpty())&{
sb.append(XMLUtil.getChildrenText(list));
sb.append(value);
sb.append("&/"&+&name&+&"&");
return&sb.toString();
&*&获取xml编码字符集
&*&@param&strxml
&*&@return
&*&@throws&IOException&
&*&@throws&JDOMException&
public&static&String&getXMLEncoding(String&strxml)&throws&JDOMException,&IOException&{
InputStream&in&=&HttpClientUtil.String2Inputstream(strxml);
SAXBuilder&builder&=&new&SAXBuilder();
Document&doc&=&builder.build(in);
in.close();
return&(String)doc.getProperty("encoding");
&*&Http客户端工具类&br/&
&*&这是内部调用类,请不要在外部调用。
&*&@author&miklchen
import&java.io.BufferedR
import&java.io.ByteArrayInputS
import&java.io.F
import&java.io.FileInputS
import&java.io.IOE
import&java.io.InputS
import&java.io.OutputS
import&java.net.HttpURLC
import&java.net.URL;
import&java.security.KeyManagementE
import&java.security.KeyS
import&java.security.KeyStoreE
import&java.security.NoSuchAlgorithmE
import&java.security.SecureR
import&java.security.UnrecoverableKeyE
import&java.security.cert.C
import&java.security.cert.CertificateE
import&java.security.cert.CertificateF
import&java.util.HashM
import&java.util.M
import&javax.net.ssl.HttpsURLC
import&javax.net.ssl.KeyManagerF
import&javax.net.ssl.SSLC
import&javax.net.ssl.TrustManagerF
public&class&HttpClientUtil&{
public&static&final&String&SunX509&=&"SunX509";
public&static&final&String&JKS&=&"JKS";
public&static&final&String&PKCS12&=&"PKCS12";
public&static&final&String&TLS&=&"TLS";
&*&get&HttpURLConnection
&*&@param&strUrl&url地址
&*&@return&HttpURLConnection
&*&@throws&IOException
public&static&HttpURLConnection&getHttpURLConnection(String&strUrl)
throws&IOException&{
URL&url&=&new&URL(strUrl);
HttpURLConnection&httpURLConnection&=&(HttpURLConnection)&url
.openConnection();
return&httpURLC
&*&get&HttpsURLConnection
&*&@param&strUrl&url地址
&*&@return&HttpsURLConnection
&*&@throws&IOException
public&static&HttpsURLConnection&getHttpsURLConnection(String&strUrl)
throws&IOException&{
URL&url&=&new&URL(strUrl);
HttpsURLConnection&httpsURLConnection&=&(HttpsURLConnection)&url
.openConnection();
return&httpsURLC
&*&获取不带查询串的url
&*&@param&strUrl
&*&@return&String
public&static&String&getURL(String&strUrl)&{
if(null&!=&strUrl)&{
int&indexOf&=&strUrl.indexOf("?");
if(-1&!=&indexOf)&{
return&strUrl.substring(0,&indexOf);
return&strU
return&strU
&*&获取查询串
&*&@param&strUrl
&*&@return&String
public&static&String&getQueryString(String&strUrl)&{
if(null&!=&strUrl)&{
int&indexOf&=&strUrl.indexOf("?");
if(-1&!=&indexOf)&{
return&strUrl.substring(indexOf+1,&strUrl.length());
return&"";
return&strU
&*&查询字符串转换成Map&br/&
&*&name1=key1&name2=key2&...
&*&@param&queryString
&*&@return
public&static&Map&queryString2Map(String&queryString)&{
if(null&==&queryString&||&"".equals(queryString))&{
Map&m&=&new&HashMap();
String[]&strArray&=&queryString.split("&");
for(int&index&=&0;&index&&&strArray.&index++)&{
String&pair&=&strArray[index];
HttpClientUtil.putMapByPair(pair,&m);
&*&把键值添加至Map&br/&
&*&pair:name=value
&*&@param&pair&name=value
&*&@param&m
public&static&void&putMapByPair(String&pair,&Map&m)&{
if(null&==&pair&||&"".equals(pair))&{
int&indexOf&=&pair.indexOf("=");
if(-1&!=&indexOf)&{
String&k&=&pair.substring(0,&indexOf);
String&v&=&pair.substring(indexOf+1,&pair.length());
if(null&!=&k&&&&!"".equals(k))&{
m.put(k,&v);
m.put(pair,&"");
&*&BufferedReader转换成String&br/&
&*&注意:流关闭需要自行处理
&*&@param&reader
&*&@return&String
&*&@throws&IOException
public&static&String&bufferedReader2String(BufferedReader&reader)&throws&IOException&{
StringBuffer&buf&=&new&StringBuffer();
String&line&=&
while(&(line&=&reader.readLine())&!=&null)&{
buf.append(line);
buf.append("\r\n");
return&buf.toString();
&*&处理输出&br/&
&*&注意:流关闭需要自行处理
&*&@param&out
&*&@param&data
&*&@param&len
&*&@throws&IOException
public&static&void&doOutput(OutputStream&out,&byte[]&data,&int&len)&
throws&IOException&{
int&dataLen&=&data.
int&off&=&0;
while(off&&&dataLen)&{
if(len&&=&dataLen)&{
out.write(data,&off,&dataLen);
out.write(data,&off,&len);
//刷新缓冲区
out.flush();
dataLen&-=&
&*&获取SSLContext
&*&@param&trustFile&
&*&@param&trustPasswd
&*&@param&keyFile
&*&@param&keyPasswd
&*&@return
&*&@throws&NoSuchAlgorithmException&
&*&@throws&KeyStoreException&
&*&@throws&IOException&
&*&@throws&CertificateException&
&*&@throws&UnrecoverableKeyException&
&*&@throws&KeyManagementException&
public&static&SSLContext&getSSLContext(
FileInputStream&trustFileInputStream,&String&trustPasswd,
FileInputStream&keyFileInputStream,&String&keyPasswd)
throws&NoSuchAlgorithmException,&KeyStoreException,
CertificateException,&IOException,&UnrecoverableKeyException,
KeyManagementException&{
TrustManagerFactory&tmf&=&TrustManagerFactory.getInstance(HttpClientUtil.SunX509);
KeyStore&trustKeyStore&=&KeyStore.getInstance(HttpClientUtil.JKS);
trustKeyStore.load(trustFileInputStream,&HttpClientUtil
.str2CharArray(trustPasswd));
tmf.init(trustKeyStore);
final&char[]&kp&=&HttpClientUtil.str2CharArray(keyPasswd);
KeyManagerFactory&kmf&=&KeyManagerFactory.getInstance(HttpClientUtil.SunX509);
KeyStore&ks&=&KeyStore.getInstance(HttpClientUtil.PKCS12);
ks.load(keyFileInputStream,&kp);
kmf.init(ks,&kp);
SecureRandom&rand&=&new&SecureRandom();
SSLContext&ctx&=&SSLContext.getInstance(HttpClientUtil.TLS);
ctx.init(kmf.getKeyManagers(),&tmf.getTrustManagers(),&rand);
&*&获取CA证书信息
&*&@param&cafile&CA证书文件
&*&@return&Certificate
&*&@throws&CertificateException
&*&@throws&IOException
public&static&Certificate&getCertificate(File&cafile)
throws&CertificateException,&IOException&{
CertificateFactory&cf&=&CertificateFactory.getInstance("X.509");
FileInputStream&in&=&new&FileInputStream(cafile);
Certificate&cert&=&cf.generateCertificate(in);
in.close();
&*&字符串转换成char数组
&*&@param&str
&*&@return&char[]
public&static&char[]&str2CharArray(String&str)&{
if(null&==&str)&return&
return&str.toCharArray();
&*&存储ca证书成JKS格式
&*&@param&cert
&*&@param&alias
&*&@param&password
&*&@param&out
&*&@throws&KeyStoreException
&*&@throws&NoSuchAlgorithmException
&*&@throws&CertificateException
&*&@throws&IOException
public&static&void&storeCACert(Certificate&cert,&String&alias,
String&password,&OutputStream&out)&throws&KeyStoreException,
NoSuchAlgorithmException,&CertificateException,&IOException&{
KeyStore&ks&=&KeyStore.getInstance("JKS");
ks.load(null,&null);
ks.setCertificateEntry(alias,&cert);
//&store&keystore
ks.store(out,&HttpClientUtil.str2CharArray(password));
public&static&InputStream&String2Inputstream(String&str)&{
return&new&ByteArrayInputStream(str.getBytes());
&RequestHandler.java
import&java.io.UnsupportedEncodingE
import&java.net.URLE
import&java.util.I
import&java.util.M
import&java.util.S
import&java.util.SortedM
import&java.util.TreeM
import&javax.servlet.http.HttpServletR
import&javax.servlet.http.HttpServletR
&'微信支付服务器签名支付请求请求类
&'============================================================================
&'api说明:
&'init(app_id,&app_secret,&partner_key,&app_key);
&'初始化函数,默认给一些参数赋值,如cmdno,date等。
&'setKey(key_)'设置商户密钥
&'getLasterrCode(),获取最后错误号
&'GetToken();获取Token
&'getTokenReal();Token过期后实时获取Token
&'createMd5Sign(signParams);生成Md5签名
&'genPackage(packageParams);获取package包
&'createSHA1Sign(signParams);创建签名SHA1
&'sendPrepay(packageParams);提交预支付
&'getDebugInfo(),获取debug信息
&'============================================================================
public&class&RequestHandler&{
/**&Token获取网关地址地址&*/
private&String&tokenU
/**&预支付网关url地址&*/
private&String&gateU
/**&查询支付通知网关URL&*/
private&String&notifyU
/**&商户参数&*/
private&String&
private&String&
private&String&
private&String&
private&String&
/**&请求的参数&*/
private&SortedMap&
/**&Token&*/
private&String&T
private&String&
/**&debug信息&*/
private&String&debugI
private&String&last_
private&HttpServletRequest&
private&HttpServletResponse&
&*&初始构造函数。
&*&@return
public&RequestHandler(HttpServletRequest&request,
HttpServletResponse&response)&{
this.last_errcode&=&"0";
this.request&=&
this.response&=&
this.charset&=&"GBK";
this.parameters&=&new&TreeMap();
//&验证notify支付订单网关
notifyUrl&=&"/gateway/simpleverifynotifyid.xml";
&*&初始化函数。
public&void&init(String&app_id,&String&app_secret,&String&app_key,
String&partner_key)&{
this.last_errcode&=&"0";
this.Token&=&"token_";
this.debugInfo&=&"";
this.appkey&=&app_
this.appid&=&app_
this.partnerkey&=&partner_
this.appsecret&=&app_
public&void&init()&{
&*&获取最后错误号
public&String&getLasterrCode()&{
return&last_
&*获取入口地址,不包含参数值
public&String&getGateUrl()&{
return&gateU
&*&获取参数值
&*&@param&parameter
&*&&&&&&&&&&&&参数名称
&*&@return&String
public&String&getParameter(String&parameter)&{
String&s&=&(String)&this.parameters.get(parameter);
return&(null&==&s)&?&""&:&s;
&&&&&*&设置参数值
&&&&&*&@param&parameter&参数名称
&&&&&*&@param&parameterValue&参数值
&&&&public&void&setParameter(String&parameter,&String&parameterValue)&{
&&&&&&&&String&v&=&"";
&&&&&&&&if(null&!=&parameterValue)&{
&&&&&&&&&&&&v&=&parameterValue.trim();
&&&&&&&&this.parameters.put(parameter,&v);
&//设置密钥
public&void&setKey(String&key)&{
this.partnerkey&=&
//设置微信密钥
public&void&&setAppKey(String&key){
this.appkey&=&
//&特殊字符处理
public&String&UrlEncode(String&src)&throws&UnsupportedEncodingException&{
return&URLEncoder.encode(src,&this.charset).replace("+",&"%20");
//&获取package的签名包
public&String&genPackage(SortedMap&String,&String&&packageParams)
throws&UnsupportedEncodingException&{
String&sign&=&createSign(packageParams);
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();
sb.append(k&+&"="&+&UrlEncode(v)&+&"&");
//&去掉最后一个&
String&packageValue&=&sb.append("sign="&+&sign).toString();
System.out.println("packageValue="&+&packageValue);
return&packageV
&*&创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
public&String&createSign(SortedMap&String,&String&&packageParams)&{
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="&+&GzhConfig.KEY);
System.out.println("md5&sb:"&+&sb);
String&sign&=&MD5Util.MD5Encode(sb.toString(),&this.charset)
.toUpperCase();
&*&创建package签名
public&boolean&createMd5Sign(String&signParams)&{
StringBuffer&sb&=&new&StringBuffer();
Set&es&=&this.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&(!"sign".equals(k)&&&&null&!=&v&&&&!"".equals(v))&{
sb.append(k&+&"="&+&v&+&"&");
//&算出摘要
String&enc&=&TenpayUtil.getCharacterEncoding(this.request,
this.response);
String&sign&=&MD5Util.MD5Encode(sb.toString(),&enc).toLowerCase();
String&tenpaySign&=&this.getParameter("sign").toLowerCase();
//&debug信息
this.setDebugInfo(sb.toString()&+&"&=&&sign:"&+&sign&+&"&tenpaySign:"
+&tenpaySign);
return&tenpaySign.equals(sign);
public&String&getRequestURL()&throws&UnsupportedEncodingException&{&&&&&&&&
&&&&&&&&this.createSign();&&&&&&&&
&&&&&&&&StringBuffer&sb&=&new&StringBuffer();
&&&&&&&&sb.append("&xml&");
&&&&&&&&String&enc&=&TenpayUtil.getCharacterEncoding(this.request,&this.response);
&&&&&&&&Set&es&=&this.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();
protected&void&createSign()&{
&&&&&&&&StringBuffer&sb&=&new&StringBuffer();
&&&&&&&&Set&es&=&this.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(null&!=&v&&&&!"".equals(v)
&&&&&&&&&&&&&&&&&&&&&&&!"sign".equals(k)&&&&!"key".equals(k))&{
&&&&&&&&&&&&&&&&sb.append(k&+&"="&+&v&+&"&");
&&&&&&&&&&&&}
&&&&&&&&sb.append("key="&+&GzhConfig.KEY);&//自己的API密钥&&&&&&
&&&&&&&&String&enc&=&TenpayUtil.getCharacterEncoding(this.request,&this.response);
&&&&&&&&String&sign&=&MD5Util.MD5Encode(sb.toString(),&enc).toUpperCase();
&&&&&&&&this.setParameter("sign",&sign);&&&&&&&&&&&&&&
&&&&//输出XML
&&&public&String&parseXML()&{
&&&StringBuffer&sb&=&new&StringBuffer();
&&&&&&&sb.append("&xml&");
&&&&&&&Set&es&=&this.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(null&!=&v&&&&!"".equals(v)&&&&!"appkey".equals(k))&{
sb.append("&"&+&k&+"&"&+&getParameter(k)&+&"&/"&+&k&+&"&\n");
&&&&&&&sb.append("&/xml&");
return&sb.toString();
&*&设置debug信息
protected&void&setDebugInfo(String&debugInfo)&{
this.debugInfo&=&debugI
public&void&setPartnerkey(String&partnerkey)&{
this.partnerkey&=&
public&String&getDebugInfo()&{
return&debugI
public&String&getKey()&{
public&static&String&setXML(String&return_code,&String&return_msg)&{
&&&&&&&&return&"&xml&&return_code&&![CDATA["&+&return_code
&&&&&&&&&&&&&&&&+&"]]&&/return_code&&return_msg&&![CDATA["&+&return_msg
&&&&&&&&&&&&&&&&+&"]]&&/return_msg&&/xml&";
TenpayUtil
import&java.text.SimpleDateF
import&java.util.D
import&javax.servlet.http.HttpServletR
import&javax.servlet.http.HttpServletR
public&class&TenpayUtil&{
private&static&Object&S
private&static&String&QRfromG
&*&把对象转换成字符串
&*&@param&obj
&*&@return&String&转换成字符串,若对象为null,则返回空字符串.
public&static&String&toString(Object&obj)&{
if(obj&==&null)
return&"";
return&obj.toString();
&*&把对象转换为int数值.
&*&@param&obj
&*&&&&&&&&&&&&包含数字的对象.
&*&@return&int&转换后的数值,对不能转换的对象返回0。
public&static&int&toInt(Object&obj)&{
int&a&=&0;
if&(obj&!=&null)
a&=&Integer.parseInt(obj.toString());
}&catch&(Exception&e)&{
&*&获取当前时间&yyyyMMddHHmmss
&*&@return&String
public&static&String&getCurrTime()&{
Date&now&=&new&Date();
SimpleDateFormat&outFormat&=&new&SimpleDateFormat("yyyyMMddHHmmss");
String&s&=&outFormat.format(now);
&*&获取当前日期&yyyyMMdd
&*&@param&date
&*&@return&String
public&static&String&formatDate(Date&date)&{
SimpleDateFormat&formatter&=&new&SimpleDateFormat("yyyyMMdd");
String&strDate&=&formatter.format(date);
return&strD
&*&取出一个指定长度大小的随机正整数.
&*&@param&length
&*&&&&&&&&&&&&int&设定所取出随机数的长度。length小于11
&*&@return&int&返回生成的随机数。
public&static&int&buildRandom(int&length)&{
int&num&=&1;
double&random&=&Math.random();
if&(random&&&0.1)&{
random&=&random&+&0.1;
for&(int&i&=&0;&i&&&&i++)&{
num&=&num&*&10;
return&(int)&((random&*&num));
&*&获取编码字符集
&*&@param&request
&*&@param&response
&*&@return&String
public&static&String&getCharacterEncoding(HttpServletRequest&request,
HttpServletResponse&response)&{
if(null&==&request&||&null&==&response)&{
return&"gbk";
String&enc&=&request.getCharacterEncoding();
if(null&==&enc&||&"".equals(enc))&{
enc&=&response.getCharacterEncoding();
if(null&==&enc&||&"".equals(enc))&{
enc&=&"gbk";
public&&static&String&URLencode(String&content){
String&URL
URLencode=&replace(Server.equals(content),&"+",&"%20");
return&URL
private&static&String&replace(boolean&equals,&String&string,&String&string2)&{
&*&获取unix时间,从&00:00:00开始的秒数
&*&@param&date
&*&@return&long
public&static&long&getUnixTime(Date&date)&{
if(&null&==&date&)&{
return&date.getTime()/1000;
&public&static&String&QRfromGoogle(String&chl)
&&&&&&&&int&widhtHeight&=&300;
&&&&&&&&String&EC_level&=&"L";
&&&&&&&&int&margin&=&0;
&&&&&&&&String&QRfromG
&&&&&&&&chl&=&URLencode(chl);
&&&&&&&&QRfromGoogle&=&"http://chart./chart?chs="&+&widhtHeight&+&"x"&+&widhtHeight&+&"&cht=qr&chld="&+&EC_level&+&"|"&+&margin&+&"&chl="&+&
&&&&&&&&return&QRfromG
&*&时间转换成字符串
&*&@param&date&时间
&*&@param&formatType&格式化类型
&*&@return&String
public&static&String&date2String(Date&date,&String&formatType)&{
SimpleDateFormat&sdf&=&new&SimpleDateFormat(formatType);
return&sdf.format(date);
public&class&MD5Util&{
private&static&String&byteArrayToHexString(byte&b[])&{
StringBuffer&resultSb&=&new&StringBuffer();
for&(int&i&=&0;&i&&&b.&i++)
resultSb.append(byteToHexString(b[i]));
return&resultSb.toString();
private&static&String&byteToHexString(byte&b)&{
int&n&=&b;
if&(n&&&0)
int&d1&=&n&/&16;
int&d2&=&n&%&16;
return&hexDigits[d1]&+&hexDigits[d2];
public&static&String&MD5Encode(String&origin,&String&charsetname)&{
String&resultString&=&
resultString&=&new&String(origin);
MessageDigest&md&=&MessageDigest.getInstance("MD5");
if&(charsetname&==&null&||&"".equals(charsetname))
resultString&=&byteArrayToHexString(md.digest(resultString
.getBytes()));
resultString&=&byteArrayToHexString(md.digest(resultString
.getBytes(charsetname)));
}&catch&(Exception&exception)&{
return&resultS
private&static&final&String&hexDigits[]&=&{&"0",&"1",&"2",&"3",&"4",&"5",
"6",&"7",&"8",&"9",&"a",&"b",&"c",&"d",&"e",&"f"&};
下面才到了页面代码:jsp 页面
&script&type="text/javascript"&src="/xxxx/jquery-1.6.2.min.js"&&/script&
&script&src="http://res./open/js/jweixin-1.0.0.js"&&/script&
&script&language="javascript"&
wx.config({
&&&&debug:&true,&//&开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
&&&&appId:&'${StringUtil.wrapString(requestAttributes.appId)!}',&//&必填,公众号的唯一标识
&&&&timestamp:&${StringUtil.wrapString(requestAttributes.timeStamp)?default(0)!},&//&必填,生成签名的时间戳
&&&&nonceStr:&'${StringUtil.wrapString(requestAttributes.nonceStr)!}',&//&必填,生成签名的随机串
&&&&signature:&'${StringUtil.wrapString(requestAttributes.signature)!}',//&必填,签名,见附录1
&&&&jsApiList:&[
&&&&'checkJsApi',
&&&&&&&&&&&&'chooseWXPay']&//&必填,需要使用的JS接口列表,所有JS接口列表见附录2
wx.ready(function(){
wx.chooseWXPay({
&&&&timestamp:&${StringUtil.wrapString(requestAttributes.timeStamp)?default(0)!},&//&支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
&&&&nonceStr:&'${StringUtil.wrapString(requestAttributes.nonceStr)!}',&//&支付签名随机串,不长于&32&位
&&&&package:&'${StringUtil.wrapString(requestAttributes.package)!}',&//&统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=***)
&&&&signType:&'${StringUtil.wrapString(requestAttributes.signType)!}',&//&签名方式,默认为'SHA1',使用新版支付需传入'MD5'
&&&&paySign:&'${StringUtil.wrapString(requestAttributes.paySign)!}',&//&支付签名
&&&&success:&function&(res)&{
&&&&&&&&//&支付成功后的回调函数
&&&&&&&&WeixinJSBridge.log(res.err_msg);
&&&&&&&&//alert("支付接口:"+res.err_code&+&res.err_desc&+&res.err_msg);
&&&&&&&&if(!res.err_msg){
&&&&&&&&&&&&&&&&&&&&//支付完后.跳转到成功页面.
&&&&&&&&location.href="orderconfirm?orderId=${StringUtil.wrapString(requestAttributes.out_trade_no)!}";
&&&&//&config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
wx.error(function(res){
&&&&//&config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
wx.checkJsApi({
&&&&jsApiList:&['chooseWXPay'],&//&需要检测的JS接口列表,所有JS接口列表见附录2,
&&&&success:&function(res)&{
&&&&//alert("检测接口:"+res.err_msg);
下面是后台异步回调代码:
&*&异步返回
@SuppressWarnings("deprecation")
public&static&String&weixinNotify(HttpServletRequest&request,&HttpServletResponse&response){
&&&&&&&&try&{
InputStream&inStream&=&request.getInputStream();
ByteArrayOutputStream&outSteam&=&new&ByteArrayOutputStream();
byte[]&buffer&=&new&byte[1024];
int&len&=&0;
while&((len&=&inStream.read(buffer))&!=&-1)&{
&&&&outSteam.write(buffer,&0,&len);
outSteam.close();
inStream.close();
String&resultStr&&=&new&String(outSteam.toByteArray(),"utf-8");
Map&String,&String&&resultMap&=&XMLUtil.doXMLParse(resultStr);
String&result_code&=&resultMap.get("result_code");
String&is_subscribe&=&resultMap.get("is_subscribe");
String&out_trade_no&=&resultMap.get("out_trade_no");
String&transaction_id&=&resultMap.get("transaction_id");
String&sign&=&resultMap.get("sign");
String&time_end&=&resultMap.get("time_end");
String&bank_type&=&resultMap.get("bank_type");
String&return_code&=&resultMap.get("return_code");
//签名验证
GenericValue&userLogin&=delegator.findOne("UserLogin",&UtilMisc.toMap("userLoginId","admin"),false);
if(return_code.equals("SUCCESS")){
&&&&//此处就是你的逻辑代码
&request.setAttribute("out_trade_no",&out_trade_no);
//通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
response.getWriter().write(RequestHandler.setXML("SUCCESS",&""));
}&catch&(UnsupportedEncodingException&e)&{&
e.printStackTrace();
}&catch&(IOException&e)&{
e.printStackTrace();
}&catch&(JDOMException&e)&{
e.printStackTrace();
return&"success";
&&&&&&&&代码中,删除了一些和公司相关的代码.所以如果直接复制进去.肯定是要做大量修改的.见谅.
更多开发者职位上
1)">1)">1" ng-class="{current:{{currentPage==page}}}" ng-repeat="page in pages"><li class='page' ng-if="(endIndex<li class='page next' ng-if="(currentPage
相关文章阅读

我要回帖

更多关于 微信公众号支付 的文章

 

随机推荐