Skip to content
This repository was archived by the owner on Apr 14, 2020. It is now read-only.

Commit 58021fb

Browse files
committed
Use NATIVE mode instead of JSAPI
1 parent bcad914 commit 58021fb

9 files changed

+181
-590
lines changed

README.md

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,67 @@ And run composer to update your dependencies:
2929

3030
The following gateways are provided by this package:
3131

32-
* WeChat Express (WeChat JSAPI)
32+
* WeChat Express (WeChat NATIVE)
3333

3434
For general usage instructions, please see the main [Omnipay](https://github.com/thephpleague/omnipay)
3535
repository.
3636

37-
WeChat JSAPI require OAuth openid to submit a new order, use `$WeChat_Express->getAuthCode($callback)` to get an url for WeChat OAuth and `$WeChat_Express-->getOpenid($code)` in callback page to get openid.
37+
## Example
3838

39-
p.s. the url for WeChat OAuth must be opened in WeChat In-App broswer, you can use `strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger') === false` to check if the page were not opened in it, and generate a QR code for user.
39+
### Make a payment
4040

41-
All methods for WeChat OAuth will be removed in next stable version and I'll publish a WeChat MP library package for composer.
41+
The WeChat NATIVE payment gateway return a URI which can be opened within WeChat In-App broswer, you can generate a QR code with the URI.
42+
43+
```php
44+
$omnipay = Omnipay::create('Wechat_Express');
45+
46+
$omnipay->setAppId('app_id'); // App ID of your WeChat MP account
47+
$omnipay->setAppKey('app_key'); // App Key of your WeChat MP account
48+
$omnipay->setMchId('partner_id'); // Partner ID of your WeChat merchandiser (WeChat Pay) account
49+
50+
$params = array(
51+
'out_trade_no' => time() . rand(100, 999), // billing id in your system
52+
'notify_url' => $notify_url, // URL for asynchronous notify
53+
'body' => $billing_desc, // A simple description
54+
'total_fee' => 0.01, // Amount with less than 2 decimals places
55+
'fee_type' => 'CNY', // Currency name from ISO4217, Optional, default as CNY
56+
);
57+
58+
$response = $omnipay->purchase($params)->send();
59+
60+
$qrCode = new Endroid\QrCode\QrCode(); // Use Endroid\QrCode to generate the QR code
61+
$qrCode
62+
->setText($response->getRedirectUrl())
63+
->setSize(120)
64+
->setPadding(0)
65+
->render();
66+
```
67+
68+
### Verify a payment (especially for asynchronous notify)
69+
70+
`completePurchase` for Omnipay-WeChat does not require the same arguments as when you made the initial `purchase` call. The only required parameter is `out_trade_no` (the billing id in your system) or `transaction_id` (the trade number from WeChat).
71+
72+
```php
73+
$omnipay = Omnipay::create('Wechat_Express');
74+
75+
$omnipay->setAppId('app_id'); // App ID of your WeChat MP account
76+
$omnipay->setAppKey('app_key'); // App Key of your WeChat MP account
77+
$omnipay->setMchId('partner_id'); // Partner ID of your WeChat merchandiser (WeChat Pay) account
78+
79+
$params = array(
80+
'out_trade_no' => $billing_id, // billing id in your system
81+
//or you can use 'transaction_id', the trade number from WeChat
82+
);
83+
84+
$response = $omnipay->completePurchase($params)->send();
85+
86+
if ($response->isSuccessful() && $response->isTradeStatusOk()) {
87+
$responseData = $response->getData();
88+
89+
// Do something here
90+
}
91+
92+
```
4293

4394
## Donate us
4495

src/Omnipay/WeChat/ExpressGateway.php

Lines changed: 27 additions & 193 deletions
Original file line numberDiff line numberDiff line change
@@ -21,232 +21,66 @@ public function getAppId()
2121
return $this->getParameter('app_id');
2222
}
2323

24-
public function setKey($key)
24+
public function setAppKey($appKey)
2525
{
26-
$this->setParameter('app_key', $key);
26+
$this->setParameter('app_key', $appKey);
2727
}
2828

29-
public function getKey()
29+
public function getAppKey()
3030
{
3131
return $this->getParameter('app_key');
3232
}
3333

34-
public function getPartner()
34+
public function setMchId($mchId)
3535
{
36-
return $this->getParameter('partner');
36+
$this->setParameter('mch_id', $mchId);
3737
}
3838

39-
public function setPartner($id)
39+
public function getMchId()
4040
{
41-
$this->setParameter('partner', $id);
42-
}
43-
44-
public function getPartnerKey()
45-
{
46-
return $this->getParameter('partner_key');
47-
}
48-
49-
public function setPartnerKey($key)
50-
{
51-
$this->setParameter('partner_key', $key);
52-
}
53-
54-
public function setCertPath($path)
55-
{
56-
$this->setParameter('cert_path', $path);
57-
}
58-
59-
public function getCertPath()
60-
{
61-
$this->getParameter('cert_path');
62-
}
63-
64-
public function setCertKeyPath($path)
65-
{
66-
$this->setParameter('cert_key_path', $path);
67-
}
68-
69-
public function getCertKeyPath()
70-
{
71-
$this->getParameter('cert_key_path');
72-
}
73-
74-
public function getNotifyUrl()
75-
{
76-
return $this->getParameter('notify_url');
41+
return $this->getParameter('mch_id');
7742
}
7843

7944
public function setNotifyUrl($url)
8045
{
8146
$this->setParameter('notify_url', $url);
8247
}
8348

84-
public function setReturnUrl($url)
85-
{
86-
$this->setParameter('return_url', $url);
87-
}
88-
89-
public function getReturnUrl($url)
90-
{
91-
return $this->getParameter('return_url');
92-
}
93-
94-
public function setCancelUrl($url)
95-
{
96-
$this->setParameter('cancel_url', $url);
97-
}
98-
99-
public function getCancelUrl($url)
100-
{
101-
return $this->getParameter('cancel_url', $url);
102-
}
103-
104-
public function setFailUrl($url)
105-
{
106-
$this->setParameter('cancel_url', $url);
107-
}
108-
109-
public function getFailUrl($url)
110-
{
111-
return $this->getParameter('fail_url', $url);
112-
}
113-
114-
public function getDefaultParameters()
115-
{
116-
return array(
117-
'timestamp' => time(),
118-
'noncestr' => bin2hex(openssl_random_pseudo_bytes(8)),
119-
);
120-
}
121-
122-
public static function xml2arrayByWechatNotifyBody($xml_str)
123-
{
124-
$postObj = simplexml_load_string($xml_str, 'SimpleXMLElement', LIBXML_NOCDATA);
125-
return array(
126-
'AppId' => (string) $postObj->AppId,
127-
'TimeStamp' => (string) $postObj->TimeStamp,
128-
'NonceStr' => (string) $postObj->NonceStr,
129-
'OpenId' => (string) $postObj->OpenId,
130-
'IsSubscribe' => (string) $postObj->IsSubscribe,
131-
'AppSignature' => (string) $postObj->AppSignature,
132-
);
133-
}
134-
135-
public function createPackageStr($params)
136-
{
137-
$out_trade_no = $params['productid'];
138-
$fee = $params['money_paid'];
139-
$opts = array(
140-
'bank_type' => 'WX',
141-
'body' => $params['subject'],
142-
'partner' => $this->getPartner(),
143-
'out_trade_no' => $out_trade_no,
144-
'total_fee' => round($fee),
145-
'fee_type' => 1,
146-
'notify_url' => isset($params['notify_url']) ? $params['notify_url'] : $this->getNotifyUrl(),
147-
'spbill_create_ip' => '127.0.0.1',
148-
'input_charset' => 'UTF-8',
149-
);
150-
ksort($opts);
151-
$qstr = http_build_query($opts);
152-
$sign = strtoupper(md5(urldecode($qstr) . '&key=' . $this->getPartnerKey()));
153-
154-
return $qstr . '&sign=' . $sign;
155-
}
156-
157-
public function getAuthCode($redirect_url)
158-
{
159-
$params['appid'] = $this->getAppId();
160-
$params['redirect_uri'] = $redirect_url;
161-
$params['response_type'] = 'code';
162-
$params['scope'] = 'snsapi_base';
163-
$params['state'] = 'STATE#wechat_redirect';
164-
165-
$params = http_build_query($params);
166-
167-
return 'https://open.weixin.qq.com/connect/oauth2/authorize?' . $params;
168-
}
169-
170-
public function getOpenid($code)
171-
{
172-
$params['appid'] = $this->getAppId();
173-
$params['secret'] = $this->getPartnerKey();
174-
$params['code'] = $code;
175-
$params['grant_type'] = 'authorization_code';
176-
177-
ksort($params);
178-
179-
$params = http_build_query($params);
180-
181-
$url = 'https://api.weixin.qq.com/sns/oauth2/access_token?' . $params;
182-
183-
$ch = curl_init();
184-
curl_setopt($ch, CURLOPT_URL, $url);
185-
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
186-
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
187-
curl_setopt($ch, CURLOPT_HEADER, false);
188-
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
189-
190-
$res = curl_exec($ch);
191-
192-
curl_close($ch);
193-
194-
$data = json_decode($res, true);
195-
196-
return $data['openid'];
197-
}
198-
199-
private function arrayOnly($array, $keys)
200-
{
201-
return array_intersect_key($array, array_flip((array) $keys));
202-
}
203-
204-
private function arrayKeyMap($array, $keymap)
49+
public function getNotifyUrl()
20550
{
206-
$keys = array_keys($keymap);
207-
$arr = $this->arrayOnly($array, $keys);
208-
$array = array_diff_key($array, array_flip((array) $keys));
209-
foreach ($arr as $k => $v) {
210-
$array[$keymap[$k]] = $v;
211-
}
212-
return $array;
51+
return $this->getParameter('notify_url');
21352
}
21453

215-
public function purchase(array $parameters = array())
54+
public function purchase($parameters = array())
21655
{
217-
if (empty($parameters['prepay_id'])) {
218-
if (!isset($parameters['open_id'])) {
219-
throw new \RuntimeException('lack open id');
220-
}
56+
if (empty($parameters['code_url'])) {
22157
$res = $this->prePurchase($parameters)->send();
222-
if (empty($res['prepay_id'])) {
223-
throw new \RuntimeException('get prepay_id failed');
224-
} else {
225-
$parameters['prepay_id'] = $res['prepay_id'];
226-
}
22758
}
22859

229-
$parameters['package'] = 'prepay_id=' . $parameters['prepay_id'];
230-
$parameters = $this->arrayKeyMap($parameters, ['out_trade_no' => 'productid']);
231-
$params = $this->arrayOnly($parameters, ['appid', 'timestamp', 'noncestr', 'productid', 'package', 'open_id']);
232-
return $this->createRequest('\Omnipay\WeChat\Message\WechatPurchaseRequest', $params);
60+
return $this->createRequest('\Omnipay\WeChat\Message\WechatPurchaseRequest', $res);
23361
}
23462

235-
public function prePurchase(array $parameters = array())
63+
public function prePurchase($parameters = array())
23664
{
237-
$parameters = $this->arrayKeyMap($parameters, ['subject' => 'body']);
238-
239-
$params = $this->arrayOnly($parameters, ['out_trade_no', 'total_fee', 'body', 'open_id']);
240-
$params['total_fee'] = round($params['total_fee']);
241-
$params['spbill_create_ip'] = $_SERVER['REMOTE_ADDR'];
242-
$params['trade_type'] = 'JSAPI';
65+
$params = array(
66+
'app_id' => $this->getAppId(),
67+
'mch_id' => $this->getMchId(),
68+
'device_info' => 'WEB',
69+
'noncestr' => bin2hex(openssl_random_pseudo_bytes(8)),
70+
'body' => $parameters['body'],
71+
'out_trade_no' => $parameters['out_trade_no'],
72+
'total_fee' => round($parameters['total_fee'] * 100),
73+
'fee_type' => $parameters['fee_type'],
74+
'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],
75+
'notify_url' => $parameters['notify_url'],
76+
'trade_type' => 'NATIVE',
77+
);
24378

24479
return $this->createRequest('\Omnipay\WeChat\Message\WechatPrePurchaseRequest', $params);
24580
}
24681

247-
public function completePurchase(array $parameters = array())
82+
public function completePurchase($parameters = array())
24883
{
249-
// $parameters['body'] = static::xml2array_by_wechat_notify_body($parameters['body']);
25084
return $this->createRequest('\Omnipay\WeChat\Message\WechatCompletePurchaseRequest', $parameters);
25185
}
25286
}

0 commit comments

Comments
 (0)