mozilla
您的搜尋結果

    應用程式內部付費 (In-app payments)

    navigator.mozPay API 可讓網頁內容執行數位貨品的付款作業,並能接收由付款服務商所傳來的購買確認訊息。我們也針對此 API 建構了 Web 付款服務商,讓你能取得數位貨品的款項。本文將說明該如何使用 navigator.mozPay API 與 Web 付款服務商的服務,以達到應用程式內付款 (In-app payments)。

    另外現正開發「fxPay」付款處理機制。FxPay 不會要求開發者必須架設伺服器以進行購買行為驗證,可算是更完整的付款方式。

    In-app payments 概述

    讓你為自己的 App 添加 In-app payments 機制,與其運作的方法:

    • 登入 Firefox Marketplace 開發者交流中心 (Developer Hub)。
    • 上傳 App、將 App 設定為 Paid 或 In-app 付款、產生應用程式金鑰 (Application Key) 與應用程式安全金鑰 (Application Secret)。
    • App 將透過上述的安全金鑰 (Secret) 簽署 JWT 請求,並呼叫 navigator.mozPay(...) 而開始付款作業
    • 系統將另開一個特殊視窗執行付款流程
      • 消費者若尚未登入,則以 Mozilla Persona 登入
      • 消費者輸入自己的 PIN 碼
      • 消費者透過電信帳單或信用卡付費
    • 消費者關閉視窗之後,你的 App 就會收到 JavaScript 回呼 (Callback)
    • 你的 App 伺服器將接收已簽署的 POST 請求,內含的 Mozilla 交易 ID 將指出已成功完成購買程序
    • 所得金額將直接匯入你的銀行帳戶

    navigator.mozPay API 目前限用於 Firefox OS。你同樣可透過 Firefox OS 應用程式管理員 (App Manager) 測試此 API。

    注意:如果是在 Firefox OS 1.2 裝置上測試,只要該裝置內並無 SIM 卡,則 mozPay 呼叫將失敗。但消費者只要裝入 SIM 卡就可解決此問題。目前市面上販售的 Firefox OS 裝置均未安裝 Firefox 1.2。若要進一步了解,可參閱 bug 989022

    逐步設定 In-app payment

    接著說明該如何設定 In-app payment。

    取得測試用的付款金鑰 (Payment Key)

    在登入至 Firefox Marketplace 開發者交流中心時,可前往 In-App Payment Keys 頁面取得應用程式金鑰與安全金鑰以利測試。雖然金鑰只能讓你模擬 In-app payments,但已足以因應相關測試。在將自己的 App 提交至 Marketplace 審核之前,應該先多嘗試相關模擬。請參閱付款模擬的相關說明。

    取得真正的付款金鑰

    在將自己的 App 提交至 Firefox Marketplace 開發者交流中心時, 系統將要求你設定付款條件。此時請選擇 App 的價格 (你也可能想免費提供),接著勾選你接受 In-app payments 的選項。在設定自己的銀行帳戶之後,前往「Manage In-App Payments」頁面取得應用程式金鑰與安全金鑰,才能執行真正的付款作業。

    透過隱私設定或類似檔案,可在自己的 App 伺服器中儲存應用程式安全金鑰。

    重要:請確認沒有任何人可讀取你的應用程式安全金鑰。絕對不要在用戶端披露該項資訊。

    設定 App

    先假設你在設計某個 Open Web App 的冒險遊戲,而你想販售「魔力獨角獸」物品,讓玩家能擁有遊戲優勢。你可設定美金 $1.99、歐元 €1.89,或任何幣值均可。接著將說明該如何設定後端伺服器,並撰寫前端程式碼而透過 navigator.mozPay 銷售產品。

    設定自己的伺服器以簽署 JWT

    因為用來簽署的應用程式安全金鑰絕對不能公開,所以你必須在伺服端簽署 JSON Web Tokens (JWTs);而非用戶端。回到剛剛冒險遊戲要賣魔力獨角獸的例子,你要在自己的伺服器上建立如 /sign-jwt 的網址。如此可建立 JSON 物件以定義產品名稱、定價等。可參閱 Web Payment API 規格以了解完整的 JWT 格式。範例如下:

    {
      "iss": APPLICATION_KEY,
      "aud": "marketplace.firefox.com",
      "typ": "mozilla/payments/pay/v1",
      "iat": 1337357297,
      "exp": 1337360897,
      "request": {
        "id": "915c07fc-87df-46e5-9513-45cb6e504e39",
        "pricePoint": 10,
        "name": "Magical Unicorn",
        "description": "Adventure Game item",
        "icons": {
          "64": "https://yourapp.com/img/icon-64.png",
          "128": "https://yourapp.com/img/icon-128.png"
        },
        "productData": "user_id=1234&my_session_id=XYZ",
        "postbackURL": "https://yourapp.com/payments/postback",
        "chargebackURL": "https://yourapp.com/payments/chargeback",
        "defaultLocale": "en",
        "locales": {
          "de": {
            "name": "Magisches Einhorn",
            "description": "Adventure Game Artikel"
          }
        }
      }
    }

    Web Payment API 規格將詳細解釋格式。此處列出幾個重點:

    • iss (issuer) 將對應你從 Firefox Marketplace 開發者交流中心所取得的 App 金鑰。
    • aud (audience) 應設定為 marketplace.firefox.com
    • request.id 均專屬對應至你的各個 App 產品。
    • 在購買當下,request.pricePoint 將展開為價格與幣別。你必須將之設定為有效的價格點數
    • request.productData 最多可容納 255 個字元的字串。當你接收到回傳的 postback 時,可讓你核對 App 的狀態。
    • request.postbackURLrequest.chargebackURL 需指向你伺服器網址的有效、絕對路徑。在 Mozilla 正式上線的服務環境中,網址均必須是 HTTPS。
    • request.icons 物件 (選填) 是你販售商品的圖示網址,其值為寬/高像素值 (圖像需為正方形)。Mozilla 的付款服務商將於付款確認頁面上使用你的 64 像素圖像。若你並未指定 64 像素的圖像,則將依照字型取得最大的圖示並將之縮放。針對首次購買該 App 的消費者,則由付款服務商在背景取得圖示,所以消費者不會立刻看到圖示。若你變更圖示,則將於 24 小時之內顯示新圖示。
    • request.defaultLocale 將敘述 In-app 產品目前的語言。除非必須定義 locales ,否則此亦為選填物件。
    • request.locales 物件 (選填) 將對應一或多個地區而重新定義 In-app 產品所內含的資料,且此處 UI 將根據存取裝置的語言而提供翻譯過的內容。舉例來說,如果有義大利消費者安裝了你的 App,你應該也想提供義大利文的 UI 介面。各個地區語言的輸入項均已鍵入語言標籤 (RFC 4646) ,並包含你所要取代的標籤。你可以只重新定義 namedescription 就好。但若定義了 locales 也就必須定義 defaultLocale

    在 Python (使用 PyJWT) 程式碼中,你可簽署並編碼上述的請求路徑如下:

    import jwt
    signed_request = jwt.encode(request_dict, application_secret, algorithm='HS256')

    此程式碼將為 JWT (使用應用程式安全金鑰) 進行簽章,並使用 HMAC SHA 256 演算法。在編碼過後就如下列:

    eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.IntcImF1ZFwiOiBcIm1hcmtldHBsYWNlLm1vemlsbGEub3JnXCIsIFwiaXNzXCI6IFwiQVBQLTEyM1wiLCBcInJlcXVlc3RcIjoge1wiY3VycmVuY3lcIjogXCJVU0RcIiwgXCJwcmljZVwiOiBcIjAuOTlcIiwgXCJuYW1lXCI6IFwiVmlydHVhbCAzRCBHbGFzc2VzXCIsIFwicHJvZHVjdGRhdGFcIjogXCJBQkMxMjNfREVGNDU2X0dISV83ODkuWFlaXCIsIFwiZGVzY3JpcHRpb25cIjogXCJWaXJ0dWFsIDNEIEdsYXNzZXNcIn0sIFwiZXhwXCI6IFwiMjAxMi0wMy0yMVQxMTowOTo1Ni43NTMxNDFcIiwgXCJpYXRcIjogXCIyMDEyLTAzLTIxVDEwOjA5OjU2LjgxMDQyMFwiLCBcInR5cFwiOiBcIm1vemlsbGEvcGF5bWVudHMvcGF5L3YxXCJ9Ig.vl4E31_5H3t5H_mM8XA69DqypCqdACVKFy3kXz9EmTI

    如上面章節所述,在 JWT 經過編碼/簽章之後,即可透過其用戶端碼而供你的 App 所使用。

    設定購買按鈕

    現在你已經有後端可為自己的產品產生 JWT 了。接著透過 navigator.mozPay 提供前端程式碼的撰寫範例。請確實在自己的 App 中提供按鈕,以利消費者購買產品。例如:

    <button id="purchase">Purchase Magical Unicorn</button>

    點選購買按鈕之後,你的 App 應會簽署 JSON Web Token (JWT) 並呼叫 navigator.mozPay。下列為 jQuery 使用範例:

    $('#purchase button').click(function() {
      // The purchase is now pending...
      $.post('/sign-jwt', {})
        .done(function(signedJWT) {
          var request = navigator.mozPay([signedJWT]);
          request.onsuccess = function() {
            waitForPostback();
          };
          request.onerror = function() {
            console.log('navigator.mozPay() error: ' + this.error.name);
          }
        })
        .fail(function() {
          console.error('Ajax post to /sign-jwt failed');
        });
    });
    
    function waitForPostback() {
      // Poll your server until you receive a postback with a JWT.
      // If the JWT signature is valid then you can dispurse the Magical Unicorn
      // product to your customer.
      // For bonus points, use Web Sockets :)
    }

    上列程式碼將送出 Ajax 請求至你伺服器上的 /sign-jwt 網址。該網址所簽署的 JSON blob 將包含產品/價格資訊,並以純文字檔回傳 JWT。而 Ajax 處理器 (Handler) 將傳送該 JWT 進入 navigator.mozPay 並等待,直到付款服務商將購買確認訊息送至你的伺服器上。若送過來的 JWT 簽章通過驗證為有效,你就可將虛擬商品交付給消費者。

    於伺服器上處理 Postback

    在正式販售出出自己的 App 產品之前,必須先等待 Marketplace 回傳購買確認訊息;此及所謂的「Postback」。此由 marketplace.firefox.com 傳送出「POST」確認通知 (即 1 組 JWT),至原始付款請求所指定的 request.postbackURL

    而此「POST」具備 application/x-www-form-urlencodedContent-Type,且亦可於 notice 參數中找到此 JWT。在你的伺服器框架中,你可透過如 request.POST['notice'] 來存取此 JWT。

    此 JWT 通知具備所有的付款請求欄位與 1 組交易 ID,並以 Firefox Marketplace 開發者交流中心取得的應用程式安全金鑰而完成簽章。當你收到 Postback 並驗證簽章之後,隨即完成購買程序。若你無法辨別 JWT 的簽章,就可能不是 Marketplace 所傳送的 JWT,你可逕行忽略。

    Web Payment API 規格即解釋了 Postback 的細節。Postback 內含原始請求,且添增的新反應參數亦包含 Mozilla 的特定交易 ID。範例如下:

    {
      "iss": "marketplace.firefox.com",
      "aud": APPLICATION_KEY,
      "typ": "mozilla/payments/pay/postback/v1",
      "exp": 1337370900,
      "iat": 1337360900,
      "request": {
        "id": "915c07fc-87df-46e5-9513-45cb6e504e39",
        "pricePoint": 10,
        "name": "Magical Unicorn",
        "description": "Adventure Game item",
        "icons": {
          "64": "https://yourapp.com/img/icon-64.png",
          "128": "https://yourapp.com/img/icon-128.png"
        },
        "productData": "user_id=1234&my_session_id=XYZ",
        "postbackURL": "https://yourapp.com/payments/postback",
        "chargebackURL": "https://yourapp.com/payments/chargeback",
        "defaultLocale": "en",
        "locales": {
          "de": {
            "name": "Magisches Einhorn",
            "description": "Adventure Game Artikel"
          }
        }
      },
      "response": {
        "transactionID": "webpay:84294ec6-7352-4dc7-90fd-3d3dd36377e9",
        "price": {"amount": "0.99", "currency": "CAD"}
      }
    }

    列出 Postback 的幾項重點:

    • 必將納入你的原始付款請求。
    • iss (issuer) 必為 marketplace.firefox.com。
    • aud (audience) 設定為你的應用程式金鑰。
    • 以你的應用程式安全金鑰簽署 JWT。
    • response.transactionID 專屬於 Mozilla 的 Web Payment Provider。
    • response.price 則為客戶實際使用的金額與幣別。

    回應 Postback

    App 必須透過純文字的 HTTP 回應 (其內僅含交易 ID),對 Postback 做出回應。例如:

    HTTP/1.1 200 OK
    Content-Type: text/plain
    
    webpay:84294ec6-7352-4dc7-90fd-3d3dd36377e9

    於伺服器上處理 Chargeback

    如果交易過程發生問題 (如消費者帳戶的餘額不足),則 Marketplace 將傳送退款通知 (即 POST 過的 JWT)。Chargeback 與 Postback 同樣都會傳送到 App,但 Chargeback 送達的時間較晚。該 POST 具備 application/x-www-form-urlencodedContent-Type,且可於 notice 參數中找到該 JWT。下列為解碼後的 Chargeback 通知範例:

    {
      "iss": "marketplace.firefox.com",
      "aud": APPLICATION_KEY,
      "typ": "mozilla/payments/pay/chargeback/v1",
      "exp": 1337370900,
      "iat": 1337360900,
      "request": {
        "id": "915c07fc-87df-46e5-9513-45cb6e504e39",
        "pricePoint": 10,
        "name": "Magical Unicorn",
        "description": "Adventure Game item",
        "icons": {
          "64": "https://yourapp.com/img/icon-64.png",
          "128": "https://yourapp.com/img/icon-128.png"
        },
        "productData": "user_id=1234&my_session_id=XYZ",
        "postbackURL": "https://yourapp.com/payments/postback",
        "chargebackURL": "https://yourapp.com/payments/chargeback",
        "defaultLocale": "en",
        "locales": {
          "de": {
            "name": "Magisches Einhorn",
            "description": "Adventure Game Artikel"
          }
        }
      },
      "response": {
        "transactionID": "webpay:84294ec6-7352-4dc7-90fd-3d3dd36377e9",
        "reason": "refund"
      }
    }

    此 JWT 和 Postback 類似,可於 Web Payment API 規格中參閱其定義細節。此處列出幾項重點:

    • 必納入原始付款請求。
    • iss (issuer) 必為 marketplace.firefox.com
    • aud (audience) 需設為你的應用程式金鑰。
    • JWT 需以你的應用程式安全金鑰完成簽章。
    • response.transactionID 專屬於 Mozilla 的 Web Payment Provider。
    • response.reason 必設為 refundreversal。
      • refund 代表已根據消費者或管理員的要求而退回款項。
      • reversal代表消費者要求信用卡發卡銀行取消交易。在爭議款項發生時,消費者亦可能透過信用卡公司取消交易。

    注意:目前 in-app payments 尚未支援退款作業。

    App 必須透過純文字的 HTTP 回應 (其內僅含交易 ID),對 Chargeback 做出回應。舉例來說:

    HTTP/1.1 200 OK
    Content-Type: text/plain
    
    webpay:84294ec6-7352-4dc7-90fd-3d3dd36377e9

    Postback/chargeback 錯誤

    若 App 伺服器是以不成功的狀態碼回應 HTTP 請求,則 Mozilla 的 Web Payment Provider 將重新嘗試 URL 數次。若仍未能接收成功回應,則 App 開發者就會收到通知,且該 App 將暫時停用。若 App 伺服器未能以交易 ID 回應 Postback 或 Chargeback,就會將該伺服器處理為錯誤並會重新嘗試。

    使用 HTTPS Postback/chargeback 網址

    於正式環境中執行 App 時,可依需要而嘗試使用安全的 HTTPS 網址。如此一來,在將 Postbacks 從 Mozilla 伺服器傳輸至自己的 App 伺服器時,可避免 Postback 資料遭他人讀取。目前並未強制使用 HTTPS 來保護付款請求,其實 JWT 簽章即可達到相同效果。

    注意:若你並未使用安全的 HTTPS Postback 網址,則請確認自己的付款請求並未包含個人識別資訊,以免遭第三方所攔截。舉例來說,需確認自己的 productData 值並未揭露任何高敏感性的使用者資料。Mozilla 預設的付款請求亦未包含任何個人識別資訊。

    Postback/chargeback IP

    如果你依照上述方式而確實檢查了 JWT 簽章,就不需為 Firefox Marketplace 伺服器 (傳送 postback/chargeback 通知給你) 的 IP 設定許可清單。但如果你想再另加額外保險 (例如防止鍵盤側錄),則 Marketplace 也能從下列 IP 位址寄發 postback/chargeback 通知給你。只要這些 IP 位址變更,都會發佈到 dev-marketplace 郵件群組之中。

    63.245.216.100

    模擬付款

    上面的「概述」部分提到,你可從 Firefox Marketplace 開發者交流中心取得特殊的應用程式金鑰 (Application Key) 與應用程式安全金鑰 (Application Secret),進而模擬 In-app payments。而這個安全金鑰亦可簽署如下的客製 JWT:

    {
      "iss": APPLICATION_KEY,
      "aud": "marketplace.firefox.com",
      "typ": "mozilla/payments/pay/v1",
      "iat": 1337357297,
      "exp": 1337360897,
      "request": {
        "id": "915c07fc-87df-46e5-9513-45cb6e504e39",
        "pricePoint": 10,
        "name": "Magical Unicorn",
        "description": "Adventure Game item",
        "icons": {
          "64": "https://yourapp.com/img/icon-64.png",
          "128": "https://yourapp.com/img/icon-128.png"
        },
        "productData": "user_id=1234&my_session_id=XYZ",
        "postbackURL": "https://yourapp.com/payments/postback",
        "chargebackURL": "https://yourapp.com/payments/chargeback",
        "simulate": {
          "result": "postback"
        }
      }
    }

    額外的 request.simulate 屬性可要求 Payment Provider 模擬相關結果,而不會真正收費。使用者介面亦不會要求登入或 PIN 碼。在開發 App 時,可透過此屬性而確認「購買」鈕已正確掛上 navigator.mozPay,且自己的伺服器可正確運作 Postbacks 與 Chargebacks 的網址。

    下列範例將模擬 1 筆成功的購買作業,並傳送簽署過的通知至你的 Postback 網址:

    {
      ...
      "request": {
        ...
        "simulate": {
          "result": "postback"
        }
      }
    }

    下列則模擬 1 筆 Chargeback 退款:

    {
      ...
      "request": {
        ...
        "simulate": {
          "result": "chargeback",
          "reason": "refund"
        }
      }
    }

    將如同真正的購買作業一般,將有 1 筆 JWT 通知傳送到你的處理器,但不會有隨機產生的 transactionID。模擬作業亦可使用 non-HTTPS 網址。

    注意:模擬的付款 JWT 不該用於正式的服務環境中,否則你的消費者將免費取得產品。

    除錯

    如果你並未正確使用 in-app payment API,則付款畫面將顯示錯誤訊息,以協助使用者進行後續步驟。付款畫面亦將提供錯誤程式碼,協助開發者找出相關錯誤。你可透過 Mozilla 的 Error Legend API,在自己慣用的程式語言中觀看錯誤代碼。舉例來說,錯誤代碼 INVALID_JWT 即表示 JWT 簽章無效,或 JWT 格式混亂。

    保護應用程式安全金鑰

    警告:請確認沒有任何人可讀取你的應用程式安全金鑰。絕對不要在用戶端披露該項資訊

    撤銷遭盜用的應用程式安全金鑰

    雖然遭盜用的機率極低,但你的安全金鑰仍可能外洩或遭盜用,這時應儘快進行下列撤銷步驟:

    1. 登入 Firefox Marketplace
    2. 前往「My Submissions」並找到自己的 App。
    3. 前往「Manage In-App Payments」頁面;就是產生自己所屬憑證 (Credentials) 的相同頁面。
    4. 點擊「Reset Credentials」按鈕。

    在重設自己的憑證之後,其他人就無法以舊憑證處理付款作業。你會看到新的應用程式金鑰與安全金鑰,並可立刻用來處理自己 App 中的付款流程。

    若要回報任何安全性問題,請填寫 Payments/Refunds 分類下的錯誤

    程式碼函式庫

    下列為 Mozilla 的 navigator.mozPay 專屬函式庫:

    Here are some generic JSON Web Token (JWT) libraries for encoding/decoding and signature verification:

    範例程式碼

    • 這裡提供 Web Fighter 原始碼。此遊戲是以 NodeJS 建構 In-app payments 功能。你可到 Marketplace 的這裡安裝。
    • 此為診斷與測試用 App,將呈現 JWT 請求的簽署方式,並以 Python 撰寫 Postbacks 與 Chargebacks 的檢驗器 (Verifier) 程式碼:In-app Payment Tester

    尋求協助

    • 你可透過 dev-webapps 郵件群組,或在 irc.mozilla.org 的 #payments 頻道上討論 In-app payments 的相關問題。
    • 若發現任何錯誤,請在 Payments/Refunds 分類下回報 Marketplace bug

    類似的付款系統

    Document Tags and Contributors

    Contributors to this page: MashKao
    最近更新: MashKao,