千家信息网

java如何实现微信jsApi支付

发表于:2024-09-23 作者:千家信息网编辑
千家信息网最后更新 2024年09月23日,java如何实现微信jsApi支付,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。标注:1、必须在微信内置浏览器进行支付;2、open i
千家信息网最后更新 2024年09月23日java如何实现微信jsApi支付

java如何实现微信jsApi支付,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

标注:1、必须在微信内置浏览器进行支付;2、open id必须获取;3、获取code必须请求后台服务器,将code获取到返回前端,再请求获取openid,将openid存在自己服务器的session中

一、账户准备

1、在微信公众平台开通服务号并付费300元认证(只有企业才能开通)获取appid,在微信支付商户平台注册超级管理员并付费300认证,获取mch_id(商户id)。

2、在微信公众平台获取 appid,appsecret。在商户平台获取mch_id,api安全中获取API密钥(paternerKey)

二、平台配置

1、商户平台:产品中心开发配置,属于支付页面

2、公众平台:账户详情功能设置,配置网页授权域名,(将txt文件放在一级域名以及目录中,可通过域名/txt(文件全称)访问,测试是否可以获取txt内容。如果不行,则进行nginx配置域名访问目录)

3、公众平台:开发,基本设置,配置服务器地址(需要写接口并返回echostr,验证服务器),令牌随便写,消息密钥(随机生成),加密模式:兼容模式。

三、开发(下载javasdk。将微信中的工具类导入https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1)

