微信小程序支付功能的实现

第一步,小程序部分功能调用,小程序页面的Wxml类似于html   

<button bindtap="payFor" type="primary" size="mini">支付按钮</button>
payFor:function(){

    var openid=app.globalData.open;
    console.log(openid);
    
    wx.request({
      url:'https://域名地址/puJin/Pay/wxPrePay.do',
      method:'GET',
      data:{
        openid:openid
      },
      header:{
        'content-type':'application/json'
      },
      success:function(res){
         console.log(res.data);
         var nonceStr=res.data.msg.nonceStr;
         var packageStr=res.data.msg.package;
         var paySign=res.data.msg.paySign;
         var timeStamp=res.data.msg.timeStamp;
         console.log(nonceStr);
         console.log(packageStr);
         console.log(paySign);
         console.log(timeStamp);
         wx.requestPayment(
          {
          'timeStamp': timeStamp,
          'nonceStr': nonceStr,
          'package': packageStr,
          'signType': 'MD5',
          'paySign': paySign,
          'success':function(res){
            console.log(res);
          },
          'fail':function(res){
          console.log(res);
          },
          'complete':function(res){
            console.log(res);
          }
          })
      },
      fail:function(res){
        console.log("--------fail--------");
      },
      complete: function (res) {
        wx.hideNavigationBarLoading(); //完成停止加载图标
        wx.stopPullDownRefresh();
    }
    })
  
  }

第二,获取openID,调用后端接口得到nonceStr,package,paySign,timeStamp需要给后台传递openid,小程序APP.js设置全局变量,这里var tha=this;一定要这样写,具体原因可以留言问我

App({
  globalData:{
    open:''
  },
  onLaunch: function () {
    var that=this;
    wx.login({
      success: function(res) {
        // console.log(res.code);
        if (res.code) {
          //发起网络请求
          var code=res.code;
          wx.request({
            url: 'https://域名地址或IP地址/puJin/Pay/getOpenid.do',  
            method:'GET',
            data:{
              code:code
            },
            header: {
              'content-type':'application/json'
            },
            success:  (res) =>{
              var openid = res.data.openid //返回openid
               console.log('openid为' + openid);
              that.globalData.open = openid;
              if (that.testDataCallback){
                that.testDataCallback(res.testData);
                }
            }
          })
         
        } else {
          console.log('获取用户登录态失败!' + res.errMsg)
        }
      }
    });
  }
  
})

第三,传递code,从后台获取openid ,前端不能获取,因为这是微信的一个坑,前端虽然也能获取到,但是微信的域名正式上线不能通过,而且小程序里面也配置不了微信的域名

@RequestMapping("/getOpenid")	
	@ResponseBody//不添加  前台接收不到后台返回的数据
    public Map<String,Object> getOpenid(HttpServletRequest request,HttpServletResponse response,String orderNumber,ModelMap mmp){
		String code=request.getParameter("code");
		System.out.println("code="+code);
		String u1="https://api.weixin.qq.com/sns/jscode2session?appid=wx9c5861fd987d9ec3&secret=d42093a70df1175f88a090dfc46a4b83&js_code="+code+"&grant_type=authorization_code";
		String str1=InterFaceDeal.interfaceUtil(u1);
		JSONObject js=JSONObject.parseObject(str1);
		String openid=(String) js.get("openid");
		System.out.println("openid="+openid);
		Map<String, Object> map=new HashMap<String, Object>();
		map.put("openid", openid);
		map.put("session_key", js.get("session_key"));
		return map;
	}

第四,请求前面小程序页面请求的接口 url:'https://域名地址或者本地测试地址/puJin/Pay/wxPrePay.do',

