主机平台:switch支付接入

这两天看到两条关于任天堂switch主机相关的两条新闻:

国内普通用户对switch主机平台了解不多,玩主机游戏的用户更是少之又少。而在海外,大型精品游戏一般都会在主机平台发布。而国内主机平台的开发圈,也基本上可以说是盲区;虽然国内一些大游戏公司会发布主机游戏,但也基本是试试水。从去年开始,我们陆续完成了uniy和ue4平台的switch支付接入,这里整理成文档,可以提供相关参考。

Switch账户


拿到switch的开发机后,第一步肯定是去申请相关的账户权限。switch账户类型可以归类为以下三种,大致了解下:

  • User Account
    switch本地账户,可离线注册。只有通过与Nintendo Account关联 ,才能获取到switch相关权限服务
  • Network Service Account
    switch网络服务账户。当User Account与Nintendo Account关联时,switch会先让用户输入Network Service Account实现关联。
  • Nintendo Account
    多个UserAccount可关联到Nintendo Account,但同一时刻只能有一个UserAccount关联。Nintendo Account与Network Service Account是一对一的关系。
switch账户类型

switch账户权限/关系

switch账户

问题


我们先主要理清下面几个问题:

  • 用户能在Switch平台上买什么?
  • 怎么买,在哪买?

1. 用户能在Switch平台上买什么?

可以把Switch平台类比为天虹,在天虹你可以买到衣服、零食等,比如衣服在五楼服饰处售卖,零食在一楼的生活超市售卖等。类似,在switch平台上,用户可以付费购买游戏、demo、游戏道具等,而购买的地方可以是switch自带的商店eShop,也可以是switch的指定网站。主要有:

  • Downloadable Software
    付费游戏,需要付费才能下载。可通过Nintendo eShop、Nintendo website购买。
  • Demo Version
    游戏demo,一般免费。可通过Nintendo eShop、Nintendo website购买。
  • Downloadable Content
    可下载的付费内容,付费下载后可离线使用,如游戏的额外关卡等。通过Nintendo eShop、Nintendo website购买。
  • Subscription Service Items
    订阅,可付费购买的使用时间权限。如游戏内30天使用某服务的权限。通过Nintendo eShop购买。
  • Consumable Service Items
    可消耗的物品,如游戏内的游戏币、钻石等。通过Nintendo eShop购买。

2. 怎么买,在哪买?

正如上节提到,用户可在Nintendo eShop和Nintendo website购买。其中,Ninnteodo eShop是Switch自带的商店,可通过switch主界面或则游戏内拉起,上面会展示可付费的游戏列表或游戏内物品。Nintendo website是Nintendo的网站,上面一般用来售卖各种游戏。

Nintendo eShop购买

如图所示,可通过switch主界面或通过游戏内调用相关API拉起eShop。


Nintendo eShop购买
支付方式

Switch支持的支付方式有:账户余额、信用卡、优惠券。

  • 账户余额
    用户Nintendo Account下的账户余额,用户可通过信用卡paypalNintendo Prepaid Card进行充值。
  • 信用卡
    用户可直接通过信用卡进行支付
  • 兑换券
    兑换券与相关商品一一关联,通过输入兑换券上兑换码获得相关商品。

Switch支付


这里以游戏售卖游戏币为例,进行switch支付接入。由于游戏币属于游戏内物品,对比前面列出的switch商品类型,可把游戏币归类为Consume Service Items商品,用户在Ninteond eShop购买。


购买Consume Service Items

上图是switch文档给出的购买Consume Service Item的流程图。结合业务整理到支付的流程图如下:


Switch支付流程

1. 拉起eShop

游戏调用SDK API并传入游戏ApplicationId,拉起Nintendo eShop,eShop中展示游戏售卖的Cousnme Service Items列表。

//方式1,传入游戏ApplicationId,此时Switch首先弹出账户选择界面,让用户选择支付账户
nn::ec::ShowShopConsumableItemList(nApplicationId);
//方式2,传入游戏ApplicationId并指定用户User
nn::ec::ShowShopConsumableItemList(nApplicationId, selectedUser);

2. 用户在eShop操作

用户在eShop界面完成购买操作,最后关闭eShop界面,回到游戏。

3. eShop关闭

用户手动关闭eShop,回到游戏。这里需要特别注意的时:游戏无法知道用户在eShop的具体操作,也不知道操作是否成功,只能检测到eShop关闭了。即回到游戏后,游戏并不知道用户是否在eShop有支付行为,也不知道支付是否成功。

那游戏该如何去判断用户是否支付成功?并将用户支付的物品发放给用户呢?

4. 查询用户交易记录

由于游戏并不知道用户在eShop的操作,只能通过后台去Nintendo Server查询用户的交易记录。由于游戏后台去Nintendo Server查询交易记录时,需要用户的授权信息(Nintendo Token(JWT协议));所以,此时)戏需要带入Nintendo Token到后台。
下面是之前在unity接入demo中写的Nintendo Token获取方式,仅供参考:

 //1、初始化
