这两天看到两条关于任天堂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平台上买什么?
- 怎么买,在哪买?
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。
支付方式
Switch支持的支付方式有:账户余额、信用卡、优惠券。
-
账户余额
用户Nintendo Account下的账户余额,用户可通过信用卡、paypal和Nintendo Prepaid Card进行充值。 -
信用卡
用户可直接通过信用卡进行支付 -
兑换券
兑换券与相关商品一一关联,通过输入兑换券上兑换码获得相关商品。
Switch支付
这里以游戏售卖游戏币为例,进行switch支付接入。由于游戏币属于游戏内物品,对比前面列出的switch商品类型,可把游戏币归类为Consume Service Items商品,用户在Ninteond eShop购买。
上图是switch文档给出的购买Consume Service Item的流程图。结合业务整理到支付的流程图如下:
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改变交易记录状态。