# 在线支付

向军大叔每晚八点在 抖音 (opens new window)bilibli (opens new window) 直播

xj-small

微信支付 (opens new window)是腾讯公司的支付业务品牌,微信支付商户平台支持线下场所、公众号、小程序、PC 网站、APP、企业微信等经营场景快速接入微信支付。

# 支付配置

下面通过 PC 扫码支付来演示微信支付的使用,其他支付方式与此大同小异。

首先需要在微信支付平台 (opens new window)申请帐号,微信提供多款支付产品 (opens new window)用于满足不同应用场景的支付。

image-20200812132837937

产品 说明
JSAPI 支付 使用微信 APP 内部浏览器发起支付,适用于微信公众号等场景
APP 支付 在 APP 中发起支付
Native 支付 PC 网页生成二维码,用户使用微信扫码支付
H5 支付 手机端浏览器的 H5 页面中发起支付,会调取用户微信 APP 完成支付

# API 证书

访问微信支付帐户中心 (opens new window) 并下载证书工具来生成证书。

每年生成证书有次数限制,所以生成好的证书请妥善保存

image-20200812133959591

执行软件首先设置证书保存目录

image-20210517163832890

设置商户信息(初次执行会自动填写)

image-20210517164050551

按提示操作剩下的步奏,将最终生成的证书妥善保存

image-20200812134823584

# API 密钥

需要设置 32 位 API 密钥,可以使用随机密码生成器 (opens new window)来生成,并设置到微信支付的API 安全 (opens new window)中,并妥善保存以供后面程序中使用。

image-20200812135040750

# 商户号

  1. 登录微信支付产品中心 (opens new window) 选择支付产品

image-20200814102706421

  1. 然后在「开发配置」中查看商户号

    image-20200814102835711

# Native 支付

Native 用于在 PC 桌面端生成二维码完成支付。

# 绑定服务号

使用 Native 支付 (opens new window) 需要首先绑定具有支付功能的微信服务号。请在 AppID 帐号管理 (opens new window) 中绑定微信服务号。

image-20200814111935324

# 设置回调地址

产品中心 >开发配置 (opens new window)> 支付配置 > Native支付 中设置 Native支付回调链接

image-20210517165143606

# h5 支付

使用 h5 支付时即在移动端浏览器支付,也需要绑定具有支付功能的微信服务号。

# 配置支付域名

然后访问 产品中心 -> JSAPI支付 -> 开发配置 -> H5支付 配置 H5 支付域名,注意域名不要加 www

image-20200814151523393

# 程序编码

下面来使用 yansongda/pay (opens new window) 快速为网站集成微信Native支付

相比自己完成支持业务来讲,使用扩展包快速便捷。

  • 使用的金额单位为

# 参数说明

下面对开发中用到的参数进行说明

  1. mch_id 微信支付商户号 帐户中心>个人信息>帐号信息>登录帐号 (opens new window)

  2. key 商户支付 API 密钥 帐户中心>API 安全>设置 API 密钥 (opens new window) 要使用 APIv3 版本的

    image-20221013023004120

  3. app_id 公众号应用 ID 产品中心>AppID 账号管理 (opens new window)

# 安装扩展

使用 composer 安装扩展包

composer require yansongda/pay -vvv

安装 endroid/qr-code (opens new window)用于生成二维码

composer require endroid/qr-code

# 配置项

创建配置文件 config/pay.php 内容如下

<?php

use Yansongda\Pay\Pay;

