微信支付--小程序支付(JAVA)

微信支付--小程序支付(JAVA)_第1张图片
已上传至github库 https://github.com/gaoruiqiang2017/weixinpay.git

步骤

/**
登录+支付 code
流程大概分为几步:
1)登录,获取code(一个code只能用一次)
2)通过code获取openid(通过请求服务器,由服务器请求微信获取并返回小程序)。微信登录+获取openid接口
3)小程序请求服务器进行预下单,上传商品详情、金额、openid。
4)服务器端接收请求,根据请求订单数据、生成第三方订单号,调用微信的统一下单接口,返回prepay_id。
5)服务器收到预下单信息后,签名并组装支付数据,返回给小程序。
6)小程序前端发起支付,并支付完成
7)服务器收到回调。
*/
微信支付--小程序支付(JAVA)_第2张图片

前端首先获取code

wx.login({
  success(res) {
    if (res.code) {
      // 发起网络请求
      wx.request({
        url: 'https://test.com/onLogin',
        data: {
          code: res.code
        }
      })
    } else {
      console.log('登录失败!' + res.errMsg)
    }
  }
})

获取openid

getOpenId:function(that, code){
    console.log(code);
    let operFlag = "getOpenid";
    console.log(operFlag);
    wx.request({
      url: 'https://xxx/weixinAppletpay/getOpenid',
      data: {
        code:code,
        operFlag:operFlag
      },
      header: { 'content-type': 'application/json' },
      success: function (res) {
        console.log(res); 
        var openid = res.data.openid;
        console.log(openid);
        that.paypay(that, openid); //预下单并支付
      },
      fail: function (res) {
        console.log(res.data.errmsg);
        console.log(res.data.errcode);
      },
      complete:function(res){
      }
    })
  },
**还需要下订单,获取订单id,这里省略**

后台接口

@RestController
@RequestMapping("/weixinAppletpay")
public class WeixinAppletPay {

    @Value("${wxAppletAppId}")
    private String wxAppletAppId;  //小程序账号id

    @Value("${mchid}")
    private String mchId;  //商户号

    @Value("${weixinKey}")
    private String weixinKey;  //密匙

    @Value("${wxAppletAppSercet}")
    private String wxAppletAppSercet; //	小程序的appsecret

    @Value("https://api.weixin.qq.com/sns/jscode2session")
    private String wxCode2SeesionUrl; //	小程序的appsecret

    @Value("https://api.mch.weixin.qq.com/pay/unifiedorder")
    private String unifiedorderUrl; //统一下单接口

    @Value("https://127.0.0.1:8080/weixinAppletpay/AppletPay")
    private String redirectUrl;  //授权后重定向的回调链接地址, 请使用 urlEncode 对链接进行处理

    /**
     * //第一步:登录,获取code(一个code只能用一次),通过code获取openid
     * 获取code参考:https://developers.weixin.qq.com/miniprogram/dev/api/wx.login.html
     *
     * @param code
     * @param httpServletRequest
     * @param httpServletResponse
     */
    public String getOpenid(HttpServletRequest httpServletRequest, HttpServletResponse
            httpServletResponse, String code, Writer writer) {
        String openid = "";
        try {
            //封装参数
            HashMap data = new HashMap<>();
            data.put("appid", wxAppletAppId);
            data.put("secret", wxAppletAppSercet);
            data.put("js_code", code);
            data.put("grant_type", "authorization_code");
            //将类型为map的参数转换为xml
            String requestXml = WXPayUtil.mapToXml(data);
            //发送参数,调用微信统一下单接口,返回xml
            String responseXml = HttpUtil.doPost(wxCode2SeesionUrl, requestXml);
            Map map = WXPayUtil.xmlToMap(responseXml);
            if (null != map.get("errmsg")) {
                return "操作失败";
            } else {
                //成功可以先把openid缓存起来,可以设置自己的小程序登录有效时间,也可以直接下订单
                String session_key = map.get("session_key");
                openid = map.get("openid");
                String unionid = map.get("unionid");
            }
        } catch (Exception e) {
            return "异常";
        }
        return openid;
    }
    
    /**
     * 支付
     * @param httpServletRequest
     * @param httpServletResponse
     * @param openid    
     * @param orderId   订单id(可以在这个接口里下订单,不用另写接口,这里是另写的)
     * @param writer
     * @param model
     * @return
     */
    public String appletPay(HttpServletRequest httpServletRequest, HttpServletResponse
            httpServletResponse, String openid, String orderId, Writer writer, Model
                                    model) {
        String mapStr = "";
        try {
        **通过订单id可以拿到订单信息**
            //获得openid调用微信统一下单接口
            HashMap dataMap = new HashMap<>();
            dataMap.put("appid", wxAppletAppId); //公众账号ID
            dataMap.put("mch_id", mchId); //商户号
            dataMap.put("nonce_str", WXPayUtil.generateNonceStr()); //随机字符串,长度要求在32位以内。
            dataMap.put("body", "手机"); //商品描述,通过订单id获得
            dataMap.put("out_trade_no", orderId); //商品订单号,用户下订单后台生成
            dataMap.put("total_fee", "1"); //商品金,通过订单id获得
            dataMap.put("spbill_create_ip", HttpUtil.getIpAddress(httpServletRequest)); //客户端ip
            //通知地址(需要是外网可以访问的)
            dataMap.put("notify_url", "https://127.0.0.1:8080/weixinAppletpay/notifyUrl");
            dataMap.put("trade_type", "JSAPI"); //交易类型
            dataMap.put("openid", openid); //商户号
            //生成签名
            String signature = WXPayUtil.generateSignature(dataMap, weixinKey);
            dataMap.put("sign", signature);//签名
            //将类型为map的参数转换为xml
            String requestXml = WXPayUtil.mapToXml(dataMap);
            //发送参数,调用微信统一下单接口,返回xml
            String responseXml = HttpUtil.doPost(unifiedorderUrl, requestXml);
            Map responseMap = WXPayUtil.xmlToMap(responseXml);
            if ("FAIL".equals(responseMap.get("return_code"))) {
                mapStr = responseMap.get("return_msg");
                writer.write(mapStr);
                return "";
            }
            if ("FAIL".equals(responseMap.get("result_code"))) {
                mapStr = responseMap.get("err_code_des");
                writer.write(mapStr);
                return "";
            }
            if ("".equals(responseMap.get("prepay_id")) || responseMap.get("prepay_id") ==
                    null) {
                writer.write("prepay_id 为空");
                return "";
            }
            //成功之后,提取prepay_id,重点就是这个
            HashMap params = new HashMap<>();
            params.put("appId", wxAppletAppId);
            params.put("nonceStr", WXPayUtil.generateNonceStr());
            params.put("package", responseMap.get("prepay_id"));
            params.put("signType", "MD5");
            params.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
            //重新签名
            String paySign = WXPayUtil.generateSignature(params, weixinKey);
            params.put("paySign", paySign);
            //传给前端页面
            //在微信浏览器里面打开H5网页中执行JS调起支付。接口输入输出数据格式为JSON。
            mapStr = params.toString();
            //前端接受参数调用wx.requestPayment(OBJECT)发起微信支付
           //返回requestPayment:ok,支付成功
        } catch (Exception e) {

        }
        return mapStr;
    }

    /**
     * 异步回调(必须有,得发布到外网)
     *
     * @param unifiedorderUrl
     * @param requestXml
     * @return
     */
    @RequestMapping("/notifyUrl")
    public String notifyUrl(String unifiedorderUrl, String requestXml) {
        System.out.print("进入支付h5回调=====================");

        //判断接受到的result_code是不是SUCCESS,如果是,则返回成功,具体业务具体分析,修改订单状态

        // 通知微信.异步确认成功.必写.不然会一直通知后台.
        String resXml = "" + "" +
                "" + " ";
        return resXml; //或者 return "success";
    }
}

pom



    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.1.1.RELEASE
         
    
    com.weixinpay
    demo
    0.0.1-SNAPSHOT
    demo
    Demo project for Spring Boot

    
        1.8
    

    
        
            org.springframework.boot
            spring-boot-starter-web
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
        

        
        
            com.github.wxpay
            wxpay-sdk
            0.0.3
        
        
            org.apache.httpcomponents
            httpclient
            4.5.5
        
        
            com.alibaba
            fastjson
            1.2.47
        
        
            com.google.zxing
            core
            3.3.0
        
        
            com.google.zxing
            javase
            3.0.0
        
        
            commons-io
            commons-io
            2.6
        
    
    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        

        demo
        
            
                src/main/resources
                true
                
                    **/*.properties
                
            
            
                src/main/resources
                false
                
                    **
                
            
        
    



util

/**
 * @Description
 * @Date:03
 */
public class HttpUtil {

    public static String doPost(String url, String requestXml) {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse httpResponse = null;
        //创建httpClient连接对象
        httpClient = HttpClients.createDefault();
        //创建post请求连接对象
        HttpPost httpPost = new HttpPost(url);
        //创建连接请求对象,并设置连接参数
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(15000)   //连接服务区主机超时时间
                .setConnectionRequestTimeout(60000) //连接请求超时时间
                .setSocketTimeout(60000).build(); //设置读取响应数据超时时间
        //为httppost请求设置参数
        httpPost.setConfig(requestConfig);
        //将上传参数放到entity属性中
        httpPost.setEntity(new StringEntity(requestXml, "UTF-8"));
        //添加头信息
        httpPost.addHeader("Content-type", "text/xml");
        String result = "";
        try {
            //发送请求
            httpResponse = httpClient.execute(httpPost);
            //从相应对象中获取返回内容
            HttpEntity entity = httpResponse.getEntity();
            result = EntityUtils.toString(entity, "UTF-8");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;

    }

    /**
     * 获取IP地址
     *
     * @param request
     * @return
     */
    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;
    }
}

properties

appid=wx12822223?22sss
mchId=149232323312333sss
weixinKey=34234234er2werwerwer
unifiedorderUrl=https://api.mch.weixin.qq.com/pay/unifiedorder

你可能感兴趣的:(微信支付)