/**
     * 	微信统一下单接口
     * @param request
     * @param response
	 * @throws Exception 
     */
	@RequestMapping("/wxPrePay")
	@ResponseBody//不添加  前台接收不到后台返回的数据
    public Map<String,Object> wxPrePay(HttpServletRequest request,HttpServletResponse response,String openid) throws Exception{
//		response.setContentType("text/html;charset=utf-8");
//		response.setHeader("Access-Control-Allow-Origin", "*");  
//       //  星号表示所有的异域请求都可以接受,   
//        response.setHeader("Access-Control-Allow-Methods", "GET,POST");
		String orderNumber=CreateOrderNumber.getOrderIdByTime();
		System.out.println("openid="+openid);
		Map<String, Object> map = new HashMap<>();
		//正式环境 
    	String notify_url= "https://zmrcm.cn/puJin/Pay/notify_url.do";
//    	Order payOrder = orderService.selectByorderNumber(orderNumber);
    	 Map<String,String> parameters = new HashMap<String,String>();
         parameters.put("appid", "小程序appid");
         parameters.put("mch_id", "商户号");  //商户号
         String nonce_str=WXPayUtil.generateNonceStr();
         parameters.put("nonce_str", nonce_str);  //随机字符串
         parameters.put("body","微信小程序支付");  //订单详情
         parameters.put("out_trade_no", orderNumber); //订单id
         parameters.put("fee_type", "CNY");  //标价币种
//         String openid=(String) openidMap.get("openid");
         parameters.put("openid",openid); // 微信公众号统一标示openid
         //String total_fee=String.format("%.2f",Double.parseDouble(payOrder.getActual_pay()));
//         String total_fee=new BigDecimal(100).multiply(new BigDecimal(payOrder.getActual_pay())).setScale(0,BigDecimal.ROUND_DOWN).toString();
         parameters.put("total_fee","100"); //支付金额   以分为单位
         parameters.put("spbill_create_ip",getIpAddr(request));//下单ip
         parameters.put("notify_url", notify_url); //下边那个方法地址   支付成功回调路径
         parameters.put("trade_type", "JSAPI");  // 固定填写
        //设置签名
         String paysign=WXPayUtil.generateSignature(parameters, "自己的(API密钥)API_KEY");
         parameters.put("sign", paysign);
         
       //封装请求参数结束
         String requestXML = WXPayUtil.mapToXml(parameters);  
        //调用统一下单接口
         String result = PayCommonUtil.httpsRequest(ConfigUtil.UNIFIED_ORDER_URL, "POST", requestXML);
         //String unifiedorder_url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
         //String result = HttpRequest.sendPost(unifiedorder_url, requestXML);//发送post请求"统一下单接口"返回预支付id:prepay_id
        
//         System.out.println(result);
         try {
        	// Map<String, String> resultMap=WXPay.unifiedOrder(parameters);
         /**统一下单接口返回正常的prepay_id,再按签名规范重新生成签名后,将数据传出。参与签名的字段名为appId,partnerId,prepayId,nonceStr,timeStamp,package。注意:package的值格式为Sign=WXPay**/
        	Map<String, String> resultMap = WXPayUtil.xmlToMap(result);
        	System.out.println("resultMap="+resultMap);
        	Map<String,String> parameterMap2 = new HashMap<String,String>();  
            parameterMap2.put("appId", "小程序appid");    
            parameterMap2.put("package", "prepay_id="+resultMap.get("prepay_id").toString().trim());//预付款id  
            parameterMap2.put("nonceStr",nonce_str);//随机字符串
            parameterMap2.put("signType", WXPayConstants.MD5);//MD5加密   非必须
            //生成的时间戳是13位,ios必须是10位
            String timestamp=WXPayUtil.getCurrentTimestamp()+"";
            parameterMap2.put("timeStamp",timestamp); 
            String sign2 = WXPayUtil.generateSignature(parameterMap2,"自己的(API密钥)API_KEY");
            parameterMap2.put("paySign", sign2);  
            map.put("code","200");
            map.put("msg",parameterMap2);
        } catch (JDOMException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return map;
    }

第六,

/**
	 * 财付通通知
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	@RequestMapping("/notify_url")
	public void ten_notify_url(HttpServletRequest request,HttpServletResponse response) throws Exception{
		//---------------------------------------------------------
		//财付通支付通知(后台通知)示例,商户按照此文档进行开发即可
		//---------------------------------------------------------
		//log.info("财付通支付通知开始");
		String result = getRequestString(request);
		
	    Map parse = XMLUtil.doXMLParse(result);
	    
	    String out_trade_no = parse.get("out_trade_no").toString();
	    String result_code = parse.get("result_code").toString();
	    String transaction_id = parse.get("transaction_id").toString();
	  //  微信支付订单号	transaction_id
	  //  log.info("商户订单号:"+out_trade_no+"......交易状态:"+result_code);
	    System.out.println("===============================");
		System.out.println("商户订单号:"+out_trade_no+"......交易状态:"+result_code);
		System.out.println("===============================");
	    if (parse.get("result_code").toString().equalsIgnoreCase("SUCCESS")) { // 交易支付成功的执行相关业务逻辑
			
//	    	Order orderInfo = orderService.selectByorderNumber(out_trade_no);
//			orderInfo.setOrder_title("微信付款");
//			orderInfo.setStatus("1");	
//			orderInfo.setPayway("0");	
//			int i=orderService.updateByPrimaryKeySelective(orderInfo);
            response.getWriter().write(setXML("SUCCESS", ""));   //告诉微信服务器,我收到信息了,不要在调用回调action了
	    } else {
//	    	Order orderInfo = orderService.selectByorderNumber(out_trade_no);
//	    	orderInfo.setOrder_title("未付款,交易关闭!");
//	    	int i=orderService.updateByPrimaryKeySelective(orderInfo);
	    }
	}
	
	private String setXML(String return_code, String return_msg) {
        return "<xml><return_code><![CDATA[" + return_code + "]]></return_code>"+
                    "<return_msg><![CDATA[" + return_msg+ "]]></return_msg></xml>";

	}
	
	private String getRequestString(HttpServletRequest request) throws IOException{
		InputStream inStream = request.getInputStream();
        ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outSteam.write(buffer, 0, len);
        }
        outSteam.close();
        inStream.close();
        
        return new String(outSteam.toByteArray(),"utf-8");//获取微信调用我们notify_url的返回信息
	}
	
	public  String getIpAddr(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.getRemoteAddr(); 
	    } 
	    return ip; 
	  }

第七,工具包

    * @return String 随机字符串
     */
    public static String generateNonceStr() {
        char[] nonceChars = new char[32];
        for (int index = 0; index < nonceChars.length; ++index) {
            nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length()));
        }
        return new String(nonceChars);
    }



/**
     * 生成签名
     *
     * @param data 待签名数据
     * @param key API密钥
     * @return 签名
     */
    public static String generateSignature(final Map<String, String> data, String key) throws Exception {
        return generateSignature(data, key, SignType.MD5);
    }

    /**
     * 生成签名. 注意,若含有sign_type字段,必须和signType参数保持一致。
     *
     * @param data 待签名数据
     * @param key API密钥
     * @param signType 签名方式
     * @return 签名
     */
    public static String generateSignature(final Map<String, String> data, String key, SignType signType) throws Exception {
        Set<String> keySet = data.keySet();
        String[] keyArray = keySet.toArray(new String[keySet.size()]);
        Arrays.sort(keyArray);
        StringBuilder sb = new StringBuilder();
        for (String k : keyArray) {
            if (k.equals(WXPayConstants.FIELD_SIGN)) {
                continue;
            }
            if (data.get(k).trim().length() > 0) // 参数值为空,则不参与签名
                sb.append(k).append("=").append(data.get(k).trim()).append("&");
        }
        sb.append("key=").append(key);
        if (SignType.MD5.equals(signType)) {
            return MD5(sb.toString()).toUpperCase();
        }
        else if (SignType.HMACSHA256.equals(signType)) {
            return HMACSHA256(sb.toString(), key);
        }
        else {
            throw new Exception(String.format("Invalid sign_type: %s", signType));
        }
    }






    /**
     * 获取当前时间戳,单位秒
     * @return
     */
    public static long getCurrentTimestamp() {
        return System.currentTimeMillis()/1000;
    }

    /**
     * 获取当前时间戳,单位毫秒
     * @return
     */
    public static long getCurrentTimestampMs() {
        return System.currentTimeMillis();
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值