3.2. API接入(含示例代码)
本文档展示了如何使用微信支付服务端 SDK 快速接入微信支付分产品,完成与微信支付对接的部分。
注意:
文档中的代码示例是用来阐述 API 基本使用方法,代码中的示例参数需替换成商户自己账号及请求参数才能跑通。
以下接入步骤仅提供参考,请商户结合自身业务需求进行评估、修改。
3.2.1.【服务端】创建支付分订单
步骤说明:完成用户授权后,即可创建支付分订单,为用户提供服务了。
示例代码
public void CreateServiceOrder() throws Exception{
//请求URL
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/payscore/serviceorder");
// 请求body参数
String reqdata = "{"
+ "\"out_order_no\":\"1234323JKHDFE1243252\","
+ "\"appid\":\"wxd678efh567hg6787\","
+ "\"service_id\":\"500001\","
+ "\"service_introduction\":\"某某酒店\","
+ "\"post_payments\": ["
+ "{"
+ "\"name\":\"就餐费用服务费\","
+ "\"amount\":4000,"
+ "\"description\":\"就餐人均100元服务费:100/小时\","
+ "\"count\":1"
+ "}"
+ "],"
+ "\"post_discounts\": ["
+ "{"
+ "\"name\":\"满20减1元\","
+ "\"description\":\"不与其他优惠叠加\""
+ "}"
+ "],"
+ "\"time_range\": {"
+ "\"start_time\":\"20091225091010\","
+ "\"end_time\":\"20091225121010\""
+ "},"
+ "\"location\": {"
+ "\"start_location\":\"嗨客时尚主题展餐厅\","
+ "\"end_location\":\"嗨客时尚主题展餐厅\""
+ "},"
+ "\"risk_fund\": {"
+ "\"name\":\"ESTIMATE_ORDER_COST\","
+ "\"amount\":10000,"
+ "\"description\":\"就餐的预估费用\""
+ "},"
+ "\"attach\":\"Easdfowealsdkjfnlaksjdlfkwqoi&wl3l2sald\","
+ "\"notify_url\":\"https://api.test.com\","
+ "\"openid\":\"oUpF8uMuAJO_M2pxb1Q9zNjWeS6o\","
+ "\"need_user_confirm\":true"
+ "}";
StringEntity entity = new StringEntity(reqdata);
entity.setContentType("application/json");
httpPost.setEntity(entity);
httpPost.setHeader("Accept", "application/json");
//完成签名并执行请求
CloseableHttpResponse response = httpClient.execute(httpPost);
try {
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) { //处理成功
System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
} else if (statusCode == 204) { //处理成功,无返回Body
System.out.println("success");
} else {
System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
throw new IOException("request failed");
}
} finally {
response.close();
}
}
try {
$resp = $client->request(
'POST',
'https://api.mch.weixin.qq.com/v3/payscore/serviceorder', //请求URL
[
// JSON请求体
'json' => [
"out_order_no" => "1234323JKHDFE1243252",
"appid" => "wxd678efh567hg6787",
"service_id" => "500001",
"service_introduction" => "某某酒店",
"post_payments" => [
[
"name" => "就餐费用服务费",
"amount" => 4000,
"description" => "就餐人均100元服务费:100/小时",
"count" => 1,
],
],
"post_discounts" => [
[
"name" => "满20减1元",
"description" => "不与其他优惠叠加",
],
],
"time_range" => [
"start_time" => "20091225091010",
"end_time" => "20091225121010",
],
"location" => [
"start_location" => "嗨客时尚主题展餐厅",
"end_location" => "嗨客时尚主题展餐厅",
],
"risk_fund" => [
"name" => "ESTIMATE_ORDER_COST",
"amount" => 10000,
"description" => "就餐的预估费用",
],
"attach" => "Easdfowealsdkjfnlaksjdlfkwqoi&wl3l2sald",
"notify_url" => "https://api.test.com",
"openid" => "oUpF8uMuAJO_M2pxb1Q9zNjWeS6o",
"need_user_confirm" => true,
],
'headers' => [ 'Accept' => 'application/json' ]
]
);
$statusCode = $resp->getStatusCode();
if ($statusCode == 200) { //处理成功
echo "success,return body = " . $resp->getBody()->getContents()."\n";
} else if ($statusCode == 204) { //处理成功,无返回Body
echo "success";
}
} catch (RequestException $e) {
// 进行错误处理
echo $e->getMessage()."\n";
if ($e->hasResponse()) {
echo "failed,resp code = " . $e->getResponse()->getStatusCode() . " return body = " . $e->getResponse()->getBody() . "\n";
}
return;
}
重要参数说明:
• 入参“need_user_confirm”,取值请选择 “false”;
• 入参“risk_fund::name”,取值请选择“【先享模式】”中的枚举值。
更多参数、响应详情及错误码请参见创建支付分订单API接口文档
3.2.2.【客户端】跳转确认订单页
微信支付根据用户不同的使用场景(APP、小程序、微信外H5)分别提供了对应跳转确认订单页的方法,请根据场景进行选择,详见跳转确认订单页API文档
3.2.3.【服务端】确认订单回调通知
步骤说明:当用户确认订单时,微信会把相关信息异步回调的方式通知商户,商户需要接收处理,并按文档规范返回应答
注意:
支付结果通知是以POST 方法访问商户设置的通知url,通知的数据以JSON 格式通过请求主体(BODY)传输。通知的数据包括了加密的支付结果详情
加密不能保证通知请求来自微信。微信会对发送给商户的通知进行签名,并将签名值放在通知的HTTP头Wechatpay-Signature。商户应当验证签名,以确认请求来自微信,而不是其他的第三方。签名验证的算法请参考微信支付API v3签名方案
支付通知http应答码为200或204才会当作正常接收,当回调处理异常时,应答的HTTP状态码应为500,或者4xx
商户成功接收到回调通知后应返回成功的http应答码为200或204
同样的通知可能会多次发送给商户系统。商户系统必须能够正确处理重复的通知。 推荐的做法是,当商户系统收到通知进行处理时,先检查对应业务数据的状态,并判断该通知是否已经处理。如果未处理,则再进行处理;如果已处理,则直接返回结果成功。在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱。
如果在所有通知频率(4小时)后没有收到微信侧回调,商户应调用查询订单接口确认订单状态。
更多参数、响应详情及错误码请参见确认订单回调通知API接口文档
3.2.4.【服务端】查询支付分订单
步骤说明:一般在创建订单后、订单完结成功后等关键流程中,商户可能有知晓订单状态的需求,此时即可通过该接口查询订单状态。
示例代码:
public void GetServiceOrder() throws Exception{
//请求URL
HttpGet httpGet = new HttpGet("https://api.mch.weixin.qq.com/v3/payscore/serviceorder?service_id=500001&out_order_no=8416518464133&appid=wxd678efh567hg6787");
HttpGet.setHeader("Accept", "application/json");
//完成签名并执行请求
CloseableHttpResponse response = httpClient.execute(HttpGet);
try {
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) { //处理成功
System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
} else if (statusCode == 204) { //处理成功,无返回Body
System.out.println("success");
} else {
System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
throw new IOException("request failed");
}
} finally {
response.close();
}
}
try {
$resp = $client->request(
'GET',
'https://api.mch.weixin.qq.com/v3/payscore/serviceorder?service_id=500001&out_order_no=8416518464133&appid=wxd678efh567hg6787', //请求URL
[
'headers' => [ 'Accept' => 'application/json']
]
);
$statusCode = $resp->getStatusCode();
if ($statusCode == 200) { //处理成功
echo "success,return body = " . $resp->getBody()->getContents()."\n";
} else if ($statusCode == 204) { //处理成功,无返回Body
echo "success";
}
} catch (RequestException $e) {
// 进行错误处理
echo $e->getMessage()."\n";
if ($e->hasResponse()) {
echo "failed,resp code = " . $e->getResponse()->getStatusCode() . " return body = " . $e->getResponse()->getBody() . "\n";
}
return;
}
3.2.5. 【服务端】取消支付分订单
步骤说明:订单为以下状态时可以取消订单:CREATED(已创单)、DOING(进行中)(包括商户完结支付分订单后,且支付分订单收款状态为待支付USER_PAYING)。
示例代码:
public void CancelServiceOrder() throws Exception{
//请求URL
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/payscore/serviceorder/{out_order_no}/cancel");
// 请求body参数
String reqdata = "{"
+ "\"appid\":\"wxd678efh567hg6787\","
+ "\"service_id\":\"500001\","
+ "\"reason\":\"用户投诉\""
+ "}";
StringEntity entity = new StringEntity(reqdata);
entity.setContentType("application/json");
httpPost.setEntity(entity);
httpPost.setHeader("Accept", "application/json");
//完成签名并执行请求
CloseableHttpResponse response = httpClient.execute(httpPost);
try {
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) { //处理成功
System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
} else if (statusCode == 204) { //处理成功,无返回Body
System.out.println("success");
} else {
System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
throw new IOException("request failed");
}
} finally {
response.close();
}
}
try {
$resp = $client->request(
'POST',
'https://api.mch.weixin.qq.com/v3/payscore/serviceorder/{out_order_no}/cancel', //请求URL
[
// JSON请求体
'json' => [
"appid" => "wxd678efh567hg6787",
"service_id" => "500001",
"reason" => "用户投诉",
],
'headers' => [ 'Accept' => 'application/json' ]
]
);
$statusCode = $resp->getStatusCode();
if ($statusCode == 200) { //处理成功
echo "success,return body = " . $resp->getBody()->getContents()."\n";
} else if ($statusCode == 204) { //处理成功,无返回Body
echo "success";
}
} catch (RequestException $e) {
// 进行错误处理
echo $e->getMessage()."\n";
if ($e->hasResponse()) {
echo "failed,resp code = " . $e->getResponse()->getStatusCode() . " return body = " . $e->getResponse()->getBody() . "\n";
}
return;
}
重要参数说明:
入参“need_user_confirm”,取值请选择 “false”;
入参“risk_fund::name”,取值请选择“【先享模式】”中的枚举值。
更多参数、响应详情及错误码请参见 取消支付分订单API接口文档
3.2.6.【服务端】完结支付分订单
步骤说明:用户服务结束后,商户通过请求完结支付分订单接口,通过微信支付分进行用户扣款操作。
注意:
public void CompleteServiceOrder() throws Exception{
//请求URL
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/payscore/serviceorder/{out_order_no}/complete");
// 请求body参数
String reqdata = "{"
+ "\"appid\":\"wxd678efh567hg6787\","
+ "\"service_id\":\"500001\","
+ "\"post_payments\": ["
+ "{"
+ "\"name\":\"就餐费用服务费\","
+ "\"amount\":4000,"
+ "\"description\":\"就餐人均100元服务费:100/小时\","
+ "\"count\":1"
+ "}"
+ "],"
+ "\"post_discounts\": ["
+ "{"
+ "\"name\":\"满20减1元\","
+ "\"description\":\"不与其他优惠叠加\","
+ "\"amount\":4000"
+ "}"
+ "],"
+ "\"total_amount\":3900,"
+ "\"time_range\": {"
+ "\"start_time\":\"20091225091010\","
+ "\"end_time\":\"20091225121010\""
+ "},"
+ "\"location\": {"
+ "\"end_location\":\"嗨客时尚主题展餐厅\""
+ "},"
+ "\"profit_sharing\":false"
+ "}";
StringEntity entity = new StringEntity(reqdata);
entity.setContentType("application/json");
httpPost.setEntity(entity);
httpPost.setHeader("Accept", "application/json");
//完成签名并执行请求
CloseableHttpResponse response = httpClient.execute(httpPost);
try {
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) { //处理成功
System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
} else if (statusCode == 204) { //处理成功,无返回Body
System.out.println("success");
} else {
System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
throw new IOException("request failed");
}
} finally {
response.close();
}
}
try {
$resp = $client->request(
'POST',
'https://api.mch.weixin.qq.com/v3/payscore/serviceorder/{out_order_no}/complete', //请求URL
[
// JSON请求体
'json' => [
"appid" => "wxd678efh567hg6787",
"service_id" => "500001",
"post_payments" => [
[
"name" => "就餐费用服务费",
"amount" => 4000,
"description" => "就餐人均100元服务费:100/小时",
"count" => 1,
],
],
"post_discounts" => [
[
"name" => "满20减1元",
"description" => "不与其他优惠叠加",
"amount" => 4000,
],
],
"total_amount" => 3900,
"time_range" => [
"start_time" => "20091225091010",
"end_time" => "20091225121010",
],
"location" => [
"end_location" => "嗨客时尚主题展餐厅",
],
"profit_sharing" => false,
],
'headers' => [ 'Accept' => 'application/json' ]
]
);
$statusCode = $resp->getStatusCode();
if ($statusCode == 200) { //处理成功
echo "success,return body = " . $resp->getBody()->getContents()."\n";
} else if ($statusCode == 204) { //处理成功,无返回Body
echo "success";
}
} catch (RequestException $e) {
// 进行错误处理
echo $e->getMessage()."\n";
if ($e->hasResponse()) {
echo "failed,resp code = " . $e->getResponse()->getStatusCode() . " return body = " . $e->getResponse()->getBody() . "\n";
}
return;
}
更多参数、响应详情及错误码请参见完结支付分订单API接口文档
3.2.7. 【服务端】修改订单金额
步骤说明:在用户扣款成功前、完结订单后(即订单状态为“待支付”),如需修改订单支付金额,可通过此接口进行订单金额修改。修改成功后,微信支付将按照修改后的金额进行用户扣款。
示例代码:
public void ModifyServiceOrder() throws Exception{
//请求URL
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/payscore/serviceorder/{out_order_no}/modify");
// 请求body参数
String reqdata = "{"
+ "\"appid\":\"wxd678efh567hg6787\","
+ "\"service_id\":\"500001\","
+ "\"post_payments\": ["
+ "{"
+ "\"name\":\"就餐费用服务费\","
+ "\"amount\":4000,"
+ "\"description\":\"就餐人均100元服务费:100/小时\","
+ "\"count\":1"
+ "}"
+ "],"
+ "\"post_discounts\": ["
+ "{"
+ "\"name\":\"满20减1元\","
+ "\"description\":\"不与其他优惠叠加\","
+ "\"amount\":100"
+ "}"
+ "],"
+ "\"total_amount\":2000,"
+ "\"reason\":\"用户投诉\""
+ "}";
StringEntity entity = new StringEntity(reqdata);
entity.setContentType("application/json");
httpPost.setEntity(entity);
httpPost.setHeader("Accept", "application/json");
//完成签名并执行请求
CloseableHttpResponse response = httpClient.execute(httpPost);
try {
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) { //处理成功
System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
} else if (statusCode == 204) { //处理成功,无返回Body
System.out.println("success");
} else {
System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
throw new IOException("request failed");
}
} finally {
response.close();
}
}
try {
$resp = $client->request(
'POST',
'https://api.mch.weixin.qq.com/v3/payscore/serviceorder/{out_order_no}/modify', //请求URL
[
// JSON请求体
'json' => [
"appid" => "wxd678efh567hg6787",
"service_id" => "500001",
"post_payments" => [
[
"name" => "就餐费用服务费",
"amount" => 4000,
"description" => "就餐人均100元服务费:100/小时",
"count" => 1,
],
],
"post_discounts" => [
[
"name" => "满20减1元",
"description" => "不与其他优惠叠加",
"amount" => 100,
],
],
"total_amount" => 2000,
"reason" => "用户投诉",
],
'headers' => [ 'Accept' => 'application/json' ]
]
);
$statusCode = $resp->getStatusCode();
if ($statusCode == 200) { //处理成功
echo "success,return body = " . $resp->getBody()->getContents()."\n";
} else if ($statusCode == 204) { //处理成功,无返回Body
echo "success";
}
} catch (RequestException $e) {
// 进行错误处理
echo $e->getMessage()."\n";
if ($e->hasResponse()) {
echo "failed,resp code = " . $e->getResponse()->getStatusCode() . " return body = " . $e->getResponse()->getBody() . "\n";
}
return;
}
更多参数、响应详情及错误码请参见修改订单金额API接口文档
3.2.8 【服务端】商户发起催收扣款
步骤说明:在订单完结成功后,支付成功前,商户可随时发起催收扣款,发起成功后微信支付将立即进行一次用户扣款(不保证一定能扣成功,仅执行一次扣款操作)。
示例代码:
public void CollectServiceOrder() throws Exception{
//请求URL
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/payscore/serviceorder/{out_order_no}/pay");
// 请求body参数
String reqdata = "{"
+ "\"appid\":\"wxd678efh567hg6787\","
+ "\"service_id\":\"500001\""
+ "}";
StringEntity entity = new StringEntity(reqdata);
entity.setContentType("application/json");
httpPost.setEntity(entity);
httpPost.setHeader("Accept", "application/json");
//完成签名并执行请求
CloseableHttpResponse response = httpClient.execute(httpPost);
try {
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) { //处理成功
System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
} else if (statusCode == 204) { //处理成功,无返回Body
System.out.println("success");
} else {
System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
throw new IOException("request failed");
}
} finally {
response.close();
}
}
try {
$resp = $client->request(
'POST',
'https://api.mch.weixin.qq.com/v3/payscore/serviceorder/{out_order_no}/pay', //请求URL
[
// JSON请求体
'json' => [
"appid" => "wxd678efh567hg6787",
"service_id" => "500001",
],
'headers' => [ 'Accept' => 'application/json' ]
]
);
$statusCode = $resp->getStatusCode();
if ($statusCode == 200) { //处理成功
echo "success,return body = " . $resp->getBody()->getContents()."\n";
} else if ($statusCode == 204) { //处理成功,无返回Body
echo "success";
}
} catch (RequestException $e) {
// 进行错误处理
echo $e->getMessage()."\n";
if ($e->hasResponse()) {
echo "failed,resp code = " . $e->getResponse()->getStatusCode() . " return body = " . $e->getResponse()->getBody() . "\n";
}
return;
}
更多参数、响应详情及错误码请参见商户发起催收扣款API接口文档
3.2.9【服务端】同步服务订单信息
步骤说明:由于一些原因,用户与商户达成线下支付或者其他支付方式支付的协议,商户可通过此接口告知微信支付该笔订单无需继续扣款,微信支付在接到此信息后将不再发起用户扣款。
示例代码:
public void SyncServiceOrder() throws Exception{
//请求URL
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/payscore/serviceorder/{out_order_no}/sync");
// 请求body参数
String reqdata = "{"
+ "\"appid\":\"wxd678efh567hg6787\","
+ "\"service_id\":\"500001\","
+ "\"type\":\"Order_Paid\","
+ "\"detail\": {"
+ "\"paid_time\":\"20091225091210\""
+ "}"
+ "}";
StringEntity entity = new StringEntity(reqdata);
entity.setContentType("application/json");
httpPost.setEntity(entity);
httpPost.setHeader("Accept", "application/json");
//完成签名并执行请求
CloseableHttpResponse response = httpClient.execute(httpPost);
try {
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) { //处理成功
System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
} else if (statusCode == 204) { //处理成功,无返回Body
System.out.println("success");
} else {
System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
throw new IOException("request failed");
}
} finally {
response.close();
}
}
try {
$resp = $client->request(
'POST',
'https://api.mch.weixin.qq.com/v3/payscore/serviceorder/{out_order_no}/sync', //请求URL
[
// JSON请求体
'json' => [
"appid" => "wxd678efh567hg6787",
"service_id" => "500001",
"type" => "Order_Paid",
"detail" => [
"paid_time" => "20091225091210",
]
],
'headers' => [ 'Accept' => 'application/json' ]
]
);
$statusCode = $resp->getStatusCode();
if ($statusCode == 200) { //处理成功
echo "success,return body = " . $resp->getBody()->getContents()."\n";
} else if ($statusCode == 204) { //处理成功,无返回Body
echo "success";
}
} catch (RequestException $e) {
// 进行错误处理
echo $e->getMessage()."\n";
if ($e->hasResponse()) {
echo "failed,resp code = " . $e->getResponse()->getStatusCode() . " return body = " . $e->getResponse()->getBody() . "\n";
}
return;
}
更多参数、响应详情及错误码请参见同步服务订单信息API接口文档
3.2.10【服务端】申请交易账单
步骤说明:微信支付按天提供交易账单文件,商户可以通过该接口获取账单文件的下载地址
示例代码:
public void TradeBill() throws Exception {
//请求URL
URIBuilder uriBuilder = new URIBuilder("https://api.mch.weixin.qq.com/v3/bill/tradebill");
uriBuilder.setParameter("bill_date", "2020-11-09");
uriBuilder.setParameter("bill_type", "ALL");
//完成签名并执行请求
HttpGet httpGet = new HttpGet(uriBuilder.build());
httpGet.addHeader("Accept", "application/json");
CloseableHttpResponse response = httpClient.execute(httpGet);
try {
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) {
System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
} else if (statusCode == 204) {
System.out.println("success");
} else {
System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
throw new IOException("request failed");
}
} finally {
response.close();
}
}
try {
$resp = $client->request(
'GET',
'https://api.mch.weixin.qq.com/v3/bill/tradebill?bill_date=2019-06-11&sub_mchid=1900000001&bill_type=ALL', //请求URL
[
'headers' => [ 'Accept' => 'application/json']
]
);
$statusCode = $resp->getStatusCode();
if ($statusCode == 200) { //处理成功
echo "success,return body = " . $resp->getBody()->getContents()."\n";
} else if ($statusCode == 204) { //处理成功,无返回Body
echo "success";
}
} catch (RequestException $e) {
// 进行错误处理
echo $e->getMessage()."\n";
if ($e->hasResponse()) {
echo "failed,resp code = " . $e->getResponse()->getStatusCode() . " return body = " . $e->getResponse()->getBody() . "\n";
}
return;
}
更多参数、响应详情及错误码请参见申请交易账单API接口文档
3.2.11【服务端】下载交易账单
步骤说明:通过申请交易账单接口获取到账单下载地址(download_url)后,再通过该接口获取到对应的账单文件,文件内包含交易相关的金额、时间、营销等信息,供商户核对订单、退款、银行到账等情况
示例代码:
public void DownloadUrl(String download_url) throws Exception{
PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(privateKey.getBytes("utf-8")));
//初始化httpClient
//该接口无需进行签名验证、通过withValidator((response) -> true)实现
httpClient = WechatPayHttpClientBuilder.create().withMerchant(mchId, mchSerialNo, merchantPrivateKey).withValidator((response) -> true).build();
//请求URL
//账单文件的下载地址的有效时间为30s
URIBuilder uriBuilder = new URIBuilder(download_url);
HttpGet httpGet = new HttpGet(uriBuilder.build());
httpGet.addHeader("Accept", "application/json");
//执行请求
CloseableHttpResponse response = httpClient.execute(httpGet);
try {
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) {
System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
} else if (statusCode == 204) {
System.out.println("success");
} else {
System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
throw new IOException("request failed");
}
} finally {
response.close();
}
}
try {
$resp = $client->request(
'GET',
'https://api.mch.weixin.qq.com/v3/billdownload/file?token=xx', //请求URL
[
'headers' => [ 'Accept' => 'application/json']
]
);
$statusCode = $resp->getStatusCode();
if ($statusCode == 200) { //处理成功
echo "success,return body = " . $resp->getBody()->getContents()."\n";
} else if ($statusCode == 204) { //处理成功,无返回Body
echo "success";
}
} catch (RequestException $e) {
// 进行错误处理
echo $e->getMessage()."\n";
if ($e->hasResponse()) {
echo "failed,resp code = " . $e->getResponse()->getStatusCode() . " return body = " . $e->getResponse()->getBody() . "\n";
}
return;
}
注意:
账单文件的下载地址的有效时间为30s
强烈建议商户将实际账单文件的哈希值和之前从接口获取到的哈希值进行比对,以确认数据的完整性
更多参数、响应详情及错误码请参见下载账单API接口文档
3.2.12【服务端】支付成功回调通知
步骤说明:当用户完成支付,微信会把相关支付结果将通过异步回调的方式通知商户,商户需要接收处理,并按文档规范返回应答。
注意:
支付结果通知是以POST 方法访问商户设置的通知url,通知的数据以JSON 格式通过请求主体(BODY)传输。通知的数据包括了加密的支付结果详情
加密不能保证通知请求来自微信。微信会对发送给商户的通知进行签名,并将签名值放在通知的HTTP头Wechatpay-Signature。商户应当验证签名,以确认请求来自微信,而不是其他的第三方。签名验证的算法请参考微信支付API v3签名方案
支付通知http应答码为200或204才会当作正常接收,当回调处理异常时,应答的HTTP状态码应为500,或者4xx
商户成功接收到回调通知后应返回成功的http应答码为200或204
同样的通知可能会多次发送给商户系统。商户系统必须能够正确处理重复的通知。 推荐的做法是,当商户系统收到通知进行处理时,先检查对应业务数据的状态,并判断该通知是否已经处理。如果未处理,则再进行处理;如果已处理,则直接返回结果成功。在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱。
如果在所有通知频率(4小时)后没有收到微信侧回调,商户应调用查询订单接口确认订单状态。
更多参数、响应详情及错误码请参见支付成功回调通知API接口文档
3.2.13【客户端】跳转订单详情
微信支付根据用户不同的使用场景(APP、小程序、微信外H5)分别提供了对应跳转订单详情页的方法,请根据场景进行选择,详见跳转订单详情页API文档