Skip to content

Support Payment Sandbox mode #658

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 21, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 51 additions & 22 deletions src/Payment/API.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,27 @@ class API extends AbstractAPI
*/
protected $merchant;

/**
* Sandbox box mode.
*
* @var bool
*/
protected $sandboxEnabled = false;

const API_HOST = 'https://api.mch.weixin.qq.com';

// api
const API_PAY_ORDER = 'https://api.mch.weixin.qq.com/pay/micropay';
const API_PREPARE_ORDER = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
const API_QUERY = 'https://api.mch.weixin.qq.com/pay/orderquery';
const API_CLOSE = 'https://api.mch.weixin.qq.com/pay/closeorder';
const API_REVERSE = 'https://api.mch.weixin.qq.com/secapi/pay/reverse';
const API_REFUND = 'https://api.mch.weixin.qq.com/secapi/pay/refund';
const API_QUERY_REFUND = 'https://api.mch.weixin.qq.com/pay/refundquery';
const API_DOWNLOAD_BILL = 'https://api.mch.weixin.qq.com/pay/downloadbill';
const API_REPORT = 'https://api.mch.weixin.qq.com/payitil/report';
const API_URL_SHORTEN = 'https://api.mch.weixin.qq.com/tools/shorturl';
const API_AUTH_CODE_TO_OPENID = 'https://api.mch.weixin.qq.com/tools/authcodetoopenid';
const API_PAY_ORDER = '/pay/micropay';
const API_PREPARE_ORDER = '/pay/unifiedorder';
const API_QUERY = '/pay/orderquery';
const API_CLOSE = '/pay/closeorder';
const API_REVERSE = '/secapi/pay/reverse';
const API_REFUND = '/secapi/pay/refund';
const API_QUERY_REFUND = '/pay/refundquery';
const API_DOWNLOAD_BILL = '/pay/downloadbill';
const API_REPORT = '/payitil/report';
const API_URL_SHORTEN = '/tools/shorturl';
const API_AUTH_CODE_TO_OPENID = '/tools/authcodetoopenid';

// order id types.
const TRANSACTION_ID = 'transaction_id';
Expand Down Expand Up @@ -82,7 +91,7 @@ public function __construct(Merchant $merchant)
*/
public function pay(Order $order)
{
return $this->request(self::API_PAY_ORDER, $order->all());
return $this->request($this->wrapApi(self::API_PAY_ORDER), $order->all());
}

/**
Expand All @@ -99,7 +108,7 @@ public function prepare(Order $order)
$order->spbill_create_ip = ($order->trade_type === Order::NATIVE) ? get_server_ip() : get_client_ip();
}

return $this->request(self::API_PREPARE_ORDER, $order->all());
return $this->request($this->wrapApi(self::API_PREPARE_ORDER), $order->all());
}

/**
Expand All @@ -116,7 +125,7 @@ public function query($orderNo, $type = self::OUT_TRADE_NO)
$type => $orderNo,
];

return $this->request(self::API_QUERY, $params);
return $this->request($this->wrapApi(self::API_QUERY), $params);
}

/**
Expand Down Expand Up @@ -144,7 +153,7 @@ public function close($tradeNo)
'out_trade_no' => $tradeNo,
];

return $this->request(self::API_CLOSE, $params);
return $this->request($this->wrapApi(self::API_CLOSE), $params);
}

/**
Expand All @@ -161,7 +170,7 @@ public function reverse($orderNo, $type = self::OUT_TRADE_NO)
$type => $orderNo,
];

return $this->safeRequest(self::API_REVERSE, $params);
return $this->safeRequest($this->wrapApi(self::API_REVERSE), $params);
}

/**
Expand Down Expand Up @@ -207,7 +216,7 @@ public function refund(
'op_user_id' => $opUserId ?: $this->merchant->merchant_id,
];

return $this->safeRequest(self::API_REFUND, $params);
return $this->safeRequest($this->wrapApi(self::API_REFUND), $params);
}

/**
Expand Down Expand Up @@ -246,7 +255,7 @@ public function queryRefund($orderNo, $type = self::OUT_TRADE_NO)
$type => $orderNo,
];

return $this->request(self::API_QUERY_REFUND, $params);
return $this->request($this->wrapApi(self::API_QUERY_REFUND), $params);
}

/**
Expand Down Expand Up @@ -300,7 +309,7 @@ public function downloadBill($date, $type = self::BILL_TYPE_ALL)
'bill_type' => $type,
];

return $this->request(self::API_DOWNLOAD_BILL, $params, 'post', [\GuzzleHttp\RequestOptions::STREAM => true], true)->getBody();
return $this->request($this->wrapApi(self::API_DOWNLOAD_BILL), $params, 'post', [\GuzzleHttp\RequestOptions::STREAM => true], true)->getBody();
}

/**
Expand All @@ -312,7 +321,7 @@ public function downloadBill($date, $type = self::BILL_TYPE_ALL)
*/
public function urlShorten($url)
{
return $this->request(self::API_URL_SHORTEN, ['long_url' => $url]);
return $this->request($this->wrapApi(self::API_URL_SHORTEN), ['long_url' => $url]);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UrlShorten 没有 sandbox 模式吧?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

文档是这样写的
1、修改商户自有程序或配置中,微信支付api的链接,如:被扫支付官网的url为:https://api.mch.weixin.qq.com/pay/micropay增加sandbox路径,变更为https://api.mch.weixin.qq.com/sandbox/pay/micropay, 即可接入沙箱验收环境,其它接口类似; ---- https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=21_2

其它接口类似 让我以为是有的。

}

/**
Expand All @@ -338,7 +347,7 @@ public function report($api, $timeConsuming, $resultCode, $returnCode, array $ot
'time' => time(),
], $other);

return $this->request(self::API_REPORT, $params);
return $this->request($this->wrapApi(self::API_REPORT), $params);
}

/**
Expand All @@ -350,7 +359,7 @@ public function report($api, $timeConsuming, $resultCode, $returnCode, array $ot
*/
public function authCodeToOpenId($authCode)
{
return $this->request(self::API_AUTH_CODE_TO_OPENID, ['auth_code' => $authCode]);
return $this->request($this->wrapApi(self::API_AUTH_CODE_TO_OPENID), ['auth_code' => $authCode]);
}

/**
Expand Down Expand Up @@ -440,4 +449,24 @@ protected function parseResponse($response)

return new Collection((array) XML::parse($response));
}

/**
* Set sandbox mode.
*
* @param bool $enabled
*/
public function sandboxMode($enabled = false)
{
$this->sandboxEnabled = $enabled;
}

/**
* Wrap sandbox API.
*
* @param string $resource
*/
protected function wrapApi($resource)
{
return self::API_HOST.($this->sandboxEnabled ? '/sandbox' : '').$resource;
}
}
32 changes: 16 additions & 16 deletions tests/Payment/PaymentAPITest.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public function getAPI()
'notify_url' => 'merchant_default_notify_url',
]);

$api = \Mockery::mock('EasyWeChat\Payment\API[getHttp]', [$merchant]);
$api = \Mockery::mock('EasyWeChat\Payment\API[getHttp]', [$merchant])->shouldAllowMockingProtectedMethods();
$api->shouldReceive('getHttp')->andReturn($http);

return $api;
Expand All @@ -63,7 +63,7 @@ public function testPrepare()

$response = $api->prepare($order);

$this->assertEquals(API::API_PREPARE_ORDER, $response['api']);
$this->assertEquals($api->wrapApi(API::API_PREPARE_ORDER), $response['api']);
$this->assertEquals('wxTestAppId', $response['params']['appid']);
$this->assertEquals('merchant_default_notify_url', $response['params']['notify_url']);
$this->assertEquals('testMerchantId', $response['params']['mch_id']);
Expand All @@ -82,7 +82,7 @@ public function testPay()

$response = $api->pay($order);

$this->assertEquals(API::API_PAY_ORDER, $response['api']);
$this->assertEquals($api->wrapApi(API::API_PAY_ORDER), $response['api']);
$this->assertEquals('wxTestAppId', $response['params']['appid']);
$this->assertEquals('testMerchantId', $response['params']['mch_id']);
$this->assertEquals('bar', $response['params']['foo']);
Expand All @@ -96,16 +96,16 @@ public function testQuery()
$api = $this->getAPI();
$response = $api->query('testTradeNoFoo');

$this->assertEquals(API::API_QUERY, $response['api']);
$this->assertEquals($api->wrapApi(API::API_QUERY), $response['api']);
$this->assertEquals('testTradeNoFoo', $response['params']['out_trade_no']);

$response = $api->query('testTradeNoBar', API::TRANSACTION_ID);

$this->assertEquals(API::API_QUERY, $response['api']);
$this->assertEquals($api->wrapApi(API::API_QUERY), $response['api']);
$this->assertEquals('testTradeNoBar', $response['params']['transaction_id']);

$response = $api->queryByTransactionId('testTransactionId');
$this->assertEquals(API::API_QUERY, $response['api']);
$this->assertEquals($api->wrapApi(API::API_QUERY), $response['api']);
$this->assertEquals('testTransactionId', $response['params']['transaction_id']);
}

Expand All @@ -117,7 +117,7 @@ public function testClose()
$api = $this->getAPI();

$response = $api->close('testTradeNo');
$this->assertEquals(API::API_CLOSE, $response['api']);
$this->assertEquals($api->wrapApi(API::API_CLOSE), $response['api']);
$this->assertEquals('testTradeNo', $response['params']['out_trade_no']);
}

Expand All @@ -129,11 +129,11 @@ public function testReverse()
$api = $this->getAPI();

$response = $api->reverse('testTradeNo');
$this->assertEquals(API::API_REVERSE, $response['api']);
$this->assertEquals($api->wrapApi(API::API_REVERSE), $response['api']);
$this->assertEquals('testTradeNo', $response['params']['out_trade_no']);

$response = $api->reverse('testTransactionId', API::TRANSACTION_ID);
$this->assertEquals(API::API_REVERSE, $response['api']);
$this->assertEquals($api->wrapApi(API::API_REVERSE), $response['api']);
$this->assertEquals('testTransactionId', $response['params']['transaction_id']);
}

Expand All @@ -145,7 +145,7 @@ public function testRefund()
$api = $this->getAPI();

$response = $api->refund('testTradeNo', 'testRefundNo', 100);
$this->assertEquals(API::API_REFUND, $response['api']);
$this->assertEquals($api->wrapApi(API::API_REFUND), $response['api']);
$this->assertEquals('testRefundNo', $response['params']['out_refund_no']);
$this->assertEquals(100, $response['params']['total_fee']);
$this->assertEquals(100, $response['params']['refund_fee']);
Expand All @@ -172,11 +172,11 @@ public function testQueryRefund()
$api = $this->getAPI();

$response = $api->queryRefund('testTradeNo');
$this->assertEquals(API::API_QUERY_REFUND, $response['api']);
$this->assertEquals($api->wrapApi(API::API_QUERY_REFUND), $response['api']);
$this->assertEquals('testTradeNo', $response['params']['out_trade_no']);

$response = $api->queryRefund('testTransactionId', API::TRANSACTION_ID);
$this->assertEquals(API::API_QUERY_REFUND, $response['api']);
$this->assertEquals($api->wrapApi(API::API_QUERY_REFUND), $response['api']);
$this->assertEquals('testTransactionId', $response['params']['transaction_id']);
}

Expand Down Expand Up @@ -208,12 +208,12 @@ public function testDownloadBill()
$api->shouldReceive('getHttp')->andReturn($http);

$response = $api->downloadBill('20150901');
$this->assertEquals(API::API_DOWNLOAD_BILL, $response['api']);
$this->assertEquals($api->wrapApi(API::API_DOWNLOAD_BILL), $response['api']);
$this->assertEquals('20150901', $response['params']['bill_date']);
$this->assertEquals(API::BILL_TYPE_ALL, $response['params']['bill_type']);

$response = $api->downloadBill('20150901', API::BILL_TYPE_SUCCESS);
$this->assertEquals(API::API_DOWNLOAD_BILL, $response['api']);
$this->assertEquals($api->wrapApi(API::API_DOWNLOAD_BILL), $response['api']);
$this->assertEquals('20150901', $response['params']['bill_date']);
$this->assertEquals(API::BILL_TYPE_SUCCESS, $response['params']['bill_type']);
}
Expand All @@ -227,7 +227,7 @@ public function testUrlShorten()

$response = $api->urlShorten('http://easywechat.org');

$this->assertEquals(API::API_URL_SHORTEN, $response['api']);
$this->assertEquals($api->wrapApi(API::API_URL_SHORTEN), $response['api']);
$this->assertEquals('http://easywechat.org', $response['params']['long_url']);
}

Expand All @@ -240,7 +240,7 @@ public function testAuthCodeToOpenId()

$response = $api->authCodeToOpenId('authcode');

$this->assertEquals(API::API_AUTH_CODE_TO_OPENID, $response['api']);
$this->assertEquals($api->wrapApi(API::API_AUTH_CODE_TO_OPENID), $response['api']);
$this->assertEquals('authcode', $response['params']['auth_code']);
}

Expand Down