- 安装微信支付sdk我这里使用的是wechatpay-php。
直接使用命令:composer require wechatpay/wechatpay - 生成平台证书,这里取参考微信支付github文档说明
- 创建唤起微信支付数据以api接口方式返回给app端。
public function wechatArousePay()
{
$order_id = $this->request->post('order_id/d', null);
$order_number = $this->request->post('order_number/s', null);
if (!$order_id and !$order_number) {
return self::fail('订单ID或订单号必须存在其中一个');
}
$order_map = array(
['uid', '=', $this->userinfo['account']],
['pay_state', '<>', 20]
);
if ($order_id) {
$order_map[] = ['order_id', '=', $order_id];
}
if ($order_number) {
$order_map[] = ['order_number', '=', $order_number];
}
$order_info = Order::where($order_map)->find();
if (!$order_info) {
return self::fail('该项目不存在或已支付');
}
if ($order_info['total_price'] <= 0) {
return self::fail('订单支付金额不合法!');
}
$PaymentAmount = bcmul($order_info['total_price'], 100, 0);
$merchantId = config('wechatpay.mch_id');
$merchantPrivateKeyFilePath = public_path() . 'wechatpay/apiclient_key.pem';
$merchantPrivateKeyInstance = PemUtil::loadPrivateKey($merchantPrivateKeyFilePath);
$merchantCertificateFilePath = public_path() . 'wechatpay/apiclient_cert.pem';
$merchantCertificateInstance = PemUtil::loadCertificate($merchantCertificateFilePath);
$merchantCertificateSerial = PemUtil::parseCertificateSerialNo($merchantCertificateInstance);
$platformCertificateFilePath = public_path() . 'wechatpay/cert.pem';
$platformCertificateInstance = PemUtil::loadCertificate($platformCertificateFilePath);
$platformCertificateSerial = PemUtil::parseCertificateSerialNo($platformCertificateInstance);
$instance = Builder::factory([
'mchid' => $merchantId,
'serial' => $merchantCertificateSerial,
'privateKey' => $merchantPrivateKeyInstance,
'certs' => [
$platformCertificateSerial => $platformCertificateInstance,
],
]);
try {
$resp = $instance
->v3->pay->transactions->app
->post(['json' => [
'appid' => config('wechatpay.wchat_app_id'),
'mchid' => $merchantId,
'description' => $order_info['remark'],
'out_trade_no' => $order_info['order_number'],
'notify_url' => config('wechatpay.notify_url') . '/client/xxxx.ClientPay/weiChatNotify',
'amount' => [
'total' => (int)$PaymentAmount,
'currency' => 'CNY'
],
]]);
$result_code = $resp->getStatusCode();
if ($result_code == 200) {
$result_data = json_decode($resp->getBody(), true);
$arouse_data = [
'appid' => config('wechatpay.wchat_app_id'),
'partnerid' => $merchantId,
'prepayid' => $result_data['prepay_id'],
'package' => "Sign=WXPay",
'noncestr' => MD5($order_info['order_number']),
'timestamp' => get_now_time(),
];
$arouse_data['sign'] = Rsa::sign(
Formatter::joinedByLineFeed(...array_values($arouse_data)),
$merchantPrivateKeyInstance
);
return self::successful('success', $arouse_data);
}
} catch (\Exception $exception) {
if ($exception instanceof \GuzzleHttp\Exception\RequestException && $exception->hasResponse()) {
$r = $exception->getResponse();
return self::result($r->getStatusCode(), $r->getReasonPhrase());
}
}
}
- ApiPost模拟数据。
- 数据回调。
public function weiChatNotify()
{
$get_content = json_decode(file_get_contents('php://input'), true);
$file_directory3 = public_path() . '/wei_chat_notify.txt';
file_put_contents($file_directory3, file_get_contents('php://input'));
$result_content = AesGcm::decrypt($get_content['resource']['ciphertext'], config('wechatpay.apiv3'), $get_content['resource']['nonce'], $get_content['resource']['associated_data']);
$content = json_decode($result_content, true);
$result_data = $this->authWeiChatOrder($content);
if (!$result_data) {
exit('FAIL');
}
$Order = new Order();
$Order::startTrans();
$order_info = $result_data['order'];
$payment_info = $result_data['body'];
try {
$chang_data = array(
'pay_state' => 20,
'pay_style' => 20,
'pay_time' => strtotime($payment_info['time_end']),
'payment_price' => bcdiv($payment_info['total_fee'], 100, 2),
'transaction_id' => $payment_info['transaction_id'],
'openid' => $payment_info['openid'],
'notify_json' => $payment_info
);
$chang_data['need_price'] = bcsub($order_info['total_price'], $chang_data['payment_price'], 2);
$result = $Order->where([['order_id', '=', $order_info['order_id']]])->update($chang_data);
if ($result) {
$Order::commitTrans();
exit("SUCCESS");
}
throw new Exception('操作失败');
} catch (\Exception $exception) {
$Order::rollbackTrans();
exit("FAIL");
}
}
- 订单校验。
public function authWeiChatOrder(array $arr)
{
if (!$arr) {
return null;
}
$order_info = Order::where([['order_number', '=', $arr['out_trade_no']]])->find();
if (!$order_info) {
return null;
}
$OrderQueryUrl = 'https://api.mch.weixin.qq.com/pay/orderquery';
$OrderQueryBody = array_filter([
'appid' => config('wechatpay.wchat_app_id'),
'mch_id' => config('wechatpay.mch_id'),
'transaction_id' => $arr['transaction_id'],
'out_trade_no' => $arr['out_trade_no'],
'nonce_str' => MD5($arr['out_trade_no']),
'sign_type' => 'MD5',
]);
$OrderQueryBody['sign'] = $this->genSign($OrderQueryBody, config('wechatpay.key'));
$xmlContext = $this->ArrayToXml($OrderQueryBody);
$request = $this->ConnCurlSend($OrderQueryUrl, '', $xmlContext, 'POST');
$reqContext = $this->XmlToArray($request);
if ($reqContext['return_code'] == 'SUCCESS' && $reqContext['result_code'] == 'SUCCESS' && $reqContext['return_msg'] == 'OK') {
return [
'order' => $order_info,
'body' => $reqContext,
];
}
return null;
}
|