npm package: @lxgfe/ng-miniapp-sdk
Description: 九游支付宝小程序 SDK
Author: ninegame-web-group
Latest version: 1.0.0

# 快速开始

## 安装SDK
通过npm安装：

```bash
npm install @lxgfe/ng-miniapp-sdk --save
```


## 初始化配置
在项目中引入SDK并初始化配置：

```javascript
// ESM 语法
import { NgMiniAppSDK } from '@lxgfe/ng-miniapp-sdk';

// CommonJS 语法
const { NgMiniAppSDK } = require('@lxgfe/ng-miniapp-sdk');

// 配置参数（九游平台获取）
const config = {
  appId: 'YOUR_APP_ID', // 申请的appID，必传
  publicKey: 'YOUR_PUBLIC_KEY', // 申请的publicKey,必传
  timeout: 5000, // 接口超时时间，单位毫秒，默认5s，可选
};

// 初始化sdk
const ngMiniAppSDK = new NgMiniAppSDK(config);
```

## SDK方法

### 通用api调用: exec
#### 入参
```javascript
ngMiniAppSDK.exec(
  api: string,
  params: IExecParams,
): Promise<any>
```

| 请求参数 | 描述 | 类型 | 是否必填 |
| --- | --- | --- | --- |
| api | 支付宝的api地址 | String | 是 |
| params | 业务请求参数 | Object | 否 |

IExecParams定义
```javascript
interface IExecParams {
  [key: string]: any;
  /** 业务请求参数 */
  bizContent?: Record<string, any>;
}
```

#### 出参
公共响应参数
| 响应参数 | 描述 | 类型 |
| --- | --- | --- |
| ngCode | 九游接口状态码,详见后面定义;<br/> 状态码为2000000,表示支付宝接口调用成功;<br/>其余状态码均为九游侧调用异常; | number |
| ngMsg | 九游接口异常错误信息 | string |
| id | 请求唯一ID | string |

支付宝接口调用成功,并能正常响应
- 会透传整个支付宝返回报文，具体详见每个接口的支付宝官方文档定义;
- 对于支付宝返回的业务异常,也是全部透传;
- 具体可以看后面的调用示例;

九游接口状态码
| 状态码 | 描述 |
| --- | --- |
| 2000000 | 请求成功 |
| 5000000 | 服务器内部错误 |
| 5000001 | 接口不存在 |
| 5000002 | 支付接口没有响应 |
| 5000003 | 接口数据解密失败 |
| 5000004 | 接口签名错误 |
| 5000005 | 支付宝接口调用失败 |

### 支付回调验签: payCallbackVerify
支付回调验签入参，获取详见[官方指引](https://opendocs.alipay.com/isv/0gp3u4?pathHash=4bfbdd96#%E5%95%86%E5%AE%B6%E9%AA%8C%E7%AD%BE%E8%A7%84%E5%88%99)

#### 入参
```javascript
// 获取支付宝支付回调的全部参数，透传给sdk，进行验签
ngMiniAppSDK.payCallbackVerify(
  query: ctx.request.query,
  body: ctx.request.body,
  header: {
    header_a: ctx.header.get('header_a'),
    header_b: ctx.header.get('header_b'),
    ...
  },
)
```
| 请求参数 | 描述 | 类型 | 是否必填 |
| --- | --- | --- | --- |
| query | 支付宝回调时，在url上的query参数 | Object | 是 |
| body | 支付宝回调时，在请求body上的参数 | Object | 是 |
| header | 支付宝回调时，在请求header头上的自定义参数 | Object | 是 |


#### 出参
| 响应参数 | 描述 | 类型 |
| --- | --- | --- |
| result | 支付验签成功校验；<br/>true：表示支付验签成功，业务方可以进行游戏内发货操作；<br/>false：表示支付验签失败； | boolean |


## SDK调用示例
### alipay.system.oauth.token（用户授权与登录）
tips: access_token过期时，重新调用该方法

#### 入参
| 请求参数 | 描述 | 类型 | 是否必填 |
| --- | --- | --- | --- |
| grant_type | 授权方式 | authorization_code:用授权码来换取授权令牌;<br/>refresh_token: 用刷新令牌来换取一个新的授权令牌; | 是 |
| code | 授权码，用户从客户端登录后得到；<br/>当refresh_token有传值时，不填；<br/>当refresh_token没有传值时，必填； | string | 否 |
| refresh_token | 刷新令牌；<br/>刷新令牌，上次换取访问令牌时得到。本参数在 grant_type 为 authorization_code 时不填；为 refresh_token 时必填，且该值来源于此接口的返回值 app_refresh_token（即至少需要通过 grant_type=authorization_code 调用此接口一次才能获取）。 | string | 否 |


#### 出参
公共响应参数
https://opendocs.alipay.com/open/02xtla#%E5%85%AC%E5%85%B1%E5%93%8D%E5%BA%94%E5%8F%82%E6%95%B0

业务响应参数
https://opendocs.alipay.com/open/02xtla#%E4%B8%9A%E5%8A%A1%E5%93%8D%E5%BA%94%E5%8F%82%E

#### 调用示例
```javascript
// case1: 获取访问令牌
const res = ngMiniAPPSDK.exec('alipay.system.oauth.token', {
  grant_type: 'authorization_code',
  code: "YOUR_CODE", // 从客户端获得的授权码
});

// case2: 刷新令牌
const res = ngMiniAPPSDK.exec('alipay.system.oauth.token', {
  grant_type: 'refresh_token',
  refresh_token: "YOUR_REFRESH_TOKEN", // 从接口返回时获得的刷新令牌
});
```

#### 响应示例
**正常响应** 
```javascript
{
  "ngCode": 2000000,
  "ngMsg": "操作成功",
  // 透传整个支付宝的响应结果
  "alipay_system_oauth_token_response": {
    "user_id": "2088102150477652",
    "open_id": "074a1CcTG1LelxKe4xQC0z",
    "access_token": "20120823ac6ffaa4",
    "expires_in": "3600",
    "refresh_token": "20120823ac6ffd",
    "re_expires_in": "3600",
    "auth_start": "2010-11-11 11:11:11"
  },
  "sign": "ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE"
}
```

**异常响应** 
```javascript
{
  "ngCode": 5000000,
  "ngMsg": "服务异常",
  "id": "ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE"
}
```

### payCallbackVerify
支付回调验签

#### 调用示例
midwayjs 伪代码

```javascript
import { Controller, Get } from '@midwayjs/core';
import { NgMiniAppSDK } from '@lxgfe/ng-miniapp-sdk';

// 配置参数（九游平台获取）
const config = {
  appId: 'YOUR_APP_ID', // 申请的appID，必传
  publicKey: 'YOUR_PUBLIC_KEY', // 申请的publicKey,必传
};

// 初始化sdk
const ngMiniAppSDK = new NgMiniAppSDK(config);

@Controller('/ng/api')
export class MyspaceController {
  // 支付回调接口
  @Get('/payCallback')
  async payCallback function () {
    const { ctx } = this;

    // 获取支付宝支付回调的全部参数，透传给sdk，进行验签
    const res = await ngMiniAppSDK.payCallbackVerify(
      query: ctx.request.query,
      body: ctx.request.body,
      header: {
        header_a: ctx.header.get('header_a'),
        header_b: ctx.header.get('header_b'),
      },
    );

    if (res?.result) {
      // TODO 支付验签成功，执行发货逻辑
    } else {
      // TODO 支付验签失败
      console.error('pay callback verify error');
    }
  }
}
```