专注收集记录技术开发学习笔记、技术难点、解决方案
网站信息搜索 >> 请输入关键词:
您当前的位置: 首页 > 行业应用

腾讯米宗师接入Demo

发布时间:2010-06-06 17:35:37 文章来源:www.iduyao.cn 采编人员:星星草
腾讯米大师接入Demo
import java.util.*;
  import com.qq.open.OpenApiV3;
  import com.qq.open.ErrorCode;
  import com.qq.open.OpensnsException;
   
  /**
  * OpenAPI V3 SDK 示例代码
  *
  * @version 3.0.0
  * @since jdk1.5
  * @author open.qq.com
  * @copyright © 2012, Tencent Corporation. All rights reserved.
  * @History:
  * 3.0.0 | nemozhang | 2012-03-21 12:01:05 | initialization
  *
  */
   
  public class TestOpenApiV3
  {
  public static void main(String args[])
  {
  // 应用基本信息
  String appid = "100703005";
  String appkey = "a7516cd28bfbfb6738d762a2a86f9741";
   
  // 用户的OpenID/OpenKey
  String openid = "1BCB34776C647F98B0B01061D9E128ED";
  String openkey = "C572333371923B241795D333946E1279";
   
  // OpenAPI的服务器IP
  // 最新的API服务器地址请参考wiki文档: http://wiki.open.qq.com/wiki/API3.0%E6%96%87%E6%A1%A3
  String serverName = "119.147.19.43";
   
  // 所要访问的平台, pf的其他取值参考wiki文档: http://wiki.open.qq.com/wiki/API3.0%E6%96%87%E6%A1%A3
  String pf = "qzone";
   
  OpenApiV3 sdk = new OpenApiV3(appid, appkey);
  sdk.setServerName(serverName);
   
  System.out.println("===========test GetUserInfo===========");
  testGetUserInfo(sdk, openid, openkey, pf);
  }
   
  /**
  * 测试调用UserInfo接口
  *
  */
  public static void testGetUserInfo(OpenApiV3 sdk, String openid, String openkey, String pf)
  {
  // 指定OpenApi Cgi名字
  String scriptName = "/v3/user/get_info";
   
  // 指定HTTP请求协议类型
  String protocol = "http";
   
  // 填充URL请求参数
  HashMap<String,String> params = new HashMap<String, String>();
  params.put("openid", openid);
  params.put("openkey", openkey);
  params.put("pf", pf);
   
  try
  {
  String resp = sdk.api(scriptName, params, protocol);
  System.out.println(resp);
  }
  catch (OpensnsException e)
  {
  System.out.printf("Request Failed. code:%d, msg:%s\n", e.getErrorCode(), e.getMessage());
  e.printStackTrace();
  }
  }
 

}

 

 

腾讯开放平台的接入是非常麻烦的, open.qq.com,腾讯开放平台的文档很多很杂,社交功能的api接口也很多还有。我现在只接了他的登录跟支付。

一、登录。

登录相对来讲还是比较简单的,首先前端sdk要正确接入获取access_token  跟 openid ,然后需要一个https  方式的get请求来取得进一步的信息。

url :https://graph.qq.com/user/get_simple_userinfo?oauth_consumer_key=%s&access_token=%s&openid=%s&clientip=&oauth_version=2.a&scope=all  

