国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

微信公眾號開發和微信支付

2019-11-11 03:55:12
字體:
來源:轉載
供稿:網友

博客這么久沒寫了(因為女朋友(^__^) 嘻嘻……),今天決定把微信相關開發遇到的坑給大家分享一下,以免大家掉入坑浪費過多的時間! 我會在文章末尾上傳一個開箱即用的微信公眾號支付的demo,理論上來講你只需要修改配置文件就可以支付了。 使用的技術:SPRingBoot、angularJs。 使用了一個第三方的微信mavne依賴: weixin-java-mp在pom可以看見,時過境遷可能weixin-java-mp版本更新了。weixin-java-mp的API:https://github.com/chanjarster/weixin-java-tools/wiki mavne依賴在中央倉庫可以查找:http://mvnrepository.com/

微信公眾號配置

access.properties文件

該文件中主要配置公眾號和微信支付相關參數,里面的信息在申請公眾號和申請微信支付就會得到(開箱即用也就是修改這個配置文件里面的內容) 這里寫圖片描述 該工具類主要映射access.properties文件鍵的名稱 這里寫圖片描述 讀取access.properties文件的方式為: String appId=PropertyHandler.getInstance().getValue(SampleConstants.WEIXIN_APPID)

初始化配置公眾號

/** * 初始化微信配置 */public class WeiXinInitConfigUtil { public static WxMpInMemoryConfigStorage wxMpConfigStorage; public static WxMpService wxMpService; public static WxMpMessageRouter wxMpMessageRouter; public static WxMpOAuth2AccessToken wxMpOAuth2AccessToken; //注意靜態塊,這里使用的是weixin-java-mp的API,直接對應配置文件填上去。 static { WxMpInMemoryConfigStorage storage=new WxMpInMemoryConfigStorage(); storage.setAppId(PropertyHandler.getInstance().getValue(SampleConstants.WEIXIN_CORPID)); storage.setSecret(PropertyHandler.getInstance().getValue(SampleConstants.WEIXIN_CORPSECRET));storage.setToken(PropertyHandler.getInstance().getValue(SampleConstants.WEIXIN_APP_APPID_TOKEN));storage.setAesKey(PropertyHandler.getInstance().getValue(SampleConstants.WEIXIN_APP_APPID_AESKEY)); wxMpConfigStorage=storage; wxMpService = new WxMpServiceImpl(); wxMpService.setWxMpConfigStorage(storage); wxMpMessageRouter = new WxMpMessageRouter(wxMpService); }}

封裝當前用戶

用攔截器來配置需要的校驗參數 。

/** * Created by orange on 2016/10/27. * 獲取微信用戶相關信息的攔截器,該攔截器將會過濾所有請求,進行是否包含 微信登錄用戶的判斷。 */@Componentpublic class WxCpIntercepter implements HandlerInterceptor { private static final long serialVersionUID = 1L; private static final Logger logger = LoggerFactory.getLogger(WxCpIntercepter.class); //在請求處理之前進行調用(Controller方法調用之前) @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String userAgent = request.getHeader("user-agent"); //獲取session里面的用戶對象 WxMpUser wxUser = (WxMpUser) request.getSession().getAttribute(SampleConstants.WEIXIN_USER); //獲取request中的code String code = request.getParameter("code"); //當request請求里面有code,但是session里面沒有weixinUser(登錄微信用戶),將會查詢的微信用戶封裝到session中 if (code != null && wxUser == null) { WxCpUtil.setUserIdForSession(request); } //設置微信校驗參數到session中 WxCpUtil.openContact(request); return true;// 只有返回true才會繼續向下執行,返回false取消當前請求 } //請求處理之后進行調用,但是在視圖被渲染之前(Controller方法調用之后) @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } //在整個請求結束之后被調用,也就是在DispatcherServlet 渲染了對應的視圖之后執行(主要是用于進行資源清理工作) @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { }}

對攔截器進行統一配置

/** * Created by orange on 2016/10/27. * 攔截器集中配置類 */@Configurationpublic class FilterConfiguration extends WebMvcConfigurerAdapter { @Override public void addInterceptors(InterceptorRegistry registry) { // 多個攔截器組成一個攔截器鏈 // addPathPatterns 用于添加攔截規則 // excludePathPatterns 用戶排除攔截 //這里可添加多個攔截器 registry.addInterceptor(new WxCpIntercepter()).addPathPatterns("/**"); super.addInterceptors(registry); }}

攔截器使用的WxCpUtil類代碼

public class WxCpUtil { private static final Logger logger = LoggerFactory.getLogger(WxCpUtil.class); /** * 判斷用戶是否關注了公眾號 * @param token * @param openid * @return */ public static boolean judgeIsFollow(String token,String openid){ int zhi=0; InputStream is=null; String url = "https://api.weixin.QQ.com/cgi-bin/user/info?access_token="+token+"&openid="+openid+"&lang=zh_CN"; try { URL urlGet = new URL(url); HttpURLConnection http = (HttpURLConnection) urlGet.openConnection(); http.setRequestMethod("GET"); // 必須是get方式請求 http.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); http.setDoOutput(true); http.setDoInput(true); http.connect(); is = http.getInputStream(); int size = is.available(); byte[] jsonBytes = new byte[size]; is.read(jsonBytes); String message = new String(jsonBytes, "UTF-8"); //序列化json字符串 Gson gson = WxMpGsonBuilder.INSTANCE.create(); JsonObject jsonObject = (JsonObject)gson.fromJson(message, JsonObject.class); //用戶是否訂閱該公眾號標識,值為0時,代表此用戶沒有關注該公眾號,1的時候表示關注了。 zhi = jsonObject.get("subscribe").getAsInt(); } catch (Exception e) { e.printStackTrace(); }finally { if(is!=null){ try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } return 1==zhi; } //獲取設置微信用戶 public static void setUserIdForSession(HttpServletRequest request) throws UnsupportedEncodingException { //通過code獲取微信用戶信息 String code = request.getParameter("code"); String state = request.getParameter("state"); logger.debug("code={}", code); logger.debug("state={}", state); String[] res = null; try { wxMpOAuth2AccessToken = wxMpService.oauth2getAccessToken(code); WxMpUser wxMpUser = wxMpService.oauth2getUserInfo(wxMpOAuth2AccessToken, null); String token = wxMpService.getAccessToken(); //判斷用戶是否關注 boolean flag = judgeIsFollow(token, wxMpUser.getOpenId()); if(!flag){//用戶沒有關注 //公眾號讓他關注 } request.getSession().setAttribute(SampleConstants.WEIXIN_USER, wxMpUser); } catch (WxErrorException e) { e.printStackTrace(); } } //設置微信校驗參數 public static void openContact(HttpServletRequest request) { try { String ip = request.getRemoteAddr(); logger.debug("ip地址={}",ip); String urlStr = WxCpUtil.getFullURL(request); logger.debug("request.getRequestURI() = {}", urlStr); if (urlStr.indexOf("goto") > -1 || urlStr.indexOf("menu") > -1) { WxJsapiSignature signature = wxMpService.createJsapiSignature(urlStr); request.getSession().setAttribute("signature", signature); } } catch (WxErrorException e) { e.printStackTrace(); try { throw new ServletException(); } catch (ServletException e1) { e1.printStackTrace(); } } } public static String getFullURL(HttpServletRequest request) { String SeverNameForURI = PropertyHandler.getInstance().getValue("SeverNameForURI"); String uri = request.getScheme() + "://" + SeverNameForURI + request.getRequestURI() + (request.getQueryString() != null ? "?" + request.getQueryString() : ""); return uri; } public static WxJsGroupSignature createGroupapiSignature(String url) throws WxErrorException { String accerssToken=wxMpService.getAccessToken(); String zhi = wxMpService.getJsapiTicket(); JsonElement tmpJsonElement = (new JsonParser()).parse(zhi); JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject(); String jsapiGroupErrcode = tmpJsonObject.get("errcode").getAsString(); String jsapiGroupId = tmpJsonObject.get("group_id").getAsString(); String jsapiGroupTicket = tmpJsonObject.get("ticket").getAsString(); long timestamp = System.currentTimeMillis() / 1000L; String noncestr = RandomUtils.getRandomStr(); String signature = SHA1.genWithAmple(new String[]{"group_ticket=" + jsapiGroupTicket, "noncestr=" + noncestr, "timestamp=" + timestamp, "url=" + url}); WxJsGroupSignature jsGroupapiSignature = new WxJsGroupSignature(); jsGroupapiSignature.setTimestamp(timestamp); jsGroupapiSignature.setNonceStr(noncestr); jsGroupapiSignature.setUrl(url); jsGroupapiSignature.setSignature(signature); jsGroupapiSignature.setGroupId(jsapiGroupId); jsGroupapiSignature.setGroupErrcode(jsapiGroupErrcode); jsGroupapiSignature.setGroupTicket(jsapiGroupTicket); jsGroupapiSignature.setAccessToken(accerssToken); logger.debug("jsapiGroupErrcode=[{}],jsapiGroupId=[{}],jsapiGroupTicket=[{}],jsapiGroupSignature=[{}]", jsapiGroupErrcode, jsapiGroupId, jsapiGroupTicket, jsGroupapiSignature.getSignature()); return jsGroupapiSignature; }}

至此我們已經把公眾號需要的配置全部封裝到session里面去了,接下來我們只需要用Ajax向后臺發起請求獲取配置就好了。

微信支付配置

第一步和第二步

微信支付平臺地址:https://pay.weixin.qq.com/ 微信公眾平臺地址:https://mp.weixin.qq.com/ 第一步在微信支付平臺設置key:安全中心—->API安全 這里寫圖片描述 第二步在微信公眾平臺設置測試授權目錄和測試白名單:微信支付—->開發配置(注意:授權目錄一定要精確到調用html頁面最后一級,比如你的支付頁面url為:www.orange.com/pay/test/pay.html那么你的授權目錄為:www.orange.com/pay/test/) 這里寫圖片描述

第三步

獲取統一下單號和微信JSAPI需要參數。 統一下單號的說白了就是微信返回給你的訂單號,JSAPI是需要這個訂單號再次進行訪問微信服務器的,微信服務器就根據這個訂單號獲取統一下單的詳細信息包括,(多少錢,買了什么東西,等等….),然后調用微信的支付客戶輸入密碼付錢。 這里有兩點需要我們注意。 微信加密校驗地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=20_1 1、微信的加密方式:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3 2、微信統一下單需要的參數:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1 具體代碼

@Controllerpublic class GetUnifiedOrderController { /** * @return 微信支付參數 */ @ResponseBody @RequestMapping("/GetUnifiedOrderController") public WXPayBean GetUnifiedOrderController(HttpServletRequest request){ //生成訂單xml String orderInfo=createOrderInfo(request); //調用統一下單API,獲取訂單號 String prepay_id = httpOrder(orderInfo); //生成最后支付的對象 WXPayBean wxpayBean = startPay(prepay_id); return wxpayBean; } /** * 生成訂單XML * @return */ private String createOrderInfo(HttpServletRequest request) { String appId = PropertyHandler.getInstance().getValue(SampleConstants.WEIXIN_APPID); String mchId = PropertyHandler.getInstance().getValue(SampleConstants.WEIXIN_MCHID); String key = PropertyHandler.getInstance().getValue(SampleConstants.WEIXIN_KEY); // orderId 商戶訂單號商戶支付的訂單號由商戶自定義生成,微信支付要求商戶訂單號保持唯一性(建議根據當前系統時間加隨機序列來生成訂單號)。 // 重新發起一筆支付要使用原訂單號,避免重復支付;已支付過或已調用關單、撤銷(請見后文的API列表)的訂單號不能重新發起支付。 String orderId=wxPayUtils.makeUUID(); //獲取當前用戶的openid WxMpUser wxUser = (WxMpUser) request.getSession().getAttribute(SampleConstants.WEIXIN_USER); String openid = wxUser.getOpenId(); //隨機字符串 String uuid = wxPayUtils.makeUUID(); //根據規則創建可排序的map集合 SortedMap<String, Object> packageParams = new TreeMap<String, Object>(); packageParams.put("appid", appId);//公眾賬號ID packageParams.put("mch_id",mchId);//商戶號 packageParams.put("nonce_str",uuid);//隨機字符串 packageParams.put("body","我是商品描述");//商品描述 注意加上<![CDATA[ ]]>保證解析器忽略解析里面的內容 packageParams.put("out_trade_no", orderId);//商戶訂單號 packageParams.put("total_fee",1);//金額需要擴大100倍:1代表支付的是0.01元 packageParams.put("spbill_create_ip","171.221.149.199");//用戶IP地址 packageParams.put("notify_url", "1598m20l41.51mypc.cn/gotoMap/scanCoedOk");//通知地址 packageParams.put("trade_type", "JSAPI");//JSAPI--公眾號支付、NATIVE--原生掃碼支付、APP--app支付 packageParams.put("openid",openid);//前用戶的openid //獲取簽名(使用工具類里面的加密方法,大家可以直接將工具類拷貝到自己的項目中使用) String sign = wxPayUtils.md5Str(packageParams,key); //拼接成一個xml。 String xml="<xml>"+ "<appid>"+appId+"</appid>"+ "<mch_id>"+mchId+"</mch_id>"+ "<nonce_str>"+uuid+"</nonce_str>"+ "<sign>"+sign+"</sign>"+ "<body><![CDATA["+"我是商品描述"+"]]></body>"+ "<out_trade_no>"+orderId+"</out_trade_no>"+ "<total_fee>"+1+"</total_fee>"+ "<spbill_create_ip>"+"171.221.149.199"+"</spbill_create_ip>"+ "<notify_url>"+"1598m20l41.51mypc.cn/gotoMap/scanCoedOk"+"</notify_url>"+ "<trade_type>"+"JSAPI"+"</trade_type>"+ "<openid>"+openid+"</openid>"+ "</xml>"; return xml; } /** * 調用統一下單API * @param orderInfo * @return */ private String httpOrder(String orderInfo) { String url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; try { HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); //加入數據 conn.setRequestMethod("POST"); conn.setDoOutput(true); BufferedOutputStream buffOutStr = new BufferedOutputStream(conn.getOutputStream()); buffOutStr.write(orderInfo.getBytes()); buffOutStr.flush(); buffOutStr.close(); //獲取輸入流 BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); String line = null; StringBuffer sb = new StringBuffer(); while((line = reader.readLine())!= null){ sb.append(line); } //解析xml SAXReader reader1 = new SAXReader(); reader1.setEncoding("utf-8"); Document document; document = reader1.read(new ByteArrayInputStream(sb.toString().getBytes("UTF-8"))); Element element = document.getRootElement();//得到xml跟標簽,此處是<root></root> Element prepay_idElement = element.element("prepay_id"); String prepay_id = prepay_idElement.getData() + ""; Element return_codeElement = element.element("return_code"); String return_code = return_codeElement.getData() + ""; Element result_codeElement = element.element("result_code"); String result_code = result_codeElement.getData() + ""; if("SUCCESS".equals(return_code)&&"SUCCESS".equals(result_code)){ //當都為SUCCESS的時候才將統一下單id返回出去 return prepay_id; } } catch (Exception e) { e.printStackTrace(); } return null; } /** * 設置微信支付最后一步所需要的參數 * @param prepay_id 統一支付id * @return 支付對象 */ private WXPayBean startPay(String prepay_id){ String appId = PropertyHandler.getInstance().getValue(SampleConstants.WEIXIN_APPID); String key = PropertyHandler.getInstance().getValue(SampleConstants.WEIXIN_KEY); WXPayBean wxPayBean=new WXPayBean(); String timeStamp = String.valueOf((System.currentTimeMillis() / 1000));//1970年到現在的秒數 String nonceStr =wxPayUtils.makeUUID();//隨機字符串 String signType = "MD5"; SortedMap<String, Object> packageParams = new TreeMap<String, Object>(); packageParams.put("appId",appId);//注意這里的appId中的I是大寫的喔不要弄錯了。 packageParams.put("timeStamp",timeStamp); packageParams.put("nonceStr",nonceStr); packageParams.put("signType",signType); packageParams.put("package","prepay_id="+prepay_id); //獲取簽名(用同樣的方式加密) String paySign = wxPayUtils.md5Str(packageParams, key); //封裝微信支付實例 wxPayBean.setTimeStamp(timeStamp); wxPayBean.setNonceStr(nonceStr); wxPayBean.setPackage_("prepay_id="+prepay_id); wxPayBean.setSignType(signType); wxPayBean.setPaySign(paySign); return wxPayBean ; }}至此我們已經封裝完成微信支付需要的全部配置,等待JSAPI向我們請求數據就好了。

工具類wxPayUtils代碼

/** * Created by orange on 2017/1/19. * 微信支付工具類 */public class wxPayUtils { /** * * @param params 需要簽名的參數,鍵值對 * @param key (支付平臺的安全密鑰)key設置路徑:微信商戶平臺(pay.weixin.qq.com)-->賬戶設置-->API安全-->密鑰設置 * @return MD5加密后轉換為大寫返回 */ public static String md5Str(SortedMap<String, Object>params,String key){ //第一步 鍵按照字典序 StringBuffer sb = new StringBuffer(); Set es = params.entrySet(); Iterator it = es.iterator(); while (it.hasNext()) { Map.Entry entry = (Map.Entry) it.next(); String k = entry.getKey()+""; String v = entry.getValue()+""; //為空不參與簽名、參數名區分大小寫 if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) { sb.append(k + "=" + v + "&"); } } //第二步拼接key sb.append("key="+key); //MD5加密 轉換為大寫返回 String sign=""; try{ String zhi = new String(sb.toString().getBytes("UTF-8")); sign=getMd5Str(zhi).toUpperCase(); }catch (UnsupportedEncodingException e){ e.printStackTrace(); } return sign; } /** * 時間戳和隨機數創建UUID * @return */ public static synchronized String makeUUID() { Date date = new Date(); String dateStr = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(date) + ""; StringBuffer s = new StringBuffer(dateStr); return s.append((new Random().nextInt(900) + 100)).toString(); }//MD5加密 public static String getMd5Str(String sourceStr){ String result = ""; try { MessageDigest md = MessageDigest.getInstance("MD5"); md.update(sourceStr.getBytes()); byte b[] = md.digest(); int i; StringBuffer buf = new StringBuffer(""); for (int offset = 0; offset < b.length; offset++) { i = b[offset]; if (i < 0) i += 256; if (i < 16) buf.append("0"); buf.append(Integer.toHexString(i)); } result = buf.toString(); System.out.println("MD5(" + sourceStr + ",32) = " + result); System.out.println("MD5(" + sourceStr + ",16) = " + buf.toString().substring(8, 24)); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return result; }}

微信支付JS

微信SDK說明:https://mp.weixin.qq.com/wiki

<!DOCTYPE html><html lang="en"><head> <title>微信支付</title> <meta charset="utf-8"/> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, minimum-scale=1.0"/> <meta http-equiv="Access-Control-Allow-Origin" content="*"/> <meta name="description" content="" /> <meta name="author" content="" /> <link href="/CSS/mycss.css" rel="stylesheet" /> <script src="http://cdn.bootcss.com/angular.js/1.5.7/angular.min.js"></script> <script src="http://cdn.bootcss.com/angular.js/1.5.7/angular-animate.min.js"></script> <script src="http://cdn.bootcss.com/angular.js/1.5.7/angular-resource.min.js"></script> <script src="http://cdn.bootcss.com/angular.js/1.5.7/angular-route.min.js"></script> <script src="http://cdn.bootcss.com/angular.js/1.5.7/angular-messages.min.js"></script> <script src="http://cdn.bootcss.com/jquery/1.12.4/jquery.js"></script> <script src="http://res.wx.qq.com/open/js/jweixin-1.1.0.js" type="text/Javascript"></script> <script src="http://cdn.bootcss.com/zepto/1.1.6/zepto.min.js"></script> <script src="/js/pay/pay.js"></script> <script> var myApp=angular.module("myApp",[]); myApp.controller("myController",function ($scope,$location,$http) { //獲取微信js配置簽名(后臺java類:ContacterController.java) var url="/getContacter"; var parObj={} //這里可以使用AJAX替換就是向后臺請求數據。(這是angular的寫法) $http.get(url,{params:parObj}).success(function(wxParm) { if(wxParm.success){ //設置微信支付的配置 getPay(wxParm); } }); //獲取微信支付配置參數 function getPay(wxParm) { //(后臺java類:GetUnifiedOrderController.java) var url="/GetUnifiedOrderController"; var parObj={} //這里可以使用AJAX替換就是向后臺請求數據。(這是angular的寫法) $http.get(url,{params:parObj}).success(function(payParm) { console.log(payParm); //調用pay.js的方法 wxconfigMap(wxParm,payParm); }); } }); </script></head><body ng-app="myApp" ng-controller="myController"> <h1>正在打開微信支付接口.....</h1></body></html>

pay.js代碼

/** * Created by orange on 2016/11/16. */var wxmap;//全局參數map包含微信初始化相關參數var paymap; //微信支付的相關參數//設置微信相關參數function wxconfigMap(wxParm,payParm){ wxmap=wxParm; paymap=payParm; wx.config({ debug: false, appId: 'wxxxxxxx', timestamp: wxmap.time, nonceStr: wxmap.randomStr, signature:wxmap.signature, jsApiList: [ 'chooseWXPay' ] });}//微信接口設置完畢回調方法wx.ready(function () { wx.chooseWXPay({ timestamp: paymap.timeStamp, // 支付簽名時間戳,注意微信jssdk中的所有使用timestamp字段均為小寫。但最新版的支付后臺生成簽名使用的timeStamp字段名需大寫其中的S字符 nonceStr: paymap.nonceStr, // 支付簽名隨機串,不長于 32 位 package: paymap.package_, // 統一支付接口返回的prepay_id參數值,提交格式如:prepay_id=***) signType:paymap.signType, // 簽名方式,默認為'SHA1',使用新版支付需傳入'MD5' paySign: paymap.paySign, // 支付簽名 success: function (res) { // alert('支付成功!'); // 支付成功后的回調函數 } });});wx.error(function (res) { alert(res.errMsg);});

需要警惕地方

1、后臺在進行加密的時候一定要注意大小寫,加密是32位的。 2、獲取統一下單Id的時候 注意body里面的內容要使用[CDATA[]]包含起來。 3、注意測試授權目錄一定是最后一級。 4、微信wx.chooseWXPay({})方法里面的 timeStamp的值是秒數,后臺要用毫秒數除以1000不要弄成毫秒數了。 5、代碼出了bug淡定點笑著面對千萬不要心急喔,加油!!!! 6、demo下載地址: https://pan.baidu.com/s/1i58z33B


上一篇:數據分析之分組拆分

下一篇:隨機 Random

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 吉水县| 和田县| 陈巴尔虎旗| 庆云县| 沅陵县| 嵊泗县| 靖安县| 毕节市| 万全县| 济宁市| 枝江市| 宣武区| 陆良县| 巍山| 富锦市| 辽阳市| 肇庆市| 拉孜县| 宜州市| 郸城县| 清流县| 杭锦后旗| 松溪县| 丁青县| 徐汇区| 伽师县| 象山县| 曲松县| 儋州市| 怀安县| 奉新县| 林口县| 石门县| 武宁县| 左云县| 开封市| 宜宾市| 古浪县| 黄浦区| 农安县| 化隆|