return [
    'alipay' => [
        'default' => [
            // 必填-支付宝分配的 app_id
            'app_id' => env('ALIPAY_APP_ID'),
            // 必填-应用私钥 字符串或路径
            'app_secret_cert' => env('ALIPAY_APP_SECRET_CRET'),
            // 必填-应用公钥证书 文件类似:appCertPublicKey_2017xxxx.crt
            'app_public_cert_path' => base_path(env('ALIPAY_APP_PUBLIC_CERT_PATH')),
            // 必填-支付宝公钥证书 文件类似:ertPublicKey_RSA2.crt
            'alipay_public_cert_path' => base_path(env('ALIPAY_PUBLIC_CERT_PATH')),
            // 必填-支付宝根证书 文件类似:crt/alipayRootCert.crt
            'alipay_root_cert_path' => base_path(env('ALIPAY_ROOT_CERT_PATH')),
            'return_url' => '',
            'notify_url' => '',
            // 选填-第三方应用授权token
            'app_auth_token' => '',
            // 选填-服务商模式下的服务商 id,当 mode 为 Pay::MODE_SERVICE 时使用该参数
            'service_provider_id' => '',
            // 选填-默认为正常模式。可选为: MODE_NORMAL, MODE_SANDBOX, MODE_SERVICE
            'mode' => Pay::MODE_NORMAL,
        ]
    ],
    'wechat' => [
        'default' => [
            // 必填-商户号,服务商模式下为服务商商户号
            'mch_id' => env("WEPAY_MCH_ID"),
            // 必填-商户秘钥 key 访问微信支付网站 [帐户中心>API 安全>设置 API 密钥],要使用 **APIv3** 版本的
            'mch_secret_key' => env('WEPAY_MCH_SECRET_KEY'),
            // 必填-商户私钥 字符串或路径 微信支付证书工具生成的 apiclient_key.pem 文件
            'mch_secret_cert' =>  base_path(env("WEPAY_MCH_SECRET_CERT")),
            // 必填-商户公钥证书路径 微信支付证书工具生成的 apiclient_cert.pem 文件
            'mch_public_cert_path' => base_path(env("WEPAY_PUBLIC_CERT_PATH")),
            // 必填
            'notify_url' => '',
            // 选填-公众号 的 app_id
            'mp_app_id' => 'wxc47243ed572e273d',
            // 选填-小程序 的 app_id
            'mini_app_id' => '',
            // 选填-app 的 app_id
            'app_id' => '',
            // 选填-合单 app_id
            'combine_app_id' => '',
            // 选填-合单商户号
            'combine_mch_id' => '',
            // 选填-服务商模式下,子公众号 的 app_id
            'sub_mp_app_id' => '',
            // 选填-服务商模式下,子 app 的 app_id
            'sub_app_id' => '',
            // 选填-服务商模式下,子小程序 的 app_id
            'sub_mini_app_id' => '',
            // 选填-服务商模式下,子商户id
            'sub_mch_id' => '',
            // 选填-微信公钥证书路径, optional,强烈建议 php-fpm 模式下配置此参数
            'wechat_public_cert_path' => [
                '45F59D4DABF31918AFCEC556D5D2C6E376675D57' => __DIR__ . '/Cert/wechatPublicKey.crt',
            ],
            // 选填-默认为正常模式。可选为: MODE_NORMAL, MODE_SERVICE
            'mode' => Pay::MODE_NORMAL,
        ]
    ],
    'unipay' => [
        'default' => [
            // 必填-商户号
            'mch_id' => '777290058167151',
            // 必填-商户公私钥
            'mch_cert_path' => __DIR__ . '/Cert/unipayAppCert.pfx',
            // 必填-商户公私钥密码
            'mch_cert_password' => '000000',
            // 必填-银联公钥证书路径
            'unipay_public_cert_path' => __DIR__ . '/Cert/unipayCertPublicKey.cer',
            // 必填
            'return_url' => 'https://yansongda.cn/unipay/return',
            // 必填
            'notify_url' => 'https://yansongda.cn/unipay/notify',
        ],
    ],
    'logger' => [
        'enable' => false,
        'file' => base_path('logs/pay.log'),
        'level' => 'info', // 建议生产环境等级调整为 info,开发环境为 debug
        'type' => 'single', // optional, 可选 daily.
        'max_file' => 30, // optional, 当 type 为 daily 时有效,默认 30 天
    ],
    'http' => [ // optional
        'timeout' => 5.0,
        'connect_timeout' => 5.0,
        // 更多配置项请参考 [Guzzle](https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html)
    ],
];

# 业务处理

下面是 Laravel 框架为例编写后台业务代码。创建控制器 App\Http\Controllers\PayController.php 内容如下

<?php

namespace App\Http\Controllers;

use App\Models\Order;
use Illuminate\Http\Request;
use Log;
use Yansongda\Pay\Pay;
use App\Services\OrderService;
use Endroid\QrCode\Builder\Builder;

class WepayController extends Controller
{
    public function __construct()
    {
        $this->middleware(['auth:sanctum'])->only('createOrder');

        $config = config('pay');
        $config['wechat']['default']['notify_url'] = url('/api/wepay/notify');
        Pay::config($config);
    }

    //发起支付
    public function pay()
    {
        $order = [
            'out_trade_no' => time(),
            'description' => '后盾人视频',
            'amount' => [
                'total' => 1,
            ],
        ];
        $result = Pay::wechat()->scan($order);
        //生成支付二维码
        return Builder::create()->data($result['code_url'])->build()->getDataUri();
    }

    //异步通知
    public function notifyUrl()
    {
        $pay = Pay::alipay();
        $result = $pay->callback();
        Log::info((array)$result);
        //修改订单状态...
        return $pay->success();
    }
}

# 路由配置

下面来配置路由

Route::get('pay','PayController@pay')->name('pay');
Route::post('pay','PayController@notify')->name('pay.notify');

# 沙箱模式

沙箱环境 (opens new window) (Beta) 是微信为降低商户测试门槛,微信支付团队开发了一套独立的仿真测试系统。该系统根据验收用例金额的不同返回不同的响应报文,以满足商户正常功能测试、安全/异常测试及性能测试的需求。

  • 沙箱模式不需要手机扫码,会自动完成支付过程

# 理解沙箱

微信支付仿真测试系统(后简称仿真系统)的简化原理图。仿真系统的 API 协议与正式 API 完全相同(API 接口文档 (opens new window))。商户开发者只需将正式 API 的调用 URL 增加一层 sandboxnew 路径,即可对接到仿真系统。

例如,付款码支付 URL:https://api.mch.weixin.qq.com/pay/micropay

变更为:https://api.mch.weixin.qq.com/sandboxnew/pay/micropay

下图是仿真系统的支付流程 商户接入验收流程

仿真系统与生产环境完全独立,包括存储层。商户在仿真系统所做的所有交易(如下单、支付、查询)均为无资金流的假数据,即:用户无需真实扣款,商户也不会有资金入账。

# 验收用例

使用微信支付沙箱模式时不像支付宝可以随意设置金额,微信支付的沙箱模式只能使用固定金额的用例操作。

需要关注「微信支付商户接入验收助手」公众号来查看,请扫描下面二维码进行关注。

二维码

# 扩展配置

使用 yansongda/pay (opens new window) 进行支付时,只需要设置配置项 mode='dev' 即可。

protected function config(){
  return  [
      "key": "xxxx",	//商户支付API密钥
      "app_id": "xxx", //公众号AppID
      "mch_id": "xxxx", //微信支付商户号
      'notify_url' => route('pay.notify'), //异步通知地址
      'mode' => 'dev', // optional,设置此参数,将进入沙箱模式
  ];
}