Account.Initialize();

//2、显示UI,让用户选择登录
Uid uid = new Uid();
Account.ShowUserSelector(ref uid);

//3、获取登录用户的UserHandle
UserHandle = new UserHandle();
Account.OpenUser(ref UserHandle, uid);

//4、检查Network Service Account是否可用
nn.Result cResult = NetworkServiceAccount.EnsureAvailable(UserHandle);
if (!cResult.IsSuccess())
{
    return false;
}

//5、获取Network Service Account Id
NetworkServiceAccountId nId = new NetworkServiceAccountId();
nn.Result gResult = NetworkServiceAccount.GetId(ref nId, UserHandle);
if (!gResult.IsSuccess())
{
    return false;
}

//6、为当前用户分配Token Cache
int count = 0;
bool asyncDone = false;
AsyncContext asyncContext = new AsyncContext();       
nn.Result eResult = NetworkServiceAccount.EnsurIdTokenCacheAsync(asyncContext, UserHandle);

//循环检查异步操作是否完成,最多检查100次,避免卡死
while (!asyncDone && ++count < 100)
{
    asyncContext.HasDone(ref asyncDone);
}

if (!asyncDone)
{
     return false;
}

if (!asyncContext.GetResult().IsSuccess() || !eResult.IsSuccess())
{
    return false;
}

//7、获取Token cache
byte[] tokenByte = new byte[1536];
ulong actualTokenSize = 0;
nn.Result loadResult = NetworkServiceAccount.LoadIdTokenCache(ref actualTokenSize, tokenByte, UserHandle);
if (loadResult.IsSuccess())
{
    NintendoToken = System.Text.Encoding.Default.GetString(tokenByte, 0,(int)actualTokenSize);
}

5. 后台查询

后台拿到客户端传的NintendoToken,先根据JWT协议校验该token合法性,然后向Nintendo Server发送查询用户交易记录查询。

后台查询接口
GET /v1/applications/{applicationId}/accounts/{nsaId}/rights? status={status}&page={page}&per_page={per_page}
Authorization: Basic {base64(clientId:clientSecret)}
X-NINTENDO-NSA-ID-TOKEN: Bearer {nsaIdToken}

后台查询接口参数

后台通过status指定查询交易的记录是PURCHASED还是CONSUMED,其中:

  • PURCHASED:新生成的交易记录
  • CONSUMED:已完成的交易记录
后台查询结果

如果查询成功,返回json结果:

{
  "total_results": (Integer; the total number of rights matching the provided criteria),
  "rights": [
    {
      "right_id": (String; Globally unique right ID),
      "nsa_id": (String; NSA ID of user who holds the right),
      "item_id": (String; the ID of the purchased item),
      "purchased_date_time": (Long; Date and time (UTC) of transaction in UNIX epoch fomat),
      "status": "(String; the status of the transaction; PURCHASED, CONSUMED",
      "country": "(String; 2 letters (ISO 3166-1 Alpha-2); the country of the created right)"
    }
  ]
}

其中:

  • rights
    json数组,可能同时返回多笔交易记录
  • right_id
    外部订单号,每笔交易记录关联的全局唯一id,可通过该id改变交易记录状态。
  • item_id
    交易记录关联的商品id。

6. 发货给用户

后台查到新的交易记录后(status为PURCHASED),向当前用户发放交易记录中指定的商品(item_id)。

7. 改变交易记录状态

只有当交易记录的状态为CONSUMED时,才能标识这笔交易的结束。因此,后台还需要发送请求到Nintendo Server改变交易记录的状态。

PUT /v1/applications/{applicationId}/accounts/{nsaId}/rights
Authorization: Basic {base64(clientId:clientSecret)}
X-NINTENDO-NSA-ID-TOKEN: Bearer {nsaIdToken}
Content-Type:application/json
[
  {
    "right_id": "(String; Globally unique right ID)",
    "status": "(String; the status of the transaction; PURCHASED, CONSUMED)"
  }
]

如上所示,后台通过put请求,通过right_id唯一关联到Nintendo Server上的交易记录,并将该交易记录的status设置为CONSUMED,改变交易记录状态。

8. 回调游戏客户端

游戏后台将补发货结果回调给游戏客户端,至此,一次支付行为全部结束了。
Note:由于后台流程是先查询,再发货,最后再改变记录状态。因此可能出现:
后台发货给用户后,但交易记录状态改变失败了,导致下次依然能查到该已发货的交易记录。此时,需要游戏后台维护交易记录发货状态表,每次发货前,判断当前交易记录是否已发货。如果已发货,则直接请求Nintendo Server改变交易记录状态。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,902评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,037评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,978评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,867评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,763评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,104评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,565评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,236评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,379评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,313评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,363评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,034评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,637评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,719评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,952评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,371评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,948评论 2 341

推荐阅读更多精彩内容