微信支付(JS API) JAVA
2015-07-06 14:36
567 查看
基于微信支付文档V3.3.7进行编码,使用JS API(网页内)并测试通过,应用在项目中。
Form:
请求支付的Action:
微信支付结果回调请求的Action:
Service:
TenPayUtil:
weChatPay.jsp
Form:
public class PayForm extends BaseForm{ private String code; //通过code换取微信的openid,谁支付的 private Integer transactionID; //交易ID private String appId; //公众账号ID private String timeStamp; //时间戳 private String nonceStr; //随机字符串 private String packages; //订单详情扩展字符串 private String paySign; //签名 private String openid; //微信openid private Integer masterOrderID; //订单ID //set get }
请求支付的Action:
@ParentPackage("main") @Namespace("/pay") @Controller public class PayAction extends BaseAction{ private PayForm form; @Resource private TransactionService transactionService; @Action(value = "weChatPay", results = { @Result(name = SUCCESS, location = "/html/transaction/jsp/weChatPay.jsp"), @Result(name = ERROR , location = "/html/common/errors/sys_error.jsp")} ) public String weChatPay(){ SystemLogger.info("用户请求支付订单号:"+form.getTransactionID()); if (StringUtils.isNotEmpty(form.getCode())) { String url = WeixinUtil.getUrl().replace("CODE", form.getCode()); String openid =""; try { Map<String, Object> map = JsonUtil.getMapByUrl(url); openid = map.get("openid").toString(); form.setOpenid(openid); } catch (Exception e) { SystemLogger.info("用户请求支付订单号:"+form.getTransactionID()+"时拉取微信用户信息失败"); } try { transactionService.createWeChatRequest(form); return SUCCESS; } catch (BusinessException e) { SystemLogger.error(e.getMessage()); form.setMessage(e.getMessage()); return ERROR; } }else{ SystemLogger.info("用户请求支付订单号:"+form.getTransactionID()+"的链接为非法链接,已拒绝"); form.setMessage("请通过合法链接进行订单支付"); return ERROR; } } @Override public Object getModel() { if(form==null){ form = new PayForm(); } return form; } }
微信支付结果回调请求的Action:
@ParentPackage("main") @Namespace("/pay") @Controller public class NotifyAction { @Resource private TransactionService transactionService; @Action(value = "notify", results = { @Result(name = "success", type = "plainText",params = { "charSet", "UTF-8"})}, interceptorRefs = { @InterceptorRef("defaultStack")} ) public String weChatNotify(){ Map<String, String> requestMap = null; SortedMap<String, String> returnMap = new TreeMap<String, String>(); String requestXML = ""; try { requestMap = TenPayUtil.parseXml(ServletActionContext.getRequest()); SystemLogger.info("接收到的微信支付回调通知:"+requestMap.toString()); SortedMap<String, String> map = new TreeMap<String, String>(); map.putAll(requestMap); String weixinSign = map.get("sign"); map.remove("sign"); String sign = TenPayUtil.sign(map, WeixinUtil.partnerKey); if(!sign.equals(weixinSign)){ SystemLogger.info("签名失败"); returnMap.put("return_code", "FAIL"); returnMap.put("return_msg", "签名失败"); requestXML = TenPayUtil.getRequestXml(returnMap); }else{ try { //更新订单的状态等等操作... returnMap.put("return_code", "SUCCESS"); requestXML = TenPayUtil.getRequestXml(returnMap); } catch (BusinessException e) { SystemLogger.info(e.getMessage()); returnMap.put("return_code", "FAIL"); returnMap.put("return_msg", "签名失败"); requestXML = TenPayUtil.getRequestXml(returnMap); } } } catch (Exception e) { SystemLogger.info("转换微信请求参数错误"); returnMap.put("return_code", "FAIL"); returnMap.put("return_msg", "转换微信请求参数错误"); requestXML = TenPayUtil.getRequestXml(returnMap); } try{ PrintWriter out = ServletActionContext.getResponse().getWriter(); out.print(requestXML); out.flush(); out.close(); }catch(Exception ex){ } return "success"; } }
Service:
@Transactional @Service(value = "transactionService") public class TransactionServiceImpl implements TransactionService{ <span style="white-space:pre"> </span>....... @Override public void createWeChatRequest(PayForm form) throws BusinessException { Transaction po = this.getTransactionByID(form.getTransactionID()); String shopOrderIDs = po.getMuiltFlag().equals("1") ? po.getRelateIDs() : po.getRelateID().toString(); MasterOrder order = masterorderService.getMasterOrderByShopOrderIDs(shopOrderIDs); if(order.getPayFlag() == 1){ throw new BusinessException("该笔订单已支付"); }else{ form.setMasterOrderID(order.getMasterOrderID()); String payTypeID = po.getPayTypeID().toString(); if(AppKeys.PAY_TYPE_ID_WECHAT.equals(payTypeID)){ //请求参数按参数名称大小进行排序 SortedMap<String, String> params = createSortedMap(form,po); //签名 String sign = TenPayUtil.sign(params, WeixinUtil.partnerKey); params.put("sign", sign); //生成xml格式 String requestXML = TenPayUtil.getRequestXml(params); //获取证书 HttpServletRequest request = ServletActionContext.getRequest(); InputStream instream = request.getSession().getServletContext().getResourceAsStream("/WEB-INF/weixinCert/apiclient_cert.p12"); String responseXML; try { //创建微信订单返回结果 responseXML = TenPayUtil.post(WeixinUtil.CREATE_ORDER_URL,WeixinUtil.partner,requestXML,instream); Map<String,String> resultMap = XmlUtil.parseXml(responseXML); String return_code = resultMap.get("return_code").toString(); if(return_code.equals("SUCCESS")){ //创建微信订单成功,获取微信预支付订单ID String prepay_id = (String) resultMap.get("prepay_id"); SortedMap<String, String> finalpackage = new TreeMap<String, String>(); String prepay_id2 = "prepay_id="+prepay_id; String packages = prepay_id2; String timeStamp = TenPayUtil.getTimeStamp(); String nonceStr = TenPayUtil.createNonceStr(); finalpackage.put("appId", WeixinUtil.appId); finalpackage.put("timeStamp", timeStamp); finalpackage.put("nonceStr", nonceStr); finalpackage.put("package", packages); finalpackage.put("signType", "MD5"); //签名 sign = TenPayUtil.sign(finalpackage, WeixinUtil.partnerKey); form.setAppId(WeixinUtil.appId); form.setTimeStamp(timeStamp); form.setPaySign(sign); form.setNonceStr(nonceStr); form.setPackages(packages); }else{ throw new BusinessException("统一支付接口获取预支付订单出错"); } }catch (Exception e) { e.printStackTrace(); SystemLogger.info(e.getMessage()); throw new BusinessException("支付异常"); } }else{ throw new BusinessException("手机端仅支持微信支付"); } } } private SortedMap<String, String> createSortedMap(PayForm form,Transaction po){ //公众账号ID String appId = WeixinUtil.appId; //商户号 String partner = WeixinUtil.partner; //当前时间 String currTime = TenPayUtil.getCurrTime(); //8位日期 String strTime = currTime.substring(8, currTime.length()); //四位随机数 String strRandom = TenPayUtil.getRandomNum(4); //10位序列号,可以自行调整。 String strReq = strTime + strRandom; //商户号 String mch_id = partner; //子商户号 非必输 String sub_mch_id=""; //设备号 非必输 String device_info=""; //随机字符串 String nonce_str = strReq; //商品描述 String body = po.getTitle(); //附加数据 String attach = "测试"; //商户订单号 String out_trade_no = po.getTransactionID().toString(); int intMoney = (int)(po.getAmount()*100); //总金额以分为单位,不带小数点 int total_fee = intMoney; //订单生成的机器 IP String spbill_create_ip = ServletActionContext.getRequest().getRemoteAddr(); //订 单 生 成 时 间 非必输 String time_start = currTime; //订单失效时间 非必输 String time_expire = ""; //商品标记 非必输 String goods_tag = ""; //这里notify_url是 支付完成后微信发给该链接信息,可以判断会员是否支付成功,改变订单状态等。 String notify_url =WeixinUtil.notifyURL; //交易类型 String trade_type = "JSAPI"; //用户标识 String openid = form.getOpenid(); //非必输 String product_id = ""; SortedMap<String, String> packageParams = new TreeMap<String, String>(); packageParams.put("appid", appId); packageParams.put("mch_id", mch_id); packageParams.put("nonce_str", nonce_str); packageParams.put("body", body); packageParams.put("attach", attach); packageParams.put("out_trade_no", out_trade_no); packageParams.put("total_fee", total_fee+""); packageParams.put("spbill_create_ip", spbill_create_ip); packageParams.put("notify_url", notify_url); packageParams.put("trade_type", trade_type); packageParams.put("openid", openid); return packageParams; } <span style="white-space:pre"> </span>...... }
TenPayUtil:
public class TenPayUtil { /** * 对请求参数名ASCII码从小到大排序后签名 * @param openid * @param userId * @return */ public static String sign(SortedMap<String, String> params,String KEY){ Set<Entry<String,String>> entrys=params.entrySet(); Iterator<Entry<String,String>> it=entrys.iterator(); StringBuffer result = new StringBuffer(); while(it.hasNext()) { Entry<String,String> entry=it.next(); result.append(entry.getKey()) .append("=") .append(entry.getValue()) .append("&"); } result.append("key=").append(KEY); SystemLogger.info(result.toString()); String sign = ""; try { sign = MD5Util.MD5(result.toString()); } catch (Exception e) { e.printStackTrace(); } return sign.toString().toUpperCase(); } public static String getRequestXml(SortedMap<String,String> params){ StringBuffer sb = new StringBuffer(); sb.append("<xml>"); Set es = params.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 ("body".equalsIgnoreCase(k)||"attach".equalsIgnoreCase(k)||"goodstag".equalsIgnoreCase(k)||"sign".equalsIgnoreCase(k)) { sb.append("<"+k+">"+"<![CDATA["+v+"]]></"+k+">"); }else { sb.append("<"+k+">"+v+"</"+k+">"); } } sb.append("</xml>"); return sb.toString(); } /** * 生成随机字符串 * @return */ public static String createNonceStr() { return UUID.randomUUID().toString().toUpperCase().replace("-", ""); } /** * 获取当前日期 yyyyMMdd * * @param date * @return String */ public static String getCurrTime() { SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss"); String strDate = formatter.format(new Date()); return strDate; } /** * 生成特定位数的随机数字 * @param length * @return */ public static String getRandomNum(int length) { String val = ""; Random random = new Random(); for (int i = 0; i < length; i++) { val += String.valueOf(random.nextInt(10)); } return val; } /** * 获取时间戳 * @return */ public static String getTimeStamp() { return String.valueOf(System.currentTimeMillis() / 1000); } /** * * @param url 请求URL * @param MCH_ID 商户号 * @param requestXML 请求参数 * @param instream 证书流 * @return * @throws NoSuchAlgorithmException * @throws CertificateException * @throws IOException * @throws KeyManagementException * @throws UnrecoverableKeyException * @throws KeyStoreException */ public static String post(String url,String MCH_ID,String requestXML,InputStream instream) throws NoSuchAlgorithmException, CertificateException, IOException, KeyManagementException, UnrecoverableKeyException, KeyStoreException{ KeyStore keyStore = KeyStore.getInstance("PKCS12"); try { keyStore.load(instream, MCH_ID.toCharArray()); } finally { instream.close(); } SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, MCH_ID.toCharArray()).build(); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( sslcontext, new String[] { "TLSv1" }, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build(); String result = ""; try { HttpPost httpPost = new HttpPost(url); StringEntity reqEntity = new StringEntity(requestXML,"UTF-8"); reqEntity.setContentType("application/x-www-form-urlencoded"); httpPost.setEntity(reqEntity); CloseableHttpResponse response = httpclient.execute(httpPost); try { HttpEntity entity = response.getEntity(); if (entity != null) { BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent(),"UTF-8")); String text; while ((text = bufferedReader.readLine()) != null) { result +=text; } } EntityUtils.consume(entity); } finally { response.close(); } } finally { httpclient.close(); } return result; } /** * 解析微信发来的请求(XML) * * @param request * @return * @throws Exception */ @SuppressWarnings("unchecked") public static Map<String, String> parseXml(HttpServletRequest request) throws Exception { // 将解析结果存储在HashMap中 Map<String, String> map = new HashMap<String, String>(); // 从request中取得输入流 InputStream inputStream = request.getInputStream(); // 读取输入流 SAXReader reader = new SAXReader(); Document document = reader.read(inputStream); // 得到xml根元素 Element root = document.getRootElement(); // 得到根元素的所有子节点 List<Element> elementList = root.elements(); // 遍历所有子节点 for (Element e : elementList) map.put(e.getName(), e.getText()); // 释放资源 inputStream.close(); inputStream = null; return map; } }
weChatPay.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <%@ include file="/html/common/taglibs.jsp"%> <!DOCTYPE html> <html> <head> <meta charset="utf-8" > <title>订单支付</title> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <link rel="stylesheet" href="<s:url value='/html/css/common/common.css' />" > <link rel="stylesheet" href="<s:url value='/html/css/index.css' />" > </head> <body> <div class="content"> <a href="javascript:callpay();" class="payment">微信支付</a> <hr> <img src="<s:url value='/html/images/logo.svg' />" class="logo"> </div> <script type="text/javascript"> var clicked = !1; // false function callpay() { if (clicked) return false; clicked = !0; // true WeixinJSBridge.invoke('getBrandWCPayRequest', { "appId" : "${appId}", "timeStamp" : "${timeStamp}", "nonceStr" : "${nonceStr}", "package" : "${packages}", "signType" : "MD5", "paySign" : "${paySign}" }, function(res) { WeixinJSBridge.log(res.err_msg); if (res.err_msg == "get_brand_wcpay_request:ok") { window.location.href = "../pay/payResult.action?transactionID=${transactionID}&masterOrderID=${masterOrderID}"; } else if (res.err_msg == "get_brand_wcpay_request:cancel") { clicked = !1; // false window.location.href = "../pay/payResult.action?message=crm.pay.cancel"; } else { clicked = !1; // false window.location.href = "../pay/payResult.action?message=crm.pay.error"; } }) } </script> </body> </html>
相关文章推荐
- iOS开发:集成微信支付和微信授权登陆
- 微信聊天测试脚本 wx_sample.php
- Senparc.Weixin.MP SDK 微信公众平台开发教程(十六):AccessToken自动管理机制
- 折腾了几天,终于解决:微信公众号第三方平台 获取component_verify_ticket
- android版微信href属性失效问题
- QQ公众号平台推出,速度抢注吧
- 如何用微信编辑器排版出美观的图文消息
- 公众号第三方平台开发 获取 component_verify_ticket
- 公众号第三方平台开发 获取 component_verify_ticket 2015-07-05 10:16 59人阅读 评论(0) 收藏
- 微信公众号token验证不过解决方法
- How To Decrypt WeChat EnMicroMsg.db Database?
- 微信破解,解密?How To Decrypt WeChat EnMicroMsg.db Database?
- 微信开发: scope参数错误或没有scope权限解决方法
- 获取微信昵称、头像等信息方法
- 微信公众号支付开发备忘
- 微信开发 支付开发redirect_uri参数错误解决办法
- 腾讯MSDK手Q微信授权登录
- JAVA 公众微信的开放源码项目管理合作伙伴招募的版本号
- 微信公众平台开发- 获取用户基本信息
- 微信公众平台开发--OAuth2.0网页授权