From cf78a6f0fa325c4104698ac6e6cb60c61ea3b784 Mon Sep 17 00:00:00 2001 From: tomivm Date: Thu, 27 Apr 2023 20:53:59 -0300 Subject: [PATCH 1/5] add mocks for PayPal Transactions --- test/helper.js | 111 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/test/helper.js b/test/helper.js index fd306531..8052b4e6 100644 --- a/test/helper.js +++ b/test/helper.js @@ -234,6 +234,32 @@ const subscriber = { isAcknowledged: false, renewalIntent: 'Renew', }, + payPalTransactionData: { + className: 'Transaction', + subscriptionId: 'subscriptionID', + transactionId: 'subscriptionID', + state: 'approved', + products: [{ + "id": "test-monthly", + "subscriptionId": "test", + "billingPeriod": "P1M", + "price": { + "currencyCode": "USD", + "units": "6" + }, + "title": "Test Subscription", + "tag": "test-monthly", + "paypalId": "P-7CR38290D5111153BMRDNDLA" + }], + platform: 'paypal', + nativePurchase: '', + purchaseId: 'orderID', + purchaseDate: '', + isPending: false, + subscriptionState: 'active', + expiryDate: '', + facilitatorAccessToken:'facilitatorAccessToken' + }, createSubscriber: async (userId) => { const newSubscriber = subscriber.subscriberData; newSubscriber.userId = userId; @@ -307,6 +333,91 @@ const subscriber = { }, }); }, + mockPayPalVerification: ({ isValid }) => { + nock('https://api-m.sandbox.paypal.com') + .post(`/v1/oauth2/token`) + .reply(200,{data:{access_token:'ttttoken'}}); + + if (isValid) { + const subscriptionDetails = { + status: 'ACTIVE', + status_update_time: '2023-04-27T20:30:29Z', + id: 'I-9UN3TA1TXMC7', + plan_id: 'P-7CR38290D5111153BMRDNDLA', + start_time: '2023-04-27T20:29:47Z', + quantity: '1', + shipping_amount: { currency_code: 'USD', value: '0.0' }, + subscriber: { + email_address: 'cboard@mock.com', + payer_id: '587FW7S4CZNEG', + name: { given_name: 'SANTIAGO', surname: 'EL QUESO' }, + shipping_address: { address: {} } + }, + billing_info: { + outstanding_balance: { currency_code: 'USD', value: '0.0' }, + cycle_executions: [ {} ], + last_payment: { amount: {}, time: '2023-04-27T20:30:28Z' }, + next_billing_time: '2023-05-27T10:00:00Z', + final_payment_time: '2027-03-27T10:00:00Z', + failed_payments_count: 0 + }, + create_time: '2023-04-27T20:30:28Z', + update_time: '2023-04-27T20:30:29Z', + plan_overridden: false, + links: [ + { + href: 'https://api.sandbox.paypal.com/v1/billing/subscriptions/I-9UN3FA1TXHC7/cancel', + rel: 'cancel', + method: 'POST' + }, + { + href: 'https://api.sandbox.paypal.com/v1/billing/subscriptions/I-9UN3FA1TXHC7', + rel: 'edit', + method: 'PATCH' + }, + { + href: 'https://api.sandbox.paypal.com/v1/billing/subscriptions/I-9UN3FA1TXHC7', + rel: 'self', + method: 'GET' + }, + { + href: 'https://api.sandbox.paypal.com/v1/billing/subscriptions/I-9UN3FA1TXHC7/suspend', + rel: 'suspend', + method: 'POST' + }, + { + href: 'https://api.sandbox.paypal.com/v1/billing/subscriptions/I-9UN3FA1TXHC7/capture', + rel: 'capture', + method: 'POST' + } + ] + } + + const { subscriptionId } = subscriber.payPalTransactionData; + nock( + `https://api-m.sandbox.paypal.com/v1/billing/subscriptions/${subscriptionId}` + ) + .get('') + .reply(200, subscriptionDetails); + return subscriptionDetails; + } + + const invalidResponse = { + name: 'RESOURCE_NOT_FOUND', + message: 'The specified resource does not exist.', + debug_id: 'e662698658963', + details: [], + links: [] + } + + const { subscriptionId } = subscriber.payPalTransactionData; + nock( + `https://api-m.sandbox.paypal.com/v1/billing/subscriptions/${subscriptionId}` + ) + .get('') + .reply(404, invalidResponse); + return invalidResponse; + } }; const subscription = { From 66a1e2772d2b484bc899f48f9fa9798f62d5ccda Mon Sep 17 00:00:00 2001 From: tomivm Date: Thu, 27 Apr 2023 20:55:24 -0300 Subject: [PATCH 2/5] Add test for create a PayPal transaction --- test/controllers/subscriber.js | 55 +++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/test/controllers/subscriber.js b/test/controllers/subscriber.js index 0ad079ba..baea9ce8 100644 --- a/test/controllers/subscriber.js +++ b/test/controllers/subscriber.js @@ -11,6 +11,7 @@ describe('Subscriber API calls', function() { const { subscriberData: mockSubscriberData, transactionData, + payPalTransactionData, createSubscriber, deleteSubscriber, } = helper.subscriber; @@ -112,7 +113,7 @@ describe('Subscriber API calls', function() { describe('POST /subscriber/${subscriber.id}/transaction', function() { let subscriber; - const { mockPurchaseTokenVerification } = helper.subscriber; + const { mockPurchaseTokenVerification, mockPayPalVerification } = helper.subscriber; before(async function() { subscriber = await createSubscriber(user.userId); @@ -203,6 +204,58 @@ describe('Subscriber API calls', function() { firstCollection.isBillingRetryPeriod.should.to.deep.equal(false); }); + it('it should creates a transaction field in subscriber using paypal.', async function() { + const mockTransactionData = payPalTransactionData; + const verifiedPurchaseReply = mockPayPalVerification({ isValid: true }) + const res = await request(server) + .post(`/subscriber/${subscriber._id}/transaction`) + .send(mockTransactionData) + .set('Authorization', `Bearer ${user.token}`) + .set('Accept', 'application/json') + .expect('Content-Type', /json/) + .expect(200); + + const transactionRes = res.body; + const collection = transactionRes.data.collection; + const firstCollection = collection[0]; + transactionRes.ok.should.to.equal(true); + console.log('transactionRes',transactionRes); + transactionRes.data.id.should.to.deep.equal( + mockTransactionData.products[0].id + ); + transactionRes.data.latest_receipt.should.to.deep.equal(true); + transactionRes.data.transaction.type.should.to.deep.equal( + mockTransactionData.platform + ); + transactionRes.data.transaction.data.transaction.nativePurchase.should.to.deep.equal( + { + ...verifiedPurchaseReply + } + ); + transactionRes.data.transaction.data.success.should.to.deep.equal(true); + + firstCollection.expiryDate.should.to.deep.equal(verifiedPurchaseReply.billing_info.next_billing_time); + }); + + it('it should not creates a PayPal transaction field if subscriptionId is invalid', async function() { + mockPayPalVerification({ isValid: false }); + + const mockTransactionData = payPalTransactionData; + const res = await request(server) + .post(`/subscriber/${subscriber._id}/transaction`) + .send(mockTransactionData) + .set('Authorization', `Bearer ${user.token}`) + .set('Accept', 'application/json') + .expect('Content-Type', /json/) + .expect(200); + + const transactionRes = res.body; + transactionRes.ok.should.to.equal(false); + // transactionRes.error.message.should.to.equal( + // 'Validation failed: transaction: error verifying purchase. Check if the purchase token is valid' + // ); + }); + it('it should should response that transaction is expired.', async function() { const receiptObject = JSON.parse(transactionData.nativePurchase.receipt); const mockTransactionData = transactionData; From 90e61b885a341b7ac10ed438f7cb0216b91e3ba0 Mon Sep 17 00:00:00 2001 From: tomivm Date: Thu, 27 Apr 2023 20:58:47 -0300 Subject: [PATCH 3/5] move Paypal tests to the end --- test/controllers/subscriber.js | 91 +++++++++++++++++----------------- 1 file changed, 45 insertions(+), 46 deletions(-) diff --git a/test/controllers/subscriber.js b/test/controllers/subscriber.js index baea9ce8..68c84eec 100644 --- a/test/controllers/subscriber.js +++ b/test/controllers/subscriber.js @@ -204,9 +204,13 @@ describe('Subscriber API calls', function() { firstCollection.isBillingRetryPeriod.should.to.deep.equal(false); }); - it('it should creates a transaction field in subscriber using paypal.', async function() { - const mockTransactionData = payPalTransactionData; - const verifiedPurchaseReply = mockPayPalVerification({ isValid: true }) + it('it should should response that transaction is expired.', async function() { + const receiptObject = JSON.parse(transactionData.nativePurchase.receipt); + const mockTransactionData = transactionData; + const verifiedPurchaseReply = mockPurchaseTokenVerification({ + isValidToken: true, + isExpired: true, + }); const res = await request(server) .post(`/subscriber/${subscriber._id}/transaction`) .send(mockTransactionData) @@ -216,12 +220,14 @@ describe('Subscriber API calls', function() { .expect(200); const transactionRes = res.body; + const expectedExpiryDate = verifiedPurchaseReply.lineItems[0]?.expiryTime; + const collection = transactionRes.data.collection; const firstCollection = collection[0]; + transactionRes.ok.should.to.equal(true); - console.log('transactionRes',transactionRes); transactionRes.data.id.should.to.deep.equal( - mockTransactionData.products[0].id + mockTransactionData.nativePurchase.productId ); transactionRes.data.latest_receipt.should.to.deep.equal(true); transactionRes.data.transaction.type.should.to.deep.equal( @@ -229,39 +235,22 @@ describe('Subscriber API calls', function() { ); transactionRes.data.transaction.data.transaction.nativePurchase.should.to.deep.equal( { - ...verifiedPurchaseReply + ...mockTransactionData.nativePurchase, + receipt: receiptObject, } ); transactionRes.data.transaction.data.success.should.to.deep.equal(true); - - firstCollection.expiryDate.should.to.deep.equal(verifiedPurchaseReply.billing_info.next_billing_time); - }); - - it('it should not creates a PayPal transaction field if subscriptionId is invalid', async function() { - mockPayPalVerification({ isValid: false }); - - const mockTransactionData = payPalTransactionData; - const res = await request(server) - .post(`/subscriber/${subscriber._id}/transaction`) - .send(mockTransactionData) - .set('Authorization', `Bearer ${user.token}`) - .set('Accept', 'application/json') - .expect('Content-Type', /json/) - .expect(200); - - const transactionRes = res.body; - transactionRes.ok.should.to.equal(false); - // transactionRes.error.message.should.to.equal( - // 'Validation failed: transaction: error verifying purchase. Check if the purchase token is valid' - // ); + firstCollection.expiryDate.should.to.deep.equal(expectedExpiryDate); + firstCollection.isExpired.should.to.deep.equal(true); + firstCollection.isBillingRetryPeriod.should.to.deep.equal(false); }); - it('it should should response that transaction is expired.', async function() { + it('it should should response that transaction is expired and is on billing retry period.', async function() { const receiptObject = JSON.parse(transactionData.nativePurchase.receipt); const mockTransactionData = transactionData; const verifiedPurchaseReply = mockPurchaseTokenVerification({ isValidToken: true, - isExpired: true, + isBillingRetryPeriod: true, }); const res = await request(server) .post(`/subscriber/${subscriber._id}/transaction`) @@ -294,16 +283,12 @@ describe('Subscriber API calls', function() { transactionRes.data.transaction.data.success.should.to.deep.equal(true); firstCollection.expiryDate.should.to.deep.equal(expectedExpiryDate); firstCollection.isExpired.should.to.deep.equal(true); - firstCollection.isBillingRetryPeriod.should.to.deep.equal(false); + firstCollection.isBillingRetryPeriod.should.to.deep.equal(true); }); - it('it should should response that transaction is expired and is on billing retry period.', async function() { - const receiptObject = JSON.parse(transactionData.nativePurchase.receipt); - const mockTransactionData = transactionData; - const verifiedPurchaseReply = mockPurchaseTokenVerification({ - isValidToken: true, - isBillingRetryPeriod: true, - }); + it('it should creates a transaction field in subscriber using paypal.', async function() { + const mockTransactionData = payPalTransactionData; + const verifiedPurchaseReply = mockPayPalVerification({ isValid: true }) const res = await request(server) .post(`/subscriber/${subscriber._id}/transaction`) .send(mockTransactionData) @@ -313,14 +298,11 @@ describe('Subscriber API calls', function() { .expect(200); const transactionRes = res.body; - const expectedExpiryDate = verifiedPurchaseReply.lineItems[0]?.expiryTime; - const collection = transactionRes.data.collection; const firstCollection = collection[0]; - transactionRes.ok.should.to.equal(true); transactionRes.data.id.should.to.deep.equal( - mockTransactionData.nativePurchase.productId + mockTransactionData.products[0].id ); transactionRes.data.latest_receipt.should.to.deep.equal(true); transactionRes.data.transaction.type.should.to.deep.equal( @@ -328,14 +310,31 @@ describe('Subscriber API calls', function() { ); transactionRes.data.transaction.data.transaction.nativePurchase.should.to.deep.equal( { - ...mockTransactionData.nativePurchase, - receipt: receiptObject, + ...verifiedPurchaseReply } ); transactionRes.data.transaction.data.success.should.to.deep.equal(true); - firstCollection.expiryDate.should.to.deep.equal(expectedExpiryDate); - firstCollection.isExpired.should.to.deep.equal(true); - firstCollection.isBillingRetryPeriod.should.to.deep.equal(true); + + firstCollection.expiryDate.should.to.deep.equal(verifiedPurchaseReply.billing_info.next_billing_time); + }); + + it('it should not creates a PayPal transaction field if subscriptionId is invalid', async function() { + mockPayPalVerification({ isValid: false }); + + const mockTransactionData = payPalTransactionData; + const res = await request(server) + .post(`/subscriber/${subscriber._id}/transaction`) + .send(mockTransactionData) + .set('Authorization', `Bearer ${user.token}`) + .set('Accept', 'application/json') + .expect('Content-Type', /json/) + .expect(200); + + const transactionRes = res.body; + transactionRes.ok.should.to.equal(false); + // transactionRes.error.message.should.to.equal( + // 'Validation failed: transaction: error verifying purchase. Check if the purchase token is valid' + // ); }); }); From 95ebdbd5a93e8f72514cbbda63dbd798c14f3300 Mon Sep 17 00:00:00 2001 From: tomivm Date: Thu, 27 Apr 2023 21:01:45 -0300 Subject: [PATCH 4/5] Update postman tests --- .../cboard-api.postman_collection.json | 191 +++++++++++++----- 1 file changed, 145 insertions(+), 46 deletions(-) diff --git a/test/postman/cboard-api.postman_collection.json b/test/postman/cboard-api.postman_collection.json index f7eb9dec..e0924fe0 100644 --- a/test/postman/cboard-api.postman_collection.json +++ b/test/postman/cboard-api.postman_collection.json @@ -165,46 +165,6 @@ }, "response": [] }, - { - "name": "/user/{id} not Authorized", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 403\", function () {", - " pm.response.to.have.status(403);", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "DELETE", - "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Authorization", - "value": "Bearer {{token}}" - } - ], - "url": { - "raw": "{{url}}/user/{{userid}}", - "host": [ - "{{url}}" - ], - "path": [ - "user", - "{{userid}}" - ] - } - }, - "response": [] - }, { "name": "/user/", "event": [ @@ -1757,7 +1717,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"userId\": \"{{userid}}\",\n \"country\": \"'United States'\",\n \"status\": \"free-trial\",\n \"product\": {\n \"planId\": \"one_year_subscription\",\n \"subscriptionId\": \"123456\",\n \"status\": \"requested\"\n }\n}" + "raw": "{\n \"userId\": \"{{userid}}\",\n \"country\": \"'United States'\",\n \"status\": \"free-trial\",\n \"product\": {\n \"subscriptionId\": \"123456\",\n \"price\": {\n \"currencyCode\": \"GBP\",\n \"units\": \"5\"\n },\n \"_id\": \"64492d6de2789a1cb0bf2769\",\n \"title\": \"test-monthly\",\n \"planId\": \"test-monthly\",\n \"status\": \"ACTIVE\",\n \"paypalId\": \"P-7CR38290D5111153BMRDNDLA\",\n \"billingPeriod\": \"P1M\",\n \"renovation\": \"Active\",\n \"createdAt\": \"2023-04-26T13:55:57.596Z\",\n \"updatedAt\": \"2023-04-26T13:55:57.596Z\"\n }\n}" }, "url": { "raw": "{{url}}/subscriber/", @@ -2019,7 +1979,72 @@ ], "body": { "mode": "raw", - "raw": "{\n \"className\": \"Transaction\",\n \"transactionId\": \"GPA.3332-8799-5619-52658\",\n \"state\": \"approved\",\n \"products\": [\n {\n \"productId\": \"premium_full\"\n }\n ],\n \"platform\": \"android-playstore\",\n \"nativePurchase\": {\n \"orderId\": \"GPA.3332-8799-5619-52658\",\n \"packageName\": \"com.unicef.cboard\",\n \"productId\": \"premium_full\",\n \"purchaseTime\": 1668093831727,\n \"purchaseState\": 0,\n \"purchaseToken\": \"{{validPurchaseToken}}\",\n \"quantity\": 1,\n \"autoRenewing\": true,\n \"acknowledged\": false,\n \"productIds\": [\n \"premium_full\"\n ],\n \"getPurchaseState\": 1,\n \"developerPayload\": \"\",\n \"accountId\": \"\",\n \"profileId\": \"\",\n \"signature\": \"XJcrs+pE1dCKERFuioZ2PtatZL1EWFd8Wb4CqGQctspuIJ7n9f/ohrGnABiP8HANyudNDcsoEd2+5l5vh5rNnsUIkePUzsoiFvm1M55Ag57hmdnElYyEBYUn+SSnOQcTzCM2rm2tlpedj1xRklwjH0oxFXj1QOQOsW0n/Vj2Gty5I0+Fp5XxbeMdruYB0TaToaLoRBCn4vATHVJca7M3QxZg9hT7p+aCOZoaCQ4/xBv+vD/VrdygaeGckWrMnTifX00H2fAvAoaC4OZ682dOQeVLHhYHO4RWDPlwinI/b+t8x1vQ/mKDQ4GxfFckrg/RRJco/9wGIxGd7257aF739w==\",\n \"receipt\": \"{\\\"orderId\\\":\\\"GPA.3332-8799-5619-52658\\\",\\\"packageName\\\":\\\"com.unicef.cboard\\\",\\\"productId\\\":\\\"premium_full\\\",\\\"purchaseTime\\\":1668093831727,\\\"purchaseState\\\":0,\\\"purchaseToken\\\":\\\"afalfjihkckgdngikhkhnpfa.AO-J1OyLtExOfZpoOORV9WKUcsyfdJMfo08iEtBuHE0ovZwNK5yl3lP5bS2Wi7CN2QvBj0AvSt-1jlkwmmY8q2KxGzakuFtzIg\\\",\\\"quantity\\\":1,\\\"autoRenewing\\\":true,\\\"acknowledged\\\":false}\"\n },\n \"purchaseId\": \"afalfjihkckgdngikhkhnpfa.AO-J1OyLtExOfZpoOORV9WKUcsyfdJMfo08iEtBuHE0ovZwNK5yl3lP5bS2Wi7CN2QvBj0AvSt-1jlkwmmY8q2KxGzakuFtzIg\",\n \"purchaseDate\": \"2022-11-10T15:23:51.727Z\",\n \"isPending\": false,\n \"isAcknowledged\": false,\n \"renewalIntent\": \"Renew\"\n}" + "raw": "{\n \"className\": \"Transaction\",\n \"transactionId\": \"GPA.3332-8799-5619-52658\",\n \"state\": \"approved\",\n \"products\": [\n {\n \"productId\": \"premium_full\"\n }\n ],\n \"platform\": \"android-playstore\",\n \"nativePurchase\": {\n \"orderId\": \"GPA.3332-8799-5619-52658\",\n \"packageName\": \"com.unicef.cboard\",\n \"productId\": \"premium_full\",\n \"purchaseTime\": 1700925235785,\n \"purchaseState\": 0,\n \"purchaseToken\": \"gdllkfajlolgdhbpgmdnafom.AO-J1Owzxm7j8Hb9prWYYq0-LvZnqNuMQ3qk3xEcpUJWStQnoSi-Ev2QXtPMkBQpEbidJmfKDwaqT0UFCP9EHfwR-2wRPPZZ7Q\",\n \"quantity\": 1,\n \"autoRenewing\": true,\n \"acknowledged\": false,\n \"productIds\": [\n \"premium_full\"\n ],\n \"getPurchaseState\": 1,\n \"developerPayload\": \"\",\n \"accountId\": \"\",\n \"profileId\": \"\",\n \"signature\": \"XJcrs+pE1dCKERFuioZ2PtatZL1EWFd8Wb4CqGQctspuIJ7n9f/ohrGnABiP8HANyudNDcsoEd2+5l5vh5rNnsUIkePUzsoiFvm1M55Ag57hmdnElYyEBYUn+SSnOQcTzCM2rm2tlpedj1xRklwjH0oxFXj1QOQOsW0n/Vj2Gty5I0+Fp5XxbeMdruYB0TaToaLoRBCn4vATHVJca7M3QxZg9hT7p+aCOZoaCQ4/xBv+vD/VrdygaeGckWrMnTifX00H2fAvAoaC4OZ682dOQeVLHhYHO4RWDPlwinI/b+t8x1vQ/mKDQ4GxfFckrg/RRJco/9wGIxGd7257aF739w==\",\n \"receipt\": \"{\\\"orderId\\\":\\\"GPA.3332-8799-5619-52658\\\",\\\"packageName\\\":\\\"com.unicef.cboard\\\",\\\"productId\\\":\\\"premium_full\\\",\\\"purchaseTime\\\":1668093831727,\\\"purchaseState\\\":0,\\\"purchaseToken\\\":\\\"afalfjihkckgdngikhkhnpfa.AO-J1OyLtExOfZpoOORV9WKUcsyfdJMfo08iEtBuHE0ovZwNK5yl3lP5bS2Wi7CN2QvBj0AvSt-1jlkwmmY8q2KxGzakuFtzIg\\\",\\\"quantity\\\":1,\\\"autoRenewing\\\":true,\\\"acknowledged\\\":false}\"\n },\n \"purchaseId\": \"afalfjihkckgdngikhkhnpfa.AO-J1OyLtExOfZpoOORV9WKUcsyfdJMfo08iEtBuHE0ovZwNK5yl3lP5bS2Wi7CN2QvBj0AvSt-1jlkwmmY8q2KxGzakuFtzIg\",\n \"purchaseDate\": \"2022-11-10T15:23:51.727Z\",\n \"isPending\": false,\n \"isAcknowledged\": false,\n \"renewalIntent\": \"Renew\"\n}" + }, + "url": { + "raw": "{{url}}/subscriber/{{subscriberId}}/transaction", + "host": [ + "{{url}}" + ], + "path": [ + "subscriber", + "{{subscriberId}}", + "transaction" + ] + } + }, + "response": [] + }, + { + "name": "/subscriber/{id}/transaction Paypal", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const schema = { ", + " \"type\": \"object\",", + " \"properties\": {", + " \"ok\": {\"type\":\"boolean\"},", + " \"data\":{ ", + " \"type\": \"object\",", + " \"properties\": {", + " \"transaction\": {\"type\":\"object\"}", + " },", + " \"required\":[\"transaction\"]", + " } ", + " },", + " \"required\":[\"ok\",\"data\"]", + "} ", + "", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"to have required props\", function () {", + " pm.response.to.have.jsonSchema(schema);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "Bearer {{token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"className\":\"Transaction\",\n \"subscriptionId\":\"{{payPalSubscriptionId}}\",\n \"transactionId\":\"{{payPalSubscriptionId}}\",\n \"state\":\"approved\",\n \"products\":[\n {\n \"id\": \"test-monthly\",\n \"subscriptionId\": \"test\",\n \"billingPeriod\": \"P1M\",\n \"price\": \n {\n \"currencyCode\": \"USD\",\n \"units\": \"6\"\n },\n \"title\": \"Test Subscription\",\n \"tag\": \"test-monthly\",\n \"paypalId\": \"P-7CR38290D5111153BMRDNDLA\"\n }],\n \"platform\":\"paypal\",\n \"nativePurchase\":\"\",\n \"purchaseId\":\"3CW11883FK516310D\",\n \"purchaseDate\":\"\",\n \"isPending\":false,\n \"subscriptionState\":\"active\",\n \"expiryDate\":\"\",\n \"facilitatorAccessToken\":\"{{facilitatorAccessToken}}\"\n}" }, "url": { "raw": "{{url}}/subscriber/{{subscriberId}}/transaction", @@ -2131,7 +2156,7 @@ "response": [] }, { - "name": "{{url}}/subscriber/{{userid}} to owned", + "name": "{{url}}/subscriber/{{userid}} transaction to null", "request": { "method": "PATCH", "header": [ @@ -2148,7 +2173,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"product\": {\n \"planId\": \"premium_full\",\n \"subscriptionId\": \"123456\",\n \"status\": \"owned\"\n }\n}" + "raw": "{\n \"product\": {\n \"planId\": \"other_plan\",\n \"subscriptionId\": \"123456\",\n \"status\": \"requested\"\n },\n \"transaction\": null\n}" }, "url": { "raw": "{{url}}/subscriber/{{subscriberId}}", @@ -2164,7 +2189,7 @@ "response": [] }, { - "name": "{{url}}/subscriber/{{userid}} transaction to null", + "name": "{{url}}/subscriber/{{userid}} to owned", "request": { "method": "PATCH", "header": [ @@ -2181,7 +2206,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"product\": {\n \"planId\": \"other_plan\",\n \"subscriptionId\": \"123456\",\n \"status\": \"requested\"\n },\n \"transaction\": null\n}" + "raw": "{\n \"product\": {\n \"planId\": \"premium_full\",\n \"subscriptionId\": \"123456\",\n \"status\": \"owned\"\n }\n}" }, "url": { "raw": "{{url}}/subscriber/{{subscriberId}}", @@ -2373,6 +2398,80 @@ } }, "response": [] + }, + { + "name": "/subscription/synchronize", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{url}}/subscription/synchronize", + "host": [ + "{{url}}" + ], + "path": [ + "subscription", + "synchronize" + ] + } + }, + "response": [] + }, + { + "name": "/subscription/list", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{url}}/subscription/list", + "host": [ + "{{url}}" + ], + "path": [ + "subscription", + "list" + ] + } + }, + "response": [] + }, + { + "name": "New Request", + "request": { + "method": "GET", + "header": [] + }, + "response": [] + }, + { + "name": "transaction/cancel paypal", + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token}}", + "type": "text" + }, + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{url}}/subscriber/cancel/{{payPalSubscriptionId}}", + "host": [ + "{{url}}" + ], + "path": [ + "subscriber", + "cancel", + "{{payPalSubscriptionId}}" + ] + } + }, + "response": [] } ] } \ No newline at end of file From b90566af5356a155788960e52abf365729569514 Mon Sep 17 00:00:00 2001 From: tomivm Date: Thu, 27 Apr 2023 21:05:55 -0300 Subject: [PATCH 5/5] response with plan id for both platforms --- api/controllers/subscriber.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/api/controllers/subscriber.js b/api/controllers/subscriber.js index 8dab5d04..f7fea13b 100644 --- a/api/controllers/subscriber.js +++ b/api/controllers/subscriber.js @@ -380,10 +380,11 @@ async function createTransaction(req, res) { }); } const transaction = subscriber.transaction; + const id = (transaction.platform === 'android-playstore' && transaction.nativePurchase.productId) || (transaction.platform === 'paypal' && transaction.products[0].id); return res.status(200).json({ ok: true, data: { - id: transaction.nativePurchase.productId, + id, latest_receipt: true, transaction: { data: { transaction, success: true },