Payment SDK (V3)

Project Address

https://github.com/yansongda/pay

Installation

composer require yansongda/pay ~3.0

Usage

Note: The following documentation is written based on the Alipay sandbox environment. If you have any questions, please provide feedback timely!

Configuration File

Assuming the following configuration file config/payment.php

<?php
/**
 * @desc Payment configuration file
 * @author Tinywan(ShaoBo Wan)
 * @date 2022/03/11 20:15
 */
return [
    '_force' => true, // Note: This must be true
    'alipay' => [
        'default' => [
            // Required - Alipay assigned app_id
            'app_id' => '20160909004708941',
            // Required - Application private key string or path
            'app_secret_cert' => 'MIIEpAIBAAKCxxxxxxxxxxxxxxP4r3m4OUmD/+XDgCg==',
            // Required - Application public key certificate path
            'app_public_cert_path' => base_path().'/payment/appCertPublicKey_2016090900470841.crt',
            // Required - Alipay public key certificate path
            'alipay_public_cert_path' => base_path().'/payment/alipayCertPublicKey_RSA2.crt',
            // Required - Alipay root certificate path
            'alipay_root_cert_path' => base_path().'/payment/alipayRootCert.crt',
            // Optional - Synchronous callback address
            'return_url' => 'https://webman.tinywan.cn/payment/alipay-return',
            // Optional - Asynchronous callback address
            'notify_url' => 'https://webman.tinywan.cn/payment/alipay-notify',
            // Optional - Service provider ID in provider mode, used when mode is Pay::MODE_SERVICE
            'service_provider_id' => '',
            // Optional - Default is normal mode. Options: MODE_NORMAL, MODE_SANDBOX, MODE_SERVICE
            'mode' => \Yansongda\Pay\Pay::MODE_SANDBOX,
        ]
    ],
    'wechat' => [
        'default' => [
            // Required - Merchant ID, service provider ID in service provider mode
            'mch_id' => '',
            // Required - Merchant secret key
            'mch_secret_key' => '',
            // Required - Merchant private key string or path
            'mch_secret_cert' => '',
            // Required - Merchant public key certificate path
            'mch_public_cert_path' => '',
            // Required
            'notify_url' => 'https://yansongda.cn/wechat/notify',
            // Optional - Public account's app_id
            'mp_app_id' => '2016082000291234',
            // Optional - Mini program's app_id
            'mini_app_id' => '',
            // Optional - App's app_id
            'app_id' => '',
            // Optional - Combined order app_id
            'combine_app_id' => '',
            // Optional - Combined merchant ID
            'combine_mch_id' => '',
            // Optional - Sub public account's app_id in service provider mode
            'sub_mp_app_id' => '',
            // Optional - Sub app's app_id in service provider mode
            'sub_app_id' => '',
            // Optional - Sub mini program's app_id in service provider mode
            'sub_mini_app_id' => '',
            // Optional - Sub merchant ID in service provider mode
            'sub_mch_id' => '',
            // Optional - WeChat public key certificate path, strongly recommended to configure this parameter in php-fpm mode
            'wechat_public_cert_path' => [
                '45F59D4DABF31918AFCEC556D5D2C6E376675D57' => __DIR__.'/Cert/wechatPublicKey.crt',
            ],
            // Optional - Default is normal mode. Options: MODE_NORMAL, MODE_SERVICE
            'mode' => \Yansongda\Pay\Pay::MODE_SANDBOX,
        ]
    ],
    'logger' => [
        'enable' => false,
        'file' => runtime_path().'/logs/alipay.log',
        'level' => 'debug', // It is recommended to adjust the level to info in the production environment; debug for the development environment
        'type' => 'single', // optional, can be set to daily.
        'max_file' => 30, // optional, valid when type is daily, default is 30 days
    ],
    'http' => [ // optional
        'timeout' => 5.0,
        'connect_timeout' => 5.0,
        // For more configuration options, please refer to [Guzzle](https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html)
    ]
];

Note: There is no specific requirement for the certificate directory; the above example places it in the framework's payment directory.

├── payment
│   ├── alipayCertPublicKey_RSA2.crt
│   ├── alipayRootCert.crt
│   └── appCertPublicKey_2016090900470841.crt

Initialization

Directly call the config method to initialize.

// Retrieve the configuration file config/payment.php
$config = config('payment');
Pay::config($config);

Note: If using the Alipay sandbox mode, remember to set the configuration file 'mode' => \Yansongda\Pay\Pay::MODE_SANDBOX,. This option defaults to normal mode.

Payment (Web)

use support\Request;
use Yansongda\Pay\Pay;

/**
 * @param Request $request
 * @return string
 */
public function payment(Request $request)
{
    // 1. Initialize configuration
    Pay::config(config('payment'));

    // 2. Web payment
    $order = [
        'out_trade_no' => time(),
        'total_amount' => '8888.88',
        'subject' => 'webman payment',
        '_method' => 'get' // Use GET method for redirection
    ];
    return Pay::alipay()->web($order)->getBody()->getContents();
}

Asynchronous Callback

use support\Request;
use Yansongda\Pay\Pay;

/**
 * @desc: Alipay asynchronous notification
 * @param Request $request
 * @return Response
 */
public function alipayNotify(Request $request): Response
{
    // 1. Initialize configuration
    Pay::config(config('payment'));

    // 2. Alipay callback handling
    $result = Pay::alipay()->callback($request->post());

    // ===================================================================================================
    // Please determine trade_status and other logic; only when the transaction notification status is TRADE_SUCCESS or TRADE_FINISHED, will Alipay deem it a successful payment by the buyer.
    // 1. The merchant needs to verify if the out_trade_no in the notification data corresponds to the order number created in the merchant system;
    // 2. Check if total_amount is indeed the actual amount of that order (i.e., the amount when the merchant order was created);
    // 3. Validate if the seller_id (or seller_email) in the notification corresponds to the operator of this out_trade_no;
    // 4. Verify if app_id is the merchant itself.
    // 5. Other business logic conditions
    // ===================================================================================================

    // 5. Alipay callback handling
    return new Response(200, [], 'success');
}

Note: Do not use the plugin itself return Pay::alipay()->success(); to respond to Alipay callbacks, as middleware issues may arise. Therefore, use the webman response class support\Response; to respond to Alipay.

Synchronous Callback

use support\Request;
use Yansongda\Pay\Pay;

/**
 * @desc: Alipay synchronous notification
 * @param Request $request
 * @author Tinywan(ShaoBo Wan)
 */
public function alipayReturn(Request $request)
{
    Log::info('Alipay synchronous notification: '.json_encode($request->get()));
    return 'success';
}

More Content

Visit the official documentation at https://pay.yansongda.cn/docs/v3/