springcloud_k8s_panzhihuazhihuishequ/applets/src/main/java/com/panzhihua/applets/api/ShopApi.java
@@ -1,5 +1,6 @@ package com.panzhihua.applets.api; import com.panzhihua.applets.config.WxMaProperties; import com.panzhihua.common.controller.BaseController; import com.panzhihua.common.model.dtos.shop.*; import com.panzhihua.common.model.vos.LoginUserInfoVO; @@ -26,6 +27,8 @@ @Resource private CommunityService communityService; @Resource private WxMaProperties properties; @ApiOperation(value = "分页查询店铺" , response = PageShopStoreVO.class) @PostMapping("pageshopstore") @@ -148,6 +151,7 @@ } orderCreateDTO.setUserId(loginUserInfo.getUserId()); orderCreateDTO.setPhone(loginUserInfo.getPhone()); orderCreateDTO.setOpenId(loginUserInfo.getOpenid()); return communityService.orderCreate(orderCreateDTO); } @@ -206,5 +210,13 @@ return communityService.orderStatistics(loginUserInfo.getUserId()); } @ApiOperation(value = "小程序微信调起支付") @PostMapping("wxpay") public R wxPay(@RequestBody OrderPayDTO orderPayDTO){ return R.ok(); } } springcloud_k8s_panzhihuazhihuishequ/applets/src/main/java/com/panzhihua/applets/api/WxCallbackApi.java
New file @@ -0,0 +1,73 @@ package com.panzhihua.applets.api; import com.panzhihua.common.utlis.PayUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.util.Map; /** * @auther lyq * @create 2021-04-14 15:02:49 * @describe 微信支付回到函数 */ @Slf4j @RestController @RequestMapping("/wx/") public class WxCallbackApi { @PostMapping("notify") public void payCallback(HttpServletRequest request, HttpServletResponse response) { log.info("微信回调接口方法 start"); log.info("微信回调接口 操作逻辑 start"); String inputLine = ""; String notityXml = ""; try { while((inputLine = request.getReader().readLine()) != null){ notityXml += inputLine; } //关闭流 request.getReader().close(); log.info("微信回调内容信息:"+notityXml); //解析成Map Map<String,String> map = PayUtil.doXMLParse(notityXml); //判断 支付是否成功 if("SUCCESS".equals(map.get("result_code"))){ log.info("微信回调返回是否支付成功:是"); //获得 返回的商户订单号 String outTradeNo = map.get("out_trade_no"); log.info("微信回调返回商户订单号:"+outTradeNo); //访问DB // WechatAppletGolfPayInfo payInfo = appletGolfPayInfoMapper.selectByPrimaryKey(outTradeNo); log.info("微信回调 根据订单号查询订单状态:"); if("0".equals("0")){ //封装 返回值 StringBuffer buffer = new StringBuffer(); buffer.append("<xml>"); buffer.append("<return_code>SUCCESS</return_code>"); buffer.append("<return_msg>OK</return_msg>"); buffer.append("</xml>"); //给微信服务器返回 成功标示 否则会一直询问 咱们服务器 是否回调成功 PrintWriter writer = response.getWriter(); //返回 writer.print(buffer.toString()); } }else{ log.info("微信回调返回支付失败"); } } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } } springcloud_k8s_panzhihuazhihuishequ/applets/src/main/java/com/panzhihua/applets/config/WxMaProperties.java
@@ -40,4 +40,19 @@ * 消息格式,XML或者JSON */ private String msgDataFormat; /** * 商户号 */ private String mchId; /** * 微信支付密钥 */ private String payKey; /** * 微信支付回调地址 */ private String notifyUrl; } springcloud_k8s_panzhihuazhihuishequ/applets/src/main/resources/bootstrap.yml
@@ -25,5 +25,8 @@ appid: wx0cef797390444b75 secret: c7ea9aaa7e391a487e8a5b9ba61045d1 msgDataFormat: JSON payKey: 01A9CB2234D7CBD0AC61B75EB1263805 mchId: 1608439275 notifyUrl: http://387405oo37.zicp.vip/api/applets/wx/notify springcloud_k8s_panzhihuazhihuishequ/common/pom.xml
@@ -114,6 +114,16 @@ <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> </dependency> <dependency> <groupId>org.jdom</groupId> <artifactId>jdom2</artifactId> <version>2.0.5</version> </dependency> <dependency> <groupId>dom4j</groupId> <artifactId>dom4j</artifactId> <version>1.6.1</version> </dependency> </dependencies> springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/constants/PayCpmstant.java
New file @@ -0,0 +1,12 @@ package com.panzhihua.common.constants; /** * 微信支付通用常量 * * @author LYQ */ public class PayCpmstant { //微信支付统一下单url地址 public static final String UNIFIEDORDER_URL="https://api.mch.weixin.qq.com/pay/unifiedorder"; } springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/model/dtos/shop/ComShopOrderCreateDTO.java
@@ -21,6 +21,9 @@ @ApiModelProperty(value = "用户手机号",hidden = true) private String phone; @ApiModelProperty(value = "用户openId",hidden = true) private String openId; @ApiModelProperty(value = "用户收货地址id",required = true) private Long receiverId; springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/model/dtos/shop/OrderPayDTO.java
New file @@ -0,0 +1,18 @@ package com.panzhihua.common.model.dtos.shop; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** * @auther lyq * @create 2021-04-14 15:02:14 * @describe 订单支付请求参数 */ @Data @ApiModel("订单支付请求参数") public class OrderPayDTO { @ApiModelProperty(value = "订单号") private String orderNo; } springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/utlis/HttpClientUtil.java
@@ -13,7 +13,13 @@ import org.apache.http.util.EntityUtils; import org.springframework.util.ObjectUtils; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; /** * @program: springcloud_k8s_panzhihuazhihuishequ @@ -86,5 +92,44 @@ } /** * 使用http请求调用接口,参数类型为xml * @param urlStr 请求地址 * @param data 请求参数 * @return 调用结果 */ public static String httpsRequest(String urlStr,String data) { try { URL url = new URL(urlStr); URLConnection con = url.openConnection(); con.setDoOutput(true); // con.setRequestProperty("Pragma:", "no-cache"); con.setRequestProperty("Cache-Control", "no-cache"); con.setRequestProperty("Content-Type", "text/xml"); OutputStreamWriter out = new OutputStreamWriter(con .getOutputStream()); log.info("urlStr=" + urlStr); log.info("xmlInfo=" + data); out.write(new String(data.getBytes("UTF-8"))); out.flush(); out.close(); BufferedReader br = new BufferedReader(new InputStreamReader(con .getInputStream())); String line = ""; StringBuffer sb = new StringBuffer(); for (line = br.readLine(); line != null; line = br.readLine()) { sb.append(br.readLine()); System.out.println(line); } return sb.toString(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return ""; } } springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/utlis/PayUtil.java
New file @@ -0,0 +1,191 @@ package com.panzhihua.common.utlis; import org.jdom2.input.SAXBuilder; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.math.BigDecimal; import java.net.InetAddress; import java.net.UnknownHostException; import java.security.MessageDigest; import java.text.SimpleDateFormat; import java.util.*; public class PayUtil { /** * 获取当前机器的ip */ public static String getLocalIp() { InetAddress ia = null; String localip = null; try { ia = ia.getLocalHost(); localip = ia.getHostAddress(); } catch (UnknownHostException e) { e.printStackTrace(); } return localip; } @SuppressWarnings("rawtypes") 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(); } /** * 创建签名Sign */ @SuppressWarnings("rawtypes") public static String createSign(String characterEncoding,SortedMap<Object, Object> parameters, String key) { StringBuffer sb = new StringBuffer(); Set es = parameters.entrySet(); Iterator<?> it = es.iterator(); while (it.hasNext()) { Map.Entry entry = (Map.Entry) it.next(); String k = (String) entry.getKey(); if (entry.getValue() != null || !"".equals(entry.getValue())) { String v = String.valueOf(entry.getValue()); if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) { sb.append(k + "=" + v + "&"); } } } sb.append("key=" + key); String sign = ""; try { sign = MD5(sb.toString()); }catch (Exception e){ return e.getMessage(); } return sign; } /** * 生成随机数 */ public static String makeUUID(int len) { return UUID.randomUUID().toString().replaceAll("-", "").substring(0, len); } /** * 生成订单号 */ public static String generateOrderNo() { SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd"); return sdf.format(new Date()) + makeUUID(16); } /** * 解析xml */ public static Map doXMLParse(String strxml) throws Exception { strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\""); if (StringUtils.isNotEmpty(strxml)) { return null; } Map m = new HashMap(); InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8")); SAXBuilder builder = new SAXBuilder(); org.jdom2.Document doc = builder.build(in); org.jdom2.Element root = doc.getRootElement(); List list = root.getChildren(); Iterator it = list.iterator(); while (it.hasNext()) { org.jdom2.Element e = (org.jdom2.Element) it.next(); String k = e.getName(); String v = ""; List children = e.getChildren(); if (children.isEmpty()) { v = e.getTextNormalize(); } else { v = getChildrenText(children); } m.put(k, v); } //关闭流 in.close(); return m; } /** * 获取子节点的xml */ public static String getChildrenText(List children) { StringBuffer sb = new StringBuffer(); if (!children.isEmpty()) { Iterator it = children.iterator(); while (it.hasNext()) { org.jdom2.Element e = (org.jdom2.Element) it.next(); String name = e.getName(); String value = e.getTextNormalize(); List list = e.getChildren(); sb.append("<" + name + ">"); if (!list.isEmpty()) { sb.append(getChildrenText(list)); } sb.append(value); sb.append("</" + name + ">"); } } return sb.toString(); } /** * 转换金额到整型 */ public static String moneyToIntegerStr(BigDecimal money) { int amount = money.multiply(new BigDecimal((100))) .setScale(0, BigDecimal.ROUND_HALF_UP).intValue(); return String.valueOf(amount); } /** * 微信下单,map to xml * @param params 参数 * @return String */ public static String mapToXml(Map<String, String> params) { StringBuilder xml = new StringBuilder(); xml.append("<xml>"); for (Map.Entry<String, String> entry : params.entrySet()) { String key = entry.getKey(); String value = entry.getValue(); // 略过空值 if (StringUtils.isEmpty(value)) continue; xml.append("<").append(key).append("><![CDATA["); xml.append(entry.getValue()); xml.append("]]></").append(key).append(">"); } xml.append("</xml>"); return xml.toString(); } /** * 生成 MD5 * * @param data 待处理数据 * @return MD5结果 */ public static String MD5(String data) throws Exception { java.security.MessageDigest md = MessageDigest.getInstance("MD5"); byte[] array = md.digest(data.getBytes("UTF-8")); StringBuilder sb = new StringBuilder(); for (byte item : array) { sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3)); } return sb.toString().toUpperCase(); } public static String create_timestamp() { return Long.toString(System.currentTimeMillis() / 1000); } } springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/utlis/WxPayUtils.java
New file @@ -0,0 +1,74 @@ package com.panzhihua.common.utlis; import com.alibaba.fastjson.JSONObject; import com.panzhihua.common.constants.PayCpmstant; import java.math.BigDecimal; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; public class WxPayUtils { public static String getUnifiedorder(String body, String openid, String outTradeNo, BigDecimal money) throws Exception{ String nonceStr = PayUtil.makeUUID(32); SortedMap<Object, Object> params = new TreeMap<>(); params.put("appid", "wx0cef797390444b75"); params.put("body", body); params.put("mch_id", "1608439275"); params.put("nonce_str",nonceStr); params.put("notify_url", "http://387405oo37.zicp.vip/api/applets/wx/notify"); params.put("openid", openid); params.put("out_trade_no", outTradeNo);//商品订单号 params.put("spbill_create_ip", PayUtil.getLocalIp());//服务部署的ip params.put("total_fee", PayUtil.moneyToIntegerStr(money));//费用的参数转型 params.put("trade_type", "JSAPI");//对接类型 params.put("sign", PayUtil.createSign("UTF-8", params, "01A9CB2234D7CBD0AC61B75EB1263805"));//MD5签名 //转换成xml String xmlData = PayUtil.getRequestXml(params); //请求微信后台,获取支付id String resXml = HttpClientUtil.httpsRequest(PayCpmstant.UNIFIEDORDER_URL, xmlData); System.out.println(resXml); JSONObject data = XMLUtils.xml2Json(resXml); JSONObject result = new JSONObject(); if(data.get("return_msg").equals("OK")){ //将微信统一下单成功的参数拼接再签名 //统一下单返回prepay_id String prepay_id = "prepay_id=" + data.getString("prepay_id"); //时间戳 Long timeStamp = System.currentTimeMillis()/1000; //封装需要签名的字段 SortedMap<Object, Object> payParams = new TreeMap<>(); params.put("appid", "wx0cef797390444b75"); params.put("nonce_str",nonceStr); params.put("package",nonceStr); params.put("signType",nonceStr); params.put("timeStamp",nonceStr); //将参数以及签名计算完成封装返回给前端 result.put("timeStamp",timeStamp); result.put("nonceStr",nonceStr); result.put("package",prepay_id); result.put("signType","MD5"); result.put("paySign",PayUtil.createSign("UTF-8", payParams, "01A9CB2234D7CBD0AC61B75EB1263805")); } return result.toJSONString(); } public static SortedMap<Object, Object> prepayId(Map<String, String> map) { SortedMap<Object, Object> parameters = new TreeMap<>(); parameters.put("appId", ""); parameters.put("timeStamp", PayUtil.create_timestamp()); parameters.put("nonceStr", map.get("nonce_str")); parameters.put("package", "prepay_id=" + map.get("prepay_id")); parameters.put("signType", "MD5"); String sign = PayUtil.createSign("UTF-8", parameters, "商户秘钥"); parameters.put("prepay_id", "prepay_id=" + map.get("prepay_id")); parameters.put("paySign", sign); return parameters; } } springcloud_k8s_panzhihuazhihuishequ/common/src/main/java/com/panzhihua/common/utlis/XMLUtils.java
New file @@ -0,0 +1,110 @@ package com.panzhihua.common.utlis; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import org.dom4j.*; import java.io.File; import java.io.FileInputStream; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.util.List; /** * XML格式化工具类 */ public class XMLUtils { public static String readFile(String path) throws Exception { File file=new File(path); FileInputStream fis = new FileInputStream(file); FileChannel fc = fis.getChannel(); ByteBuffer bb = ByteBuffer.allocate(new Long(file.length()).intValue()); //fc向buffer中读入数据 fc.read(bb); bb.flip(); String str=new String(bb.array(),"UTF8"); fc.close(); fis.close(); return str; } /** * xml转json * @param xmlStr * @return * @throws DocumentException */ public static JSONObject xml2Json(String xmlStr) throws DocumentException{ Document doc= DocumentHelper.parseText(xmlStr); JSONObject json=new JSONObject(); dom4j2Json(doc.getRootElement(), json); return json; } /** * xml转json * @param element * @param json */ public static void dom4j2Json(Element element,JSONObject json){ //如果是属性 for(Object o:element.attributes()){ Attribute attr=(Attribute)o; if(!isEmpty(attr.getValue())){ json.put("@"+attr.getName(), attr.getValue()); } } List<Element> chdEl=element.elements(); if(chdEl.isEmpty()&&!isEmpty(element.getText())){//如果没有子元素,只有一个值 json.put(element.getName(), element.getText()); } for(Element e:chdEl){//有子元素 if(!e.elements().isEmpty()){//子元素也有子元素 JSONObject chdjson=new JSONObject(); dom4j2Json(e,chdjson); Object o=json.get(e.getName()); if(o!=null){ JSONArray jsona=null; if(o instanceof JSONObject){//如果此元素已存在,则转为jsonArray JSONObject jsono=(JSONObject)o; json.remove(e.getName()); jsona=new JSONArray(); jsona.add(jsono); jsona.add(chdjson); } if(o instanceof JSONArray){ jsona=(JSONArray)o; jsona.add(chdjson); } json.put(e.getName(), jsona); }else{ if(!chdjson.isEmpty()){ json.put(e.getName(), chdjson); } } }else{//子元素没有子元素 for(Object o:element.attributes()){ Attribute attr=(Attribute)o; if(!isEmpty(attr.getValue())){ json.put("@"+attr.getName(), attr.getValue()); } } if(!e.getText().isEmpty()){ json.put(e.getName(), e.getText()); } } } } public static boolean isEmpty(String str) { if (str == null || str.trim().isEmpty() || "null".equals(str)) { return true; } return false; } } springcloud_k8s_panzhihuazhihuishequ/service_community/src/main/java/com/panzhihua/service_community/service/impl/ComShopOrderServiceImpl.java
@@ -9,6 +9,7 @@ import com.panzhihua.common.model.dtos.PageDTO; import com.panzhihua.common.model.dtos.shop.*; import com.panzhihua.common.model.vos.R; import com.panzhihua.common.utlis.WxPayUtils; import com.panzhihua.service_community.dao.ComShopOrderDAO; import com.panzhihua.service_community.model.dos.ComShopOrderDO; import com.panzhihua.common.model.vos.R; @@ -54,6 +55,7 @@ private ComShopOrderGoodsDAO comShopOrderGoodsDAO; @Resource private ComShopOrderDAO comShopOrderDAO; /** * 订单预览 @@ -265,7 +267,6 @@ //创建订单操作记录 ComShopOrderOperateDO orderOperateDO = new ComShopOrderOperateDO(); orderOperateDO.setOrderNo(orderNo); orderOperateDO.setOperationType(ComShopOrderOperateDO.operationType.create); orderOperateDO.setOperationTime(new Date()); if(StringUtils.isNotEmpty(orderCreateDTO.getPhone())){ @@ -279,6 +280,14 @@ shopOrderVO.setOrderNo(orderNo); shopOrderVO.setOrderTotal(orderTotal); try { //调用wx支付 String xml = WxPayUtils.getUnifiedorder("",orderCreateDTO.getOpenId(),orderNo,orderTotal); log.info("微信支付返回参数:" + xml); }catch (Exception e){ log.error("调用微信支付异常,异常原因:" + e.getMessage()); } return R.ok(shopOrderVO); }