填写好自己应用的所有内容。https协议的java实现

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. import java.io.BufferedReader;  
  2. import java.io.DataOutputStream;  
  3. import java.io.IOException;  
  4. import java.io.InputStreamReader;  
  5. import java.net.HttpURLConnection;  
  6. import java.net.URL;  
  7. import java.util.Map;  
  8. import java.util.Map.Entry;  
  9.   
  10. import javax.net.ssl.HostnameVerifier;  
  11. import javax.net.ssl.HttpsURLConnection;  
  12. import javax.net.ssl.SSLSession;  
  13.   
  14. import org.apache.http.HttpEntity;  
  15. import org.apache.http.HttpResponse;  
  16. import org.apache.http.client.ClientProtocolException;  
  17. import org.apache.http.client.methods.HttpPost;  
  18. import org.apache.http.entity.ByteArrayEntity;  
  19. import org.apache.http.impl.client.DefaultHttpClient;  
  20. import org.apache.http.params.HttpConnectionParams;  
  21. import org.apache.http.params.HttpParams;  
  22. import org.slf4j.Logger;  
  23. import org.slf4j.LoggerFactory;  
  24.   
  25.   
  26. public class MyhttpService {  
  27.     private  int read_time_out = 10000;  
  28.     private Logger logger = LoggerFactory.getLogger(MyhttpService.class);  
  29.       
  30.     public MyhttpService() {  
  31.         super();  
  32.     }  
  33.       
  34.     public MyhttpService(int time_out) {  
  35.         read_time_out = time_out;  
  36.     }  
  37.       
  38.     public String doPost(String url, Map<String,String> params){  
  39.         StringBuilder postData = new StringBuilder();  
  40.         for(Entry<String,String> entry:params.entrySet()){  
  41.             if(postData.length()!=0){  
  42.                 postData.append("&");  
  43.             }  
  44.             postData.append(entry.getKey()).append("=").append(entry.getValue());  
  45.         }  
  46.         return service(false, url, postData.toString(), "POST"null);  
  47.     }  
  48.     public String doPost(String url, Map<String,String> params,Map<String,String> headers){  
  49.         StringBuilder postData = new StringBuilder();  
  50.         for(Entry<String,String> entry:params.entrySet()){  
  51.             if(postData.length()!=0){  
  52.                 postData.append("&");  
  53.             }  
  54.             postData.append(entry.getKey()).append("=").append(entry.getValue());  
  55.         }  
  56.         return service(false, url, postData.toString(), "POST", headers);  
  57.     }  
  58.     public String doPost(String url,String body){  
  59.         return service(false, url, body, "POST"null);  
  60.     }  
  61.       
  62.     public String doPost(String url, String postData, Map<String,String> headers){  
  63.         return service(false, url, postData, "POST", headers);  
  64.     }  
  65.       
  66.     public String doGet(String url, Map<String,String> headers){  
  67.         return service(false, url, null"GET", headers);  
  68.     }  
  69.       
  70.     public String doGet(String url){  
  71.         return service(false, url, null"GET"null);  
  72.     }  
  73.       
  74.     public String doHttpsPost(String url, String postData) {  
  75.         return service(true, url, postData, "POST",null);  
  76.     }  
  77.     public String doHttpsPost(String url, Map<String,String> params){  
  78.         return  doHttpsPost(url,params,null);  
  79.     }  
  80.       
  81.     public String doHttpsPost(String url, Map<String,String> params,Map<String,String> headers){  
  82.         StringBuilder postData = new StringBuilder();  
  83.         for(Entry<String,String> entry:params.entrySet()){  
  84.             if(postData.length()!=0){  
  85.                 postData.append("&");  
  86.             }  
  87.             postData.append(entry.getKey()).append("=").append(entry.getValue());  
  88.         }  
  89.         return service(true, url, postData.toString(), "POST", headers);  
  90.     }  
  91.     public String doHttpsGet(String url) {  
  92.         return service(true, url, null"GET",null);  
  93.     }  
  94.       
  95.     private String service(boolean isHttps, String url, String postData, String method, Map<String,String> headers){  
  96.           
  97.         HttpURLConnection conn = null;  
  98.         try {  
  99.             boolean doOutput = postData != null && postData.equals("");  
  100.             conn = isHttps ? createHttpsConn(url, method, doOutput) : createHttpConn(url, method, doOutput);  
  101.   
  102.             fillProperties(conn, headers);  
  103.   
  104.             if(doOutput) writeMsg(conn, postData);  
  105.   
  106.             String msg = readMsg(conn);  
  107.   
  108.             logger.debug(msg);  
  109.   
  110.             return msg;  
  111.         } catch (Exception ex) {  
  112.             logger.error(ex.getMessage(), ex);  
  113.         } finally {  
  114.             if (conn != null) {  
  115.                 conn.disconnect();  
  116.                 conn = null;  
  117.             }  
  118.         }  
  119.         return null;  
  120.     }  
  121.   
  122.     private HttpURLConnection createHttpConn(String url, String method, boolean doOutput) throws IOException {  
  123.         URL dataUrl = new URL(url);  
  124.         HttpURLConnection conn = (HttpURLConnection) dataUrl.openConnection();  
  125.         conn.setReadTimeout(read_time_out);  
  126.         conn.setRequestMethod(method);  
  127.         conn.setDoOutput(doOutput);  
  128.         conn.setDoInput(true);  
  129.         return conn;  
  130.     }  
  131.       
  132.     public static void main(String[] args) {  
  133. //      System.out.println(DigestUtils.md5DigestAsHex("19a98d31-4652-4b94-b7cd-129e8ddaliji11899CNY68appstoreQY7road-16-WAN-0668ddddSHEN-2535-7ROAD-shenqug-lovedede77".getBytes()));  
  134.     }  
  135.   
  136.     private String readMsg(HttpURLConnection conn) throws IOException {  
  137.         return readMsg(conn, "UTF-8");  
  138.     }  
  139.   
  140.     private String readMsg(HttpURLConnection conn, String charSet) throws IOException {  
  141.         BufferedReader reader = null;  
  142.         try{  
  143.             reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), charSet));  
  144.             StringBuilder sb = new StringBuilder();  
  145.   
  146.             String line = null;  
  147.             while ((line = reader.readLine()) != null) {  
  148.                 sb.append(line);  
  149.             }  
  150.   
  151.             return sb.toString();  
  152.         } finally {  
  153.             if(reader != null){  
  154.                 reader.close();  
  155.             }  
  156.         }  
  157.     }  
  158.   
  159.     private void writeMsg(HttpURLConnection conn, String postData) throws IOException {  
  160.         DataOutputStream dos = new DataOutputStream(conn.getOutputStream());  
  161.         dos.write(postData.getBytes());  
  162.         dos.flush();  
  163.         dos.close();  
  164.     }  
  165.   
  166.     private void fillProperties(HttpURLConnection conn, Map<String,String> params) {  
  167.         if(params == null||params.isEmpty()){  
  168.             return;  
  169.         }  
  170.   
  171.         for (Entry<String,String> entry: params.entrySet()) {  
  172.             conn.addRequestProperty(entry.getKey(), entry.getValue());  
  173.         }  
  174.     }  
  175.       
  176.       
  177.     public String httpsPost(String url, String postData) {  
  178.         HttpURLConnection conn = null;  
  179.         try {  
  180.             boolean doOutput = (postData != null && postData.equals(""));//!Strings.isNullOrEmpty(postData);  
  181.             conn = createHttpsConn(url, "POST", doOutput);  
  182.             if (doOutput)  
  183.                 writeMsg(conn, postData);  
  184.   
  185.             return readMsg(conn);  
  186.         } catch (Exception ex) {  
  187.             // ingore  
  188.             // just print out  
  189.             logger.error(ex.getMessage(), ex);  
  190.         } finally {  
  191.             if (conn != null) {  
  192.                 conn.disconnect();  
  193.                 conn = null;  
  194.             }  
  195.         }  
  196.         return null;  
  197.     }  
  198.       
  199.   
  200.     private HttpURLConnection createHttpsConn(String url, String method, boolean doOutput) throws Exception {  
  201.         HostnameVerifier hv = new HostnameVerifier() {  
  202.             public boolean verify(String urlHostName, SSLSession session) {  
  203.                 return true;  
  204.             }  
  205.         };  
  206.   
  207.         HttpsURLConnection.setDefaultHostnameVerifier(hv);  
  208.         trustAllHttpsCertificates();  
  209.   
  210.         URL dataUrl = new URL(url);  
  211.           
  212.         HttpURLConnection conn = (HttpURLConnection) dataUrl.openConnection();  
  213.         conn.setReadTimeout(read_time_out);  
  214.         conn.setRequestMethod(method);  
  215.         conn.setDoOutput(doOutput);  
  216.         conn.setDoInput(true);  
  217.         return conn;  
  218.     }  
  219.       
  220.     private static void trustAllHttpsCertificates() throws Exception {  
  221.   
  222.         //  Create a trust manager that does not validate certificate chains:  
  223.   
  224.         javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];  
  225.           
  226.         javax.net.ssl.TrustManager tm = new miTM();  
  227.   
  228.         trustAllCerts[0] = tm;  
  229.   
  230.         javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance("SSL");  
  231.   
  232.         sc.init(null, trustAllCerts, null);  
  233.   
  234.         javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(  
  235.                 sc.getSocketFactory());  
  236.   
  237.     }  
  238.       
  239.     public static class miTM implements javax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager {  
  240.         public java.security.cert.X509Certificate[] getAcceptedIssuers() {  
  241.             return null;  
  242.         }  
  243.   
  244.         public boolean isServerTrusted(  
  245.                 java.security.cert.X509Certificate[] certs) {  
  246.             return true;  
  247.         }  
  248.   
  249.         public boolean isClientTrusted(  
  250.                 java.security.cert.X509Certificate[] certs) {  
  251.             return true;  
  252.         }  
  253.   
  254.         public void checkServerTrusted(  
  255.                 java.security.cert.X509Certificate[] certs, String authType) throws  
  256.                 java.security.cert.CertificateException {  
  257.             return;  
  258.         }  
  259.   
  260.         public void checkClientTrusted(  
  261.                 java.security.cert.X509Certificate[] certs, String authType) throws  
  262.                 java.security.cert.CertificateException {  
  263.             return;  
  264.         }  
  265.     }  
  266.     /**  
  267.      * 执行一个HTTP POST请求,返回请求响应的内容 
  268.      * @param url        请求的URL地址  
  269.      * @param params 请求的查询参数,可以为null  
  270.      * @return 返回请求响应的内容  
  271.      */   
  272.     public static String doPostforUC(String url, String body) {   
  273.         StringBuffer stringBuffer = new StringBuffer();  
  274.         HttpEntity entity = null;  
  275.         BufferedReader in = null;  
  276.         HttpResponse response = null;  
  277.         try {  
  278.             DefaultHttpClient httpclient = new DefaultHttpClient();  
  279.             HttpParams params = httpclient.getParams();  
  280.             HttpConnectionParams.setConnectionTimeout(params, 20000);  
  281.             HttpConnectionParams.setSoTimeout(params, 20000);  
  282.             HttpPost httppost = new HttpPost(url);  
  283.             httppost.setHeader("Content-Type""application/x-www-form-urlencoded");  
  284.   
  285.             httppost.setEntity(new ByteArrayEntity(body.getBytes("UTF-8")));  
  286.             response = httpclient.execute(httppost);  
  287.               
  288.             entity = response.getEntity();  
  289.             in = new BufferedReader(new InputStreamReader(entity.getContent(),"UTF-8"));  
  290.             String ln;  
  291.             while ((ln = in.readLine()) != null) {  
  292.                 stringBuffer.append(ln);  
  293.                 stringBuffer.append("\r\n");  
  294.             }  
  295.             httpclient.getConnectionManager().shutdown();  
  296.         } catch (ClientProtocolException e) {  
  297.             e.printStackTrace();  
  298.         } catch (IOException e1) {  
  299.             e1.printStackTrace();  
  300.         } catch (IllegalStateException e2) {  
  301.             e2.printStackTrace();  
  302.         } catch (Exception e) {  
  303.             e.printStackTrace();  
  304.         } finally {  
  305.             if (null != in) {  
  306.                 try {  
  307.                     in.close();  
  308.                     in = null;  
  309.                 } catch (IOException e3) {  
  310.                     e3.printStackTrace();  
  311.                 }  
  312.             }  
  313.         }  
  314.         return stringBuffer.toString();  
  315.     }   
  316.   
  317. }  

