Java 微信公众号支付(JSAPI) - 新闻资讯 - 云南小程序开发|云南软件开发|云南网站建设-昆明葵宇信息科技有限公司

159-8711-8523

云南网建设/小程序开发/软件开发

知识

不管是网站,软件还是小程序,都要直接或间接能为您产生价值,我们在追求其视觉表现的同时,更侧重于功能的便捷,营销的便利,运营的高效,让网站成为营销工具,让软件能切实提升企业内部管理水平和效率。优秀的程序为后期升级提供便捷的支持!

您当前位置>首页 » 新闻资讯 » 公众号相关 >

Java 微信公众号支付(JSAPI)

发表时间:2020-10-19

发布人:葵宇科技

浏览次数:24

1:微信公众平台:https://mp.weixin.qq.com/ 企业邮箱账号注册申请;

2:找到接口权限,设置网页授权;

网页授权域名:

这里重点注意 设置域名:需要下载这个txt文件,微信会在设置完域名之后调用域名下的文件访问内容。

注:这里提供一个小得解决方案:

内网穿透设置免费域名: natapp.exe;百度教程。设置一个当前开发项目端口得免费域名。

下载微信得txt文件拿到里面得内容,提供一个Get接口。

@RestController
@RequestMapping("/MP_verify_RiguI1gGI9QyALmH.txt")
public class WxTxtController {
    @GetMapping()
    public String txt() {
        return "RiguI1gGI9QyALmH";
    }

这样就可以保证网页授权域名通过微信验证。

3.微信商户平台申请开通支付:https://pay.weixin.qq.com/

通过之后,需要得配置:账户中心-API证书;产品中心-开发配置-公众号支付授权目录 可以是:"http:natapp.exe生成得免费域名/index/",

参数介绍:

APPID:公共号ID;

SECRET:公众号secret;

MCH_ID:支付商户ID;

PATER_NER_KEY:支付密钥;就是API安全这个里面那个32位得;

接下来进入贴代码:

获取code:CALL_BACK_URL:就是生成得免费域名;

