微信支付开发-支付工厂AppApi产品代码

news/2024/9/20 13:40:27/

一、JSAPI支付产品、APP支付产品、小程序支付产品流程图

二、工厂父类抽象类代码开发

<?php
/*** 微信父类抽象类* User: 龙哥·三年风水* Date: 2024/9/19* Time: 11:33*/
namespace Payment\WechatPay;
abstract class WechatPaymentHandle
{/*** 下单* User: 龙哥·三年风水* Date: 2024/9/19* Time: 11:36* @ return mixed*/protected abstract function pay();/*** 查询* User: 龙哥·三年风水* Date: 2024/9/19* Time: 11:39* @ param $transactionId 原支付交易对应的微信订单号* @ return mixed*/protected abstract function transac($transactionId);/*** 退款* User: 龙哥·三年风水* Date: 2024/9/19* Time: 11:42* @ param $outRefundNo 退款单号* @ param $amount 退款额* @ param string $notifyUrl 异步通知地址* @ param string $transactionId 原支付交易对应的微信订单号,与$outTradeNo二选一* @ param string $outTradeNo 原支付交易对应的商户订单号,与$transactionId二选一* @ return mixed*/protected abstract function refunds($outRefundNo,$amount,$notifyUrl ='',$transactionId = '',$outTradeNo = '');
}

三、工厂通道选择类代码开发

<?php
/*** 微信支付工厂通道选择类* User: 龙哥·三年风水* Date: 2024/9/19* Time: 11:47*/
namespace Payment\WechatPay;
use app\BaseError;
use Payment\WechatPay\impl\AppApi;
use Payment\WechatPay\impl\JsApi;
class WechatPaymentFactory
{protected static $instance = null;//缓存实例protected $merchantId = null;// 商户号protected $merchantSerialNumber = null;// 商户API证书序列号protected $appid = null;// 公众号IDprotected $merchantPrivateKey = null;// 商户私钥protected $channelType = 0;//通道类型/*** 初始化资源*/public function __construct($type){$this->merchantId = config('pay.wechat.merchant_id');$this->appid = config('pay.wechat.app_id');$this->merchantSerialNumber = config('pay.wechat.merchant_serial_number');$file = file_get_contents('./wechatpay/apiclient_key.pem');$this->merchantPrivateKey = openssl_get_privatekey($file);// 读取商户秘钥self::$instance = null;$this->channelType = $type;}/*** 通道选择* User: 龙哥·三年风水* Date: 2024/9/19* Time: 14:34* @ param $url* @ param $data* @ return null|JsApi*/public function sendWechatPaymentHandle($url,$data){switch ((int)$this->channelType){case 1:$data['appid'] = $this->appid;$data['mchid'] = $this->merchantId;$authorization = $this->getSign($url,$data);self::$instance = new JsApi($url,$authorization,$data);break;case 2:$data['appid'] = $this->appid;$data['mchid'] = $this->merchantId;$authorization = $this->getSign($url,$data);self::$instance = new AppApi($url,$authorization,$data);break;case 3:break;case 4:break;case 5:break;default:self::$instance = null;throw new BaseError("未设置任何通道",50000,200);break;}return self::$instance;}/*** 生成签名* User: 龙哥·三年风水* Date: 2024/9/19* Time: 14:01* @ param $url* @ param $data* @ return string*/protected function getSign($url,$data){$timestamp = time();$nonce = alnum(12).date('YmdHis', $timestamp) . rand(1000, 9999);$url_parts = parse_url($url);$canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));$data = json_encode($data);$message = 'POST' . "\n" .$canonical_url . "\n" .$timestamp . "\n" .$nonce . "\n" .$data . "\n";openssl_sign($message, $signature, $this->merchantPrivateKey, "sha256WithRSAEncryption");$sign = base64_encode($signature);$schema = 'WECHATPAY2-SHA256-RSA2048';$token = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"',  $this->merchantId, $nonce, $timestamp, $this->merchantSerialNumber, $sign);return "Authorization: " . $schema . " " . $token;}/***销毁资源*/public function __destruct(){$this->merchantId = null;$this->appid = null;$this->merchantSerialNumber = null;$this->merchantPrivateKey = null;self::$instance = null;}
}

四、AppApi支付产品代码开发

<?php
/*** App支付方式* User: 龙哥·三年风水* Date: 2024/9/20* Time: 10:55*/
namespace Payment\WechatPay\impl;
use Payment\WechatPay\WechatPaymentHandle;
use app\BaseError;
class AppApi extends WechatPaymentHandle
{protected $url = ''; //访问路径protected $header = ''; //头文件protected $data = []; //数据组/*** 初始化* @ param $url* @ param $header* @ param $data*/public function __construct($url,$header,$data){$this->url = $url;$this->header = $header;$this->data = $data;}/*** 下单* User: 龙哥·三年风水* Date: 2024/9/19* Time: 11:36* @ return mixed*/public function pay(){$res = http_post($this->url, $this->header, $this->data);$arr = json_decode($res, true);if(isset($arr['code'])) {$error['code'] = $arr['code'];$error['message'] = $arr['message'];$error['timestamp'] = time();$error['ip'] = get_client_ip();file_put_contents('app_pay.txt', json_encode($error) . PHP_EOL, FILE_APPEND);throw new BaseError($arr['message'], 50000, 200);}return $arr;}/*** 查询* User: 龙哥·三年风水* Date: 2024/9/19* Time: 11:39* @ param $transactionId 原支付交易对应的微信订单号* @ return mixed*/public function transac($transactionId){// TODO: Implement transac() method.}/*** 退款* User: 龙哥·三年风水* Date: 2024/9/19* Time: 11:42* @ param $outRefundNo 退款单号* @ param $amount 退款额* @ param string $notifyUrl 异步通知地址* @ param string $transactionId 原支付交易对应的微信订单号,与$outTradeNo二选一* @ param string $outTradeNo 原支付交易对应的商户订单号,与$transactionId二选一* @ return mixed*/public function refunds($outRefundNo, $amount, $notifyUrl = '', $transactionId = '', $outTradeNo = ''){// TODO: Implement refunds() method.}/****/public function __destruct(){$this->url = '';$this->header = '';$this->data = [];}
}

五、测试调用

public function index(){//定义参数$data['description'] = '运费钱';$data['out_trade_no'] = create_order();$data['time_expire'] = date('Y-m-d\TH:i:s\+08:00',time()+3600);$data['notify_url'] = 'http://www.baidu.com';$data['amount'] = ['total'     =>  100,'currency'  =>  'CNY'];// 初始化通道$wechatPaymentFactory = new WechatPaymentFactory(2);// 选择实例$wechatPaymentHandle = $wechatPaymentFactory->sendWechatPaymentHandle('https://api.mch.weixin.qq.com/v3/pay/transactions/app',$data);$res = $wechatPaymentHandle->pay();var_dump($res);
}

http://www.ppmy.cn/news/1528002.html

相关文章

如何查看电脑什么时候被人动过及看过的文件?

一、查看Windows事件查看器 Windows系统具有强大的日志记录功能&#xff0c;通过“事件查看器”可以查看电脑的使用记录。具体步骤如下&#xff1a; 按下Win R组合键打开运行窗口&#xff0c;输入eventvwr.msc命令并回车&#xff0c;打开事件查看器。 在事件查看器中&#x…

2.计算机网络基础

2. 计算机网络基础 (1) 计算机网络的定义 计算机网络是指将地理位置不同、具有独立功能的多个计算机系统通过通信线路和设备连接起来,以功能完善的网络软件实现网络中资源共享的系统。最简单的定义是:计算机网络是一些互相连接的、自治的计算机系统的集合。最庞大的计算机网…

Kafka基础概念

1.kafka概念 Producer&#xff1a;生产消息实例 Broker&#xff1a;管理和存储消息服务端服务器 Consumer&#xff1a;消费消息的实例 Record&#xff1a;kafka系统中的消息 2.kafka概念-主题 topic&#xff1a;主题&#xff0c;消息的类别 主要用于区别一个broker&#…

DAY11:学习作业

p 和 "hello,world"存储在内存哪个区域&#xff1f;( ) int main(){char *p "hello,world";return 0; } 答案&#xff1a;栈区 分析&#xff1a;内存分为内核、栈区、共享映射区、堆区、静态区全局区&#xff0c;内核是放命令行参数得&#xff0c;栈区是…

Linux操作系统 进程(3)

接上文 Linux进程优先级之后&#xff0c;我们了解到僵尸进程与孤儿进程的形成原因&#xff0c;既然是因为父进程没有接收子进程的退出状态导致的&#xff0c;那么我们该如何去获取子进程的退出状态呢&#xff1f;那本篇文章将围绕这个问题来解释进程。 环境 &#xff1a; vsco…

阿里史上最大规模开源发布,超GPT-4o 、Llama-3.1!

今天凌晨&#xff0c;阿里巴巴官宣了史上最大规模的开源发布&#xff0c;推出了基础模型Qwen2.5、专用于编码Qwen2.5-Coder和数学的Qwen2.5-Math。 这三大类模型一共有10多个版本&#xff0c;包括0.5B、1.5B、3B、7B、14B、32B和72B&#xff0c;适用于个人、企业以及移动端、P…

13_Python的高阶函数

高阶函数 高阶函数是Python编程中一个非常强大和有用的特性&#xff0c;它们允许程序员编写更简洁、更抽象的代码。 Python中的高阶函数是那些至少满足以下一个条件的函数&#xff1a; 接受一个或多个函数作为输入&#xff08;也就是说&#xff0c;它的参数之一是函数&#…

前端vue-父传子

父传子的话是在components中创建一个子组件MyTest.vue&#xff0c;并且在父组件中先导入(import MyTest from "./components/MyTest")&#xff0c;再注册&#xff08;在expo二default中写上 compnents:{MyTest}&#xff09;&#xff0c;再使用标签&#xff08;<My…

axios二次封装

axios的使用以及二次封装 一&#xff1a;axios的使用二&#xff1a;vue中的二次封装1.终端下载2.main.js中引入3.封装axios实例--http.js4.添加请求拦截器5.添加响应1拦截器6.封装请求API7.组件内使用 一&#xff1a;axios的使用 1.下载 npm i axios -S2.引入 import axios …

财富通公司开发维修售后小程序,解决售后维修问题

财富通公司为广大用户开发的维修售后小程序&#xff0c;旨在便捷地解决售后维修问题&#xff0c;提升用户体验&#xff0c;增强客户粘性。以下是该小程序如何具体解决售后维修问题的几个关键点&#xff1a; 一. 一站式报修流程 1.简化操作&#xff1a;用户只需通过小程序几步…

[Unity Demo]从零开始制作空洞骑士Hollow Knight第四集:制作更多的敌人

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、制作敌人僵尸虫Zombie 1.公式化导入制作僵尸虫Zombie素材2.制作僵尸虫Zombie的Walker.cs状态机3.制作敌人僵尸虫的playmaker状态机二、制作敌人爬虫Climber…

手把手教你用Ollama AnythingLLM搭建AI知识库,无需编程,跟着做就行!

在本地电脑上跑大语言模型&#xff08;LLM&#xff09;&#xff0c;已经不是什么高科技操作了。随着技术的迭代&#xff0c;现在利用Ollam和AnythingLLM就可以轻松构建自己的本地知识库&#xff0c;人人皆可上手&#xff0c;有手就行。过往要达成这一目标&#xff0c;可是需要有…

mysql学习教程,从入门到精通,SQL 删除数据(DELETE 语句)(19)

1、SQL 删除数据&#xff08;DELETE 语句&#xff09; 在SQL中&#xff0c;TRUNCATE TABLE 语句用于删除表中的所有行&#xff0c;但不删除表本身。这个操作通常比使用 DELETE 语句删除所有行要快&#xff0c;因为它不记录每一行的删除操作到事务日志中&#xff0c;而是直接重…

ConflictingBeanDefinitionException | 运行SpringBoot项目时报错bean定义冲突解决方案

具体报错&#xff1a; Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name ‘CommissionMapperImpl’ for bean class [com.xxx.mapper.carrier.CommissionMapperImpl] conflicts with existing, non-co…

基于嵌入式系统的水果分类解决方案:STM32F4与OpenCV的决策树实现

一、项目概述 项目目标和用途 本项目旨在利用 STM32F4 单片机结合 OpenCV 实现水果分类&#xff0c;通过决策树算法对不同种类的水果进行识别和分类。项目可以广泛应用于智能农业、自动售货机及教育领域等场景&#xff0c;帮助用户快速识别水果种类&#xff0c;提高生产效率和…

条件编译代码记录

#include <iostream>// 基类模板 template<typename T> class Base { public:void func() {std::cout << "Base function" << std::endl;} };// 特化的子类 template<typename T> class Derived : public Base<T> { public:void…

密集行人数据集 CrowdHumanvoc和yolo两种格式,yolo可以直接使用train val test已经划分好有yolov8训练200轮模型

密集行人数据集 CrowdHuman voc和yolo两种格式&#xff0c;yolo可以直接使用 train val test已经划分好 有yolov8训练200轮模型。 CrowdHuman 密集行人检测数据集 数据集描述 CrowdHuman数据集是一个专为密集行人检测设计的数据集&#xff0c;旨在解决行人密集场景下的检测挑…

python 爬虫 selenium 笔记

todo 阅读并熟悉 Xpath, 这个与 Selenium 密切相关、 selenium selenium 加入无图模式&#xff0c;速度快很多。 from selenium import webdriver from selenium.webdriver.chrome.options import Options# selenium 无图模式&#xff0c;速度快很多。 option Options() o…

【C++篇】C++类与对象深度解析(二):类的默认成员函数详解

文章目录 【C篇】C类与对象深度解析&#xff08;二&#xff09;前言1. 类的默认成员函数2. 构造函数2.1 函数名与类名相同2.2 无返回值2.3 对象实例化时系统会自动调用2.4 构造函数可以重载2.5 默认构造函数的生成规则2.6 无参构造函数与全缺省构造函数的关系2.7 内置类型与自定…

【Kubernetes】常见面试题汇总(十七)

目录 51.简述 Kubernetes 网络策略&#xff1f; 52.简述 Kubernetes 网络策略原理&#xff1f; 53.简述 Kubernetes 中 flannel 的作用&#xff1f; 54.简述 Kubernetes Calico 网络组件实现原理&#xff1f; 51.简述 Kubernetes 网络策略&#xff1f; - 为实现细粒度的容器…