xsolla支付

Jingxc大约 9 分钟payjava后端payjavaxsolla后端

xsolla支付

xsolla: 您已尽心尽力开发出令人惊叹、独一无二的游戏。作为您的合作伙伴,帮助您将成果与世界共享是我们的使命。

作为开发者在集成xsolla支付接口之前,首先要有一系列的准备,xsolla商家账号,接入流程参考官方文档 https://developers.xsolla.com/zh/doc/pay-station/integration-guide/get-started/open in new window

1. 注册xsolla商家账号

注意

自己在这里遇到一个坑,在创建账号时创建的项目不是active的我也不清楚为啥,导致后面的请求都不行,后来联系了平台人员,我把项目删了重新新建一个,刚建完就是active的,就很奇妙

官方的人员很热情,回复得也很快很有耐心,直接点击下面的在线聊天就能沟通,点赞,下面是部分回复

相关信息

我:你好,我是开发人员,我想接入咱们的支付功能,在获取用户令牌时返回

"message": "Project is not active. Please make sure you have successfully passed all tests
<a href=\"https:\/\/publisher.xsolla.com\/403694\/projects\/217604\" target=\"_blank\">here<\/a> and activate your project.",

这是因为什么?

Simon:

https://publisher.xsolla.com/403694/projects/217604/edit/webhooks您还需要设置open in new window webhook 并粘贴 webhook 的 URL 以激活您的项目。

我:我是按照咱们官方文档步骤来的,webhook这一块下面的商店/支付/订阅都需要填写才能激活项目吗?

Simon

https://developers.xsolla.com/solutions/payments/open in new window 它是付款文档,但您可以在那里看到有关如何设置项目和启用它的所有信息。它还有关于 webhook 的主题。

我:按照上面操作了一顿还是不行,后来干脆把创建账号时创建的项目删了,再按照上面创建一个,直接变成active的了,很奇妙

Simon: 很高兴分享指向我们最相关解决方案的链接。 您还可以使用我发送给您的链接来集成它并启用您的项目。

您还可以查看最适合您的项目的内容。

支付 - https://xsolla.com/products/paystationopen in new window

游戏内商店 - https://xsolla.com/products/in-game-storeopen in new window

网上商店 - https://xsolla.com/solution/web-shop-for-mobile-games?cardId=290open in new window

游戏销售 - https://xsolla.com/solutions/online-game-sales?cardId=166open in new window

数字分销中心 - https://xsolla.com/products/digital-distribution-hubopen in new window

订阅 - https://xsolla.com/products/subscriptionsopen in new window

Simon:

您可以在发布者帐户中选择产品,单击感兴趣的产品选项卡中的文档。还有一个完整的集成指南,其中包括启用您的项目和产品

1.1 商户ID:


  • 项目设置 > Webhooks 部分。 记录商户id,项目id,api密钥备用(webhook)
  • 公司设置 > 公司 部分。

1.2 API密钥


仅在创建它时在发布商帐户中显示一次,必须存储在己侧。可以在以下部分中创建新的密钥:

  • 公司设置 > API密钥
  • 项目设置 > API密钥

2. 获取用户令牌

提示

请求地址: https://api.xsolla.com/merchant/v2/merchants/{xsollaUserId}/tokenopen in new window

xsollaUserId: 用户创建的商户id

封装请求头信息

xsollaAPI使用基本认证open in new window 。所有发送到API的请求必须包含 Authorization: Basic <your_authorization_basic_key> 头,其中 <your_authorization_basic_key> 是按照Base64标准加密的 商户ID: API密钥 对。请前往 发布商帐户open in new window 找到以下参数:

//授权信息
String xsollaUserId = constantInfo.getUserId();//商户id
String appId = constantInfo.getAppId();//项目id
String appKey = constantInfo.getAppKey();//密钥
String headerBasic = OauthSignatureUtil.headerBasic(xsollaUserId, appKey);//方法参见java-paypal

Map<String, String> headers = new HashMap<>();
headers.put("Authorization", headerBasic);

对于请求提没什么可说的直接按照文档上赋值就可以了

示例代码:

@Override
@OperationLogger
public ReturnResult createToken(CreateTokenParams params) {

    String userId = params.getUserId();
    String gameId = params.getGameId();
    String channelId = params.getChannelId();
    String email = params.getEmail();
    String currencyType = params.getCurrencyType();

    //验证账号是否存在
    UserAccountInfo accountInfo = UserAccountInfo.builder().userId(userId).build();
    accountInfo = userAccountInfoMapper.selectOne(new QueryWrapper<>(accountInfo));
    if (accountInfo == null) {
        return ReturnResultError.builder().code(ConstantCommon.RETURN_CODE_903).msg("账号不存在").data("")
                .build();
    }

    String username = accountInfo.getUsername();

    //查询渠道配置信息
    ConstantMeInfo constantInfo = getCacheConstantInfo(gameId, channelId, "xsolla");

    //授权信息
    String xsollaUserId = constantInfo.getUserId();//商户id
    String appId = constantInfo.getAppId();//项目id
    String appKey = constantInfo.getAppKey();//密钥
    String headerBasic = OauthSignatureUtil.headerBasic(xsollaUserId, appKey);//方法参见java-paypal

    Map<String, String> headers = new HashMap<>();
    headers.put("Authorization", headerBasic);

    //请求体
    Map<String, Object> xsollaParams = new HashMap<>();
    xsollaParams.put("settings", new HashMap<String, Object>() {{
        put("currency", currencyType);
        put("language", "en");//xsolla支付界面语言。可定制化配置
        put("project_id", Integer.parseInt(appId));
    }});
    xsollaParams.put("user", new HashMap<String, Object>() {{
        put("email", new HashMap<String, String>() {{
            put("value", email);
        }});
        put("id", new HashMap<String, String>() {{
            put("value", userId);
        }});
        put("name", new HashMap<String, String>() {{
            put("value", username);
        }});
    }});

    Map<String, String> createToken = client.postByJsonToMap("https://api.xsolla.com/merchant/v2/merchants/" + xsollaUserId + "/token", headers, xsollaParams);

    System.out.println(JSON.toJSONString(createToken));
    return ReturnResultSuccess.builder().code(ConstantCommon.RETURN_CODE_200).msg("订单创建成功").data(JSON.toJSONString(createToken))
            .count(ConstantCommon.RETURN_COUNT_1).build();
}

这样就拿到了用户的token信息

{
    "token":"twpuiVlqxd95a0rL2isA7RmTjSD7rzXa_lc_en_bg_FFFFFF_tb_3D46F5"
}

3. 使用指定商品创建订单

目前使用的是指定商品创建订单,商品信息需要在商户后台提前配置,项目-商店-虚拟商品,配置即可,也可以使用api创建虚拟商品

https://developers.xsolla.com/zh/api/igs-bb/operation/admin-create-virtual-item/open in new window

虚拟商品
虚拟商品

提示

请求地址: https://store.xsolla.com/api/v2/project/{projectId}/payment/item/{productId}open in new window

projectId:项目id,productId:商品id,sku

封装请求头信息,用到上步骤获取的用户令牌

//授权信息
Map<String, String> headers = new HashMap<>();
headers.put("Authorization", "Bearer " + token);

封装用户付款ui

//配置ui显示
Map<String, Object> ui = new HashMap<>();
ui.put("desktop", new HashMap<String, Object>() {{//桌面版本的界面设置。
    put("header", new HashMap<String, Object>() {{
        put("close_button", false);//是否在支付中心桌面端显示关闭按钮。该按钮将关闭支付中心并将用户重定向到settings.return_url参数中指定的URL。默认为false。
        put("is_visible", true);//页眉在支付UI上是否可见。
        put("type", "normal");//如何显示页眉。不能:compact(隐藏项目名称和用户ID)或normal(默认)
        put("visible_logo", true);//标题中将显示Logo
        put("visible_name", true);//页眉中是否显示项目名称。
        put("visible_purchase", true);//是否在页眉中显示购买描述(purchase.description.value )
    }});
}});
ui.put("mobile", new HashMap<String, Object>() {{
    put("footer", new HashMap<String, Object>() {{
        put("is_visible", true);//是否在移动版本的支付UI中隐藏或显示脚注。
    }});
    put("header", new HashMap<String, Object>() {{
        put("close_button", false);//是否在支付中心移动端显示关闭按钮。该按钮将关闭支付中心并将用户重定向到settings.return_url参数中指定的URL。默认为false。
    }});
}});
ui.put("size", "large");
ui.put("theme", "default");
ui.put("version", "mobile");//设备的类型。可以是desktop(默认值)或mobile。

完整的请求体信息

Map<String, Object> xsollaParams = new HashMap<>();
xsollaParams.put("settings", new HashMap<String, Object>() {{
    put("ui", ui);
    put("return_url", constantInfo.getReturnUrl());
    put("redirect_policy", new HashMap<String, String>() {
        {
            put("redirect_conditions", "successful");
        }
    });//回调触发
}});
xsollaParams.put("sandbox", true);//沙盒环境
xsollaParams.put("quantity", 1);
xsollaParams.put("custom_parameters", new HashMap<String, Object>() {{//项目特定参数。
    put("character_id", userId);
}});

