1. 接口规则 为了在保证支付安全的前提下,带给商户简单、一致且易用的开发体验,我们推出了全新的微信支付APIv3接口。该版本API的具体规则请参考 APIv3接口规则 。
2. 开发准备 2.1. 搭建和配置开发环境 开发者应当依据自身的编程语言来构建并配置相应的开发环境。
2.2. 业务开发配置 2.2.1. 注册App App接入微信支付,需要先将商户App在微信开放平台进行注册,登记App开发参数以生成AppID。具体操作步骤如下:
1.登录 微信开放平台 ,进入【管理中心 → 移动应用 → 创建移动应用】;
2.完成基本信息的录入,商户需要在本步骤提交App对应的下载地址,应用官网,应用水印,icon等业务信息;
3.完成平台信息的录入,商户需要在本步骤提交App在Android/iOS/鸿蒙端对应的开发参数,包括Android端应用的包名,应用签名,iOS端应用的Bundle ID, Universal Links,鸿蒙端应用的Bundle ID 和 Identifier等;
4.以上信息全部提交完成后,即完成App的注册,商户可在【管理中心 → 移动应用】中,选择具体的应用查看其AppID及已获得的接口能力;
5.获取到App的AppID后,需要将该AppID与商户的收款mch_id进行绑定,商户可登录商户平台后前往【产品中心 -> AppID账号管理】界面中进行AppID的绑定及管理,界面如图所示:
2.2.2. iOS开发要点说明 由于苹果公司在iOS13系统回收了查询 App bundleID 的能力,导致微信无法保证授权凭证能正确返回给AppID对应的应用。为此,微信支付强烈要求所有商户尽快升级到OpenSDK1.8.6,并让用户及时更新App,否则安全风险将一直存在。
详细OpenSDK升级指引请参见: OpenSDK升级指引
注意
OpenSDK升级后请一定按照文档要求完成验证工作,确保OpenSDK升级成功。
以下项目开发环境以Xcode6.0,运行环境为IOS7.0为例,说明其开发中需要的操作
一、项目设置AppID 商户在微信开放平台申请开发App应用后,微信开放平台会生成App的唯一标识AppID。在Xcode中打开项目,设置项目属性中的URL Schemes为您的AppID。如图标红位置所示
二、注册AppID 商户App工程中引入微信lib库和头文件,调用API前,需要先向微信注册您的AppID,代码如下:
[WXApi registerApp:@"wxd930ea5d5a258f4f" withDescription:@"demo 2.0"];
2.2.3. Android开发要点说明 1、后台设置 商户在微信开放平台申请开发应用后,微信开放平台会生成App的唯一标识AppID。由于需要保证支付安全,需要在开放平台绑定商户应用包名和应用签名,设置好后才能正常发起支付。设置界面在【开放平台】中的栏目【管理中心 修改应用 修改开发信息】里面,如图红框内所示。
应用包名:是在App项目配置文件AndroidManifest.xml中声明的package值,例如上图中的package="demo.wxpay.tenpay.com"。
应用签名:根据项目的应用包名和编译使用的keystore,可由签名工具生成一个32位的md5串,在调试的手机上安装签名工具后,运行可生成应用签名串,如图8.9所示,绿色串即应用签名。
点击下载 签名生成工具
2、注册AppID 商户App工程中引入微信JAR包,调用API前,需要先向微信注册您的AppID,代码如下:
1 final IWXAPI msgApi = WXAPIFactory . createWXAPI ( context , null ) ;
2
3 msgApi . registerApp ( "wxd930ea5d5a258f4f" ) ; 2.2.4. 鸿蒙开发要点说明 1、配置鸿蒙应用信息 前往 微信开放平台 ,在「管理中心 - 移动应用 - 详情 - 开发配置」中点击「编辑」进入修改开发信息的页面,继续在「平台信息」板块中填入鸿蒙应用所需的 Bundle ID 和 identifier 信息,然后提交审核,等待审核通过即可。
关于「鸿蒙应用」中的 Bundle ID、Identifier、以及应用下载地址的提供的说明如下:
注意事项:
2、下载鸿蒙开发的 IDE 前往鸿蒙官网下载 DevEco Studio NEXT
3、配置 sdk 依赖 在 DevEco Studio NEXT中打开你的项目,以 demo 工程 为示例:
修改项目中的oh-package.json5文件,在dependencies中加入微信 opensdk 的依赖项:
1 {
2 "name" : "demo" ,
3 "version" : "1.0.0" ,
4 "description" : "Please describe the basic information." ,
5 "main" : "" ,
6 "author" : "" ,
7 "license" : "" ,
8 "dependencies" : {
9 "@tencent/wechat_open_sdk" : "1.0.0"
10 }
11 } 3. 快速接入 3.1. 业务流程图 重点步骤说明:
步骤3: 用户下单发起支付,商户可通过微信支付App下单API创建支付订单。
商户调用 App下单 API后,分正常返回和异常返回情况:
步骤8: 商户通过 App调起支付 OpenSDK调起微信支付,发起支付请求,有关OpenSDK调起支付的详细说明,请参考 iOS开发要点说明 的说明
步骤15-19: 用户支付成功后,商户可通过以下两种方式获取订单状态。
我们通过以下接口将用户确认订单信息回调通知给商户系统:
方法一: 支付结果通知。用户支付成功后,微信支付会将支付成功的结果以回调通知的形式同步给商户,商户的回调地址需要在调用App下单API时传入notify_url参数。
方法二: 当因网络抖动或本身notify_url存在问题等原因,导致无法接收到回调通知时,商户也可主动调用 查询订单API 查询订单API来获取订单状态。
3.2. API接入(含示例代码) 文档展示了如何使用微信支付服务端 SDK 快速接入支付有礼,完成与微信支付对接的部分。
3.2.1. 【服务端】App下单 步骤说明 :用户在商户App内完成商户选择后进入支付页面,商户需要通过后端请求该 App下单API 来获取预支付ID。
JAVA代码示例:
1 public void CreateOrder ( ) throws Exception {
2
3 HttpPost httpPost = new HttpPost ( "https://api.mch.weixin.qq.com/v3/pay/transactions/app" ) ;
4
5 String reqdata = "{"
6 + "\"time_expire\":\"2018-06-08T10:34:56+08:00\","
7 + "\"amount\": {"
8 + "\"total\":100,"
9 + "\"currency\":\"CNY\""
10 + "},"
11 + "\"mchid\":\"1230000109\","
12 + "\"description\":\"Image形象店-深圳腾大-QQ公仔\","
13 + "\"notify_url\":\"https://www.weixin.qq.com/wxpay/pay.php\","
14 + "\"out_trade_no\":\"1217752501201407033233368018\","
15 + "\"goods_tag\":\"WXG\","
16 + "\"appid\":\"wxd678efh567hg6787\","
17 + "\"attach\":\"自定义数据说明\","
18 + "\"detail\": {"
19 + "\"invoice_id\":\"wx123\","
20 + "\"goods_detail\": ["
21 + "{"
22 + "\"goods_name\":\"iPhoneX 256G\","
23 + "\"wechatpay_goods_id\":\"1001\","
24 + "\"quantity\":1,"
25 + "\"merchant_goods_id\":\"商品编码\","
26 + "\"unit_price\":828800"
27 + "},"
28 + "{"
29 + "\"goods_name\":\"iPhoneX 256G\","
30 + "\"wechatpay_goods_id\":\"1001\","
31 + "\"quantity\":1,"
32 + "\"merchant_goods_id\":\"商品编码\","
33 + "\"unit_price\":828800"
34 + "}"
35 + "],"
36 + "\"cost_price\":608800"
37 + "},"
38 + "\"scene_info\": {"
39 + "\"store_info\": {"
40 + "\"address\":\"广东省深圳市南山区科技中一道10000号\","
41 + "\"area_code\":\"440305\","
42 + "\"name\":\"腾讯大厦分店\","
43 + "\"id\":\"0001\""
44 + "},"
45 + "\"device_id\":\"013467007045764\","
46 + "\"payer_client_ip\":\"14.23.150.211\""
47 + "}"
48 + "}" ;
49 StringEntity entity = new StringEntity ( reqdata , "utf-8" ) ;
50 entity . setContentType ( "application/json" ) ;
51 httpPost . setEntity ( entity ) ;
52 httpPost . setHeader ( "Accept" , "application/json" ) ;
53
54 CloseableHttpResponse response = httpClient . execute ( httpPost ) ;
55 try {
56 int statusCode = response . getStatusLine ( ) . getStatusCode ( ) ;
57 if ( statusCode == 200 ) {
58 System . out . println ( "success,return body = " + EntityUtils . toString ( response . getEntity ( ) ) ) ;
59 } else if ( statusCode == 204 ) {
60 System . out . println ( "success" ) ;
61 } else {
62 System . out . println ( "failed,resp code = " + statusCode + ",return body = " + EntityUtils . toString ( response . getEntity ( ) ) ) ;
63 throw new IOException ( "request failed" ) ;
64 }
65 } finally {
66 response . close ( ) ;
67 }
68 } PHP代码示例:
1 try {
2 $resp = $client - >request (
3 'POST' ,
4 'https://api.mch.weixin.qq.com/v3/pay/transactions/app' ,
5 [
6
7 'json' = > [
8 " time_expire" = > " 2018-06-08T10:34:56+08:00" ,
9 " amount" = > [
10 " total" = > 100 ,
11 " currency" = > " CNY" ,
12 ] ,
13 " mchid" = > " 1230000109" ,
14 " description" = > " Image形象店-深圳腾大-QQ公仔" ,
15 " notify_url" = > " https://www.weixin.qq.com/wxpay/pay.php" ,
16 " out_trade_no" = > " 1217752501201407033233368018" ,
17 " goods_tag" = > " WXG" ,
18 " appid" = > " wxd678efh567hg6787" ,
19 " attach" = > " 自定义数据说明" ,
20 " detail" = > [
21 " invoice_id" = > " wx123" ,
22 " goods_detail" = > [
23 [
24 " goods_name" = > " iPhoneX 256G" ,
25 " wechatpay_goods_id" = > " 1001" ,
26 " quantity" = > 1 ,
27 " merchant_goods_id" = > " 商品编码" ,
28 " unit_price" = > 828800 ,
29 ] ,
30 [
31 " goods_name" = > " iPhoneX 256G" ,
32 " wechatpay_goods_id" = > " 1001" ,
33 " quantity" = > 1 ,
34 " merchant_goods_id" = > " 商品编码" ,
35 " unit_price" = > 828800 ,
36 ] ,
37 ] ,
38 " cost_price" = > 608800 ,
39 ] ,
40 " scene_info" = > [
41 " store_info" = > [
42 " address" = > " 广东省深圳市南山区科技中一道10000号" ,
43 " area_code" = > " 440305" ,
44 " name" = > " 腾讯大厦分店" ,
45 " id" = > " 0001" ,
46 ] ,
47 " device_id" = > " 013467007045764" ,
48 " payer_client_ip" = > " 14.23.150.211" ,
49 ]
50 ] ,
51 'headers' = > [ 'Accept' = > 'application/json' ]
52 ]
53 ) ;
54 $statusCode = $resp - >getStatusCode ( ) ;
55 if ( $statusCode == 200 ) {
56 echo " success,return body = " . $resp - >getBody ( ) - >getContents ( ) . " \n" ;
57 } else if ( $statusCode == 204 ) {
58 echo " success" ;
59 }
60 } catch ( RequestException $e ) {
61
62 echo $e - >getMessage ( ) . " \n" ;
63 if ( $e - >hasResponse ( ) ) {
64 echo " failed,resp code = " . $e - >getResponse ( ) - >getStatusCode ( ) . " return body = " . $e - >getResponse ( ) - >getBody ( ) . " \n" ;
65 }
66 return ;
67 } 重要入参说明:
更多参数、响应详情及错误码请参见 App下单API 接口文档。
3.2.2. 【客户端】OpenSDK调起支付 步骤说明: 通过 App下单API 成功获取 预支付交易会话标识(prepay_id) 后,需要通过OpenSDK来调起微信支付收银台
重要入参说明:
package: 取固定值Sign=WXPay
signType: 该接口V3版本仅支持RSA
paySign: 签名
paySign生成规则、响应详情及错误码请参见 App调起支付 接口文档。
iOS SDK调用说明
一、拉起支付 商户服务器生成支付订单,先调用App下单API生成预付单,获取到prepay_id后将参数再次签名传输给App发起支付。以下是调起微信支付的关键代码:
1 PayReq * request = [ [ [ PayReq alloc ] init ] autorelease ] ;
2 request . partnerId = @ " 10000100" ;
3 request . prepayId = @ " 1101000000140415649af9fc314aa427" ;
4 request . package = @ " Sign=WXPay" ;
5 request . nonceStr = @ " a462b76e7436e98e0ed6e13c64b4fd1c" ;
6 request . timeStamp = @ " 1397527777" ;
7 request . sign = @ " 582282D72DD2B03AD892830965F428CB16E7A256" ;
8 [ WXApi sendReq:request ] 二、SDK结果回调 按照微信SDK Sample,在类实现onResp函数,支付完成后,微信App会返回到商户App并回调onResp函数,开发者需要在该函数中接收通知,判断返回错误码。 如果支付成功则去后台查询支付结果再展示用户实际支付结果。注意一定不能以客户端返回作为用户支付的结果,应以服务器端接收的支付通知或查询API返回的结果为准。
代码示例如下:
1 - ( void ) onResp: ( BaseResp * ) resp {
2 if ( [ respisKindOfClass: [ PayRespclass ] ] ) {
3 PayResp * response = ( PayResp * ) resp ;
4 switch ( response . errCode ) {
5 caseWXSuccess:
6 NSlog ( @ " 支付成功" ) ;
7 break ;
8 default:
9 NSlog ( @ " 支付失败,retcode=%d" , resp . errCode ) ;
10 break ;
11 }
12 }
13 } 回调中errCode值列表:
-2
用户取消
无需处理。发生场景:用户不支付了,点击取消,返回App。
0
成功
展示成功页面
-1
错误
可能的原因:签名错误、未注册AppID、项目设置AppID不正确、注册的AppID与设置的不匹配、其他异常等。
Android SDK调用说明
一、SDK拉起支付 商户服务器生成支付订单,先调用App下单API生成预付单,获取到prepay_id后将参数再次签名传输给App发起支付。以下是调起微信支付的关键代码:
1 IWXAPI api ;
2 PayReq request = new PayReq ( ) ;
3 request . appId = " wxd930ea5d5a258f4f" ;
4 request . partnerId = " 1900000109" ;
5 request . prepayId = " 1101000000140415649af9fc314aa427" , ;
6 request . packageValue = " Sign=WXPay" ;
7 request . nonceStr = " 1101000000140429eb40476f8896f4c9" ;
8 request . timeStamp = " 1398746574" ;
9 request . sign = " 7FFECB600D7157C5AA49810D2D8F28BC2811827B" ;
10 api . sendReq ( request ) ; 二、支付结果回调 参照微信SDK Sample,在商户包名.wxapi包路径中实现WXPayEntryActivity类(包名或类名不一致会造成无法回调),在WXPayEntryActivity类中实现onResp函数,支付完成后,微信App会返回到商户App并回调onResp函数,开发者需要在该函数中接收通知,判断返回错误码。 如果支付成功则去后台查询支付结果再展示用户实际支付结果。注意一定不能以客户端返回作为用户支付的结果,应以服务器端的接收的支付通知或查询API返回的结果为准。
代码示例如下:
1 public void onResp ( BaseRespresp ) {
2 if ( resp . getType ( ) == ConstantsAPI . COMMAND_PAY_BY_WX ) {
3 Log . d ( TAG , "onPayFinish,errCode=" + resp . errCode ) ;
4 AlertDialog . Builderbuilder = newAlertDialog . Builder ( this ) ;
5 builder . setTitle ( R . string . app_tip ) ;
6 }
7 } 回调中errCode值列表:
0
成功
展示成功页面
-1
错误
可能的原因:签名错误、未注册AppID、项目设置AppID不正确、注册的AppID与设置的不匹配、其他异常等。
-2
用户取消
无需处理。发生场景:用户不支付了,点击取消,返回App。
鸿蒙 SDK 调用说明
一、SDK拉起支付 商户服务器生成支付订单,先调用App下单API生成预付单,获取到prepay_id后将参数再次签名传输给App发起支付。以下是调起微信支付的关键代码:
1 import * as wxopensdk from '@wechat/open_sdk' ;
2
3
4 export const WXApi = wxopensdk . WXAPIFactory . createWXAPI ( APP_ID )
5
6
7 class WXApiEventHandlerImpl implements wxopensdk . WXApiEventHandler {
8 private onReqCallbacks : Map<OnWXReq , OnWXReq> = new Map
9 private onRespCallbacks : Map<OnWXResp , OnWXResp> = new Map
10
11 registerOnWXReqCallback ( on : OnWXReq ) {
12 this . onReqCallbacks . set ( on , on )
13 }
14 unregisterOnWXReqCallback ( on : OnWXReq ) {
15 this . onReqCallbacks . delete ( on )
16 }
17
18 registerOnWXRespCallback ( on : OnWXResp ) {
19 this . onRespCallbacks . set ( on , on )
20 }
21 unregisterOnWXRespCallback ( on : OnWXResp ) {
22 this . onRespCallbacks . delete ( on )
23 }
24
25 onReq ( req : wxopensdk . BaseReq ) : void {
26 Log . i ( kTag , "onReq:%s" , JSON . stringify ( req ) )
27 this . onReqCallbacks . forEach ( ( on ) = > {
28 on ( req )
29 } )
30 }
31
32 onResp ( resp : wxopensdk . BaseResp ) : void {
33 Log . i ( kTag , "onResp:%s" , JSON . stringify ( resp ) )
34 this . onRespCallbacks . forEach ( ( on ) = > {
35 on ( resp )
36 } )
37 }
38 }
39 export const WXEventHandler = new WXApiEventHandlerImpl
40
41
42 let req = new wxopensdk . PayReq
43 req . appId = 'wxd930ea5d5a258f4f'
44 req . partnerId = '1900000109'
45 req . prepayId = '1101000000140415649af9fc314aa427'
46 req . packageValue = 'Sign=WXPay'
47 req . nonceStr = '1101000000140429eb40476f8896f4c9'
48 req . timeStamp = '1398746574'
49 req . sign = '7FFECB600D7157C5AA49810D2D8F28BC2811827B'
50
51
52
53 let finished = await this . wxApi . sendReq ( context : common . UIAbilityContext , req )
54
55
56
57 export default class EntryAbility extends UIAbility {
58 onCreate ( want : Want , _launchParam : AbilityConstant . LaunchParam ) : void {
59 this . handleWeChatCallIfNeed ( want )
60 }
61
62 onNewWant ( want : Want , _launchParam : AbilityConstant . LaunchParam ) : void {
63 this . handleWeChatCallIfNeed ( want )
64 }
65
66 private handleWeChatCallIfNeed ( want : Want ) {
67 WXApi . handleWant ( want , WXEventHandler )
68 }
69 }
二、支付结果回调 支付完成后,微信App会返回到商户App并回调onResp函数,开发者需要在该函数中接收通知,判断返回错误码。 如果支付成功则去后台查询支付结果再展示用户实际支付结果。注意一定不能以客户端返回作为用户支付的结果,应以服务器端接收的支付通知或查询API返回的结果为准。
示例代码:
1 onResp ( resp : wxopensdk . BaseResp ) : void {
2 Log . i ( kTag , "onResp:%s" , JSON . stringify ( resp ) )
3 this . onRespCallbacks . forEach ( ( on ) = > {
4 on ( resp )
5 } )
6 } 回调中errCode值列表:
0
成功
展示成功页面
-1
错误
可能的原因:签名错误、未注册AppID、项目设置AppID不正确、注册的AppID与设置的不匹配、其他异常等
-2
用户取消
无需处理。发生场景:用户不支付了,点击取消,返回App
3.2.3.【服务端】接收支付结果通知 步骤说明: 当用户完成支付,微信会把相关支付结果将通过异步回调的方式通知商户,商户需要接收处理,并按文档规范返回应答。
注意
支付结果通知是以POST 方法访问商户设置的通知URL,通知的数据以JSON 格式通过请求主体(BODY)传输。通知的数据包括了加密的支付结果详情。
加密不能保证通知请求来自微信。微信会对发送给商户的通知进行签名,并将签名值放在通知的HTTP头Wechatpay-Signature。商户应当验证签名,以确认请求来自微信,而不是其他的第三方。签名验证的算法请参考 《微信支付API v3签名验证》 。
支付通知HTTP应答码为200或204才会当作正常接收,当回调处理异常时,应答的HTTP状态码应为500,或者4xx。
商户成功接收到回调通知后应返回成功的HTTP应答码为200或204。
同样的通知可能会多次发送给商户系统。商户系统必须能够正确处理重复的通知。 推荐的做法是,当商户系统收到通知进行处理时,先检查对应业务数据的状态,并判断该通知是否已经处理。如果未处理,则再进行处理;如果已处理,则直接返回结果成功。在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱。
对后台通知交互时,如果微信收到商户的应答不符合规范或超时,微信认为通知失败,微信会通过一定的策略定期重新发起通知,尽可能提高通知的成功率,但微信不保证通知最终能成功。(通知频率为15s/15s/30s/3m/10m/20m/30m/30m/30m/60m/3h/3h/3h/6h/6h - 总计 24h4m)。
特别提醒: 商户系统对于开启结果通知的内容一定要做签名验证,并校验通知的信息是否与商户侧的信息一致,防止数据泄露导致出现“假通知”,造成资金损失。
更多参数、响应详情及错误码请参见 支付结果通知 接口文档。
3.2.4. 【服务端】查询订单 步骤说明: 当商户后台、网络、服务器等出现异常,商户系统最终未接收到支付通知时,商户可通过查询订单接口核实订单支付状态。
示例代码(通过微信订单号查询):
JAVA示例代码:
1 public void QueryOrder ( ) throws Exception {
2
3
4 URIBuilder uriBuilder = new URIBuilder ( "https://api.mch.weixin.qq.com/v3/pay/transactions/id/4200000745202011093730578574" ) ;
5 uriBuilder . setParameter ( "mchid" , mchId ) ;
6
7
8 HttpGet httpGet = new HttpGet ( uriBuilder . build ( ) ) ;
9 httpGet . addHeader ( "Accept" , "application/json" ) ;
10 CloseableHttpResponse response = httpClient . execute ( httpGet ) ;
11
12 try {
13 int statusCode = response . getStatusLine ( ) . getStatusCode ( ) ;
14 if ( statusCode == 200 ) {
15 System . out . println ( "success,return body = " + EntityUtils . toString ( response . getEntity ( ) ) ) ;
16 } else if ( statusCode == 204 ) {
17 System . out . println ( "success" ) ;
18 } else {
19 System . out . println ( "failed,resp code = " + statusCode + ",return body = " + EntityUtils . toString ( response . getEntity ( ) ) ) ;
20 throw new IOException ( "request failed" ) ;
21 }
22 } finally {
23 response . close ( ) ;
24 }
25 } PHP代码示例:
1 try {
2 $resp = $client - >request (
3 'GET' ,
4 'https://api.mch.weixin.qq.com/v3/pay/transactions/id/1217752501201407033233368018?mchid=1230000109' ,
5 [
6 'headers' = > [ 'Accept' = > 'application/json' ]
7 ]
8 ) ;
9 $statusCode = $resp - >getStatusCode ( ) ;
10 if ( $statusCode == 200 ) {
11 echo " success,return body = " . $resp - >getBody ( ) - >getContents ( ) . " \n" ;
12 } else if ( $statusCode == 204 ) {
13 echo " success" ;
14 }
15 } catch ( RequestException $e ) {
16
17 echo $e - >getMessage ( ) . " \n" ;
18 if ( $e - >hasResponse ( ) ) {
19 echo " failed,resp code = " . $e - >getResponse ( ) - >getStatusCode ( ) . " return body = " . $e - >getResponse ( ) - >getBody ( ) . " \n" ;
20 }
21 return ;
22 } 更多参数、响应详情及错误码请参见 微信支付订单号 / 商户订单号 接口文档。
3.2.5. 【服务端】关闭订单 步骤说明: 当商户订单支付失败需要生成新单号重新发起支付,要对原订单号调用关单,避免重复支付;系统下单后,用户支付超时,系统退出不再受理,避免用户继续,请调用关单接口
JAVA代码示例:
1 public void CloseOrder ( ) throws Exception {
2
3
4 HttpPost httpPost = new HttpPost ( "https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/sdkphp12345678920201028112429/close" ) ;
5
6 String reqdata = "{\"mchid\": \"" + mchId + "\"}" ;
7
8 StringEntity entity = new StringEntity ( reqdata , "utf-8" ) ;
9 entity . setContentType ( "application/json" ) ;
10 httpPost . setEntity ( entity ) ;
11 httpPost . setHeader ( "Accept" , "application/json" ) ;
12
13
14 CloseableHttpResponse response = httpClient . execute ( httpPost ) ;
15 try {
16 int statusCode = response . getStatusLine ( ) . getStatusCode ( ) ;
17 if ( statusCode == 200 ) {
18 System . out . println ( "success,return body = " + EntityUtils . toString ( response . getEntity ( ) ) ) ;
19 } else if ( statusCode == 204 ) {
20 System . out . println ( "success" ) ;
21 } else {
22 System . out . println ( "failed,resp code = " + statusCode + ",return body = " + EntityUtils . toString ( response . getEntity ( ) ) ) ;
23 throw new IOException ( "request failed" ) ;
24 }
25 } finally {
26 response . close ( ) ;
27 }
28 } PHP代码示例:
1 try {
2 $resp = $client - >request (
3 'POST' ,
4 'https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/{out_trade_no}/close' ,
5 [
6
7 'json' = > [
8 " mchid " = > " 1230000109" ,
9 ] ,
10 'headers' = > [ 'Accept' = > 'application/json' ]
11 ]
12 ) ;
13 $statusCode = $resp - >getStatusCode ( ) ;
14 if ( $statusCode == 200 ) {
15 echo " success,return body = " . $resp - >getBody ( ) - >getContents ( ) . " \n" ;
16 } else if ( $statusCode == 204 ) {
17 echo " success" ;
18 }
19 } catch ( RequestException $e ) {
20
21 echo $e - >getMessage ( ) . " \n" ;
22 if ( $e - >hasResponse ( ) ) {
23 echo " failed,resp code = " . $e - >getResponse ( ) - >getStatusCode ( ) . " return body = " . $e - >getResponse ( ) - >getBody ( ) . " \n" ;
24 }
25 return ;
26 } 更多参数、响应详情及错误码请参见 关闭订单 接口文档。
3.2.6. 【服务端】申请交易账单 步骤说明: 微信支付按天提供交易账单文件,商户可以通过该接口获取账单文件的下载地址。
JAVA代码示例:
1 public void TradeBill ( ) throws Exception {
2
3
4 URIBuilder uriBuilder = new URIBuilder ( "https://api.mch.weixin.qq.com/v3/bill/tradebill" ) ;
5 uriBuilder . setParameter ( "bill_date" , "2020-11-09" ) ;
6 uriBuilder . setParameter ( "bill_type" , "ALL" ) ;
7
8
9 HttpGet httpGet = new HttpGet ( uriBuilder . build ( ) ) ;
10 httpGet . addHeader ( "Accept" , "application/json" ) ;
11 CloseableHttpResponse response = httpClient . execute ( httpGet ) ;
12
13 try {
14 int statusCode = response . getStatusLine ( ) . getStatusCode ( ) ;
15 if ( statusCode == 200 ) {
16 System . out . println ( "success,return body = " + EntityUtils . toString ( response . getEntity ( ) ) ) ;
17 } else if ( statusCode == 204 ) {
18 System . out . println ( "success" ) ;
19 } else {
20 System . out . println ( "failed,resp code = " + statusCode + ",return body = " + EntityUtils . toString ( response . getEntity ( ) ) ) ;
21 throw new IOException ( "request failed" ) ;
22 }
23 } finally {
24 response . close ( ) ;
25 }
26 } PHP代码示例:
1 try {
2 $resp = $client - >request (
3 'GET' ,
4 'https://api.mch.weixin.qq.com/v3/bill/tradebill?bill_date=2019-06-11&bill_type=ALL' ,
5 [
6 'headers' = > [ 'Accept' = > 'application/json' ]
7 ]
8 ) ;
9 $statusCode = $resp - >getStatusCode ( ) ;
10 if ( $statusCode == 200 ) {
11 echo " success,return body = " . $resp - >getBody ( ) - >getContents ( ) . " \n" ;
12 } else if ( $statusCode == 204 ) {
13 echo " success" ;
14 }
15 } catch ( RequestException $e ) {
16
17 echo $e - >getMessage ( ) . " \n" ;
18 if ( $e - >hasResponse ( ) ) {
19 echo " failed,resp code = " . $e - >getResponse ( ) - >getStatusCode ( ) . " return body = " . $e - >getResponse ( ) - >getBody ( ) . " \n" ;
20 }
21 return ;
22 } 更多参数、响应详情及错误码请参见 申请交易账单 支付通知API接口文档
3.2.7. 【服务端】下载账单 步骤说明: 通过申请交易账单接口获取到账单下载地址(download_url)后,再通过该接口获取到对应的账单文件,文件内包含交易相关的金额、时间、营销等信息,供商户核对订单、退款、银行到账等情况。
注意
账单文件的下载地址的有效时间为30s。
强烈建议商户将实际账单文件的哈希值和之前从接口获取到的哈希值进行比对,以确认数据的完整性。
该接口响应的信息请求头中不包含微信接口响应的签名值,因此需要跳过验签的流程。
微信在次日9点启动生成前一天的对账单,建议商户10点后再获取。
JAVA代码示例:
1 public void DownloadUrl ( String download_url ) throws Exception {
2 PrivateKey merchantPrivateKey = PemUtil . loadPrivateKey ( new ByteArrayInputStream ( privateKey . getBytes ( "utf-8" ) ) ) ;
3
4
5 httpClient = WechatPayHttpClientBuilder . create ( ) . withMerchant ( mchId , mchSerialNo , merchantPrivateKey ) . withValidator ( ( response ) - > true ) . build ( ) ;
6
7
8 URIBuilder uriBuilder = new URIBuilder ( download_url ) ;
9 HttpGet httpGet = new HttpGet ( uriBuilder . build ( ) ) ;
10 httpGet . addHeader ( "Accept" , "application/json" ) ;
11
12 CloseableHttpResponse response = httpClient . execute ( httpGet ) ;
13 try {
14 int statusCode = response . getStatusLine ( ) . getStatusCode ( ) ;
15 if ( statusCode == 200 ) {
16 System . out . println ( "success,return body = " + EntityUtils . toString ( response . getEntity ( ) ) ) ;
17 } else if ( statusCode == 204 ) {
18 System . out . println ( "success" ) ;
19 } else {
20 System . out . println ( "failed,resp code = " + statusCode + ",return body = " + EntityUtils . toString ( response . getEntity ( ) ) ) ;
21 throw new IOException ( "request failed" ) ;
22 }
23 } finally {
24 response . close ( ) ;
25 }
26 } PHP代码示例:
1 try {
2 $resp = $client - >request (
3 'GET' ,
4 'https://api.mch.weixin.qq.com/v3/billdownload/file?token=xx' ,
5 [
6 'headers' = > [ 'Accept' = > 'application/json' ]
7 ]
8 ) ;
9 $statusCode = $resp - >getStatusCode ( ) ;
10 if ( $statusCode == 200 ) {
11 echo " success,return body = " . $resp - >getBody ( ) - >getContents ( ) . " \n" ;
12 } else if ( $statusCode == 204 ) {
13 echo " success" ;
14 }
15 } catch ( RequestException $e ) {
16
17 echo $e - >getMessage ( ) . " \n" ;
18 if ( $e - >hasResponse ( ) ) {
19 echo " failed,resp code = " . $e - >getResponse ( ) - >getStatusCode ( ) . " return body = " . $e - >getResponse ( ) - >getBody ( ) . " \n" ;
20 }
21 return ;
22 } 更多参数、响应详情及错误码请参见 下载账单 支付通知API接口文档。
4. 常见问题 Q:微信App支付,前端调起的时候返回errcode = -1该如何排查? A:请按以下几点进行排查:
1.查看App下单参数返回是否正常,是否有正确的在调用SDK前获取了正确的prepay_id;
2.查看调用SDK签名是否正确,请注意以下几点:
3.检查客户端调用sendReq(PayReq)对象赋值的正确性(必要时让商户提供数据),若通过异步获取到后台数据,比如data对象是 通过异步请求得到的对象:request.AppID = data.AppID; 实际AppID属性值为空;
4.检查对应的开发配置,包括iOS的AppID配置,Android的包名 \及包签名设置。
Q:App调用“唤起支付API”返回:商户支付下单ID非法 A:请确认唤起支付参数字段名是否与文档的一致。
Q:服务商模式下,调用App下单接口,返回“特殊子商户未授权的产品权限” A:App支付需要进行单独的授权开通才可使用,请前往服务商平台子商户管理中找到对应的子商户授权服务商App支付权限。
Q:调用App下单接口,返回“sub_appid与sub_mch_id不匹配” A:在调用App下单接口前,需保证子商户号与子商户App的AppID存在绑定关系,请服务商前往服务商平台的子商户管理页面中操作绑定。