APP微信支付后台内容小结

来源:互联网 发布:华罗庚的优化法时间 编辑:程序博客网 时间:2024/05/18 00:52

  第一次做微信支付,在网上找了很多的demo,但我觉得没有一个可以拿来现成就可以用的,我东拼西凑下才“拼接”成功,终于和我们的手机前段打通脉络,经过测试还算好用。话不多说,在此作为我一个记忆节点,也希望能帮助到有和我相同困惑的朋友们!

此处使用spring MVC Controller注入方式,调用方法。

@Controller
@RequestMapping("/AsynAlipayNotifyController")
public class AsynAlipayNotifyController {

/**
 * App端调用微信支付
 * @param body
 * @param out_trade_no
 * @param total_fee
 * @param spbill_create_ip
 * @return
 * @author superma
 */
@Author(type=CheckType.NO_CHECK)
@RequestMapping("/getWxPayInfo.json")
public @ResponseBody JSONMap<String,Object> getWxPayInfo(String body,String out_trade_no,int total_fee,
String spbill_create_ip){
JSONMap<String,Object> model = new JSONMap<String,Object>();
try{
//获取支付参数

String appid =WXSignUtils.APPID;           //在工具类中定义申请的ID号
System.out.println("appid:"+appid);

String mch_id =WXSignUtils.MCH_ID;
System.out.println("mch_id:"+mch_id);

String nonce_str =RandCharsUtils.getRandomString(16);

String time_start =RandCharsUtils.timeStart();
System.out.println(time_start);

String time_expire =RandCharsUtils.timeExpire();
System.out.println(time_expire);

String notify_url =WXSignUtils.NOTIFY_URL;

System.out.println("notify_url:"+notify_url);

String trade_type = WXSignUtils.TRADE_TYPE;
//开始生成签名
   SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();
    parameters.put("appid", appid);    
parameters.put("mch_id", mch_id);                       //商户id
parameters.put("nonce_str", nonce_str);               //随机字符串
parameters.put("body", body);                                //商品描述    
parameters.put("out_trade_no", out_trade_no);   //订单编号
parameters.put("total_fee", total_fee);                   //总价,‘分’为单位
parameters.put("time_start", time_start);              //支付生成时间
parameters.put("time_expire", time_expire);       //支付失效时间
parameters.put("notify_url", notify_url);                  //返回地址
parameters.put("trade_type", trade_type);           //交易类型
parameters.put("spbill_create_ip", spbill_create_ip);  //手机ip

String sign = WXSignUtils.createSign("UTF-8", parameters);
System.out.println("签名:"+sign);

Unifiedorder unifiedorder = new Unifiedorder();
unifiedorder.setAppid(appid);
unifiedorder.setMch_id(mch_id);
unifiedorder.setNonce_str(nonce_str);
unifiedorder.setSign(sign);
unifiedorder.setBody(body);
unifiedorder.setOut_trade_no(out_trade_no);
unifiedorder.setTotal_fee(total_fee);
unifiedorder.setSpbill_create_ip(spbill_create_ip);
unifiedorder.setTime_start(time_start);
unifiedorder.setTime_expire(time_expire);
unifiedorder.setNotify_url(notify_url);
unifiedorder.setTrade_type(trade_type);
//unifiedorder.setTimeStamp(timeStamp);

//xml解析
String xmlInfo = HttpXmlUtils.xmlInfo(unifiedorder);

String wxUrl = WXSignUtils.WXURL;

String method =WXSignUtils.METHOD;

String weixinPost = HttpXmlUtils.httpsRequest(wxUrl, method, xmlInfo).toString();

System.out.println("weixinPost:"+weixinPost);

ParseXMLUtils.jdomParseXml(weixinPost);
   
model.put("weixinPost", weixinPost);
model.put(SysConstant.OP_FLAG, true);
model.put(SysConstant.OP_MESSAGE, SysConstant.SUCCESS);
   }catch(Exception e){
e.printStackTrace();
model.put(SysConstant.OP_FLAG, false);
model.put(SysConstant.OP_MESSAGE, SysConstant.Exception);
}
return model;
}

}


上面方法所调用的工具类

/**
 * 签名算法sign
  */