订单创建成功,返回

{
    "order_id":32304580,
    "token":"twpugyGEI56prN2fAzMKu5ynipYwXZqe_lc_cn_bg_FFFFFF_tb_3D46F5"
}

也可以使用服务端的为购买创建支付令牌,接入方式和客户端差不多

4. 支付

提示

直接访问 https://sandbox-secure.xsolla.com/paystation4/?token=TOKENopen in new window 即可跳转到付款页面,当然也可以用iframe中打开

使用上面的链接在沙盒模式下打开支付UI。项目发布后,请使用此URL:https://secure.xsolla.com/paystation4/?token=TOKEN。open in new window

支付页面
支付页面

选择paypal支付,可以用paypal沙盒虚拟账号支付,有关paypal账号部分参见java-paypal

付款成功
付款成功

在个人商户邮箱就可收到用户的付款信息

商家邮箱
商家邮箱

查询订单状态


可通过查询订单状态,确认是否完成付款

5. 通过发布商帐户进行管理

可以使用 发布商帐户open in new window 轻松管理付款:

  • 会计 > 交易登记表 中查看交易历史记录、统计数据及上传交易数据。( 需要选择测试交易就能看见刚才测试的支付订单 )
  • 会计 > 付款 中核对收入。
  • 会计 > 报告 导出用于法律合规事宜的报告。

6. 退款

可以发起部分退款,也可以全额退款,这里只介绍全额退款,详细的文档请参见

https://developers.xsolla.com/zh/api/pay-station/operation/request-refund/open in new window

退款需要交易id,交易id

  • 商户:商户后台交易记录能查看到交易id
  • 用户:用户在付款后,ui页面有显示(№1163315218)
@Override
@OperationLogger
public ReturnResult refundOrder(RefundOrderParams params) {

    String userId = params.getUserId();
    String orderId = params.getOrderId();
    String gameId = params.getGameId();
    String channelId = params.getChannelId();
    String transcationId = params.getTranscationId();
    String desc = params.getDesc();

    //查询订单是否存在
    OrderMeInfo orderMeInfo = OrderMeInfo.builder().gameId(gameId).channelId(channelId).orderId(orderId).userId(userId)
            .orderStatus(ConstantCommon.ORDER_STATUS_1).build();
    orderMeInfo = orderMeInfoMapper.selectOne(new QueryWrapper<>(orderMeInfo));
    if (orderMeInfo == null) {
        return ReturnResultError.builder().code(ConstantCommon.RETURN_CODE_903).msg("订单不存在或者不存在/已退款").data("")
                .build();
    }

    //查询渠道配置信息
    ConstantMeInfo constantInfo = getCacheConstantInfo(gameId, channelId, "xsolla");

    //授权信息
    String xsollaUserId = constantInfo.getUserId();//商户id
    String appKey = constantInfo.getAppKey();//密钥
    String headerBasic = OauthSignatureUtil.headerBasic(xsollaUserId, appKey);

    Map<String, String> headers = new HashMap<>();
    headers.put("Authorization", headerBasic);

    Map<String, Object> xsollaParams = new HashMap<>();
    xsollaParams.put("description", "退款理由" + desc);
    xsollaParams.put("email", "18712709017@163.com");//用户邮箱

    Map<String, String> refund = client.postByJsonToMap("https://api.xsolla.com/merchant/v2/merchants/"
            + constantInfo.getUserId() + "/reports/transactions/" + transcationId + "/refund", headers, xsollaParams);
    System.out.println(JSON.toJSONString(refund));

    //TODO 更新订单信息
    return ReturnResultSuccess.builder().code(ConstantCommon.RETURN_CODE_200).msg("退款成功").data(refund)
            .count(ConstantCommon.RETURN_COUNT_1).build();
}

7. 设置WEBHOOK(重要)

如希望接收事件通知(如支付状态变化),请在发布商帐户中设置Webhook:

  1. 发布商帐户open in new window 中打开您的项目。
  2. 在侧边栏中单击 项目设置 ,然后前往 Webhooks
  3. Webhooks 开关设置为
  4. 指定Webhook URL。
  5. 默认会生成一个用于项目Webhook签名的密钥。如要生成一个新密钥,请单击刷新图标。
  6. 单击 保存设置

推荐实现以下Webhook:

要确认已收到Webhook,您的服务器必须作出如下响应:

  • 不带消息正文的HTTP代码204。
  • 描述问题的HTTP代码400(如果指定用户未找到或传入的签名无效)。

xsolla的接入到目前就已基本完成

上次编辑于:
贡献者: Jingxc,jingxc