一.说明
公司最近要做微信支付的功能,看了网上的许多的博客,说的不是很具体,这里总结下,以比较具体的方式总结下微信支付开发流程,总的来说分为两个过程,第一个是
生成微信JSSDK的签名,这个过程是用来拉起微信支付的框框的,第二个是预支付ID的生成,这个是用来真正支付的。好了,下面介绍这两个模块的开发过程
二。微信支付
1.生成微信JSSDK的签名
这个过程需要我们后台为前台生成一些参数,好让他可以拉起微信支付的框框,由于这个过程可能会涉及安全问题,最好在后台完成
下面附上代码
/**
* 取得config
* @param request
* @param response
* @return
*/
@RequestMapping("getPayConfig")
public String weiXinPayConfig(HttpServletRequest request,HttpServletResponse response) {
Map config = new TreeMap();
String url = request.getRequestURL().toString();
String configStr=null;
PrepayIdRequestHandler prepayReqHandler = new PrepayIdRequestHandler(request, response);
String noncestr = WXUtil.getNonceStr();
String timestamp = WXUtil.getTimeStamp();
//获得token
String token = AccessTokenRequestHandler.getAccessToken();
String jsapi_ticket= getJsapi_ticket(token);
config.put("jsapi_ticket",jsapi_ticket);
config.put("timestamp",timestamp);
config.put("noncestr",noncestr);
config.put("url","这里的链接其实不写也可以,反正我是没看到有什么用");
try {
String sign = prepayReqHandler.createSHA1Sign(config);
config.put("appId",ConstantUtil.getApp_Id());
config.put("signature",sign);
config.remove("jsapi_ticket");
ObjectMapper om = new ObjectMapper();
JSONObject jsonObject = JSONObject.fromObject(config);
configStr=jsonObject.toString();
} catch (Exception e) {
e.printStackTrace();
return "error";
}
return configStr;
}
注意我们这里是使用Map来存储这些参数的,因为他们满足键值对的结构,timestamp区系统时间就好了,nocestr是随机字符串,可以用UUID生成,这些在官方的api中都有
后面附上下载链接,值得注意的是token,jsapi_ticket,signature的生成,这里有个不错的博客可以参考,如下 微信JSSDK生成签名
最有我们把Map转换成json字符串返回给前台就可以了,我是返回Json的,你也可以返回Map,只要前台能处理你返回的数据就可以了,这样前台就能拉起微信支付的框框了
2.生成预支付Id
前面的处理是为了完成支付框的拉起工作,下一步是真正的支付环节了,代码如下:
@RequestMapping("prepay")
public String doWeinXinRequest(HttpServletRequest request,HttpServletResponse response,String unionId) throws Exception {
// unionId = "ortat1BVmZBBX7eZ4Ru9l5vWMBnw";
Map resInfo = new HashMap();
//设置响应的url
String notify_url = ConstantUtil.getNotify_url();
System.out.println(notify_url);
String resultJson=null;
//---------------生成订单号 开始------------------------
//当前时间 yyyyMMddHHmmss
String currTime = TenpayUtil.getCurrTime();
//8位日期
String strTime = currTime.substring(8, currTime.length());
//四位随机数
String strRandom = TenpayUtil.buildRandom(4) + "";
//10位序列号,可以自行调整。
String strReq = strTime + strRandom;
//订单号,此处用时间加随机数生成,商户根据自己情况调整,只要保持全局唯一就行
String out_trade_no = strReq;
//---------------生成订单号 结束------------------------
PrepayIdRequestHandler prepayReqHandler = new PrepayIdRequestHandler(request, response);//获取prepayid的请求类
//ClientRequestHandler clientHandler = new ClientRequestHandler(request, response);//返回客户端支付参数的请求类
int retcode;
String retmsg = "";
String xml_body = "";
//获取token值
String token = AccessTokenRequestHandler.getAccessToken();
// log.info("获取token------值 " + token);
if (!"".equals(token)) {
String noncestr = WXUtil.getNonceStr();
String timestamp = WXUtil.getTimeStamp();
//获取微信端的openId
String openId = userService.getOpenIdByUnion_id(unionId, User.WEIXINStatus);
System.out.println(openId);
prepayReqHandler.setParameter("appid", ConstantUtil.getApp_Id());
prepayReqHandler.setParameter("mch_id", ConstantUtil.getPartner());
prepayReqHandler.setParameter("device_info", "WEB"); //商品描述
prepayReqHandler.setParameter("nonce_str", noncestr);
prepayReqHandler.setParameter("body",new String(ConstantUtil.getBody().getBytes("ISO-8859-1"),"UTF-8")); //商品描述
prepayReqHandler.setParameter("out_trade_no", out_trade_no); //商家订单号
prepayReqHandler.setParameter("total_fee",ConstantUtil.getTotal_fee()); //商品金额,以分为单位
prepayReqHandler.setParameter("spbill_create_ip", request.getRemoteAddr());
prepayReqHandler.setParameter("notify_url", notify_url); //接收财付通通知的URL
prepayReqHandler.setParameter("trade_type", "JSAPI");
prepayReqHandler.setParameter("openid", openId);
String sign = generateSignature(prepayReqHandler.getAllParameters(), ConstantUtil.getPartner_key(), "MD5");
System.out.println("sign:----->" + sign);
//log.info("获取package------值 " + packageValue);
prepayReqHandler.setParameter("sign", sign);
String gateUrl = ConstantUtil.getGateurl();
prepayReqHandler.setGateUrl(gateUrl);
//获取prepayId
String prepayid = prepayReqHandler.sendPrepay();
System.out.println("获取prepayid------值 " + prepayid);
if(prepayid!=null){
Map returnMap = new LinkedHashMap<>();
returnMap.put("appId", ConstantUtil.getApp_Id());
returnMap.put("timeStamp", timestamp);
returnMap.put("nonceStr", noncestr);
returnMap.put("package", "prepay_id="+prepayid);
returnMap.put("signType", "MD5");
sign = generateSignature(returnMap, ConstantUtil.getPartner_key(), "MD5");
returnMap.put("paySign", sign);
ObjectMapper om = new ObjectMapper();
resultJson = om.writeValueAsString(returnMap);
System.out.println(resultJson);
}
return resultJson;
}else{
return ConstantUtil.getFail_errcode();
}
}
我们看到,我们为了获取预支付Id需要准备一系列参数,其中 appId,mch_Id可以直接问申请微信的人要就可以了,编码一定要使用MD5的如果提示签名错误,可以使用
z官方签名校验工具来测试,但是加密方式必须是MD5的,商品名称body必须是UTF-8编码的,其中你在请求微信接口时,也要保证你的编码也是UTF-8的,注意必须把这些
参数转成xml的格式给微信接口才行,不能是json,最后,接口就会返回预支付Id和,注意他返回的也是xml,所有也要用做xml转换,最后把预支付ID和相关参数发到前台,
前台调用相关微信api即可完成支付,过程其实就是这样的了
的v