「支付专题」微信支付如何接入webman-admin开源管理后台

2023-11-13 15:47:24 浏览数 (1)

介绍

这篇文章主要为大家详细介绍微信支付如何接入开源管理后台webman-admin开发教程

必须申请开通微信支付

  • 微信支付官方地址:https://pay.weixin.qq.com/index.php/core/home/login?return_url=/
  • 申请指引:https://pay.weixin.qq.com/index.php/public/bare_applyment/login4bank

支付流程

接入流程

1. 登录商户

登录微信商户平台:https://pay.weixin.qq.com

2. 获取商户号

3. 添加支付授权域名目录

授权域名格式:http://域名/

注意:域名最后的斜杠绝不能少

4. 若提示没有安装证书,请安装证书

按照提示语按照即可

5. 配置API安全

6. 申请API证书

注意:以前申请过的,并且可以找到的,直接跳过。找不到的,点击更换证书

7. 生成API证书

8. 下载至本地安装

9. 商户号和商户名称

对照检查商户号和商户名称是否为你当前配置帐号信息,确定无误后点击“下一步”

10. 复制证书内容

点击工具右侧「复制」

11. 打开商户平台(切换为浏览器)

12. 复制证书串

13. 切换至证书工具

14. 查看证书文件夹

15. 建议复制证书

建议复制证书,保存到的资料文件夹。证书为 _cert.zip 结尾压缩包。

16.解压证书压缩包

