微信支付jsapi

微信支付jsapi

微信支付jsapi
微信支付jsapi
微信支付jsapi
商户已有H5商城网站,用户通过消息或扫描二维码在微信内打开网页时,可以调用微信支付完成下单购买的流程。

开发步骤

技术博客

jspi支付,是指微信公众号里面的打开网站,支付

大致流程

  1. 获取所需参数
  2. 发送给统一下单的接口
  3. 根据返回的参数,进行解析,如果成功,将部分参数发送给前台。注意前台的浏览器是微信内置浏览器,有一个内置的js对象,可以通过js对象,调起支付
  4. 最后跳转到结果页面

正式开发

jsapi统一下单api列表
下面列举必须字段

Appid,mch_id,nonce_str,sign,body,out_trade_no,total_fee,spbill_create_ip,notify_url,trade_type,openid

注意:total_fee是分为单位

String total_fee = info.getOrderMoney().multiply(new BigDecimal("100")).intValue()+"";

说下不好获取的

spbill_create_ip:我当时就是写了127.0.0.1,我并不清楚怎么获取

notify_url:写公网可以访问的地址,最好去看下官网的介绍,

out_trade_no:前6位是随机数,后面是数据库中实际的订单编号,这样是为了回调的时候获取订单编号,当然也可以使用别的方法。

openid:是指一个用户到一个公众号,对应的一个key,是唯一的,获取方法文档

我的思路是,先获取code,H5界面里面,有一个去支付按钮,而去支付按钮是一个超链接

https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx1111111111111111&redirect_uri=http%3A%2F%2Fm.XXXX.com%2FpayList.html%3ForderNumber%3D"+orderNum+"&response_type=code&scope=snsapi_base&state=123#wechat_redirect";

这里面的redirect_uri需要格式化

import java.net.URLEncoder;
String formatUrl = URLEncoder.encode("http://m.XXXX.com/payList.html?orderNumber=XXXXXXX","UTF_8");

跳转回来的时候是

http://m.XXXX.com/payList.html?orderNumber=XXXXXXX&code=sdhjsdhfjhasjhfhjasdhbavbnb

这个code呢,你开发在电脑端是看不见的,这也就是微信坑的地方,所以你 下载微信开发者工具

获取code之后,点击微信支付,发送ajax请求给后台

