npm package: @gulibs/tegg-wechat-pay-v3
Description: WeChat Pay API v3 plugin for Egg.js 4.x - single and multi-merchant support
Author: HectorGu
Latest version: 0.0.2

# @gulibs/tegg-wechat-pay-v3

WeChat Pay API v3 plugin for Egg.js 4.x with single and multi-merchant support.

## Features

- WeChat Pay API v3 (RESTful, JSON, SHA256-RSA, AES-256-GCM callback)
- Single merchant: `client` config, use `app.wechatPayV3` / `ctx.wechatPayV3` directly
- Multi-merchant: `clients` config, use `app.wechatPayV3.get('clientId')` or `app.wechatPayV3s.get('clientId')`
- Full TypeScript support
- Powered by [@gulibs/wechat-pay-v3](https://www.npmjs.com/package/@gulibs/wechat-pay-v3)

## Requirements

- Node.js >= 22.18.0
- Egg.js >= 4.1.0-beta.35

## Install

### Install Latest Version

```bash
pnpm add @gulibs/tegg-wechat-pay-v3
# or
npm i @gulibs/tegg-wechat-pay-v3
```

### Install Beta Version

To install the beta version, you must explicitly specify the `@beta` tag:

```bash
pnpm add @gulibs/tegg-wechat-pay-v3@beta
# or
npm i @gulibs/tegg-wechat-pay-v3@beta
```

**Note**: Using `@latest` or no tag will install the latest stable version, not the beta version.

## Usage

### 1. Enable Plugin

```typescript
// config/plugin.ts
import wechatPayV3Plugin from '@gulibs/tegg-wechat-pay-v3';

export default {
  ...wechatPayV3Plugin(),
};
```

### 2. Configure (Single Merchant)

```typescript
// config/config.default.ts
import { readFileSync } from 'node:fs';

export default {
  teggWechatPayV3: {
    app: true,
    agent: false,
    client: {
      mchid: 'your-mchid',
      apiclient_cert: readFileSync('./apiclient_cert.pem'),
      apiclient_key: readFileSync('./apiclient_key.pem'),
      apiV3Key: 'your-api-v3-key', // required for callback decrypt/verify
      // optional: wechatPayPublicKeyPath, wechatPayPublicKey, downloadDir, sandbox
    },
  },
};
```

### 3. Configure (Multi-Merchant)

```typescript
// config/config.default.ts
import { readFileSync } from 'node:fs';

export default {
  teggWechatPayV3: {
    app: true,
    agent: false,
    default: {
      // optional: shared defaults for all clients
    },
    clients: {
      merchantA: {
        mchid: 'mchid-a',
        apiclient_cert: readFileSync('./certs/merchant-a-cert.pem'),
        apiclient_key: readFileSync('./certs/merchant-a-key.pem'),
        apiV3Key: 'api-v3-key-a',
      },
      merchantB: {
        mchid: 'mchid-b',
        apiclient_cert: readFileSync('./certs/merchant-b-cert.pem'),
        apiclient_key: readFileSync('./certs/merchant-b-key.pem'),
        apiV3Key: 'api-v3-key-b',
      },
    },
  },
};
```

### 4. Use in Code (Single Merchant)

`ctx.wechatPayV3` is the [@gulibs/wechat-pay-v3](https://www.npmjs.com/package/@gulibs/wechat-pay-v3) container: use `.use(Class)` to get pay APIs, `.handleCallback()` for notifications.

```typescript
// In controller or service
import type { Context } from 'egg';
import { NativePay, MiniProgramPay } from '@gulibs/wechat-pay-v3';

// Native payment
const nativePay = ctx.wechatPayV3.use(NativePay);
const { code_url } = await nativePay.order({
  appid: 'your-appid',
  mchid: ctx.app.config.teggWechatPayV3!.client!.mchid,
  description: 'test',
  out_trade_no: 'ORDER_' + Date.now(),
  notify_url: 'https://your-domain.com/notify',
  amount: { total: 1 },
  scene_info: { payer_client_ip: ctx.ip },
});

// MiniProgram / JSAPI: use MiniProgramPay or JSPay
const miniPay = ctx.wechatPayV3.use(MiniProgramPay);
const { prepay_id } = await miniPay.order({ ... });
const payParams = miniPay.getPayParams({ appId: 'your-appid', prepay_id });
```

### 5. Use in Code (Multi-Merchant)

```typescript
// Get client by id
const payA = ctx.wechatPayV3.get('merchantA');
const payB = ctx.wechatPayV3s.get('merchantB'); // alias

const nativePayA = payA.use(NativePay);
const miniPayB = payB.use(MiniProgramPay);
```

### 6. Callback Verify and Decrypt

Use the container's `handleCallback` (verify + decrypt in one step):

```typescript
// POST /notify
const data = await ctx.wechatPayV3.handleCallback(ctx.headers, ctx.request.body);
// data.resource is decrypted; verify is done inside handleCallback
```

## Configuration

| Option | Type | Description |
|--------|------|-------------|
| `teggWechatPayV3.default` | `Partial<WeChatPayV3ClientConfig>` | Default options merged into each client (multi-merchant) |
| `teggWechatPayV3.client` | `WeChatPayV3ClientConfig` | Single merchant config |
| `teggWechatPayV3.clients` | `Record<string, WeChatPayV3ClientConfig>` | Multi-merchant config (key = clientId) |
| `teggWechatPayV3.app` | `boolean` | Enable in app process (default: true) |
| `teggWechatPayV3.agent` | `boolean` | Enable in agent process (default: false) |

**WeChatPayV3ClientConfig** (aligns with [@gulibs/wechat-pay-v3](https://www.npmjs.com/package/@gulibs/wechat-pay-v3) `ContainerOptions`): `mchid`, `apiclient_cert`, `apiclient_key`, `apiV3Key` (required); `userAgent`, `autoUpdateCertificates`, `downloadDir`, `wechatPayPublicKeyPath`, `wechatPayPublicKey`, `sandbox`, `singleton` (optional). Cert/key can be file path (string) or Buffer.

## License

MIT