Initial project files: BESCMS full source
This commit is contained in:
@@ -0,0 +1,591 @@
|
||||
<?php
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* 接口访问类,包含所有微信支付API列表的封装,类中方法为static方法,
|
||||
* 每个接口有默认超时时间(除提交被扫支付为10s,上报超时时间为1s外,其他均为6s)
|
||||
* @author widyhu
|
||||
*
|
||||
*/
|
||||
class WxPayApi
|
||||
{
|
||||
/**
|
||||
*
|
||||
* 统一下单,WxPayUnifiedOrder中out_trade_no、body、total_fee、trade_type必填
|
||||
* appid、mchid、spbill_create_ip、nonce_str不需要填入
|
||||
* @param WxPayUnifiedOrder $inputObj
|
||||
* @param int $timeOut
|
||||
* @throws WxPayException
|
||||
* @return 成功时返回,其他抛异常
|
||||
*/
|
||||
public static function unifiedOrder($inputObj, $timeOut = 6)
|
||||
{
|
||||
$url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
|
||||
//检测必填参数
|
||||
if(!$inputObj->IsOut_trade_noSet()) {
|
||||
return dr_return_data(0, "缺少统一支付接口必填参数out_trade_no!");
|
||||
}else if(!$inputObj->IsBodySet()){
|
||||
return dr_return_data(0, "缺少统一支付接口必填参数body!");
|
||||
}else if(!$inputObj->IsTotal_feeSet()) {
|
||||
return dr_return_data(0, "缺少统一支付接口必填参数total_fee!");
|
||||
}else if(!$inputObj->IsTrade_typeSet()) {
|
||||
return dr_return_data(0, "缺少统一支付接口必填参数trade_type!");
|
||||
}
|
||||
|
||||
//关联参数
|
||||
if($inputObj->GetTrade_type() == "JSAPI" && !$inputObj->IsOpenidSet()){
|
||||
return dr_return_data(0, "统一支付接口中,缺少必填参数openid!trade_type为JSAPI时,openid为必填参数!");
|
||||
}
|
||||
|
||||
if($inputObj->GetTrade_type() == "NATIVE" && !$inputObj->IsProduct_idSet()){
|
||||
return dr_return_data(0, "统一支付接口中,缺少必填参数product_id!trade_type为JSAPI时,product_id为必填参数!");
|
||||
}
|
||||
|
||||
//异步通知url未设置,则使用配置文件中的url
|
||||
if(!$inputObj->IsNotify_urlSet()){
|
||||
$inputObj->SetNotify_url(NOTIFY_URL);//异步通知url
|
||||
}
|
||||
|
||||
$inputObj->SetAppid(APPID);//公众账号ID
|
||||
$inputObj->SetMch_id(MCHID);//商户号
|
||||
$inputObj->SetSpbill_create_ip($_SERVER['REMOTE_ADDR']);//终端ip
|
||||
//$inputObj->SetSpbill_create_ip("1.1.1.1");
|
||||
$inputObj->SetNonce_str(self::getNonceStr());//随机字符串
|
||||
|
||||
//签名
|
||||
$inputObj->SetSign();
|
||||
$xml = $inputObj->ToXml();
|
||||
|
||||
$startTimeStamp = self::getMillisecond();//请求开始时间
|
||||
$response = self::postXmlCurl($xml, $url, false, $timeOut);
|
||||
if (isset($response['code']) && $response['code']==0) {
|
||||
return $response;
|
||||
}
|
||||
$result = WxPayResults::Init($response);
|
||||
if (isset($result['code']) && $result['code']==0) {
|
||||
return $result;
|
||||
} elseif (isset($result['return_code']) && $result['return_code']=='FAIL') {
|
||||
return dr_return_data(0, $result['return_msg']);
|
||||
}
|
||||
|
||||
self::reportCostTime($url, $startTimeStamp, $result);//上报请求花费时间
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 查询订单,WxPayOrderQuery中out_trade_no、transaction_id至少填一个
|
||||
* appid、mchid、spbill_create_ip、nonce_str不需要填入
|
||||
* @param WxPayOrderQuery $inputObj
|
||||
* @param int $timeOut
|
||||
* @throws WxPayException
|
||||
* @return 成功时返回,其他抛异常
|
||||
*/
|
||||
public static function orderQuery($inputObj, $timeOut = 6)
|
||||
{
|
||||
$url = "https://api.mch.weixin.qq.com/pay/orderquery";
|
||||
//检测必填参数
|
||||
if(!$inputObj->IsOut_trade_noSet() && !$inputObj->IsTransaction_idSet()) {
|
||||
return dr_return_data(0, "订单查询接口中,out_trade_no、transaction_id至少填一个!");
|
||||
}
|
||||
$inputObj->SetAppid(APPID);//公众账号ID
|
||||
$inputObj->SetMch_id(MCHID);//商户号
|
||||
$inputObj->SetNonce_str(self::getNonceStr());//随机字符串
|
||||
|
||||
$inputObj->SetSign();//签名
|
||||
$xml = $inputObj->ToXml();
|
||||
|
||||
$startTimeStamp = self::getMillisecond();//请求开始时间
|
||||
$response = self::postXmlCurl($xml, $url, false, $timeOut);
|
||||
$result = WxPayResults::Init($response);
|
||||
self::reportCostTime($url, $startTimeStamp, $result);//上报请求花费时间
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 关闭订单,WxPayCloseOrder中out_trade_no必填
|
||||
* appid、mchid、spbill_create_ip、nonce_str不需要填入
|
||||
* @param WxPayCloseOrder $inputObj
|
||||
* @param int $timeOut
|
||||
* @throws WxPayException
|
||||
* @return 成功时返回,其他抛异常
|
||||
*/
|
||||
public static function closeOrder($inputObj, $timeOut = 6)
|
||||
{
|
||||
$url = "https://api.mch.weixin.qq.com/pay/closeorder";
|
||||
//检测必填参数
|
||||
if(!$inputObj->IsOut_trade_noSet()) {
|
||||
return dr_return_data(0, "订单查询接口中,out_trade_no必填!");
|
||||
}
|
||||
$inputObj->SetAppid(APPID);//公众账号ID
|
||||
$inputObj->SetMch_id(MCHID);//商户号
|
||||
$inputObj->SetNonce_str(self::getNonceStr());//随机字符串
|
||||
|
||||
$inputObj->SetSign();//签名
|
||||
$xml = $inputObj->ToXml();
|
||||
|
||||
$startTimeStamp = self::getMillisecond();//请求开始时间
|
||||
$response = self::postXmlCurl($xml, $url, false, $timeOut);
|
||||
$result = WxPayResults::Init($response);
|
||||
self::reportCostTime($url, $startTimeStamp, $result);//上报请求花费时间
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 申请退款,WxPayRefund中out_trade_no、transaction_id至少填一个且
|
||||
* out_refund_no、total_fee、refund_fee、op_user_id为必填参数
|
||||
* appid、mchid、spbill_create_ip、nonce_str不需要填入
|
||||
* @param WxPayRefund $inputObj
|
||||
* @param int $timeOut
|
||||
* @throws WxPayException
|
||||
* @return 成功时返回,其他抛异常
|
||||
*/
|
||||
public static function refund($inputObj, $timeOut = 6)
|
||||
{
|
||||
$url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
|
||||
//检测必填参数
|
||||
if(!$inputObj->IsOut_trade_noSet() && !$inputObj->IsTransaction_idSet()) {
|
||||
return dr_return_data(0, "退款申请接口中,out_trade_no、transaction_id至少填一个!");
|
||||
}else if(!$inputObj->IsOut_refund_noSet()){
|
||||
return dr_return_data(0, "退款申请接口中,缺少必填参数out_refund_no!");
|
||||
}else if(!$inputObj->IsTotal_feeSet()){
|
||||
return dr_return_data(0, "退款申请接口中,缺少必填参数total_fee!");
|
||||
}else if(!$inputObj->IsRefund_feeSet()){
|
||||
return dr_return_data(0, "退款申请接口中,缺少必填参数refund_fee!");
|
||||
}else if(!$inputObj->IsOp_user_idSet()){
|
||||
return dr_return_data(0, "退款申请接口中,缺少必填参数op_user_id!");
|
||||
}
|
||||
$inputObj->SetAppid(APPID);//公众账号ID
|
||||
$inputObj->SetMch_id(MCHID);//商户号
|
||||
$inputObj->SetNonce_str(self::getNonceStr());//随机字符串
|
||||
|
||||
$inputObj->SetSign();//签名
|
||||
$xml = $inputObj->ToXml();
|
||||
$startTimeStamp = self::getMillisecond();//请求开始时间
|
||||
$response = self::postXmlCurl($xml, $url, true, $timeOut);
|
||||
$result = WxPayResults::Init($response);
|
||||
self::reportCostTime($url, $startTimeStamp, $result);//上报请求花费时间
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 查询退款
|
||||
* 提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,
|
||||
* 用零钱支付的退款20分钟内到账,银行卡支付的退款3个工作日后重新查询退款状态。
|
||||
* WxPayRefundQuery中out_refund_no、out_trade_no、transaction_id、refund_id四个参数必填一个
|
||||
* appid、mchid、spbill_create_ip、nonce_str不需要填入
|
||||
* @param WxPayRefundQuery $inputObj
|
||||
* @param int $timeOut
|
||||
* @throws WxPayException
|
||||
* @return 成功时返回,其他抛异常
|
||||
*/
|
||||
public static function refundQuery($inputObj, $timeOut = 6)
|
||||
{
|
||||
$url = "https://api.mch.weixin.qq.com/pay/refundquery";
|
||||
//检测必填参数
|
||||
if(!$inputObj->IsOut_refund_noSet() &&
|
||||
!$inputObj->IsOut_trade_noSet() &&
|
||||
!$inputObj->IsTransaction_idSet() &&
|
||||
!$inputObj->IsRefund_idSet()) {
|
||||
return dr_return_data(0, "退款查询接口中,out_refund_no、out_trade_no、transaction_id、refund_id四个参数必填一个!");
|
||||
}
|
||||
$inputObj->SetAppid(APPID);//公众账号ID
|
||||
$inputObj->SetMch_id(MCHID);//商户号
|
||||
$inputObj->SetNonce_str(self::getNonceStr());//随机字符串
|
||||
|
||||
$inputObj->SetSign();//签名
|
||||
$xml = $inputObj->ToXml();
|
||||
|
||||
$startTimeStamp = self::getMillisecond();//请求开始时间
|
||||
$response = self::postXmlCurl($xml, $url, false, $timeOut);
|
||||
$result = WxPayResults::Init($response);
|
||||
self::reportCostTime($url, $startTimeStamp, $result);//上报请求花费时间
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载对账单,WxPayDownloadBill中bill_date为必填参数
|
||||
* appid、mchid、spbill_create_ip、nonce_str不需要填入
|
||||
* @param WxPayDownloadBill $inputObj
|
||||
* @param int $timeOut
|
||||
* @throws WxPayException
|
||||
* @return 成功时返回,其他抛异常
|
||||
*/
|
||||
public static function downloadBill($inputObj, $timeOut = 6)
|
||||
{
|
||||
$url = "https://api.mch.weixin.qq.com/pay/downloadbill";
|
||||
//检测必填参数
|
||||
if(!$inputObj->IsBill_dateSet()) {
|
||||
return dr_return_data(0, "对账单接口中,缺少必填参数bill_date!");
|
||||
}
|
||||
$inputObj->SetAppid(APPID);//公众账号ID
|
||||
$inputObj->SetMch_id(MCHID);//商户号
|
||||
$inputObj->SetNonce_str(self::getNonceStr());//随机字符串
|
||||
|
||||
$inputObj->SetSign();//签名
|
||||
$xml = $inputObj->ToXml();
|
||||
|
||||
$response = self::postXmlCurl($xml, $url, false, $timeOut);
|
||||
if(substr($response, 0 , 5) == "<xml>"){
|
||||
return "";
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交被扫支付API
|
||||
* 收银员使用扫码设备读取微信用户刷卡授权码以后,二维码或条码信息传送至商户收银台,
|
||||
* 由商户收银台或者商户后台调用该接口发起支付。
|
||||
* WxPayWxPayMicroPay中body、out_trade_no、total_fee、auth_code参数必填
|
||||
* appid、mchid、spbill_create_ip、nonce_str不需要填入
|
||||
* @param WxPayWxPayMicroPay $inputObj
|
||||
* @param int $timeOut
|
||||
*/
|
||||
public static function micropay($inputObj, $timeOut = 10)
|
||||
{
|
||||
$url = "https://api.mch.weixin.qq.com/pay/micropay";
|
||||
//检测必填参数
|
||||
if(!$inputObj->IsBodySet()) {
|
||||
return dr_return_data(0, "提交被扫支付API接口中,缺少必填参数body!");
|
||||
} else if(!$inputObj->IsOut_trade_noSet()) {
|
||||
return dr_return_data(0, "提交被扫支付API接口中,缺少必填参数out_trade_no!");
|
||||
} else if(!$inputObj->IsTotal_feeSet()) {
|
||||
return dr_return_data(0, "提交被扫支付API接口中,缺少必填参数total_fee!");
|
||||
} else if(!$inputObj->IsAuth_codeSet()) {
|
||||
return dr_return_data(0, "提交被扫支付API接口中,缺少必填参数auth_code!");
|
||||
}
|
||||
|
||||
$inputObj->SetSpbill_create_ip($_SERVER['REMOTE_ADDR']);//终端ip
|
||||
$inputObj->SetAppid(APPID);//公众账号ID
|
||||
$inputObj->SetMch_id(MCHID);//商户号
|
||||
$inputObj->SetNonce_str(self::getNonceStr());//随机字符串
|
||||
|
||||
$inputObj->SetSign();//签名
|
||||
$xml = $inputObj->ToXml();
|
||||
|
||||
$startTimeStamp = self::getMillisecond();//请求开始时间
|
||||
$response = self::postXmlCurl($xml, $url, false, $timeOut);
|
||||
$result = WxPayResults::Init($response);
|
||||
self::reportCostTime($url, $startTimeStamp, $result);//上报请求花费时间
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 撤销订单API接口,WxPayReverse中参数out_trade_no和transaction_id必须填写一个
|
||||
* appid、mchid、spbill_create_ip、nonce_str不需要填入
|
||||
* @param WxPayReverse $inputObj
|
||||
* @param int $timeOut
|
||||
* @throws WxPayException
|
||||
*/
|
||||
public static function reverse($inputObj, $timeOut = 6)
|
||||
{
|
||||
$url = "https://api.mch.weixin.qq.com/secapi/pay/reverse";
|
||||
//检测必填参数
|
||||
if(!$inputObj->IsOut_trade_noSet() && !$inputObj->IsTransaction_idSet()) {
|
||||
return dr_return_data(0, "撤销订单API接口中,参数out_trade_no和transaction_id必须填写一个!");
|
||||
}
|
||||
|
||||
$inputObj->SetAppid(APPID);//公众账号ID
|
||||
$inputObj->SetMch_id(MCHID);//商户号
|
||||
$inputObj->SetNonce_str(self::getNonceStr());//随机字符串
|
||||
|
||||
$inputObj->SetSign();//签名
|
||||
$xml = $inputObj->ToXml();
|
||||
|
||||
$startTimeStamp = self::getMillisecond();//请求开始时间
|
||||
$response = self::postXmlCurl($xml, $url, true, $timeOut);
|
||||
$result = WxPayResults::Init($response);
|
||||
self::reportCostTime($url, $startTimeStamp, $result);//上报请求花费时间
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 测速上报,该方法内部封装在report中,使用时请注意异常流程
|
||||
* WxPayReport中interface_url、return_code、result_code、user_ip、execute_time_必填
|
||||
* appid、mchid、spbill_create_ip、nonce_str不需要填入
|
||||
* @param WxPayReport $inputObj
|
||||
* @param int $timeOut
|
||||
* @throws WxPayException
|
||||
* @return 成功时返回,其他抛异常
|
||||
*/
|
||||
public static function report($inputObj, $timeOut = 1)
|
||||
{
|
||||
$url = "https://api.mch.weixin.qq.com/payitil/report";
|
||||
//检测必填参数
|
||||
if(!$inputObj->IsInterface_urlSet()) {
|
||||
return dr_return_data(0, "接口URL,缺少必填参数interface_url!");
|
||||
} if(!$inputObj->IsReturn_codeSet()) {
|
||||
return dr_return_data(0, "返回状态码,缺少必填参数return_code!");
|
||||
} if(!$inputObj->IsResult_codeSet()) {
|
||||
return dr_return_data(0, "业务结果,缺少必填参数result_code!");
|
||||
} if(!$inputObj->IsUser_ipSet()) {
|
||||
return dr_return_data(0, "访问接口IP,缺少必填参数user_ip!");
|
||||
} if(!$inputObj->IsExecute_time_Set()) {
|
||||
return dr_return_data(0, "接口耗时,缺少必填参数execute_time_!");
|
||||
}
|
||||
$inputObj->SetAppid(APPID);//公众账号ID
|
||||
$inputObj->SetMch_id(MCHID);//商户号
|
||||
$inputObj->SetUser_ip($_SERVER['REMOTE_ADDR']);//终端ip
|
||||
$inputObj->SetTime(date("YmdHis"));//商户上报时间
|
||||
$inputObj->SetNonce_str(self::getNonceStr());//随机字符串
|
||||
|
||||
$inputObj->SetSign();//签名
|
||||
$xml = $inputObj->ToXml();
|
||||
|
||||
$startTimeStamp = self::getMillisecond();//请求开始时间
|
||||
$response = self::postXmlCurl($xml, $url, false, $timeOut);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 生成二维码规则,模式一生成支付二维码
|
||||
* appid、mchid、spbill_create_ip、nonce_str不需要填入
|
||||
* @param WxPayBizPayUrl $inputObj
|
||||
* @param int $timeOut
|
||||
* @throws WxPayException
|
||||
* @return 成功时返回,其他抛异常
|
||||
*/
|
||||
public static function bizpayurl($inputObj, $timeOut = 6)
|
||||
{
|
||||
if(!$inputObj->IsProduct_idSet()){
|
||||
return dr_return_data(0, "生成二维码,缺少必填参数product_id!");
|
||||
}
|
||||
|
||||
$inputObj->SetAppid(APPID);//公众账号ID
|
||||
$inputObj->SetMch_id(MCHID);//商户号
|
||||
$inputObj->SetTime_stamp(time());//时间戳
|
||||
$inputObj->SetNonce_str(self::getNonceStr());//随机字符串
|
||||
|
||||
$inputObj->SetSign();//签名
|
||||
|
||||
return $inputObj->GetValues();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 转换短链接
|
||||
* 该接口主要用于扫码原生支付模式一中的二维码链接转成短链接(weixin://wxpay/s/XXXXXX),
|
||||
* 减小二维码数据量,提升扫描速度和精确度。
|
||||
* appid、mchid、spbill_create_ip、nonce_str不需要填入
|
||||
* @param WxPayShortUrl $inputObj
|
||||
* @param int $timeOut
|
||||
* @throws WxPayException
|
||||
* @return 成功时返回,其他抛异常
|
||||
*/
|
||||
public static function shorturl($inputObj, $timeOut = 6)
|
||||
{
|
||||
$url = "https://api.mch.weixin.qq.com/tools/shorturl";
|
||||
//检测必填参数
|
||||
if(!$inputObj->IsLong_urlSet()) {
|
||||
return dr_return_data(0, "需要转换的URL,签名用原串,传输需URL encode!");
|
||||
}
|
||||
$inputObj->SetAppid(APPID);//公众账号ID
|
||||
$inputObj->SetMch_id(MCHID);//商户号
|
||||
$inputObj->SetNonce_str(self::getNonceStr());//随机字符串
|
||||
|
||||
$inputObj->SetSign();//签名
|
||||
$xml = $inputObj->ToXml();
|
||||
|
||||
$startTimeStamp = self::getMillisecond();//请求开始时间
|
||||
$response = self::postXmlCurl($xml, $url, false, $timeOut);
|
||||
$result = WxPayResults::Init($response);
|
||||
self::reportCostTime($url, $startTimeStamp, $result);//上报请求花费时间
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 支付结果通用通知
|
||||
* @param function $callback
|
||||
* 直接回调函数使用方法: notify(you_function);
|
||||
* 回调类成员函数方法:notify(array($this, you_function));
|
||||
* $callback 原型为:function function_name($data){}
|
||||
*/
|
||||
public static function notify($callback, &$msg)
|
||||
{
|
||||
//获取通知的数据
|
||||
$xml = file_get_contents('php://input');
|
||||
//如果返回成功则验证签名
|
||||
try {
|
||||
$result = WxPayResults::Init($xml);
|
||||
} catch (WxPayException $e){
|
||||
$msg = $e->errorMessage();
|
||||
return false;
|
||||
}
|
||||
|
||||
return call_user_func($callback, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 产生随机字符串,不长于32位
|
||||
* @param int $length
|
||||
* @return 产生的随机字符串
|
||||
*/
|
||||
public static function getNonceStr($length = 32)
|
||||
{
|
||||
$chars = "abcdefghijklmnopqrstuvwxyz0123456789";
|
||||
$str ="";
|
||||
for ( $i = 0; $i < $length; $i++ ) {
|
||||
$str .= substr($chars, mt_rand(0, strlen($chars)-1), 1);
|
||||
}
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* 直接输出xml
|
||||
* @param string $xml
|
||||
*/
|
||||
public static function replyNotify($xml)
|
||||
{
|
||||
echo $xml;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 上报数据, 上报的时候将屏蔽所有异常流程
|
||||
* @param string $usrl
|
||||
* @param int $startTimeStamp
|
||||
* @param array $data
|
||||
*/
|
||||
private static function reportCostTime($url, $startTimeStamp, $data)
|
||||
{
|
||||
//如果不需要上报数据
|
||||
if(REPORT_LEVENL == 0){
|
||||
return;
|
||||
}
|
||||
//如果仅失败上报
|
||||
if(REPORT_LEVENL == 1 &&
|
||||
wx_array_key_exists("return_code", $data) &&
|
||||
$data["return_code"] == "SUCCESS" &&
|
||||
wx_array_key_exists("result_code", $data) &&
|
||||
$data["result_code"] == "SUCCESS")
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//上报逻辑
|
||||
$endTimeStamp = self::getMillisecond();
|
||||
$objInput = new WxPayReport();
|
||||
$objInput->SetInterface_url($url);
|
||||
$objInput->SetExecute_time_($endTimeStamp - $startTimeStamp);
|
||||
//返回状态码
|
||||
if(wx_array_key_exists("return_code", $data)){
|
||||
$objInput->SetReturn_code($data["return_code"]);
|
||||
}
|
||||
//返回信息
|
||||
if(wx_array_key_exists("return_msg", $data)){
|
||||
$objInput->SetReturn_msg($data["return_msg"]);
|
||||
}
|
||||
//业务结果
|
||||
if(wx_array_key_exists("result_code", $data)){
|
||||
$objInput->SetResult_code($data["result_code"]);
|
||||
}
|
||||
//错误代码
|
||||
if(wx_array_key_exists("err_code", $data)){
|
||||
$objInput->SetErr_code($data["err_code"]);
|
||||
}
|
||||
//错误代码描述
|
||||
if(wx_array_key_exists("err_code_des", $data)){
|
||||
$objInput->SetErr_code_des($data["err_code_des"]);
|
||||
}
|
||||
//商户订单号
|
||||
if(wx_array_key_exists("out_trade_no", $data)){
|
||||
$objInput->SetOut_trade_no($data["out_trade_no"]);
|
||||
}
|
||||
//设备号
|
||||
if(wx_array_key_exists("device_info", $data)){
|
||||
$objInput->SetDevice_info($data["device_info"]);
|
||||
}
|
||||
|
||||
try{
|
||||
self::report($objInput);
|
||||
} catch (WxPayException $e){
|
||||
//不做任何处理
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 以post方式提交xml到对应的接口url
|
||||
*
|
||||
* @param string $xml 需要post的xml数据
|
||||
* @param string $url url
|
||||
* @param bool $useCert 是否需要证书,默认不需要
|
||||
* @param int $second url执行超时时间,默认30s
|
||||
* @throws WxPayException
|
||||
*/
|
||||
private static function postXmlCurl($xml, $url, $useCert = false, $second = 30)
|
||||
{
|
||||
$ch = curl_init();
|
||||
//设置超时
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, $second);
|
||||
|
||||
/*
|
||||
//如果有配置代理这里就设置代理
|
||||
if(CURL_PROXY_HOST != "0.0.0.0"
|
||||
&& CURL_PROXY_PORT != 0){
|
||||
curl_setopt($ch,CURLOPT_PROXY, CURL_PROXY_HOST);
|
||||
curl_setopt($ch,CURLOPT_PROXYPORT, CURL_PROXY_PORT);
|
||||
}*/
|
||||
|
||||
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);
|
||||
|
||||
if($useCert == true){
|
||||
//设置证书
|
||||
//使用证书:cert 与 key 分别属于两个.pem文件
|
||||
curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
|
||||
curl_setopt($ch,CURLOPT_SSLCERT, SSLCERT_PATH);
|
||||
curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
|
||||
curl_setopt($ch,CURLOPT_SSLKEY, SSLKEY_PATH);
|
||||
}
|
||||
//post提交方式
|
||||
curl_setopt($ch, CURLOPT_POST, TRUE);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
|
||||
//运行curl
|
||||
$data = curl_exec($ch);
|
||||
//返回结果
|
||||
if($data){
|
||||
curl_close($ch);
|
||||
return $data;
|
||||
} else {
|
||||
$error = curl_errno($ch);
|
||||
curl_close($ch);
|
||||
return dr_return_data(0, "curl出错,错误码:$error");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取毫秒级别的时间戳
|
||||
*/
|
||||
private static function getMillisecond()
|
||||
{
|
||||
//获取毫秒的时间戳
|
||||
$time = explode ( " ", microtime () );
|
||||
$time = $time[1] . ($time[0] * 1000);
|
||||
$time2 = explode( ".", $time );
|
||||
$time = $time2[0];
|
||||
return $time;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,213 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
*
|
||||
* JSAPI支付实现类
|
||||
* 该类实现了从微信公众平台获取code、通过code获取openid和access_token、
|
||||
* 生成jsapi支付js接口所需的参数、生成获取共享收货地址所需的参数
|
||||
*
|
||||
* 该类是微信支付提供的样例程序,商户可根据自己的需求修改,或者使用lib中的api自行开发
|
||||
*
|
||||
* @author widy
|
||||
*
|
||||
*/
|
||||
class JsApiPay
|
||||
{
|
||||
/**
|
||||
*
|
||||
* 网页授权接口微信服务器返回的数据,返回样例如下
|
||||
* {
|
||||
* "access_token":"ACCESS_TOKEN",
|
||||
* "expires_in":7200,
|
||||
* "refresh_token":"REFRESH_TOKEN",
|
||||
* "openid":"OPENID",
|
||||
* "scope":"SCOPE",
|
||||
* "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
|
||||
* }
|
||||
* 其中access_token可用于获取共享收货地址
|
||||
* openid是微信支付jsapi支付接口必须的参数
|
||||
* @var array
|
||||
*/
|
||||
public $data = null;
|
||||
|
||||
/**
|
||||
*
|
||||
* 通过跳转获取用户的openid,跳转流程如下:
|
||||
* 1、设置自己需要调回的url及其其他参数,跳转到微信服务器https://open.weixin.qq.com/connect/oauth2/authorize
|
||||
* 2、微信服务处理完成之后会跳转回用户redirect_uri地址,此时会带上一些参数,如:code
|
||||
*
|
||||
* @return 用户的openid
|
||||
*/
|
||||
public function GetOpenid()
|
||||
{
|
||||
//通过code获得openid
|
||||
if (!isset($_GET['code'])){
|
||||
//触发微信返回code码
|
||||
$baseUrl = urlencode((defined('SYS_HTTPS') && SYS_HTTPS ? 'https://' : 'http://').$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'].$_SERVER['QUERY_STRING']);
|
||||
$url = $this->__CreateOauthUrlForCode($baseUrl);
|
||||
Header("Location: $url");
|
||||
exit();
|
||||
} else {
|
||||
//获取code码,以获取openid
|
||||
$code = $_GET['code'];
|
||||
$openid = $this->getOpenidFromMp($code);
|
||||
return $openid;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 获取jsapi支付的参数
|
||||
* @param array $UnifiedOrderResult 统一支付接口返回的数据
|
||||
* @throws WxPayException
|
||||
*
|
||||
* @return json数据,可直接填入js函数作为参数
|
||||
*/
|
||||
public function GetJsApiParameters($UnifiedOrderResult)
|
||||
{
|
||||
if(!wx_array_key_exists("appid", $UnifiedOrderResult)
|
||||
|| !wx_array_key_exists("prepay_id", $UnifiedOrderResult)
|
||||
|| $UnifiedOrderResult['prepay_id'] == "")
|
||||
{
|
||||
return dr_return_data(0, "参数错误");
|
||||
}
|
||||
$jsapi = new WxPayJsApiPay();
|
||||
$jsapi->SetAppid($UnifiedOrderResult["appid"]);
|
||||
$timeStamp = time();
|
||||
$jsapi->SetTimeStamp("$timeStamp");
|
||||
$jsapi->SetNonceStr(WxPayApi::getNonceStr());
|
||||
$jsapi->SetPackage("prepay_id=" . $UnifiedOrderResult['prepay_id']);
|
||||
$jsapi->SetSignType("MD5");
|
||||
$jsapi->SetPaySign($jsapi->MakeSign());
|
||||
$parameters = json_encode($jsapi->GetValues());
|
||||
return $parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 通过code从工作平台获取openid机器access_token
|
||||
* @param string $code 微信跳转回来带上的code
|
||||
*
|
||||
* @return openid
|
||||
*/
|
||||
public function GetOpenidFromMp($code)
|
||||
{
|
||||
$url = $this->__CreateOauthUrlForOpenid($code);
|
||||
//初始化curl
|
||||
$ch = curl_init();
|
||||
//设置超时
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, $this->curl_timeout);
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,FALSE);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,FALSE);
|
||||
curl_setopt($ch, CURLOPT_HEADER, FALSE);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
|
||||
/*
|
||||
if(CURL_PROXY_HOST != "0.0.0.0"
|
||||
&& CURL_PROXY_PORT != 0){
|
||||
curl_setopt($ch,CURLOPT_PROXY, CURL_PROXY_HOST);
|
||||
curl_setopt($ch,CURLOPT_PROXYPORT, CURL_PROXY_PORT);
|
||||
}*/
|
||||
//运行curl,结果以jason形式返回
|
||||
$res = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
//取出openid
|
||||
$data = json_decode($res,true);
|
||||
$this->data = $data;
|
||||
if (!$data) {
|
||||
exit($res.' 不是一个有效的json数据');
|
||||
} elseif (isset($data['errcode']) && $data['errcode']) {
|
||||
exit('错误代码('.$data['errcode'].'):'.$data['errmsg']);
|
||||
}
|
||||
$openid = $data['openid'];
|
||||
return $openid;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 拼接签名字符串
|
||||
* @param array $urlObj
|
||||
*
|
||||
* @return 返回已经拼接好的字符串
|
||||
*/
|
||||
private function ToUrlParams($urlObj)
|
||||
{
|
||||
$buff = "";
|
||||
foreach ($urlObj as $k => $v)
|
||||
{
|
||||
if($k != "sign"){
|
||||
$buff .= $k . "=" . $v . "&";
|
||||
}
|
||||
}
|
||||
|
||||
$buff = trim($buff, "&");
|
||||
return $buff;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 获取地址js参数
|
||||
*
|
||||
* @return 获取共享收货地址js函数需要的参数,json格式可以直接做参数使用
|
||||
*/
|
||||
public function GetEditAddressParameters()
|
||||
{
|
||||
$getData = $this->data;
|
||||
$data = array();
|
||||
$data["appid"] = APPID;
|
||||
$data["url"] = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
|
||||
$time = time();
|
||||
$data["timestamp"] = "$time";
|
||||
$data["noncestr"] = "1234568";
|
||||
$data["accesstoken"] = $getData["access_token"];
|
||||
ksort($data);
|
||||
$params = $this->ToUrlParams($data);
|
||||
$addrSign = sha1($params);
|
||||
|
||||
$afterData = array(
|
||||
"addrSign" => $addrSign,
|
||||
"signType" => "sha1",
|
||||
"scope" => "jsapi_address",
|
||||
"appId" => APPID,
|
||||
"timeStamp" => $data["timestamp"],
|
||||
"nonceStr" => $data["noncestr"]
|
||||
);
|
||||
$parameters = json_encode($afterData);
|
||||
return $parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 构造获取code的url连接
|
||||
* @param string $redirectUrl 微信服务器回跳的url,需要url编码
|
||||
*
|
||||
* @return 返回构造好的url
|
||||
*/
|
||||
private function __CreateOauthUrlForCode($redirectUrl)
|
||||
{
|
||||
$urlObj["appid"] = APPID;
|
||||
$urlObj["redirect_uri"] = "$redirectUrl";
|
||||
$urlObj["response_type"] = "code";
|
||||
$urlObj["scope"] = "snsapi_base";
|
||||
$urlObj["state"] = "STATE"."#wechat_redirect";
|
||||
$bizString = $this->ToUrlParams($urlObj);
|
||||
return "https://open.weixin.qq.com/connect/oauth2/authorize?".$bizString;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 构造获取open和access_toke的url地址
|
||||
* @param string $code,微信跳转带回的code
|
||||
*
|
||||
* @return 请求的url
|
||||
*/
|
||||
private function __CreateOauthUrlForOpenid($code)
|
||||
{
|
||||
$urlObj["appid"] = APPID;
|
||||
$urlObj["secret"] = APPSECRET;
|
||||
$urlObj["code"] = $code;
|
||||
$urlObj["grant_type"] = "authorization_code";
|
||||
$bizString = $this->ToUrlParams($urlObj);
|
||||
return "https://api.weixin.qq.com/sns/oauth2/access_token?".$bizString;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* 刷卡支付实现类
|
||||
* @author widyhu
|
||||
*
|
||||
*/
|
||||
class NativePay
|
||||
{
|
||||
/**
|
||||
*
|
||||
* 生成扫描支付URL,模式一
|
||||
* @param BizPayUrlInput $bizUrlInfo
|
||||
*/
|
||||
public function GetPrePayUrl($productId)
|
||||
{
|
||||
$biz = new WxPayBizPayUrl();
|
||||
$biz->SetProduct_id($productId);
|
||||
$values = WxpayApi::bizpayurl($biz);
|
||||
$url = "weixin://wxpay/bizpayurl?" . $this->ToUrlParams($values);
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 参数数组转换为url参数
|
||||
* @param array $urlObj
|
||||
*/
|
||||
private function ToUrlParams($urlObj)
|
||||
{
|
||||
$buff = "";
|
||||
foreach ($urlObj as $k => $v)
|
||||
{
|
||||
$buff .= $k . "=" . $v . "&";
|
||||
}
|
||||
|
||||
$buff = trim($buff, "&");
|
||||
return $buff;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 生成直接支付url,支付url有效期为2小时,模式二
|
||||
* @param UnifiedOrderInput $input
|
||||
*/
|
||||
public function GetPayUrl($input)
|
||||
{
|
||||
if($input->GetTrade_type() == "NATIVE")
|
||||
{
|
||||
$result = WxPayApi::unifiedOrder($input);
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* 回调基础类
|
||||
* @author widyhu
|
||||
*
|
||||
*/
|
||||
class WxPayNotify extends WxPayNotifyReply
|
||||
{
|
||||
/**
|
||||
*
|
||||
* 回调入口
|
||||
* @param bool $needSign 是否需要签名输出
|
||||
*/
|
||||
final public function Handle($needSign = true)
|
||||
{
|
||||
$msg = "OK";
|
||||
//当返回false的时候,表示notify中调用NotifyCallBack回调失败获取签名校验失败,此时直接回复失败
|
||||
$result = WxpayApi::notify(array($this, 'NotifyCallBack'), $msg);
|
||||
if($result == false){
|
||||
$this->SetReturn_code("FAIL");
|
||||
$this->SetReturn_msg($msg);
|
||||
$this->ReplyNotify(false);
|
||||
return;
|
||||
} else {
|
||||
//该分支在成功回调到NotifyCallBack方法,处理完成之后流程
|
||||
$this->SetReturn_code("SUCCESS");
|
||||
$this->SetReturn_msg("OK");
|
||||
}
|
||||
$this->ReplyNotify($needSign);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 回调方法入口,子类可重写该方法
|
||||
* 注意:
|
||||
* 1、微信回调超时时间为2s,建议用户使用异步处理流程,确认成功之后立刻回复微信服务器
|
||||
* 2、微信服务器在调用失败或者接到回包为非确认包的时候,会发起重试,需确保你的回调是可以重入
|
||||
* @param array $data 回调解释出的参数
|
||||
* @param string $msg 如果回调处理失败,可以将错误信息输出到该方法
|
||||
* @return true回调出来完成不需要继续回调,false回调处理未完成需要继续回调
|
||||
*/
|
||||
public function NotifyProcess($data, &$msg)
|
||||
{
|
||||
//TODO 用户基础该类之后需要重写该方法,成功的时候返回true,失败返回false
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* notify回调方法,该方法中需要赋值需要输出的参数,不可重写
|
||||
* @param array $data
|
||||
* @return true回调出来完成不需要继续回调,false回调处理未完成需要继续回调
|
||||
*/
|
||||
final public function NotifyCallBack($data)
|
||||
{
|
||||
$msg = "OK";
|
||||
$result = $this->NotifyProcess($data, $msg);
|
||||
|
||||
if($result == true){
|
||||
$this->SetReturn_code("SUCCESS");
|
||||
$this->SetReturn_msg("OK");
|
||||
} else {
|
||||
$this->SetReturn_code("FAIL");
|
||||
$this->SetReturn_msg($msg);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 回复通知
|
||||
* @param bool $needSign 是否需要签名输出
|
||||
*/
|
||||
final public function ReplyNotify($needSign = true)
|
||||
{
|
||||
//如果需要签名
|
||||
if($needSign == true &&
|
||||
$this->GetReturn_code($return_code) == "SUCCESS")
|
||||
{
|
||||
$this->SetSign();
|
||||
}
|
||||
WxpayApi::replyNotify($this->ToXml());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* 支付接口配置
|
||||
*/
|
||||
|
||||
return [
|
||||
|
||||
'name' => '微信',
|
||||
'icon' => '<i class="fa fa-weixin"></i>',
|
||||
|
||||
];
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* 微信支付回调接口
|
||||
*/
|
||||
|
||||
define('APPID', $config['appid']);
|
||||
define('MCHID', $config['mchid']);
|
||||
define('KEY', $config['key']);
|
||||
define('APPSECRET', $config['appsecret']);
|
||||
define('REPORT_LEVENL', 0);
|
||||
|
||||
require "WxPay.Data.php";
|
||||
require "WxPay.Api.php";
|
||||
require "WxPay.Notify.php";
|
||||
|
||||
|
||||
class PayNotifyCallBack extends WxPayNotify
|
||||
{
|
||||
|
||||
|
||||
//查询订单
|
||||
public function Queryorder($transaction_id)
|
||||
{
|
||||
$input = new WxPayOrderQuery();
|
||||
$input->SetTransaction_id($transaction_id);
|
||||
$result = WxPayApi::orderQuery($input);
|
||||
if(wx_array_key_exists("return_code", $result)
|
||||
&& wx_array_key_exists("result_code", $result)
|
||||
&& $result["return_code"] == "SUCCESS"
|
||||
&& $result["result_code"] == "SUCCESS")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//重写回调处理函数
|
||||
public function NotifyProcess($data, &$msg)
|
||||
{
|
||||
$notfiyOutput = array();
|
||||
|
||||
if(!wx_array_key_exists("transaction_id", $data)){
|
||||
$msg = "输入参数不正确";
|
||||
return false;
|
||||
}
|
||||
|
||||
//查询订单,判断订单真实性
|
||||
if(!$this->Queryorder($data["transaction_id"])){
|
||||
$msg = "订单查询失败";
|
||||
return false;
|
||||
}
|
||||
|
||||
// 处理支付表状态
|
||||
$rt = \Phpcmf\Service::M('Pay', 'pay')->paysuccess($data['out_trade_no'], $data["transaction_id"]);
|
||||
//file_put_contents(WEBPATH."wx.txt", var_export($data, true));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
$notify = new PayNotifyCallBack();
|
||||
$notify->Handle(false);
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* 微信支付ajax实时监测状态接口
|
||||
* $result // 支付记录表的回调详情
|
||||
*/
|
||||
|
||||
define('APPID', $config['appid']);
|
||||
define('MCHID', $config['mchid']);
|
||||
define('KEY', $config['key']);
|
||||
define('APPSECRET', $config['appsecret']);
|
||||
define('REPORT_LEVENL', 0);
|
||||
|
||||
require "WxPay.Data.php";
|
||||
require "WxPay.Api.php";
|
||||
require "WxPay.Notify.php";
|
||||
|
||||
$sn = \Phpcmf\Service::C()->member_cache['pay']['prefix'].date('YmdHis', $data['inputtime']).'-'.$data['id'];
|
||||
$input = new WxPayOrderQuery();
|
||||
$input->SetOut_trade_no($sn);
|
||||
$rt = WxPayApi::orderQuery($input);
|
||||
|
||||
// 判断支付成功
|
||||
if ($rt['result_code'] == 'SUCCESS' && $rt['return_code'] == 'SUCCESS' && $rt['trade_state'] == 'SUCCESS') {
|
||||
$rt = \Phpcmf\Service::M('Pay', 'pay')->paysuccess($rt['out_trade_no'], $rt["transaction_id"]);
|
||||
$return = ['code' => 1, 'msg' => 'ok'];
|
||||
} elseif ($rt['return_code'] == 'FAIL') {
|
||||
$return = ['code' => 0, 'msg' => $rt['return_msg']];
|
||||
} elseif (isset($rt['code']) && $rt['code'] == 0) {
|
||||
$return = ['code' => 0, 'msg' => $rt['msg']];
|
||||
} else {
|
||||
$return = ['code' => 0, 'msg' => dr_lang('未付款')];
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* 支付回调接口URL
|
||||
*/
|
||||
|
||||
define('IS_API', 'pay'); // 项目标识
|
||||
define('SELF', pathinfo(__FILE__, PATHINFO_BASENAME)); // 该文件的名称
|
||||
require('../../../index.php'); // 引入主文件
|
||||
@@ -0,0 +1,240 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* 微信支付发起接口
|
||||
*/
|
||||
|
||||
if (IS_API_HTTP) {
|
||||
define('APPID', \Phpcmf\Service::C()->get_cache('weixin', 'xcx', 'appid'));
|
||||
define('APPSECRET', \Phpcmf\Service::C()->get_cache('weixin', 'xcx', 'appsecret'));
|
||||
} else {
|
||||
define('APPID', $config['appid']);
|
||||
define('APPSECRET', $config['appsecret']);
|
||||
}
|
||||
|
||||
define('MCHID', $config['mchid']);
|
||||
define('KEY', $config['key']);
|
||||
define('NOTIFY_URL', ROOT_URL."api/pay/".$data['type']."/notify_url.php");
|
||||
define('NOTIFY_API_URL', ROOT_URL."index.php?s=pay&m=ajax&id=".$id);
|
||||
define('REPORT_LEVENL', 0);
|
||||
|
||||
require "WxPay.Data.php";
|
||||
require "WxPay.Api.php";
|
||||
require "WxPay.JsApiPay.php";
|
||||
require "WxPay.NativePay.php";
|
||||
|
||||
// 当前已经登录的用户
|
||||
$member = \Phpcmf\Service::C()->member;
|
||||
// 付款界面模板
|
||||
$htmlfile = is_file(WEBPATH.'config/pay/payweixin.html') ? WEBPATH.'config/pay/payweixin.html' : CONFIGPATH.'pay/payweixin.html';
|
||||
$data['title'] = dr_strcut($data['title'], 30);
|
||||
if (IS_API_HTTP && dr_is_app('weixin')) {
|
||||
// 微信插件:客户端小程序请求
|
||||
//①、获取用户openid
|
||||
$oauth = $this->table('member_oauth')->where('uid', $data['uid'])->where('oauth', 'wxxcx')->getRow();
|
||||
if (!$oauth) {
|
||||
$return = dr_return_data(0, '服务器没有此用户');
|
||||
} else {
|
||||
$input = new WxPayUnifiedOrder();
|
||||
$input->SetBody($data['title']);
|
||||
$input->SetOut_trade_no($sn);
|
||||
$input->SetTotal_fee($data['value'] * 100); // 金额
|
||||
$input->SetTime_start(date("YmdHis", SYS_TIME));
|
||||
$input->SetTime_expire(date("YmdHis", SYS_TIME + 7200));
|
||||
$input->SetNotify_url(NOTIFY_URL);
|
||||
$input->SetTrade_type("JSAPI"); // JSAPI,NATIVE,APP
|
||||
$input->SetProduct_id($pid);
|
||||
$input->SetOpenid($oauth['oid']);
|
||||
$order = WxPayApi::unifiedOrder($input);
|
||||
if (isset($order['code']) && $order['code'] == 0) {
|
||||
$return = dr_return_data(0, '微信服务端:'.$order['msg']);
|
||||
} elseif ($order["err_code_des"]) {
|
||||
$return = dr_return_data(0, '微信服务端:'.$order['err_code_des']);
|
||||
} else {
|
||||
// 存储支付结果
|
||||
$order['sn'] = $sn;
|
||||
$tools = new JsApiPay();
|
||||
$param = $tools->GetJsApiParameters($order);
|
||||
\Phpcmf\Service::C()->_json(1, 'ok', json_decode($param, true));
|
||||
}
|
||||
}
|
||||
} elseif (dr_is_weixin_app()) {
|
||||
// 手机微信客户端调用jsapi
|
||||
//①、获取用户openid
|
||||
$tools = new JsApiPay();
|
||||
$openId = $tools->GetOpenid();
|
||||
if (!$openId) {
|
||||
$return = dr_return_data(0, 'openId获取失败');
|
||||
} else {
|
||||
// 统一下单
|
||||
$input = new WxPayUnifiedOrder();
|
||||
$input->SetBody($data['title']);
|
||||
$input->SetOut_trade_no($sn);
|
||||
$input->SetTotal_fee($data['value'] * 100); // 金额
|
||||
$input->SetTime_start(date("YmdHis", SYS_TIME));
|
||||
$input->SetTime_expire(date("YmdHis", SYS_TIME + 7200));
|
||||
$input->SetNotify_url(NOTIFY_URL);
|
||||
$input->SetTrade_type("JSAPI"); // JSAPI,NATIVE,APP
|
||||
$input->SetProduct_id($pid);
|
||||
$input->SetOpenid($openId);
|
||||
$order = WxPayApi::unifiedOrder($input);
|
||||
if (isset($order['code']) && $order['code'] == 0) {
|
||||
$return = dr_return_data(0, '微信服务端:'.$order['msg']);
|
||||
} elseif ($order["err_code_des"]) {
|
||||
$return = dr_return_data(0, '微信服务端:'.$order['err_code_des']);
|
||||
} else {
|
||||
$jsApiParameters = $tools->GetJsApiParameters($order);
|
||||
//获取共享收货地址js函数参数
|
||||
$editAddress = $tools->GetEditAddressParameters();
|
||||
// 存储支付结果
|
||||
$order['sn'] = $sn;
|
||||
$code = '
|
||||
<script type="text/javascript">
|
||||
//调用微信JS api 支付
|
||||
function jsApiCall()
|
||||
{
|
||||
WeixinJSBridge.invoke(
|
||||
\'getBrandWCPayRequest\',
|
||||
' . $jsApiParameters . ',
|
||||
function(res){
|
||||
if (res.err_msg == "get_brand_wcpay_request:ok") {
|
||||
// 付款成功
|
||||
window.location.href = "'.PAY_URL.'index.php?s=pay&m=call&id='.$id.'";
|
||||
} else if (res.err_msg == "get_brand_wcpay_request:cancel") {
|
||||
dr_tips(0, "'.dr_lang('付款取消').'");
|
||||
} else {
|
||||
dr_tips(0, "'.dr_lang('服务端错误: ').'"+res.err_msg);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function callpay()
|
||||
{
|
||||
if (typeof WeixinJSBridge == "undefined"){
|
||||
if( document.addEventListener ){
|
||||
document.addEventListener(\'WeixinJSBridgeReady\', jsApiCall, false);
|
||||
}else if (document.attachEvent){
|
||||
document.attachEvent(\'WeixinJSBridgeReady\', jsApiCall);
|
||||
document.attachEvent(\'onWeixinJSBridgeReady\', jsApiCall);
|
||||
}
|
||||
}else{
|
||||
jsApiCall();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<button class="fc-weixin-pay" type="button" onclick="callpay()" >立即支付</button>
|
||||
';
|
||||
|
||||
// 获取付款界面代码
|
||||
ob_start();
|
||||
$file = \Phpcmf\Service::V()->code2php(file_get_contents($htmlfile));
|
||||
require_once $file;
|
||||
$html = ob_get_clean();
|
||||
$return = dr_return_data(1, 'ok', $html);
|
||||
}
|
||||
}
|
||||
} elseif (\Phpcmf\Service::IS_MOBILE_USER()) {
|
||||
// 手机端H5支付
|
||||
$input = new WxPayUnifiedOrder();
|
||||
$input->SetBody($data['title']);
|
||||
$input->SetOut_trade_no($sn);
|
||||
$input->SetTotal_fee($data['value'] * 100); // 金额
|
||||
$input->SetTime_start(date("YmdHis", SYS_TIME));
|
||||
$input->SetTime_expire(date("YmdHis", SYS_TIME + 7200));
|
||||
$input->SetNotify_url(NOTIFY_URL);
|
||||
$input->SetTrade_type("MWEB"); // JSAPI,NATIVE,APP
|
||||
$input->SetProduct_id($pid);
|
||||
$input->SetOpenid($openId);
|
||||
$order = WxPayApi::unifiedOrder($input);
|
||||
|
||||
if (isset($order['code']) && $order['code'] == 0) {
|
||||
$return = dr_return_data(0, '微信服务端:'.$order['msg']);
|
||||
} elseif ($order["err_code_des"]) {
|
||||
$return = dr_return_data(0, '微信服务端:'.$order['err_code_des']);
|
||||
} else {
|
||||
|
||||
// 存储支付结果
|
||||
$order['sn'] = $sn;
|
||||
$code = '
|
||||
<a class="fc-weixin-pay" style="padding-top:10px;" href="'.$order['mweb_url'].'" >立即支付</a>
|
||||
<script>
|
||||
function dr_weixin_notify() {
|
||||
$.ajax({
|
||||
type : "post",
|
||||
url : "'.NOTIFY_API_URL.'",
|
||||
dataType : "jsonp",
|
||||
jsonp: "callback",
|
||||
jsonpCallback:"success_jsonpCallback",
|
||||
success : function(html){
|
||||
if (html.code == 1) {
|
||||
window.location.href = "'.ROOT_URL.'index.php?s=pay&m=call&id='.$id.'";
|
||||
}
|
||||
},
|
||||
error:function(){ }
|
||||
});
|
||||
}
|
||||
$(function(){
|
||||
setInterval(\'dr_weixin_notify()\', 1000);
|
||||
});
|
||||
</script>';
|
||||
|
||||
// 获取付款界面代码
|
||||
ob_start();
|
||||
$file = \Phpcmf\Service::V()->code2php(file_get_contents($htmlfile));
|
||||
require_once $file;
|
||||
$html = ob_get_clean();
|
||||
$return = dr_return_data(1, 'ok', $html);
|
||||
}
|
||||
|
||||
} else {
|
||||
// 电脑扫码支付
|
||||
$notify = new NativePay();
|
||||
// 统一下单
|
||||
$input = new WxPayUnifiedOrder();
|
||||
$input->SetBody($data['title']);
|
||||
$input->SetOut_trade_no($sn);
|
||||
$input->SetTotal_fee($data['value'] * 100); // 金额
|
||||
$input->SetTime_start(date("YmdHis", SYS_TIME));
|
||||
$input->SetTime_expire(date("YmdHis", SYS_TIME + 7200));
|
||||
$input->SetNotify_url(NOTIFY_URL);
|
||||
$input->SetTrade_type("NATIVE"); // JSAPI,NATIVE,APP
|
||||
$input->SetProduct_id($pid);
|
||||
$result = $notify->GetPayUrl($input);
|
||||
if (isset($result['code']) && $result['code'] == 0) {
|
||||
$return = dr_return_data(0, '微信服务端:'.$result['msg']);
|
||||
} elseif ($result["err_code_des"]) {
|
||||
$return = dr_return_data(0, '微信服务端:'.$result['err_code_des']);
|
||||
} else {
|
||||
// 存储支付结果
|
||||
$result['sn'] = $sn;
|
||||
$code = '
|
||||
<img class="wxpay" src="'.dr_qrcode($result["code_url"]).'"/>
|
||||
<script>
|
||||
function dr_weixin_notify() {
|
||||
$.ajax({
|
||||
type : "post",
|
||||
url : "'.NOTIFY_API_URL.'",
|
||||
dataType : "jsonp",
|
||||
jsonp: "callback",
|
||||
jsonpCallback:"success_jsonpCallback",
|
||||
success : function(html){
|
||||
if (html.code == 1) {
|
||||
window.location.href = "'.PAY_URL.'index.php?s=pay&m=call&id='.$id.'";
|
||||
}
|
||||
},
|
||||
error:function(){ }
|
||||
});
|
||||
}
|
||||
$(function(){
|
||||
setInterval(\'dr_weixin_notify()\', 1000);
|
||||
});
|
||||
</script>';
|
||||
// 获取付款界面代码
|
||||
ob_start();
|
||||
$file = \Phpcmf\Service::V()->code2php(file_get_contents($htmlfile));
|
||||
require_once $file;
|
||||
$html = ob_get_clean();
|
||||
$return = dr_return_data(1, 'ok', $html);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* 微信退款接口
|
||||
* 由 Pay::payrefund() require 调用
|
||||
*
|
||||
* 可用变量:$data 流水记录,$config 接口配置,$money 退款金额
|
||||
* 须设置:$return = dr_return_data(...)
|
||||
*
|
||||
* 注意:退款需商户号配置 API 证书(apiclient_cert.pem / apiclient_key.pem)
|
||||
*/
|
||||
|
||||
$money = abs(isset($money) ? $money : $data['value']);
|
||||
$transaction_id = trim((string)$data['result']); // 支付成功时写入的微信交易号
|
||||
$out_trade_no = trim((string)\Phpcmf\Service::C()->member_cache['pay']['prefix'])
|
||||
. date('YmdHis', (int)$data['inputtime']) . '00' . $data['id'];
|
||||
$out_refund_no = 'RF' . $data['id'] . date('YmdHis');
|
||||
$total_fee = (int)round($money * 100);
|
||||
$refund_fee = $total_fee;
|
||||
|
||||
if (!$config || empty($config['appid']) || empty($config['mchid']) || empty($config['key'])) {
|
||||
$return = dr_return_data(0, dr_lang('微信退款配置不完整'));
|
||||
} elseif (!$transaction_id && !$out_trade_no) {
|
||||
$return = dr_return_data(0, dr_lang('缺少微信交易号,无法退款'));
|
||||
} else {
|
||||
|
||||
// API 证书路径(退款必填),默认放在 weixin 目录下
|
||||
$cert = dirname(__FILE__) . '/cert/apiclient_cert.pem';
|
||||
$key = dirname(__FILE__) . '/cert/apiclient_key.pem';
|
||||
if (!empty($config['sslcert_path'])) {
|
||||
$cert = $config['sslcert_path'];
|
||||
}
|
||||
if (!empty($config['sslkey_path'])) {
|
||||
$key = $config['sslkey_path'];
|
||||
}
|
||||
if (!is_file($cert) || !is_file($key)) {
|
||||
$return = dr_return_data(0, dr_lang('微信退款证书未配置(请放置 apiclient_cert.pem / apiclient_key.pem)'));
|
||||
} else {
|
||||
if (!defined('APPID')) {
|
||||
define('APPID', $config['appid']);
|
||||
}
|
||||
if (!defined('APPSECRET')) {
|
||||
define('APPSECRET', isset($config['appsecret']) ? $config['appsecret'] : '');
|
||||
}
|
||||
if (!defined('MCHID')) {
|
||||
define('MCHID', $config['mchid']);
|
||||
}
|
||||
if (!defined('KEY')) {
|
||||
define('KEY', $config['key']);
|
||||
}
|
||||
if (!defined('NOTIFY_URL')) {
|
||||
define('NOTIFY_URL', ROOT_URL . 'api/pay/' . $data['type'] . '/notify_url.php');
|
||||
}
|
||||
if (!defined('REPORT_LEVENL')) {
|
||||
define('REPORT_LEVENL', 0);
|
||||
}
|
||||
if (!defined('SSLCERT_PATH')) {
|
||||
define('SSLCERT_PATH', $cert);
|
||||
}
|
||||
if (!defined('SSLKEY_PATH')) {
|
||||
define('SSLKEY_PATH', $key);
|
||||
}
|
||||
|
||||
require_once dirname(__FILE__) . '/WxPay.Data.php';
|
||||
require_once dirname(__FILE__) . '/WxPay.Api.php';
|
||||
|
||||
$input = new WxPayRefund();
|
||||
if ($transaction_id) {
|
||||
$input->SetTransaction_id($transaction_id);
|
||||
} else {
|
||||
$input->SetOut_trade_no($out_trade_no);
|
||||
}
|
||||
$input->SetTotal_fee($total_fee);
|
||||
$input->SetRefund_fee($refund_fee);
|
||||
$input->SetOut_refund_no($out_refund_no);
|
||||
$input->SetOp_user_id(MCHID);
|
||||
|
||||
$result = WxPayApi::refund($input);
|
||||
if (isset($result['code']) && (int)$result['code'] === 0) {
|
||||
$return = $result;
|
||||
} elseif (isset($result['return_code']) && $result['return_code'] == 'SUCCESS'
|
||||
&& isset($result['result_code']) && $result['result_code'] == 'SUCCESS') {
|
||||
$return = dr_return_data(1, dr_lang('退款成功'), $result);
|
||||
} else {
|
||||
$msg = isset($result['err_code_des']) && $result['err_code_des']
|
||||
? $result['err_code_des']
|
||||
: (isset($result['return_msg']) ? $result['return_msg'] : dr_lang('微信退款失败'));
|
||||
if (isset($result['msg']) && $result['msg']) {
|
||||
$msg = $result['msg'];
|
||||
}
|
||||
$return = dr_return_data(0, $msg, is_array($result) ? $result : []);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
|
||||
$weixin_cert_dir = ROOTPATH.'api/pay/weixin/cert/';
|
||||
$weixin_cert_default = $weixin_cert_dir.'apiclient_cert.pem';
|
||||
$weixin_key_default = $weixin_cert_dir.'apiclient_key.pem';
|
||||
?>
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">AppId</label>
|
||||
<div class="col-md-9">
|
||||
<input type="text" class="form-control input-large" name="data[<?php echo $dir;?>][appid]" value="<?php echo $data[$dir]['appid']?>" >
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">AppSecret</label>
|
||||
<div class="col-md-9">
|
||||
<input type="text" class="form-control input-large" name="data[<?php echo $dir;?>][appsecret]" value="<?php echo $data[$dir]['appsecret']?>" >
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">MCHID</label>
|
||||
<div class="col-md-9">
|
||||
<input type="text" class="form-control input-large" name="data[<?php echo $dir;?>][mchid]" value="<?php echo $data[$dir]['mchid']?>" >
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">KEY</label>
|
||||
<div class="col-md-9">
|
||||
<input type="text" class="form-control input-large" name="data[<?php echo $dir;?>][key]" value="<?php echo $data[$dir]['key']?>" >
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label"><?php echo dr_lang('退款API证书'); ?></label>
|
||||
<div class="col-md-9">
|
||||
<div class="alert alert-warning" style="margin-bottom:10px;">
|
||||
<p><?php echo dr_lang('微信退款必须配置商户 API 证书,否则无法退款。'); ?></p>
|
||||
<p><?php echo dr_lang('请在微信商户平台下载证书,将以下文件放到默认目录:'); ?></p>
|
||||
<p><code><?php echo $weixin_cert_default; ?></code></p>
|
||||
<p><code><?php echo $weixin_key_default; ?></code></p>
|
||||
<p class="margin-top-10"><?php echo dr_lang('也可在下方填写自定义绝对路径(留空则使用默认路径)。'); ?></p>
|
||||
</div>
|
||||
<p>
|
||||
<input type="text" class="form-control" name="data[<?php echo $dir;?>][sslcert_path]" id="dr_weixin_sslcert_path" value="<?php echo isset($data[$dir]['sslcert_path']) ? htmlspecialchars($data[$dir]['sslcert_path']) : '';?>" placeholder="<?php echo htmlspecialchars($weixin_cert_default); ?>">
|
||||
<span class="help-block"><?php echo dr_lang('证书文件 apiclient_cert.pem 路径'); ?></span>
|
||||
</p>
|
||||
<p>
|
||||
<input type="text" class="form-control" name="data[<?php echo $dir;?>][sslkey_path]" id="dr_weixin_sslkey_path" value="<?php echo isset($data[$dir]['sslkey_path']) ? htmlspecialchars($data[$dir]['sslkey_path']) : '';?>" placeholder="<?php echo htmlspecialchars($weixin_key_default); ?>">
|
||||
<span class="help-block"><?php echo dr_lang('密钥文件 apiclient_key.pem 路径'); ?></span>
|
||||
</p>
|
||||
<p>
|
||||
<button type="button" class="btn blue btn-sm" onclick="dr_weixin_check_cert()">
|
||||
<i class="fa fa-check-circle"></i> <?php echo dr_lang('检测证书'); ?>
|
||||
</button>
|
||||
<span class="help-block"><?php echo dr_lang('检测证书文件是否存在、可读,以及 PEM 格式是否可用'); ?></span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
function dr_weixin_check_cert() {
|
||||
var cert = $('#dr_weixin_sslcert_path').val() || '';
|
||||
var key = $('#dr_weixin_sslkey_path').val() || '';
|
||||
var url = '<?php echo dr_url('pay/payapi/check_cert'); ?>';
|
||||
url += '&sslcert_path=' + encodeURIComponent(cert);
|
||||
url += '&sslkey_path=' + encodeURIComponent(key);
|
||||
dr_ajax_url(url);
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user