@RequestMapping("/payH5")
    @ResponseBody
    public Object payH5(@RequestParam("orderNumber") String orderNumber, @RequestParam("type") Integer type, HttpServletRequest request, HttpServletResponse response,@RequestParam(value = "code",defaultValue = "")String code) throws Exception{
        try{

            OrderInfo info = orderInfoService.selectOne(new EntityWrapper<OrderInfo>()
                    .eq("order_number", orderNumber));
            ModelAndView modelAndView = new ModelAndView();
            //支付宝支付
            if(type.intValue()==1){
               response.sendRedirect("http://m.XXXX.com/alipay.html?orderNumber="+orderNumber);

                //微信支付
            }else if(type.intValue()==0){
                if("".equals(code)){
                   return "返回错误界面";
                }
                WxpayConfig wxpayConfig = new WxpayConfig();

                //此处获取openid,后台发请求给,通过code,appId,appsecret
                String res = HttpUtil.sendGet("https://api.weixin.qq.com/sns/oauth2/access_token",
                        "appid="+wxpayConfig.getApp_id()+"&secret="+wxpayConfig.getApp_secret()+"&code="+code+"&grant_type=authorization_code");
                JSONObject json = JSONObject.parseObject(res);
                String openId = json.getString("openid");
                Map<String,String> paraMap = new HashMap<>();
                paraMap.put("appid",wxpayConfig.getApp_id());
                paraMap.put("body",info.getOrderProject());
                paraMap.put("mch_id",wxpayConfig.getMch_id());
                paraMap.put("nonce_str", WXPayUtil.generateNonceStr());
                paraMap.put("openid",openId);
                String randomNum = (int)((Math.random()*9+1)*100000)+"";
                String orderNo =randomNum+orderNumber;
                paraMap.put("out_trade_no",orderNo);
                paraMap.put("spbill_create_ip",wxpayConfig.getSpbill_create_ip());
                String total_fee = info.getOrderMoney().multiply(new BigDecimal("100")).intValue()+"";
                paraMap.put("total_fee",total_fee);
                paraMap.put("trade_type",wxpayConfig.getTrade_type());
                paraMap.put("notify_url","http://XXXX.com/XXXX/api/wxnotify?orderNumber="+orderNumber);
                String apiKey = wxpayConfig.getApi_key();
                String sign = WXPayUtil.generateSignature(paraMap,apiKey);
                paraMap.put("sign",sign);
                String xml = WXPayUtil.mapToXml(paraMap);
                //统一下单 https://api.mch.weixin.qq.com/pay/unifiedorder
                String unifiedorder_url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
                String xmlStr = HttpUtil.sendPost(unifiedorder_url,xml,false);
                //以下内容是返回前端页面的json数据
                String prepay_id = "";//预支付id
                if (xmlStr.indexOf("SUCCESS") != -1) {
                    Map<String, String> map = WXPayUtil.xmlToMap(xmlStr);
                    prepay_id = (String) map.get("prepay_id");
                }
                Map<String, String> payMap = new HashMap<String, String>();
                payMap.put("appId", wxpayConfig.getApp_id());
                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, wxpayConfig.getApi_key());
                payMap.put("paySign", paySign);
                return payMap;
            }
            return "";

        }catch (Exception e){
            e.printStackTrace();
        }
        return "end";
//        return new SuccessResponseData();
    }

获取sign

获取sign

下载后,里面有一些工具类,WXPayUtil里面有一个方法可以获取

返回数据到前台后,前台调用js对象,执行

 WeixinJSBridge.invoke( 'getBrandWCPayRequest', {
                "appId":appId,     //公众号名称,由商户传入
                "timeStamp":timeStamp,         //时间戳,自1970年以来的秒数
                "nonceStr":nonceStr, //随机串
                "package":package,
                "signType":signType,         //微信签名方式:
                "paySign":paySign //微信签名
            }, function(res){
                console.log(res);
                window.location.href = "http://m.XXXX.com/orderDetail.html?orderNum="+orderNumber;
                // if(res.err_msg == "get_brand_wcpay_request:ok" ) {
                //     console.log('支付成功');
                //     //支付成功后跳转的页面
                // }else if(res.err_msg == "get_brand_wcpay_request:cancel"){
                //     console.log('支付取消');
                // }else if(res.err_msg == "get_brand_wcpay_request:fail"){
                //     console.log('支付失败');
                // } //使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
}

就会执行微信支付,不管成功没有,都会跳转到orderDetail界面,查看order详情

微信回调

微信会返回结果

我应该处理什么

  1. 告诉微信,我收到了,返回success
  2. 对订单信息,获取orderNum,对订单状态进行更新
@RequestMapping("/wxnotify")
public String wxnotify(HttpServletRequest request,HttpServletResponse response){
    InputStream is = null;
    try{
    is = request.getInputStream();
    String xml = WXPayUtil.inputStream2String(is);
    Map<String,String> notifyMap = WXPayUtil.xmlToMap(xml);
    if(notifyMap.get("return_code").equals("SUCCESS")) {
    String orderNumber = notifyMap.get("out_trade_no").substring(6);
    OrderInfo info = orderInfoService.selectOne(new EntityWrapper<OrderInfo>()
    .eq("order_number", orderNumber));
    info.setOrderState(1);
    orderInfoService.updateById(info);
    String amount = notifyMap.get("total_fee");
    System.out.println("实际付款:"+amount);
    }
    response.getWriter().write("<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>");
    is.close();
    } catch (Exception e) {
    e.printStackTrace();
    }
    return null;
}