解压证书压缩包,得到文件(暂时不用管,后面会用到

17. 配置API秘钥(点击设置秘钥)

18.设置秘钥

设置秘钥,包含随机大小写字母、数字组合,32位。(记得保存)【不会的可以在 https://suijimimashengcheng.51240.com 里选择32位,随机生成,然后复制,在过来粘贴。】

支付相关配置完成,记得保存相关资料。

支付

安装依赖

代码语言:javascript复制
composer require yansongda/pay ^3.0.0

配置文件

假设有以下配置文件 config/payment.php

代码语言:javascript复制
<?php
/**
 * @desc 支付配置文件
 * @author Tinywan(ShaoBo Wan)
 * @date 2023/4/5 13:51
 */
declare(strict_types=1);

return [
    'wechat' => [
        'default' => [
            // 必填-商户号,服务商模式下为服务商商户号
            // 可在 https://pay.weixin.qq.com/ 账户中心->商户信息 查看
            'mch_id' => '12312312321',
            // 必填-商户秘钥
            // 即 API v3 密钥(32字节,形如md5值),可在 账户中心->API安全 中设置
            'mch_secret_key' => '3324324reewrwerew',
            // 必填-商户私钥 字符串或路径
            // 即 API证书 PRIVATE KEY,可在 账户中心->API安全->申请API证书 里获得
            // 文件名形如:apiclient_key.pem
            'mch_secret_cert' => public_path().'/cert/wechat/apiclient_key.pem',
            // 必填-商户公钥证书路径
            // 即 API证书 CERTIFICATE,可在 账户中心->API安全->申请API证书 里获得
            // 文件名形如:apiclient_cert.pem
            'mch_public_cert_path' => public_path().'/cert/wechat/apiclient_cert.pem',
            // 必填-微信回调url
            // 不能有参数,如?号,空格等,否则会无法正确回调
            'notify_url' => 'http://webman.tinywan.com/gateway/payment/wechat-notify',
            'return_url' => 'http://webman.tinywan.com/index',
            // 选填-公众号 的 app_id
            // 可在 mp.weixin.qq.com 设置与开发->基本配置->开发者ID(AppID) 查看
            'mp_app_id' => 'dsfdsfdsfdsdfdsafds',
            // 选填-小程序 的 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' => YansongdaPayPay::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' => true,
        'file' => runtime_path().'/logs/pay.log',
        'level' => 'debug', // 建议生产环境等级调整为 info,开发环境为 debug
        'type' => 'single', // optional, 可选 daily.
        'max_file' => 30, // optional, 当 type 为 daily 时有效,默认 30 天
    ],
    'http' => [ // optional
        'timeout' => 5.0,
        'connect_timeout' => 5.0,
    ],
];

注意:证书目录放在的框架的 public公共目录下

代码语言:javascript复制
webman.tinywan.com/public$ tree -L 4
.
├── 404.html
├── cert
│   └── wechat
│       ├── apiclient_cert.p12
│       ├── apiclient_cert.pem
│       ├── apiclient_key.pem
│       └── 证书使用说明.txt

使用

初始化

直接调用 config 方法初始化

代码语言:javascript复制
// 获取配置文件 config/payment.php
Pay::config(config('payment'));

注意:这里使用「微信公众号」进行支付

支付(微信公众号支付)

「服务端接口代码」

代码语言:javascript复制
use supportRequest;
use WebmanConfig;
use YansongdaPayPay;

/**
 * @desc: 公众号支付
 * @param Request $request
 * @return Response
 * @author Tinywan(ShaoBo Wan)
 */
public function recharge(Request $request): Response
{
    // 1. 订单预备订单
    $user['username'] = 'Tinywan';
    // 这个根据微信授权获取
    $user['openid'] = 'fsdfsd342343241231fdsfsdafsd';
    $order_sn = time();
    $totalAmount = 0.01;
    $discountAmount = 0;
    $payAmount = $totalAmount - $discountAmount;

    // 2. 支付开始预备订单
    Pay::config(config('payment'));
    $preOrder = [
        'out_trade_no' => $order_sn,
        'description' => $user['username'].',充值开源技术小栈',
        'amount' => [
            'total' => $payAmount * 100, // 分
        ],
        'payer' => [
            'openid' => $user['openid']
        ],
    ];
    // 公众号支付
    $wechatRes = Pay::wechat()->mp($preOrder);
}

路由地址为:/test/recharge

「前端JS代码」

代码语言:javascript复制
<!-- 引入 layui.css -->
<link rel="stylesheet" href="https://www.layuicdn.com/layui-v2.7.6/css/layui.css">
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
<script src="https://www.layuicdn.com/layui-v2.7.6/layui.js"></script>
<script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
<script>
    let paySign;
    let appId;
    let timeStamp;
    let nonceStr;
    let packageStr;
    let signType;
    // 触发支付
    layui.use(['form'], function () {
        var form = layui.form, layer = layui.layer;
        //监听提交
        form.on('submit(submit)', function (data) {
            $.ajax({
                type: "post",
                dataType: "json",
                data: {
                    openId: "{$openid}",
                    score: 100,
                    money: 10
                },
                url: "/test/recharge",
                async: false,
                success: function (data) {
                    if (data.code === 0) {
                        appId = data.data.appId;
                        paySign = data.data.paySign;
                        timeStamp = data.data.timeStamp;
                        nonceStr = data.data.nonceStr;
                        packageStr = data.data.package;
                        signType = data.data.signType;
                        callpay();
                    } else {
                        layer.msg("下单失败请稍后再重试", {
                            time: 50000,
                        });
                        return false;
                    }
                },
                error: function () {
                    layer.alert('系统异常')
                }
            });
            return false;
        });
    });

    /**
     * @desc 下单成功后调用 调用微信的支付界面
     * @author Tinywan(ShaoBo Wan)
     */
    function callpay() {
        console.log('调用微信的支付界面')
        if (typeof WeixinJSBridge == "undefined") {
            console.log('undefinedundefinedundefined');
            if (document.addEventListener) {
                document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
            } else if (document.attachEvent) {
                document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
                document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
            }
        } else {
            onBridgeReady();
        }
    }

    /**
     * @desc 下面两个方法都是固定写法 调用微信自带的支付界面
     * @author Tinywan(ShaoBo Wan)
     */
    function onBridgeReady() {
        WeixinJSBridge.invoke(
            'getBrandWCPayRequest', {
                "appId": appId,     //公众号名称,由商户传入
                "paySign": paySign,         //微信签名
                "timeStamp": timeStamp, //时间戳,自1970年以来的秒数
                "nonceStr": nonceStr, //随机串
                "package": packageStr,  //预支付交易会话标识
                "signType": signType     //微信签名方式
            },
            function (res) {
                if (res.err_msg === "get_brand_wcpay_request:ok") {
                    window.location.href = 'http://webman.tinywan.com/user/home'
                } else if (res.err_msg === "get_brand_wcpay_request:cancel") {
                    window.location.href = 'http://webman.tinywan.com/user/recharge?openid={$openid}';
                } else if (res.err_msg === "get_brand_wcpay_request:fail") {
                    window.location.href = 'http://webman.tinywan.com/user/home?openid={$openid}';
                }
            }
        );
    }
</script>
异步回调
代码语言:javascript复制
use supportRequest;
use WebmanConfig;
use YansongdaPayPay;

/**
 * @desc:『微信』异步通知
 * @param Request $request
 * @return string
 */
public function wechatNotify(Request $request): string
{
    Pay::config(Config::get('payment'));
    $result = Pay::wechat()->callback($request->post());

    // 接受回调信息
    $openid = $result['resource']['ciphertext']['payer']['openid'];
    $mchid = $result['resource']['ciphertext']['mchid'];
    $thirdSn = $result['resource']['ciphertext']['transaction_id'];
    $outTradeNo = $result['resource']['ciphertext']['out_trade_no'];
    $tradeState= $result['resource']['ciphertext']['trade_state'];
    $totalAmount = bcdiv((string) $result['resource']['ciphertext']['amount']['total'], '100', 2);

    // 异步响应
    $success = Pay::wechat()->success()->getBody()->getContents();
    return $success;
}

注意:这里异步接受请求方式为 POST 请求方式。

「异步参数接受数据」

代码语言:javascript复制
{
    "id": "1f5c3fb7-4f13-5069-a3fc-5708e98a4c1d",
    "create_time": "2023-11-05T19:30:16 08:00",
    "resource_type": "encrypt-resource",
    "event_type": "TRANSACTION.SUCCESS",
    "summary": "支付成功",
    "resource": {
        "original_type": "transaction",
        "algorithm": "AEAD_AES_256_GCM",
        "ciphertext": {
            "mchid": "1643333333427",
            "appid": "wxd39133333333ae28e1",
            "out_trade_no": "20231103333333331181193183",
            "transaction_id": "42000033333333334559785",
            "trade_type": "JSAPI",
            "trade_state": "SUCCESS",
            "trade_state_desc": "支付成功",
            "bank_type": "OTHERS",
            "attach": "",
            "success_time": "2023-11-05T19:30:16 08:00",
            "payer": {
                "openid": "oyRe_1DFDSFSDFSDFSDFrY"
            },
            "amount": {
                "total": 100,
                "payer_total": 100,
                "currency": "CNY",
                "payer_currency": "CNY"
            }
        },
        "associated_data": "transaction",
        "nonce": "d8bcd7PDSFSDF2"
    }
}

支付结果

日志

所有相关支付日志多存储在 项目目录/runtime/logs/pay.log文件中

0 人点赞