 /**
     * 微信公众平台授权登录
     *
     * @param response
     * @return
     * @throws IOException
     */
    @PostMapping("/publicLogin")
    @ResponseBody
    public AjaxResult login(HttpServletResponse response) throws IOException {
        //回调的url
        String redirect_uri = URLEncoder.encode(CALL_BACK_URL + "/api/wxBusiness/publicCallBack", "UTF-8");
        String url = "https://open.weixin.qq.com/connect/oauth2/authorize?" +
                "appid=APPID" +
                "&redirect_uri=REDIRECT_URI" +
                "&response_type=code" +
                "&scope=SCOPE" +
                "&state=123#wechat_redirect";
        return AjaxResult.success(url.replace("APPID", APPID).replace("REDIRECT_URI", redirect_uri).replace("SCOPE", "snsapi_userinfo"));
    }
  
/**
     * 微信公众平台回调
     *
     * @param modelMap
     * @param req
     * @param resp
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/publicCallBack", method = RequestMethod.GET)
    @ResponseBody
    public AjaxResult callBack(ModelMap modelMap, HttpServletRequest req, HttpServletResponse resp) throws Exception {
   String code = req.getParameter("code");

        return AjaxResult.success(code);
    }

其实这些代码前端写 也是没问题得。

拿到code:调用微信统一下单接口:

JSAPI:官方文档 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_1

下载Java包 然后把那些wxPay得文件引入项目;

 /**
     * @param request
     * @param code
     * @return Map
     * @Description 微信浏览器内微信支付/公众号支付(JSAPI)
     */
    @RequestMapping(value = "/orders", method = RequestMethod.GET)
    @ResponseBody
    public AjaxResult orders(HttpServletRequest request, String code) {
        try {
            //订单号
            String orderNumber = DateUtils.dateTimeNow(DateUtils.YYYYMMDDHHMMSS + "" + (int) (Math.random() * 10000));
            //页面获取openId接口
            String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + APPID
                    + "&secret=" + SECRET
                    + "&code=" + code
                    + "&grant_type=authorization_code";

            JSONObject jsonObject = HttpUtils.doGetJson(url);
        /*
         { "access_token":"ACCESS_TOKEN",
            "expires_in":7200,
            "refresh_token":"REFRESH_TOKEN",
            "openid":"OPENID",
            "scope":"SCOPE"
           }
         */
            String openid = jsonObject.getString("openid");
            LOGGER.info("openId:" + openid);
            //拼接统一下单地址参数
            Map<String, String> paraMap = new HashMap<String, String>();
            //获取请求ip地址
            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.getRemoteAddr();
            }
            if (ip.indexOf(",") != -1) {
                String[] ips = ip.split(",");
                ip = ips[0].trim();
            }
            String nonceStr = WXPayUtil.generateNonceStr();
            LOGGER.info("nonce_str:"+nonceStr);
            paraMap.put("appid", APPID);
            paraMap.put("body", ORDER_BODY);
            paraMap.put("mch_id", MCH_ID);
            paraMap.put("nonce_str", nonceStr);
            paraMap.put("openid", openid);
            paraMap.put("out_trade_no", orderNumber);//订单号
            paraMap.put("spbill_create_ip", ip);
            paraMap.put("total_fee", "1");
            paraMap.put("trade_type", "JSAPI");
            paraMap.put("notify_url", " http://dtpbuf.natappfree.cc/api/wxBusiness/callback");// 此路径是微信服务器调用支付结果通知路径随意写
            String sign = WXPayUtil.generateSignature(paraMap, PATER_NER_KEY);
            LOGGER.info("微信sign:" + sign);/*
            LOGGER.info("验签:"+WXPayUtil.isSignatureValid(sign,PATER_NER_KEY));*/
            paraMap.put("sign", sign);
            String xml = WXPayUtil.mapToXml(paraMap);//将所有参数(map)转xml格式

            // 统一下单 https://api.mch.weixin.qq.com/pay/unifiedorder
            String unifiedorder_url = "https://api.mch.weixin.qq.com/pay/unifiedorder";

            String xmlStr = HttpUtils.sendPost(unifiedorder_url, xml);//发送post请求"统一下单接口"返回预支付id:prepay_id
            LOGGER.info("xml:" + xmlStr);
            //以下内容是返回前端页面的json数据
            String prepay_id = "";//预支付id
            String nonce_str="";
            if (xmlStr.indexOf("SUCCESS") != -1) {
                Map<String, String> map = WXPayUtil.xmlToMap(xmlStr);
                prepay_id = (String) map.get("prepay_id");
                nonce_str=(String) map.get("nonce_str");
            }
            Map<String, String> payMap = new HashMap<String, String>();
            payMap.put("appId", APPID);
            payMap.put("timeStamp", WXPayUtil.getCurrentTimestamp() + "");
            payMap.put("nonceStr", nonceStr);
            payMap.put("package", "prepay_id=" + prepay_id);
            payMap.put("signType", "MD5");
            String paySign = WXPayUtil.generateSignature(payMap, PATER_NER_KEY);
            payMap.put("paySign", paySign);
            /**
             * 订单初始化
             */
            SysOrderInfo orderInfo = new SysOrderInfo();
            orderInfo.setOrderNumber(orderNumber);
            orderInfo.setOrderBody(OrderConstants.ORDER_CLASS_BODY);
            orderInfo.setOpenId(openid);
            orderInfo.setOrderStatus(OrderConstants.ORDER_STATUS_NOT);
            orderInfo.setOrderType(OrderConstants.ORDER_TYPE_LEARN);
            orderInfo.setOrderTradeType(OrderConstants.ORDER_TRADE_JS_API);
            orderInfo.setOrderPrice(BigDecimal.valueOf(OrderConstants.ORDER_PRICE));
            orderInfoService.insertSysOrderInfo(orderInfo);
            orderWxVo orderWxVo = new orderWxVo();
            orderWxVo.setAppId(APPID);
            orderWxVo.setTimeStamp(WXPayUtil.getCurrentTimestamp() + "");
            orderWxVo.setNonceStr(nonceStr);
            orderWxVo.setSignType("MD5");
            orderWxVo.setPackages("prepay_id=" + prepay_id);
            orderWxVo.setPaySign(paySign);
            return AjaxResult.success(orderWxVo);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

直接拿着用就可以。这里几个小坑:①:nonceStr 这个参数 统一下单 签名 和返回前端得参数二次签名 得是同一个字符串。

②:code只能用一次;③:SignType必须是MD5;修改微信提供得wxPay里得

  public WXPay(final WXPayConfig config, final String notifyUrl, final boolean autoReport, final boolean useSandbox) throws Exception {
        this.config = config;
        this.notifyUrl = notifyUrl;
        this.autoReport = autoReport;
        this.useSandbox = useSandbox;
        if (useSandbox) {
            this.signType = SignType.MD5; // 沙箱环境
        }
        else {
            this.signType = SignType.MD5;
        }
        this.wxPayRequest = new WXPayRequest(config);
    }

重点:else {
this.signType = SignType.MD5;
}

回调:

  /**
     * 支付回调
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping("callback")
    public String callBack(HttpServletRequest request, HttpServletResponse response) {
        InputStream is = null;
        try {
            is = request.getInputStream();//获取请求的流信息(这里是微信发的xml格式所有只能使用流来读)
            String xml = WXPayUtil.inputStream2String(is, "UTF-8");
            Map<String, String> notifyMap = WXPayUtil.xmlToMap(xml);//将微信发的xml转map

            if (notifyMap.get("return_code").equals("SUCCESS")) {
                if (notifyMap.get("result_code").equals("SUCCESS")) {
                    String orderNumber = notifyMap.get("out_trade_no");//商户订单号
                    LOGGER.info("回调订单号:"+orderNumber);
                    
                    /**
                     * 自己的业务处理
                     */
                  
                     
                }
            }
            //告诉微信服务器收到信息了,不要在调用回调action了========这里很重要回复微信服务器信息用流发送一个xml即可
            response.getWriter().write("<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>");
            is.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

js得代码 官网里有:

这个只有在微信内置浏览器能识别这个方法。WeixinJSBridge..invoke。

相关案例查看更多