【开源微信】微信支付V3接口调用与PHP开源实现

1、概述

支付功能是软件服务的关键一环,需要用户、支付应用、服务商和支付平台共同参与完成。为此,支付平台开放基础支付API,并提供常用开发语言SDK供开发者使用;支付服务商和软件开发者基于API和SDK根据业务场景开发具体支付业务。但是,从基础支付API、SDK到最终实现支付的过程比较复杂,需要一套简洁的实现框架和更高层的工具。本文以微信支付V3为基础,设计一套前后端分离支付框架,并提供开源实现(奇辰Open-API),做到支付功能开箱即用。

1.1支付服务参与者

  • 支付平台:微信支付、支付宝等第三方平台;
  • 服务商:具备基于支付平台基础功能提供支付服务的商家;
  • 应用:由服务商提供或者自研的具备支付功能应用,包括H5、小程序、APP等;
  • 用户:使用支付应用功能的人。

本文档主要面向服务商或者具备自研能力的应用开发者。

1.2难点关键技术

  • 通用支付流程架构:管理员支付配置,用户从前端使用支付功能,后端闭环支付业务流程。
  • 开箱即用API:通过简单的API调用即可完成业务所需支付功能。

2、通用支付架构

设计前后端分离通用支付架构如下图所示:

 基于前后端分离开源奇辰Open-API框架的后端支付服务实现后端支付业务,由开源框架后端服务完成和第三方微信支付平台的调用和回调工作,开发者不必再关注这方面的工作,可以把重心放在支付业务侧; 基于开源前端基础框架实现所需的支付应用和支付后台。在这个支付架构下,管理员通过支付台调用后端支付业务进行支付设置;用户支付应用端使用支付功能。

3、微信支付V3开源PHP实现框架

3.1支付设置

微信支付V3所有接口功能基于证书进行实现,有两类证书需要加以区分:商户API证书是每个微信商户自身的证书,另一类是微信支付平台证书;关于两类证书详情请参考微信支付官方文档。在 开源奇辰Open-API框架已经对证书管理进行了封装,开发者不再需要进行证书相关业务的开发。

  1. 先设置微信支付商户号、商户密钥,上传商户API证书三个文件;
  2. 完成前面设置,可以直接在后台获取微信支付平台证书。每个商户对应的微信支付平台证书不同,开源框架已经封装了微信支付平台证书管理,开发者不再需要关注此项功能开发。 

3.2支付调用

管理员完成微信支付设置后,前端应用可以调用封装好的接口发起支付。

  • 调用接口

调用方式:HTTP、HTTPS

api: pay/wx/pay

HTTP请求方法:POST

  • 接口实现

后端封装的接口实现如下:

public function pay(Request $request)
    {
        $instance = Init::getInstance();
        $conf = ConfModel::first();
        $resp = $instance
            ->v3->pay->transactions->jsapi
            ->post(['json' => [
                'mchid'        => $conf->mchid,
                'out_trade_no' => Sn::build_order_no(),
                'appid'        => $conf->miniapp_appid,
                'description'  => '奇辰Open-API微信支付',
                'notify_url'   => env('HOST_URL') . '/pay/wx/notify',
                'amount'       => [
                    'total'    => 1,
                    'currency' => 'CNY'
                ],
                'payer' => [
                    'openid' => $request->input('openid')
                ]
            ]]);
        $jsapi_result = json_decode($resp->getBody()->getContents());
        // 从本地文件中加载「商户API私钥」,「商户API私钥」会用来生成请求的签名
        $merchantPrivateKeyFilePath = 'file://' . env('ATTACHMENT_ROOT') . $conf->key_file;
        $merchantPrivateKeyInstance = Rsa::from($merchantPrivateKeyFilePath, Rsa::KEY_TYPE_PRIVATE);
        $params = [
            'appId'     => $conf->miniapp_appid,
            'timeStamp' => (string)Formatter::timestamp(),
            'nonceStr'  => Formatter::nonce(),
            'package'   => 'prepay_id=' . $jsapi_result->prepay_id,
        ];
        $params += ['paySign' => Rsa::sign(
            Formatter::joinedByLineFeed(...array_values($params)),
            $merchantPrivateKeyInstance
        ), 'signType' => 'RSA'];

        $res = ResultTool::success();
        $res['data']['params'] = $params;
        return $res;
    }

代码第3行调用微信支付初始化函数获取微信支付实例,第12行设置支付回调接口,第18行设置接口参数传入的微信openid。接口返回前端调起支付所需的js参数,如下:

pay() {
            let user_info = uni.getStorageSync('user_info')
            wxPay({
                openid: user_info.openid
            }).then(res => {
                if (res.errorCode == 200) {
                    let params = res.data
                    wx.requestPayment({
                        timeStamp: params.timeStamp,
                        nonceStr: params.nonceStr,
                        package: params.package,
                        signType: params.signType,
                        paySign: params.paySign,
                        success(res) { 
                            console.log(res)
                        },
                        fail(res) { 
                            console.log(res)
                        }
                    })
                }
            })
        }

