PHP code example of moonpie / mp-virtual-pay

1. Go to this page and download the library: Download moonpie/mp-virtual-pay library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

moonpie / mp-virtual-pay example snippets


use EasyWeChat\MiniProgram\Application;
use Moonpie\EasyWechat\VirtualPay\VirtualPayServiceProvider;

$config = [
    'app_id' => 'wx-app-id',
    'secret' => 'wx-app-secret',
    'response_type' => 'array',
    
    // 虚拟支付配置
    'virtual_pay' => [
        'offer_id' => 'your offer id',
        'app_key' => 'your-prod-app-key',
        'sandbox_app_key' => 'your-sandbox-app-key',
        'env' => 0, // 0-正式环境 1-沙箱环境
    ],
];

$miniProgram = new Application($config);
$miniProgram->register(new VirtualPayServiceProvider());

// 1. 查询用户余额(需要用户态签名)
$balance = $miniProgram->virtual_pay_balance->queryUserBalance(
    'user-openid',
    '127.0.0.1',
    $userSessionKey // 从用户登录获取
);

// 2. 扣减代币(需要用户态签名)
$result = $miniProgram->virtual_pay_currency->currencyPay([
    'openid' => 'user-openid',
    'amount' => 100,
    'order_id' => 'order-123',
    'user_ip' => '127.0.0.1',
    'payitem' => json_encode([[
        'productid' => 'item-001',
        'unit_price' => 100,
        'quantity' => 1
    ]])
], $userSessionKey);

// 3. 查询商家余额(不需要用户态签名)
$bizBalance = $miniProgram->virtual_pay_balance->queryBizBalance();

// 4. 代币赠送(不需要用户态签名)
$presentResult = $miniProgram->virtual_pay_currency->presentCurrency([
    'openid' => 'user-openid',
    'order_id' => 'present-001',
    'amount' => 50,
]);

// 5. 查询订单
$order = $miniProgram->virtual_pay_order->queryOrder('order-123');//使用商家订单号
$order = $miniProgram->virtual_pay_order->queryWxOrder('wx-order-123');//使用微信订单号

// 6. 退款
$refund = $miniProgram->virtual_pay_order->refundOrder([
    'openid' => 'user-openid',
    'order_id' => 'order-123',
    'refund_order_id' => 'refund-001',
    'left_fee' => 100,
    'refund_fee' => 100,
    'refund_reason' => '0',
    'req_from' => '2',
]);
// 7. 发起支付, 需要sessionKey
$signData = [
'buyQuantity' => 1, //number		是	购买数量
'env' => 0, //number		否	环境配置, 0 米大师正式环境, 1 米大师沙箱环境, 默认为 0
'currencyType' => 'CNY', //string		是	币种 合法值	说明 CNY	人民币
'productId' => '', string		否	道具ID, **该字段仅mode=short_series_goods时需要必填**
'goodsPrice' => 100, //number		否	道具单价(分), **该字段仅mode=short_series_goods时需要必填**, 用来校验价格与后台道具价格是否一致, 避免用户在业务商城页看到的价格与实际价格不一致导致投诉 
'activitySellingPrice' => 40, //number		否	道具优惠价格(分),**非必填,该字段需与goodsPrice一起传入**。如用户使用优惠券、积分等,需要以低于道具价格下单时可传入,传入后该价格即为实际下单价格,优惠价格最低为道具价格的40%。(注:iOS端暂不支持使用优惠价格下单) 
'outTradeNo' => 'unique order no', //string		是	业务订单号, 每个订单号只能使用一次, 重复使用会失败(极端情况不保证唯一, 不建议业务强依赖唯一性).  要求8-32个字符内, 只能是数字、大小写字母、符号 _-|*@组成, 不能以下划线(_)开头
'attach' => '', //	string		是	透传数据, 发货通知时会透传给
];
$mode = 'short_series_goods';//可选项short_series_goods	道具直购|short_series_coin	代币充值
$virtualPayData = $miniProgram->virtual_pay_order->buildVirtualPayData($signData, $mode, $sessionKey);

// 8. 消息通知回调
//添加统一的消息监听器
use EasyWeChat\Kernel\Messages\Message;
$dispatcher = $app->events;
$dispatcher->addListener('xpay_goods_deliver_notify', callable(Event\GoodsDeliveredEvent $event));//道具发货推送
$dispatcher->addListener('xpay_coin_pay_notify', callable(Event\CoinPaidEvent $event));//代币支付推送
$dispatcher->addListener('xpay_refund_notify', callable(Event\RefundProcessedEvent $event));//退款推送
$dispatcher->addListener('xpay_complaint_notify', callable(Event\ComplaintFiledEvent $event));//用户投诉推送
$dispatcher->addListener('xpay_subscribe_ios_refund_query_notify', callable(Event\IosRefundQueryNotifyEvent $event));//iOS退款问询推送
$handler = new Moonpie\EasyWechat\VirtualPay\Server\Handlers\VirtualPayEventHandler($dispatcher, $app);
$app->server->push($handler, Message::EVENT);
$response = $app->server->serve();
//如何处理$response需要针对不同框架对Symfony Response的支持区别对待
//使用者的重心将集中到如何编写具体事件的callable
//其中callback中的返回数据是该$event, 使用以下方法来生成微信要求的response
return $event->markOk();//返回正常
return $event->markFail(reason);//返回错误

use Moonpie\EasyWechat\VirtualPay\Event\IosRefundQueryNotifyEvent;

$dispatcher->addListener('xpay_subscribe_ios_refund_query_notify', function (IosRefundQueryNotifyEvent $event) {
    // 获取问询信息
    $refundTime = $event->getRefundTime();           // 问询时间(Unix时间戳)
    $orderTime = $event->getOrderTime();             // 原订单时间(Unix时间戳)
    $channelBill = $event->getChannelBill();         // Apple票据号
    $bundleId = $event->getBundleId();               // Apple bundleid
    $productId = $event->getProductId();             // 道具ID
    $pCount = $event->getPCount();                   // 道具/代币数量
    $refundReason = $event->getRefundRequestReason();// 用户退款原因
    $provideStatus = $event->getProvideStatus();     // 发货状态: 0-未发货 1-已发货 2-发货中
    $payOrderId = $event->getPayOrderId();           // 退款对应支付订单号

    // 根据业务策略决定是否同意退款
    if ($provideStatus === 0) {
        // 未发货,同意退款
        $event->approveRefund('订单未发货,同意退款', '未发货');
    } else {
        // 已发货,拒绝退款
        $event->rejectRefund('道具已消耗,无法退款', '已消耗');
    }
});