1、支付前获取基本参数

  /**     * 微信中请求打开页面     */    @RequestMapping(value = "/toJob")    public String  toJob(HttpServletResponse response){        String appId = WxConstants.APPID;        String tologin =redirectURL;        return "redirect:https://open.weixin.qq.com/connect/oauth3/authorize?appid="+appId+"&redirect_uri="+tologin+"&response_type=code&scope=snsapi_base#wechat_redirect";    }    /**     * 微信请求打开页面重定向到该接口,获取code     * 然后重定向到自己页面     */    @RequestMapping(value = "/tologin")    public String  tologin(String code ,HttpServletResponse response){        return "redirect:"+loginUrl+code;    }    /**     * 获取open id     */    @RequestMapping("/getOpenId")    @ResponseBody    public String getOpenId( @RequestParam("code") String code,HttpServletRequest request){        logger.info("code  code:" + code);        Map result = new HashMap<>();        //页面获取openId接口        String getopenid_url = "https://api.weixin.qq.com/sns/oauth3/access_token";        Map param = new HashMap<>();        param.put("appid", WxConstants.APPID);        param.put("secret", WxConstants.SECRET);        param.put("code", code);        param.put("grant_type", "authorization_code");        //向微信服务器发送get请求获取openIdStr        String openIdStr = HttpClientUtil.doGet(getopenid_url, param);        JSONObject jsonObject = JSON.parseObject(openIdStr);        logger.info("opendID  JSON:" + openIdStr);        String openid =  jsonObject.getString("openid");        //将open id存入session。        //如果直接重定向到该接口,openid存不到session中,只会存在腾讯的session中        //微信中打开页面只能请求后台接口,后台获取到code拼接到前台页面后面        //前台获取到code,然后请求获取open id的接口,可以将open id存到我们自己服务器中        request.getSession().setAttribute("openid", openid);        //返回登录页        return openid;    }    /**     * 微信测试接口     * @param request     * @return     */    @RequestMapping("/Token")    @ResponseBody    public String Token(HttpServletRequest request){        logger.info(JSON.toJSONString(request.getParameterMap()));        return request.getParameter("echostr");    }

2、支付、回调

/**     * 简历微信支付     * @param request     * @param isUpdate 是否是认证订单     */    @RequestMapping(value = "/wxPayJob")    @ResponseBody    public Map wxpay(HttpServletRequest request,                                    @RequestParam("isUpdate") Integer isUpdate,                                     @RequestParam("jobUserId") Long jobUserId,                                     @RequestParam("totalAmount") String totalAmount) {        String openId = (String) request.getSession().getAttribute("openid");        logger.info("opendID  pay:" + openId);        //获取openId        String ip = WxUtils.getIpAddress(request);        //将元转化为分        String totalFee =  AmountUtils.changeY2F(totalAmount);        Map result = wxService.orderPayment(openId, ip, totalFee, jobUserId, isUpdate);        return result;    }    /**     * 微信支付回调     * @param request     * @param response     * @return     */    @RequestMapping(value = "/wxPayJobNotify")    @ResponseBody    public  String wxPayJobNotify(HttpServletRequest request, HttpServletResponse response) {        InputStream is = null;        try {            is = request.getInputStream();//获取请求的流信息(这里是微信发的xml格式所有只能使用流来读)            String xml =  IOUtils.toString(is, "utf-8");            Map notifyMap = WXPayUtil.xmlToMap(xml);//将微信发的xml转map            if(notifyMap.get("return_code").equals("SUCCESS")){                if(notifyMap.get("result_code").equals("SUCCESS")){                    String orderNum = notifyMap.get("out_trade_no");//商户订单号                    String amountpaid = notifyMap.get("total_fee");//实际支付的订单金额:单位 分                    String  amount =  AmountUtils.changeF2Y(amountpaid);                    //String openid = notifyMap.get("openid");  //如果有需要可以获取                    //String trade_type = notifyMap.get("trade_type");                    //修改认证状态,订单状态                    jobOrderDtoService.updateState(orderNum);                    }                }            //告诉微信服务器收到信息了,不要在调用回调action了========这里很重要回复微信服务器信息用流发送一个xml即可            response.getWriter().write("");            is.close();        } catch (Exception e) {            e.printStackTrace();        }        return null;    }

3、支付统一下单主体

 //微信支付----异步回调(接口:payForOrder)    @Value(value = "${WxConfig.wxJObNotifyUrl}")    private String wxJObNotifyUrl;    /**     *  调用微信支付     */    @Override    public Map orderPayment(String openId, String ip, String totalAmount, Long jobUserId, Integer isUpdate) {        Map payMap = new HashMap();        try{            String OrderNum = OrderNumUtil.outtradeno("JOB");            String body = "认证";            Map  mapBody =  setSortedMap(openId,OrderNum,body,totalAmount,ip);            String xml = WXPayUtil.mapToXml(mapBody);//将所有参数(map)转xml格式            // 统一下单            String unifiedorder_url = "https://api.mch.weixin.qq.com/pay/unifiedorder";            //发送post请求"统一下单接口"返回预支付id:prepay_id            Map xmlMap = new HashMap<>();            xmlMap.put("xml",xml);            String xmlStr = HttpClientUtil.doPostJson(unifiedorder_url, xml);            //返回前端页面的json数据            payMap = resultMap(xmlStr);                       //插入简历订单                    } catch (Exception e) {            e.printStackTrace();        }            return payMap;     }    /**     * 下单主体信息     */    public Map setSortedMap(String openId,String OrderNum,String body,String totalFee,String ip) throws  Exception{        //拼接统一下单地址参数        Map paraMap = new HashMap();        paraMap.put("appid", WxConstants.APPID);        paraMap.put("body", body);        paraMap.put("mch_id", WxConstants.MCHID);        paraMap.put("nonce_str", WXPayUtil.generateNonceStr());//生成uuID        paraMap.put("openid", openId);        paraMap.put("out_trade_no", OrderNum);//订单号        paraMap.put("spbill_create_ip", ip);        paraMap.put("total_fee",totalFee);//金额 单位 分        paraMap.put("trade_type", WxConstants.WX_TRADE_JSAPI);        paraMap.put("notify_url",wxJObNotifyUrl);// 此路径是微信服务器调用支付结果通知路径随意写        String sign = WXPayUtil.generateSignature(paraMap, WxConstants.KEY);        paraMap.put("sign", sign);        return paraMap;    }    /**     * 返回前端页面的json数据     */    public  Map resultMap(String xmlStr)throws  Exception{        Map json = WXPayUtil.xmlToMap(xmlStr);        //JSONObject json = JSONObject.parseObject(xmlStr);//转成Json格式        LOGGER.info("prepay_id  JSON:" + json);        //获取prepay_id        String prepay_id = json.get("prepay_id");//预支付id        if (xmlStr.indexOf("SUCCESS") != -1) {            Map map = WXPayUtil.xmlToMap(xmlStr);            prepay_id = (String) map.get("prepay_id");        }        Map payMap = new HashMap();        payMap.put("appId", WxConstants.APPID);        payMap.put("timeStamp", WXPayUtil.getCurrentTimestamp()+"");        payMap.put("nonceStr", WXPayUtil.generateNonceStr());        payMap.put("signType", "MD5");        payMap.put("package", "prepay_id=" + prepay_id);        String paySign = WXPayUtil.generateSignature(payMap, WxConstants.KEY);        payMap.put("paySign", paySign);        return payMap;    }

4、工具类:

元转分,分转元

public class AmountUtils {    /**金额为分的格式 */    public static final String CURRENCY_FEN_REGEX = "\\-?[0-9]+";    /**     * 将分为单位的转换为元并返回金额格式的字符串 (除100)     *     * @param amount     * @return     * @throws Exception     */    public static String changeF2Y(Long amount) throws Exception{        if(!amount.toString().matches(CURRENCY_FEN_REGEX)) {            throw new Exception("金额格式有误");        }        int flag = 0;        String amString = amount.toString();        if(amString.charAt(0)=='-'){            flag = 1;            amString = amString.substring(1);        }        StringBuffer result = new StringBuffer();        if(amString.length()==1){            result.append("0.0").append(amString);        }else if(amString.length() == 2){            result.append("0.").append(amString);        }else{            String intString = amString.substring(0,amString.length()-2);            for(int i=1; i<=intString.length();i++){                if( (i-1)%3 == 0 && i !=1){                    result.append(",");                }                result.append(intString.substring(intString.length()-i,intString.length()-i+1));            }            result.reverse().append(".").append(amString.substring(amString.length()-2));        }        if(flag == 1){            return "-"+result.toString();        }else{            return result.toString();        }    }    /**     * 将分为单位的转换为元 (除100)     *     * @param amount     * @return     * @throws Exception     */    public static String changeF2Y(String amount) throws Exception{        if(!amount.matches(CURRENCY_FEN_REGEX)) {            throw new Exception("金额格式有误");        }        return BigDecimal.valueOf(Long.valueOf(amount)).divide(new BigDecimal(100)).toString();    }    /**     * 将元为单位的转换为分 (乘100)     *     * @param amount     * @return     */    public static String changeY2F(Long amount){        return BigDecimal.valueOf(amount).multiply(new BigDecimal(100)).toString();    }    /**     * 将元为单位的转换为分 替换小数点,支持以逗号区分的金额     *     * @param amount     * @return     */    public static String changeY2F(String amount){        String currency =  amount.replaceAll("\\$|\\¥|\\,", "");  //处理包含, ¥ 或者$的金额        int index = currency.indexOf(".");        int length = currency.length();        Long amLong = 0l;        if(index == -1){            amLong = Long.valueOf(currency+"00");        }else if(length - index >= 3){            amLong = Long.valueOf((currency.substring(0, index+3)).replace(".", ""));        }else if(length - index == 2){            amLong = Long.valueOf((currency.substring(0, index+2)).replace(".", "")+0);        }else{            amLong = Long.valueOf((currency.substring(0, index+1)).replace(".", "")+"00");        }        return amLong.toString();    }    public static void main(String[] args) {//        try {//            System.out.println("结果:"+changeF2Y("-000a00"));//        } catch(Exception e){//            System.out.println("----------->>>"+e.getMessage());////          return e.getErrorCode();//        }//      System.out.println("结果:"+changeY2F("1.00000000001E10"));        System.out.println(AmountUtils.changeY2F("1.33"));        try {            System.out.println(AmountUtils.changeF2Y("1322"));        } catch (Exception e) {            e.printStackTrace();        }//        System.out.println(Long.parseLong(AmountUtils.changeY2F("1000000000000000")));//        System.out.println(Integer.parseInt(AmountUtils.changeY2F("10000000")));//        System.out.println(Integer.MIN_VALUE);//        long a = 0;//        System.out.println(a);    }}

http doPost doGet 请求

import org.apache.http.NameValuePair;import org.apache.http.client.entity.UrlEncodedFormEntity;import org.apache.http.client.methods.CloseableHttpResponse;import org.apache.http.client.methods.HttpGet;import org.apache.http.client.methods.HttpPost;import org.apache.http.entity.ContentType;import org.apache.http.entity.StringEntity;import org.apache.http.impl.client.CloseableHttpClient;import org.apache.http.impl.client.HttpClients;import org.apache.http.message.BasicNameValuePair;import org.apache.http.util.EntityUtils;import java.io.IOException;import java.net.URI;import java.util.ArrayList;import java.util.List;import java.util.Map;public class HttpClientUtil {        public static String doGet(String url, Map param) {                // 创建Httpclient对象                CloseableHttpClient httpclient = HttpClients.createDefault();                String resultString = "";                CloseableHttpResponse response = null;                try {                        StringBuilder sb = new StringBuilder(url+"?");                        for (String key : param.keySet()) {                                sb.append(key+"="+param.get(key)+"&");                        }                        sb.deleteCharAt(sb.length()-1);                        URI uri = new URI(sb.toString());                        // 创建http GET请求                        HttpGet httpGet = new HttpGet(uri);                        // 执行请求                        response = httpclient.execute(httpGet);                        // 判断返回状态是否为200                        if (response.getStatusLine().getStatusCode() == 200) {                                resultString = EntityUtils.toString(response.getEntity(), "UTF-8");                        }                } catch (Exception e) {                        e.printStackTrace();                } finally {                        try {                                if (response != null) {                                        response.close();                                }                                httpclient.close();                        } catch (IOException e) {                                e.printStackTrace();                        }                }                return resultString;        }        public static String doGet(String url) {                return doGet(url, null);        }        public static String doPost(String url, Map param) {                // 创建Httpclient对象                CloseableHttpClient httpClient = HttpClients.createDefault();                CloseableHttpResponse response = null;                String resultString = "";                try {                        // 创建Http Post请求                        HttpPost httpPost = new HttpPost(url);                        // 创建参数列表                        if (param != null) {                                List paramList = new ArrayList<>();                                for (String key : param.keySet()) {                                        paramList.add(new BasicNameValuePair(key, param.get(key)));                                }                                // 模拟表单                                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList);                                httpPost.setEntity(entity);                        }                        // 执行http请求                        response = httpClient.execute(httpPost);                        resultString = EntityUtils.toString(response.getEntity(), "utf-8");                } catch (Exception e) {                        e.printStackTrace();                } finally {                        try {                                response.close();                        } catch (IOException e) {                                // TODO Auto-generated catch block                                e.printStackTrace();                        }                }                return resultString;        }        public static String doPost(String url) {                return doPost(url, null);        }                public static String doPostJson(String url, String json) {                // 创建Httpclient对象                CloseableHttpClient httpClient = HttpClients.createDefault();                CloseableHttpResponse response = null;                String resultString = "";                try {                        // 创建Http Post请求                        HttpPost httpPost = new HttpPost(url);                        // 创建请求内容                        StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);                        httpPost.setEntity(entity);                        // 执行http请求                        response = httpClient.execute(httpPost);                        resultString = EntityUtils.toString(response.getEntity(), "utf-8");                } catch (Exception e) {                        e.printStackTrace();                } finally {                        try {                                response.close();                        } catch (IOException e) {                                // TODO Auto-generated catch block                                e.printStackTrace();                        }                }                return resultString;        }}

微信工具类

import com.alibaba.fastjson.JSON;import org.apache.commons.lang3.StringUtils;import org.dom4j.Document;import org.dom4j.DocumentHelper;import org.dom4j.Element;import javax.servlet.http.HttpServletRequest;import java.util.*;public class WxUtils {    //请求xml组装    public static String getRequestXml(Map parameters){        StringBuffer sb = new StringBuffer();        sb.append("");        Set es = parameters.entrySet();        Iterator it = es.iterator();        while(it.hasNext()) {            Map.Entry entry = (Map.Entry)it.next();            sb.append("<"+entry.getKey()+">"+entry.getValue()+"");        }        sb.append("");        return sb.toString();    }    /**     * 随机字符串生成     */    public static String getRandomString(int length) { //length表示生成字符串的长度        String base = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";        Random random = new Random();        StringBuffer sb = new StringBuffer();        for (int i = 0; i < length; i++) {            int number = random.nextInt(base.length());            sb.append(base.charAt(number));        }        return sb.toString();    }    /**     * 将xml格式的字符串转换成Map对象     *     * @param xmlStr xml格式的字符串     * @return Map对象     * @throws Exception 异常     */    public static Map xmlStrToMap(String xmlStr) throws Exception {        if(StringUtils.isEmpty(xmlStr)) {            return null;        }        Map map = new HashMap<>();        //将xml格式的字符串转换成Document对象        Document doc = DocumentHelper.parseText(xmlStr);        //获取根节点        Element root = doc.getRootElement();        //获取根节点下的所有元素        List children = root.elements();        //循环所有子元素        if(children != null && children.size() > 0) {            for(int i = 0; i < children.size(); i++) {                Element child = (Element)children.get(i);                map.put(child.getName(), child.getTextTrim());            }        }        return map;    }    public static  T  xmlStrToBean(String xmlStr, Class clazz) throws InstantiationException, IllegalAccessException {        T obj = clazz.newInstance();        try {            // 将xml格式的数据转换成Map对象            Map map = xmlStrToMap(xmlStr);            //将map对象的数据转换成Bean对象            obj = JSON.parseObject(JSON.toJSONString(map),clazz);        } catch(Exception e) {            e.printStackTrace();        }        return obj;    }    public static String getIpAddress(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.getHeader("HTTP_CLIENT_IP");        }        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {            ip = request.getHeader("HTTP_X_FORWARDED_FOR");        }        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {            ip = request.getRemoteAddr();        }        return ip;    }}

微信常量类

public class WxConstants {    //微信统一下单请求xml参数    public static final String APPID="wx1111111"; //appid是微信公众账号或开放平台APP的唯一标识    public static final String MCHID="111111";//商户申请微信支付后,由微信支付分配的商户收款账号    public static final String SECRET="aaaaaaaa";//AppSecret是APPID对应的接口密码    public static final String KEY="1111111111";//交易过程生成签名的密钥 同API密钥    public static final String NONCE_STR="nonce_str";    public static final String SIGN="sign";//生成签名    public static final String ATTACH="attach";    public static final String TIMESTAMP = "timeStamp";    public static final String NONCESTR = "noncestr";    public static final String PREPAYID = "prepayid";    public static final String PARTNERID = "111111";//API密钥    public static final String PACKAGE = "package";    public static final String OPENID ="OPENID";//用户唯一标识    public static final int getHttpConnectTimeoutMs = 8000;//连接时间    public static final int getHttpReadTimeoutMs = 10000; //超时时间    /**     * 微信 JSAPI支付(或小程序支付)微信中调用网页支付     */    public static final String WX_TRADE_JSAPI = "JSAPI";    /**     * 微信 Native支付     */    public static final String WX_TRADE_NATIVE = "NATIVE";    /**     * 微信 H5支付     */    public static final String WX_TRADE_MWEB = "MWEB";    /**     * 微信 app支付     */    public static final String WX_TRADE_APP = "APP";    }

看完上述内容,你们掌握java如何实现微信jsApi支付的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注行业资讯频道,感谢各位的阅读!

0