内容的返回是json格式的,可以从里面找自己需要的内容来解析

 

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. JSONParser jsonParser = new JSONParser(JSONParser.DEFAULT_PERMISSIVE_MODE);  
  2.                     JSONObject obj;  
  3.                     obj = (JSONObject) jsonParser.parse(doHttpsGet);  
  4.                     String code = String.valueOf(obj.get("ret"));  
  5.                     if(code.equals("0")){  
  6.                         String nickName = String.valueOf(obj.get("nickname"));  

后面就是自己服务器的逻辑了。登录相对来讲还是很简单的。

 

二、支付
1、腾讯的支付接口不知道是新开发的,还是涉及太多,总之非常乱,他们的开放平台的wiki上面有,四个服务,应用接入,移动接入,网站接入,腾讯云接入。因为我们是移动游戏所以,应该按照移动接入来接,但是实际上还要涉及应用接入这边的文档。只看一边的文档会发现少很多东西。按照文档接入出现问题。正题。

我手中的文档是 移动接入的sdk下载里面的

,腾讯的支付有两种:第一种是由腾讯来管理我们的支付,举例就是玩家充值的元宝在腾讯服务器上面,这个蛋疼的地方是,以后你所有的元宝操作都要跟腾讯交互,增加、扣除、赠送等等都要写协议去腾讯云处理。所以我们用了另外一种模式,道具购买模式。道具购买模式是直接花q点或者q币购买我们的道具,这个道具就是元宝。

2、这里有一个问题是,sdk里面自带的文档跟wiki上面的不一致,调用的接口也不是一个

这个对我们的影响在于后面的发货接口。发货接口的文档又再wiki上面,所以后面我们回到wiki的时候发现两份文档对不上。sdk文档包括腾讯托管跟我们自己管理元宝两种,第一种因为接口多,所以大部分是将第一种方式的。

3、道具购买服务器需要实现两个接口。购买道具下订单接口。购买结束回调接口。

下单接口需要客户端在登录时候取得  paytoken  openkey  pf  pfkey  然后按照文档以  http  方式连接开放api就可以了。

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. //qq直接购买道具下单界面  
  2.     public String qq_buy_items(String appid,String sessionId ,String openid,String pay_token,String openkey ,String amount,String pf,String pfkey){  
  3.         String appkey = PlatformUtil.QQ_APPKEY;  
  4.         String apiaddress = "119.147.19.43";//qq测试地址  
  5. //        String apiaddress = "openapi.tencentyun.com";//qq正式  
  6.         //pf = "qq_m_qq-10000144-android-10000144-1111";  
  7.         //pfkey = "pfkey";  
  8.         OpenApiV3 openApiV3 = new OpenApiV3(appid, appkey, apiaddress);  
  9.         String zoneid="1";  
  10.           
  11.         Map<String,String> params = new HashMap<String, String>();  
  12.         params.put("openid", openid);  
  13.         params.put("openkey", openkey);  
  14.         params.put("pf", pf);  
  15.         params.put("pfkey",pfkey);  
  16.         params.put("ts", String.valueOf(System.currentTimeMillis()/1000));  
  17.         params.put("pay_token", pay_token);  
  18.         params.put("zoneid", zoneid);  
  19.         params.put("appmode""1");  
  20.         params.put("appid", appid);  
  21.         int iamount = SCUtils.calcScCount(amount+".0");  
  22.         String payitem = String.format("100*1*%s",String.valueOf(iamount));  
  23.         String goodsmeta = "元宝*元宝";  
  24.         String goodsurl = "http://dragon.dl.hoolaigames.com/other/CH.png";  
  25.         String app_metadata = String.format("%s-%s-",sessionId,String.valueOf(amount));  
  26.         params.put("payitem", payitem);  
  27.         params.put("goodsmeta", goodsmeta);  
  28.         params.put("goodsurl", goodsurl);  
  29.         params.put("app_metadata",app_metadata);    //这个在最终透传时候会增加腾讯的内容,*qdqd*qq 告诉我们是用什么方式支付的  
  30. //        params.put("qq_m_qq",String.format("%s,%s,%s", appid,openid,openkey) );  
  31.         try {  
  32.             Map<String,String> cookies = new HashMap<String, String>();  
  33.             cookies.put("session_id", SnsSigCheck.encodeUrl("openid"));  
  34.             cookies.put("session_type", SnsSigCheck.encodeUrl("kp_actoken"));  
  35.             cookies.put("org_loc ",SnsSigCheck.encodeUrl("/mpay/buy_goods_m"));  
  36.             String api = openApiV3.api("/mpay/buy_goods_m", params,null ,"http");  
  37.             return api;  
  38.         } catch (OpensnsException e) {  
  39.             log.error("openApiV3.api invoke failed",e);  
  40.             return "error";  
  41.         }  
  42.     }  

其中的  OpenApiV3 其实可以从开放平台下载,是  http://wiki.open.qq.com/wiki/SDK%E4%B8%8B%E8%BD%BD  里面其实是一些验证以及http的访问。实际接入时候可以下载一个最新的看看。返回值也是一个json

 

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. JSONParser jsonParser = new JSONParser(JSONParser.DEFAULT_PERMISSIVE_MODE);  
  2.                     JSONObject obj;  
  3.                     obj = (JSONObject) jsonParser.parse(payurl);  
  4.                     int ret = (Integer) obj.get("ret");  
  5.                     String msg = (String) obj.get("msg");  
  6.                     String token_id = (String) obj.get("token");  
  7.                     String url_params = (String) obj.get("url_params");  

关于返回值里面参数,文档跟实际的返回有些出入,不一致,token 文档中写的是token_id  但实际返回的是token,这个可以实际debug看下再接收参数。得到的这些值需要发送给前端的sdk,前端的sdk会用这个返回的url 处理剩下的逻辑。

 

4、支付回调。客户端拿到刚才的url 会回传给腾讯,然后腾讯会调用我们在后台配置的回调接口,来通知支付结果,同时我们也要处理道具发放逻辑。这里有一个非常困难的问题 https协议的证书问题。 腾讯的证书最变态的一点是绑定ip地址,当然也是为了安全考虑。腾讯的后台我没有登录,但是应该是配置回调的ip地址,填写回调url  然后腾讯会生成一个绑定ip地址的证书,你需要安装这个证书在那台服务器上面,

发货URL用来给腾讯计费后台回调。用户付费成功后,腾讯计费后台将回调该URL给用户发货。在9001端口后可以是一个cgi或者php的路径。

hosting应用on CVM(即应用部署在腾讯CVM服务器上):
-发货URL只需HTTP协议即可,不需要使用SSL安全协议。
-必须使用9001端口(内网端口,需开发者主动启用,用apache iis或nginx做一个web监听,端口改成9001)。

hosting应用on CEE_V2(即应用部署在腾讯CEE_V2服务器上):
-发货URL只需HTTP协议即可,不需要使用SSL安全协议。
-必须使用9001端口(内网端口,需开发者主动启用,用apache iis或nginx做一个web监听,端口改成9001)。
-路径必须以ceecloudpay开头,即支付相关代码必须都放到应用根目录下的“ceecloudpay”目录下。
-对于CEE其发货URL的IP只能填写为10.142.11.27或者10.142.52.17(详见:CEE_V2访问云支付)。 

non-hosting应用(即应用部署在开发者自己的服务器上):
-发货URL必须使用HTTPS协议。
-必须使用443端口(外网端口)。
-必须填写发货服务器所在运营商(电信/联通)。

这是腾讯官方文档对于这个的解释,总之很麻烦的一个东西,中间遇到什么问题,建议找他们的企业支持。

5、证书的安装。

证书安装很坑爹的一个没有官方文档,官方有一个window浏览器的导入文档,没有linux的。这太无语了。

证书的安装可以安装在apache 或者 nginx 下面,我没有直接安装在tomcat下面,应该也是可以的吧,用apache或者nginx 可以做转发,转发到本地debug什么的。所以,我们用的是nginx做转发。首先腾讯后台下载一个这样的证书包。

这个里面带钥匙的那个需要密码,密码在readme里面,但是其实linux下面并没有用到,这个我估计是原始的密钥文件,可以和那个key生成 crt 文件,但是这里已经是生成好了的 crt 文件所以还是直接用比较好,先给第一个最长的那个起个别的名字。然后上传到 nginx 服务器的 conf 目录下面 ,nginx 在安装服务的时候应该是默认为支持https的 ssl 的,所以一般是不需要重新编译的,如果需要重新编译,可以去网上找找相关资料。如果你的  nginx  支持,那么就剩下一步,修改配置文件。 同样是conf目录下面的  nginx.conf   

 

[plain] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. server {  
  2.         listen       443;  
  3.         server_name  xxxxxxx;  
  4.         ssl                       on;  
  5.         ssl_certificate           oem.crt;  
  6.         ssl_certificate_key       oem.key;  
  7.         ssl_verify_client         off;  
  8.         ssl_session_timeout       5m;  
  9.         ssl_protocols             SSLv2 SSLv3 TLSv1;  
  10.         ssl_ciphers               ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;  
  11.         ssl_prefer_server_ciphers on;  
  12.         ssl_client_certificate      ca.crt;  
  13.         ssl_verify_depth            1;  
  14.   
  15.         location ~  ^/xxxxxr/* {  
  16.                 proxy_pass http://xxxxxx3;  
  17.                 index  index.jsp index.html index.htm;  
  18.                 proxy_set_header        Host $host;  
  19.                 proxy_set_header  X-Real-IP  $remote_addr;  
  20.                 proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;  
  21.         }  
  22.     }  

里面的

[plain] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. ssl_client_certificate  
[plain] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. ssl_certificate  

对应证书里面的名字,修改完成后记得reload    ./nginx -s reload  一下应该就生效了,我是做了转发本地处理的,当然也可以转发到任意服务器或者本机。如果下订单成功但是收不到回调,多半是这个证书的问题,可以看 nginx的log日志看看有没有访问到。如果没有80%都是证书的问题,询问下腾讯的支持让他们帮你查下日志吧,不过等他们反馈,估计你已经找到原因了。

 

6、支付回调的验证,当你终于能收到回调了,恭喜你你就要成功了。

对于支付回调的处理,其实很简单,但是腾讯的就很蛋疼。这就是上面说的蛋疼的问题,没有文档。sdk里面的文档说去看 wiki ,wiki里面的文档貌似不是这一版的,而且sdk文档里面的连接还是去 wiki 的主页,哎。  这里忍不住吐槽太多太乱,大家看上去都差不多,我哪知道是我需要的接口。最终我看到这个貌似像 :

http://wiki.open.qq.com/wiki/%E5%9B%9E%E8%B0%83%E5%8F%91%E8%B4%A7URL%E7%9A%84%E5%8D%8F%E8%AE%AE%E8%AF%B4%E6%98%8E_V3

这个文档上面的参数回调,大部分都是正确的。注意是大部分,因为收到的所有参数都要参与 HmacSHA1 签名,所以一个参数错误就悲剧了,你都不知道去哪里找,贴一下我最终的回调处理。

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. //qq支付回调接口,根据http://wiki.open.qq.com/wiki/%E5%9B%9E%E8%B0%83%E5%8F%91%E8%B4%A7URL%E7%9A%84%E5%8D%8F%E8%AE%AE%E8%AF%B4%E6%98%8E_V3   编写  
  2.     protected void processRequest(HttpServletRequest request, HttpServletResponse response)  
  3.             throws ServletException, IOException  {  
  4.         response.setContentType("text/html;charset=UTF-8");  
  5.         PrintWriter out = response.getWriter();  
  6.         Map<String, Object> obj = new HashMap<String, Object>();  
  7.         try {  
  8.             String openid = request.getParameter("openid");     //根据APPID以及QQ号码生成,即不同的appid下,同一个QQ号生成的OpenID是不一样的。  
  9.             String appid = request.getParameter("appid");       //应用的唯一ID。可以通过appid查找APP基本信息。  
  10.             String ts = request.getParameter("ts");             //linux时间戳。 注意开发者的机器时间与腾讯计费开放平台的时间相差不能超过15分钟。  
  11.             String payitem = request.getParameter("payitem");   //接收标准格式为ID*price*num   G001*10*1  
  12.             String token = request.getParameter("token");       //应用调用v3/pay/buy_goods接口成功返回的交易token  
  13.             String billno = request.getParameter("billno");     //支付流水号(64个字符长度。该字段和openid合起来是唯一的)。  
  14.             String version = request.getParameter("version");   //协议版本 号,由于基于V3版OpenAPI,这里一定返回“v3”。  
  15.             String zoneid = request.getParameter("zoneid");     //在支付营销分区配置说明页面,配置的分区ID即为这里的“zoneid”。  如果应用不分区,则为0。  
  16.             String providetype = request.getParameter("providetype");//发货类型   0表示道具购买,1表示营销活动中的道具赠送,2表示交叉营销任务集市中的奖励发放。  
  17.             //Q点/Q币消耗金额或财付通游戏子账户的扣款金额。可以为空 若传递空值或不传本参数则表示未使用Q点/Q币/财付通游戏子账户。注意,这里以0.1Q点为单位。即如果总金额为18Q点,则这里显示的数字是180。  
  18.             String amt = request.getParameter("amt");             
  19.             String payamt_coins = request.getParameter("payamt_coins");//扣取的游戏币总数,单位为Q点。  
  20.             String pubacct_payamt_coins = request.getParameter("pubacct_payamt_coins");//扣取的抵用券总金额,单位为Q点。  
  21.             String appmeta = request.getParameter("appmeta"); 
  22.             String clientver = request.getParameter("clientver");  
  23.             String sig = request.getParameter("sig");  
  24.               
  25.             String url = "/xxx/xxxx";  
  26.               
  27.             Map<String, String> params = createCallbackParamsMap(openid, appid, ts, payitem, token, billno, version, zoneid,  
  28.                     providetype, amt, payamt_coins, pubacct_payamt_coins, appmeta,clientver);  
  29.             if(SnsSigCheck.verifySig(request.getMethod(), url,params, PlatformUtil.QQ_APPKEY+"&", sig)){  
  30.                   
  31.                 if(ok){  
  32.                       
  33.                 }else{  
  34.                       
  35.                     obj.put("ret"0);  
  36.                     obj.put("msg""ok");  
  37.                 }  
  38.             }else{  
  39.                 log.info("qqPayCallback SnsSigCheck fail.");  
  40.                 obj.put("ret", -5);  
  41.                 obj.put("msg""签名错误");  
  42.             }  
  43.                 String resp = JSONObject.toJSONString(obj);  
  44.                 out.println(resp);  
  45.         } catch (SQLException | DbException | ProtocolException | NumberFormatException | OpensnsException e) {  
  46.             e.printStackTrace();  
  47.         } finally {  
  48.             out.close();  
  49.         }  

中间标红的地方都是有问题的地方,都是坑。首先 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. pubacct_payamt_coins  

是有可能传空的,因为你没有用抵用券对吧,但是记住这个也需要加入签名。  clientver  神坑。我最终也没再文档或者哪里找到这个参数为什么给我传过来,但是你就是传过来了,而且你还必须接收,必须加入签名中去,也许我水平太菜,反正我是没找到这个参数在那个文档上面写了。鄙视

 

createCallbackParamsMap  字面意思就是把参数弄到 map里面 

SnsSigCheck.verifySig  这也是上面下载的那个工具项目中自带的功能,其实就是一个   HmacSHA1  的 utf 格式的签名。可以下载,有兴趣的也可以自己写写。

 (三)总结

腾讯的支付接口应该做的不难,困难在于没有一个明确的文档。

 

参考链接:

/img/2014/08/28/12562187

https://github.com/liujiuwu/OpenApi/blob/master/src/main/java/TestOpenApiV3.java

友情提示:
信息收集于互联网,如果您发现错误或造成侵权,请及时通知本站更正或删除,具体联系方式见页面底部联系我们,谢谢。

其他相似内容:

  • 《松本行弘的程序全世界》之面向对象

    《松本行弘的程序世界》之面向对象 最近读《SICP》把脑细胞搞死大半,还没看完2章,而且看得也是一知半解,实在是受不了了,...

  • GroovyHelp 3.2.7 GA公布

    GroovyHelp 3.2.7 GA发布 GroovyHelp简介   GroovyHelp是一款Javadoc及Groovydoc搜索查阅软件,它能够帮助Java开发人员以...

  • Velocity在Roller中的使用

    Velocity在Roller中的应用 Velocity是java世界中出现比较早,也比较成熟的、性能比较好的、应用也比较广泛的模板框架。   所...

  • Rpc远程调用框架的设计与兑现(2)

    Rpc远程调用框架的设计与实现(2) 接上: 3   基于Json的前后端数据交互 3.1   轻量级的数据交换形式 3.1.1    什么是Jso...

  • excel 单元格的锁定 以及 JXL的兑现方式

    excel 单元格的锁定 以及 JXL的实现方式 在使用excel表格时,有些列是不希望用户可以修改的,诸如审计日志里面确定的部分,而审计...

  • 仓秤跟散料秤:java连接opc Server

    仓秤和散料秤:java连接opc Server 这三篇都是之前写好的,一直没发。 这次一起发出来吧。   java连接硬件很痛苦,特别是对我这...

  • Rpc远程调用框架的设计与兑现(1)

    Rpc远程调用框架的设计与实现(1) Rpc远程调用框架的设计与实现 1     Rpc远程调用框架设计概述 1.1   研究背景 1.1.1...

  • 集合中的线程安全有关问题

    集合中的线程安全问题 一、why? Java中常用的集合框架推荐使用的三个实现:HashSet\ArrayList\HashMap都是线程不安全的.如...

  • Java定时任务的兑现

    Java定时任务的实现 本例依据Java自身提供的接口实现,通过监听器(Listener)和定时器(Timer)定时执行某个任务(Task)。 MyListener: ...

  • java中log日记的使用

    java中log日志的使用 一、介绍  Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控...

热门推荐: