支付
$callBackUrl = input('server.REQUEST_SCHEME') . '://' . $_SERVER['HTTP_HOST'] . '/api/callback/wechatPay'; // 微信充值回掉地址
$data = (new YongyouPay())->payment('订单号','订单金额','回调地址','openid');
YongyouPay.php
class YongyouPay
{
protected $rsa_public_key; //对方公钥,加密用
protected $rsa_private_key; //己方私钥,解密用
public function __construct(){
//构造函数,可以通过不同运行环境,载入参数
$this->rsa_public_key = '';
$this->rsa_private_key = '';
}
/**
* 支付
* @param $order_id
* @param $money
* @param $back_notify_url
* @param $openid
* @param $body
* @return array|mixed|void
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function payment($order_id,$money,$back_notify_url,$openid,$body = '外卖订单')
{
//报文体,array
$message_body = [
'mchnt_cd' => '', //富友商户号
'order_date' => date('Ymd'),
'order_id' => $order_id,
'order_amt' => MoneyHelper::y2f($money),
'order_pay_type' => 'LETPAY',
'back_notify_url' => $back_notify_url,
'goods_name' => $body,
'goods_detail' => $body,
'appid' => '', //微信小程序appid
'openid' => $openid,
'ver' => '1.0.0'
];
//生成message
$message = $this->publicEncryptRsa(json_encode($message_body));
//发送请求,这里用的Guzzle
$client = new Client(['verify' => false]);
$url = 'https://aggpcpay.fuioupay.com/aggpos/order.fuiou'; //接口地址
$res = $client->request('POST', $url, [
'json' => [
'mchnt_cd' => $message_body['mchnt_cd'], //这里的mchnt_cd要取报文体里面的mchnt_cd
'message' => $message
]
]);
$result = $res->getBody()->getContents();
//得到响应,解密数据
if ($result) {
$result = json_decode($result, true);
if ($result['resp_code'] == '0000') {
//只有resp_code为0000的时候,才有message。
$decrypted = $this->privateDecryptRsa($result['message'], $this->rsa_private_key);
if ($decrypted) {
$decrypted = json_decode($decrypted, true);
}
return $data = json_decode($decrypted['order_info'],true);
}else{
return ExceptionSms::sms($result['resp_code'],[],$result['resp_desc']);
}
}
}
/**
* 退款
* @param $refundNumber
* @param $pay_order_date
* @param $order_id
* @param $money
* @return mixed|void
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function refund_transfer($refundNumber,$pay_order_date,$order_id,$money)
{
//报文体,array
$message_body = [
'mchnt_cd' => '', //富友商户号
'refund_order_date' => date('Ymd'),
'refund_order_id' => $refundNumber,
'pay_order_date' => $pay_order_date,
'pay_order_id' => $order_id,
'refund_amt' => MoneyHelper::y2f($money),
'ver' => '1.0.0'
];
// return json($message_body);
//生成message
$message = $this->publicEncryptRsa(json_encode($message_body));
//发送请求,这里用的Guzzle
$client = new Client(['verify' => false]);
$url = 'https://refund-transfer.fuioupay.com/refund_transfer/aggposRefund.fuiou'; //接口地址
$res = $client->request('POST', $url, [
'json' => [
'mchnt_cd' => $message_body['mchnt_cd'], //这里的mchnt_cd要取报文体里面的mchnt_cd
'message' => $message
]
]);
$result = $res->getBody()->getContents();
//得到响应,解密数据
if ($result) {
return $result = json_decode($result, true);
}
}
public function callBack($postStr)
{
$result = json_decode($postStr, true);
return $this->privateDecryptRsa($result['message'], $this->rsa_private_key);
}
private function publicEncryptRsa($plainData = ''){
if (!is_string($plainData)) {
return null;
}
$encrypted = '';
$partLen = $this->getPublicKenLen()/8 - 11;
$plainData = str_split($plainData, $partLen);
$publicPEMKey = $this->getPublicKey();
foreach ($plainData as $chunk) {
$partialEncrypted = '';
$encryptionOk = openssl_public_encrypt($chunk, $partialEncrypted, $publicPEMKey, OPENSSL_PKCS1_PADDING);
if ($encryptionOk === false) {
return false;
}
$encrypted .= $partialEncrypted;
}
return base64_encode($encrypted);
}
private function getPublicKenLen()
{
$pub_id = openssl_get_publickey($this->getPublicKey());
return openssl_pkey_get_details($pub_id)['bits'];
}
private function getPublicKey()
{
$public_key = $this->rsa_public_key;
//这里的public_key,是一行的情况,才是这样处理;
$pubic_pem = chunk_split($public_key, 64, "\n");
$pubic_pem = "-----BEGIN PUBLIC KEY-----\n" . $pubic_pem . "-----END PUBLIC KEY-----\n";
return $pubic_pem;
}
private function privateDecryptRsa($data = '')
{
if (!is_string($data)) {
return null;
}
$decrypted = '';
$partLen = $this->getPrivateKenLen() / 8;
$data = str_split(base64_decode($data), $partLen);
$privatePEMKey = $this->getPrivateKey();
foreach ($data as $chunk) {
$partial = '';
$decryptionOK = openssl_private_decrypt($chunk, $partial, $privatePEMKey, OPENSSL_PKCS1_PADDING);
if ($decryptionOK === false) {
return false;
}
$decrypted .= $partial;
}
return $decrypted;
}
private function getPrivateKenLen()
{
$pub_id = openssl_get_privatekey($this->getPrivateKey());
return openssl_pkey_get_details($pub_id)['bits'];
}
private function getPrivateKey()
{
//这里的private_key,是一行的情况,才是这样处理;
$private_key = $this->rsa_private_key;
$private_pem = chunk_split($private_key, 64, "\n");
$private_pem = "-----BEGIN PRIVATE KEY-----\n" . $private_pem . "-----END PRIVATE KEY-----\n";
return $private_pem;
}
}
支付回调
/**
* 微信支付回调
*/
public function wechatPay()
{
$postStr = file_get_contents('php://input');
$weChat = new YongyouPay();
$xmlObject = $weChat->callBack($postStr);
$xmlArray = json_decode($xmlObject,true);
if (!$xmlArray || !$xmlArray['order_st']) {
$this->we_log_result("微信支付回掉失败");
$this->print_result_we(false);
}
if ($xmlArray['order_st'] != 1) {
$this->we_log_result('微信支付回调.'.$xmlArray['return_msg']);
$this->print_result_we(false);
}
// 验证成功,执行订单操作
$outTradeNo = $xmlArray['order_id'];
$tradeNo = $xmlArray['fy_order_id'];
$order_fas_ssn = $xmlArray['order_fas_ssn'];
$order_fas_date = $xmlArray['order_fas_date'];
$order = OrderModel::getThisBySn($outTradeNo); //获取订单
if (!$order) {
$this->we_log_result(sprintf("订单号%s不存在", $outTradeNo));
$this->print_result_we(false);
}
if ($order['o_status'] == 1) {
$this->we_log_result(sprintf("订单号%s不允许重复支付", $outTradeNo));
$this->print_result_we(false);
}
// 付款成功
try {
// TODO 订单完成后续操作
$this->we_log_result("订单号:" . $outTradeNo . "\n微信支付交易号:" . $tradeNo . "\n付款成功");
} catch (\Exception $e) {
$this->we_log_result("订单号:" . $outTradeNo . "\n微信支付交易号:" . $tradeNo . "\n付款失败\n失败原因:" . $e->getMessage());
$this->print_result_we(false);
}
}
退款
$pay_order_date = date('Ymd', strtotime($order->finish_at));
$result = (new YongyouPay())->refund_transfer('退款流水号', $pay_order_date, '退款订单号', '退款金额');