前端wxPay函数在第9-13行获取后端返回的支付参数params,前端调用wx.requrestPayment函数调起支付如下图所示:

 3.3支付回调

支付完成后,前面支付设置的回调接口能收到相关支付信息。

  • 回调接口

调用方式:HTTP、HTTPS

api: pay/wx/notify

HTTP请求方法:POST

  • 接口实现

后端封装的接口实现如下:

public function callback(Request $request)
    {
        $inWechatpaySignature = $request->header('Wechatpay-Signature'); // 请根据实际情况获取
        $inWechatpayTimestamp = $request->header('Wechatpay-Timestamp'); // 请根据实际情况获取
        $inWechatpaySerial = $request->header('Wechatpay-Serial'); // 请根据实际情况获取
        $inWechatpayNonce = $request->header('Wechatpay-Nonce'); // 请根据实际情况获取
        $inBody = file_get_contents('php://input'); // 请根据实际情况获取,例如: file_get_contents('php://input');

        $conf = ConfModel::first();
        $apiv3Key = $conf->signkey; // 在商户平台上设置的APIv3密钥

        // 根据通知的平台证书序列号,查询本地平台证书文件,
        // 假定为 `/path/to/wechatpay/inWechatpaySerial.pem`
        $platformPublicKeyInstance = Rsa::from('file://' . env('ATTACHMENT_ROOT') . 'wxpay/' . 'wechatpay_' . $inWechatpaySerial . '.pem', Rsa::KEY_TYPE_PUBLIC);

        // 检查通知时间偏移量,允许5分钟之内的偏移
        $timeOffsetStatus = 300 >= abs(Formatter::timestamp() - (int)$inWechatpayTimestamp);
        $verifiedStatus = Rsa::verify(
            // 构造验签名串
            Formatter::joinedByLineFeed($inWechatpayTimestamp, $inWechatpayNonce, $inBody),
            $inWechatpaySignature,
            $platformPublicKeyInstance
        );
        if ($timeOffsetStatus && $verifiedStatus) {
            // 转换通知的JSON文本消息为PHP Array数组
            $inBodyArray = (array)json_decode($inBody, true);
            // 使用PHP7的数据解构语法,从Array中解构并赋值变量
            ['resource' => [
                'ciphertext'      => $ciphertext,
                'nonce'           => $nonce,
                'associated_data' => $aad
            ]] = $inBodyArray;
            // 加密文本消息解密
            $inBodyResource = AesGcm::decrypt($ciphertext, $apiv3Key, $nonce, $aad);
            // 把解密后的文本转换为PHP Array数组
            $inBodyResourceArray = (array)json_decode($inBodyResource, true);
            // print_r($inBodyResourceArray);// 打印解密后的结果
        }

        echo 'success';
    }

在回调接口的第36行$inBodyResourceArray里面可以开发业务所需要的支付回调功能。

 4、更多

开源项目:Open-Api

更多信息:www.lokei.cn

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现微信v3扫码支付,可以使用PHP编程语言进行开发。下面是一种可能的实现方式: 首先,需要在微信支付商户平台上进行相关配置。确保您已经开通了扫码支付功能,并且已获取到了商户号、API密钥等必要的信息。 然后,您需要用到PHP的curl扩展库来进行HTTP请求和接口调用。通过curl库,您可以方便地向微信支付接口发送请求,并获取返回结果。 在编码中,首先需要构建请求参数。具体来说,您需要构建一个JSON格式的请求体,包含必要的支付信息,例如商户订单号、支付金额、通知URL等。同时,还需要对请求体进行签名,以确保请求的安全性。 接下来,使用curl库发送HTTP请求到微信支付的统一下单API。请求中包含了商户号、API密钥和构建好的请求体。发送成功后,微信支付会返回一个预支付交易会话标识,用于生成二维码。 通过解析返回的结果,您可以获取到包含二维码URL的字段。将该URL显示在您的页面上,用户可以使用微信扫描该二维码完成支付。 同时,您还需要处理用户支付结果的通知。当用户支付成功后,微信服务器会向您预先设置的通知URL发送支付结果通知。您需要编写一个接收通知的回调函数来处理这些通知。在回调函数中,您需要验证通知的签名,并对通知进行处理,例如更新订单状态、保存支付结果等。 最后,您需要考虑支付的安全性。在进行支付时,要确保请求的数据、返回的结果以及通知的验证中都使用了正确的API密钥。此外,还需要对请求参数、返回结果和通知进行签名验证,以防止数据被篡改。 综上所述,通过PHP实现微信v3扫码支付的过程主要包括:配置微信支付商户平台、构建请求参数、发送HTTP请求、处理支付结果通知和保障支付的安全性。通过合理的开发和配置,您可以成功实现微信扫码支付功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值