Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android平台接入服務器總結(一)騰訊qq應用寶接入

android平台接入服務器總結(一)騰訊qq應用寶接入

編輯:關於Android編程

騰訊開放平台的接入是非常麻煩的, 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實現

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
import java.util.Map.Entry;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class MyhttpService {
    private  int read_time_out = 10000;
    private Logger logger = LoggerFactory.getLogger(MyhttpService.class);
    
    public MyhttpService() {
        super();
    }
    
    public MyhttpService(int time_out) {
        read_time_out = time_out;
    }
    
    public String doPost(String url, Map params){
        StringBuilder postData = new StringBuilder();
        for(Entry entry:params.entrySet()){
            if(postData.length()!=0){
                postData.append("&");
            }
            postData.append(entry.getKey()).append("=").append(entry.getValue());
        }
        return service(false, url, postData.toString(), "POST", null);
    }
    public String doPost(String url, Map params,Map headers){
        StringBuilder postData = new StringBuilder();
        for(Entry entry:params.entrySet()){
            if(postData.length()!=0){
                postData.append("&");
            }
            postData.append(entry.getKey()).append("=").append(entry.getValue());
        }
        return service(false, url, postData.toString(), "POST", headers);
    }
    public String doPost(String url,String body){
        return service(false, url, body, "POST", null);
    }
    
    public String doPost(String url, String postData, Map headers){
        return service(false, url, postData, "POST", headers);
    }
    
    public String doGet(String url, Map headers){
        return service(false, url, null, "GET", headers);
    }
    
    public String doGet(String url){
        return service(false, url, null, "GET", null);
    }
    
    public String doHttpsPost(String url, String postData) {
        return service(true, url, postData, "POST",null);
    }
    public String doHttpsPost(String url, Map params){
        return  doHttpsPost(url,params,null);
    }
    
    public String doHttpsPost(String url, Map params,Map headers){
        StringBuilder postData = new StringBuilder();
        for(Entry entry:params.entrySet()){
            if(postData.length()!=0){
                postData.append("&");
            }
            postData.append(entry.getKey()).append("=").append(entry.getValue());
        }
        return service(true, url, postData.toString(), "POST", headers);
    }
    public String doHttpsGet(String url) {
        return service(true, url, null, "GET",null);
    }
    
    private String service(boolean isHttps, String url, String postData, String method, Map headers){
        
        HttpURLConnection conn = null;
        try {
            boolean doOutput = postData != null && postData.equals("");
            conn = isHttps ? createHttpsConn(url, method, doOutput) : createHttpConn(url, method, doOutput);

            fillProperties(conn, headers);

            if(doOutput) writeMsg(conn, postData);

            String msg = readMsg(conn);

            logger.debug(msg);

            return msg;
        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
        } finally {
            if (conn != null) {
                conn.disconnect();
                conn = null;
            }
        }
        return null;
    }

    private HttpURLConnection createHttpConn(String url, String method, boolean doOutput) throws IOException {
        URL dataUrl = new URL(url);
        HttpURLConnection conn = (HttpURLConnection) dataUrl.openConnection();
        conn.setReadTimeout(read_time_out);
        conn.setRequestMethod(method);
        conn.setDoOutput(doOutput);
        conn.setDoInput(true);
        return conn;
    }
    
    public static void main(String[] args) {
//      System.out.println(DigestUtils.md5DigestAsHex("19a98d31-4652-4b94-b7cd-129e8ddaliji11899CNY68appstoreQY7road-16-WAN-0668ddddSHEN-2535-7ROAD-shenqug-lovedede77".getBytes()));
    }

    private String readMsg(HttpURLConnection conn) throws IOException {
        return readMsg(conn, "UTF-8");
    }

    private String readMsg(HttpURLConnection conn, String charSet) throws IOException {
        BufferedReader reader = null;
        try{
            reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), charSet));
            StringBuilder sb = new StringBuilder();

            String line = null;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }

            return sb.toString();
        } finally {
            if(reader != null){
                reader.close();
            }
        }
    }

    private void writeMsg(HttpURLConnection conn, String postData) throws IOException {
        DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
        dos.write(postData.getBytes());
        dos.flush();
        dos.close();
    }

    private void fillProperties(HttpURLConnection conn, Map params) {
        if(params == null||params.isEmpty()){
            return;
        }

        for (Entry entry: params.entrySet()) {
            conn.addRequestProperty(entry.getKey(), entry.getValue());
        }
    }
    
    
    public String httpsPost(String url, String postData) {
        HttpURLConnection conn = null;
        try {
            boolean doOutput = (postData != null && postData.equals(""));//!Strings.isNullOrEmpty(postData);
            conn = createHttpsConn(url, "POST", doOutput);
            if (doOutput)
                writeMsg(conn, postData);

            return readMsg(conn);
        } catch (Exception ex) {
            // ingore
            // just print out
            logger.error(ex.getMessage(), ex);
        } finally {
            if (conn != null) {
                conn.disconnect();
                conn = null;
            }
        }
        return null;
    }
    

    private HttpURLConnection createHttpsConn(String url, String method, boolean doOutput) throws Exception {
        HostnameVerifier hv = new HostnameVerifier() {
            public boolean verify(String urlHostName, SSLSession session) {
                return true;
            }
        };

        HttpsURLConnection.setDefaultHostnameVerifier(hv);
        trustAllHttpsCertificates();

        URL dataUrl = new URL(url);
        
        HttpURLConnection conn = (HttpURLConnection) dataUrl.openConnection();
        conn.setReadTimeout(read_time_out);
        conn.setRequestMethod(method);
        conn.setDoOutput(doOutput);
        conn.setDoInput(true);
        return conn;
    }
    
    private static void trustAllHttpsCertificates() throws Exception {

        //  Create a trust manager that does not validate certificate chains:

        javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];
        
        javax.net.ssl.TrustManager tm = new miTM();

        trustAllCerts[0] = tm;

        javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance("SSL");

        sc.init(null, trustAllCerts, null);

        javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(
                sc.getSocketFactory());

    }
    
    public static class miTM implements javax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager {
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        public boolean isServerTrusted(
                java.security.cert.X509Certificate[] certs) {
            return true;
        }

        public boolean isClientTrusted(
                java.security.cert.X509Certificate[] certs) {
            return true;
        }

        public void checkServerTrusted(
                java.security.cert.X509Certificate[] certs, String authType) throws
                java.security.cert.CertificateException {
            return;
        }

        public void checkClientTrusted(
                java.security.cert.X509Certificate[] certs, String authType) throws
                java.security.cert.CertificateException {
            return;
        }
    }
    /** 
     * 執行一個HTTP POST請求,返回請求響應的內容
     * @param url        請求的URL地址 
     * @param params 請求的查詢參數,可以為null 
     * @return 返回請求響應的內容 
     */ 
    public static String doPostforUC(String url, String body) { 
        StringBuffer stringBuffer = new StringBuffer();
        HttpEntity entity = null;
        BufferedReader in = null;
        HttpResponse response = null;
        try {
            DefaultHttpClient httpclient = new DefaultHttpClient();
            HttpParams params = httpclient.getParams();
            HttpConnectionParams.setConnectionTimeout(params, 20000);
            HttpConnectionParams.setSoTimeout(params, 20000);
            HttpPost httppost = new HttpPost(url);
            httppost.setHeader("Content-Type", "application/x-www-form-urlencoded");

            httppost.setEntity(new ByteArrayEntity(body.getBytes("UTF-8")));
            response = httpclient.execute(httppost);
            
            entity = response.getEntity();
            in = new BufferedReader(new InputStreamReader(entity.getContent(),"UTF-8"));
            String ln;
            while ((ln = in.readLine()) != null) {
                stringBuffer.append(ln);
                stringBuffer.append("\r\n");
            }
            httpclient.getConnectionManager().shutdown();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e1) {
            e1.printStackTrace();
        } catch (IllegalStateException e2) {
            e2.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != in) {
                try {
                    in.close();
                    in = null;
                } catch (IOException e3) {
                    e3.printStackTrace();
                }
            }
        }
        return stringBuffer.toString();
    } 

}
內容的返回是json格式的,可以從裡面找自己需要的內容來解析

JSONParser jsonParser = new JSONParser(JSONParser.DEFAULT_PERMISSIVE_MODE);
                    JSONObject obj;
                    obj = (JSONObject) jsonParser.parse(doHttpsGet);
                    String code = String.valueOf(obj.get("ret"));
                    if(code.equals("0")){
                        String nickName = String.valueOf(obj.get("nickname"));
後面就是自己服務器的邏輯了。登錄相對來講還是很簡單的。

二、支付
1、騰訊的支付接口不知道是新開發的,還是涉及太多,總之非常亂,他們的開放平台的wiki上面有,四個服務,應用接入,移動接入,網站接入,騰訊雲接入。因為我們是移動游戲所以,應該按照移動接入來接,但是實際上還要涉及應用接入這邊的文檔。只看一邊的文檔會發現少很多東西。按照文檔接入出現問題。正題。

我手中的文檔是 移動接入的sdk下載裡面的

vcrHo6zS1LrzxOPL+dPQtcTUqrGmstnX97a80qq4+sza0ba9u7ulo6zU9rzToaK/27P9oaLU+cvNtci1yLa80qrQtNCt0unIpcza0bbUxrSmwO2ho8v50tTO0sPH08PBy8HtzeLSu9bWxKPKvaOstcC+37m6wvLEo8q9oaO1wL7fubrC8sSjyr3Kx9axvdO7qHG147vy1d9xsdK5usLyztLDx7XEtcC+36Os1eK49rXAvt++zcrH1KqxpqGjPC9wPgo8cD4yoaLV4sDv09DSu7j2zsrM4srHo6xzZGvA78Pm19S0+LXEzsS1tbj6d2lracnPw+a1xLK70rvWwqOstffTw7XEvdO/2tKysrvKx9K7uPY8L3A+CjxwPjxpbWcgc3JjPQ=="" alt="\">這個對我們的影響在於後面的發貨接口。發貨接口的文檔又再wiki上面,所以後面我們回到wiki的時候發現兩份文檔對不上。sdk文檔包括騰訊托管跟我們自己管理元寶兩種,第一種因為接口多,所以大部分是將第一種方式的。

3、道具購買服務器需要實現兩個接口。購買道具下訂單接口。購買結束回調接口。

下單接口需要客戶端在登錄時候取得 paytoken openkey pf pfkey 然後按照文檔以 http 方式連接開放api就可以了。

//qq直接購買道具下單界面
	public String qq_buy_items(String appid,String sessionId ,String openid,String pay_token,String openkey ,String amount,String pf,String pfkey){
        String appkey = PlatformUtil.QQ_APPKEY;
        String apiaddress = "119.147.19.43";//qq測試地址
//        String apiaddress = "openapi.tencentyun.com";//qq正式
        //pf = "qq_m_qq-10000144-android-10000144-1111";
        //pfkey = "pfkey";
        OpenApiV3 openApiV3 = new OpenApiV3(appid, appkey, apiaddress);
        String zoneid="1";
        
        Map params = new HashMap();
        params.put("openid", openid);
        params.put("openkey", openkey);
        params.put("pf", pf);
        params.put("pfkey",pfkey);
        params.put("ts", String.valueOf(System.currentTimeMillis()/1000));
        params.put("pay_token", pay_token);
        params.put("zoneid", zoneid);
        params.put("appmode", "1");
        params.put("appid", appid);
        int iamount = SCUtils.calcScCount(amount+".0");
        String payitem = String.format("100*1*%s",String.valueOf(iamount));
        String goodsmeta = "元寶*元寶";
        String goodsurl = "http://dragon.dl.hoolaigames.com/other/CH.png";
        String app_metadata = String.format("%s-%s-",sessionId,String.valueOf(amount));
        params.put("payitem", payitem);
        params.put("goodsmeta", goodsmeta);
        params.put("goodsurl", goodsurl);
        params.put("app_metadata",app_metadata);    //這個在最終透傳時候會增加騰訊的內容,*qdqd*qq 告訴我們是用什麼方式支付的
//        params.put("qq_m_qq",String.format("%s,%s,%s", appid,openid,openkey) );
        try {
            Map cookies = new HashMap();
            cookies.put("session_id", SnsSigCheck.encodeUrl("openid"));
            cookies.put("session_type", SnsSigCheck.encodeUrl("kp_actoken"));
            cookies.put("org_loc ",SnsSigCheck.encodeUrl("/mpay/buy_goods_m"));
            String api = openApiV3.api("/mpay/buy_goods_m", params,null ,"http");
            return api;
        } catch (OpensnsException e) {
            log.error("openApiV3.api invoke failed",e);
            return "error";
        }
    }
其中的 OpenApiV3 其實可以從開放平台下載,是 http://wiki.open.qq.com/wiki/SDK%E4%B8%8B%E8%BD%BD 裡面其實是一些驗證以及http的訪問。實際接入時候可以下載一個最新的看看。返回值也是一個json

JSONParser jsonParser = new JSONParser(JSONParser.DEFAULT_PERMISSIVE_MODE);
                    JSONObject obj;
                    obj = (JSONObject) jsonParser.parse(payurl);
                    int ret = (Integer) obj.get("ret");
                    String msg = (String) obj.get("msg");
                    String token_id = (String) obj.get("token");
                    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

server {
        listen       443;
        server_name  xxxxxxx;
        ssl                       on;
        ssl_certificate           oem.crt;
        ssl_certificate_key       oem.key;
        ssl_verify_client         off;
        ssl_session_timeout       5m;
        ssl_protocols             SSLv2 SSLv3 TLSv1;
        ssl_ciphers               ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
        ssl_prefer_server_ciphers on;
        ssl_client_certificate      ca.crt;
        ssl_verify_depth            1;

        location ~  ^/xxxxxr/* {
                proxy_pass http://xxxxxx3;
                index  index.jsp index.html index.htm;
                proxy_set_header        Host $host;
                proxy_set_header  X-Real-IP  $remote_addr;
                proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
裡面的
ssl_client_certificate
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 簽名,所以一個參數錯誤就悲劇了,你都不知道去哪裡找,貼一下我最終的回調處理。

//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   編寫
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException  {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        Map obj = new HashMap();
        try {
            String openid = request.getParameter("openid");     //根據APPID以及QQ號碼生成,即不同的appid下,同一個QQ號生成的OpenID是不一樣的。
            String appid = request.getParameter("appid");       //應用的唯一ID。可以通過appid查找APP基本信息。
            String ts = request.getParameter("ts");             //linux時間戳。 注意開發者的機器時間與騰訊計費開放平台的時間相差不能超過15分鐘。
            String payitem = request.getParameter("payitem");   //接收標准格式為ID*price*num   G001*10*1
            String token = request.getParameter("token");       //應用調用v3/pay/buy_goods接口成功返回的交易token
            String billno = request.getParameter("billno");     //支付流水號(64個字符長度。該字段和openid合起來是唯一的)。
            String version = request.getParameter("version");   //協議版本 號,由於基於V3版OpenAPI,這裡一定返回“v3”。
            String zoneid = request.getParameter("zoneid");     //在支付營銷分區配置說明頁面,配置的分區ID即為這裡的“zoneid”。  如果應用不分區,則為0。
            String providetype = request.getParameter("providetype");//發貨類型   0表示道具購買,1表示營銷活動中的道具贈送,2表示交叉營銷任務集市中的獎勵發放。
            //Q點/Q幣消耗金額或財付通游戲子賬戶的扣款金額。可以為空 若傳遞空值或不傳本參數則表示未使用Q點/Q幣/財付通游戲子賬戶。注意,這裡以0.1Q點為單位。即如果總金額為18Q點,則這裡顯示的數字是180。
            String amt = request.getParameter("amt");           
            String payamt_coins = request.getParameter("payamt_coins");//扣取的游戲幣總數,單位為Q點。
            String pubacct_payamt_coins = request.getParameter("pubacct_payamt_coins");//扣取的抵用券總金額,單位為Q點。
            String appmeta = request.getParameter("appmeta");
            String clientver = request.getParameter("clientver");
            String sig = request.getParameter("sig");
            
            String url = "/xxx/xxxx";
            
            Map params = createCallbackParamsMap(openid, appid, ts, payitem, token, billno, version, zoneid,
                    providetype, amt, payamt_coins, pubacct_payamt_coins, appmeta,clientver);
            if(SnsSigCheck.verifySig(request.getMethod(), url,params, PlatformUtil.QQ_APPKEY+"&", sig)){
                
                if(ok){
                    
                }else{
                    
                    obj.put("ret", 0);
                    obj.put("msg", "ok");
                }
            }else{
                log.info("qqPayCallback SnsSigCheck fail.");
                obj.put("ret", -5);
                obj.put("msg", "簽名錯誤");
            }
                String resp = JSONObject.toJSONString(obj);
                out.println(resp);
        } catch (SQLException | DbException | ProtocolException | NumberFormatException | OpensnsException e) {
            e.printStackTrace();
        } finally {
            out.close();
        }
中間標紅的地方都是有問題的地方,都是坑。首先
pubacct_payamt_coins
是有可能傳空的,因為你沒有用抵用券對吧,但是記住這個也需要加入簽名。 clientver 神坑。我最終也沒再文檔或者哪裡找到這個參數為什麼給我傳過來,但是你就是傳過來了,而且你還必須接收,必須加入簽名中去,也許我水平太菜,反正我是沒找到這個參數在那個文檔上面寫了。鄙視

createCallbackParamsMap 字面意思就是把參數弄到 map裡面

SnsSigCheck.verifySig 這也是上面下載的那個工具項目中自帶的功能,其實就是一個 HmacSHA1 的 utf 格式的簽名。可以下載,有興趣的也可以自己寫寫。

(三)總結

騰訊的支付接口應該做的不難,困難在於沒有一個明確的文檔。




  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved