1. 應用調用應用服務器進行下單;
2. 應用調用360SDK支付接口;
3. 360SDK展示支付頁面,引導用戶完成支付流程;
a. 若調用接口時指定金額,則顯示固定金額支付界面;
b. 若調用接口時不指定金額,則顯示不固定金額的支付界面;
4. 支付結束或退出360SDK支付客戶端界面后,360SDK客戶端會返回支付結果給應用客戶端的支付模塊;
5. 支付成功后,360服務器回調應用服務器上的通知接口,通知支付結果;
6. (可選) 應用服務器調用360服務器端訂單確認接口,驗證支付通知的合法性;
功能說明:
應用調用360SDK支付接口時,360SDK彈出支付選擇界面。用戶在界面上完成支付。
關于應用方訂單號的問題:應用方需要生成自己的訂單號app_order_id,應用訂單號不能重復提交,并且一個應用訂單不管是否支付成功,都只能支付一次。這樣做是為了避免重復支付。通知應用方加錢時,會返回應用訂單號, 同時提供360訂單號。
Access token由于與當前登錄用戶id綁定,因此可以加強支付安全性。但要注意token的時間期限(有效期為10小時)。過期后調用支付接口會失敗。游戲可以引導用戶重新登錄.
接口示例:
注意:
1. 必選參數不能為空, 不能為0,否則支付失敗。
2. 參數名,以ProtocolKeys中定義的常量為準。
/** * 使用360SDK的支付接口 * * @param isLandScape 是否橫屏顯示支付界面 * @param isFixed 是否定額支付 */ protected void doSdkPay(final boolean isLandScape, final boolean isFixed) { if(!isAccessTokenValid) { Toast.makeText(SdkUserBaseActivity.this, R.string.access_token_invalid, Toast.LENGTH_SHORT).show(); return; } if(!isQTValid) { Toast.makeText(SdkUserBaseActivity.this, R.string.qt_invalid, Toast.LENGTH_SHORT).show(); return; } // 支付基礎參數 Intent intent = getPayIntent(isLandScape, isFixed); // 必需參數,使用360SDK的支付模塊。 intent.putExtra(ProtocolKeys.FUNCTION_CODE, ProtocolConfigs.FUNC_CODE_PAY); // 可選參數,登錄界面的背景圖片路徑,必須是本地圖片路徑 intent.putExtra(ProtocolKeys.UI_BACKGROUND_PICTRUE, ""); Matrix.invokeActivity(this, intent, mPayCallback); } /** * 生成調用360SDK支付接口基礎參數的Intent * * @param isLandScape 是否橫屏顯示登錄界面 * @param isFixed 是否定額支付 * * @return Intent */ protected Intent getPayIntent(boolean isLandScape, boolean isFixed) { Bundle bundle = new Bundle(); QihooPayInfo pay = getQihooPayInfo(isFixed); // 界面相關參數,360SDK界面是否以橫屏顯示。 bundle.putBoolean(ProtocolKeys.IS_SCREEN_ORIENTATION_LANDSCAPE, isLandScape); // 可選參數,登錄界面的背景圖片路徑,必須是本地圖片路徑 bundle.putString(ProtocolKeys.UI_BACKGROUND_PICTRUE, ""); // *** 以下非界面相關參數 *** // 設置QihooPay中的參數。 // 必需參數,用戶access token,要使用注意過期和刷新問題,最大64字符。 bundle.putString(ProtocolKeys.ACCESS_TOKEN, pay.getAccessToken()); // 必需參數,360賬號id。 bundle.putString(ProtocolKeys.QIHOO_USER_ID, pay.getQihooUserId()); // 必需參數,所購買商品金額, 以分為單位。金額大于等于100分,360SDK運行定額支付流程; 金額數為0,360SDK運行不定額支付流程。 bundle.putString(ProtocolKeys.AMOUNT, pay.getMoneyAmount()); // 必需參數,所購買商品名稱,應用指定,建議中文,最大10個中文字。 bundle.putString(ProtocolKeys.PRODUCT_NAME, pay.getProductName()); // 必需參數,購買商品的商品id,應用指定,最大16字符。 bundle.putString(ProtocolKeys.PRODUCT_ID, pay.getProductId()); // 必需參數,應用方提供的支付結果通知uri,最大255字符。360服務器將把支付接口回調給該uri,具體協議請查看文檔中,支付結果通知接口–應用服務器提供接口。 bundle.putString(ProtocolKeys.NOTIFY_URI, pay.getNotifyUri()); // 必需參數,游戲或應用名稱,最大16中文字。 bundle.putString(ProtocolKeys.APP_NAME, pay.getAppName()); // 必需參數,應用內的用戶名,如游戲角色名。 若應用內綁定360賬號和應用賬號,則可用360用戶名,最大16中文字。(充值不分區(qū)服,充到統一的用戶賬戶,各區(qū)服角色均可使用)。 bundle.putString(ProtocolKeys.APP_USER_NAME, pay.getAppUserName()); // 必需參數,應用內的用戶id。 // 若應用內綁定360賬號和應用賬號,充值不分區(qū)服,充到統一的用戶賬戶,各區(qū)服角色均可使用,則可用360用戶ID最大32字符。 bundle.putString(ProtocolKeys.APP_USER_ID, pay.getAppUserId()); // 必需參數,應用訂單號,應用內必須唯一,最大32字符。 bundle.putString(ProtocolKeys.APP_ORDER_ID, pay.getAppOrderId()); // 可選參數,應用擴展信息1,原樣返回,最大255字符。 bundle.putString(ProtocolKeys.APP_EXT_1, pay.getAppExt1()); // 可選參數,應用擴展信息2,原樣返回,最大255字符。 bundle.putString(ProtocolKeys.APP_EXT_2, pay.getAppExt2()); Intent intent = new Intent(this, ContainerActivity.class); intent.putExtras(bundle); return intent; }
callback的 json數據格式:
成功返回
{error_code: 0, error_msg: "支付成功", content:""}
失敗返回
{error_code: 1, error_msg: "支付失敗", content:""}
取消返回
{error_code: -1, error_msg: "支付取消", content:""}
支付正在進行
{error_code: -2, error_msg: "正在進行", content:""}
access_token失效
{error_code: 4010201, error_msg: "token已失效", content:""}
QT失效
{error_code: 4009911, error_msg: "登錄已失效", content:""}
callback示例:
/** * 支付的回調 */ protected IDispatcherCallback mPayCallback = new IDispatcherCallback() { @Override public void onFinished(String data) { Log.d(TAG, "mPayCallback, data is " + data); if(TextUtils.isEmpty(data)) { return; } boolean isCallbackParseOk = false; JSONObject jsonRes; try { jsonRes = new JSONObject(data); // error_code 狀態(tài)碼: 0 支付成功, -1 支付取消, 1 支付失敗, -2 支付進行中。 // error_msg 狀態(tài)描述 int errorCode = jsonRes.optInt("error_code"); isCallbackParseOk = true; switch (errorCode) { case 0: case 1: case -1: case -2: { isAccessTokenValid = true; String errorMsg = jsonRes.optString("error_msg"); String text = getString(R.string.pay_callback_toast, errorCode, errorMsg); Toast.makeText(SdkUserBaseActivity.this, text, Toast.LENGTH_SHORT).show(); } break; case 4010201: isAccessTokenValid = false; Toast.makeText(SdkUserBaseActivity.this, R.string.access_token_invalid, Toast.LENGTH_SHORT).show(); break; case 4009911: //QT失效 isQTValid = false; Toast.makeText(SdkUserBaseActivity.this, R.string.qt_invalid, Toast.LENGTH_SHORT).show(); break; default: break; } } catch (JSONException e) { e.printStackTrace(); } // 用于測試數據格式是否異常。 if (!isCallbackParseOk) { Toast.makeText(SdkUserBaseActivity.this, getString(R.string.data_format_error), Toast.LENGTH_LONG).show(); } } };
應用客戶端調用支付接口時, 需指定支付結果的通知回調地址notify_uri. 支付完成后, 360服務器會把支付結果以GET方式通知到此地址 (建議應用服務端接口同時支持GET和POST). 應用接收驗證參數后, 給用戶做游戲內充值.
應用服務端通知接口在接收到通知消息后, 需回應ok(僅返回小寫ok這兩個字母,不要有其它輸出), 表示通知已經接收. 如果回應其他值或者不回應, 則被認為通知失敗, 360會嘗試多次通知. 這個機制用來避免掉單。
應用應做好接收到多次通知的準備, 防止多次加錢. 同時, 需要特別注意的是, 回應的ok表示應用已經正常接到消息, 無需繼續(xù)發(fā)送通知. 它不表示訂單成功與否, 或者應用處理成功與否. 對于重復的通知, 應用可能發(fā)現訂單已經成功處理完畢, 無需繼續(xù)處理, 也要返回ok(僅返回小寫ok這兩個字母,不要有其它輸出). 否則, 360會認為未成功通知, 會繼續(xù)發(fā)送通知.
支付結果通知的參數如下:
參數 | 必選 | 參數類型 | 最大長度 | 參數說明 | 是否參與簽名 |
app_key | Y | varchar | 32 | 應用app key | Y |
product_id | Y | varchar | 36 | 應用自定義的商品id | Y |
amount | Y | int unsigned | 11 | 總價,以分為單位 | Y |
app_uid | Y | varchar | 50 | 應用分配給用戶的id | Y |
app_ext1 | N | varchar | 255 | 應用擴展信息1原樣返回 | Y |
app_ext2 | N | varchar | 255 | 應用擴展信息2原樣返回 | Y |
user_id | Y | bigint unsigned | 20 | 360賬號id | Y |
order_id | Y | bigint unsigned | 20 | 360返回的支付訂單號 | Y |
gateway_flag | Y | varchar | 16 | 如果支付返回成功,返回success 應用需要確認是success才給用戶加錢 | Y |
sign_type | Y | varchar | 8 | 定值 md5 | Y |
app_order_id | N | varchar | 64 | 應用訂單號 支付請求時傳遞,原樣返回 | Y |
sign_return | Y | varchar | 32 | 應用回傳給訂單核實接口的參數 不加入簽名校驗計算 | N |
sign | Y | varchar | 32 | 簽名 | N |
應用接收到支付平臺回調的請求,參見附錄的簽名算法對參數進行簽名,然后和平臺傳遞的簽名sign比較,從而校驗平臺請求的合法性.
通知消息樣例:
order_id=1211090012345678901&app_key=1234567890abcdefghijklmnopqrstuv&product_id=p1&amount=101&app_uid=123456789&app_ext1=XXX201211091985&app_order_id=order1234&user_id=987654321&sign_type=md5&gateway_flag=success&sign=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&sign_return=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
樣例的簽名字段排列 (列出來僅供參考, 請根據實際參數情況用程序排序產生, 不要寫死在程序里)
amount, app_ext1, app_key, app_order_id, app_uid, gateway_flag, order_id, product_id, sign_type, user_id
樣例的簽名串
101#XXX201211091985#1234567890abcdefghijklmnopqrstuv#order1234#123456789#success#1211090012345678901#p1#md5#987654321# 應用 app_secret
1. 驗證接口地址為: http://mgame.#/pay/order_verify.json
2. 為了安全起見,驗證參數不需要傳client_id,client_secret參數,如果傳了服務端會報錯
3. 需要計算簽名
為了防止偽造的支付成功通知, 應用可以使用本接口做通知數據的校驗.把支付結果通知接口(4.2.2節(jié))收到的通知消息里的參數, 計算簽名后調用接口, 即可校驗數據是否正確.
接口地址:
http://mgame.#/pay/order_verify.json?參數
參數說明:
參數均來自應用加錢接口收到的支付通知消息, 原樣提供即可。
如果參數提供正確, 訂單核實接口返回為json格式數據.
驗證成功返回
{"ret":"verified"}
驗證不成功返回
{"ret":"{錯誤信息}"}
返回結果中可能的錯誤信息包括
更多建議: