PHP服务商微信支付分支付(需确认模式)

//查询支付分是否支付
public function serviceorderServiceorder($out_order_no)
{

    $setting = [];

    $service_id = $setting['service_id'];
    $sub_mchid = $setting['mchid'];

    $ps = "/v3/payscore/partner/serviceorder?service_id=${service_id}&sub_mchid=${sub_mchid}&out_order_no=${out_order_no}";
    $url = "https://api.mch.weixin.qq.com" . $ps;

    $header = $this->getV3Sign('GET', $ps, "", $setting);

    $res = $this->curl_post($url, [], $header, false);
    $result = json_decode($res, true);
    if ($result['state'] == "DONE") {
        $need_collection = true;
    } else {
        $need_collection = false;
    }
    $transaction_id = $result['collection']['details'][0]['transaction_id'] ?? "";
    $state = $result['state'];
    return compact('state', 'need_collection', 'transaction_id');

}

//完成信用分订单
public function completeServiceorder($data)
{

    $setting = [];
    $data['money'] = (int)bcmul($data['money'], 100, 0);
    $out_order_no = $data['order_no'];
    $service_id = $setting['service_id'];
    $sub_mchid = $setting['mchid'];
    $post_payments = [[
        'name' => '付款',
        'amount' => $data['money']
    ]];

    $time_range = [
        'end_time' => date('Ymd', time())
    ];

    $total_amount = $data['money'];

    $url = "https://api.mch.weixin.qq.com/v3/payscore/partner/serviceorder/" . $out_order_no . "/complete";

    $arr = [
        'service_id' => $service_id,
        'sub_mchid' => $sub_mchid,
        'post_payments' => $post_payments,
        'total_amount' => $total_amount,
        'time_range' => $time_range
    ];
    $arr = json_encode($arr);
    $header = $this->getV3Sign('POST', "/v3/payscore/partner/serviceorder/" . $out_order_no . "/complete", $arr, $setting);

    $res = $this->curl_post($url, $arr, $header);
    $result = json_decode($res, true);
    if (isset($result['message']) && $result['message']) {
        \think\Log::error($result['message'] . "_" . $data['order_no']);
        return false;
    }

    return true;

}


//取消信用分订单
public function cancelServiceorder($out_order_no)
{

    $setting = [];
    $service_id = $setting['service_id'];
    $sub_mchid = $setting['mchid'];
    $reason = "用户取消";

    $arr = [
        'service_id' => $service_id,
        'sub_mchid' => $sub_mchid,
        'reason' => $reason
    ];

    $url = "https://api.mch.weixin.qq.com/v3/payscore/partner/serviceorder/{$out_order_no}/cancel";

    $arr = json_encode($arr);
    $header = $this->getV3Sign('POST', "/v3/payscore/partner/serviceorder/{$out_order_no}/cancel", $arr, $setting);

    $res = $this->curl_post($url, $arr, $header);
    $result = json_decode($res, true);

    return $result;
}

//创建信用分订单
public function addServiceorder($data)
{
    $setting = [];//数组数据
    $service_id = $setting['service_id'];
    $appid = $setting['main_gzh_app_id'];
    $sub_appid = $setting['gzh_app_id'];
    $sub_mchid = $setting['mchid'];
    $out_order_no = $data['order_no'];
    $service_introduction = "付款";//描述
    $risk_fund = [
        'name' => 'ESTIMATE_ORDER_COST',
        'amount' => 10000
    ];

    $time_range = [
        'start_time' => date('Ymd', time())
    ];
    $notify_url = $setting['zfj_notify_url'] ?? "";

    $arr = [
        'sub_appid' => $sub_appid,
        'service_id' => $service_id,
        'appid' => $appid,
        'sub_mchid' => $sub_mchid,
        'out_order_no' => $out_order_no,
        'service_introduction' => $service_introduction,
        'risk_fund' => $risk_fund,
        'time_range' => $time_range,
        'notify_url' => $notify_url,
        'need_user_confirm' => true
    ];

    $url = "https://api.mch.weixin.qq.com/v3/payscore/partner/serviceorder";

    $arr = json_encode($arr);
    $header = $this->getV3Sign('POST', '/v3/payscore/partner/serviceorder', $arr, $setting);

    $res = $this->curl_post($url, $arr, $header);
    $result = json_decode($res, true);
    if (isset($result['message']) && $result['message']) {
        throw new BaseException(['msg' => 'message: ' . $result['message']]);
    }

    $timestamp = time();
    $nonce_str = getRandom(32);//随机串

    $js_arr = [
        'sign_type' => 'HMAC-SHA256',
        'mch_id' => $result['mchid'],
        'package' => $result['package'],
        'timestamp' => $timestamp,
        'nonce_str' => $nonce_str
    ];

    $sign = $this->makeSign($js_arr, $setting['v3_apikey']);

    $js_arr['sign'] = $sign;
    ksort($js_arr);
    $js_arr = $this->toUrlParams($js_arr);
    $a_s = [
        'order_id' => $result['order_id'],
        'out_order_no' => $result['out_order_no'],
        'package' => $result['package'],
        'cont' => $js_arr
    ];
    return $a_s;
}

/**
 * 格式化参数格式化成url参数
 * @param $values
 * @return string
 */
public function toUrlParams($values)
{
    $buff = '';
    foreach ($values as $k => $v) {
        if ($k != 'sign' && $v != '' && !is_array($v)) {
            $buff .= $k . '=' . $v . '&';
        }
    }
    return trim($buff, '&');
}

/**
 * 生成签名
 * @param $values
 * @return string 本函数不覆盖sign成员变量,如要设置签名需要调用SetSign方法赋值
 */
public function makeSign($values, $key = null)
{
    //签名步骤一:按字典序排序参数
    ksort($values);
    $string = $this->toUrlParams($values);
    //签名步骤二:在string后加入KEY
    $string = $string . '&key=' . $key;
    $string = md5($string);
    $string = hash_hmac("sha256", $string, $key);
    //签名步骤四:所有字符转为大写
    $result = strtoupper($string);
    return $result;
}


public function getV3Sign($http_method = 'POST', $url = '', $body = '', $config)
{
    $mch_private_key = $config['key_pem'];
    $timestamp = time();//时间戳
    $nonce = getRandom(32);//随机串

    //构造签名串
    $message = $http_method . "\n" . $url . "\n" . $timestamp . "\n" . $nonce . "\n" . $body . "\n";
    //计算签名值
    openssl_sign($message, $raw_sign, $mch_private_key, 'SHA256');
    $sign = base64_encode($raw_sign);
//        echo $message;
//        echo "<br />";
//        echo $sign;exit;

    //设置HTTP头
    $token = sprintf('WECHATPAY2-SHA256-RSA2048 mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"',
        $config['main_mchid'], $nonce, $timestamp, $config['serial_no'], $sign);
    $headers = [
        'Accept: application/json',
        'User-Agent: */*',
        'Content-Type: application/json; charset=utf-8',
        'Authorization: ' . $token,
    ];
    return $headers;
}

Index.php

//免密自动支付
public function index()
{
	$order_no = "订单号";
    $rts = (new WxGzhPay())->addServiceorder([
        'order_no' => $order_no
    ]);
	
	$wx_js = "";//微信js参数

    $this->assign('wx_js', $wx_js);
    $this->assign('queryString', $rts);	
	
	return view();

}

html部分代码

wx.config({
    debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
    appId: '{$wx_js["appID"]}', // 必填,公众号的唯一标识
    timestamp: '{$wx_js["timestamp"]}', // 必填,生成签名的时间戳
    nonceStr: '{$wx_js["noncestr"]}', // 必填,生成签名的随机串
    signature: '{$wx_js["signature"]}',// 必填,签名
    jsApiList: ['openBusinessView'] // 必填,需要使用的JS接口列表
});

let wechatInfo = navigator.userAgent.match(/MicroMessenger\/([\d\.]+)/i);
let wechatVersion = wechatInfo[1];
if (compareVersion(wechatVersion, '7.0.5') >= 0) {
    goToWXScore();
} else {
    // 提示用户升级微信客户端版本
    window.href = 'https://support.weixin.qq.com/cgi-bin/readtemplate?t=page/common_page__upgrade&text=text005&btn_text=btn_text_0'
}

let az_type = 1

if(/android/i.test(navigator.userAgent)){
     az_type = 1
 }
 if(/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)){
     az_type = 2
 }

function goToWXScore() {
      wx.ready(()=>{
          wx.checkJsApi({
              jsApiList: ['openBusinessView'], // 需要检测的JS接口列表
              success: function (res) {
                  if (res.checkResult.openBusinessView) {
                      wx.invoke(
                          'openBusinessView', {
                              businessType: 'wxpayScoreUse',
                              queryString: 'package={$queryString["package"]}'
                          },
                          function (res) {
                              if(az_type==1){
                                  if (parseInt(res.err_code) === 0) {
                                      let r = JSON.parse(res.extraData)
                                      if(!r.query_id){
                                         //成功
                                      }else {
                                          //失败
                                      }
                                  } else {
                                  	//失败
                                  }
                              }else{
                                  let the_code = JSON.stringify(res['err_code'])
                                  // 从微信侧小程序返回时会执行这个回调函数
                                  if (parseInt(the_code) === 0) {

                                      let r = JSON.stringify(res.extraData)
                                      if(r=="{}"){
                                          //失败
                                      }else {
                                          //成功
                                      }
                                  } else {
                                          //失败
                                  }
                              }

                          });
                  }
              }
          });
      })

  }

正常的话会跳入此页面
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/392049.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【PyQt】14-绘图-QPainter

文章目录 前言一、QPainter二、绘制文本-drawTextQt里面的文本对齐方式 运行结果 三、像素点总结 前言 1、学会画图方法 一、QPainter 通常可以绘制文本、各种图形&#xff08;点、线、椭圆、弧、扇形、多边形等等&#xff09;、图像。 必须在painrEvent事件方法中绘制各种元…

CES 2024:NVIDIA 通过新的笔记本电脑、GPU 和工具提供生成式 AI

在 CES 2024 上&#xff0c;NVIDIA 推出了一系列硬件和软件&#xff0c;旨在释放 Windows 11 PC 上生成式 AI 的全部潜力。 在 PC 上本地运行生成式 AI 对于隐私、延迟和成本敏感型应用程序至关重要。在 CES 上&#xff0c;NVIDIA 将在整个技术堆栈中带来新的创新&#xff0c;…

MATLAB导出图程序

本文将以代码的形式快速介绍MATLAB导出图到Paper 1 从simulation导出数 2 与simulation同源文件夹下创建导图m文件 代码如下&#xff1a; % 实验后的数据处理用 M-文件 % clear all % 清空工作空间 % close all      % 关闭所有图形窗口 % load adp.mat …

双指针算法+例题

1、性质 双指针算法&#xff0c;实质上是把朴素算法O&#xff08;n^2),发现一些性质&#xff0c;转换成 O&#xff08;N&#xff09;时间复杂度。 2、图解核心思想 3、代码模板 for(int i0,j0;i<n;i) {while(j<i && check(i,j)) j;//每道题目的具体逻辑 } 4…

对树莓派上配置mdadm的一些补充

1、如果要重新配置该如何回退到初始状态&#xff1f; 答&#xff1a;可参考以下指令&#xff1a; cat /proc/mdstat sudo umount /dev/md0 sudo mdadm --stop /dev/md0 sudo mdadm --zero-superblock /dev/sda sudo mdadm --zero-superblock /dev/sdb sudo nano /etc/fstab&a…

ModuleNotFoundError: No module named ‘torchvision.models.utils‘报错的一种解决方法

最近在做一个BEV项目&#xff0c;在配置环境的时候&#xff0c;遇到了报错的一个问题&#xff1a; ModuleNotFoundError: No module named ‘torchvision.models.utils’ 我开始以为是我没有安装torchvision pip install torchvision -i http://pypi.douban.com/simple输入这…

CSS-基础-MDN文档学习笔记

CSS构建基础 查看更多学习笔记&#xff1a;GitHub&#xff1a;LoveEmiliaForever MDN中文官网 CSS选择器 选择器是什么 CSS 选择器是 CSS 规则的第一部分&#xff0c;它用来选择HTML元素&#xff0c;选择器所选择的元素&#xff0c;叫做选择器的对象 选择器列表 如果有多…

实战 | 使用CNN和OpenCV实现数字识别项目(步骤 + 源码)

导 读 本文主要介绍使用CNN和OpenCV实现数字识别项目,含详细步骤和源码。 前 言 在当今世界,深度学习和图像处理技术正在各个应用领域得到利用。在这篇博文中,我们将使用卷积神经网络 (CNN) 和 OpenCV 库完成数字识别项目。我们将逐步掌握该项目如何执行。 项目准…

安装 SEED-XDS560v2 Driver.exe

安装 SEED-XDS560v2 Driver.exe References CCS 5.5.0.00077 安装目录 D:\ti\ccsv5\ SEED-XDS560v2 Driver.exe 安装目录 D:\ti\ccsv5\ccs_base References [1] Yongqiang Cheng, https://yongqiang.blog.csdn.net/

【51单片机实验笔记】开关篇(二) 矩阵按键

目录 前言原理图分析矩阵按键扫描算法 软件实现1. 矩阵键盘检测2. 简易计算器实现 总结 前言 本节内容&#xff0c;我们学习一下矩阵按键&#xff0c;它是独立按键的阵列形式&#xff0c;常见的应用即键盘。 本节涉及到的封装源文件可在《模块功能封装汇总》中找到。 本节完…

jmeter-10调试取样器

文章目录 作用设置使用举例 作用 jmeter中添加调试取样器&#xff0c;可以用于检测测试过程的值如&#xff1a;变量、参数、系统设置等 设置 选择线程组右键 >>> 添加 >>> 取样器 >>> 调试取样器&#xff08;Debug Sampler&#xff09; jmeter …

Docker 镜像仓库是什么?有哪些镜像仓库命令?

1. Docker 的架构 &#xff08;图片来源&#xff1a;Docker架构图&#xff09; Registry&#xff08;Docker 仓库&#xff09; &#xff1a; Docker 仓库用来保存镜像&#xff0c;Docker 官方提供了一个公共的 Docker 仓库&#xff0c;称为 Docker Hub&#xff0c;开发者可以在…

函数、极限、连续——刷题(4

目录 1.题目&#xff1a;2.解题思路和步骤&#xff1a;3.总结&#xff1a;小结&#xff1a; 1.题目&#xff1a; 2.解题思路和步骤&#xff1a; 记住这个公式即可&#xff1a; 所以就很容易求解了&#xff1a; 3.总结&#xff1a; 记住这个公式即可&#xff1a; 小结&am…

使用 Coze 搭建 TiDB 助手

导读 本文介绍了使用 Coze 平台搭建 TiDB 文档助手的过程。通过比较不同 AI Bot 平台&#xff0c;突出了 Coze 在插件能力和易用性方面的优势。文章深入讨论了实现原理&#xff0c;包括知识库、function call、embedding 模型等关键概念&#xff0c;最后成功演示了如何在 Coze…

GIS使用 RUSLE 方法绘制土壤侵蚀风险图

侵蚀是指土壤在水或风的作用下离开其所在位置,它分为两种:自然侵蚀和加速侵蚀。水土流失实际上是一个自然过程,因此形成了肥沃的三角洲平原,但在人类活动的影响下,这一过程加速,水土流失超过了应有的程度。因此,农业生产率下降,生产成本上升,水坝寿命缩短,水质下降,…

11-k8s中网络资源service

一、service资源概述 每当我们企业的业务pod迭代功能的时候&#xff0c;都会修改pod&#xff0c;修改后重新启动pod&#xff0c;ip就会变化&#xff0c;那么在生产环境当中&#xff0c;从用户到宿主机、从宿主机到pod&#xff0c;这一个访问流程&#xff0c;都是事先写好的&…

【JavaScript】面试手写题精讲之数组(下)

引入 这章主要讲的是数组的排序篇&#xff0c;我们知道面试的时候&#xff0c;数组的排序是经常出现的题目。所以这块还是有必要进行一下讲解的。笔者观察了下前端这块的常用算法排序题&#xff0c;大概可以分为如下 冒泡排–> 稳定排序插入排序–> 稳定排序选择排序–…

你了解API测试吗?如何充分的测试一个API?

什么是API&#xff1f; API代表应用程序接口。API是软件系统中的中间层&#xff0c;负责数据源与用户看到的图形用户界面&#xff08;GUI&#xff09;之间的数据通信。换句话说&#xff0c;API是软件的业务层&#xff0c;它在表示层和数据层之间创建连接。 API测试侧重于所谓的…

Leecode之面试题消失的数字

一.题目及剖析 https://leetcode.cn/problems/missing-number-lcci/description/ 方法有很多,这里将两种时间复杂度为O(N)的方法 二.思路引入 第一种方法 先将0-n的总和求出来,在求出数组的总和,在做差就能得到消失的数字,不过要注意的是数据有可能溢出,这个方法很简单就不再…

Acwing二分和前缀和(二)

机器人跳跃问题 原题链接&#xff1a;https://www.acwing.com/activity/content/problem/content/1570/ 二分查找更新条件只有两种&#xff1a; Rmid;else Lmid1&#xff1a;mid(LR)/2Lmid;else R mid-1&#xff1a;mid(LR1)/2 这两种更新条件的结果是一样的。 #include<…