public class WXSignUtils {

private static String Key = "W7IvC8FYCmUlsigWks48P********";  //此处为在微信公众平台上申请的各个参数,按顺序要求填写在下方即可
    
public static final String APPID="wx06440c98****";

public static final String MCH_ID="14223*****";

public static final String NOTIFY_URL=CommonUtil.WEBSITE+"GetWxNotifyUrlController/payNotifyUrl.json";   //调用微信支付传递参数的路径

public static final String TRADE_TYPE="APP";

public static final String WXURL="https://api.mch.weixin.qq.com/pay/unifiedorder";

public static final String METHOD="POST";
/**
* 微信支付签名算法sign
* @param characterEncoding
* @param parameters
* @return
*/
@SuppressWarnings("rawtypes")
public static String createSign(String characterEncoding,SortedMap<Object,Object> parameters){
StringBuffer sb = new StringBuffer();
Set es = parameters.entrySet();//所有参与传参的参数按照accsii排序(升序)
Iterator it = es.iterator();
while(it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
String k = (String)entry.getKey();
Object v = entry.getValue();
if(null != v && !"".equals(v) 
&& !"sign".equals(k) && !"key".equals(k)) {
sb.append(k + "=" + v + "&");
}
}
sb.append("key=" + Key);
System.out.println("字符串拼接后是:"+sb.toString());
String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
return sign;
}

//生成时间的工具类
public class RandCharsUtils {
private static SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");

public static String getRandomString(int length) { 
String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";   
Random random = new Random();   
StringBuffer sb = new StringBuffer();
int number = 0;
for (int i = 0; i < length; i++) {   
number = random.nextInt(base.length());   
sb.append(base.charAt(number));   
}   
return sb.toString();   
}   

/*
* 当前时间
*/
public static String timeStart(){
return df.format(new Date());
}

/*
* 30分钟有效期
*/
public static String timeExpire(){
Calendar now=Calendar.getInstance();
now.add(Calendar.MINUTE,30);
return df.format(now.getTimeInMillis());
}

}

以上类和方法就是需要APP端按参数要求请求数据,通过以上方法就可以想微信发起支付请求了。

下面要接受微信发送回来的回调参数,服务器要接受参数,并更新因支付而产生各个参数的变化


@Controller
@RequestMapping("/GetWxNotifyUrlController")
public class GetWxNotifyUrlController {

protected static final Logger LOG = LoggerFactory
           .getLogger(GetWxNotifyUrlController.class);
@Resource
private ZlGoodCartService zlGoodCartService;
@Resource(name="ZlGoodAccountService")
private ZlGoodAccountService zlGoodAccountService;
   
   @RequestMapping("/payNotifyUrl.json")
   @ResponseBody
   public String payNotifyUrl(HttpServletRequest request, HttpServletResponse response) throws Exception {
       BufferedReader reader = null;
       reader = request.getReader();
       String line = "";
       String xmlString = null;
       StringBuffer inputString = new StringBuffer();
       while ((line = reader.readLine()) != null) {
           inputString.append(line);
       }
       xmlString = inputString.toString();
       request.getReader().close();
       System.out.println("----接收到的数据如下:---" + xmlString);
       Map<String, String> map = new HashMap<String, String>();
       String result_code = "";
       String return_code = "";
       String out_trade_no = "";
       map = XMLUtil.doXMLParse(xmlString);
       result_code = map.get("result_code");
       out_trade_no = map.get("out_trade_no");
       return_code = map.get("return_code");

              //此处为接收微信回调后的参数进行“验签”,如果通过后进行状态的更新
       if (checkSign(xmlString)) {
       
        //此处方法省略,可根据"out_trade_no"订单流水号,更新订单信息,比如销售量的增加,库存量的减少等等……
       
           return returnXML(result_code);
       } else {
           return returnXML("FAIL");
       }

   }

         //验签方法
   private boolean checkSign(String xmlString) {
       Map<Object, Object> map = null;
       try {
           map = XMLUtil.doXMLParse(xmlString);
       } catch (Exception e) {
           e.printStackTrace();
       }
       String signFromAPIResponse = map.get("sign").toString();
       if (signFromAPIResponse == "" || signFromAPIResponse == null) {
           System.out.println("API返回的数据签名数据不存在,有可能被第三方篡改!!!");
           return false;
       }
       System.out.println("服务器回包里面的签名是:" + signFromAPIResponse);

       //清掉返回数据对象里面的Sign数据(不能把这个数据也加进去进行签名),然后用签名算法进行签名

       map.put("sign", "");
       //将API返回的数据根据用签名算法进行计算新的签名,用来跟API返回的签名进行比较
       String signForAPIResponse = getSign(map);
       if (!signForAPIResponse.equals(signFromAPIResponse)) {
           //签名验不过,表示这个API返回的数据有可能已经被篡改了
           System.out.println("API返回的数据签名验证不通过,有可能被第三方篡改!!! signForAPIResponse生成的签名为" + signForAPIResponse);
           return false;
       }
       System.out.println("恭喜,API返回的数据签名验证通过!!!");

       return true;

   }

            //返回xml格式串
   private String returnXML(String return_code) {
       return "<xml><return_code><![CDATA["
               + return_code
               + "]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
   }
   
    //获取签名
   public String getSign(Map<Object, Object> map) {
       SortedMap<Object, Object> signParams = new TreeMap<Object, Object>();
       for (Map.Entry<Object, Object> stringStringEntry : map.entrySet()) {
           signParams.put(stringStringEntry.getKey(), stringStringEntry.getValue());
       }
       signParams.remove("sign");
       String sign = WXSignUtils.createSign("UTF-8", signParams);
       return sign;
   }

}

通过以上两部分应该就可以完成微信支付的后台操作,还有些细节我并没有完全记录,也怪我能力一般,水平有限,希望能为您提供一点点帮助也算好的,千万别误导了朋友们,这是我第一次记录的内容,我还会继续努力,相信会越来越好!

0 0