封装一个Model或者Vender类
Model
<?php
/**
* User: Eden
* Date: 2019/3/21
* 共有内容
*/
class WxPayModel extends Model {
protected static $SSL_CERT_PATH = './apiclient_cert.pem';//证书路径
protected static $SSL_KEY_PATH = './apiclient_key.pem';//证书路径
public static function unifiedOrder($openid,$order_num,$total_fee,$products_name,$notify_url = ''){
$trade_no = $order_num;
$url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
$param = [
'appid' => C('APPID'),
'mch_id' => C('MCHID'),
'nonce_str' => self::createNonceStr(),
'sign_type' => 'MD5',
'body' => $products_name, //商品名称组合
'attach' => C('APP_NAME').'-附加信息',
'out_trade_no' => $trade_no, //订单号
'fee_type' => 'CNY',
'total_fee' => $total_fee,
'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],
'goods_tag' => C('APP_NAME').'-商品标记',
'notify_url' => $notify_url ?:C('NOTIFY_URL'),
'trade_type' => 'JSAPI',
'openid' => $openid
];
$sign = self::MakeSign($param);
$param['sign'] = $sign;
$xml = self::ToXml($param);
$result = self::FromXml(Http::postXmlCurl($url,$xml));
setlog($param,$result,__METHOD__);
// 加工数据
$data = [
'appId' => $result['appid'] ?: C('APPID'),
'timeStamp' => time(),
'nonceStr' => self::createNonceStr(),
'package' => 'prepay_id=' . $result['prepay_id'],
'signType' => 'MD5'
];
$sign = self::MakeSign($data);
$data['sign'] = $sign;
return $data;
}
/**
* 处理退款
* @param $out_trade_no
* @param $total_fee
* @param $refund_fee
* @return array
* @throws Exception
*/
public static function refundOrder($out_trade_no,$total_fee,$refund_fee) {
$refund_no = $out_trade_no.rand('1111,9999');
$param = array(
'appid' => C('APPID'),
'mch_id' => C('MCHID'),
'nonce_str' => self::createNonceStr(),
'out_refund_no' => $refund_no, //由后端生成的退款单号,需要保证唯一,因为多个同样的退款单号只会退款一次。
'out_trade_no' => $out_trade_no, //退款订单在支付时生成的订单号
'total_fee' => $total_fee,
'refund_fee' => $refund_fee,
'op_user_id' => C('MCHID'), //操作员 op_user_id .与商户号相同即可
);
$param['sign'] = self::MakeSign($param);
$xml_data = self::ToXml($param);
$xml_result = self::postXmlSSLCurl($xml_data,'https://api.mch.weixin.qq.com/secapi/pay/refund');
$result = self::FromXml($xml_result);
setlog($param,$result,__METHOD__);
if (!$result){
$result_arr = [
'num' => '0',
'desc' => '接口错误',
];
return $result_arr;
}
if ($result['result_code'] != 'SUCCESS'){
$result_arr = [
'num' => '-1',
'desc' => $result['err_code_des']
];
} else {
$result_arr = [
'num' => '1',
'desc' => '退款成功',
'refund_id' => $result['refund_id'],
'refund_no' => $refund_no,
];
}
return $result_arr;
}
public static function FromXml($xml)
{
if(!$xml){
throw new Exception("xml数据异常!");
}
//将XML转为array
//禁止引用外部xml实体
libxml_disable_entity_loader(true);
$values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
return $values;
}
public static function ToXml($array){
if(!is_array($array)|| count($array) <= 0){
return ;
}
$xml = '<xml version="1.0">';
foreach ($array as $key=>$val){
if (is_numeric($val)){
$xml.="<".$key.">".$val."</".$key.">";
}else{
$xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
}
}
$xml.="</xml>";
return $xml;
}
public static function createNonceStr($length = 16) {
$chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
$str = '';
for ( $i = 0; $i < $length; $i++ ) {
$str .= substr($chars, mt_rand(0, strlen($chars)-1), 1);
}
return $str;
}
public static function MakeSign($data)
{
//签名步骤一:按字典序排序参数
ksort($data);
$string = self::ToUrlParams($data);
//签名步骤二:在string后加入KEY
$string = $string . "&key=".C('WEIXIN_PAY_KEY');
//签名步骤三:MD5加密
$string = md5($string);
//签名步骤四:所有字符转为大写
$result = strtoupper($string);
return $result;
}
public static function ToUrlParams($array)
{
$buff = "";
foreach ($array as $k => $v)
{
if($k != "sign" && $v != "" && !is_array($v)){
$buff .= $k . "=" . $v . "&";
}
}
$buff = trim($buff, "&");
return $buff;
}
/**
* 需要使用证书的请求
*/
public static function postXmlSSLCurl($xml,$url,$second=30)
{
$ch = curl_init();
//超时时间
curl_setopt($ch, CURLOPT_TIMEOUT, $second);
//这里设置代理,如果有的话
//curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8');
//curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
//设置header
curl_setopt($ch, CURLOPT_HEADER, FALSE);
//要求结果为字符串且输出到屏幕上
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
//设置证书
//使用证书:cert 与 key 分别属于两个.pem文件
//默认格式为PEM,可以注释
curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM');
curl_setopt($ch, CURLOPT_SSLCERT, self::$SSL_CERT_PATH);
//默认格式为PEM,可以注释
curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM');
curl_setopt($ch, CURLOPT_SSLKEY, self::$SSL_KEY_PATH);
//post提交方式
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
$data = curl_exec($ch);
//返回结果
if ($data) {
curl_close($ch);
return $data;
} else {
$error = curl_errno($ch);
echo "curl出错,错误码:$error" . "<br>";
curl_close($ch);
return false;
}
}
}
Vendor类
<?php
/**
* User: Eden
* Date: 2019/3/21
* 共有内容
*/
class WxPay {
protected static $SSL_CERT_PATH = './apiclient_cert.pem';//证书路径
protected static $SSL_KEY_PATH = './apiclient_key.pem';//证书路径
public static function unifiedOrder($openid,$order_num,$total_fee,$products_name,$notify_url = ''){
$trade_no = $order_num;
$url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
$param = [
'appid' => C('APPID'),
'mch_id' => C('MCHID'),
'nonce_str' => self::createNonceStr(),
'sign_type' => 'MD5',
'body' => $products_name, //商品名称组合
'attach' => C('APP_NAME').'-附加信息',
'out_trade_no' => $trade_no, //订单号
'fee_type' => 'CNY',
'total_fee' => $total_fee,
'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],
'goods_tag' => C('APP_NAME').'-商品标记',
'notify_url' => $notify_url ?:C('NOTIFY_URL'),
'trade_type' => 'JSAPI',
'openid' => $openid
];
$sign = self::MakeSign($param);
$param['sign'] = $sign;
$xml = self::ToXml($param);
$result = self::FromXml(Http::postXmlCurl($url,$xml));
setlog($param,$result,__METHOD__);
// 加工数据
$data = [
'appId' => $result['appid'] ?: C('APPID'),
'timeStamp' => time(),
'nonceStr' => self::createNonceStr(),
'package' => 'prepay_id=' . $result['prepay_id'],
'signType' => 'MD5'
];
$sign = self::MakeSign($data);
$data['sign'] = $sign;
return $data;
}
/**
* 处理退款
* @param $out_trade_no
* @param $total_fee
* @param $refund_fee
* @return array
* @throws Exception
*/
public static function refundOrder($out_trade_no,$total_fee,$refund_fee) {
$refund_no = $out_trade_no.rand('1111,9999');
$param = array(
'appid' => C('APPID'),
'mch_id' => C('MCHID'),
'nonce_str' => self::createNonceStr(),
'out_refund_no' => $refund_no, //由后端生成的退款单号,需要保证唯一,因为多个同样的退款单号只会退款一次。
'out_trade_no' => $out_trade_no, //退款订单在支付时生成的订单号
'total_fee' => $total_fee,
'refund_fee' => $refund_fee,
'op_user_id' => C('MCHID'), //操作员 op_user_id .与商户号相同即可
);
$param['sign'] = self::MakeSign($param);
$xml_data = self::ToXml($param);
$xml_result = self::postXmlSSLCurl($xml_data,'https://api.mch.weixin.qq.com/secapi/pay/refund');
$result = self::FromXml($xml_result);
setlog($param,$result,__METHOD__);
if (!$result){
$result_arr = [
'num' => '0',
'desc' => '接口错误',
];
return $result_arr;
}
if ($result['result_code'] != 'SUCCESS'){
$result_arr = [
'num' => '-1',
'desc' => $result['err_code_des']
];
} else {
$result_arr = [
'num' => '1',
'desc' => '退款成功',
'refund_id' => $result['refund_id'],
'refund_no' => $refund_no,
];
}
return $result_arr;
}
public static function FromXml($xml)
{
if(!$xml){
throw new Exception("xml数据异常!");
}
//将XML转为array
//禁止引用外部xml实体
libxml_disable_entity_loader(true);
$values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
return $values;
}
public static function ToXml($array){
if(!is_array($array)|| count($array) <= 0){
return ;
}
$xml = '<xml version="1.0">';
foreach ($array as $key=>$val){
if (is_numeric($val)){
$xml.="<".$key.">".$val."</".$key.">";
}else{
$xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
}
}
$xml.="</xml>";
return $xml;
}
public static function createNonceStr($length = 16) {
$chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
$str = '';
for ( $i = 0; $i < $length; $i++ ) {
$str .= substr($chars, mt_rand(0, strlen($chars)-1), 1);
}
return $str;
}
public static function MakeSign($data)
{
//签名步骤一:按字典序排序参数
ksort($data);
$string = self::ToUrlParams($data);
//签名步骤二:在string后加入KEY
$string = $string . "&key=".C('WEIXIN_PAY_KEY');
//签名步骤三:MD5加密
$string = md5($string);
//签名步骤四:所有字符转为大写
$result = strtoupper($string);
return $result;
}
public static function ToUrlParams($array)
{
$buff = "";
foreach ($array as $k => $v)
{
if($k != "sign" && $v != "" && !is_array($v)){
$buff .= $k . "=" . $v . "&";
}
}
$buff = trim($buff, "&");
return $buff;
}
/**
* 需要使用证书的请求
*/
public static function postXmlSSLCurl($xml,$url,$second=30)
{
$ch = curl_init();
//超时时间
curl_setopt($ch, CURLOPT_TIMEOUT, $second);
//这里设置代理,如果有的话
//curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8');
//curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
//设置header
curl_setopt($ch, CURLOPT_HEADER, FALSE);
//要求结果为字符串且输出到屏幕上
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
//设置证书
//使用证书:cert 与 key 分别属于两个.pem文件
//默认格式为PEM,可以注释
curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM');
curl_setopt($ch, CURLOPT_SSLCERT, self::$SSL_CERT_PATH);
//默认格式为PEM,可以注释
curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM');
curl_setopt($ch, CURLOPT_SSLKEY, self::$SSL_KEY_PATH);
//post提交方式
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
$data = curl_exec($ch);
//返回结果
if ($data) {
curl_close($ch);
return $data;
} else {
$error = curl_errno($ch);
echo "curl出错,错误码:$error" . "<br>";
curl_close($ch);
return false;
}
}
}
使用效果差不多。
封装一个Model或者Vender类的更多相关文章
- python+selenium之自定义封装一个简单的Log类
python+selenium之自定义封装一个简单的Log类 一. 问题分析: 我们需要封装一个简单的日志类,主要有以下内容: 1. 生成的日志文件格式是 年月日时分秒.log 2. 生成的xxx.l ...
- Python之自定义封装一个简单的Log类
参考:http://www.jb51.net/article/42626.htm 参考:http://blog.csdn.net/u011541946/article/details/70198676 ...
- Python+Selenium中级篇之8-Python自定义封装一个简单的Log类《转载》
Python+Selenium中级篇之8-Python自定义封装一个简单的Log类: https://blog.csdn.net/u011541946/article/details/70198676
- java模板模式项目中使用--封装一个http请求工具类
需要调用http接口的代码继承FundHttpTemplate类,重写getParamData方法,在getParamDate里写调用逻辑. 模板: package com.crb.ocms.fund ...
- PHP封装一个通用好用的文件上传处理类
封装一个文件上传类完成基本功能如下: 1.可上传多个或单个文件 2.上传成功返回一个或多个文件名 3.上传失败则返回每个失败文件的错误信息 上传类中的基本功能: 1.构造参数,用户可以自定义配置参数, ...
- Directx11学习笔记【四】 封装一个简单的Dx11DemoBase
根据前面两个笔记的内容,我们来封装一个简单的基类,方便以后的使用. 代码和前面类似,没有什么新的内容,直接看代码吧(由于代码上次都注释了,这次代码就没怎么写注释o(╯□╰)o) Dx11DemoBas ...
- 第二十二章、 Model/View便利类树型部件QTreeWidget
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.引言 树部件(Tree Widget)是Qt Designer中 Item Widgets(It ...
- Swift - 简单封装一个工具类模板
创建模板类(封装一个类) 例1:新建一个名字叫做 Product 的类 Product.swift File 的内容 class Product { var name: String var desc ...
- 基于AFNetWorking封装一个网络请求数据的类
1.新建一个继承于NSObject类的类,在.h文件中 #import "AFHTTPRequestOperationManager.h" //定义两个block来接收请求成功和失 ...
随机推荐
- leetcode解题报告(16):Move Zeroes
描述 Given an array nums, write a function to move all 0's to the end of it while maintaining the rela ...
- Js 之cookie插件(jquery.cookie.js)
一.代码 (function (factory) { if (typeof define === 'function' && define.amd) { // AMD define([ ...
- anzhuang ruanjian
makepkg -i https://github.com/arch4edu/arch4edu/wiki/Add-arch4edu-to-your-Archlinux Add arch4edu to ...
- TynSerial结构体序列(还原)
TynSerial结构体序列(还原) 1)定义一个结构体 type TRec = record id, name: string; end; 2)结构体序列(还原) procedure TForm1. ...
- html,body设置{height:100%}[转]
一般情况下,我们css控制的最高节点就是body,例如设置: body{background:#069;} 则浏览器界面就是完全的#068的背景色.这里看上去是<body>标签下的背景色起 ...
- OpenGL ES: (3) EGL、EGL绘图的基本步骤、EGLSurface、ANativeWindow
1. EGL概述 EGL 是 OpenGL ES 渲染 API 和本地窗口系统(native platform window system)之间的一个中间接口层,它主要由系统制造商实现. EGL提供如 ...
- leetcode 55. Jump Game、45. Jump Game II(贪心)
55. Jump Game 第一种方法: 只要找到一个方式可以到达,那当前位置就是可以到达的,所以可以break class Solution { public: bool canJump(vecto ...
- net start mysql 发生系统错误2 系统找不到指定的文件
以管理员身份运行,在命令行输入cd+mySQL的bin目录的安装路径 C:\Windows\system32>cd C:\Program Files\MySQL\MySQL Server5.6\ ...
- 【分类算法】感知机(Perceptron)
0 - 算法描述 感知机算法是一类二分类算法,其问题描述为,给定一个训练数据集 $$T=\{(x_1,y_1),(x_2,y_2),\cdots,(x_N,y_N)\},$$ 其中$x_i\in \m ...
- c语言 GPS nmealib学习笔记
.nmealib简介 nmealib是一个基于C语言的用于nmea协议的开源库.虽然nmea体积小巧,但是却具备了不少功能. 分析NMEA语句并把结果保存在合适的C语言结构体中. 除了解析NMEA语句 ...